diff --git a/.changeset/healthy-cycles-visit.md b/.changeset/healthy-cycles-visit.md new file mode 100644 index 000000000..b1d9b2a37 --- /dev/null +++ b/.changeset/healthy-cycles-visit.md @@ -0,0 +1,5 @@ +--- +"@bigcommerce/catalyst-core": patch +--- + +fix redirection to the Login page after password change diff --git a/core/app/[locale]/(default)/account/[tab]/_components/account-status-provider.tsx b/core/app/[locale]/(default)/account/[tab]/_components/account-status-provider.tsx index 97c2b1f31..9474129b0 100644 --- a/core/app/[locale]/(default)/account/[tab]/_components/account-status-provider.tsx +++ b/core/app/[locale]/(default)/account/[tab]/_components/account-status-provider.tsx @@ -1,6 +1,6 @@ 'use client'; -import { createContext, PropsWithChildren, useContext, useEffect, useState } from 'react'; +import { createContext, ReactNode, useContext, useEffect, useState } from 'react'; import { State as AccountState } from '../_actions/submit-customer-change-password-form'; @@ -9,16 +9,22 @@ export const AccountStatusContext = createContext<{ setAccountState: (state: AccountState | ((prevState: AccountState) => AccountState)) => void; } | null>(null); -export const AccountStatusProvider = ({ children }: PropsWithChildren) => { +export const AccountStatusProvider = ({ + children, + isPermanentBanner = false, +}: { + children: ReactNode; + isPermanentBanner?: boolean; +}) => { const [accountState, setAccountState] = useState({ status: 'idle', message: '' }); useEffect(() => { - if (accountState.status !== 'idle') { + if (accountState.status !== 'idle' && !isPermanentBanner) { setTimeout(() => { setAccountState({ status: 'idle', message: '' }); }, 3000); } - }, [accountState, setAccountState]); + }, [accountState, setAccountState, isPermanentBanner]); return ( diff --git a/core/app/[locale]/(default)/login/_components/change-password-form.tsx b/core/app/[locale]/(default)/login/_components/change-password-form.tsx index e88a9a2fa..32a8911b4 100644 --- a/core/app/[locale]/(default)/login/_components/change-password-form.tsx +++ b/core/app/[locale]/(default)/login/_components/change-password-form.tsx @@ -17,6 +17,7 @@ import { Input } from '~/components/ui/input'; import { Message } from '~/components/ui/message'; import { useRouter } from '~/navigation'; +import { useAccountStatusContext } from '../../account/[tab]/_components/account-status-provider'; import { submitChangePasswordForm } from '../_actions/submit-change-password-form'; interface Props { @@ -51,6 +52,7 @@ export const ChangePasswordForm = ({ customerId, customerToken }: Props) => { const [newPassword, setNewPasssword] = useState(''); const [isConfirmPasswordValid, setIsConfirmPasswordValid] = useState(true); + const { setAccountState } = useAccountStatusContext(); const t = useTranslations('Account.ChangePassword'); let messageText = ''; @@ -59,10 +61,6 @@ export const ChangePasswordForm = ({ customerId, customerToken }: Props) => { messageText = state.message; } - if (state.status === 'success') { - messageText = t('successMessage'); - } - const handleNewPasswordChange = (e: ChangeEvent) => setNewPasssword(e.target.value); const handleConfirmPasswordValidation = (e: ChangeEvent) => { @@ -72,12 +70,13 @@ export const ChangePasswordForm = ({ customerId, customerToken }: Props) => { }; if (state.status === 'success') { - setTimeout(() => router.push('/login'), 2000); + setAccountState({ status: 'success', message: t('confirmChangePassword') }); + router.push('/login'); } return ( <> - {(state.status === 'error' || state.status === 'success') && ( + {state.status === 'error' && (

{messageText}

diff --git a/core/app/[locale]/(default)/login/_components/login-form.tsx b/core/app/[locale]/(default)/login/_components/login-form.tsx index de24ad31a..9161e3dec 100644 --- a/core/app/[locale]/(default)/login/_components/login-form.tsx +++ b/core/app/[locale]/(default)/login/_components/login-form.tsx @@ -17,6 +17,7 @@ import { import { Input } from '~/components/ui/input'; import { Message } from '~/components/ui/message'; +import { useAccountStatusContext } from '../../account/[tab]/_components/account-status-provider'; import { submitLoginForm } from '../_actions/submit-login-form'; const SubmitButton = () => { @@ -39,6 +40,7 @@ export const LoginForm = () => { const [isEmailValid, setIsEmailValid] = useState(true); const [isPasswordValid, setIsPasswordValid] = useState(true); const [state, formAction] = useFormState(submitLoginForm, { status: 'idle' }); + const { accountState } = useAccountStatusContext(); const t = useTranslations('Account.Login'); @@ -62,6 +64,12 @@ export const LoginForm = () => { return ( <> + {accountState.status === 'success' && ( + +

{accountState.message}

+
+ )} + {isFormInvalid && ( { const reCaptchaRef = useRef(null); const [reCaptchaToken, setReCaptchaToken] = useState(''); const [isReCaptchaValid, setReCaptchaValid] = useState(true); + const { setAccountState } = useAccountStatusContext(); + const router = useRouter(); const onReCatpchaChange = (token: string | null) => { if (!token) { @@ -96,10 +100,11 @@ export const ResetPasswordForm = ({ reCaptchaSettings }: Props) => { const customerEmail = formData.get('email'); - setFormStatus({ + setAccountState({ status: 'success', - message: t('successMessage', { email: customerEmail?.toString() }), + message: t('confirmResetPassword', { email: customerEmail?.toString() }), }); + router.push('/login'); } if (submit.status === 'error') { @@ -111,7 +116,7 @@ export const ResetPasswordForm = ({ reCaptchaSettings }: Props) => { return ( <> - {formStatus && ( + {formStatus?.status === 'error' && (

{formStatus.message}

diff --git a/core/app/[locale]/(default)/login/layout.tsx b/core/app/[locale]/(default)/login/layout.tsx new file mode 100644 index 000000000..bca388880 --- /dev/null +++ b/core/app/[locale]/(default)/login/layout.tsx @@ -0,0 +1,7 @@ +import { PropsWithChildren } from 'react'; + +import { AccountStatusProvider } from '../account/[tab]/_components/account-status-provider'; + +export default function LoginLayout({ children }: PropsWithChildren) { + return {children}; +} diff --git a/core/messages/en.json b/core/messages/en.json index 7c8f6ac28..24ab49794 100644 --- a/core/messages/en.json +++ b/core/messages/en.json @@ -259,7 +259,7 @@ "Register": { "heading": "New account", "submit": "Create account", - "submitting": "Creating account...", + "submitting": "Creating account...", "recaptchaText": "Pass ReCAPTCHA check", "successMessage": "Dear {firstName} {lastName}, your account was successfully created. Redirecting to account...", "stateProvincePrefix": "Choose state or province", @@ -286,7 +286,8 @@ "confirmPasswordValidationMessage": "Entered passwords are mismatched. Please try again.", "newPasswordValidationMessage": "New password must be different from the current password or/and match confirm password.", "notEmptyMessage": "Field should not be empty", - "successMessage": "Password has been updated successfully!" + "successMessage": "Password has been updated successfully!", + "confirmChangePassword": "Your password has been successfully updated. Please log in using your new credentials." }, "SubmitChangePassword": { "spinnerText": "Submitting...", @@ -297,7 +298,8 @@ "emailLabel": "Email", "emailValidationMessage": "Enter a valid email such as name@domain.com", "successMessage": "Your password reset email is on its way to {email}. If you don't see it, check your spam folder.", - "recaptchaText": "Pass ReCAPTCHA check" + "recaptchaText": "Pass ReCAPTCHA check", + "confirmResetPassword": "If the email address {email} is linked to an account in our store, we have sent you a password reset email. Please check your inbox and spam folder if you don't see it." }, "SubmitResetPassword": { "spinnerText": "Submitting...",