/* global React, Icons, RBAuth, useAuth */ // ============================================================ // Auth — sign in / sign up modal + nav account control // Open from anywhere: window.requestAuth({ mode, next }) // ============================================================ const { useState: useStateAuth, useEffect: useEffectAuth } = React; window.requestAuth = (opts) => window.dispatchEvent(new CustomEvent("rb-auth-open", { detail: opts || {} })); const isEmailA = (s) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s); function AuthModal({ mode: initMode, next, onClose }) { const [mode, setMode] = useStateAuth(initMode === "signup" ? "signup" : "signin"); const [name, setName] = useStateAuth(""); const [email, setEmail] = useStateAuth(""); const [pw, setPw] = useStateAuth(""); const [busy, setBusy] = useStateAuth(false); const [err, setErr] = useStateAuth(""); const [info, setInfo] = useStateAuth(""); useEffectAuth(() => { const onKey = (e) => { if (e.key === "Escape") onClose(); }; document.addEventListener("keydown", onKey); return () => document.removeEventListener("keydown", onKey); }, []); const submit = async (e) => { e.preventDefault(); setErr(""); setInfo(""); if (!isEmailA(email)) { setErr("Enter a valid email address."); return; } if (pw.length < 6) { setErr("Password must be at least 6 characters."); return; } setBusy(true); try { if (mode === "signup") { const r = await RBAuth.signUp(email.trim(), pw, name.trim()); if (r && r.user && !r.session) { setInfo("Check your inbox to confirm your email, then sign in."); setMode("signin"); setBusy(false); return; } } else { await RBAuth.signIn(email.trim(), pw); } setBusy(false); if (typeof next === "function") setTimeout(next, 30); onClose(); } catch (e2) { setBusy(false); setErr((e2 && e2.message) || "Something went wrong. Please try again."); } }; const magic = async () => { setErr(""); setInfo(""); if (!isEmailA(email)) { setErr("Enter your email first."); return; } setBusy(true); try { await RBAuth.magicLink(email.trim()); setInfo("Magic link sent — check your email."); } catch (e2) { setErr((e2 && e2.message) || "Could not send link."); } setBusy(false); }; return (
{ if (e.target === e.currentTarget) onClose(); }}>
get-resume.com

{mode === "signup" ? "Create your account" : "Welcome back"}

{mode === "signup" ? "Save your résumés to the cloud and unlock Pro." : "Sign in to access your saved résumés and Pro."}

{mode === "signup" && ( )} {err &&
{err}
} {info &&
{info}
}
{mode === "signup" ? ( <>Already have an account? ) : ( <>New here? )}
); } // Mounted once at app root; listens for rb-auth-open. function AuthGate() { const [state, setState] = useStateAuth(null); useEffectAuth(() => { const h = (e) => setState((e.detail) || {}); window.addEventListener("rb-auth-open", h); return () => window.removeEventListener("rb-auth-open", h); }, []); if (!state) return null; if (!RBAuth.enabled()) { // backend not configured — let the user know, don't trap them return (
setState(null)}>
Demo mode

Accounts aren't connected yet

Add your Supabase keys in config.js to enable real sign-in. Until then the app runs locally on this device.

); } return setState(null)} />; } // Nav control: shows Sign in, or the account menu when logged in. function AccountButton() { const { user, enabled } = useAuth(); const [open, setOpen] = useStateAuth(false); if (!enabled) return null; // hide entirely in demo mode if (!user) { return ( ); } const label = (user.user_metadata && user.user_metadata.full_name) || user.email; const initial = (label || "?").trim().charAt(0).toUpperCase(); return (
{open && (
setOpen(false)}>
{label}{user.email}
)}
); } Object.assign(window, { AuthModal, AuthGate, AccountButton });