From f729bd399978101f90824b5ba1e3097577c84a28 Mon Sep 17 00:00:00 2001 From: Dakshesh Jain Date: Thu, 16 Feb 2023 16:19:05 +0530 Subject: [PATCH 1/5] feat: resend login code on signing page after 30 seconds --- .../components/account/email-code-form.tsx | 51 ++++++++++++++++--- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/apps/app/components/account/email-code-form.tsx b/apps/app/components/account/email-code-form.tsx index 003d515f4f3..79a0f115ec9 100644 --- a/apps/app/components/account/email-code-form.tsx +++ b/apps/app/components/account/email-code-form.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; // ui import { CheckCircleIcon } from "@heroicons/react/20/solid"; @@ -15,14 +15,21 @@ type EmailCodeFormValues = { token?: string; }; +const RESEND_CODE_TIMER = 30; + export const EmailCodeForm = ({ onSuccess }: any) => { const [codeSent, setCodeSent] = useState(false); + const [codeResent, setCodeResent] = useState(false); + const [isCodeResending, setIsCodeResending] = useState(false); + const [resendCodeTimer, setResendCodeTimer] = useState(RESEND_CODE_TIMER); + const { setToastAlert } = useToast(); const { register, handleSubmit, setError, setValue, + getValues, formState: { errors, isSubmitting, isValid, isDirty }, } = useForm({ defaultValues: { @@ -66,10 +73,20 @@ export const EmailCodeForm = ({ onSuccess }: any) => { }); }; + useEffect(() => { + let timer: NodeJS.Timeout; + if (codeSent) { + timer = setTimeout(() => { + setResendCodeTimer((prev) => prev - 1); + }, 1000); + } + return () => clearTimeout(timer); + }, [codeSent, resendCodeTimer]); + return ( <>
- {codeSent && ( + {(codeSent || codeResent) && (
@@ -77,7 +94,9 @@ export const EmailCodeForm = ({ onSuccess }: any) => {

- Please check your mail for code. + {codeResent + ? "Please check your mail for new code." + : "Please check your mail for code."}

@@ -114,15 +133,31 @@ export const EmailCodeForm = ({ onSuccess }: any) => { error={errors.token} placeholder="Enter code" /> - {/* */} + {resendCodeTimer > 0 ? ( +

+ Didn{"'"}t receive code? Get new code in {resendCodeTimer} seconds. +

+ ) : isCodeResending ? ( + "Sending code..." + ) : ( + "Resend code" + )} +
)}
From 19f2057a96ea8a300a2b2273ceac913e0726968b Mon Sep 17 00:00:00 2001 From: Dakshesh Jain Date: Thu, 16 Feb 2023 18:20:34 +0530 Subject: [PATCH 2/5] feat: handling error on code send --- .../components/account/email-code-form.tsx | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/apps/app/components/account/email-code-form.tsx b/apps/app/components/account/email-code-form.tsx index 79a0f115ec9..a6abb88f247 100644 --- a/apps/app/components/account/email-code-form.tsx +++ b/apps/app/components/account/email-code-form.tsx @@ -21,6 +21,7 @@ export const EmailCodeForm = ({ onSuccess }: any) => { const [codeSent, setCodeSent] = useState(false); const [codeResent, setCodeResent] = useState(false); const [isCodeResending, setIsCodeResending] = useState(false); + const [errorResendingCode, setErrorResendingCode] = useState(false); const [resendCodeTimer, setResendCodeTimer] = useState(RESEND_CODE_TIMER); const { setToastAlert } = useToast(); @@ -42,6 +43,7 @@ export const EmailCodeForm = ({ onSuccess }: any) => { }); const onSubmit = async ({ email }: EmailCodeFormValues) => { + setErrorResendingCode(false); await authenticationService .emailCode({ email }) .then((res) => { @@ -49,7 +51,12 @@ export const EmailCodeForm = ({ onSuccess }: any) => { setCodeSent(true); }) .catch((err) => { - console.log(err); + setErrorResendingCode(true); + setToastAlert({ + title: "Oops!", + type: "error", + message: err?.error, + }); }); }; @@ -83,6 +90,12 @@ export const EmailCodeForm = ({ onSuccess }: any) => { return () => clearTimeout(timer); }, [codeSent, resendCodeTimer]); + const emailOld = getValues("email"); + + useEffect(() => { + setErrorResendingCode(false); + }, [emailOld]); + return ( <> @@ -146,7 +159,9 @@ export const EmailCodeForm = ({ onSuccess }: any) => { setResendCodeTimer(RESEND_CODE_TIMER); }); }} - disabled={resendCodeTimer > 0} + disabled={ + resendCodeTimer > 0 || isCodeResending || isSubmitting || errorResendingCode + } > {resendCodeTimer > 0 ? (

@@ -154,6 +169,8 @@ export const EmailCodeForm = ({ onSuccess }: any) => {

) : isCodeResending ? ( "Sending code..." + ) : errorResendingCode ? ( + "Please try again later" ) : ( "Resend code" )} From 2535dae30a3d209668ca19e0e2ff889b8943d657 Mon Sep 17 00:00:00 2001 From: Dakshesh Jain Date: Fri, 17 Feb 2023 13:06:26 +0530 Subject: [PATCH 3/5] refractor: isResendDisabled varible for resend button --- apps/app/components/account/email-code-form.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/app/components/account/email-code-form.tsx b/apps/app/components/account/email-code-form.tsx index a6abb88f247..8184ccc8f13 100644 --- a/apps/app/components/account/email-code-form.tsx +++ b/apps/app/components/account/email-code-form.tsx @@ -42,6 +42,9 @@ export const EmailCodeForm = ({ onSuccess }: any) => { reValidateMode: "onChange", }); + const isResendDisabled = + resendCodeTimer > 0 || isCodeResending || isSubmitting || errorResendingCode; + const onSubmit = async ({ email }: EmailCodeFormValues) => { setErrorResendingCode(false); await authenticationService @@ -159,9 +162,7 @@ export const EmailCodeForm = ({ onSuccess }: any) => { setResendCodeTimer(RESEND_CODE_TIMER); }); }} - disabled={ - resendCodeTimer > 0 || isCodeResending || isSubmitting || errorResendingCode - } + disabled={isResendDisabled} > {resendCodeTimer > 0 ? (

From e694c40da7484dcb77672ca4ac136d6d84594e67 Mon Sep 17 00:00:00 2001 From: Dakshesh Jain Date: Fri, 17 Feb 2023 14:55:15 +0530 Subject: [PATCH 4/5] dev: timer count-down hook --- apps/app/hooks/use-timer.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 apps/app/hooks/use-timer.tsx diff --git a/apps/app/hooks/use-timer.tsx b/apps/app/hooks/use-timer.tsx new file mode 100644 index 00000000000..1edf4931ab0 --- /dev/null +++ b/apps/app/hooks/use-timer.tsx @@ -0,0 +1,19 @@ +import { useState, useEffect } from "react"; + +const TIMER = 30; + +const useTimer = (initialValue: number = TIMER) => { + const [timer, setTimer] = useState(initialValue); + + useEffect(() => { + const interval = setInterval(() => { + setTimer((prev) => prev - 1); + }, 1000); + + return () => clearInterval(interval); + }, []); + + return { timer, setTimer }; +}; + +export default useTimer; From b4c5e9b5afb5ae7588ecebb77201896e3a2d8aec Mon Sep 17 00:00:00 2001 From: Dakshesh Jain Date: Fri, 17 Feb 2023 15:04:07 +0530 Subject: [PATCH 5/5] refractor: using new timer hook in sign in page --- .../components/account/email-code-form.tsx | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/apps/app/components/account/email-code-form.tsx b/apps/app/components/account/email-code-form.tsx index 8184ccc8f13..fbf907b7bc1 100644 --- a/apps/app/components/account/email-code-form.tsx +++ b/apps/app/components/account/email-code-form.tsx @@ -6,6 +6,7 @@ import { Button, Input } from "components/ui"; // services import authenticationService from "services/authentication.service"; import useToast from "hooks/use-toast"; +import useTimer from "hooks/use-timer"; // icons // types @@ -15,16 +16,15 @@ type EmailCodeFormValues = { token?: string; }; -const RESEND_CODE_TIMER = 30; - export const EmailCodeForm = ({ onSuccess }: any) => { const [codeSent, setCodeSent] = useState(false); const [codeResent, setCodeResent] = useState(false); const [isCodeResending, setIsCodeResending] = useState(false); const [errorResendingCode, setErrorResendingCode] = useState(false); - const [resendCodeTimer, setResendCodeTimer] = useState(RESEND_CODE_TIMER); const { setToastAlert } = useToast(); + const { timer: resendCodeTimer, setTimer: setResendCodeTimer } = useTimer(); + const { register, handleSubmit, @@ -83,16 +83,6 @@ export const EmailCodeForm = ({ onSuccess }: any) => { }); }; - useEffect(() => { - let timer: NodeJS.Timeout; - if (codeSent) { - timer = setTimeout(() => { - setResendCodeTimer((prev) => prev - 1); - }, 1000); - } - return () => clearTimeout(timer); - }, [codeSent, resendCodeTimer]); - const emailOld = getValues("email"); useEffect(() => { @@ -159,7 +149,7 @@ export const EmailCodeForm = ({ onSuccess }: any) => { onSubmit({ email: getValues("email") }).then(() => { setCodeResent(true); setIsCodeResending(false); - setResendCodeTimer(RESEND_CODE_TIMER); + setResendCodeTimer(30); }); }} disabled={isResendDisabled} @@ -192,7 +182,11 @@ export const EmailCodeForm = ({ onSuccess }: any) => {