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
| Responsibility | Detail |
|---|---|
| Imaging studies queue | The single screen they sign in to: a table of imaging studies (study UID, patient, modality, body part, status, started date, performer). |
| Order intake | Imaging 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 acquisition | Editing a study captures modality, body part, body site, started/ended dates, performer, and a DICOM path. |
| Reading & reporting | Edit findings + conclusion on the study. The final report is published as a DiagnosticReport and shows up under the ordering doctor’s Results. |
| Patient context | Click 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 observations | The 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
- Sign in. The system bounces them straight to
/radiology. No dashboard. - Watch the queue. The table shows every imaging study, sorted by id desc (newest first).
- 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.
- 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.
- 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.
- 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.
- Click “Conditions” to inform interpretation — e.g. CKD changes contrast strategy; pregnancy contraindicates fluoroscopy.
- 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.
- 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_newon 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, notservice_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.roleisdoctorornurse.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:
- Sets the post-login home to
#/<wardRoute>(skips/dashboard). - Bounces any
#/dashboardhit back to the ward route. - Renders
renderWardShell(wardKey)— for radiology, the slot hosts<radiology-page>. The route is/radiology. 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
doctorstable):Diagnostic Radiology - role:
doctor
Idempotency: users.email UNIQUE → ON 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()fetchesGET /api/imaging-studies(orGET /api/imaging-studies/patient/:idif aselectedPatientIdis set), andGET /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 resolvespatient_namefroms.patient_nameif present, otherwise from the loadedthis.patientslist. - 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-levelradiology-open-chartevent with the augmented payload. <radiology-patient-chart>mounted at the bottom of the render template — single instance, subscribes to the window event inconnectedCallback.- 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.
- Allergies rows get a red border + “contrast-relevant” badge when the substance matches
B.6 Categories — list and create endpoints
| Card | List API | Add API | Editable |
|---|---|---|---|
| Imaging Study | passed in via show(study) | n/a | no |
| Vitals | GET /api/observations/patient/:id/vitals | POST /api/observations category: vital-signs | yes |
| Allergies | GET /api/allergies/patient/:id | POST /api/allergies | yes |
| Conditions | GET /api/conditions/patient/:id | POST /api/conditions | yes |
| Nursing Assess. | GET /api/nursing-assessments/patient/:id | POST /api/nursing-assessments | yes |
| Medications | GET /api/prescriptions?patient_id= | (placed by ordering doctor — read-only here) | no |
| Lab Orders | GET /api/service-requests?patient_id= filter category ~ “lab” | (read-only) | no |
| Imaging Orders | same, filter category ~ “rad|imag” | (read-only) | no |
| Results | GET /api/diagnostic-reports?patient_id= | (published from the radiology board’s Edit) | no |
| Care Plans | GET /api/care-plans?patient_id= | (read-only) | no |
| Consents | GET /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:
| Chip | code | display | unit |
|---|---|---|---|
| BP | 85354-9 | Blood Pressure | mmHg |
| HR | 8867-4 | Heart Rate | bpm |
| Temp | 8310-5 | Body Temperature | °C |
| SpO2 | 59408-5 | Oxygen Saturation | % |
| RR | 9279-1 | Respiratory Rate | /min |
| Wt | 29463-7 | Body Weight | kg |
| Pain | 38208-5 | Pain Severity | 0-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/radiologybecause backend permission is role-based; only the kiosk shell narrows this client-side. Ideally the radiology routes checkuser.department ∈ imaging disciplinesserver-side too. - Radiology nurse seed user. No nurse is seeded — only the radiology doctor. Add a
radiology.nurse@hospital.comfor 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. Joiningimaging_studies → patientsserver-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-chartcomponent 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