// LoginScreen + SetupScreen - layout B from the auth brainstorm spec: // 22px wordmark + "WILD DRAGON BROADCAST" tagline above a --bg-1 card. // Matches DESIGN.md tokens; no decoration, dense, ops register. (function () { const API_BASE = '/api/v1'; async function postJson(path, body) { return fetch(API_BASE + path, { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'dragonflight-ui', }, body: JSON.stringify(body), }); } function Brand() { return (
Dragonflight
Wild Dragon Broadcast
); } function Card({ children }) { return (
{children}
); } function Field({ label, type = 'text', value, onChange, autoComplete, autoFocus }) { return (
onChange(e.target.value)} style={{ width: '100%', background: 'var(--bg-3)', border: '1px solid var(--border)', borderRadius: 4, padding: '8px 10px', fontSize: 12.5, color: 'var(--text-1)', fontFamily: 'var(--font-mono)', boxSizing: 'border-box', }} />
); } function Button({ children, disabled, onClick, type = 'button' }) { return ( ); } function ErrorRow({ text }) { if (!text) return null; return (
{text}
); } function Screen({ children }) { return (
e.preventDefault()} style={{ width: 300 }}> {children}
); } function LoginScreen({ onDone }) { const [username, setUsername] = React.useState(''); const [password, setPassword] = React.useState(''); const [error, setError] = React.useState(''); const [busy, setBusy] = React.useState(false); const submit = async () => { setError(''); setBusy(true); try { const r = await postJson('/auth/login', { username, password }); if (r.status === 200) { onDone(); return; } const body = await r.json().catch(() => ({})); setError(body.error || ('Login failed: ' + r.status)); } catch (e) { setError(e.message || 'Login failed'); } finally { setBusy(false); } }; return ( ); } function SetupScreen({ onDone }) { const [username, setUsername] = React.useState(''); const [password, setPassword] = React.useState(''); const [confirm, setConfirm] = React.useState(''); const [error, setError] = React.useState(''); const [busy, setBusy] = React.useState(false); const submit = async () => { setError(''); if (password !== confirm) { setError('Passwords do not match'); return; } if (password.length < 12) { setError('Password must be at least 12 characters'); return; } setBusy(true); try { const r = await postJson('/auth/setup', { username, password }); if (r.status === 200) { onDone(); return; } const body = await r.json().catch(() => ({})); setError(body.error || ('Setup failed: ' + r.status)); } catch (e) { setError(e.message || 'Setup failed'); } finally { setBusy(false); } }; return (
First-run setup: create the first admin
); } window.LoginScreen = LoginScreen; window.SetupScreen = SetupScreen; })();