// The staff chart's sections, shared by its nav, its Record view and its breadcrumb. export type PatientNavSubSection = { id: string; label: string }; export type PatientNavSection = { id: string; label: string; subSections?: PatientNavSubSection[]; alsoActiveOn?: string[] }; // Lean sections every staff workspace sees. export const BASE_STAFF_SECTIONS: PatientNavSection[] = [ { id: "profile", label: "Profile" }, // Where staff see who acts for the patient and record a parent or guardian for a minor. { id: "related-persons", label: "Family & caregivers" }, { id: "appointments", label: "Appointments" }, { id: "tasks", label: "Tasks" }, { id: "insurance", label: "Insurance" }, // The patient's paperwork. Both routes existed and rendered correctly for weeks with NOTHING in // any nav pointing at either - the same failure as My History, which was built, deployed and // invisible. It reports as nothing at all: no error, no 404, just a section that is never offered, // so the only way to find it is to already know the URL. // // Intake answers are the reason the patient filled the form in. A clinician who cannot reach them // asks the patient the same questions again at the visit - which is the exact re-asking this product // exists to stop. // // In BASE (not CHART) sections on purpose, for the same reason Access Log is: paperwork is // front-desk work before it is clinical work. A receptionist checking whether intake came back is // the commonest reader of both. { id: "questionnaire-responses", label: "Questionnaire Answers" }, { id: "documents", label: "Documents" }, { id: "notes", label: "Internal Notes" }, // - "who has been in this chart". In BASE (not CHART) sections on purpose: the server route // admits receptionists as well as practitioners, because they can already read the chart at their own // org and the principle is "if you can read the chart, you can read who else read it". { id: "access-log", label: "Access Log" }, ]; // The chart's clinical lists by group (practitioner workspace only). IDs + sub-section IDs MUST match the // paths in App.tsx renderPatientRoutes(). Record replaces these groups in the nav and lists them itself. export const RECORD_SECTION_GROUPS: PatientNavSection[] = [ { id: "clinical", label: "Clinical", subSections: [ { id: "family-history", label: "Family History" }, { id: "allergy-intolerances", label: "Allergies" }, { id: "conditions", label: "Conditions" }, { id: "procedures", label: "Procedures" }, { id: "adverse-events", label: "Adverse Events" }, { id: "clinical-impressions", label: "Clinical Impressions" }, { id: "detected-issues", label: "Detected Issues" }, ]}, { id: "diagnostics", label: "Diagnostics", subSections: [ { id: "observations", label: "Observations" }, { id: "body-structures", label: "Body Structures" }, { id: "diagnostics-reports", label: "Diagnostic Reports" }, { id: "media", label: "Media" }, { id: "imaging-studies", label: "Imaging" }, ]}, { id: "medications", label: "Medications", subSections: [ { id: "medication-statements", label: "Medication Statements" }, { id: "medication-requests", label: "Medication Requests" }, { id: "medication-administrations", label: "Administrations" }, { id: "medication-dispenses", label: "Dispenses" }, { id: "immunizations", label: "Immunizations" }, { id: "immunization-evaluations", label: "Immunization Evaluations" }, { id: "immunization-recommendations", label: "Immunization Recommendations" }, ]}, { id: "device-data", label: "Device Data", subSections: [ { id: "devices", label: "Devices" }, { id: "device-use-statements", label: "Device Use Statements" }, { id: "device-requests", label: "Device Requests" }, ]}, { id: "care-provision", label: "Care Provision", subSections: [ { id: "care-plans", label: "Care Plans" }, { id: "care-teams", label: "Care Teams" }, { id: "outside-providers", label: "Outside Providers" }, { id: "goals", label: "Goals" }, { id: "diagnostic-orders", label: "Tests & Imaging" }, { id: "nutrition-orders", label: "Nutrition Orders" }, { id: "referrals", label: "Referrals" }, { id: "risk-assessments", label: "Risk Assessments" }, { id: "vision-prescriptions", label: "Vision Prescriptions" }, ]}, ]; export const CHART_SECTIONS: PatientNavSection[] = [ { id: "record", label: "Record", alsoActiveOn: RECORD_SECTION_GROUPS.map((group) => group.id) }, ]; // Encounters/Episodes - practitioner AND receptionist (front-desk starts/arrives encounters). export const MANAGEMENT_SECTION: PatientNavSection = { id: "management", label: "Management", subSections: [ { id: "encounters", label: "Encounters" }, { id: "episodes-of-care", label: "Episodes of Care" }, ]}; const CHART_ROOT = /^\/dashboard\/(?:encounters\/[^/]+\/)?patients\/([^/]+)(?:\/(.*))?$/; /** * The staff chart's trail, "Dashboard > Patients > Yusuf Demir > Record": the patient's name only when * the loaded patient is the one the address names, and the deepest section the nav can name as the leaf. */ export const staffChartCrumbTrail = ( pathname: string, loaded: { id?: string; name?: string } | undefined, ): { path: string; label: string }[] | undefined => { const match = CHART_ROOT.exec(pathname.replace(/\/+$/, "")); if (!match || match[1] === "import" || match[1] === "new") return undefined; const [, id, rest = ""] = match; const chart = pathname.slice(0, pathname.indexOf(`/patients/${id}`) + `/patients/${id}`.length); const trail = [ { path: "/dashboard", label: "Dashboard" }, { path: "/dashboard/patients", label: "Patients" }, { path: chart, label: loaded?.id === id && loaded.name ? loaded.name : "Patient" }, ]; const [first, second] = rest.split("/"); const sections = [...BASE_STAFF_SECTIONS, ...CHART_SECTIONS, ...RECORD_SECTION_GROUPS, MANAGEMENT_SECTION]; const section = sections.find((candidate) => candidate.id === first); const leaf = section?.subSections?.find((candidate) => candidate.id === second)?.label ?? section?.label; if (leaf) trail.push({ path: `${chart}/${rest}`, label: leaf }); return trail; };