change login

This commit is contained in:
hamid zarghami
2025-11-16 11:19:40 +03:30
parent 3c14645fb5
commit 3592b4cdae
7 changed files with 61 additions and 61 deletions
+3
View File
@@ -23,6 +23,9 @@
"enter_info_login": "لطفا اطلاعات خود را وارد کنید.", "enter_info_login": "لطفا اطلاعات خود را وارد کنید.",
"mobile_or_email": " شماره موبایل یا ایمیل", "mobile_or_email": " شماره موبایل یا ایمیل",
"enter_mobile_or_email": " شماره موبایل یا ایمیل خود را وارد کنید", "enter_mobile_or_email": " شماره موبایل یا ایمیل خود را وارد کنید",
"mobile": "شماره موبایل",
"enter_mobile": "شماره موبایل خود را وارد کنید",
"otp_sent": "کد تایید ارسال شد",
"have_account": "آیا حساب کاربری ندارید؟", "have_account": "آیا حساب کاربری ندارید؟",
"register": "ثبت نام", "register": "ثبت نام",
"enter_otp": "کد تایید را وارد کنید", "enter_otp": "کد تایید را وارد کنید",
+1 -6
View File
@@ -4,11 +4,10 @@ import LogoSmallImage from '../../assets/images/logo-small.svg'
import { useAuthStore } from './store/AuthStore' import { useAuthStore } from './store/AuthStore'
import LoginStep1 from './components/LoginStep1' import LoginStep1 from './components/LoginStep1'
import LoginStep2 from './components/LoginStep2' import LoginStep2 from './components/LoginStep2'
import LoginStep3 from './components/LoginStep3'
const Login: FC = () => { const Login: FC = () => {
const { stepLogin, phone, email } = useAuthStore() const { stepLogin, phone } = useAuthStore()
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'>
@@ -24,10 +23,6 @@ const Login: FC = () => {
: :
stepLogin === 2 && !!phone ? stepLogin === 2 && !!phone ?
<LoginStep2 /> <LoginStep2 />
: stepLogin === 2 && !!email ?
<LoginStep3 />
: stepLogin === 3 ?
<LoginStep3 />
: null : null
} }
</div> </div>
+20 -29
View File
@@ -1,46 +1,38 @@
import { type FC } from 'react' import { type FC } from 'react'
import Input from '../../../components/Input' import Input from '../../../components/Input'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { type LoginType } from '../types/AuthTypes'
import { useFormik } from 'formik' import { useFormik } from 'formik'
import * as Yup from 'yup' import * as Yup from 'yup'
import { useAuthStore } from '../store/AuthStore' import { useAuthStore } from '../store/AuthStore'
import Error from '../../../components/Error' import Error from '../../../components/Error'
import Button from '../../../components/Button' import Button from '../../../components/Button'
import { isEmail } from '../../../config/func' import { useLoginWithOtp } from '../hooks/useAuthData'
import { useCheckHasAccount, useLoginWithOtp } from '../hooks/useAuthData'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { type ErrorType } from '../../../helpers/types' import { type ErrorType } from '../../../helpers/types'
import { useParams } from 'react-router-dom'
type LoginStep1FormType = {
phone: string;
}
const LoginStep1: FC = () => { const LoginStep1: FC = () => {
const { t } = useTranslation('global') const { t } = useTranslation('global')
const { setPhone, phone, setStepLogin, setEmail } = useAuthStore() const { setPhone, phone, setStepLogin } = useAuthStore()
const loginWithOtp = useLoginWithOtp() const loginWithOtp = useLoginWithOtp()
const checkHasAccount = useCheckHasAccount() const { slug } = useParams()
const formik = useFormik<LoginType>({ const formik = useFormik<LoginStep1FormType>({
initialValues: { initialValues: {
phone_email: phone, phone: phone,
}, },
validationSchema: Yup.object({ validationSchema: Yup.object({
phone_email: Yup.string() phone: Yup.string()
.required(t('errors.required')) .required(t('errors.required'))
}), }),
onSubmit(values) { onSubmit(values) {
if (isEmail(values.phone_email)) { setPhone(values.phone)
setEmail(values.phone_email) loginWithOtp.mutate({ phone: values.phone, slug: slug as string }, {
checkHasAccount.mutate({ email: values.phone_email }, {
onSuccess() {
setStepLogin(2)
},
onError(error: ErrorType) {
toast.error(error?.response?.data?.error?.message[0])
},
})
} else {
setPhone(values.phone_email)
loginWithOtp.mutate({ phone: values.phone_email }, {
onSuccess() { onSuccess() {
setStepLogin(2) setStepLogin(2)
toast.success(t('auth.otp_sent')) toast.success(t('auth.otp_sent'))
@@ -49,7 +41,6 @@ const LoginStep1: FC = () => {
toast.error(error?.response?.data?.error?.message[0]) toast.error(error?.response?.data?.error?.message[0])
}, },
}) })
}
}, },
}) })
@@ -66,19 +57,19 @@ const LoginStep1: FC = () => {
<div className='mt-16'> <div className='mt-16'>
<Input <Input
label={t('auth.mobile_or_email')} label={t('auth.mobile')}
placeholder={t('auth.enter_mobile_or_email')} placeholder={t('auth.enter_mobile')}
type='text' type='text'
className='text-right' className='text-right'
name='phone_email' name='phone'
onChange={formik.handleChange} onChange={formik.handleChange}
value={formik.values.phone_email} value={formik.values.phone}
/> />
{ {
formik.touched.phone_email && formik.errors.phone_email && formik.touched.phone && formik.errors.phone &&
<Error <Error
errorText={formik.errors.phone_email} errorText={formik.errors.phone}
/> />
} }
@@ -89,7 +80,7 @@ const LoginStep1: FC = () => {
label={t('auth.next')} label={t('auth.next')}
className='mt-8' className='mt-8'
onClick={() => formik.handleSubmit()} onClick={() => formik.handleSubmit()}
isLoading={loginWithOtp.isPending || checkHasAccount.isPending} isLoading={loginWithOtp.isPending}
/> />
</div> </div>
+22 -13
View File
@@ -7,12 +7,12 @@ import { useAuthStore } from '../store/AuthStore'
import Button from '../../../components/Button' import Button from '../../../components/Button'
import OTPInput from 'react-otp-input' import OTPInput from 'react-otp-input'
import { useCountDown } from '../../../hooks/useCountDown' import { useCountDown } from '../../../hooks/useCountDown'
// import ArrowLeftIcon from '../../../assets/images/arrow-left.svg'
import { Pages } from '../../../config/Pages' import { Pages } from '../../../config/Pages'
import { useOtpVerify } from '../hooks/useAuthData' import { useOtpVerify } from '../hooks/useAuthData'
import { type ErrorType } from '../../../helpers/types' import { type ErrorType } from '../../../helpers/types'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { setToken, setRefreshToken } from '../../../config/func' import { setToken, setRefreshToken } from '../../../config/func'
import { useParams } from 'react-router-dom'
const LoginStep2: FC = () => { const LoginStep2: FC = () => {
@@ -20,25 +20,26 @@ const LoginStep2: FC = () => {
const { phone, setStepLogin } = useAuthStore() const { phone, setStepLogin } = useAuthStore()
const { value } = useCountDown(2, true) const { value } = useCountDown(2, true)
const otpVerify = useOtpVerify() const otpVerify = useOtpVerify()
const { slug } = useParams()
const formik = useFormik<OtpVerifyType>({ const formik = useFormik<{ otp: string }>({
initialValues: { initialValues: {
phone: phone, otp: ''
code: ''
}, },
validationSchema: Yup.object({ validationSchema: Yup.object({
code: Yup.string() otp: Yup.string()
.required(t('errors.required')) .required(t('errors.required'))
}), }),
onSubmit(values) { onSubmit(values) {
const params: OtpVerifyType = { const params: OtpVerifyType = {
phone: phone, phone: phone,
code: values.code otp: values.otp,
slug: slug as string
} }
otpVerify.mutate(params, { otpVerify.mutate(params, {
onSuccess(data) { onSuccess(data) {
setToken(data?.data?.accessToken?.token) setToken(data?.data?.tokens?.accessToken?.token)
setRefreshToken(data?.data?.refreshToken?.token) setRefreshToken(data?.data?.tokens?.refreshToken?.token)
window.location.href = Pages.dashboard window.location.href = Pages.dashboard
}, },
onError(error: ErrorType) { onError(error: ErrorType) {
@@ -75,17 +76,25 @@ const LoginStep2: FC = () => {
<div className='mt-2 w-full flex justify-center dltr otp'> <div className='mt-2 w-full flex justify-center dltr otp'>
<OTPInput <OTPInput
shouldAutoFocus shouldAutoFocus
value={formik.values.code} value={formik.values.otp}
numInputs={5} numInputs={5}
inputType='tel' inputType='tel'
onChange={(otp: string) => formik.setFieldValue('code', otp)} containerStyle={{ direction: 'ltr', width: '100%' }}
renderInput={(props) => <input {...props} className='w-full h-[50px] flex-1 mx-2 bg-white border rounded-2.5' />} onChange={(otp: string) => formik.setFieldValue('otp', otp)}
renderInput={(props) =>
<input
{...props}
type='tel'
autoComplete="one-time-code"
inputMode="numeric"
className='w-full min-w-[50px] h-[45px] sm:h-[50px] flex-1 mx-1 sm:mx-2 bg-white border border-gray-300 outline-0 rounded-[10px] text-center text-sm' />
}
/> />
</div> </div>
{ {
formik.touched.code && formik.errors.code && formik.touched.otp && formik.errors.otp &&
<div className='text-xs mt-2 text-red-500'>{formik.errors.code}</div> <div className='text-xs mt-2 text-red-500'>{formik.errors.otp}</div>
} }
<div className='flex mt-4 justify-end'> <div className='flex mt-4 justify-end'>
+2 -2
View File
@@ -15,12 +15,12 @@ export const loginWithPassword = async (params: LoginWithPasswordType) => {
}; };
export const loginWithOtp = async (params: LoginWithOtpType) => { export const loginWithOtp = async (params: LoginWithOtpType) => {
const { data } = await axios.post(`/auth/otp/send`, params); const { data } = await axios.post(`/admin/auth/otp/request`, params);
return data; return data;
}; };
export const otpVerify = async (params: OtpVerifyType) => { export const otpVerify = async (params: OtpVerifyType) => {
const { data } = await axios.post(`/auth/otp/verify/admin`, params); const { data } = await axios.post(`/admin/auth/otp/verify`, params);
return data; return data;
}; };
export const checkHasAccount = async (params: CheckHasAccountType) => { export const checkHasAccount = async (params: CheckHasAccountType) => {
+3 -1
View File
@@ -25,11 +25,13 @@ export type LoginWithPasswordType = XOR<
export type LoginWithOtpType = { export type LoginWithOtpType = {
phone: string; phone: string;
slug: string;
}; };
export type OtpVerifyType = { export type OtpVerifyType = {
phone: string; phone: string;
code: string; otp: string;
slug: string;
}; };
export type CheckHasAccountType = { export type CheckHasAccountType = {
+1 -1
View File
@@ -6,7 +6,7 @@ import Login from '../pages/auth/Login'
const Auth: FC = () => { const Auth: FC = () => {
return ( return (
<Routes>sa <Routes>sa
<Route path={Pages.auth.login} element={<Login />} /> <Route path={Pages.auth.login + '/:slug'} element={<Login />} />
</Routes> </Routes>
) )
} }