import { useState, useEffect, type FormEvent, type FC } from 'react'; import { useNavigate } from 'react-router-dom'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { getSetupStatus, performSetup, SetupRequest } from '../api/setup'; import client from '../api/client'; import { useAuth } from '../hooks/useAuth'; import { Input } from '../components/ui/Input'; import { Button } from '../components/ui/Button'; import { PasswordStrengthMeter } from '../components/PasswordStrengthMeter'; import { isValidEmail } from '../utils/validation'; const Setup: FC = () => { const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); const { login, isAuthenticated } = useAuth(); const [formData, setFormData] = useState({ name: '', email: '', password: '', }); const [error, setError] = useState(null); const [emailValid, setEmailValid] = useState(null); const { data: status, isLoading: statusLoading } = useQuery({ queryKey: ['setupStatus'], queryFn: getSetupStatus, retry: false, }); useEffect(() => { if (formData.email) { setEmailValid(isValidEmail(formData.email)); } else { setEmailValid(null); } }, [formData.email]); useEffect(() => { // Wait for setup status to load if (statusLoading) return; // If setup is required, stay on this page (ignore stale auth) if (status?.setupRequired) { return; } // If setup is NOT required, redirect based on auth if (isAuthenticated) { navigate('/'); } else { navigate('/login'); } }, [status, statusLoading, isAuthenticated, navigate]); const mutation = useMutation({ mutationFn: async (data: SetupRequest) => { // 1. Perform Setup await performSetup(data); // 2. Auto Login await client.post('/auth/login', { email: data.email, password: data.password }); // 3. Update Auth Context await login(); }, onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: ['setupStatus'] }); navigate('/'); }, onError: (err: Error) => { setError(err.message || t('setup.setupFailed')); }, }); const handleSubmit = (e: FormEvent) => { e.preventDefault(); setError(null); mutation.mutate(formData); }; if (statusLoading) { return (
{t('common.loading')}
); } if (status && !status.setupRequired) { return null; // Will redirect in useEffect } return (
Charon

{t('setup.welcomeTitle')}

{t('setup.welcomeDescription')}

setFormData({ ...formData, name: e.target.value })} />
setFormData({ ...formData, email: e.target.value })} className={emailValid === false ? 'border-red-500 focus:ring-red-500' : emailValid === true ? 'border-green-500 focus:ring-green-500' : ''} autoComplete="email" /> {emailValid === false && (

{t('setup.invalidEmail')}

)}
setFormData({ ...formData, password: e.target.value })} autoComplete="new-password" />
{error && (
{error}
)}
); }; export default Setup;