import { useState, useEffect } from 'react'; import { Sparkles, ArrowLeft } from 'lucide-react'; import { api, setAuthToken, needsPasswordReset } from '@/lib/api'; type Stage = 'invite' | 'register' | 'login' | 'reset-password'; export function InviteGateScreen({ onRegistered }: { onRegistered: () => void }) { const [stage, setStage] = useState('invite'); const [inviteCode, setInviteCode] = useState(''); const [email, setEmail] = useState(''); const [loginField, setLoginField] = useState(''); const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [newPassword, setNewPassword] = useState(''); const [confirmNewPassword, setConfirmNewPassword] = useState(''); const [error, setError] = useState(''); const [loading, setLoading] = useState(false); useEffect(() => { const params = new URLSearchParams(window.location.search); const code = params.get('invite'); if (code) { setInviteCode(code); handleValidateCode(code); } }, []); async function handleValidateCode(code?: string) { const codeToValidate = code || inviteCode.trim(); if (!codeToValidate) { setError('Please enter an invite code'); return; } setLoading(true); setError(''); try { const result = await api.invites.validate(codeToValidate); if (result.valid) { setInviteCode(codeToValidate); setStage('register'); } else { setError('Invalid or already used invite code'); } } catch { setError('Could not validate invite code'); } finally { setLoading(false); } } async function handleRegister() { if (!email.trim()) { setError('Email is required'); return; } if (password.length < 8) { setError('Password must be at least 8 characters'); return; } if (password !== confirmPassword) { setError('Passwords do not match'); return; } setLoading(true); setError(''); try { const result = await api.auth.register(email.trim(), password, inviteCode); setAuthToken(result.token); onRegistered(); } catch (e) { setError(e instanceof Error ? e.message : 'Registration failed'); } finally { setLoading(false); } } async function handleLogin() { if (!loginField.trim() || !password) { setError('Email/username and password required'); return; } setLoading(true); setError(''); try { const result = await api.auth.login(loginField.trim(), password); setAuthToken(result.token); if (needsPasswordReset()) { setStage('reset-password'); } else { onRegistered(); } } catch (e) { setError(e instanceof Error ? e.message : 'Login failed'); } finally { setLoading(false); } } async function handlePasswordReset() { if (newPassword.length < 8) { setError('Password must be at least 8 characters'); return; } if (newPassword !== confirmNewPassword) { setError('Passwords do not match'); return; } setLoading(true); setError(''); try { const result = await api.auth.changePassword(newPassword); setAuthToken(result.token); onRegistered(); } catch (e) { setError(e instanceof Error ? e.message : 'Password change failed'); } finally { setLoading(false); } } return (

AI Tycoon

{stage === 'reset-password' ? 'Please set a new password to continue.' : 'Access is invite-only during early access.'}

{stage === 'invite' && ( <>
setInviteCode(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleValidateCode()} placeholder="Enter your invite code" className="w-full bg-surface-800 border border-surface-600 rounded-lg px-4 py-3 text-surface-100 placeholder:text-surface-500 focus:outline-none focus:ring-2 focus:ring-accent/50 focus:border-accent font-mono tracking-wider text-center text-lg" autoFocus maxLength={8} />
{error &&

{error}

}
)} {stage === 'register' && ( <>
Invite: {inviteCode}
setEmail(e.target.value)} placeholder="you@example.com" className="w-full bg-surface-800 border border-surface-600 rounded-lg px-4 py-2.5 text-surface-100 placeholder:text-surface-500 focus:outline-none focus:ring-2 focus:ring-accent/50 focus:border-accent" autoFocus />
setPassword(e.target.value)} placeholder="Min 8 characters" className="w-full bg-surface-800 border border-surface-600 rounded-lg px-4 py-2.5 text-surface-100 placeholder:text-surface-500 focus:outline-none focus:ring-2 focus:ring-accent/50 focus:border-accent" />
setConfirmPassword(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleRegister()} placeholder="Confirm your password" className="w-full bg-surface-800 border border-surface-600 rounded-lg px-4 py-2.5 text-surface-100 placeholder:text-surface-500 focus:outline-none focus:ring-2 focus:ring-accent/50 focus:border-accent" />
{error &&

{error}

} )} {stage === 'login' && ( <>
setLoginField(e.target.value)} placeholder="admin" className="w-full bg-surface-800 border border-surface-600 rounded-lg px-4 py-2.5 text-surface-100 placeholder:text-surface-500 focus:outline-none focus:ring-2 focus:ring-accent/50 focus:border-accent" autoFocus />
setPassword(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleLogin()} placeholder="Your password" className="w-full bg-surface-800 border border-surface-600 rounded-lg px-4 py-2.5 text-surface-100 placeholder:text-surface-500 focus:outline-none focus:ring-2 focus:ring-accent/50 focus:border-accent" />
{error &&

{error}

} )} {stage === 'reset-password' && ( <>
You must set a new password before continuing.
setNewPassword(e.target.value)} placeholder="Min 8 characters" className="w-full bg-surface-800 border border-surface-600 rounded-lg px-4 py-2.5 text-surface-100 placeholder:text-surface-500 focus:outline-none focus:ring-2 focus:ring-accent/50 focus:border-accent" autoFocus />
setConfirmNewPassword(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handlePasswordReset()} placeholder="Confirm your new password" className="w-full bg-surface-800 border border-surface-600 rounded-lg px-4 py-2.5 text-surface-100 placeholder:text-surface-500 focus:outline-none focus:ring-2 focus:ring-accent/50 focus:border-accent" />
{error &&

{error}

} )}

Manage data centers, train models, serve millions of users, and achieve AGI.

); }