import React, { useState, useEffect, useRef } from "react"; import { View, ScrollView, TextInput, ActivityIndicator, KeyboardAvoidingView, Platform, Pressable, } from "react-native"; import { useSirouRouter } from "@sirou/react-native"; import { AppRoutes } from "@/lib/routes"; import { Text } from "@/components/ui/text"; import { Button } from "@/components/ui/button"; import { useLocalSearchParams, Stack } from "expo-router"; import { ScreenWrapper } from "@/components/ScreenWrapper"; import { StandardHeader } from "@/components/StandardHeader"; import { api } from "@/lib/api"; import { useAuthStore } from "@/lib/auth-store"; import { toast } from "@/lib/toast-store"; import { useColorScheme } from "nativewind"; export default function OtpScreen() { const nav = useSirouRouter(); const { phone, verificationId } = useLocalSearchParams<{ phone: string; verificationId: string; }>(); const setAuth = useAuthStore((state) => state.setAuth); const { colorScheme } = useColorScheme(); const isDark = colorScheme === "dark"; const [code, setCode] = useState(["", "", "", "", "", ""]); const [loading, setLoading] = useState(false); const [timer, setTimer] = useState(30); const inputs = useRef([]); useEffect(() => { let interval: any; if (timer > 0) { interval = setInterval(() => { setTimer((t) => t - 1); }, 1000); } return () => clearInterval(interval); }, [timer]); const handleInputChange = (text: string, index: number) => { const newCode = [...code]; newCode[index] = text; setCode(newCode); // Auto-focus next input if (text && index < 5) { inputs.current[index + 1]?.focus(); } }; const handleKeyDown = (e: any, index: number) => { if (e.nativeEvent.key === "Backspace" && !code[index] && index > 0) { inputs.current[index - 1]?.focus(); } }; const handleVerify = async () => { const fullCode = code.join(""); if (fullCode.length < 6) { toast.error("Invalid Code", "Please enter the full 6-digit code"); return; } setLoading(true); try { const response = await api.auth.verifyOtp({ body: { phone: phone as string, code: fullCode, verificationId: verificationId as string, }, }); const permissions: string[] = []; setAuth( response.user, response.accessToken, response.refreshToken, permissions, ); toast.success("Welcome!", "Login successful."); nav.go("(tabs)"); } catch (err: any) { toast.error( "Verification Failed", err.message || "Invalid or expired code", ); } finally { setLoading(false); } }; const handleResend = async () => { setLoading(true); try { await api.auth.sendOtp({ body: { phone: phone as string } }); toast.success("OTP Sent", "A new verification code has been sent."); setTimer(30); } catch (err: any) { toast.error("Error", "Failed to resend code"); } finally { setLoading(false); } }; return ( Verify your number Enter the 6-digit code we sent to{"\n"} {phone} {code.map((digit, i) => ( (inputs.current[i] = el)} value={digit} onChangeText={(text) => handleInputChange(text, i)} onKeyPress={(e) => handleKeyDown(e, i)} keyboardType="number-pad" maxLength={1} className="w-10 h-10 border top-[2px] border-border rounded-[6px] text-center text-lg flex items-center justify-center font-bold bg-card text-foreground" placeholderTextColor={isDark ? "#475569" : "#cbd5e1"} /> ))} {timer > 0 ? ( Resend code in{" "} {timer}s ) : ( Resend Verification Code )} ); }