import { useSyncExternalStore } from 'react'; /** * The team a phone has opened as a page of its own, so the shell's trail can end on its name: * "Dashboard › Collaboration teams › Primary care team", as the deck's 390 team board draws it. * * From a tablet up a team opens OVER the list and nothing is published, so the trail stays the list's. * Keyed by team id and checked against the address, so a name can only ever crumb its own team. */ export interface OpenTeam { teamId: string; name: string; } let current: OpenTeam | undefined; const listeners = new Set<() => void>(); export const publishOpenTeam = (team: OpenTeam | undefined): void => { if (current?.teamId === team?.teamId && current?.name === team?.name) return; current = team; listeners.forEach((listener) => listener()); }; const subscribe = (listener: () => void) => { listeners.add(listener); return () => { listeners.delete(listener); }; }; export const useOpenTeam = (): OpenTeam | undefined => useSyncExternalStore(subscribe, () => current, () => current); const TEAM_PAGE = /^\/dashboard\/collaboration-teams\/([^/]+)\/?$/; export const teamPageCrumbTrail = ( pathname: string, open: OpenTeam | undefined, ): { path: string; label: string }[] | undefined => { const teamId = TEAM_PAGE.exec(pathname)?.[1]; if (!teamId || !open || open.teamId !== teamId) return undefined; return [ { path: '/dashboard', label: 'Dashboard' }, { path: '/dashboard/collaboration-teams', label: 'Collaboration teams' }, { path: pathname, label: open.name }, ]; };