'use client'; import { useState, useEffect, useRef } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; import api from '@/lib/api'; export default function VerifyOtpPage() { const router = useRouter(); const searchParams = useSearchParams(); const email = searchParams.get('email') || ''; const [otp, setOtp] = useState(['', '', '', '', '', '']); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [canResend, setCanResend] = useState(false); const [countdown, setCountdown] = useState(60); const inputRefs = useRef<(HTMLInputElement | null)[]>([]); // Countdown timer for resend useEffect(() => { if (countdown > 0) { const timer = setTimeout(() => setCountdown(countdown - 1), 1000); return () => clearTimeout(timer); } else { setCanResend(true); } }, [countdown]); // Focus first input on mount useEffect(() => { inputRefs.current[0]?.focus(); }, []); const handleChange = (index: number, value: string) => { // Only allow digits if (!/^\d*$/.test(value)) return; const newOtp = [...otp]; newOtp[index] = value.slice(-1); // Take only the last digit setOtp(newOtp); // Auto-focus next input if (value && index < 5) { inputRefs.current[index + 1]?.focus(); } // Auto-submit when all 6 digits are entered if (index === 5 && value && newOtp.every(digit => digit !== '')) { handleVerify(newOtp.join('')); } }; const handleKeyDown = (index: number, e: React.KeyboardEvent) => { // Handle backspace if (e.key === 'Backspace' && !otp[index] && index > 0) { inputRefs.current[index - 1]?.focus(); } }; const handlePaste = (e: React.ClipboardEvent) => { e.preventDefault(); const pastedData = e.clipboardData.getData('text').replace(/\D/g, '').slice(0, 6); if (pastedData.length === 6) { const newOtp = pastedData.split(''); setOtp(newOtp); inputRefs.current[5]?.focus(); handleVerify(pastedData); } }; const handleVerify = async (code?: string) => { setError(null); const otpCode = code || otp.join(''); if (otpCode.length !== 6) { setError('Please enter the complete 6-digit code'); return; } setIsLoading(true); try { const result = await api.verifyOTP(email, otpCode); if (result.ok && result.data) { // Save auth token localStorage.setItem('accessToken', result.data.accessToken); localStorage.setItem('userId', result.data.userId.toString()); // Get user profile to determine next screen const profileResult = await api.getMe(); if (profileResult.ok && profileResult.data) { const user = profileResult.data.user; const beneficiaries = profileResult.data.beneficiaries || []; // Navigation logic (similar to NavigationController) if (!user.firstName) { router.replace('/enter-name'); } else if (beneficiaries.length === 0) { router.replace('/add-loved-one'); } else { router.replace('/dashboard'); } } else { router.replace('/dashboard'); } } else { setError(result.error?.message || 'Invalid verification code'); setOtp(['', '', '', '', '', '']); inputRefs.current[0]?.focus(); } } catch { setError('Network error. Please try again.'); setOtp(['', '', '', '', '', '']); inputRefs.current[0]?.focus(); } finally { setIsLoading(false); } }; const handleResend = async () => { setError(null); setCanResend(false); setCountdown(60); try { const result = await api.requestOTP(email); if (!result.ok) { setError('Failed to resend code. Please try again.'); setCanResend(true); } } catch { setError('Network error. Please try again.'); setCanResend(true); } }; return (
{/* Header */}

Check your email

We sent a verification code to

{email}

{/* OTP Form */}
{/* OTP Inputs */}
{otp.map((digit, index) => ( { inputRefs.current[index] = el; }} type="text" inputMode="numeric" maxLength={1} value={digit} onChange={(e) => handleChange(index, e.target.value)} onKeyDown={(e) => handleKeyDown(index, e)} disabled={isLoading} className="w-12 h-12 text-center text-2xl font-bold border-2 border-gray-300 rounded-lg focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500 focus:outline-none disabled:bg-gray-100 disabled:cursor-not-allowed transition-colors" /> ))}
{/* Error Message */} {error && (

{error}

)} {/* Verify Button */}
{/* Resend Code */}
{canResend ? ( ) : (

Resend code in {countdown}s

)}
{/* Back to Login */}
); }