import { useState } from 'react' import type { ReactElement } from 'react' import type { BatchStage, BoardTab } from '../types' import type { Project } from '../project' import { PROJECT_LABEL } from '../project' import { IconSpend, IconPage, IconLoop, IconIdCard, IconPatients } from './icons' /** * The app-wide section rail, at a fixed 236px. * * It used to collapse to a 56px icon strip and expand to an overlay on hover. * That is gone with the reskin: the rail is now always labelled, which is what * the approved mockup shows and what removes the "hover to find out what these * icons are" step from every navigation. * * Two projects, one rail: ECW's boards (templates 1-6) and Tebra's (template 7 * / Gulf Coast), each under its own group header. See project.ts for how a * batch or run is assigned to one or the other. * * Selection and drag-and-drop-to-move-stage behaviour are unchanged — only the * shape of the control moved. */ export function Sidebar({ tab, onTab, counts, onDropBatch, onDropRun, isAdmin, projects, }: { tab: BoardTab onTab: (t: BoardTab) => void /** Per project, per stage — each section shows its own queue depth. */ counts: Record> /** A batch card dragged onto a section moves to that stage. */ onDropBatch: (batchId: string, stage: BatchStage) => void /** A single document dragged onto Automation is gathered into its own batch. */ onDropRun?: (jobId: string) => void /** Gates each section's ROI item, and the single account-level People * item below them all — both are admin-and-above. */ isAdmin: boolean /** Which sections render at all. A scoped admin sees one; everyone else sees * both. Independent of `isAdmin`: an operator sees both sections' boards * with ROI/People hidden inside each, while a scoped admin has a whole * section absent regardless of role. */ projects: Project[] }) { return ( ) } /** One project's name above its own nav list, with the bar glyph the mockup * uses for a group header. The divider is skipped on the first section — * there is nothing yet to divide it from. */ function SectionHead({ project, first }: { project: Project; first: boolean }) { return ( <> {!first &&
}
{PROJECT_LABEL[project]}
) } export const BATCH_DRAG_TYPE = 'application/x-superbill-batch' const RUN_DRAG_TYPE = 'application/x-superbill-run' function Item({ tab, dropStage, dropTab, icon: IconEl, label, hint, active, n, onSelect, onDropBatch, onDropRun, }: { tab: BoardTab /** The stage a card dropped here should move to. Absent on sections that * are a view rather than a place, which is what makes them reject a drop. */ dropStage?: BatchStage /** The board to navigate to after a drop. Two projects can share a stage * name (both have an "extraction" and an "automation"), so the stage alone * no longer identifies which board a card landed on — this does. Defaults * to `tab`, which was the drop target anyway on every item that has one. */ dropTab?: BoardTab icon: (p: { size?: number; className?: string }) => ReactElement label: string hint: string active: boolean /** Omitted on sections that count nothing — a report has no queue depth. */ n?: number onSelect: (t: BoardTab) => void onDropBatch?: (batchId: string, stage: BatchStage) => void onDropRun?: (jobId: string) => void }) { const [over, setOver] = useState(false) return ( ) }