const { useState, useEffect } = React; function JoinModal({ apiBase, visible, onDone }) { const [code, setCode] = useState(""); const [handle, setHandle] = useState(localStorage.getItem("bb_handle") || ""); const [pin, setPin] = useState(""); const [pushOptIn, setPushOptIn] = useState(true); const [busy, setBusy] = useState(false); const [err, setErr] = useState("") const [hasSavedCode, setHasSavedCode] = useState(false); useEffect(() => { if (visible) { const stored = localStorage.getItem("bb_group_code") || ""; setCode(stored); setHasSavedCode(!!stored); } }, [visible]); if (!visible) return null; const submit = async (e) => { e.preventDefault(); setErr(""); if (!/^[0-9]{4}$/.test(pin)) { setErr("PIN must be exactly 4 digits"); return; } setBusy(true); try { const groupCode = code.trim(); // Join / sign-in const r = await fetch(`${apiBase}/auth/join`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ code: groupCode, handle, pin }), }); const j = await r.json(); if (!j.ok) throw new Error(j.error || "Join failed"); localStorage.setItem("bb_group_code", groupCode); localStorage.setItem("bb_handle", handle); localStorage.setItem("bb_token", j.token || ""); // Register for push notifications if available if (pushOptIn && typeof registerPushToken === "function") { await registerPushToken(apiBase, j.token); } const roles = Array.isArray(j.roles) ? j.roles : j.role ? [j.role] : []; onDone(j.token, j.handle, roles); } catch (e) { setErr(e.message); } finally { setBusy(false); } }; return (