This commit is contained in:
hamid zarghami
2025-08-25 09:19:13 +03:30
parent 418b45fde5
commit 6e1ebdf023
20 changed files with 736 additions and 10 deletions
+132
View File
@@ -0,0 +1,132 @@
import { FC, useEffect } from 'react'
import { useAuthentication, useVerifyOtp } from '../hooks/useAuthData'
import { Button } from '@/components/ui/button'
import OTPInput from 'react-otp-input'
import { useForm } from 'react-hook-form'
import { VerifyOtpType } from '../types/Types'
import * as yup from "yup"
import { yupResolver } from "@hookform/resolvers/yup"
import { useAuthStore } from '../store/AuthStore'
import { toast } from '@/components/Toast'
import { extractErrorMessage } from '@/helpers/errorUtils'
import Error from '@/components/Error'
import { setRefreshToken, setToken } from '@/config/func'
import { useCountDown } from '@/hooks/useCountDown'
const LoginStep2: FC = () => {
const { phone } = useAuthStore()
const { isPending, mutate: verifyOtp } = useVerifyOtp()
const { mutate: authentication, isPending: isAuthenticationPending } = useAuthentication();
const { value: countdownValue, reset: resetCountdown } = useCountDown(2, true, () => {
// When countdown ends, enable resend button
})
const validationSchema = yup
.object({
otpCode: yup.string().required('کد را وارد کنید'),
phone: yup.string().required('شماره تلفن خود را وارد کنید'),
})
.required()
const {
handleSubmit,
watch,
setValue,
formState: { errors },
} = useForm<VerifyOtpType>({
resolver: yupResolver(validationSchema),
defaultValues: {
phone: phone,
},
})
const onSubmit = (data: VerifyOtpType) => {
verifyOtp(data, {
onSuccess: (data) => {
toast('ورود با موفقیت انجام شد', 'success')
setToken(data?.results?.data?.accessToken?.token)
setRefreshToken(data?.results?.data?.refreshToken?.token)
window.location.href = '/'
},
onError: (error: Error) => {
toast(extractErrorMessage(error), 'error')
}
})
}
const handleResendOtp = () => {
authentication({
phone: phone,
}, {
onSuccess: () => {
resetCountdown()
toast('کد جدید ارسال شد', 'success')
}
})
}
useEffect(() => {
if (watch('otpCode')?.length === 5) {
onSubmit({
otpCode: watch('otpCode'),
phone: phone,
})
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [watch('otpCode')])
return (
<div className='flex-1 flex flex-col justify-center'>
<div className='text-[#CCCCCC] text-2xl font-black'>کد دریافتی را وارد نمایید</div>
<div className='mt-8 dltr otp'>
<OTPInput
shouldAutoFocus
value={watch("otpCode")}
numInputs={5}
inputType='tel'
containerStyle={{ direction: 'ltr' }}
onChange={(otp: string) => setValue('otpCode', otp)}
renderInput={(props) =>
<input
{...props}
type='tel'
autoComplete="one-time-code"
inputMode="numeric"
className='w-full h-[50px] flex-1 mx-2 bg-white border rounded-[10px]' />
}
/>
</div>
{
errors.otpCode?.message && <Error errorText={errors.otpCode.message} />
}
<div className='mt-8'>
<Button isLoading={isPending} className='w-full h-11' onClick={handleSubmit(onSubmit)}>تایید</Button>
</div>
{/* Countdown and Resend Section */}
<div className='mt-6'>
<div className='flex items-center justify-between'>
<span className='text-[#CCCCCC] text-sm'>کد فعالسازی را دریافت نکردید؟</span>
{countdownValue !== '00:00' ? (
<span className='text-blue-500 font-medium text-sm'>{countdownValue}</span>
) : (
<Button
variant={'ghost'}
isLoading={isAuthenticationPending}
onClick={handleResendOtp}
className='text-blue-500 hover:text-blue-600 cursor-pointer text-sm font-medium transition-colors'
>
دوباره امتحان کنید
</Button>
)}
</div>
</div>
</div>
)
}
export default LoginStep2