fix: seperated auth pages

This commit is contained in:
Mahyar Khanbolooki
2025-08-21 20:24:31 +03:30
parent 3cb48023b6
commit ef91469766
7 changed files with 787 additions and 195 deletions
+251
View File
@@ -0,0 +1,251 @@
'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<HTMLInputElement>) => {
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<HTMLButtonElement, MouseEvent>
| React.MouseEvent<HTMLInputElement, 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<HTMLFormElement>) => {
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 (
<AuthFormWrapper isPending={isPending} onSubmit={onSubmit}>
{step === AUTH_STEP.ENTER_NUMBER && (
<StepEnterNumber
pending={isPending}
onChange={onChange}
value={number}
/>
)}
{step === AUTH_STEP.ENTER_OTP && (
<StepEnterOtp
pending={isPending}
onChange={onChange}
onClick={onClick}
phoneNumber={number}
value={otp}
timerRunning={timerRunning}
secondsLeft={secondsLeft}
/>
)}
{step === AUTH_STEP.ENTER_RESET_PASSWORD && (
<StepNewPassword
isReset
pending={isPending}
onChange={onChange}
onClick={onClick}
value={password}
repeatValue={passwordRepeat}
passwordVisible={showPassword}
repeatPasswordVisible={showPasswordRepeat}
/>
)}
</AuthFormWrapper>
)
}
export default AuthIndex