import React, { useState, useEffect, useRef, useCallback } from "react"; import { useAuth } from "../contexts/AuthContext"; import PasswordStrengthMeter from "./PasswordStrengthMeter"; import PasswordInput from "./PasswordInput"; import ForgotPasswordModal from "./ForgotPasswordModal"; import VerificationCodeModal from "./VerificationCodeModal"; interface AuthModalProps { show: boolean; onHide: () => void; initialMode?: "login" | "signup"; } const AuthModal: React.FC = ({ show, onHide, initialMode = "login", }) => { const [mode, setMode] = useState<"login" | "signup">(initialMode); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [firstName, setFirstName] = useState(""); const [lastName, setLastName] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(""); const [showForgotPassword, setShowForgotPassword] = useState(false); const [showVerificationModal, setShowVerificationModal] = useState(false); const { login, register } = useAuth(); const modalRef = useRef(null); // Update mode when modal is opened with different initialMode useEffect(() => { if (show && initialMode) { setMode(initialMode); } }, [show, initialMode]); // Focus trapping for accessibility const handleKeyDown = useCallback((e: KeyboardEvent) => { if (e.key !== "Tab" || !modalRef.current) return; const focusableElements = modalRef.current.querySelectorAll( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ); const focusableArray = Array.from(focusableElements).filter( (el) => !el.hasAttribute("disabled") && el.offsetParent !== null ); if (focusableArray.length === 0) return; const firstElement = focusableArray[0]; const lastElement = focusableArray[focusableArray.length - 1]; if (e.shiftKey) { // Shift + Tab: if on first element, go to last if (document.activeElement === firstElement) { e.preventDefault(); lastElement.focus(); } } else { // Tab: if on last element, go to first if (document.activeElement === lastElement) { e.preventDefault(); firstElement.focus(); } } }, []); // Set up focus trap and initial focus when modal is shown useEffect(() => { if (show && !showForgotPassword && !showVerificationModal) { document.addEventListener("keydown", handleKeyDown); // Focus the first input element when modal opens if (modalRef.current) { const firstInput = modalRef.current.querySelector('input'); firstInput?.focus(); } return () => { document.removeEventListener("keydown", handleKeyDown); }; } }, [show, showForgotPassword, showVerificationModal, handleKeyDown]); const resetModal = () => { setError(""); setEmail(""); setPassword(""); setFirstName(""); setLastName(""); setShowVerificationModal(false); }; const handleGoogleLogin = () => { const clientId = process.env.REACT_APP_GOOGLE_CLIENT_ID; const redirectUri = `${window.location.origin}/auth/google/callback`; const scope = 'openid email profile'; const responseType = 'code'; const googleAuthUrl = `https://accounts.google.com/o/oauth2/v2/auth?` + `client_id=${encodeURIComponent(clientId || '')}` + `&redirect_uri=${encodeURIComponent(redirectUri)}` + `&response_type=${responseType}` + `&scope=${encodeURIComponent(scope)}` + `&access_type=offline` + `&prompt=consent`; window.location.href = googleAuthUrl; }; const handleEmailSubmit = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); setError(""); try { if (mode === "login") { await login(email, password); onHide(); } else { const response = await register({ email, password, firstName, lastName, username: email.split("@")[0], // Generate username from email }); // Show verification modal after successful registration setShowVerificationModal(true); // Don't call onHide() - keep modal context for verification } } catch (err: any) { setError(err.response?.data?.error || "An error occurred"); } finally { setLoading(false); } }; if (!show && !showForgotPassword && !showVerificationModal) return null; return ( <> {/* Verification Code Modal - shown after signup */} {showVerificationModal && ( { setShowVerificationModal(false); resetModal(); onHide(); }} email={email} onVerified={() => { setShowVerificationModal(false); resetModal(); onHide(); }} /> )} {!showForgotPassword && !showVerificationModal && (

Welcome to Village Share

{error && (
{error}
)} {/* Email Form */}
{mode === "signup" && ( <>
setFirstName(e.target.value)} required />
setLastName(e.target.value)} required />
)}
setEmail(e.target.value)} required />
setPassword(e.target.value)} required /> {mode === "signup" && (
)} {mode === "login" && ( )}

or
{/* Social Login Options */}

By continuing, you agree to Village Share's{" "} Terms of Service {" "} and{" "} Privacy Policy .

)} {/* Forgot Password Modal */} setShowForgotPassword(false)} onBackToLogin={() => setShowForgotPassword(false)} /> ); }; export default AuthModal;