// =========================== // LoginForm.tsx // ©AngelaMos | 2025 // =========================== import { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; import { isAxiosError } from 'axios'; import { Button } from '@/components/common/Button'; import { Input } from '@/components/common/Input'; import { useLogin } from '@/hooks/useAuth'; import { useUIStore } from '@/store/uiStore'; import { loginSchema } from '@/lib/validation'; import './AuthForm.css'; export const LoginForm = (): React.ReactElement => { const loginFormState = useUIStore((state) => state.loginForm); const setLoginFormField = useUIStore((state) => state.setLoginFormField); const clearLoginForm = useUIStore((state) => state.clearLoginForm); const clearExpiredData = useUIStore((state) => state.clearExpiredData); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [errors, setErrors] = useState<{ email?: string; password?: string }>( {}, ); const { mutate: login, isPending, error } = useLogin(); useEffect(() => { clearExpiredData(); setEmail(loginFormState.email); setPassword(loginFormState.password); }, [clearExpiredData, loginFormState.email, loginFormState.password]); const handleEmailChange = (value: string): void => { setEmail(value); setLoginFormField('email', value); if (errors.email !== null && errors.email !== undefined) { validateField('email', value); } }; const handlePasswordChange = (value: string): void => { setPassword(value); setLoginFormField('password', value); if (errors.password !== null && errors.password !== undefined) { validateField('password', value); } }; const validateField = (field: 'email' | 'password', value: string): void => { const result = loginSchema.safeParse({ email: field === 'email' ? value : email, password: field === 'password' ? value : password, }); if (!result.success) { const fieldError = result.error.issues.find((err) => err.path[0] === field); if (fieldError !== null && fieldError !== undefined) { setErrors((prev) => ({ ...prev, [field]: fieldError.message })); } else { setErrors((prev) => { const { [field]: _, ...rest } = prev; return rest; }); } } else { setErrors((prev) => { const { [field]: _, ...rest } = prev; return rest; }); } }; const handleBlur = (field: 'email' | 'password'): void => { const value = field === 'email' ? email : password; validateField(field, value); }; const validateForm = (): boolean => { const result = loginSchema.safeParse({ email, password, }); if (!result.success) { const newErrors: { email?: string; password?: string } = {}; result.error.issues.forEach((err) => { const field = err.path[0] as keyof typeof newErrors; if (field !== null && field !== undefined) { newErrors[field] = err.message; } }); setErrors(newErrors); return false; } setErrors({}); return true; }; const handleSubmit = (e: React.FormEvent): void => { e.preventDefault(); if (!validateForm()) { return; } login( { email, password }, { onSuccess: () => { clearLoginForm(); }, }, ); }; return (

Welcome Back

Sign in to your account

handleEmailChange(e.target.value)} onBlur={() => handleBlur('email')} error={errors.email} placeholder="you@example.com" autoComplete="email" required /> handlePasswordChange(e.target.value)} onBlur={() => handleBlur('password')} error={errors.password} placeholder="Enter your password" autoComplete="current-password" required />
{error !== null && error !== undefined && isAxiosError(error) ? (
{(error.response?.data as { detail?: string } | undefined)?.detail ?? 'Login failed. Please try again.'}
) : null}

Don't have an account?{' '} Sign up

); };