forgot password
This commit is contained in:
+7
-2
@@ -42,12 +42,17 @@
|
|||||||
"enter_mobile_number": "شماره موبایل خود را وارد کنید",
|
"enter_mobile_number": "شماره موبایل خود را وارد کنید",
|
||||||
"try_again": "ارسال مجدد",
|
"try_again": "ارسال مجدد",
|
||||||
"toast_resend_code": "کد جدیدی برای شما ارسال شد",
|
"toast_resend_code": "کد جدیدی برای شما ارسال شد",
|
||||||
"old_version": "نسخه قدیمی داشبورد"
|
"old_version": "نسخه قدیمی داشبورد",
|
||||||
|
"enter_info_forgot": "ایمیل خود را وارد کنید",
|
||||||
|
"welcome_forgot": "فراموشی رمز عبور",
|
||||||
|
"email_code": "کد تایید",
|
||||||
|
"newPassword": "پسورد جدید"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"required": "این فیلد اجباری می باشد",
|
"required": "این فیلد اجباری می باشد",
|
||||||
"password_not_match": "رمز عبور با تکرار آن مطابقت ندارد",
|
"password_not_match": "رمز عبور با تکرار آن مطابقت ندارد",
|
||||||
"is_not_image": "فرمت فایل انتخاب شده اشتباه می باشد"
|
"is_not_image": "فرمت فایل انتخاب شده اشتباه می باشد",
|
||||||
|
"format_email_error": "فرمت ایمیل اشتباه است"
|
||||||
},
|
},
|
||||||
"description": "توضیحات",
|
"description": "توضیحات",
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { useState, type FC } from 'react'
|
||||||
|
import LogoImage from '../../assets/images/logo.svg'
|
||||||
|
import LogoSmallImage from '../../assets/images/logo-small.svg'
|
||||||
|
import ForgotStep1 from './components/ForgotStep1'
|
||||||
|
import ForgotStep2 from './components/ForgotStep2'
|
||||||
|
|
||||||
|
|
||||||
|
const Forgot: FC = () => {
|
||||||
|
|
||||||
|
const [step, setStep] = useState<number>(1)
|
||||||
|
const [email, setEmail] = useState<string>('')
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='w-full h-full flex justify-center lg:py-[75px] py-4 lg:items-center lg:px-10 px-4'>
|
||||||
|
<div className='flex w-full max-h-[812px] max-w-[1200px] bg-secondary h-full rounded-3xl overflow-hidden'>
|
||||||
|
<div className='flex-1 min-w-[50%] overflow-y-auto bg-white lg:px-9 px-4 py-7'>
|
||||||
|
<div className='flex-1 h-full flex flex-col'>
|
||||||
|
|
||||||
|
<div className='flex relative flex-1 flex-col h-full justify-center'>
|
||||||
|
<img src={LogoSmallImage} className='w-8 hidden xl:block' />
|
||||||
|
<img src={LogoImage} className='w-44 right-0 left-0 mx-auto absolute top-10 xl:hidden' />
|
||||||
|
{
|
||||||
|
step === 1 ?
|
||||||
|
<ForgotStep1 changeEmail={setEmail} changeStep={setStep} />
|
||||||
|
:
|
||||||
|
<ForgotStep2 email={email} changeStep={setStep} />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex-1 min-w-[50%] lg:flex hidden justify-center items-center'>
|
||||||
|
<img src={LogoImage} className='h-20' />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Forgot
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import { FC } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Input from '../../../components/Input'
|
||||||
|
import { useFormik } from 'formik'
|
||||||
|
import { ForgotPasswordType } from '../types/AuthTypes'
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
import Button from '../../../components/Button'
|
||||||
|
import { useForgotPassword } from '../hooks/useAuthData'
|
||||||
|
import { toast } from '../../../components/Toast'
|
||||||
|
import { ErrorType } from '../../../helpers/types'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
changeStep: (value: number) => void,
|
||||||
|
changeEmail: (value: string) => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
const ForgotStep1: FC<Props> = ({ changeStep, changeEmail }) => {
|
||||||
|
|
||||||
|
const { t } = useTranslation('global')
|
||||||
|
const { mutate, isPending } = useForgotPassword()
|
||||||
|
const formik = useFormik<ForgotPasswordType>({
|
||||||
|
initialValues: {
|
||||||
|
email: ''
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
email: Yup.string().email(t('errors.format_email_error')).required(t('errors.required'))
|
||||||
|
}),
|
||||||
|
onSubmit: (values) => {
|
||||||
|
mutate(values, {
|
||||||
|
onSuccess: (data) => {
|
||||||
|
toast(data?.data?.message)
|
||||||
|
changeEmail(values.email)
|
||||||
|
changeStep(2)
|
||||||
|
},
|
||||||
|
onError: (error: ErrorType) => {
|
||||||
|
toast(error.response?.data?.error.message[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='mt-5'>
|
||||||
|
<h2 className='text-2xl font-bold'>
|
||||||
|
{t('auth.welcome_forgot')}
|
||||||
|
</h2>
|
||||||
|
<p className='text-description text-sm mt-2'>
|
||||||
|
{t('auth.enter_info_forgot')}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className='mt-16'>
|
||||||
|
<Input
|
||||||
|
label={t('email')}
|
||||||
|
{...formik.getFieldProps('email')}
|
||||||
|
error_text={formik.touched.email && formik.errors.email ? formik.errors.email : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
label={t('auth.next')}
|
||||||
|
className='mt-8'
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
isLoading={isPending}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ForgotStep1
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import { FC } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Input from '../../../components/Input'
|
||||||
|
import { useFormik } from 'formik'
|
||||||
|
import { ResetPasswordType } from '../types/AuthTypes'
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
import Button from '../../../components/Button'
|
||||||
|
import { useResetPassword } from '../hooks/useAuthData'
|
||||||
|
import { toast } from '../../../components/Toast'
|
||||||
|
import { ErrorType } from '../../../helpers/types'
|
||||||
|
import { Pages } from '../../../config/Pages'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
changeStep: (value: number) => void,
|
||||||
|
email: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const ForgotStep2: FC<Props> = ({ email }) => {
|
||||||
|
|
||||||
|
const { t } = useTranslation('global')
|
||||||
|
const { mutate, isPending } = useResetPassword()
|
||||||
|
const formik = useFormik<ResetPasswordType>({
|
||||||
|
initialValues: {
|
||||||
|
email: email,
|
||||||
|
code: '',
|
||||||
|
newPassword: ''
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
email: Yup.string().email(t('errors.format_email_error')).required(t('errors.required')),
|
||||||
|
code: Yup.string().required(t('errors.required')),
|
||||||
|
newPassword: Yup.string().required(t('errors.required')),
|
||||||
|
}),
|
||||||
|
onSubmit: (values) => {
|
||||||
|
mutate(values, {
|
||||||
|
onSuccess: (data) => {
|
||||||
|
toast(data?.data?.message)
|
||||||
|
window.location.href = Pages.auth.login
|
||||||
|
},
|
||||||
|
onError: (error: ErrorType) => {
|
||||||
|
toast(error.response?.data?.error.message[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='mt-5'>
|
||||||
|
<h2 className='text-2xl font-bold'>
|
||||||
|
{t('auth.welcome_forgot')}
|
||||||
|
</h2>
|
||||||
|
<p className='text-description text-sm mt-2'>
|
||||||
|
{t('auth.enter_info_forgot')}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className='mt-16'>
|
||||||
|
<Input
|
||||||
|
readOnly
|
||||||
|
label={t('email')}
|
||||||
|
{...formik.getFieldProps('email')}
|
||||||
|
value={email}
|
||||||
|
error_text={formik.touched.email && formik.errors.email ? formik.errors.email : ''}
|
||||||
|
/>
|
||||||
|
<div className='mt-5'>
|
||||||
|
<Input
|
||||||
|
label={t('auth.email_code')}
|
||||||
|
{...formik.getFieldProps('code')}
|
||||||
|
error_text={formik.touched.code && formik.errors.code ? formik.errors.code : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='mt-5'>
|
||||||
|
<Input
|
||||||
|
label={t('auth.newPassword')}
|
||||||
|
{...formik.getFieldProps('newPassword')}
|
||||||
|
error_text={formik.touched.newPassword && formik.errors.newPassword ? formik.errors.newPassword : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
label={t('auth.next')}
|
||||||
|
className='mt-8'
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
isLoading={isPending}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ForgotStep2
|
||||||
@@ -11,6 +11,9 @@ import { isEmail } from '../../../config/func'
|
|||||||
import { useCheckHasAccount, useLoginWithOtp } from '../hooks/useAuthData'
|
import { useCheckHasAccount, useLoginWithOtp } from '../hooks/useAuthData'
|
||||||
import { ErrorType } from '../../../helpers/types'
|
import { ErrorType } from '../../../helpers/types'
|
||||||
import { toast } from '../../../components/Toast'
|
import { toast } from '../../../components/Toast'
|
||||||
|
import { ArrowLeft } from 'iconsax-react'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import { Pages } from '../../../config/Pages'
|
||||||
const LoginStep1: FC = () => {
|
const LoginStep1: FC = () => {
|
||||||
|
|
||||||
const { t } = useTranslation('global')
|
const { t } = useTranslation('global')
|
||||||
@@ -100,12 +103,12 @@ const LoginStep1: FC = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div> */}
|
</div> */}
|
||||||
|
|
||||||
{/* <a href='https://accounts.danakcorp.com' target='_blank' className='mt-6 flex gap-1 text-sm justify-center text-description'>
|
<Link to={Pages.auth.forgotPassword} className='mt-6 flex gap-1 text-sm justify-center text-description'>
|
||||||
<div>
|
<div>
|
||||||
{t('auth.old_version')}
|
{t('auth.forgot_password')}
|
||||||
</div>
|
</div>
|
||||||
<ArrowLeft size={20} color='black' />
|
<ArrowLeft size={20} color='black' />
|
||||||
</a> */}
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,4 +42,16 @@ export const useLogout = () => {
|
|||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: (_) => api.logout(),
|
mutationFn: (_) => api.logout(),
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useForgotPassword = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.forgotPassword,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useResetPassword = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.resetPassword,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
@@ -2,11 +2,13 @@ import axios from "../../../config/axios";
|
|||||||
import {
|
import {
|
||||||
CheckHasAccountPhoneType,
|
CheckHasAccountPhoneType,
|
||||||
CheckHasAccountType,
|
CheckHasAccountType,
|
||||||
|
ForgotPasswordType,
|
||||||
LoginWithOtpType,
|
LoginWithOtpType,
|
||||||
LoginWithPasswordType,
|
LoginWithPasswordType,
|
||||||
OtpVerifyType,
|
OtpVerifyType,
|
||||||
RefreshTokenType,
|
RefreshTokenType,
|
||||||
RegisterType,
|
RegisterType,
|
||||||
|
ResetPasswordType,
|
||||||
} from "../types/AuthTypes";
|
} from "../types/AuthTypes";
|
||||||
|
|
||||||
export const loginWithPassword = async (params: LoginWithPasswordType) => {
|
export const loginWithPassword = async (params: LoginWithPasswordType) => {
|
||||||
@@ -29,7 +31,7 @@ export const checkHasAccount = async (params: CheckHasAccountType) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const checkHasAccountRegister = async (
|
export const checkHasAccountRegister = async (
|
||||||
params: CheckHasAccountPhoneType
|
params: CheckHasAccountPhoneType,
|
||||||
) => {
|
) => {
|
||||||
const { data } = await axios.post(`/auth/register/initiate`, params);
|
const { data } = await axios.post(`/auth/register/initiate`, params);
|
||||||
return data;
|
return data;
|
||||||
@@ -48,3 +50,13 @@ export const logout = async () => {
|
|||||||
const { data } = await axios.post(`/auth/logout`);
|
const { data } = await axios.post(`/auth/logout`);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const forgotPassword = async (params: ForgotPasswordType) => {
|
||||||
|
const { data } = await axios.post(`/auth/forgot-password`, params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const resetPassword = async (params: ResetPasswordType) => {
|
||||||
|
const { data } = await axios.post(`/auth/reset-password`, params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -48,3 +48,13 @@ export type RegisterType = {
|
|||||||
export type RefreshTokenType = {
|
export type RefreshTokenType = {
|
||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ForgotPasswordType = {
|
||||||
|
email: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ResetPasswordType = {
|
||||||
|
newPassword: string;
|
||||||
|
email: string;
|
||||||
|
code: string;
|
||||||
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { FC } from 'react'
|
|||||||
import { Route, Routes } from 'react-router-dom'
|
import { Route, Routes } from 'react-router-dom'
|
||||||
import { Pages } from '../config/Pages'
|
import { Pages } from '../config/Pages'
|
||||||
import Login from '../pages/auth/Login'
|
import Login from '../pages/auth/Login'
|
||||||
|
import Forgot from '../pages/auth/Forgot'
|
||||||
// import Register from '../pages/auth/Register'
|
// import Register from '../pages/auth/Register'
|
||||||
|
|
||||||
const AuthRouter: FC = () => {
|
const AuthRouter: FC = () => {
|
||||||
@@ -9,6 +10,7 @@ const AuthRouter: FC = () => {
|
|||||||
<Routes>
|
<Routes>
|
||||||
<Route path={Pages.auth.login} element={<Login />} />
|
<Route path={Pages.auth.login} element={<Login />} />
|
||||||
<Route path={Pages.auth.register} element={<Login />} />
|
<Route path={Pages.auth.register} element={<Login />} />
|
||||||
|
<Route path={Pages.auth.forgotPassword} element={<Forgot />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user