// register.jsx — Everest new account registration function RegisterForm({ onLogin, onBack }) { const [step, setStep] = React.useState("register"); // "register" | "totp" const [name, setName] = React.useState(""); const [email, setEmail] = React.useState(""); const [password, setPassword] = React.useState(""); const [error, setError] = React.useState(null); const [totpData, setTotpData] = React.useState(null); // {token, totp_secret, totp_qr} const [code, setCode] = React.useState(""); const [loading, setLoading] = React.useState(false); async function handleRegister(e) { e.preventDefault(); setError(null); setLoading(true); try { const res = await fetch("/api/v1/auth/register", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name, email, password }), }); const data = await res.json(); if (!res.ok) throw new Error(data.detail || "Registration failed"); setTotpData(data); setStep("totp"); } catch (err) { setError(err.message); } finally { setLoading(false); } } async function handleTotp(e) { e.preventDefault(); setError(null); setLoading(true); try { const res = await fetch("/api/v1/auth/verify-totp", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ token: totpData.token, code }), }); const data = await res.json(); if (!res.ok) throw new Error(data.detail || "Invalid code"); onLogin(); } catch (err) { setError(err.message); } finally { setLoading(false); } } if (step === "totp") { return (
Set up authenticator
Scan this QR code with your authenticator app
{totpData?.totp_qr && ({totpData.totp_secret}
Create account
Mission Control — new expedition member
Already have an account?{" "}