import { useEffect, useRef, useState } from "react"; import { createProject } from "./api"; import { useProject } from "./project"; import { getIdentity, subscribeIdentity } from "./session"; import { ChevronDown } from "./icons"; // The top-bar project ("repo") switcher. The pill shows the open project's name; clicking opens a menu // of every project with its case count, and selecting one scopes the worklist. An admin (session role // "admin") also gets a "New project" action that creates one, refreshes the list, and switches to it. export default function ProjectSwitcher() { const { projectId, setProjectId, projects, refresh } = useProject(); const [open, setOpen] = useState(false); const [isAdmin, setIsAdmin] = useState(() => getIdentity().role === "admin"); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); const ref = useRef(null); // The New project action follows the session identity: it appears on an admin login and disappears on // sign-out without a reload. useEffect(() => subscribeIdentity(() => setIsAdmin(getIdentity().role === "admin")), []); // Dismiss the menu on a click outside it. useEffect(() => { if (!open) return; function onPointerDown(event: MouseEvent) { if (ref.current && !ref.current.contains(event.target as Node)) setOpen(false); } document.addEventListener("mousedown", onPointerDown); return () => document.removeEventListener("mousedown", onPointerDown); }, [open]); const current = projects.find((p) => p.project_id === projectId); // Before the project list loads (or if the open project is not in it), fall back to the raw project id // rather than a hardcoded product name that can disagree with the real project record (#247). const currentName = current?.name ?? projectId; function select(id: string) { setProjectId(id); setOpen(false); } async function handleNewProject() { const name = window.prompt("New project name")?.trim(); if (!name) return; setBusy(true); setError(null); try { const created = await createProject(name); await refresh(); setProjectId(created.project_id); setOpen(false); } catch (err) { setError(err instanceof Error ? err.message : String(err)); } finally { setBusy(false); } } return (
{open ? (
{projects.map((p) => ( ))} {projects.length === 0 ? No projects yet. : null} {isAdmin ? ( <>
) : null} {error ? ( {error} ) : null}
) : null}
); }