"use client"; /** * AddEmailModal — centred portal dialog with a single email input for * users who signed up via OAuth and never shared an address. Mirrors * the ChangePasswordModal pattern so the look and feel matches. * * On success: closes itself and updates the auth-provider's user so the * rest of the app immediately sees the new email. The BFF stores the * address as unverified and fires a verification link to it; the user * sees that as the existing "verify your email" banner on the next * render. * * Entry points: * • VerifyEmailBanner — top-of-page "Add an email" button * • /settings → Authentication → Add your email row */ import { useEffect, useState } from "react"; import { createPortal } from "react-dom"; import { X } from "lucide-react"; import { useAuth } from "@/components/auth/auth-provider"; import { auth, AuthError } from "@/lib/auth"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; export function AddEmailModal({ open, onClose, }: { open: boolean; onClose: () => void; }) { const { setUser } = useAuth(); const [email, setEmail] = useState(""); const [error, setError] = useState(null); const [submitting, setSubmitting] = useState(false); // Blank slate every time the modal opens. useEffect(() => { if (open) return; setEmail(""); setError(null); setSubmitting(false); }, [open]); // Esc-to-close. useEffect(() => { if (!open) return; function onKey(e: KeyboardEvent) { if (e.key === "Escape") onClose(); } document.addEventListener("keydown", onKey); return () => document.removeEventListener("keydown", onKey); }, [open, onClose]); // Body scroll-lock while open. useEffect(() => { if (!open) return; const prev = document.body.style.overflow; document.body.style.overflow = "hidden"; return () => { document.body.style.overflow = prev; }; }, [open]); if (!open || typeof document === "undefined") return null; async function onSubmit(e: React.SyntheticEvent) { e.preventDefault(); setError(null); setSubmitting(true); try { const updated = await auth.setEmail(email); setUser(updated); onClose(); } catch (err) { setError(err instanceof AuthError ? err.message : "Could not save email."); } finally { setSubmitting(false); } } return createPortal( <>

Add your email

Add an email to enable password recovery and notifications. We'll send a verification link to confirm it's yours.

setEmail(e.target.value)} placeholder="you@example.com" />
{error ? (

{error}

) : null}
, document.body, ); }