import { useEffect, useState, type ReactNode } from 'react' import { useQuery, useQueryClient } from '@tanstack/react-query' import { apiFetch, setToken, UNAUTHORIZED_EVENT } from '@/lib/api' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { useI18n } from '@/i18n' interface AuthStatus { needsSetup: boolean authenticated: boolean email: string | null } function Centered({ children }: { children: ReactNode }) { return (
{children}
) } function AuthForm({ mode, onAuthed }: { mode: 'setup' | 'login'; onAuthed: () => void }) { const { t } = useI18n() const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [error, setError] = useState('') const [busy, setBusy] = useState(false) const isSetup = mode === 'setup' async function submit(e: React.FormEvent) { e.preventDefault() setBusy(true) setError('') try { const res = await apiFetch<{ token: string }>(isSetup ? '/api/auth/setup' : '/api/auth/login', { method: 'POST', body: JSON.stringify({ email, password }), }) setToken(res.token) onAuthed() } catch (err) { setError((err as Error).message) } finally { setBusy(false) } } return (
FreeLLMAPI

{isSetup ? t('auth.createYourAccount') : t('auth.signIn')}

{isSetup ? t('auth.setupDescription') : t('auth.loginDescription')}

setEmail(e.target.value)} placeholder={t('auth.emailPlaceholder')} />
setPassword(e.target.value)} placeholder={isSetup ? t('auth.passwordPlaceholderSetup') : t('auth.passwordPlaceholderLogin')} />
{error &&

{error}

}
) } export function AuthGate({ children }: { children: ReactNode }) { const { t } = useI18n() const queryClient = useQueryClient() const { data, isLoading, isError, refetch } = useQuery({ queryKey: ['auth-status'], queryFn: () => apiFetch('/api/auth/status'), retry: false, }) useEffect(() => { const handler = () => { refetch() } window.addEventListener(UNAUTHORIZED_EVENT, handler) return () => window.removeEventListener(UNAUTHORIZED_EVENT, handler) }, [refetch]) function onAuthed() { // New session: drop any cached (unauthenticated) data and re-check status. queryClient.invalidateQueries() refetch() } if (isLoading) return

{t('auth.loading')}

if (isError || !data) { return (
{t('auth.serverUnreachableBefore')}npm run dev{t('auth.serverUnreachableAfter')}
) } if (data.needsSetup) return if (!data.authenticated) return return <>{children} }