Nexus Docs Documentation for the Nexus hospital management system

Guides

Ward

General inpatient stays, elective admissions, and post-transfer recovery — the fifth and last ward kiosk.

Two parts:

  • Part A — Business level. What ward staff (general inpatient floor doctors and nurses) 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/WORKFLOWS.md, docs/ADMISSIONS_OFFICER_GUIDE.md.

This is the fifth and last of the ward kiosks. ICU / Maternity / Emergency / Operations cover the four specialty boards; Ward covers everyone else — inpatient stays, planned/elective admissions, day-cases, and post-transfer recovery from any of the specialty units.


Part A — Business level

A.1 What a Ward doctor / nurse owns

ResponsibilityDetail
Ward boardThe single screen they sign in to. Two tabs: Ward Patients (admitted, currently on a wing) and Waiting List (queued for a bed). Wing filter chips at the top let staff focus on one wing at a time.
Patient chartA popup that opens when they click a patient name. Holds Admission snapshot, Vitals, Allergies, Conditions, Nursing Assess., Medications, Lab/Imaging Orders, Results, Care Plans, Consents.
Recording observationsThey can add new vitals, allergies, conditions, and nursing assessments directly from the chart popup. Vitals form has the standard 7 chips: BP, HR, Temp, SpO2, RR, Wt, Pain.
Nursing assessmentsThe assessment-type dropdown is tuned for ward work: Braden (skin), Morse (fall), Pain, CAM (confusion), ADL (activities of daily living).
Placing ordersThe + Order button on each row opens Quick Orders (Prescription / Lab / Imaging). Pharmacy / Laboratory / Radiology are notified but invisible to the ward clinician.
Waiting listAdd patients to the queue with a priority (1–4), preferred wing, reason, and diagnosis. When a bed frees up, Assign the patient to a room and they jump straight onto the ward tab.
Daily roundsEdit each patient row to update room/bed, attending nurse, mobility status, diet restrictions, expected stay, visiting hours, care plan.

A.2 What they cannot do

The Ward shell is intentionally narrow — kiosk-style, like the four specialty wards:

  • No sidebar, no global navigation, no dashboard.
  • No access to lab, pharmacy, radiology, billing, HR, or admissions screens.
  • No access to ICU / Maternity / Emergency / Operations boards (use the standard transfer flow).
  • No access to patients who are not on the ward board.

Forbidden URLs land on the standard Forbidden page.

A.3 What the screen looks like

When a ward doctor or nurse logs in:

┌──────────────────────────────────────────────────────────────────────────────┐
│ M  Mando · Ward            [ Ward ]                 🔔   Dr. Maya Farah ┄     │
├──────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│   🏥 Ward Management                       [+ Waiting List]  [+ Acceptance] │
│   3 patients • 1 waiting                                                     │
│                                                                              │
│   [ Ward Patients (3) ]  Waiting List (1)                                   │
│                                                                              │
│   ┌ All Wings ─ Cardiology ─ Neurology ─ Orthopedics ─ Pediatrics ─ … ─┐    │
│                                                                              │
│   ┌ general ─ John Smith ─ Dr. Maya Farah ─ Room 305 ─ [Cardiology Wing]┐    │
│   │ Bed: B-2   Nurse: Sarah   Mobility: assisted   Stay: 3-5 days       │    │
│   │ Diet: Low-sodium   Visiting Hours: 14:00-17:00, 19:00-20:30          │    │
│   │ Care Plan: Daily ECG, BP q4h, monitor for arrhythmia                  │    │
│   │ ─────────────────────────────  [+ Order] [Edit] [🗑]                  │    │
│   └────────────────────────────────────────────────────────────────────────┘│
└──────────────────────────────────────────────────────────────────────────────┘

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

A.4 The day, end to end

  1. Sign in. The system bounces them straight to /normal-acceptance (the ward board). No dashboard.
  2. Read the board. Two tabs — Ward Patients and Waiting List. On Ward Patients, wing-filter chips at the top show occupancy per wing.
  3. Click a wing chip to focus on one wing’s patients only, or All Wings to see everyone.
  4. Click the patient name. The chart popup opens with 11 cards: Admission, Vitals, Allergies, Conditions, Nursing Assess., Medications, Lab Orders, Imaging Orders, Results, Care Plans, Consents. Each card shows a count.
  5. Click “Admission”. Read-only snapshot: wing, room, bed, ward type, attending nurse, mobility, expected stay, visiting hours, diet restrictions, care plan, notes. The chart’s bottom hint reminds the user that editing the admission record happens on the board (Edit on the row).
  6. Click “Vitals” → + Add. Form has seven chips: BP, HR, Temp, SpO2, RR, Wt, Pain. Click a chip → fields pre-fill → type the value → Save.
  7. Click “Allergies / Conditions / Nursing Assess.” → + Add. Same flow. The Nursing Assess. dropdown is tuned for ward routine: Braden, Morse, Pain, CAM, ADL.
  8. Place an order. Close the chart, click + Order on the row. Three tabs: Prescription, Lab, Imaging. Submit → Pharmacy / Lab / Radiology gets the alert.
  9. Update rounds. Click Edit on the row to change wing/room/bed, nurse, mobility, diet, expected stay, visiting hours, care plan, notes.
  10. Discharge. The bin icon removes the acceptance record (the patient’s underlying admission is closed via the standard reception/cashier discharge flow).
  11. Manage the queue. Switch to the Waiting List tab. + Waiting List adds a new entry. When a bed opens, click Assign on a waiting entry → pick an available room → it admits immediately.

A.5 Notifications

Inbound (the bell flashes):

  • Patient transferred from ICU / ER / Operations to a regular ward — fired by the originating ward’s “Transfer to Ward” handoff.
  • New planned/elective admission landed — fired by Reception with admission_type = inpatient / planned / daycase.
  • Stat lab or imaging result finalised on one of their patients (planned).

Outbound (they create them implicitly):

  • Placing a Lab order → Laboratory.
  • Placing an Imaging order → Radiology.
  • New prescription → MAR / pharmacy queue.
  • Assigning a waiting-list patient to a room → Reception (so the bill state stays in sync).

A.6 Common pitfalls

  • “I can’t find a place to update post-op notes.” Post-op notes belong on the Operations board, not the ward board. The ward chart shows medications and care plans; the originating OR record stays where it was created.
  • “I want to upgrade a patient to ICU.” Today the ward board has no direct To ICU button. Use the existing room-transfer flow (Edit → change wing) or close the case and have ICU re-admit. Future enhancement could mirror ER’s “To ICU” handoff.
  • “The patient I’m looking for isn’t on Ward Patients.” They might be on the waiting list. Check the second tab. If they’re nowhere, Reception hasn’t admitted them yet (admission_type = inpatient / planned / daycase / normal).
  • “I tried to open the lab page and got Forbidden.” Correct — ward staff place orders but never browse lab/pharmacy/radiology. Use + Order on the row.
  • “My patient transferred from ICU isn’t here.” ICU’s “Transfer to Ward” creates an acceptance record in this ward. If they don’t appear, check the wing filter — they may be on a different wing.

Part B — Technical level

B.1 Identity & ward shell

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

  • users.role is doctor or nurse.
  • users.department (case-insensitive, trimmed) is one of: ward, general ward, wards, internal medicine, general medicine, medicine, pediatrics, paediatrics, ophthalmology, oncology, pulmonology, endocrinology, gastroenterology, nephrology, dermatology, ent, family medicine.

This list lives in AppRoot.WARD_CONFIG.ward.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') 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 ward, the slot hosts <normal-acceptance-page> (the existing ward acceptances + waiting-list page). The route is /normal-acceptance.
  4. renderWardPage(wardKey) switches on the key and returns the right page element.

All five ward kiosks (ICU / Maternity / Emergency / Operations / Ward) now use the same generic shell.

B.2 Seed data

Five ward-doctor logins are created idempotently on every boot by ensureWardDoctors. For Ward:

  • email: ward.doctor@hospital.com
  • password: admin123
  • name: Dr. Maya Farah
  • department: Ward
  • specialization (in doctors table): Internal Medicine
  • role: doctor

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

Nurses are seeded the same way once a user record with role='nurse' and department='Ward' (or one of the inpatient aliases) is created (no nurse seed today — add via /hr or /users).

B.3 RBAC

Backend (path-based middleware): the doctor and nurse role permission tables in backend/internal/middleware/roles.go now include normal-acceptance and waiting-list for both roles. They keep excluding lab, pharmacy, pharmacy-dispense, radiology, general-inventory. They allow prescriptions, service-requests, diagnostic-reports, imaging-studies, observations, allergies, conditions, nursing-assessments, care-plans, consents, plus all five ward routes.

Frontend: getNavigationForUser(user) in frontend/src/services/role-permissions.js narrows frontDesk to ['normal-acceptance'] for any doctor/nurse whose department resolves to ward. Sixteen department aliases are mapped (general ward, internal medicine, pediatrics, etc.).

B.4 Ward board

frontend/src/pages/normal-acceptance-page.js is the existing ward acceptances + waiting list page. Wired up:

  • loadData() calls GET /api/normal-acceptances, GET /api/admissions?...&type=normal, GET /api/wings, GET /api/rooms, GET /api/waiting-list, GET /api/patients, GET /api/doctors in parallel.
  • Two tabs: Ward Patients (acceptances list, wing-filter chips at top) and Waiting List (priority-coded queue).
  • _isWardUser getter (new) is wired in for parity with the other ward pages.
  • Patient name click on the Ward Patients tab now calls openChart(a)<ward-patient-chart>.show(acceptanceRecord) instead of the older <patient-encounter-popup>. The popup is still imported and stays available for the Waiting List tab’s name click (since waiting entries don’t yet have a populated chart).
  • New + Order button on each acceptance row opens Quick Orders with source="ward".
  • The Edit / Discharge modals stay untouched.

B.5 Ward patient chart popup

frontend/src/components/ward-patient-chart.js is a sibling of icu / maternity / emergency / operations charts with one extra card. Two views inside one panel:

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

  • Header: name • MRN • gender • DOB · wing · Room · Bed. “All categories” button hidden.
  • Info bar: gender, DOB, blood type, phone, admission #, ward type.
  • Body: 11 category cards. Each card has icon + label + hint + count badge.
  • Counts are loaded by loadCounts() — Admission is always 1 (the acceptance record passed in via show()); the rest mirror the other charts.

Detail view (after a card click):

  • Admission renders as a single read-only snapshot card (wing, room, bed, ward type, attending nurse, mobility, expected stay, visiting hours, diet restrictions, care plan, notes). A tip-banner reminds users that edits happen on the ward board.
  • The remaining 10 categories are identical to ICU / Maternity / ER / Operations.

B.6 Categories — list and create endpoints

CardList APIAdd APIEditable
Admissionpassed in via show(acceptance)(use Edit / Discharge on the board)no
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=(use Quick Orders → Prescription)no
Lab OrdersGET /api/service-requests?patient_id= filter category ~ “lab”(use Quick Orders → Lab)no
Imaging Orderssame, filter category ~ “rad|imag”(use Quick Orders → Imaging)no
ResultsGET /api/diagnostic-reports?patient_id=n/ano
Care PlansGET /api/care-plans?patient_id=(use the care-plan workflow)no
ConsentsGET /api/consents?patient_id=(use the consents workflow)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().

B.7 Vitals quick chips

Vitals add form has the standard seven chips (no ward-specific extras — ward staff capture all the routine vitals):

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

Click chip → code, display, unit pre-fill → user only types the value.

B.8 Quick Orders

The + Order button opens frontend/src/components/quick-orders.js with source="ward". Submitting routes to:

TabEndpointReceiving alert
PrescriptionPOST /api/prescriptions source=wardPharmacy queue
LabPOST /api/service-requests category=laboratoryLaboratory department
ImagingPOST /api/service-requests category=radiologyRadiology department

There is no ward-internal transfer/handoff today — ward patients move out via the standard discharge flow at the cashier, or via Edit (room/wing change).

B.9 Build / verification

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

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

  • Admission edit from inside the chart. Today the chart is read-only on the Admission card; users have to close the popup and click Edit on the row. Worth wiring an inline edit for mobility / diet / visiting hours / care plan (the values that change every shift).
  • Direct “To ICU” handoff from the ward. ER and OR have explicit upgrade paths to ICU; the ward board does not. A patient deteriorating on a regular ward currently has to be moved by closing the acceptance and having ICU re-admit. Worth adding a ward → ICU handoff modal that mirrors emergency-page’s transferToICU.
  • Critical-result back-alerts on stat labs/imaging. Same gap noted in the other ward guides.
  • Per-patient row-level filter on reads. RBAC is path-based today.
  • All five wards now share the same kiosk shell + chart popup pattern. Refactor opportunity: extract the five chart components into a single ward-patient-chart component that accepts a wardKey + extra category descriptor — they currently duplicate ~600 lines each.

Last updated: 2026-04-26