From 7deb8f353c5198efe7eb7d75bbe0ad73375c340f Mon Sep 17 00:00:00 2001 From: Bunsy Date: Fri, 19 Jan 2024 13:54:42 +0700 Subject: [PATCH] fix: confirm users before they reload the page Signed-off-by: Bunsy --- .../ResetPasswordPage/ResetPasswordPage.tsx | 24 ++++++--- signup-ui/src/pages/SignUpPage/SignUpPage.tsx | 50 +++++++++++++++++-- 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/signup-ui/src/pages/ResetPasswordPage/ResetPasswordPage.tsx b/signup-ui/src/pages/ResetPasswordPage/ResetPasswordPage.tsx index c7ead3a6..ff6345d1 100644 --- a/signup-ui/src/pages/ResetPasswordPage/ResetPasswordPage.tsx +++ b/signup-ui/src/pages/ResetPasswordPage/ResetPasswordPage.tsx @@ -1,5 +1,6 @@ import { useCallback, useEffect, useMemo } from "react"; import { yupResolver } from "@hookform/resolvers/yup"; +import { isEqual } from "lodash"; import { Resolver, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import * as yup from "yup"; @@ -69,7 +70,12 @@ export const ResetPasswordPage = ({ settings }: ResetPasswordPageProps) => { // Step 3 - ResetPassword yup.object({ newPassword: validatePassword(settings, t), - confirmNewPassword: validateConfirmPassword("newPassword", settings, t, false), + confirmNewPassword: validateConfirmPassword( + "newPassword", + settings, + t, + false + ), }), // Step 4 - ResetPasswordStatus yup.object({}), @@ -92,13 +98,19 @@ export const ResetPasswordPage = ({ settings }: ResetPasswordPageProps) => { }); const { + getValues, formState: { isDirty }, } = methods; useEffect(() => { + if (isEqual(resetPasswordFormDefaultValues, getValues())) return; + if ( step === ResetPasswordStep.ResetPasswordConfirmation || - (criticalError && criticalError.errorCode === "invalid_transaction") + (criticalError && + ["invalid_transaction", "knowledgebase_mismatch"].includes( + criticalError.errorCode + )) ) return; @@ -115,7 +127,7 @@ export const ResetPasswordPage = ({ settings }: ResetPasswordPageProps) => { return () => { window.removeEventListener("beforeunload", handleTabBeforeUnload); }; - }, [step, criticalError]); + }, [step, criticalError, getValues()]); const getResetPasswordContent = (step: ResetPasswordStep) => { switch (step) { @@ -137,9 +149,9 @@ export const ResetPasswordPage = ({ settings }: ResetPasswordPageProps) => { return ( <> {criticalError && - ["invalid_transaction", "knowledgebase_mismatch"].includes(criticalError.errorCode) && ( - - )} + ["invalid_transaction", "knowledgebase_mismatch"].includes( + criticalError.errorCode + ) && }
{getResetPasswordContent(step)}
diff --git a/signup-ui/src/pages/SignUpPage/SignUpPage.tsx b/signup-ui/src/pages/SignUpPage/SignUpPage.tsx index cef187cd..b6412fa5 100644 --- a/signup-ui/src/pages/SignUpPage/SignUpPage.tsx +++ b/signup-ui/src/pages/SignUpPage/SignUpPage.tsx @@ -1,11 +1,14 @@ -import { useCallback, useMemo } from "react"; +import { useCallback, useEffect, useMemo } from "react"; import { yupResolver } from "@hookform/resolvers/yup"; +import { useMutationState } from "@tanstack/react-query"; +import { isEqual } from "lodash"; import { Resolver, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import * as yup from "yup"; import { Button } from "~components/ui/button"; import { Form } from "~components/ui/form"; +import { keys as mutationKeys } from "~pages/shared/mutations"; import { validateCaptchaToken, validateConfirmPassword, @@ -14,7 +17,7 @@ import { validatePassword, validateUsername, } from "~pages/shared/validation"; -import { SettingsDto } from "~typings/types"; +import { SettingsDto, VerifyChallengeResponseDto } from "~typings/types"; import { AccountRegistrationStatus } from "./AccountRegistrationStatus/AccountRegistrationStatus"; import AccountSetup from "./AccountSetup"; @@ -109,6 +112,43 @@ export const SignUpPage = ({ settings }: SignUpPageProps) => { mode: "onBlur", }); + const { getValues } = methods; + + const [challengeVerification] = useMutationState({ + filters: { + mutationKey: mutationKeys.challengeVerification, + status: "success", + }, + select: (mutation) => mutation.state.data as VerifyChallengeResponseDto, + }); + + useEffect(() => { + if (isEqual(signUpFormDefaultValues, getValues())) return; + + if ( + (step === SignUpStep.PhoneStatus && + challengeVerification.errors.length > 0 && + ["already-registered", "identifier_already_registered"].includes( + challengeVerification.errors[0].errorCode + )) || + step === SignUpStep.AccountRegistrationStatus || + (criticalError && criticalError.errorCode === "invalid_transaction") + ) + return; + + const handleTabBeforeUnload = (event: BeforeUnloadEvent) => { + event.preventDefault(); + + return (event.returnValue = t("reset_password_discontinue_prompt")); + }; + + window.addEventListener("beforeunload", handleTabBeforeUnload); + + return () => { + window.removeEventListener("beforeunload", handleTabBeforeUnload); + }; + }, [step, criticalError, getValues()]); + const getSignUpStepContent = (step: SignUpStep) => { switch (step) { case SignUpStep.Phone: @@ -131,9 +171,9 @@ export const SignUpPage = ({ settings }: SignUpPageProps) => { return ( <> {criticalError && - ["invalid_transaction", "identifier_already_registered"].includes(criticalError.errorCode) && ( - - )} + ["invalid_transaction", "identifier_already_registered"].includes( + criticalError.errorCode + ) && }
{getSignUpStepContent(step)}