From 6d5f3e29aaf26cd7d62598fe2da8684464974e20 Mon Sep 17 00:00:00 2001 From: Skeby <103804946+Skeby@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:31:46 +0100 Subject: [PATCH] feat: implement forgot password page --- .../(auth-routes)/forgot-password/page.tsx | 318 +++++++++++++++++- src/app/(auth-routes)/layout.tsx | 4 +- src/components/common/button/button.tsx | 3 + src/components/common/input-otp/index.tsx | 40 +++ src/components/common/input/index.tsx | 123 +++++++ src/components/common/input/input.tsx | 96 ++++++ src/components/layouts/footer/footer.test.tsx | 1 + src/components/ui/input-otp.tsx | 75 +++++ src/components/ui/tooltip.tsx | 30 ++ 9 files changed, 685 insertions(+), 5 deletions(-) create mode 100644 src/components/common/input-otp/index.tsx create mode 100644 src/components/common/input/index.tsx create mode 100644 src/components/common/input/input.tsx create mode 100644 src/components/ui/input-otp.tsx create mode 100644 src/components/ui/tooltip.tsx diff --git a/src/app/(auth-routes)/forgot-password/page.tsx b/src/app/(auth-routes)/forgot-password/page.tsx index 6c0021b0d..f28284bdf 100644 --- a/src/app/(auth-routes)/forgot-password/page.tsx +++ b/src/app/(auth-routes)/forgot-password/page.tsx @@ -1,9 +1,319 @@ -function ForgotPassword() { - return ( +"use client"; + +import { TooltipArrow } from "@radix-ui/react-tooltip"; +import { AnimatePresence, motion } from "framer-motion"; +import { CircleCheck, X } from "lucide-react"; +import Link from "next/link"; +import { ReactNode, useState } from "react"; + +import CustomButton from "~/components/common/button/button"; +import { InputOtp } from "~/components/common/input-otp"; +import CustomInput from "~/components/common/input/input"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "~/components/ui/tooltip"; +import { cn } from "~/lib/utils"; + +const registeredEmails = [ + "akinsanyaadeyinka4166@gmail.com", + "ellafedora@gmail.com", + "alice@example.com", + "bob@example.com", + "charlie@example.com", + "david@example.com", + "eve@example.com", + "frank@example.com", + "grace@example.com", + "hank@example.com", + "irene@example.com", + "jack@example.com", + "karen@example.com", + "leo@example.com", + "mike@example.com", + "nancy@example.com", + "oliver@example.com", + "paul@example.com", + "quincy@example.com", + "rachel@example.com", + "steve@example.com", + "tina@example.com", + "ursula@example.com", + "victor@example.com", + "wendy@example.com", + "xander@example.com", + "yvonne@example.com", + "zach@example.com", +]; + +const Error = ({ + children, + className, +}: { + children?: ReactNode; + className?: string; +}) => ( +

+ {children} +

+); + +const Heading = ({ children }: { children: ReactNode }) => ( +

+ {children} +

+); + +const Description = ({ children }: { children: ReactNode }) => ( +

{children}

+); + +const ForgotPassword = () => { + const [currentStage, setCurrentStage] = useState(0); + const [email, setEmail] = useState(""); + const [code, setCode] = useState(""); + const [isCodeComplete, setIsCodeComplete] = useState(false); + const [isCodeCorrect, setIsCodeCorrect] = useState(false); + const [isOtpResent, setIsOtpResent] = useState(false); + const [showSuccessMessage, setShowSuccessMessage] = useState(true); + const [emailTooltipContent, setEmailTooltipContent] = useState(""); + + const Default = ( <> -
forgot password
+
+ Forgot Password + + Enter the email address you used to create the account to receive + instructions on how to reset your password + +
+ + + + { + const newValue = event.target.value; + const emailMatch = newValue + ? registeredEmails.find((email) => email.includes(newValue)) + : undefined; + setEmailTooltipContent( + emailMatch ? (emailMatch === newValue ? "" : emailMatch) : "", + ); + setEmail(newValue); + }} + value={email} + variant="border" + label="Email" + placeholder="Enter your email" + className="h-12 rounded-lg text-sm placeholder:text-sm focus:border-primary focus:bg-zinc-50 focus:placeholder:text-neutral-dark-2 sm:h-16 sm:text-lg sm:placeholder:text-lg" + labelClassName="sm:text-xl text-[13px] text-neutral-dark-2" + /> + {email && + !registeredEmails.some((registeredEmail) => + registeredEmail.includes(email), + ) && ( + + This email doesn't match our records please try again + + )} + + { + setEmail(emailTooltipContent); + setEmailTooltipContent(""); + }} + > + {emailTooltipContent} + + + + + + Send + +
+ + Remember your Password? + + + Login + +
); -} + + const VerificationCode = ( + <> +
+ Verification Code{isOtpResent ? " Resent" : ""} + + Confirm the OTP sent to + {email} and enter the verification + code that was sent. Code expires in{" "} + 00:59 + +
+
+ { + setCode(value); + setIsCodeComplete(value.length === 6); + }} + onComplete={() => { + setIsCodeCorrect(code === "123456"); + }} + /> + {!isCodeCorrect && isCodeComplete && ( + The OTP entered is not correct. Try again + )} +
+ + Verify + +
+

+ + Didn't receive any code? + + setIsOtpResent(true)} + > + Resend OTP + +

+ {isOtpResent && ( + <> +
+ + Or + +
+

{ + setCurrentStage(0); + setIsOtpResent(false); + setIsCodeComplete(false); + setCode(""); + setEmail(""); + }} + > + Change email +

+ + )} +
+ + ); + + const VerificationSuccessful = ( + <> +
+ Verification Successful + + Your verification was successful, you can now proceed to reset your + password + +
+ + Reset Password + + + ); + + const VerificationSuccessfulMessage = ( + +
+
+ +

+ Email Verified Successfully +

+
+ setShowSuccessMessage(false)} + /> +
+
+ ); + + const sections = [ + { + element: Default, + stage: 0, + onSubmit: () => setCurrentStage(1), + }, + { + element: VerificationCode, + stage: 1, + onSubmit: () => setCurrentStage(2), + }, + { + element: VerificationSuccessful, + stage: 2, + onSubmit: () => {}, + }, + ]; + + return ( +
+ + {currentStage === 2 && + showSuccessMessage && + VerificationSuccessfulMessage} + + {sections.map( + (section, index) => + section.stage === currentStage && ( +
{ + event.preventDefault(); + section.onSubmit(); + }} + key={index} + className="mt-8 flex w-full max-w-[552px] flex-col gap-y-5 sm:gap-y-6" + > + {section.element} +
+ ), + )} +
+ ); +}; export default ForgotPassword; diff --git a/src/app/(auth-routes)/layout.tsx b/src/app/(auth-routes)/layout.tsx index 0248d906d..8f29f2af4 100644 --- a/src/app/(auth-routes)/layout.tsx +++ b/src/app/(auth-routes)/layout.tsx @@ -5,7 +5,9 @@ function Layout({ children }) { return ( <> -
{children}
+
+ {children} +