// Book opens the overview's booking dialog via router state, so a reload does not reopen it. export type FrontDeskHeaderAction = "book"; export const FRONT_DESK_HOME = "/dashboard/receptionist"; export const FRONT_DESK_APPOINTMENTS = "/dashboard/appointments"; export interface FrontDeskActionState { frontDeskAction?: FrontDeskHeaderAction; } export const readFrontDeskAction = (state: unknown): FrontDeskHeaderAction | undefined => { const action = (state as FrontDeskActionState | null)?.frontDeskAction; return action === "book" ? action : undefined; }; export interface FrontDeskActionGrants { search: boolean; register: boolean; book: boolean; } type MayCall = (method: string, path: string) => boolean | undefined; /** * Header actions follow the caller's grants, not the workspace title: Search needs patient search, Register * patient creation and Book appointment creation. A grant the server has not yet answered is drawn only for * the front desk, whose actions these always were; an explicit refusal is never drawn. A patient viewer gets * none, and a closed practice refuses its staff the patients they reach, so it gets none either. Only the * Receptionist and Practitioner decks draw these actions, so every other workspace gets none. */ export const frontDeskActionGrants = ({ isPatientViewer, closedToStaff, isReceptionist, deskWorkspace, mayCall, noAccess, }: { isPatientViewer: boolean; closedToStaff: boolean; isReceptionist: boolean; deskWorkspace: boolean; mayCall: MayCall; /** The gateway refused this member here; the page below says so and offers only Sign out. */ noAccess?: boolean; }): FrontDeskActionGrants => { if (isPatientViewer || closedToStaff || !deskWorkspace || noAccess) return { search: false, register: false, book: false }; const granted = (method: string, path: string) => { const answer = mayCall(method, path); return answer === true || (answer === undefined && isReceptionist); }; return { search: granted("GET", "/Patient"), register: granted("POST", "/Patient"), book: granted("POST", "/Appointment"), }; };