import React, { useState, useEffect } from 'react'; import { useLocation, useNavigate, useParams } from 'react-router-dom'; import { useAuth } from '../contexts/AuthContext'; import { Button } from '../components/UiKit'; type AuthStep = 'email' | 'otp' | 'password-fallback'; const ModernLogin: React.FC = () => { const navigate = useNavigate(); const location = useLocation(); const { inviteCode: routeInviteCode } = useParams<{ inviteCode: string }>(); // Auth state const { signInWithGoogle, signInWithEmail, signUpWithEmail, user, loading, sendOTP: authSendOTP, verifyOTP: authVerifyOTP } = useAuth(); // Form state const [step, setStep] = useState('email'); const [email, setEmail] = useState(''); const [otp, setOtp] = useState(''); const [password, setPassword] = useState(''); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(''); const [inviteCode, setInviteCode] = useState(null); const [resendCooldown, setResendCooldown] = useState(0); const [demoOTP, setDemoOTP] = useState(null); // Extract invite code from URL useEffect(() => { if (routeInviteCode) { setInviteCode(routeInviteCode); } else { const hashSearch = location.hash.includes('?') ? location.hash.split('?')[1] : ''; const searchParams = new URLSearchParams(hashSearch); const queryInvite = searchParams.get('invite'); if (queryInvite) { setInviteCode(queryInvite); } } }, [routeInviteCode, location]); // Handle successful authentication useEffect(() => { if (user && !loading) { if (inviteCode) { navigate(`/org-selection?invite=${inviteCode}`, { replace: true }); } else { navigate('/org-selection', { replace: true }); } } }, [user, loading, navigate, inviteCode]); // Resend cooldown timer useEffect(() => { if (resendCooldown > 0) { const timer = setTimeout(() => setResendCooldown(resendCooldown - 1), 1000); return () => clearTimeout(timer); } }, [resendCooldown]); const sendOTP = async (emailAddress: string) => { try { setIsLoading(true); setError(''); setDemoOTP(null); // Call auth context method const response = await authSendOTP(emailAddress, inviteCode || undefined); // If OTP is returned in response (demo mode), display it if (response.otp) { setDemoOTP(response.otp); } setStep('otp'); setResendCooldown(60); // 60 second cooldown } catch (err) { console.error('OTP send error:', err); setError(err instanceof Error ? err.message : 'Failed to send verification code. Please try again.'); } finally { setIsLoading(false); } }; const verifyOTP = async () => { try { setIsLoading(true); setError(''); // Call auth context method await authVerifyOTP(email, otp, inviteCode || undefined); // Success - user will be set in auth context and useEffect will handle navigation } catch (err) { console.error('OTP verification error:', err); setError(err instanceof Error ? err.message : 'Invalid verification code. Please try again.'); } finally { setIsLoading(false); } }; const handleEmailSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!email.trim()) return; await sendOTP(email); }; const handleOTPSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!otp.trim()) return; await verifyOTP(); }; const handlePasswordFallback = async (e: React.FormEvent) => { e.preventDefault(); if (!password.trim()) return; try { setIsLoading(true); setError(''); // Try login first, then signup if user doesn't exist try { await signInWithEmail(email, password); } catch (loginError) { // If login fails, try creating account await signUpWithEmail(email, password, email.split('@')[0]); } } catch (err) { console.error('Password auth error:', err); setError(err instanceof Error ? err.message : 'Authentication failed'); } finally { setIsLoading(false); } }; const handleGoogleAuth = async () => { try { setIsLoading(true); setError(''); await signInWithGoogle(); } catch (err) { console.error('Google auth error:', err); setError('Google authentication failed. Please try again.'); } finally { setIsLoading(false); } }; const renderEmailStep = () => (
A

{inviteCode ? 'Join Organization' : 'Welcome to Auditly'}

{inviteCode ? 'Enter your email to join the organization' : 'Enter your email to get started' }

setEmail(e.target.value)} placeholder="Enter your email" className="w-full pl-12 pr-4 py-3.5 bg-gray-50 border text-gray-700 border-gray-200 rounded-full focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-all" required />
{error && (
{error}
)}
or
); const renderOTPStep = () => (

Check your email

We sent a verification code to
{email}

setOtp(e.target.value.replace(/\D/g, '').slice(0, 6))} placeholder="000000" className="w-full px-4 py-4 bg-gray-50 border border-gray-200 text-gray-700 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent text-center text-3xl tracking-[0.5em] font-mono outline-none transition-all" maxLength={6} required />
{demoOTP && (
Demo Mode
Your verification code is {demoOTP}
)} {error && (
{error}
)}
); const renderPasswordStep = () => (

Sign in with password

Enter your password for
{email}

setPassword(e.target.value)} placeholder="Enter your password" className="w-full px-4 py-3.5 bg-gray-50 border border-gray-200 rounded-full focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-all" required />
{error && (
{error}
)}
); if (loading) { return (
); } return (
{step === 'email' && renderEmailStep()} {step === 'otp' && renderOTPStep()} {step === 'password-fallback' && renderPasswordStep()}
); }; export default ModernLogin;