// login.jsx — two-step auth: password then TOTP const { useState: useStateL, useCallback: useCallbackL } = React; function LoginScreen({ onLogin, onRegister }) { const [step, setStep] = useStateL("password"); // password | setup | totp const [email, setEmail] = useStateL("getpat@gmail.com"); const [password, setPassword] = useStateL(""); const [code, setCode] = useStateL(""); const [token, setToken] = useStateL(""); const [setupInfo, setSetupInfo] = useStateL(null); const [error, setError] = useStateL(""); const [loading, setLoading] = useStateL(false); const submitPassword = useCallbackL(async (e) => { e.preventDefault(); setError(""); setLoading(true); try { const r = await fetch("/api/v1/auth/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password }), }); const data = await r.json(); if (!r.ok) { setError(data.detail || "Login failed"); return; } setToken(data.token); if (data.step === "setup") { setSetupInfo({ secret: data.totp_secret, uri: data.totp_uri, qr: data.totp_qr }); setStep("setup"); } else { setStep("totp"); } } catch { setError("Network error"); } finally { setLoading(false); } }, [email, password]); const submitTotp = useCallbackL(async (e) => { e.preventDefault(); setError(""); setLoading(true); try { const r = await fetch("/api/v1/auth/verify-totp", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ token, code }), }); const data = await r.json(); if (!r.ok) { setError(data.detail || "Invalid code"); return; } onLogin(); } catch { setError("Network error"); } finally { setLoading(false); } }, [token, code, onLogin]); return (
Everest
{step === "password" && (

Mission Control

setEmail(e.target.value)} autoFocus required /> setPassword(e.target.value)} required /> {error &&

{error}

}
)} {step === "setup" && setupInfo && (

Set up authenticator

Scan this QR code with Google Authenticator, Authy, or any TOTP app.

{setupInfo.qr ? TOTP QR code :

QR unavailable — use the secret key below.

}
Secret key (manual entry) {setupInfo.secret}
Show otpauth URI {setupInfo.uri}
setCode(e.target.value.replace(/\D/g, ""))} autoFocus required /> {error &&

{error}

}
)} {step === "totp" && (

Two-factor verification

Enter the 6-digit code from your authenticator app.

setCode(e.target.value.replace(/\D/g, ""))} autoFocus required /> {error &&

{error}

}
)} {step === "password" && onRegister && (

New here?{" "}

)}
); } const LS = { overlay: { position: "fixed", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", background: "#0f1117", zIndex: 9999 }, card: { background: "#1a1d27", border: "1px solid rgba(255,255,255,0.08)", borderRadius: "12px", padding: "2.5rem 2rem", width: "100%", maxWidth: "380px", boxShadow: "0 24px 64px rgba(0,0,0,0.5)" }, logo: { display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: "1.5rem" }, logoMark: { fontSize: "1.4rem", color: "#C9512B" }, logoText: { fontSize: "1.2rem", fontWeight: 600, color: "#e8e6e3", letterSpacing: "0.02em" }, subtitle: { margin: "0 0 1.25rem", fontSize: "0.85rem", color: "#888", textTransform: "uppercase", letterSpacing: "0.08em" }, hint: { fontSize: "0.82rem", color: "#888", lineHeight: 1.5, margin: "0 0 1rem" }, label: { display: "block", fontSize: "0.78rem", color: "#888", marginBottom: "0.3rem", textTransform: "uppercase", letterSpacing: "0.06em" }, input: { display: "block", width: "100%", boxSizing: "border-box", padding: "0.6rem 0.75rem", marginBottom: "1rem", background: "#0f1117", color: "#e8e6e3", border: "1px solid rgba(255,255,255,0.12)", borderRadius: "6px", fontSize: "0.95rem", outline: "none" }, btn: { display: "block", width: "100%", padding: "0.65rem", background: "#C9512B", color: "#fff", border: "none", borderRadius: "6px", fontSize: "0.9rem", fontWeight: 600, cursor: "pointer", marginTop: "0.5rem" }, linkBtn: { display: "block", width: "100%", padding: "0.5rem", background: "transparent", color: "#888", border: "none", fontSize: "0.82rem", cursor: "pointer", marginTop: "0.5rem" }, error: { color: "#e05c5c", fontSize: "0.82rem", margin: "0 0 0.75rem" }, secretBox: { background: "#0f1117", border: "1px solid rgba(255,255,255,0.1)", borderRadius: "6px", padding: "0.75rem", marginBottom: "0.75rem" }, secretLabel: { display: "block", fontSize: "0.72rem", color: "#888", textTransform: "uppercase", letterSpacing: "0.06em", marginBottom: "0.3rem" }, secret: { fontSize: "0.85rem", color: "#e8e6e3", wordBreak: "break-all", letterSpacing: "0.1em" }, summary: { fontSize: "0.78rem", color: "#888", cursor: "pointer" }, uriText: { display: "block", fontSize: "0.7rem", color: "#888", wordBreak: "break-all", marginTop: "0.4rem" }, };