Single source of truth for a fresh Claude session to implement the complete IPD flow.
Covers: entity contracts, status state machines, worklist nodes, per-stage UI routes & actions, row-click navigation, reject/cancel flows, and data sources.
1. End-to-End Patient Journey
OPD/ER Doctor Admission Staff IPD Nurse Doctor Cashier
──────────── ─────────────── ───────── ────── ───────
│ │ │ │ │
1. Create admission request │ │ │ │
POST /admissions │ │ │ │
admissionStatus=request │ │ │ │
approvalStatus=pending │ │ │ │
│ │ │ │ │
│ ┌────────────────────────────┤ │ │ │
│ │ 2a. Approve + reserve bed │ │ │ │
│ │ approvalStatus=reserved │ │ │ │
│ │ bed.status → reserved │ │ │ │
│ │ │ │ │ │
│ │ 2b. OR reject/cancel │ │ │ │
│ │ admissionStatus=cancelled│ │ │ │
│ │ bed.status → vacant │ │ │ │
│ └────────────────────────────┤ │ │ │
│ │ │ │ │
│ │ 3. Forward to ward │ │ │
│ │ approvalStatus= │ │ │
│ │ receiveOrders │ │ │
│ │ transferStatus=success │ │ │
│ │──────────────────────────────► │ │
│ │ │ │ │
│ │ 4. Receive patient │ │
│ │ admissionStatus=admitted │ │
│ │ bed.status → admitted │ │
│ │ encounter_class = IMP │ │
│ │ │ │ │
│ │ 5. Nursing assessment │ │
│ │ Vitals, fall risk, pain │ │
│ │ │ │ │
│ │ 6. Daily care ◄────────── 7. Doctor rounds │
│ │ MAR, vitals, Orders, progress notes │
│ │ procedures Discharge planning │
│ │ │ │ │
│ │ 8. Discharge prep ◄──── 9. Write discharge summary │
│ │ admissionStatus= │ │
│ │ discharged │ │
│ │ bed → discharge_pending │ │
│ │ bed → cleaning → vacant │ │
│ │ │ │ │
│ │ │ │ 10. Bill close │
│ │ │ │ billClosed │
│ │ │ │ = true │
2. Status State Machines
2.1 AdmissionStatus (MongoDB — canonical write truth)
┌─────────────┐
│ request │ Doctor creates admission request
└──────┬──────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌───────────────┐
│ pending │ │cancelled │ │ cancelRequest │
└─────┬────┘ └──────────┘ └───────┬───────┘
│ │
┌────────┼──────────┐ ┌──────┴──────┐
▼ ▼ ▼ │ cancelled │
┌────────────┐ ┌───────────────────┐ │ OR pending │
│appointment │ │receivePendingAdmit│ └─────────────┘
└─────┬──────┘ └───────┬───────────┘
│ │
└────────┬───────┘
▼
┌──────────┐
│ admitted │ Patient on ward
└─────┬────┘
│
┌────┴────┐
▼ ▼
┌────────────┐ ┌──────────┐
│transferred │ │discharged│ Terminal
└─────┬──────┘ └──────────┘
│
▼
admitted (at new ward)
Values: request, pending, appointment, admitted, receivePendingAdmit, discharged, cancelled, cancelRequest, transferred
2.2 ApprovalStatus (MongoDB)
pending → reserved → receiveOrders → receivePendingAdmit
└→ cancel
Values: pending, reserved, receiveOrders, receivePendingAdmit, cancel
2.3 Valid Transitions (Frontend — ADMISSION_STATUS_FLOW)
pending → [reserved, receiveOrders, cancelled, cancelRequest]
reserved → [receiveOrders, admitted, cancelled, cancelRequest]
receiveOrders → [admitted, cancelled, cancelRequest]
admitted → [transferred, discharged]
transferred → [admitted, discharged]
discharged → [] ← terminal
cancelled → [] ← terminal
cancelRequest → [cancelled, pending] ← can revert to pending
Source: web/packages/adt-kit/src/admission/admissionStatusConfig.ts
2.4 Bed Status (Supabase)
┌───────────┐
┌───────►│ vacant │◄──────────┐
│ └─────┬─────┘ │
│ │ │
│ ┌──────────▼──────────┐ ┌──┴────────────┐
│ │ reserved │ │out_of_service │
│ └──────────┬──────────┘ └───────────────┘
│ │
│ ┌──────────▼──────────┐
│ │ admitted │
│ └──────────┬──────────┘
│ │
│ ┌──────────▼──────────┐
└───┤ discharge_pending │
└─────────────────────┘
Values: vacant, reserved, admitted, discharge_pending, cleaning, out_of_service
2.5 Status Groups (Frontend Filter)
| Group |
Statuses |
UI Context |
| Active (pre-admission) |
pending, reserved, receiveOrders |
Admission request pipeline tabs |
| In Care (inpatient) |
admitted, transferred |
IPD nurse dashboard Tab 0 |
| Terminal |
discharged, cancelled, cancelRequest |
Discharged / cancelled tabs |
| Cancellable |
pending, reserved, receiveOrders |
Show cancel button |
3. Worklist Node Mapping (MASTER_WORKFLOW_NODES)
3.1 Admission Request Pipeline
| Worklist Node |
Label TH |
Label EN |
Maps to |
Transitions |
ipd-pending-bed |
รอจองเตียง |
Pending Bed Reservation |
approvalStatus: pending |
→ bed-reserved, cancelled |
ipd-bed-reserved |
จองเตียงสำเร็จ |
Bed Reserved |
approvalStatus: reserved |
→ ready-to-admit, cancelled |
ipd-ready-to-admit |
รอแอดมิท |
Ready to Admit |
approvalStatus: receiveOrders |
→ admitted, cancelled |
ipd-admitted |
แอดมิทแล้ว |
Admitted |
admissionStatus: admitted |
→ nursing-assessment, doctor-round, discharge-summary, cancelled |
ipd-cancelled |
ยกเลิกการจอง |
Admission Cancelled |
admissionStatus: cancelled |
terminal |
3.2 Nurse In-Ward Workflow (parallel, starts after ipd-admitted)
| Worklist Node |
Label TH |
Label EN |
Transitions |
ipd-nursing-assessment |
ประเมินผลทางการพยาบาล |
Nursing Assessment |
→ nurse-rounds, medication-admin, nurse-handover, nurse-discharge-prep |
ipd-nurse-rounds |
ราวด์พยาบาล |
Nurse Rounds |
→ medication-admin, nurse-handover, nurse-discharge-prep |
ipd-medication-administration |
ให้ยาผู้ป่วย |
Medication Administration |
→ nurse-rounds, nurse-handover, nurse-discharge-prep |
ipd-nurse-handover |
ส่งเวรพยาบาล |
Nurse Handover |
→ nurse-rounds, medication-admin, nurse-discharge-prep |
ipd-nurse-discharge-prep |
เตรียมจำหน่าย (พยาบาล) |
Nurse Discharge Prep |
→ finished |
3.3 Doctor In-Ward Workflow (parallel, starts after ipd-admitted)
| Worklist Node |
Label TH |
Label EN |
Transitions |
ipd-doctor-round |
ราวด์แพทย์ |
Doctor Round |
→ doctor-orders, progress-note, discharge-summary |
ipd-doctor-orders |
สั่งการรักษา |
Doctor Orders |
→ doctor-round, progress-note, discharge-summary |
ipd-doctor-progress-note |
บันทึกการรักษา |
Progress Note |
→ doctor-round, doctor-orders, discharge-summary |
ipd-discharge-summary |
สรุปการจำหน่าย |
Discharge Summary |
→ finished |
3.4 Per-Patient Command Center (6 Steps)
| Step |
Node(s) |
Label TH |
Label EN |
Bypassable |
| 1 |
ipd-admitted |
รับเข้าหอผู้ป่วย |
Admission |
No |
| 2 |
ipd-nursing-assessment |
ประเมินพยาบาล |
Assessment |
No |
| 3 |
ipd-nurse-rounds + ipd-medication-administration + ipd-doctor-round + ipd-doctor-orders |
การดูแลประจำวัน |
Active Care |
No |
| 4 |
Procedure miniapps |
หัตถการ |
Procedures |
Yes |
| 5 |
ipd-nurse-discharge-prep + ipd-discharge-summary |
วางแผนจำหน่าย |
Discharge Planning |
No |
| 6 |
Bill reconciliation |
ปิดเคส |
Closeout |
No |
Route: /ipd/patient/:encounterId/command-center
Source: web/src/containers/ipd-patient-command-center/types.ts
4.1 Admission Request Pipeline (/ipd/admission-request)
Tab 0: Pending (รอจองเตียง / approvalStatus: pending)
| Action |
Label TH |
API Call |
Result |
| Reserve bed |
จองเตียง |
PUT /admissions/:_id { approvalStatus: 'reserved', bedName, wardId } |
→ reserved |
| Cancel request |
ยกเลิกการจอง |
cancelRequestAdmitStatus(id) → PUT { admissionStatus: 'cancelRequest' } |
→ cancelRequest |
| View details |
รายละเอียดการจองเตียง |
Opens dialog requestforadmin |
— |
| View bed details |
รายละเอียดเตียง |
Opens dialog beddetails |
— |
| Treatment rights |
สิทธิการรักษา |
Opens dialog rightoftreatment |
— |
| Admission history |
ประวัติการแอดมิด |
Opens dialog admissionhistory |
— |
| Patient Timeline |
Patient Timeline |
Navigate /patient-profile/:patientId |
— |
| E-Form |
E-Form |
Opens eform dialog |
— |
Tab 1: Reserved (จองเตียงสำเร็จ / approvalStatus: reserved)
| Action |
Label TH |
API Call |
Result |
| Forward to ward |
ส่งต่อแอดมิท |
updateTransferStatus(id) → transferStatus: 'success' |
→ receiveOrders |
| Confirm bed |
ยืนยันเตียง |
Opens dialog beddetails (confirm/change bed) |
— |
| Cancel reservation |
ยกเลิกการจอง |
cancelRequestAdmitStatus(id) |
→ cancelRequest |
Tab 2: Orders Received (รอแอดมิท / approvalStatus: receiveOrders)
| Action |
Label TH |
API Call |
Result |
| Admit patient |
รับเข้าหอ |
PUT /admissions/:_id { admissionStatus: 'admitted' } |
→ admitted |
| Cancel |
ยกเลิก |
cancelRequestAdmitStatus(id) |
→ cancelRequest |
| Transfer patient |
เคลื่อนย้ายผู้ป่วย |
Opens DialogPatientTransfer |
— |
Tab 3: Cancelled (ยกเลิก / admissionStatus: cancelled)
| Action |
Label TH |
API Call |
Result |
| Print |
Print |
— |
— |
| (read-only) |
— |
— |
terminal state |
4.2 IPD Nurse Dashboard (/ipd/work-list)
Tab 0: Admitted (ผู้ป่วยที่พักอยู่ในหอ)
Row click → /ipd/patient/:encounterId/command-center
| Row Action |
Context |
| View vital signs |
Inline order status icons (lab, imaging, medication, procedure, pharmacy) |
| Bed transfer |
WardViewPanel DnD or transfer dialog |
| View orders |
Order status column click |
| More menu (⋮) |
Opens patient command center |
Tab 1: Pending Admit (ผู้ป่วยที่ยังไม่ได้รับเข้าหอ)
Row click → /ipd/admission-request
Filter: approvalStatus: 'pending' | 'receiveOrders'
Tab 2: Reserved (ผู้ป่วยที่มีการจองเตียง)
Row click → /ipd/admission-request
Filter: approvalStatus: 'reserved'
Tab 3: Discharged Open Bill (ผู้ป่วยจำหน่ายที่ยังไม่ปิดบัญชี)
Row click → /ipd/discharge-cockpit?encounterId=...&patientId=...
Filter: admissionStatus: 'discharged', billClosed: false
| Action |
Context |
| View discharge summary |
FHIR R4 cockpit (19-card EMRAM Stage 6) |
| View billing |
Billing reconciliation |
Tab 4: Discharged Closed Bill (ผู้ป่วยจำหน่ายที่ปิดบัญชีแล้ว)
Row click → /ipd/discharge-cockpit (read-only)
Filter: admissionStatus: 'discharged', billClosed: true
Tab 5: Food Orders (ผู้ป่วยที่มีรายการ food order)
Not yet implemented
4.3 IPD Patient Command Center (/ipd/patient/:encounterId/command-center)
| Step |
Primary Action |
Secondary Actions |
| 1 Admission |
View admission context (AN, ward, bed, doctor) |
Edit bed assignment, transfer |
| 2 Assessment |
Complete nursing assessment form |
Fall risk, pressure injury, pain score |
| 3 Active Care |
Vitals entry, MAR, order management |
Lab/imaging/medication/procedure orders |
| 4 Procedures |
Surgical/procedural workflow |
Bypass if no procedures |
| 5 Discharge |
Write discharge summary, clearances |
Discharge cockpit (FHIR R4) |
| 6 Closeout |
Bill reconciliation, coding |
Medical certificate, ICD coding |
4.4 Discharge Cockpit (/ipd/discharge-cockpit)
FHIR R4 discharge summary — 19-card EMRAM Stage 6 view.
Also available as modules.IpdDischargeCockpit in patient-profile DynamicCoreApp.
5. Reject / Cancel Flows
5.1 Cancel Request (initiated by requestor)
Any CANCELLABLE status (pending, reserved, receiveOrders)
│
▼ cancelRequestAdmitStatus(admissionId)
│ → PUT /admissions/:_id { admissionStatus: 'cancelRequest' }
│
▼ admissionStatus = cancelRequest
│
├──► Admin approves cancel → admissionStatus = cancelled (terminal)
│ → bed.status → vacant (snapshots cleared)
│ → ipd_admissions.status = cancelled
│ → department_queues.status = CANCELLED
│
└──► Admin reverts → admissionStatus = pending (back to start)
5.2 Direct Cancel (by admin/system)
Any CANCELLABLE status (pending, reserved, receiveOrders)
│
▼ updateAdmissions({ _id, obj: { admissionStatus: 'cancelled' } })
│
▼ admissionStatus = cancelled (terminal)
→ bed.status → vacant (snapshots cleared)
→ ipd_admissions.status = cancelled
→ department_queues.status = CANCELLED
Reserved bed patient
│
▼ "ยกเลิกการจอง" button in actionMenuWithoutTab3
│
▼ Opens confirmation dialog
│ → mutateCancelAdmission(patientInfo._id)
│ → cancelRequestAdmitStatus(id)
│
▼ admissionStatus = cancelRequest → cancelled
→ bed.status → reserved → vacant
5.4 Discharge Flow
Admitted patient
│
▼ Doctor writes discharge summary
│ ipd-discharge-summary node
│
▼ Nurse discharge prep
│ ipd-nurse-discharge-prep node
│ bed.status → discharge_pending
│
▼ PUT /admissions/:_id { admissionStatus: 'discharged', dischargeDate, dischargeDisposition }
│
▼ Orchestrator side effects:
│ → bed.status → cleaning → vacant (snapshots cleared)
│ → ipd_admissions.status = discharged, discharge_date set
│ → encounter_journey_cache: admission_context updated
│ → department_queues.status = COMPLETED
│
▼ Patient moves to Tab 3 (discharged, bill open)
│
▼ Cashier closes bill
│ financial_summary.billClosed = true
│
▼ Patient moves to Tab 4 (discharged, bill closed)
6. Tab Count Data Sources
| Tab |
API |
Extraction |
Ward-Filtered? |
| 0 (admitted) |
listAllAdmissions({ admissionStatus: 'admitted', subClinic: wardId, pageSize: 1 }) |
(await response).data?.total |
Yes |
| 1 (pending admit) |
getAmountAdmissionApi({ startAt: undefined, endAt: undefined }) |
.data.pending + .data.receiveOrders |
No (global) |
| 2 (reserved) |
getAmountAdmissionApi() |
.data.reserved |
No (global) |
| 3 (discharged open) |
listAllAdmissions({ admissionStatus: 'discharged', subClinic: wardId, pageSize: 1 }) |
(await response).data?.total |
Yes |
| 4 (discharged closed) |
Not yet available |
Needs billClosed filter on backend |
— |
Note on callAPI response chain:
callAPI does return response.data (unwraps Axios envelope)
- Backend returns
{ data: { total, rows, ... } } — one more .data wrapper
- So
(await response).data?.total gives the count
7. Row Click Navigation
Implementation: handleRowClick in MainTab.tsx
activeTab |
Navigate to |
Parameters |
| 0 (admitted) |
/ipd/patient/:encounterId/command-center |
encounterId from row.encounterId || row.encounter_id || row.encounterRef?._id |
| 1 (pending) |
/ipd/admission-request?admissionId=:id&patientId=:pid |
row._id || row.id, row.patientID?._id || row.patient_id |
| 2 (reserved) |
/ipd/admission-request?admissionId=:id&patientId=:pid |
same as Tab 1 |
| 3 (discharged open) |
/ipd/discharge-cockpit?encounterId=:eid&patientId=:pid |
encounter + patient IDs |
| 4 (discharged closed) |
/ipd/discharge-cockpit?encounterId=:eid&patientId=:pid (read-only) |
same as Tab 3 |
Alternative for Tab 3/4: Navigate to patient-profile with DischargeCockpit module:
/patient-profile/:patientId → DynamicCoreApp IPD_DISCHARGE_COCKPIT
8. Entity Contracts (Compact)
Admission (MongoDB)
| Field |
Type |
Key |
_id |
ObjectId |
PK |
encounterId |
ObjectId |
FK → Encounter |
patientID |
ObjectId |
FK → Patient |
admissionStatus |
AdmissionStatus |
§2.1 |
approvalStatus |
ApprovalStatus |
§2.2 |
transferStatus |
pending | success |
§2.3 |
wardId / ward |
ObjectId |
FK → SubClinic |
bedName / bedLabel |
string |
Bed display name |
admitDateTime |
Date |
When admitted |
dischargeDate |
Date |
When discharged |
visitType |
AdmissionType |
ELECTIVE / EMERGENCY / ROUTINE / etc. |
priority |
string |
ROUTINE / URGENT / STAT |
isBedReserved |
‘Y’ / ‘N’ |
|
REST: POST /admissions, PUT /admissions/:_id
Bed (Supabase — write truth for occupancy)
| Column |
Type |
Notes |
id |
uuid |
PK |
ward_id |
text |
Ward identifier |
name |
text |
Display label (e.g. “A-101”) |
bed_type |
text |
standard / icu / ccu |
status |
text |
§2.4 — CHECK constraint |
encounter_id |
text |
Current encounter |
admission_id |
text |
Current admission |
patient_id |
text |
Current patient |
hn_snapshot |
text |
Denormalized |
an_snapshot |
text |
Denormalized |
patient_name_snapshot |
text |
Denormalized |
IPD Admission (Supabase — read model)
| Column |
Type |
Notes |
id |
uuid |
PK |
admission_number |
text |
AN |
status |
text |
planned / in-progress / reserved / pending-discharge / discharged / cancelled |
patient_id |
text |
MongoDB ObjectId |
ward_id |
text |
Ward |
bed_id |
uuid |
FK → bed.id |
admission_date |
timestamptz |
|
discharge_date |
timestamptz |
|
los_days |
integer |
|
9. Orchestrator Side-Effect Table
| Admission Status |
Bed Effect |
IPD Admission |
Queue Effect |
request / pending |
— |
— |
dept_type=admission, status=WAITING |
reserved |
bed → reserved, snapshots set |
upsert, status=reserved |
status=ACTIVE |
receiveOrders |
— |
— |
— |
admitted |
bed → admitted |
status=in-progress |
dept_type=ipd, status=ACTIVE |
discharged |
bed → vacant, snapshots cleared |
status=discharged |
status=COMPLETED |
cancelled |
bed → vacant, snapshots cleared |
status=cancelled |
status=CANCELLED |
10. Data Architecture
Frontend action → Backend REST API → MongoDB write + NATS event
→ Supabase hospital_events INSERT
→ encounter-orchestrator (Deno Edge Function)
→ updates 3 read models atomically:
1. encounter_journey_cache (clinical context)
2. bed (occupancy + patient snapshots)
3. ipd_admissions (denormalized dashboard rows)
→ postgres_changes realtime push
→ React hooks re-render UI
Dual Data Source Resolution
| Field |
MongoDB (REST) |
Supabase |
Use |
| Ward ID |
ward._id (ObjectId) |
bed.ward_id (text slug) |
Ward selector merges both |
| Bed ID |
bed._id (ObjectId) |
bed.id (UUID) |
Grid uses Supabase; REST uses MongoDB |
| Patient ID |
patient._id (ObjectId) |
ipd_admissions.patient_id (text) |
Cross-reference by HN |
| Encounter ID |
encounter._id (ObjectId) |
encounter_journey_cache.encounter_id (text) |
String comparison |
| Admission Number |
admission.an |
ipd_admissions.admission_number |
Unique business key |
11. Frontend APIs
| Function |
Location |
Purpose |
listAllAdmissions(params) |
src/services/ever-administration/admissions.service.ts:42 |
Paginated admission list (MongoDB) |
getAmountAdmissionApi({ startAt, endAt }) |
Same file :276 |
Approval-status counts: { pending, reserved, receiveOrders, cancelled } |
updateAdmissions({ _id, obj }) |
Same file :160 |
Update admission fields |
cancelRequestAdmitStatus(id) |
Same file :247 |
Set admissionStatus: 'cancelRequest' |
updateTransferStatus(id) |
Same file |
Set transferStatus: 'success' |
listBedApi({ ward, page, pageSize }) |
src/services/ever-administration/bed.service.ts |
Bed list (MongoDB) |
bedStatusApi.transferAtomic(...) |
src/services/medbase/bedStatus.medbase.ts |
Supabase RPC bed transfer |
ipdWardService.* |
src/services/supabase/ipdWard.supabase.service.ts |
Supabase IPD queries |
12. Key Files Index
Routes
| File |
Purpose |
web/src/routes/IPDRoutes.tsx |
All /ipd/* route definitions |
Status & Config
| File |
Purpose |
web/packages/adt-kit/src/admission/admissionStatusConfig.ts |
Status enum, labels, chip colors, ADMISSION_STATUS_FLOW transitions, status groups |
web/packages/medical-kit/src/medical-worklist/workflowState.ts |
MASTER_WORKFLOW_NODES — IPD admission + nurse + doctor nodes |
web/src/containers/ipd-patient-command-center/types.ts |
6-step command center definitions |
Dashboard
| File |
Purpose |
web/packages/medical-kit/src/ipd-system/hooks/useIpdDashboard.ts |
Dashboard data hook (MongoDB + Supabase merge, tab counts) |
web/packages/medical-kit/src/ipd-system/ipd-management/components/dashboard/MainTab.tsx |
Dashboard orchestrator, handleRowClick (needs navigation wiring) |
web/packages/medical-kit/src/ipd-system/ipd-management/components/dashboard/WardViewPanel.tsx |
DnD bed grid |
web/packages/medical-kit/src/ipd-system/ipd-management/components/dashboard/Profile.tsx |
Patient profile sidebar |
Admission Request
| File |
Purpose |
web/packages/adt-kit/src/admission/components/list-patient-request-admission/RequestAdmission.tsx |
Admission pipeline list — approve/reject/cancel/forward actions |
web/packages/adt-kit/src/admission/components/list-patient-request-admission/PatientListRequestAdmission.tsx |
Tab wrapper with approval-status counts |
web/packages/miniapps/admission-request/RequestForAdmin.tsx |
Admission request form |
web/packages/miniapps/admission-request/WardBedVisualizer.tsx |
Visual bed picker |
Discharge
| File |
Purpose |
web/src/containers/ipd-discharge-cockpit/page.tsx |
FHIR R4 discharge summary cockpit |
web/src/containers/ipd-discharge-pipeline/page.tsx |
7-phase discharge pipeline |
Backend
| File |
Purpose |
services/administration/.../admission/admission.service.ts |
Admission CRUD (MongoDB) |
services/administration/.../admission/admission.controller.mixin.ts |
REST endpoints + event emission |
packages/platform-api-schema/src/administration/admission/entity/AdmissionStatus.ts |
Canonical status enum |
infrastructure/medbase/functions/encounter-orchestrator/index.ts |
Read model projection |
13. Invariants
- MongoDB is write truth for clinical admission — all status transitions go through
PUT /admissions/:_id
- Bed table is write truth for occupancy — only orchestrator +
transfer_bed_atomic RPC write to it
- Frontend never writes to Supabase read model tables — use backend APIs
- encounter_class = ‘IMP’ set by orchestrator on admission events
- bed_status_log is append-only — UPDATE/DELETE blocked by trigger
- transfer_bed_atomic is atomic — both beds locked FOR UPDATE in one transaction
- Ward IDs are heterogeneous — MongoDB ObjectIds vs Supabase text slugs; dashboard merges both
- Realtime is eventual — postgres_changes ~100ms; UI handles brief inconsistency
- Patient snapshots must be cleared on discharge/transfer-out
- CANCELLABLE_STATUSES = [pending, reserved, receiveOrders] — only these show cancel button
14. Implementation Tasks (for executing session)
P0 — Wire row click navigation ✅
- [x] Add
useNavigate() to MainTab.tsx
- [x] Branch
handleRowClick on activeTab per §7
- [x] Extract
encounterId from dual-source row data
P1 — Verify tab counts ✅
- [x] Confirm 3 independent count queries in
useIpdDashboard.ts produce correct numbers
- [ ] Test with real backend data (admitted, discharged, approval counts)
P2 — Discharge cockpit wiring ✅
- [x] Ensure
/ipd/discharge-cockpit accepts encounterId + patientId query params
- [x] Connect Tab 3/4 row click to discharge cockpit
P3 — Cancel flow from dashboard ✅
- [x] Add cancel action to Tab 1/2 row context menu
- [x] Wire
cancelRequestAdmitStatus API
- [x] Refresh tab counts after cancel
P4 — Tab 4 (bill closed) backend ✅
- [x] Add
billClosed filter param to listAllAdmissions API
- [x] Separate Tab 3 (open bill) from Tab 4 (closed bill) counts
P5 — Admission request deep linking ✅
- [x] Ensure
/ipd/admission-request accepts admissionId query param to auto-select patient
- [x] Connect Tab 1/2 row click to admission request with pre-selection