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
| Responsibility | Detail |
|---|---|
| Ward board | The 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 chart | A 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 observations | They 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 assessments | The assessment-type dropdown is tuned for ward work: Braden (skin), Morse (fall), Pain, CAM (confusion), ADL (activities of daily living). |
| Placing orders | The + Order button on each row opens Quick Orders (Prescription / Lab / Imaging). Pharmacy / Laboratory / Radiology are notified but invisible to the ward clinician. |
| Waiting list | Add 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 rounds | Edit 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
- Sign in. The system bounces them straight to
/normal-acceptance(the ward board). No dashboard. - Read the board. Two tabs — Ward Patients and Waiting List. On Ward Patients, wing-filter chips at the top show occupancy per wing.
- Click a wing chip to focus on one wing’s patients only, or All Wings to see everyone.
- 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.
- 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).
- Click “Vitals” → + Add. Form has seven chips: BP, HR, Temp, SpO2, RR, Wt, Pain. Click a chip → fields pre-fill → type the value → Save.
- Click “Allergies / Conditions / Nursing Assess.” → + Add. Same flow. The Nursing Assess. dropdown is tuned for ward routine: Braden, Morse, Pain, CAM, ADL.
- Place an order. Close the chart, click
+ Orderon the row. Three tabs: Prescription, Lab, Imaging. Submit → Pharmacy / Lab / Radiology gets the alert. - Update rounds. Click Edit on the row to change wing/room/bed, nurse, mobility, diet, expected stay, visiting hours, care plan, notes.
- Discharge. The bin icon removes the acceptance record (the patient’s underlying admission is closed via the standard reception/cashier discharge flow).
- 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
+ Orderon the row. - “My patient transferred from ICU isn’t here.” ICU’s “Transfer to Ward” creates an
acceptancerecord 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.roleisdoctorornurse.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:
- Sets the post-login home to
#/<wardRoute>(skips/dashboard). - Bounces any
#/dashboardhit back to the ward route. - Renders
renderWardShell(wardKey)— for ward, the slot hosts<normal-acceptance-page>(the existing ward acceptances + waiting-list page). The route is/normal-acceptance. 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
doctorstable):Internal Medicine - role:
doctor
Idempotency: users.email UNIQUE → ON 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()callsGET /api/normal-acceptances,GET /api/admissions?...&type=normal,GET /api/wings,GET /api/rooms,GET /api/waiting-list,GET /api/patients,GET /api/doctorsin parallel.- Two tabs: Ward Patients (acceptances list, wing-filter chips at top) and Waiting List (priority-coded queue).
_isWardUsergetter (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 viashow()); 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
| Card | List API | Add API | Editable |
|---|---|---|---|
| Admission | passed in via show(acceptance) | (use Edit / Discharge on the board) | 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= | (use Quick Orders → Prescription) | no |
| Lab Orders | GET /api/service-requests?patient_id= filter category ~ “lab” | (use Quick Orders → Lab) | no |
| Imaging Orders | same, filter category ~ “rad|imag” | (use Quick Orders → Imaging) | no |
| Results | GET /api/diagnostic-reports?patient_id= | n/a | no |
| Care Plans | GET /api/care-plans?patient_id= | (use the care-plan workflow) | no |
| Consents | GET /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):
| 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 |
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:
| Tab | Endpoint | Receiving alert |
|---|---|---|
| Prescription | POST /api/prescriptions source=ward | Pharmacy queue |
| Lab | POST /api/service-requests category=laboratory | Laboratory department |
| Imaging | POST /api/service-requests category=radiology | Radiology 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-chartcomponent that accepts a wardKey + extra category descriptor — they currently duplicate ~600 lines each.
Last updated: 2026-04-26