132 lines
4.8 KiB
TypeScript
132 lines
4.8 KiB
TypeScript
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 |