128 lines
3.9 KiB
TypeScript
128 lines
3.9 KiB
TypeScript
import ActionLink from '@/components/shared/ActionLink'
|
|
import Captcha from '@/components/shared/Captcha'
|
|
import Alert from '@/components/ui/Alert'
|
|
import Button from '@/components/ui/Button'
|
|
import { FormContainer, FormItem } from '@/components/ui/Form'
|
|
import Input from '@/components/ui/Input'
|
|
import { ROUTES_ENUM } from '@/constants/route.constant'
|
|
import { sendPasswordResetCode } from '@/proxy/account/account.service'
|
|
import { store } from '@/store'
|
|
import useTimeOutMessage from '@/utils/hooks/useTimeOutMessage'
|
|
import type { AxiosError } from 'axios'
|
|
import { Field, Form, Formik } from 'formik'
|
|
import { motion } from 'framer-motion'
|
|
import { useState } from 'react'
|
|
import * as Yup from 'yup'
|
|
|
|
type ForgotPasswordFormSchema = {
|
|
email: string
|
|
captchaResponse: string
|
|
}
|
|
|
|
const validationSchema = Yup.object().shape({
|
|
email: Yup.string().required('Please enter your email'),
|
|
captchaResponse: Yup.string().required(),
|
|
})
|
|
|
|
const ForgotPassword = () => {
|
|
const { userName } = store.getState().auth.user
|
|
const disableSubmit = false
|
|
const signInUrl = ROUTES_ENUM.account.login
|
|
|
|
const [emailSent, setEmailSent] = useState(false)
|
|
|
|
const [message, setMessage] = useTimeOutMessage()
|
|
|
|
const onSendMail = async (
|
|
values: ForgotPasswordFormSchema,
|
|
setSubmitting: (isSubmitting: boolean) => void,
|
|
) => {
|
|
setSubmitting(true)
|
|
try {
|
|
const resp = await sendPasswordResetCode(values)
|
|
if (resp.data) {
|
|
setSubmitting(false)
|
|
setEmailSent(true)
|
|
}
|
|
} catch (errors) {
|
|
setMessage(
|
|
(errors as AxiosError<{ message: string }>)?.response?.data?.message ||
|
|
(errors as Error).toString(),
|
|
)
|
|
setSubmitting(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<motion.div
|
|
initial={{ opacity: 0, x: 100 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ duration: 0.5, origin: 1 }}
|
|
>
|
|
<div className="mb-6">
|
|
{emailSent ? (
|
|
<>
|
|
<h3 className="mb-1">Check your email</h3>
|
|
<p>We have sent a password recovery instruction to your email</p>
|
|
</>
|
|
) : (
|
|
<>
|
|
<h3 className="mb-1">Forgot Password</h3>
|
|
<p>Please enter your email address to receive a verification code</p>
|
|
</>
|
|
)}
|
|
</div>
|
|
{message && (
|
|
<Alert showIcon className="mb-4" type="danger">
|
|
{message}
|
|
</Alert>
|
|
)}
|
|
<Formik
|
|
initialValues={{
|
|
email: userName,
|
|
captchaResponse: '',
|
|
}}
|
|
validationSchema={validationSchema}
|
|
onSubmit={(values, { setSubmitting }) => {
|
|
if (!disableSubmit) {
|
|
onSendMail(values, setSubmitting)
|
|
} else {
|
|
setSubmitting(false)
|
|
}
|
|
}}
|
|
>
|
|
{({ touched, errors, isSubmitting, setFieldValue }) => (
|
|
<Form>
|
|
<FormContainer>
|
|
<div className={emailSent ? 'hidden' : ''}>
|
|
<FormItem invalid={errors.email && touched.email} errorMessage={errors.email}>
|
|
<Field
|
|
type="email"
|
|
autoComplete="off"
|
|
name="email"
|
|
placeholder="Email"
|
|
component={Input}
|
|
/>
|
|
</FormItem>
|
|
</div>
|
|
<Captcha
|
|
onError={() => setFieldValue('captchaResponse', '')}
|
|
onExpire={() => setFieldValue('captchaResponse', '')}
|
|
onSuccess={(token: string) => setFieldValue('captchaResponse', token)}
|
|
/>
|
|
<Button block loading={isSubmitting} variant="solid" type="submit">
|
|
{emailSent ? 'Resend Email' : 'Send Email'}
|
|
</Button>
|
|
<div className="mt-4 text-center">
|
|
<span>Back to </span>
|
|
<ActionLink to={signInUrl}>Sign in</ActionLink>
|
|
</div>
|
|
</FormContainer>
|
|
</Form>
|
|
)}
|
|
</Formik>
|
|
</motion.div>
|
|
)
|
|
}
|
|
|
|
export default ForgotPassword
|