14 KiB
VigilCare Dashboard — User Guide
The VigilCare Dashboard (vigilcare-dashboard/) is a Vue 3 single-page application that gives clinicians a live view of the virtual ward: who is on the floor, which patients are deteriorating, what alerts need action, and — on the patient detail screen — vital sign trends, NEWS2 history, and plain-language alert reasoning.
It reads from the VigilCare Clinical API over HTTP. It does not connect to Kafka, RabbitMQ, or PostgreSQL directly. Polling keeps the UI fresh while the API and background consumers do the clinical work.
Table of Contents
- What the dashboard does
- Prerequisites
- Quick start
- Screens
- Patient detail — clinical review mode
- Working with the simulator
- Configuration
- Development
- Troubleshooting
1. What the dashboard does
In a real hospital, nurses and physicians need a ward board: acuity at a glance, drill-down into one patient, and a way to act on alerts. This frontend implements that workflow against the VigilCare API.
| Capability | Where in the app | API backing |
|---|---|---|
| Ward overview — active patients sorted by NEWS2 risk | Virtual Ward (/ward) |
GET /encounters?status=ACTIVE |
| Department filter | Virtual Ward toolbar | Same list endpoint with department |
| Patient drill-down | Patient Detail (/patients/:encounterId) |
GET /encounters/{id}, observations, scores, orders |
| Latest vitals snapshot | Patient Detail — Vitals panel | GET /encounters/{id}/observations |
| NEWS2 current score | Patient Detail — Scores panel | GET /encounters/{id}/news2/current |
| Open alerts per patient | Patient Detail — Active Alerts | GET /encounters/{id}/alerts |
| Acknowledge / resolve alerts | Patient Detail or Alert Center | PATCH /alerts/{id}/acknowledge, /resolve |
| Sepsis bundle status | Patient Detail — Sepsis Bundle panel | GET /encounters/{id}/sepsis-bundle/current |
| Clinical orders | Patient Detail — Orders panel | GET /encounters/{id}/orders |
| Vital sign trend charts (HR, RR, BP, SpO₂, temp) | Patient Detail — Clinical review section | Observations (Chart.js) |
| NEWS2 score over time | Patient Detail — NEWS2 history chart | GET /encounters/{id}/news2/history |
| Alert reasoning (“why did this fire?”) | Patient Detail — click an alert row | Client-side rules + alert details |
| Medication context on alerts | Alert reasoning panel | GET /encounters/{id}/medications |
| Local replay controls | Patient Detail — replay bar | Scrubs fetched data (not live simulator control) |
| Global alert inbox | Alert Center (/alerts) |
GET /alerts with status filter |
| Clinician feedback on alerts | Alert Center, Patient Detail reasoning | Pinia + localStorage (client-side) |
| Feedback summary & export | Feedback Summary (/feedback) |
Aggregate stats; export JSON/CSV |
What it is not: a full EHR, authentication server, or simulator remote control. Replay controls scrub through data already loaded from the API; they do not pause or speed up the .NET simulator process. Alert feedback is stored in the browser until exported — see clinical-testing-guide.md for the clinician workflow.
2. Prerequisites
- Node.js 20+ and npm
- VigilCare Clinical API running at
http://localhost:5270(see root README — Getting Started) - CORS: API
Dashboardpolicy must allow the dev origin (http://localhost:5173by default)
Optional but recommended for demo data:
- VigilCare Simulator — replay a scenario so observations and alerts populate while you watch the dashboard update. See simulator-guide.md.
3. Quick start
From the repository root:
# Terminal 1 — infrastructure + API
docker compose up -d
dotnet run --project VigilCareClinicalAPI
# Terminal 2 — dashboard
cd vigilcare-dashboard
npm install
npm run dev
Open http://localhost:5173. The app redirects to Virtual Ward.
To populate live data, run a simulator scenario in a third terminal:
dotnet run --project VigilCare.Simulator -- replay \
VigilCare.Simulator/Scenarios/List/uti-sepsis-elderly-01.json \
--speed 60
Return to the dashboard, click a patient row, and watch vitals, charts, and alerts update every few seconds.
4. Screens
Virtual Ward (/ward)
The home screen lists active encounters as a responsive table (desktop) or card list (mobile).
- Patients are sorted by NEWS2 score (highest risk first).
- A badge shows how many patients have NEWS2 ≥ 7.
- Filter by department: All, ICU, General Medicine, Surgery.
- Click a row to open Patient Detail.
Data refreshes every 10 seconds via polling.
Alert Center (/alerts)
A hospital-wide alert inbox independent of any single patient.
- Filter tabs: Open, Acknowledged, Resolved, Escalated.
- Each card shows severity, alert type, details, and triggered time.
- Ack opens a confirmation modal (uses clinician ID from settings — default
DR-DEMO). - Resolve is available after acknowledge.
Use this when you need to triage alerts across the ward without opening each patient first.
Feedback Summary (/feedback)
Purpose: Research and evaluation view for structured clinician ratings on alerts.
- Aggregate stats: total ratings, % useful/would act, % false positive, timing issues.
- Breakdown by alert type (sepsis, NEWS2, heart rate warning, etc.).
- Recent feedback entries with notes.
- Export JSON / Export CSV for study analysis.
Ratings are collected via six buttons on each alert (see clinical-testing-guide.md for definitions aimed at doctors and nurses).
Patient Detail (/patients/:encounterId)
The clinical review screen. See §5 for the full breakdown.
5. Patient detail — clinical review mode
Layout top to bottom:
┌─────────────────────────────────────────────────────────┐
│ ← Ward Patient Name │
├─────────────────────────────────────────────────────────┤
│ Scores (NEWS2) │ Latest Vitals │ Active Alerts │
├─────────────────────────────────────────────────────────┤
│ Alert reasoning panel (after clicking an alert) │
├─────────────────────────────────────────────────────────┤
│ Orders │ Sepsis Bundle (if present) │
├─────────────────────────────────────────────────────────┤
│ Vital sign trend charts (5) │
│ NEWS2 score history chart │
│ Replay controls │
└─────────────────────────────────────────────────────────┘
Scores panel
Shows the current NEWS2 total, risk level, and encounter metadata (room/bed, department). If no score has been computed yet, displays —.
Vitals panel
Latest value per observation code (heart rate, respiratory rate, blood pressure, SpO₂, temperature, etc.), deduplicated to the most recent reading per code.
Active alerts
Open alerts for this encounter. Click a row to open the reasoning panel below the grid.
- Ack / Resolve buttons use
@click.stopso they do not trigger row selection. - Selected row is highlighted.
Alert reasoning
Explains why an alert fired in plain language:
| Alert type | Explanation shown |
|---|---|
WarningHeartRate, WarningSystolicBp, WarningTempC |
Threshold range + extracted value from details |
SepsisWarning |
SIRS criteria summary |
QsofaWarning |
qSOFA criteria summary |
News2Warning / News2Emergency |
NEWS2 risk tier |
RapidDeterioration |
Trajectory / rate-of-change |
| Unknown types | Falls back to raw details string |
If medications were administered within 90 minutes before the alert, a Recent medications block appears (supports reviewing medication-false-alarm-01 and similar scenarios).
Orders and sepsis bundle
- Orders — pending and resulted clinical orders for the encounter.
- Sepsis bundle — only rendered when a bundle exists; shows compliance status, deadline, and four treatment elements.
Clinical review charts
Five vital sign trend line charts (Chart.js via vue-chartjs):
- Heart rate, respiratory rate, systolic BP, SpO₂, temperature
- Responsive grid: 1 column (mobile) → 2 (
sm) → 3 (xl) - Respects
prefers-reduced-motion(animations disabled when OS setting is on)
NEWS2 history chart plots totalScore over time with per-point fill colors for risk bands (low / medium / high).
Replay controls
Local playback UI for reviewing scenario timelines:
- Pause / resume, speed presets (1×, 60×, 360×, Instant)
- Progress bar and elapsed time display
- Next Alert → cycles through open alerts chronologically, selects each for reasoning, and scrolls to the chart section
Replay state is client-side only. It does not send commands to the simulator.
Patient detail data polls every 5 seconds.
Clinician feedback (on alerts)
Below each alert in Alert Center and below the reasoning panel on Patient Detail:
| Rating | Meaning |
|---|---|
| Useful | Clinically appropriate alert |
| Would act | Would change management based on this alert |
| Too early | Right direction, wrong timing (too soon) |
| Too late | Problem existed; alert came too late |
| False positive | Should not have fired for this context |
| Missing context | Valid concern but insufficient information |
Tap + Note for optional free text. Ratings save automatically in the browser. Export from Feedback Summary when the session ends.
6. Working with the simulator
Typical demo flow:
- Start API + dashboard (§3).
- Replay a scenario at moderate speed (
--speed 60). - Open Virtual Ward — new or updated encounters appear as the simulator creates them.
- Click the patient — watch vitals and charts fill in as observations ingest.
- When alerts fire, click an alert row to read reasoning; try Next Alert → on the replay bar.
- Use Alert Center to acknowledge alerts globally.
Suggested scenarios:
| Scenario file | What to observe in the dashboard |
|---|---|
uti-sepsis-elderly-01.json |
SIRS/qSOFA alerts, sepsis bundle panel, rising acuity |
medication-false-alarm-01.json |
HR warnings with medication context in reasoning |
news2-deterioration-01.json (if present) |
NEWS2 history chart and score panel |
7. Configuration
| Setting | Location | Default |
|---|---|---|
| API base URL | vigilcare-dashboard/.env → VITE_API_URL |
http://localhost:5270 |
| Clinician ID (acknowledge) | Pinia settings store / localStorage key clinicianId |
DR-DEMO |
| Dark mode | Header toggle / localStorage key darkMode |
System preference |
| Ward poll interval | usePolling in WardDashboard.vue |
10 s |
| Patient detail poll | usePolling in PatientDetail.vue |
5 s |
Example .env:
VITE_API_URL=http://localhost:5270
8. Development
cd vigilcare-dashboard
npm install
npm run dev # http://localhost:5173
npm test # Vitest — composables + component tests
npm run build # production bundle
npm run preview # preview production build
Stack: Vue 3 (<script setup>), Vue Router, Pinia, Tailwind CSS v4, Chart.js + vue-chartjs.
Key directories:
vigilcare-dashboard/src/
├── api/ # HTTP client + encounter/clinical/alert fetchers
├── components/
│ ├── charts/ # VitalChart, TrendsGrid, News2History
│ ├── replay/ # ReplayControls
│ ├── alerts/ # AlertReasoning, AlertCard, …
│ ├── patient/ # VitalsPanel, ScoresPanel, AlertsList, …
│ └── ward/ # WardTable, PatientRow, PatientCard
├── composables/ # useChartData, useReplayControls, usePolling, chartFormat
├── stores/ # ward, alerts, settings (Pinia)
└── views/ # WardDashboard, PatientDetail, AlertCenter
Implementation plans: docs/plans/phase-17-plan.md (ward shell + detail), docs/plans/phase-18-plan.md (charts, replay, reasoning), docs/plans/phase-19-plan.md (clinician feedback).
Clinician testing: clinical-testing-guide.md — step-by-step guide for doctors and nurses participating in evaluation sessions.
9. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Blank ward / network errors in console | API not running or wrong URL | Start API; check VITE_API_URL |
| CORS error in browser | Dashboard origin not allowed | Add origin to API DashboardOptions in appsettings.json |
| Charts crash on mount | Chart data not unwrapped | Ensure VitalTrendChart wrapper is used (see TrendsGrid.vue) |
| No patients listed | No active encounters | Run simulator or use seeded API data |
| NEWS2 chart empty | Scores not computed yet | Wait for Kafka news2-scoring consumer after observations ingest |
| Acknowledge fails 400 | Invalid clinician ID | Set clinicianId in localStorage or settings store |
For API and infrastructure issues, see the root README and docker-compose-usage-and-troubleshooting.md.