Nexus Docs Documentation for the Nexus hospital management system

Guides

Radiology

Imaging-studies queue with patient-context for contrast safety — the second non-bedside kiosk.

Two parts:

  • Part A — Business level. What radiology staff (radiologists, radiology nurses, technologists filling those roles) are responsible for, what the screen looks like when they sign in, and how the day flows.
  • Part B — Technical level. What the routes, components, RBAC, and APIs do under the hood.

Companion docs: docs/ICU_GUIDE.md, docs/MATERNITY_GUIDE.md, docs/EMERGENCY_GUIDE.md, docs/OPERATIONS_GUIDE.md, docs/WARD_GUIDE.md, docs/LAB_GUIDE.md, docs/WORKFLOWS.md.

This is the seventh ward-style kiosk and the second non-bedside one (after Lab). It pins radiology staff to the existing imaging-studies page (/radiology) and adds a patient-context popup so a radiologist reading a study can pull up clinical context — especially the allergies and conditions that determine contrast safety — without leaving the work queue.


Part A — Business level

A.1 What a Radiology doctor / nurse owns

ResponsibilityDetail
Imaging studies queueThe single screen they sign in to: a table of imaging studies (study UID, patient, modality, body part, status, started date, performer).
Order intakeImaging orders coming in from the wards (ICU / ER / Maternity / Operations / Ward) appear in the queue the moment a doctor places one.
Study creation+ New Imaging Order opens a form to create a study against a patient and (optionally) an encounter — used when imaging happens without an explicit service_request.
Image acquisitionEditing a study captures modality, body part, body site, started/ended dates, performer, and a DICOM path.
Reading & reportingEdit findings + conclusion on the study. The final report is published as a DiagnosticReport and shows up under the ordering doctor’s Results.
Patient contextClick any patient name on the queue → chart popup with the imaging study itself plus vitals, allergies, conditions, current medications, prior reports, care plans, consents. The chart highlights contrast-relevant allergies (iodine / contrast / gadolinium / latex / shellfish) and flags peri-procedure medications (metformin, anticoagulants).
Recording observationsThe chart’s editable categories (Vitals, Allergies, Conditions, Nursing Assess.) are mostly for context — adding a contrast allergy you discovered during screening, or a pre-procedure pain score.

A.2 What they cannot do

The Radiology shell is intentionally narrow — kiosk-style, like the six other kiosks:

  • No sidebar, no global navigation, no dashboard.
  • No access to ward boards (ICU / ER / Maternity / Operations / Ward), no access to lab, pharmacy, billing, HR, or admissions.
  • No access to a patient unless that patient has at least one imaging study or radiology service request.

Forbidden URLs land on the standard Forbidden page.

A.3 What the screen looks like

When a radiology doctor or nurse logs in:

┌──────────────────────────────────────────────────────────────────────────────┐
│ M  Mando · Radiology       [ Radiology ]            🔔   Dr. Nora Aoun ┄      │
├──────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│   Radiology & Imaging                                  + New Imaging Order  │
│                                                                              │
│   Search by study UID, modality, body part, or patient…                      │
│                                                                              │
│   Study UID    Patient        Modality   Body Part    Status      Started   │
│   IMG-2026-…   John Smith     CT         Chest         in-progress 09:14    │
│   IMG-2026-…   Maria Garcia   MRI        Brain         scheduled   —        │
│   IMG-2026-…   Anna Taylor    XR         Pelvis        completed   08:02    │
│   …                                                                          │
└──────────────────────────────────────────────────────────────────────────────┘

Top bar: brand → single static tab “Radiology” → notification bell → user pill → Sign out.

A.4 The day, end to end

  1. Sign in. The system bounces them straight to /radiology. No dashboard.
  2. Watch the queue. The table shows every imaging study, sorted by id desc (newest first).
  3. Click a patient name on any row → the chart popup opens with 11 cards: Imaging Study, Vitals, Allergies, Conditions, Nursing Assess., Medications, Lab Orders, Imaging Orders, Results, Care Plans, Consents.
  4. Click “Imaging Study” → snapshot of this study: modality, body part, body site, study UID, status, started/ended, performer, DICOM path, findings, conclusion.
    • Banner appears when the modality is contrast-capable (CT / MRI / angiography / fluoroscopy) and the patient has any recorded allergies. Read the Allergies card before scanning.
    • A milder banner appears for any contrast-capable modality even with no allergies — a reminder to confirm renal function and allergy history.
  5. Click “Allergies” → list of every allergy. Contrast-relevant entries (iodine, contrast, gadolinium, latex, shellfish) get a red border and a “contrast-relevant” badge so they stand out.
  6. Click “Medications” → active prescriptions. Metformin and oral / parenteral anticoagulants (warfarin, heparin, apixaban, rivaroxaban, dabigatran, edoxaban, enoxaparin) get an orange border and a “peri-procedure” badge so the radiologist knows to coordinate with the ordering doctor before contrast / interventional procedures.
  7. Click “Conditions” to inform interpretation — e.g. CKD changes contrast strategy; pregnancy contraindicates fluoroscopy.
  8. Add a vital / allergy / condition / nursing note if pre-procedure screening turned up something. The Allergies add form’s Substance defaults to “Iodine contrast” and the criticality defaults to “High” so the common case is one click + Save.
  9. Move the study through the workflow. Close the chart, click Edit on the row to update status (scheduled → in-progress → completed), record findings, conclusion, performer, DICOM path. Save → ordering doctor sees it under Results.

A.5 Notifications

Inbound (the bell flashes):

  • New imaging order placed by a doctor (the wards) — fires imaging_order_new on the Radiology department feed. STAT priority orders fire at high priority.

Outbound (the radiology team fires automatically):

  • Final report published → ordering doctor’s notification feed (planned — see follow-ups below).
  • Critical-finding flagged → ward + ordering doctor (planned).

A.6 Common pitfalls

  • “I want to enter findings but the chart popup is open.” The chart is for context, not result entry. Close it and click Edit on the study row.
  • “I tried to open the lab page and got Forbidden.” Correct — radiology staff can’t browse lab. Use the Lab Orders card on the chart to see a patient’s pre-procedure labs (e.g. creatinine before a contrast CT).
  • “The patient I’m expecting isn’t on the queue.” Either (a) the doctor hasn’t placed an imaging order yet, (b) no imaging study record was created. The queue is imaging_studies, not service_requests — if an order was placed but no study created, click + New Imaging Order to create one.
  • “My patient has 30 prior reports.” That’s expected on a long admission. Use the search box to filter by study UID, modality, body part, or patient name.
  • “The chart says contrast-relevant but I see no allergy.” The badge fires when the modality is contrast-capable AND any allergy exists, not just contrast allergies — it’s a prompt to read the list, not a hard alert. Open the Allergies card to confirm.

Part B — Technical level

B.1 Identity & ward shell

A user is treated as a “Radiology kiosk user” when all of these are true:

  • users.role is doctor or nurse.
  • users.department (case-insensitive, trimmed) is one of: radiology, imaging, medical imaging, diagnostic imaging, interventional radiology, nuclear medicine, mri, ct, ultrasound, mammography.

This list lives in AppRoot.WARD_CONFIG.radiology.depts and matches the new entries in WARD_NAV in frontend/src/services/role-permissions.js.

Shell decision is generic — AppRoot.wardForUser(user) returns the ward key ('icu' / 'maternity' / 'emergency' / 'operations' / 'ward' / 'lab' / 'radiology') or null. When non-null, app-root.js:

  1. Sets the post-login home to #/<wardRoute> (skips /dashboard).
  2. Bounces any #/dashboard hit back to the ward route.
  3. Renders renderWardShell(wardKey) — for radiology, the slot hosts <radiology-page>. The route is /radiology.
  4. renderWardPage(wardKey) switches on the key and returns the right page element.

All seven kiosks (ICU / Maternity / Emergency / Operations / Ward / Lab / Radiology) now share the same generic shell.

B.2 Seed data

Seven ward-doctor logins are created idempotently on every boot by ensureWardDoctors. For Radiology:

  • email: radiology.doctor@hospital.com
  • password: admin123
  • name: Dr. Nora Aoun
  • department: Radiology
  • specialization (in doctors table): Diagnostic Radiology
  • role: doctor

Idempotency: users.email UNIQUEON CONFLICT (email) DO NOTHING for users; INSERT … WHERE NOT EXISTS for the matching doctors row.

Radiology nurses are created the same way once a user record with role='nurse' and department='Radiology' (or one of the modality aliases) is added.

B.3 RBAC

Backend (path-based middleware): the doctor and nurse role permission tables in backend/internal/middleware/roles.go now include radiology for both roles. Doctors get full CRUD; nurses get GET/POST/PUT. They keep excluding pharmacy, pharmacy-dispense, general-inventory. They allow prescriptions, service-requests, diagnostic-reports, imaging-studies, observations, allergies, conditions, nursing-assessments, care-plans, consents, plus all seven ward routes including lab and radiology.

Note: backend permission is role-based, so any doctor/nurse can technically GET /api/radiology — the kiosk shell + WARD_NAV is what narrows non-radiology users out of the radiology nav. Department-aware backend RBAC remains a follow-up.

Frontend: getNavigationForUser(user) in frontend/src/services/role-permissions.js narrows frontDesk to ['radiology'] for any doctor/nurse whose department resolves to one of the imaging disciplines. Ten department aliases are mapped (radiology, imaging, medical imaging, interventional radiology, nuclear medicine, MRI, CT, ultrasound, mammography, etc.).

B.4 Radiology page

frontend/src/pages/radiology-page.js — the existing imaging studies table. Wired up:

  • loadData() fetches GET /api/imaging-studies (or GET /api/imaging-studies/patient/:id if a selectedPatientId is set), and GET /api/patients (used as a lookup table for patient name resolution since the imaging-studies query doesn’t JOIN patients server-side).
  • New patientNameFor(s) helper resolves patient_name from s.patient_name if present, otherwise from the loaded this.patients list.
  • New Patient column on the table — displays the resolved name as a clickable link.
  • Search box now matches on patient name as well as study UID, modality, body part, performer.
  • New openChart(s) method spreads the study with the resolved patient_name and dispatches a window-level radiology-open-chart event with the augmented payload.
  • <radiology-patient-chart> mounted at the bottom of the render template — single instance, subscribes to the window event in connectedCallback.
  • The Edit / Delete / Create modals stay untouched.

B.5 Radiology patient chart popup

frontend/src/components/radiology-patient-chart.js is a sibling of the lab + five ward kiosk charts. Two views inside one panel:

Grid view (default after show() is called):

  • Header: name • MRN • gender • DOB · modality body_part. “All categories” button hidden.
  • Info bar: gender, DOB, blood type, phone, admission #, modality pill, status pill (colour-coded: scheduled blue / in-progress orange / completed green / cancelled grey).
  • Body: 11 category cards. Each card has icon + label + hint + count badge.

Detail view (after a card click):

  • Imaging Study renders as a single read-only snapshot card (modality, body part, body site, study UID, status, started/ended, performer, DICOM path, findings, conclusion). A red banner fires when the modality is contrast-capable AND the patient has recorded allergies. A neutral banner fires for any contrast-capable modality even with no allergies. A tip-banner reminds users that edits happen on the radiology board.
  • The remaining 10 categories are identical to the lab + five ward charts, with these radiology-specific touches:
    • Allergies rows get a red border + “contrast-relevant” badge when the substance matches /(iod|contrast|gadol|latex|shellfish)/i.
    • Medications rows get an orange border + “peri-procedure” badge when the drug matches /(metformin|warfarin|coumadin|heparin|apixaban|rivaroxaban|dabigatran|edoxaban|enoxaparin)/i.

B.6 Categories — list and create endpoints

CardList APIAdd APIEditable
Imaging Studypassed in via show(study)n/ano
VitalsGET /api/observations/patient/:id/vitalsPOST /api/observations category: vital-signsyes
AllergiesGET /api/allergies/patient/:idPOST /api/allergiesyes
ConditionsGET /api/conditions/patient/:idPOST /api/conditionsyes
Nursing Assess.GET /api/nursing-assessments/patient/:idPOST /api/nursing-assessmentsyes
MedicationsGET /api/prescriptions?patient_id=(placed by ordering doctor — read-only here)no
Lab OrdersGET /api/service-requests?patient_id= filter category ~ “lab”(read-only)no
Imaging Orderssame, filter category ~ “rad|imag”(read-only)no
ResultsGET /api/diagnostic-reports?patient_id=(published from the radiology board’s Edit)no
Care PlansGET /api/care-plans?patient_id=(read-only)no
ConsentsGET /api/consents?patient_id=(read-only)no

For each editable category the chart’s submitAdd(e) method assembles the FHIR-shaped payload and POSTs it. On success it re-fetches the active category and re-runs loadCounts().

The Allergies add form is tuned for radiology: Substance placeholder is “Iodine contrast”, the Category dropdown moves “Contrast / biologic” up, and Criticality defaults to “High”.

The Nursing Assess. dropdown is tuned for radiology: Pre-procedure check, Contrast allergy screening, Pregnancy screen, Pain, Claustrophobia (MRI), Other.

B.7 Vitals quick chips

Vitals add form has the standard seven chips:

Chipcodedisplayunit
BP85354-9Blood PressuremmHg
HR8867-4Heart Ratebpm
Temp8310-5Body Temperature°C
SpO259408-5Oxygen Saturation%
RR9279-1Respiratory Rate/min
Wt29463-7Body Weightkg
Pain38208-5Pain Severity0-10

B.8 Where reading actually happens

The chart popup is not where the radiologist records findings — that flow lives on the radiology board itself (Edit on the row). The chart’s purpose is:

  • Read patient context (allergies, conditions, current meds) to interpret the study and choose contrast strategy.
  • Capture the rare bedside-style note that surfaces during pre-procedure screening (an unrecorded latex allergy noticed in the changing room, etc.).

Final reports are published as diagnostic_report rows linked back to the originating service_request and imaging_study.

B.9 Build / verification

  • Backend: go build ./... — clean.
  • Frontend: npx vite build — 1.56 MB / 254 kB gzip in ~2s.

B.10 Known follow-ups (not done yet)

  • Critical-finding back-alerts. When a radiology report is published with a critical finding (e.g. PE on CTA, intracranial bleed on head CT, free air on CXR), fire a high-priority notification to the ordering doctor and the patient’s current ward. The order-route notification is in place; the result-route is not.
  • Department-aware backend RBAC. Today any doctor/nurse can GET /api/radiology because backend permission is role-based; only the kiosk shell narrows this client-side. Ideally the radiology routes check user.department ∈ imaging disciplines server-side too.
  • Radiology nurse seed user. No nurse is seeded — only the radiology doctor. Add a radiology.nurse@hospital.com for parity.
  • Per-study DICOM viewer. Today the chart shows the DICOM path as a string. A small viewer / link to OHIF would let the radiologist read images directly from the chart context.
  • Backend JOIN for patient_name. The radiology page resolves patient names client-side from a separate getPatients() call. Joining imaging_studies → patients server-side would simplify the frontend and avoid the lookup miss when patients aren’t fully loaded.
  • Seven chart components share ~85% of their code. Refactor opportunity: extract a single ward-patient-chart component parameterised by a ward descriptor (snapshot card renderer, vital-chip preset, item-flag rules, nursing-assess types). The seven files duplicate ~3,500 lines.

Last updated: 2026-04-27