) => {
+ const validationStatus = e.target.validity.valueMissing;
+
+ return setIsEmailValid(!validationStatus);
+ };
+
+ const onSubmit = async (formData: FormData) => {
+ if (reCaptchaSettings?.isEnabledOnStorefront && !reCaptchaToken) {
+ return setReCaptchaValid(false);
+ }
+
+ setReCaptchaValid(true);
+
+ const submit = await submitResetPasswordForm({
+ formData,
+ reCaptchaToken,
+ path: '/login?action=change_password',
+ });
+
+ if (submit.status === 'success') {
+ form.current?.reset();
+
+ const customerEmail = formData.get('email');
+
+ setFormStatus({
+ status: 'success',
+ message: t('successMessage', { email: customerEmail?.toString() }),
+ });
+ }
+
+ if (submit.status === 'error') {
+ setFormStatus({ status: 'error', message: submit.error ?? '' });
+ }
+
+ reCaptchaRef.current?.reset();
+ };
+
+ return (
+ <>
+ {formStatus && (
+
+ {formStatus.message}
+
+ )}
+
+ {t('description')}
+
+
+ >
+ );
+};
diff --git a/apps/core/app/[locale]/(default)/login/page.tsx b/apps/core/app/[locale]/(default)/login/page.tsx
index 9c06fffe0..6d260fc70 100644
--- a/apps/core/app/[locale]/(default)/login/page.tsx
+++ b/apps/core/app/[locale]/(default)/login/page.tsx
@@ -2,11 +2,13 @@ import { Button } from '@bigcommerce/components/button';
import { NextIntlClientProvider } from 'next-intl';
import { getMessages, getTranslations } from 'next-intl/server';
+import { getReCaptchaSettings } from '~/client/queries/get-recaptcha-settings';
import { Link } from '~/components/link';
import { LocaleType } from '~/i18n';
import { ChangePasswordForm } from './_components/change-password-form';
import { LoginForm } from './_components/login-form';
+import { ResetPasswordForm } from './_components/reset-password-form';
export const metadata = {
title: 'Login',
@@ -43,6 +45,19 @@ export default async function Login({ params: { locale }, searchParams }: Props)
);
}
+ if (action === 'reset_password') {
+ const reCaptchaSettings = await getReCaptchaSettings();
+
+ return (
+
+
{t('resetPasswordHeading')}
+
+
+
+
+ );
+ }
+
return (
{t('heading')}
diff --git a/apps/core/client/mutations/submit-reset-password.ts b/apps/core/client/mutations/submit-reset-password.ts
index f41da70c0..e22f6fea5 100644
--- a/apps/core/client/mutations/submit-reset-password.ts
+++ b/apps/core/client/mutations/submit-reset-password.ts
@@ -8,6 +8,7 @@ export const ResetPasswordSchema = z.object({
});
type SubmitResetPassword = z.infer & {
+ path: string;
reCaptchaToken?: string;
};
@@ -27,10 +28,11 @@ const SUBMIT_RESET_PASSWORD_MUTATION = graphql(`
}
`);
-export const submitResetPassword = async ({ email, reCaptchaToken }: SubmitResetPassword) => {
+export const submitResetPassword = async ({ email, path, reCaptchaToken }: SubmitResetPassword) => {
const variables = {
input: {
email,
+ path,
},
...(reCaptchaToken && { reCaptchaV2: { token: reCaptchaToken } }),
};
diff --git a/apps/core/messages/en.json b/apps/core/messages/en.json
index 03dd1d2cc..726ed6856 100644
--- a/apps/core/messages/en.json
+++ b/apps/core/messages/en.json
@@ -191,6 +191,17 @@
"SubmitChangePassword": {
"spinnerText": "Submitting...",
"submitText": "Change password"
+ },
+ "ResetPassword": {
+ "description": "Enter the email associated with your account below. We'll send you instructions to reset your password.",
+ "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"
+ },
+ "SubmitResetPassword": {
+ "spinnerText": "Submitting...",
+ "submitText": "Reset password"
}
},
"NotFound": {