"use client"; import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import { useAuth } from "@/components/AuthProvider"; import { c2api } from "@/lib/c2api"; import { Button } from "@/components/ui/Button"; /** * Shown to any signed-in user with no org_id claim — see ChromeSwitcher's * no-claim guard (SAAS_PLAN.md B3). Two ways to land here: * 1. Just created an account via /signup, org name not collected yet. * 2. Signed in via Google on /login (which auto-creates a Firebase account * on first use) and was never provisioned into anything. * Either way, this is the one screen an unprovisioned account can reach, * and completing it is what POST /auth/signup uses to grant org_id/org_role. */ export default function OnboardingPage() { const { user, loading, orgId, refreshClaims } = useAuth(); const router = useRouter(); const [orgName, setOrgName] = useState(""); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(null); useEffect(() => { if (loading) return; if (!user) { router.replace("/login"); return; } if (orgId) { router.replace("/dashboard"); } }, [loading, user, orgId, router]); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); if (!orgName.trim()) return; setSubmitting(true); setError(null); try { await c2api.signup(orgName.trim()); // Firebase custom claims only show up in a *freshly fetched* ID token — // getIdTokenResult(true) inside refreshClaims forces that fetch, then // AuthProvider's own state (orgId) updates and the effect above // redirects to /dashboard. await refreshClaims(); } catch (err) { setError(err instanceof Error ? err.message : "Could not set up your organization. Try again."); setSubmitting(false); } } if (loading || !user || orgId) return null; return (

Set up your organization

One more step — name the organization your nodes, calls, and incidents will belong to. You can change this later.

setOrgName(e.target.value)} required autoFocus placeholder="e.g. Riverside County Scanner" className="w-full bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-indigo-500" />
{error &&

{error}

}
); }