'use client' import React, { useState, type FormEvent, type ChangeEvent, useEffect, useTransition } from 'react' import { useAuthStore } from '@/zustand/authStore' import { redirect, useRouter } from 'next/navigation' import StepEnterNumber from '@/features/auth/components/StepEnterNumber' import StepEnterOtp from '@/features/auth/components/StepEnterOtp' import { AUTH_PAGE_ELEMENT, AUTH_STEP } from '@/enums' import { useCountdown } from '@/hooks/useCountdown' import StepNewPassword from '@/features/auth/components/StepNewPassword' import AuthFormWrapper from '@/features/auth/components/AuthFormWrapper' import { useCheckUserExistsLazy } from '@/hooks/auth/useCheckUserExists' import { useOtpRequest } from '@/hooks/auth/useOtpRequest' import { useOtpValidation } from '@/hooks/auth/useOtpValidation' import { useResetPassword } from '@/hooks/auth/useResetPassword' import { useAuthTempStore } from '@/zustand/authTempStroe' type Props = object function AuthIndex ({}: Props) { const update_temp_store = useAuthTempStore(state => state.update) const user_temp_store = useAuthTempStore(state => state.user) const user_auth_store = useAuthStore(state => state.user) const isAuthenticated = useAuthStore(state => state.isAuthenticated) const [number, setNumber] = useState( user_temp_store?.number ?? user_auth_store?.number ?? '' ) const [password, setPassword] = useState('') const [passwordRepeat, setPasswordRepeat] = useState('') const [otp, setOtp] = useState('') const [showPassword, setShowPassword] = useState(false) const [showPasswordRepeat, setShowPasswordRepeat] = useState(false) const [step, setStep] = useState( number == '' ? AUTH_STEP.ENTER_NUMBER : AUTH_STEP.ENTER_OTP ) const { timerRunning, secondsLeft, restart, stop } = useCountdown( step === AUTH_STEP.ENTER_OTP ) const [isPending, startTransition] = useTransition() const { run: runUserExistCheck } = useCheckUserExistsLazy() const { run: runOtpRequest } = useOtpRequest() // eslint-disable-next-line @typescript-eslint/no-unused-vars const { run: runOtpValidation } = useOtpValidation() const { run: runResetPassword } = useResetPassword() const router = useRouter() useEffect(() => { if (isAuthenticated) { redirect('/') } }, [isAuthenticated]) useEffect(() => { if (step === AUTH_STEP.ENTER_OTP) { startTransition(() => { setOtp('') console.log('REQUEST OTP') runOtpRequest(number) }) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [step]) const onChange = (e: ChangeEvent) => { if (e.target.name == AUTH_PAGE_ELEMENT.INPUT_PHONE) { setNumber(() => e.target.value) } else if (e.target.name == AUTH_PAGE_ELEMENT.INPUT_PASSWORD) { setPassword(() => e.target.value) } else if (e.target.name == AUTH_PAGE_ELEMENT.INPUT_PASSWORD_REPEAT) { setPasswordRepeat(() => e.target.value) } else if (e.target.name.startsWith(AUTH_PAGE_ELEMENT.INPUT_OTP)) { const index = +e.target.name.split('-')[2] const prev = otp.padEnd(6).split('') prev[index] = e.target.value const next = prev.join('') if (otp.length >= 6 && next.trim().length >= otp.length) return setOtp(next.trimEnd()) } } const onClick = async ( e: | React.MouseEvent | React.MouseEvent ) => { e.stopPropagation() const target = e.target as HTMLButtonElement if (target.id === AUTH_PAGE_ELEMENT.TOGGLE_PASSWORD) { setShowPassword(state => !state) } if (target.id === AUTH_PAGE_ELEMENT.TOGGLE_REPEAT_PASSWORD) { setShowPasswordRepeat(state => !state) } else if (target.id === AUTH_PAGE_ELEMENT.RESET_PASSWORD) { setShowPassword(false) setShowPasswordRepeat(false) setPassword('') setPasswordRepeat('') setStep(() => AUTH_STEP.ENTER_OTP) } else if (target.id === AUTH_PAGE_ELEMENT.RESEND_OTP) { if (!timerRunning) { startTransition(async () => { try { await runOtpRequest(number) restart() } catch { console.error('Could not ask for otp') } }) } } } const onSubmit = async (e: FormEvent) => { e.preventDefault() startTransition(async () => { try { /* DEV SECTION */ /* REMOVE THIS CODE FOR PRODUCTION */ throw false /* END OF DEV SECTION */ /* SECTION DETAILS */ /* if number is entered in the /auth page or is available in main auth store this page directly shows the OTP page */ /* Otherwise it shows the number page */ if (step == AUTH_STEP.ENTER_NUMBER) { const userExists = await runUserExistCheck(number) update_temp_store({ number: number, mustLogin: userExists }) if (userExists) { setStep(AUTH_STEP.ENTER_RESET_PASSWORD) } else { // TODO: error user not found } } else if (step == AUTH_STEP.ENTER_OTP) { // if (!await runOtpValidation({ phone: number, otp })) { // setOtp(''); // console.error('Wrong otp'); // } stop() console.log(await runUserExistCheck(number)) if (await runUserExistCheck(number)) { setStep(AUTH_STEP.ENTER_RESET_PASSWORD) } else { // TODO: error user not found } } else if ( step == AUTH_STEP.ENTER_CREATE_PASSWORD || step == AUTH_STEP.ENTER_CURRENT_PASSWORD ) { setStep(AUTH_STEP.ENTER_RESET_PASSWORD) } else if (step == AUTH_STEP.ENTER_RESET_PASSWORD) { update_temp_store({ password, repeatPassword: passwordRepeat }) try { await runResetPassword({ phone: number, newPassword: password, otp: otp }) console.log('Password changed') redirect('/') } catch (e) { console.error('Could not reset password: ', e) } } } catch (ex) { console.error(ex) // TODO: Add toast errors /* DEV SECTION */ /* REMOVE THIS CODE FOR PRODUCTION */ if (step == AUTH_STEP.ENTER_NUMBER) { update_temp_store({ number }) setStep(AUTH_STEP.ENTER_OTP) } else if (step === AUTH_STEP.ENTER_OTP) { setStep(AUTH_STEP.ENTER_RESET_PASSWORD) } else if ( step == AUTH_STEP.ENTER_CREATE_PASSWORD || step == AUTH_STEP.ENTER_CURRENT_PASSWORD ) { setStep(AUTH_STEP.ENTER_RESET_PASSWORD) } else if (step == AUTH_STEP.ENTER_RESET_PASSWORD) { update_temp_store({ password, repeatPassword: passwordRepeat }) try { console.log('Password changed') router.replace('/auth') } catch (e) { console.error('Could not reset password: ', e) } } /* END OF DEV SECTION */ } }) } return ( {step === AUTH_STEP.ENTER_NUMBER && ( )} {step === AUTH_STEP.ENTER_OTP && ( )} {step === AUTH_STEP.ENTER_RESET_PASSWORD && ( )} ) } export default AuthIndex