register
This commit is contained in:
@@ -19,6 +19,7 @@ export default tseslint.config(
|
|||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
...reactHooks.configs.recommended.rules,
|
...reactHooks.configs.recommended.rules,
|
||||||
|
'react-hooks/exhaustive-deps': false,
|
||||||
'react-refresh/only-export-components': [
|
'react-refresh/only-export-components': [
|
||||||
'warn',
|
'warn',
|
||||||
{ allowConstantExport: true },
|
{ allowConstantExport: true },
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const DatePickerComponent: FC<Props> = (props: Props) => {
|
|||||||
const formattedDate = `${value.year}/${value.month.number}/${value.day}`;
|
const formattedDate = `${value.year}/${value.month.number}/${value.day}`;
|
||||||
props.onChange(formattedDate);
|
props.onChange(formattedDate);
|
||||||
}
|
}
|
||||||
}, [props, value]);
|
}, [value]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (props.defaulValue && !value) {
|
if (props.defaulValue && !value) {
|
||||||
|
|||||||
+4
-1
@@ -30,13 +30,16 @@
|
|||||||
"verfify_code_text_2": "ارسال شد.",
|
"verfify_code_text_2": "ارسال شد.",
|
||||||
"change_number": "تغییر شماره",
|
"change_number": "تغییر شماره",
|
||||||
"verify_code": "کد تایید ",
|
"verify_code": "کد تایید ",
|
||||||
|
"enter_verify_code": "کد تایید ارسالی را وارد کنید ",
|
||||||
"counter_otp": "مانده تا دریافت مجدد کد",
|
"counter_otp": "مانده تا دریافت مجدد کد",
|
||||||
"login_with_password": "ورود با رمز عبور",
|
"login_with_password": "ورود با رمز عبور",
|
||||||
"enter_password_step3": "رمز عبور را وارد کنید",
|
"enter_password_step3": "رمز عبور را وارد کنید",
|
||||||
"enter_your_password": "رمز عبور خود را وارد کنید.",
|
"enter_your_password": "رمز عبور خود را وارد کنید.",
|
||||||
"forgot_password": "فراموشی رمز عبور",
|
"forgot_password": "فراموشی رمز عبور",
|
||||||
"login_with_otp": "ورود با رمز عبور یکبار مصرف",
|
"login_with_otp": "ورود با رمز عبور یکبار مصرف",
|
||||||
"otp_sent": "کد تایید ارسال شد"
|
"otp_sent": "کد تایید ارسال شد",
|
||||||
|
"mobile_number": "شماره موبایل",
|
||||||
|
"enter_mobile_number": "شماره موبایل خود را وارد کنید"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"required": "این فیلد اجباری می باشد"
|
"required": "این فیلد اجباری می باشد"
|
||||||
|
|||||||
+13
-53
@@ -2,20 +2,23 @@ import { FC } from 'react'
|
|||||||
import LogoImage from '../../assets/images/logo.svg'
|
import LogoImage from '../../assets/images/logo.svg'
|
||||||
import LogoSmallImage from '../../assets/images/logo-small.svg'
|
import LogoSmallImage from '../../assets/images/logo-small.svg'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Input from '../../components/Input'
|
|
||||||
import DatePickerComponent from '../../components/DatePicker'
|
|
||||||
import Button from '../../components/Button'
|
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Pages } from '../../config/Pages'
|
import { Pages } from '../../config/Pages'
|
||||||
|
import RegisterStep1 from './components/RegisterStep1'
|
||||||
|
import { useAuthStore } from './store/AuthStore'
|
||||||
|
import RegisterStep2 from './components/RegisterStep2'
|
||||||
|
|
||||||
|
|
||||||
const Register: FC = () => {
|
const Register: FC = () => {
|
||||||
|
|
||||||
|
const { stepLogin } = useAuthStore()
|
||||||
const { t } = useTranslation('global')
|
const { t } = useTranslation('global')
|
||||||
|
|
||||||
|
|
||||||
return (
|
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='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 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 flex flex-col justify-center min-w-[50%] overflow-y-auto bg-white lg:px-9 px-4 py-7'>
|
||||||
<div className=''>
|
<div className=''>
|
||||||
<img src={LogoSmallImage} className='w-8' />
|
<img src={LogoSmallImage} className='w-8' />
|
||||||
<div className='mt-5'>
|
<div className='mt-5'>
|
||||||
@@ -27,55 +30,12 @@ const Register: FC = () => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <div className='mt-5 text-sm'>
|
{
|
||||||
{t('auth.user_info')}
|
stepLogin === 1 ?
|
||||||
</div> */}
|
<RegisterStep1 />
|
||||||
|
:
|
||||||
<div className='mt-5 rowTwoInput'>
|
<RegisterStep2 />
|
||||||
<Input
|
}
|
||||||
label={t('auth.name')}
|
|
||||||
placeholder={t('auth.enter_name')}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Input
|
|
||||||
label={t('auth.family')}
|
|
||||||
placeholder={t('auth.enter_family')}
|
|
||||||
/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div className='mt-4 min-w-full rowTwoInput'>
|
|
||||||
<DatePickerComponent label={t('auth.dateofbirth')} onChange={(date: string) => console.log(date)} placeholder={t('auth.select_date')} />
|
|
||||||
|
|
||||||
<Input
|
|
||||||
label={t('auth.national_code')}
|
|
||||||
placeholder={t('auth.national_code_enter')}
|
|
||||||
/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='mt-4 rowTwoInput'>
|
|
||||||
<Input
|
|
||||||
label={t('auth.email')}
|
|
||||||
placeholder={t('auth.enter_email')}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
label={t('auth.phonen_number')}
|
|
||||||
placeholder={t('auth.enter_phone_number')}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='mt-4 rowTwoInput'>
|
|
||||||
<Input
|
|
||||||
label={t('auth.password')}
|
|
||||||
placeholder={t('auth.enter_password')}
|
|
||||||
type='password'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
label={t('auth.next')}
|
|
||||||
className='mt-8'
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className='mt-6 flex justify-center gap-2 items-center text-sm'>
|
<div className='mt-6 flex justify-center gap-2 items-center text-sm'>
|
||||||
<p className='text-description'>
|
<p className='text-description'>
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import { FC } from 'react'
|
||||||
|
import Input from '../../../components/Input'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { CheckHasAccountPhoneType } from '../types/AuthTypes'
|
||||||
|
import { useFormik } from 'formik'
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
import { useAuthStore } from '../store/AuthStore'
|
||||||
|
import Error from '../../../components/Error'
|
||||||
|
import Button from '../../../components/Button'
|
||||||
|
import { useCheckHasAccountRegister, useLoginWithOtp } from '../hooks/useAuthData'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import { ErrorType } from '../../../helpers/types'
|
||||||
|
|
||||||
|
const RegisterStep1: FC = () => {
|
||||||
|
|
||||||
|
const { t } = useTranslation('global')
|
||||||
|
const { setPhone, setStepLogin } = useAuthStore()
|
||||||
|
const loginWithOtp = useLoginWithOtp()
|
||||||
|
const checkHasAccount = useCheckHasAccountRegister()
|
||||||
|
|
||||||
|
const formik = useFormik<CheckHasAccountPhoneType>({
|
||||||
|
initialValues: {
|
||||||
|
phone: '',
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
phone: Yup.string()
|
||||||
|
.required(t('errors.required'))
|
||||||
|
}),
|
||||||
|
onSubmit(values) {
|
||||||
|
checkHasAccount.mutate(values, {
|
||||||
|
onSuccess() {
|
||||||
|
setPhone(values.phone)
|
||||||
|
setStepLogin(2)
|
||||||
|
},
|
||||||
|
onError(error: ErrorType) {
|
||||||
|
toast.error(error?.response?.data?.error?.message[0])
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='flex-1'>
|
||||||
|
|
||||||
|
|
||||||
|
<div className='mt-16'>
|
||||||
|
<Input
|
||||||
|
label={t('auth.mobile_number')}
|
||||||
|
placeholder={t('auth.enter_mobile_number')}
|
||||||
|
type='tel'
|
||||||
|
className='text-right'
|
||||||
|
name='phone'
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
value={formik.values.phone}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{
|
||||||
|
formik.touched.phone && formik.errors.phone &&
|
||||||
|
<Error
|
||||||
|
errorText={formik.errors.phone}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<Button
|
||||||
|
label={t('auth.next')}
|
||||||
|
className='mt-8'
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
isLoading={loginWithOtp.isPending || checkHasAccount.isPending}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RegisterStep1
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
import { FC, Fragment } from 'react'
|
||||||
|
import { useFormik } from 'formik'
|
||||||
|
import { RegisterType } from '../types/AuthTypes'
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
import { useAuthStore } from '../store/AuthStore'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Input from '../../../components/Input'
|
||||||
|
import DatePickerComponent from '../../../components/DatePicker'
|
||||||
|
import Button from '../../../components/Button'
|
||||||
|
import { useRegister } from '../hooks/useAuthData'
|
||||||
|
import { ErrorType } from '../../../helpers/types'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import { Pages } from '../../../config/Pages'
|
||||||
|
|
||||||
|
const RegisterStep2: FC = () => {
|
||||||
|
|
||||||
|
const { t } = useTranslation('global')
|
||||||
|
const { phone } = useAuthStore()
|
||||||
|
const register = useRegister()
|
||||||
|
|
||||||
|
const formik = useFormik<RegisterType>({
|
||||||
|
initialValues: {
|
||||||
|
firstName: '',
|
||||||
|
lastName: '',
|
||||||
|
birthDate: '',
|
||||||
|
code: 0,
|
||||||
|
nationalCode: '',
|
||||||
|
password: '',
|
||||||
|
phone: phone,
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
firstName: Yup.string()
|
||||||
|
.required(t('errors.required')),
|
||||||
|
lastName: Yup.string()
|
||||||
|
.required(t('errors.required')),
|
||||||
|
birthDate: Yup.string()
|
||||||
|
.required(t('errors.required')),
|
||||||
|
code: Yup.number()
|
||||||
|
.required(t('errors.required')),
|
||||||
|
nationalCode: Yup.string()
|
||||||
|
.required(t('errors.required')),
|
||||||
|
password: Yup.string()
|
||||||
|
.required(t('errors.required')),
|
||||||
|
phone: Yup.string()
|
||||||
|
.required(t('errors.required')),
|
||||||
|
}),
|
||||||
|
onSubmit(values) {
|
||||||
|
register.mutate(values, {
|
||||||
|
onSuccess(data) {
|
||||||
|
localStorage.setItem(import.meta.env.VITE_TOKEN_NAME, data?.data?.accessToken?.token)
|
||||||
|
localStorage.setItem(import.meta.env.VITE_REFRESH_TOKEN_NAME, data?.data?.refreshToken?.token)
|
||||||
|
window.location.href = Pages.dashboard
|
||||||
|
},
|
||||||
|
onError(error: ErrorType) {
|
||||||
|
toast.error(error?.response?.data?.error?.message[0])
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(formik.errors);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<div className='mt-5 rowTwoInput'>
|
||||||
|
<Input
|
||||||
|
label={t('auth.name')}
|
||||||
|
placeholder={t('auth.enter_name')}
|
||||||
|
name='firstName'
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
error_text={formik.touched.firstName && formik.errors.firstName ? formik.errors.firstName : ''}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label={t('auth.family')}
|
||||||
|
placeholder={t('auth.enter_family')}
|
||||||
|
name='lastName'
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
error_text={formik.touched.lastName && formik.errors.lastName ? formik.errors.lastName : ''}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className='mt-4 min-w-full rowTwoInput'>
|
||||||
|
<DatePickerComponent
|
||||||
|
label={t('auth.dateofbirth')}
|
||||||
|
onChange={(date: string) => formik.setFieldValue('birthDate', date)}
|
||||||
|
placeholder={t('auth.select_date')}
|
||||||
|
error_text={formik.touched.birthDate && formik.errors.birthDate ? formik.errors.birthDate : ''}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label={t('auth.national_code')}
|
||||||
|
placeholder={t('auth.national_code_enter')}
|
||||||
|
name='nationalCode'
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
error_text={formik.touched.nationalCode && formik.errors.nationalCode ? formik.errors.nationalCode : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-4 rowTwoInput'>
|
||||||
|
<Input
|
||||||
|
label={t('auth.password')}
|
||||||
|
placeholder={t('auth.enter_password')}
|
||||||
|
type='password'
|
||||||
|
name='password'
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
error_text={formik.touched.password && formik.errors.password ? formik.errors.password : ''}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
label={t('auth.phonen_number')}
|
||||||
|
placeholder={t('auth.enter_phone_number')}
|
||||||
|
readOnly
|
||||||
|
value={phone}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-4 rowTwoInput'>
|
||||||
|
<Input
|
||||||
|
label={t('auth.verify_code')}
|
||||||
|
placeholder={t('auth.enter_verify_code')}
|
||||||
|
type='tel'
|
||||||
|
name='code'
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
error_text={formik.touched.code && formik.errors.code ? formik.errors.code : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
label={t('auth.next')}
|
||||||
|
className='mt-8'
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
isLoading={register.isPending}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RegisterStep2
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMutation } from '@tanstack/react-query';
|
import { useMutation } from '@tanstack/react-query';
|
||||||
import * as api from '../service/AuthService'
|
import * as api from '../service/AuthService'
|
||||||
import { CheckHasAccountType, LoginWithOtpType, LoginWithPasswordType, OtpVerifyType } from '../types/AuthTypes';
|
import { CheckHasAccountPhoneType, CheckHasAccountType, LoginWithOtpType, LoginWithPasswordType, OtpVerifyType, RegisterType } from '../types/AuthTypes';
|
||||||
|
|
||||||
export const useLoginWithPassword = () => {
|
export const useLoginWithPassword = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
@@ -24,4 +24,16 @@ export const useCheckHasAccount = () => {
|
|||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: (variables: CheckHasAccountType) => api.checkHasAccount(variables),
|
mutationFn: (variables: CheckHasAccountType) => api.checkHasAccount(variables),
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCheckHasAccountRegister = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (variables: CheckHasAccountPhoneType) => api.checkHasAccountRegister(variables),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useRegister = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (variables: RegisterType) => api.register(variables),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
import axios from "../../../config/axios";
|
import axios from "../../../config/axios";
|
||||||
import {
|
import {
|
||||||
|
CheckHasAccountPhoneType,
|
||||||
CheckHasAccountType,
|
CheckHasAccountType,
|
||||||
LoginWithOtpType,
|
LoginWithOtpType,
|
||||||
LoginWithPasswordType,
|
LoginWithPasswordType,
|
||||||
OtpVerifyType,
|
OtpVerifyType,
|
||||||
|
RegisterType,
|
||||||
} from "../types/AuthTypes";
|
} from "../types/AuthTypes";
|
||||||
|
|
||||||
export const loginWithPassword = async (params: LoginWithPasswordType) => {
|
export const loginWithPassword = async (params: LoginWithPasswordType) => {
|
||||||
@@ -24,3 +26,14 @@ export const checkHasAccount = async (params: CheckHasAccountType) => {
|
|||||||
const { data } = await axios.post(`/auth/check`, params);
|
const { data } = await axios.post(`/auth/check`, params);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const checkHasAccountRegister = async (
|
||||||
|
params: CheckHasAccountPhoneType
|
||||||
|
) => {
|
||||||
|
const { data } = await axios.post(`/auth/register/initiate`, params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
export const register = async (params: RegisterType) => {
|
||||||
|
const { data } = await axios.post(`/auth/register/complete`, params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -35,3 +35,17 @@ export type OtpVerifyType = {
|
|||||||
export type CheckHasAccountType = {
|
export type CheckHasAccountType = {
|
||||||
email: string;
|
email: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CheckHasAccountPhoneType = {
|
||||||
|
phone: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RegisterType = {
|
||||||
|
phone: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
birthDate: string;
|
||||||
|
nationalCode: string;
|
||||||
|
password: string;
|
||||||
|
code: number;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user