import { useEffect, useRef, useState } from 'react' import { useLocation, useNavigate } from 'react-router-dom' import { requestOtp, verifyOtp } from '../services/authApi' import { fetchMyCafes } from '../services/campaignApi' import { storeAuthTokens } from '../utils/authToken' import { setCafeUuid } from '../utils/cafe' import { toEnglishDigits, toPersianDigits } from '../utils/formatNumber' import { toE164 } from '../utils/phone' import { getUserRole } from '../utils/role' const OTP_LENGTH = 5 const DEFAULT_RESEND_SECONDS = 120 function EditIcon({ className = '' }: { className?: string }) { return ( ) } function formatCountdown(seconds: number) { const mm = String(Math.floor(seconds / 60)).padStart(2, '0') const ss = String(seconds % 60).padStart(2, '0') return toPersianDigits(`${mm}:${ss}`) } export default function LoginOtp() { const navigate = useNavigate() const location = useLocation() const state = location.state as { phone?: string; ttl?: number } | null const phone = state?.phone ?? '' const loginPath = getUserRole() === 'cafe_owner' ? '/cafe/login' : '/login' const [otp, setOtp] = useState(Array(OTP_LENGTH).fill('')) const [secondsLeft, setSecondsLeft] = useState(Math.round(state?.ttl ?? DEFAULT_RESEND_SECONDS)) const [resendCycle, setResendCycle] = useState(0) const [error, setError] = useState('') const [isSubmitting, setIsSubmitting] = useState(false) const [isResending, setIsResending] = useState(false) const inputRefs = useRef<(HTMLInputElement | null)[]>([]) useEffect(() => { if (!phone) { navigate(loginPath, { replace: true }) } }, [phone, loginPath, navigate]) useEffect(() => { const timer = setInterval(() => { setSecondsLeft((s) => { if (s <= 1) { clearInterval(timer) return 0 } return s - 1 }) }, 1000) return () => clearInterval(timer) }, [resendCycle]) const handleOtpChange = (index: number, rawValue: string) => { const digit = toEnglishDigits(rawValue).replace(/[^0-9]/g, '').slice(-1) setOtp((prev) => { const next = [...prev] next[index] = digit return next }) setError('') if (digit && index < OTP_LENGTH - 1) { inputRefs.current[index + 1]?.focus() } } const handleOtpKeyDown = (index: number, e: React.KeyboardEvent) => { if (e.key === 'Backspace' && !otp[index] && index > 0) { inputRefs.current[index - 1]?.focus() } } const handleResend = async () => { setError('') setIsResending(true) try { const { ttl } = await requestOtp(toE164(phone)) setOtp(Array(OTP_LENGTH).fill('')) inputRefs.current[0]?.focus() setSecondsLeft(Math.round(ttl)) setResendCycle((c) => c + 1) } catch { setError('ارسال مجدد کد با خطا مواجه شد. لطفاً دوباره تلاش کنید.') } finally { setIsResending(false) } } const canSubmit = otp.every((digit) => digit !== '') && !isSubmitting const handleSubmit = async () => { setError('') setIsSubmitting(true) try { const tokens = await verifyOtp(toE164(phone), otp.join('')) storeAuthTokens(tokens.access_token, tokens.refresh_token) const role = getUserRole() if (role === 'cafe_owner') { const myCafes = await fetchMyCafes().catch(() => []) if (myCafes.length > 0) { setCafeUuid(myCafes[0].uuid) navigate('/owner/panel') } else { navigate('/owner/register') } } else { navigate('/') } } catch { setError('کد وارد شده صحیح نیست') } finally { setIsSubmitting(false) } } return (

کد ارسال شده را وارد کنید:

{phone}
{otp.map((digit, index) => ( { inputRefs.current[index] = el }} type="text" inputMode="numeric" maxLength={1} value={digit} onChange={(e) => handleOtpChange(index, e.target.value)} onKeyDown={(e) => handleOtpKeyDown(index, e)} className="h-14 w-14 rounded-lg border border-gray-200 bg-[#F8F8F8] text-center text-xl font-semibold text-gray-900 focus:border-[#223D5D] focus:outline-none" /> ))}
{secondsLeft > 0 ? (

ارسال مجدد کد: {formatCountdown(secondsLeft)}

) : ( )}
{error &&

{error}

}
) }