import React, { useState, useRef, useEffect } from "react"; import { View, Text, StyleSheet, TouchableOpacity, TextInput, Modal, ActivityIndicator, Platform, Keyboard, TouchableWithoutFeedback, } from "react-native"; import { useTranslation } from "react-i18next"; import { ResetPasswordModal } from "./ResetPasswordModal"; type VerificationCodeInputProps = { visible: boolean; onClose: () => void; phoneNumber?: string; onVerify: (code: string) => Promise; onResend: () => Promise; onResetPassword?: (password: string) => Promise; }; export const VerificationCodeInput = ({ visible, onClose, phoneNumber = "", onVerify, onResend, onResetPassword = async () => true, }: VerificationCodeInputProps) => { const { t } = useTranslation(); // Single string to store the entire verification code const [verificationCode, setVerificationCode] = useState(""); const [isCodeError, setIsCodeError] = useState(false); const [loading, setLoading] = useState(false); const [countdown, setCountdown] = useState(60); const [isResending, setIsResending] = useState(false); const [resendActive, setResendActive] = useState(false); // New state for password reset modal const [showPasswordReset, setShowPasswordReset] = useState(false); // Reference to the hidden input that will handle all keystrokes const hiddenInputRef = useRef(null); // Focus the hidden input whenever the component is visible useEffect(() => { if (visible) { startCountdown(); setTimeout(() => { hiddenInputRef.current?.focus(); }, 300); } return () => { // Reset states when component unmounts setVerificationCode(""); setIsCodeError(false); setCountdown(60); setResendActive(false); setShowPasswordReset(false); }; }, [visible]); // Function to focus the hidden input const focusInput = () => { hiddenInputRef.current?.focus(); }; // Function to start countdown const startCountdown = () => { setResendActive(false); setCountdown(60); const timer = setInterval(() => { setCountdown((prevCount) => { if (prevCount <= 1) { clearInterval(timer); setResendActive(true); return 0; } return prevCount - 1; }); }, 1000); return () => clearInterval(timer); }; // Handle code input change const handleCodeChange = (text: string) => { if (isCodeError) setIsCodeError(false); // Only accept digits and limit to 6 characters const cleanedText = text.replace(/[^0-9]/g, '').substring(0, 6); setVerificationCode(cleanedText); // Auto-submit if all 6 digits are entered if (cleanedText.length === 6) { Keyboard.dismiss(); handleVerifyCode(cleanedText); } }; // Handle verify code submission const handleVerifyCode = async (code: string) => { setLoading(true); try { const success = await onVerify(code); if (!success) { setIsCodeError(true); } else { // Instead of closing, show password reset modal setShowPasswordReset(true); } } catch (error) { setIsCodeError(true); } finally { setLoading(false); } }; // Handle resend code const handleResend = async () => { if (!resendActive) return; setIsResending(true); try { await onResend(); startCountdown(); } catch (error) { console.error("Failed to resend code:", error); } finally { setIsResending(false); } }; // Handle password reset submission const handlePasswordReset = async (password: string) => { try { const success = await onResetPassword(password); if (success) { // Password reset was successful // The parent component already handles closing all modals setShowPasswordReset(false); // Note: Don't call onClose() here as the parent already does that } return success; } catch (error) { console.error("Failed to reset password:", error); return false; } }; // Create an array representation of the code for display const codeArray = verificationCode.split(''); while (codeArray.length < 6) { codeArray.push(''); } return ( {t("login.verification.title")} {t("login.verification.description")} {phoneNumber}. {t("login.verification.expiration")} {/* Hidden input that captures all key presses */} {/* Touchable area to focus input when touched */} {codeArray.map((digit, index) => ( {digit} ))} {/* Error message */} {isCodeError && ( ! {t("login.verification.incorrect")} )} {/* Resend button */} {isResending ? ( ) : ( {resendActive ? t("login.verification.resend") : `${t("login.verification.resend")} (${countdown}s)`} )} {/* Help section */} {t("login.verification.didntReceive")} {t("login.verification.helpPoint1")} {t("login.verification.helpPoint2")} {/* Password Reset Modal */} setShowPasswordReset(false)} onSubmit={handlePasswordReset} /> ); }; const styles = StyleSheet.create({ modalContainer: { flex: 1, backgroundColor: "rgba(0,0,0,0.5)", justifyContent: "flex-end", zIndex: 9999, }, verificationContainer: { backgroundColor: "#fff", borderTopLeftRadius: 20, borderTopRightRadius: 20, height: "80%", shadowColor: "#000", shadowOffset: { width: 0, height: -2 }, shadowOpacity: 0.1, shadowRadius: 5, elevation: 5, }, verificationHeader: { flexDirection: "row", alignItems: "center", paddingTop: 20, paddingHorizontal: 16, paddingBottom: 15, borderBottomWidth: 1, borderBottomColor: "#f0f0f0", }, closeButton: { padding: 8, width: 36, height: 36, justifyContent: "center", alignItems: "center", }, closeButtonText: { fontSize: 18, color: "#000", }, headerTitle: { flex: 1, fontSize: 18, fontWeight: "600", color: "#000", textAlign: "center", marginRight: 36, }, verificationContent: { padding: 20, paddingBottom: Platform.OS === "ios" ? 50 : 30, }, description: { fontSize: 14, color: "#333", marginBottom: 20, lineHeight: 20, }, hiddenInput: { position: 'absolute', opacity: 0, height: 0, width: 0, }, codeInputContainer: { flexDirection: "row", justifyContent: "space-between", marginBottom: 20, width: "100%", }, codeInput: { width: '14%', height: 60, borderWidth: 1, borderColor: "#E1E1E1", borderRadius: 5, justifyContent: 'center', alignItems: 'center', }, codeInputText: { fontSize: 24, fontWeight: "500", }, codeInputError: { borderColor: "#FF3B30", }, codeInputFilled: { borderColor: "#0066FF", }, errorContainer: { flexDirection: "row", alignItems: "center", marginBottom: 15, }, errorIconContainer: { width: 20, height: 20, borderRadius: 10, backgroundColor: "#FF3B30", justifyContent: "center", alignItems: "center", marginRight: 8, }, errorIcon: { color: "white", fontSize: 14, fontWeight: "bold", }, errorText: { color: "#FF3B30", fontSize: 14, }, resendContainer: { alignItems: "flex-end", marginBottom: 30, }, resendButton: { padding: 5, }, resendButtonDisabled: { opacity: 0.7, }, resendText: { color: "#0066FF", fontSize: 14, fontWeight: "500", }, resendTextDisabled: { color: "#999", }, helpContainer: { backgroundColor: "#F8F8F8", padding: 15, borderRadius: 10, marginTop: 20, }, helpTitle: { fontSize: 16, fontWeight: "600", marginBottom: 10, color: "#333", }, helpItem: { flexDirection: "row", alignItems: "center", marginBottom: 8, }, bulletPoint: { width: 8, height: 8, borderRadius: 4, backgroundColor: "#FF9500", marginRight: 10, }, helpText: { fontSize: 14, color: "#333", flex: 1, }, });