import React, { useState, useEffect, useRef } from "react"; import { View, ScrollView, Keyboard, Platform, KeyboardAvoidingView, TouchableWithoutFeedback, type ScrollView as ScrollViewType, } from "react-native"; import { Button } from "~/components/ui/button"; import { Input } from "~/components/ui/input"; import { Label } from "~/components/ui/label"; import { Text } from "~/components/ui/text"; import { router } from "expo-router"; import { usePhoneAuth, useAuthState } from "~/lib/hooks/useAuth"; import { ROUTES } from "~/lib/routes"; import BackButton from "~/components/ui/backButton"; import { AuthService } from "~/lib/services/authServices"; import { useGlobalLoading } from "~/lib/hooks/useGlobalLoading"; import ScreenWrapper from "~/components/ui/ScreenWrapper"; import ModalToast from "~/components/ui/toast"; import { useTranslation } from "react-i18next"; export default function OTP() { const [otpCode, setOtpCode] = useState(""); const [countdown, setCountdown] = useState(60); const [otpVerified, setOtpVerified] = useState(false); const { t } = useTranslation(); const { verifyOTP, sendOTP, loading, error } = usePhoneAuth(); const { user } = useAuthState(); const { showLoader, hideLoader, isGlobalLoading } = useGlobalLoading(); const loaderActiveRef = useRef(false); const scrollViewRef = useRef(null); const [toastVisible, setToastVisible] = useState(false); const [toastTitle, setToastTitle] = useState(""); const [toastDescription, setToastDescription] = useState( undefined ); const [toastVariant, setToastVariant] = useState< "success" | "error" | "warning" | "info" >("info"); const toastTimeoutRef = useRef | null>(null); const showToast = ( title: string, description?: string, variant: "success" | "error" | "warning" | "info" = "info" ) => { if (toastTimeoutRef.current) { clearTimeout(toastTimeoutRef.current); } setToastTitle(title); setToastDescription(description); setToastVariant(variant); setToastVisible(true); toastTimeoutRef.current = setTimeout(() => { setToastVisible(false); toastTimeoutRef.current = null; }, 2500); }; const handleVerifyOTP = async () => { Keyboard.dismiss(); if (!otpCode.trim() || otpCode.length !== 6) { showToast( t("otp.validationErrorTitle"), t("otp.validationInvalidCode"), "warning" ); return; } try { loaderActiveRef.current = true; showLoader(); await verifyOTP(otpCode); console.log("OTP VERIFIED successfully"); } catch (error) { if (loaderActiveRef.current) { hideLoader(); loaderActiveRef.current = false; } showToast(t("otp.toastErrorTitle"), t("otp.toastInvalidCode"), "error"); } }; const handleResendCode = async () => { Keyboard.dismiss(); // You'll need to store the phone number from the previous screen // For now, we'll show a message showToast(t("otp.toastInfoTitle"), t("otp.toastResendInfo"), "info"); }; // Countdown timer for resend button useEffect(() => { if (countdown > 0) { const timer = setTimeout(() => setCountdown(countdown - 1), 1000); return () => clearTimeout(timer); } }, [countdown]); // Scroll back when keyboard is dismissed useEffect(() => { const keyboardDidHide = Keyboard.addListener( Platform.OS === "ios" ? "keyboardWillHide" : "keyboardDidHide", () => { scrollViewRef.current?.scrollTo({ y: 0, animated: true }); } ); return () => { keyboardDidHide.remove(); }; }, []); // Show errors useEffect(() => { if (error) { showToast(t("otp.toastVerificationErrorTitle"), error, "error"); } }, [error]); // Handle navigation after OTP verification useEffect(() => { const checkProfileAndNavigate = async () => { if (user?.uid && !otpVerified) { console.log("User authenticated, checking profile existence"); setOtpVerified(true); // Set flag before navigation try { const profileExists = await AuthService.checkUserProfileExists( user.uid ); console.log("Profile exists:", profileExists); if (profileExists) { console.log("User profile exists, redirecting to home"); router.replace(ROUTES.HOME); } else { console.log( "User profile does not exist, redirecting to phone setup" ); router.replace(ROUTES.PHONE_SETUP); } } catch (error) { console.error("Error checking profile:", error); // Default to phone setup if there's an error router.replace(ROUTES.PHONE_SETUP); } finally { if (loaderActiveRef.current) { hideLoader(); loaderActiveRef.current = false; } } } }; checkProfileAndNavigate(); }, [user, otpVerified, hideLoader]); useEffect(() => { return () => { if (toastTimeoutRef.current) { clearTimeout(toastTimeoutRef.current); } }; }, []); // Note: We don't redirect authenticated users here since they need to complete setup return ( { showToast( t("otp.toastInfoTitle"), t("otp.toastBackInfo"), "info" ); router.back(); }} /> {t("otp.title")} {t("otp.description")} ); }