import { useState, useEffect, useCallback } from 'react'; import { Alert } from 'react-native'; import { useNavigation, useRoute, RouteProp } from '@react-navigation/native'; import { StackNavigationProp } from '@react-navigation/stack'; import { RootState, useAppDispatch, useAppSelector, verifyOtp } from '@store'; import { AuthStackParamList } from '@navigation/authStack'; type OtpNavProp = StackNavigationProp; type OtpRouteProp = RouteProp; const OTP_LENGTH = 6; const RESEND_TIMER = 30; export const useOtpScreen = () => { const navigation = useNavigation(); const route = useRoute(); const dispatch = useAppDispatch(); const { mobileNumber } = route.params; const { loginData, user } = useAppSelector((state: RootState) => state.auth); const [otp, setOtp] = useState(Array(OTP_LENGTH).fill('')); const [activeIndex, setActiveIndex] = useState(0); const [timer, setTimer] = useState(RESEND_TIMER); const [isLoading, setIsLoading] = useState(false); useEffect(() => { if (timer > 0) { const interval = setInterval(() => setTimer(t => t - 1), 1000); return () => clearInterval(interval); } }, [timer]); const resetOtp = useCallback(() => { setOtp(Array(OTP_LENGTH).fill('')); setActiveIndex(0); }, []); const handleKeyPress = useCallback( (key: string) => { if (key === 'backspace') { if (otp[activeIndex] || activeIndex > 0) { const newOtp = [...otp]; if (otp[activeIndex]) { newOtp[activeIndex] = ''; } else if (activeIndex > 0) { newOtp[activeIndex - 1] = ''; setActiveIndex(activeIndex - 1); } setOtp(newOtp); } } else if (key >= '0' && key <= '9' && activeIndex < OTP_LENGTH) { const newOtp = [...otp]; newOtp[activeIndex] = key; setOtp(newOtp); if (activeIndex < OTP_LENGTH - 1) { setActiveIndex(activeIndex + 1); } } }, [otp, activeIndex], ); const handleResend = useCallback(() => { setTimer(RESEND_TIMER); resetOtp(); // TODO: dispatch resend/loginWithPhone thunk here if needed }, [resetOtp]); const handleVerify = useCallback(async () => { const otpString = otp.join(''); if (otpString.length !== OTP_LENGTH) return; setIsLoading(true); try { await dispatch( verifyOtp({ phone: mobileNumber, code: otpString, role: 'CUSTOMER' }), ).unwrap(); navigation.navigate('SetLocationScreen'); } catch (error) { const message = typeof error === 'string' ? error : 'Invalid OTP. Please try again.'; Alert.alert('Verification Failed', message); resetOtp(); } finally { setIsLoading(false); } }, [dispatch, mobileNumber, navigation, otp, resetOtp]); return { // data mobileNumber, loginData, user, otp, activeIndex, timer, isLoading, otpLength: OTP_LENGTH, isOtpComplete: otp.join('').length === OTP_LENGTH, // actions handleKeyPress, handleVerify, handleResend, }; };