"use client"; import { Suspense, useEffect, useState } from "react"; import Link from "next/link"; import { useSearchParams, useRouter } from "next/navigation"; import AuthShell from "@/components/AuthShell"; import { api } from "@/lib/api"; function Inner() { const sp = useSearchParams(); const r = useRouter(); const token = sp.get("token"); const email = sp.get("email") ?? ""; const [code, setCode] = useState(""); const [err, setErr] = useState(""); const [msg, setMsg] = useState(""); const [busy, setBusy] = useState(false); const [linkState, setLinkState] = useState<"idle" | "ok" | "err">("idle"); // If arriving via the email link, verify by token automatically. useEffect(() => { if (token) { api(`/auth/verify-email?token=${token}`) .then(() => { setLinkState("ok"); setTimeout(() => r.push("/onboarding"), 1200); }) .catch(() => setLinkState("err")); } }, [token, r]); async function submit(e: React.FormEvent) { e.preventDefault(); setErr(""); setBusy(true); try { await api("/auth/verify-code", { method: "POST", body: JSON.stringify({ email, code }) }); r.push("/onboarding"); } catch (e: any) { setErr(typeof e.detail === "string" ? e.detail : "Verification failed"); } finally { setBusy(false); } } async function resend() { setMsg(""); setErr(""); await api("/auth/resend-code", { method: "POST", body: JSON.stringify({ email }) }).catch(() => {}); setMsg("A new code has been sent."); } // Token-link flow display if (token) { return ( {linkState === "ok" &&

✓ Verified. Redirecting…

} {linkState === "err" &&

This link is invalid or expired. Enter your code below instead.

} {linkState === "idle" &&

Verifying…

} Back to login
); } return (
{err &&

{err}

} {msg &&

{msg}

}
Back to login

In local dev (MOCK_EMAIL), the code is printed in the backend console.

); } export default function VerifyEmail() { return ; }