632 lines
29 KiB
Markdown
632 lines
29 KiB
Markdown
# 📄 Product Requirements Document (PRD) — Contextual UI EPD
|
|
|
|
**Projectnaam:** Contextual UI EPD — "Het Slimme EPD"
|
|
**Versie:** v1.0
|
|
**Datum:** 23-12-2024
|
|
**Auteur:** Colin Lit
|
|
|
|
---
|
|
|
|
## 1. Doelstelling
|
|
|
|
🎯 **Doel van deze sectie:** Beschrijf waarom dit product of prototype wordt gebouwd en wat het beoogde resultaat is.
|
|
|
|
### Primair doel
|
|
|
|
Uitbreiden van het bestaande Speedrun EPD met **Contextual UI**: een systeem waarin voorgedefinieerde interface-componenten **automatisch verschijnen op basis van context** — wie je bent, welke patiënt actief is, welk moment van de dag het is, en wat je probeert te doen.
|
|
|
|
### Het kernprincipe
|
|
|
|
> **"Pre-built components, smart triggers"**
|
|
>
|
|
> We genereren geen UI on-the-fly (te onvoorspelbaar voor zorg), maar tonen **geteste bouwblokken op het juiste moment**. De AI zit in het *bepalen wanneer* en het *vullen van content*, niet in het genereren van interface-elementen.
|
|
|
|
### Het contrast met traditionele EPD's
|
|
|
|
| Aspect | Traditioneel EPD | Contextual UI EPD |
|
|
|--------|------------------|-------------------|
|
|
| Navigatie | 47 menu-items, tabbladen, submenu's | Context bepaalt wat je ziet |
|
|
| Interface | Altijd alles zichtbaar | Alleen wat nu relevant is |
|
|
| Timing | Gebruiker zoekt zelf | Systeem toont proactief |
|
|
| Klikken | 12 klikken voor rapportage | 1 zin of automatisch |
|
|
| Context | Gebruiker moet onthouden | Systeem begrijpt situatie |
|
|
|
|
### Secundaire doelen
|
|
|
|
- Demonstreren van "intelligent interface" concept voor gesprekken met Nedap, Medicore, etc.
|
|
- LinkedIn content over next-gen EPD interfaces
|
|
- Technische showcase van context-aware React componenten
|
|
- Valideren of "proactieve UI" gewaardeerd wordt door zorgprofessionals
|
|
|
|
### Relatie met Speedrun EPD
|
|
|
|
Dit is **geen nieuw product** maar een uitbreiding op de bestaande codebase:
|
|
- Hergebruik van alle database schemas
|
|
- Hergebruik van bestaande API routes en AI-functionaliteit
|
|
- Hergebruik van UI componenten (speech recorder, editors, etc.)
|
|
- Toevoeging van Context Engine en Trigger System
|
|
|
|
---
|
|
|
|
## 2. Doelgroep
|
|
|
|
🎯 **Doel:** Schets wie de eindgebruikers, stakeholders en testers zijn.
|
|
|
|
### Primaire gebruikers
|
|
|
|
| Rol | Behoeften | Pijnpunten vandaag |
|
|
|-----|-----------|-------------------|
|
|
| **Verpleegkundige** | Snelle notities tussen zorgmomenten | 40% tijd aan administratie, zoeken naar juiste scherm |
|
|
| **SPV/Behandelaar** | Rapportage na gesprek, overdracht | 20 min typen na crisis-interventie |
|
|
| **Teamleider** | Overzicht, overdracht ontvangen | Informatie verspreid over schermen |
|
|
|
|
### Secundaire stakeholders
|
|
|
|
| Rol | Interesse |
|
|
|-----|-----------|
|
|
| **ICT Manager** | Minder training nodig, snellere adoptie |
|
|
| **Product Owner (demo)** | AI-toegevoegde waarde zien |
|
|
| **Developer (inspiratie)** | Context-aware UI patterns leren |
|
|
|
|
### Gebruikerscontext
|
|
|
|
De interface moet werken in situaties waar:
|
|
- Handen bezet zijn (handschoenen, zorghandelingen)
|
|
- Tijd schaars is (tussen patiënten door)
|
|
- Concentratie elders ligt (na emotioneel gesprek)
|
|
- Meerdere patiënten tegelijk aandacht vragen
|
|
|
|
---
|
|
|
|
## 3. Kernfunctionaliteiten (MVP-scope)
|
|
|
|
🎯 **Doel:** Afbakenen van de minimale werkende functies.
|
|
|
|
### 3.1 Architectuur: De Drie Lagen
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ LAAG 1: CONTEXT ENGINE │
|
|
│ Houdt bij: gebruiker, patiënt, tijd, dienst, recente │
|
|
│ acties. Zustand store + Supabase realtime. │
|
|
└─────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ LAAG 2: TRIGGER SYSTEM │
|
|
│ Rules engine die bepaalt wanneer welk component │
|
|
│ verschijnt. Combinatie van tijd, events, en intent. │
|
|
└─────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ LAAG 3: PRE-BUILT COMPONENTS │
|
|
│ Geteste UI-blokken die door triggers worden getoond │
|
|
│ en automatisch worden gevuld met relevante data. │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### 3.2 MVP Componenten
|
|
|
|
| # | Component | Trigger | Data/AI | Prioriteit |
|
|
|---|-----------|---------|---------|------------|
|
|
| 1 | **Command Input** | Altijd zichtbaar (centraal) | Voice + text | Must |
|
|
| 2 | **DagnotatieBlock** | Intent "notitie" of voice | Pre-fill patiënt, categorie | Must |
|
|
| 3 | **ZoekenBlock** | Intent "zoek" of patiëntnaam | Fuzzy search results | Must |
|
|
| 4 | **PatientContextCard** | Patiënt geselecteerd | Laatste rapportages, alerts | Must |
|
|
| 5 | **RapportageBlock** | Intent "gesprek" of "rapportage" | AI-samenvatting optie | Should |
|
|
| 6 | **OverdrachtPanel** | Tijd = einde dienst OF intent | AI-samenvatting per patiënt | Should |
|
|
| 7 | **AgendaContextCard** | Afspraak binnen 15 min | Patiënt + laatste contact | Could |
|
|
| 8 | **FallbackPicker** | Lage intent confidence | Grid met alle opties | Must |
|
|
|
|
### 3.3 Context Engine Specificatie
|
|
|
|
```typescript
|
|
interface ContextState {
|
|
// Gebruiker
|
|
currentUser: {
|
|
id: string;
|
|
name: string;
|
|
role: 'verpleegkundige' | 'behandelaar' | 'teamleider';
|
|
};
|
|
|
|
// Dienst
|
|
currentShift: {
|
|
type: 'ochtend' | 'middag' | 'avond' | 'nacht';
|
|
startTime: Date;
|
|
endTime: Date;
|
|
patients: string[]; // IDs van toegewezen patiënten
|
|
};
|
|
|
|
// Actieve patiënt (sticky)
|
|
activePatient: {
|
|
id: string;
|
|
name: string;
|
|
lastContact: Date;
|
|
alerts: Alert[];
|
|
} | null;
|
|
|
|
// Recente acties
|
|
recentActions: Action[]; // Laatste 5-10
|
|
|
|
// Tijd-gevoelige context
|
|
upcomingAppointment: Appointment | null; // Binnen 30 min
|
|
shiftEndingSoon: boolean; // < 1 uur tot einde
|
|
}
|
|
```
|
|
|
|
### 3.4 Trigger Rules Specificatie
|
|
|
|
| Trigger Type | Conditie | Actie | Prioriteit |
|
|
|--------------|----------|-------|------------|
|
|
| **Intent** | Voice/text input geclassificeerd | Open bijbehorend block | 1 (hoogste) |
|
|
| **Patient Select** | Patiënt aangeklikt/gevonden | Toon PatientContextCard | 2 |
|
|
| **Time: Appointment** | Afspraak binnen 15 min | Toon AgendaContextCard | 3 |
|
|
| **Time: Shift End** | < 1 uur tot einde dienst | Suggestie OverdrachtPanel | 4 |
|
|
| **Fallback** | Intent confidence < 0.7 | Toon FallbackPicker | 5 (laagste) |
|
|
|
|
### 3.5 Intent Classification
|
|
|
|
**Two-tier approach voor snelheid:**
|
|
|
|
```typescript
|
|
// Tier 1: Local keyword matching (< 10ms)
|
|
const quickMatch = (input: string): IntentResult | null => {
|
|
const patterns = [
|
|
{ regex: /notitie|dagnotitie|noteren/i, intent: 'dagnotitie' },
|
|
{ regex: /zoek|vind|wie is/i, intent: 'zoeken' },
|
|
{ regex: /overdracht|dienst\s*(eindigt|klaar)/i, intent: 'overdracht' },
|
|
{ regex: /rapport|gesprek|consult/i, intent: 'rapportage' },
|
|
{ regex: /afspraken?|agenda|planning/i, intent: 'agenda' },
|
|
];
|
|
// ... matching logic
|
|
};
|
|
|
|
// Tier 2: Claude API (fallback, < 500ms)
|
|
const aiClassify = async (input: string): Promise<IntentResult> => {
|
|
// Alleen aangeroepen als quickMatch null of low confidence
|
|
};
|
|
```
|
|
|
|
**Entity Extraction:**
|
|
|
|
Naast intent ook extraheren:
|
|
- `patient_name`: "Jan de Vries", "mevrouw Jansen"
|
|
- `category`: "medicatie", "ADL", "incident"
|
|
- `time_reference`: "vandaag", "gisteren", "afgelopen dienst"
|
|
|
|
---
|
|
|
|
## 4. Gebruikersflows (Demo- of MVP-flows)
|
|
|
|
🎯 **Doel:** Laten zien hoe de gebruiker stap-voor-stap door het systeem gaat.
|
|
|
|
### Flow 1: Snelle Dagnotitie via Voice (30 seconden)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ 1. Gebruiker opent Command Center │
|
|
│ → Ziet: lege input, context "Ochtend | 8 patiënten" │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 2. Spreekt: "Notitie Jan de Vries medicatie gegeven" │
|
|
│ → Deepgram transcribeert real-time │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 3. System analyseert: │
|
|
│ → Intent: dagnotitie (confidence 0.95) │
|
|
│ → Patient: "Jan de Vries" → ID lookup │
|
|
│ → Category: "Medicatie" │
|
|
│ → Text: "medicatie gegeven" │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 4. DagnotatieBlock verschijnt: │
|
|
│ → Patient: Jan de Vries ✓ (pre-filled) │
|
|
│ → Categorie: Medicatie ✓ (pre-filled) │
|
|
│ → Tekst: "medicatie gegeven" ✓ (pre-filled) │
|
|
│ → [Opslaan] knop highlighted │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 5. Gebruiker: review → klik Opslaan │
|
|
│ → Toast: "Notitie opgeslagen" │
|
|
│ → Block verdwijnt │
|
|
│ → Recent badge: "Jan - Medicatie" verschijnt │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Flow 2: Patiënt Opzoeken + Context (45 seconden)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ 1. Gebruiker typt: "Jan" │
|
|
│ → Intent: zoeken │
|
|
│ → Query: "Jan" │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 2. ZoekenBlock verschijnt met matches: │
|
|
│ ┌──────────────────────────────────────────────┐ │
|
|
│ │ Jan de Vries │ 15-03-1965 │ Laatst: 2u │ │
|
|
│ │ Jan Bakker │ 22-08-1978 │ Laatst: 1d │ │
|
|
│ │ Jantine Smit │ 04-11-1990 │ Laatst: 3d │ │
|
|
│ └──────────────────────────────────────────────┘ │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 3. Gebruiker klikt "Jan de Vries" │
|
|
│ → activePatient wordt gezet │
|
|
│ → ZoekenBlock sluit │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 4. PatientContextCard verschijnt: │
|
|
│ ┌──────────────────────────────────────────────┐ │
|
|
│ │ JAN DE VRIES (59) │ │
|
|
│ │ ───────────────────────────────────────── │ │
|
|
│ │ Laatste contact: 2 uur geleden │ │
|
|
│ │ │ │
|
|
│ │ Recente notities: │ │
|
|
│ │ • 09:15 Medicatie uitgereikt │ │
|
|
│ │ • Gisteren: Goed gesprek over ontslag │ │
|
|
│ │ │ │
|
|
│ │ ⚠️ Let op: 2 valincidenten deze week │ │
|
|
│ │ │ │
|
|
│ │ [Notitie] [Rapportage] [Behandelplan] │ │
|
|
│ └──────────────────────────────────────────────┘ │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 5. Gebruiker klikt [Notitie] │
|
|
│ → DagnotatieBlock opent met Jan pre-filled │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Flow 3: Automatische Overdracht Suggestie (proactief)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ Context: Het is 15:15, dienst eindigt om 16:00 │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 1. System detecteert: shiftEndingSoon = true │
|
|
│ → Subtiele banner verschijnt: │
|
|
│ ┌──────────────────────────────────────────────┐ │
|
|
│ │ 🕐 Dienst eindigt over 45 min │ │
|
|
│ │ Wil je alvast de overdracht voorbereiden? │ │
|
|
│ │ [Start overdracht] [Later] │ │
|
|
│ └──────────────────────────────────────────────┘ │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 2. Gebruiker klikt [Start overdracht] │
|
|
│ → OverdrachtPanel opent │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 3. OverdrachtPanel toont: │
|
|
│ ┌──────────────────────────────────────────────┐ │
|
|
│ │ OVERDRACHT OCHTEND → MIDDAG │ │
|
|
│ │ 08:00 - 16:00 | 8 patiënten │ │
|
|
│ │ ───────────────────────────────────────── │ │
|
|
│ │ │ │
|
|
│ │ ▼ Jan de Vries │ │
|
|
│ │ AI-samenvatting: Rustige ochtend, medicatie│ │
|
|
│ │ uitgereikt zonder problemen. Let op val- │ │
|
|
│ │ risico bij toiletbezoek. │ │
|
|
│ │ [Bronnen: 3 notities] │ │
|
|
│ │ │ │
|
|
│ │ ▼ Marie van den Berg │ │
|
|
│ │ AI-samenvatting: ... │ │
|
|
│ │ │ │
|
|
│ │ [Kopieer alles] [Verstuur naar collega] │ │
|
|
│ └──────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Flow 4: Ambigue Input met Fallback
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ 1. Gebruiker typt: "medicatie" │
|
|
│ → Intent: onduidelijk (dagnotitie? metingen?) │
|
|
│ → Confidence: 0.5 │
|
|
│ → Geen patiënt gespecificeerd │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 2. FallbackPicker verschijnt: │
|
|
│ ┌──────────────────────────────────────────────┐ │
|
|
│ │ Wat wil je doen? │ │
|
|
│ │ │ │
|
|
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
|
|
│ │ │ 📝 │ │ 🔍 │ │ 📋 │ │ │
|
|
│ │ │ Notitie │ │ Zoeken │ │ Rapport │ │ │
|
|
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
|
|
│ │ │ │
|
|
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
|
|
│ │ │ 🔄 │ │ 📅 │ │ 💊 │ │ │
|
|
│ │ │Overdracht│ │ Agenda │ │ Meting │ │ │
|
|
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
|
|
│ └──────────────────────────────────────────────┘ │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ 3. Gebruiker klikt [Notitie] │
|
|
│ → DagnotatieBlock opent │
|
|
│ → "medicatie" ingevuld als tekst │
|
|
│ → Vraagt om patiënt te selecteren │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Niet in Scope
|
|
|
|
🎯 **Doel:** Duidelijk maken wat (nog) niet wordt gebouwd.
|
|
|
|
### Expliciet uitgesloten (v1)
|
|
|
|
| Feature | Reden |
|
|
|---------|-------|
|
|
| **Volledig voice-only navigatie** | Voice is input, niet navigatie. Te foutgevoelig. |
|
|
| **AI-gegenereerde UI componenten** | Onvoorspelbaar, niet geschikt voor zorg. Pre-built only. |
|
|
| **Ambient listening** | Privacy concerns, v2+ feature |
|
|
| **Multi-user realtime** | Complexiteit, niet nodig voor demo |
|
|
| **Offline mode** | Complexiteit, later toevoegen |
|
|
| **Behandelplan block** | Te complex, lage frequentie, bestaande UI voldoet |
|
|
| **Intake block** | Wizard is complex, 1x/maand, lage waarde voor MVP |
|
|
| **Metingen block** | Lage waarde-perceptie bij stakeholders |
|
|
| **Native mobile app** | Responsive web is voldoende |
|
|
| **FHIR/externe EPD integratie** | Post-MVP, apart project |
|
|
|
|
### Bewust versimpeld (v1)
|
|
|
|
| Aspect | Versimpeling |
|
|
|--------|--------------|
|
|
| **Diensten** | Hardcoded tijden (08-16, 16-23, 23-08) |
|
|
| **Patiënt-toewijzing** | Alle patiënten zichtbaar, geen restricties |
|
|
| **Alerts** | Alleen handmatig toegevoegd, geen automatische detectie |
|
|
|
|
---
|
|
|
|
## 6. Succescriteria
|
|
|
|
🎯 **Doel:** Objectieve meetlat voor een geslaagde oplevering.
|
|
|
|
### Functionele criteria
|
|
|
|
| Criterium | Target | Meetmethode |
|
|
|-----------|--------|-------------|
|
|
| Intent classification accuracy | > 85% | Test set van 50 voorbeelden |
|
|
| Voice transcription accuracy | > 90% | Handmatige review sample |
|
|
| Pre-fill correctheid | > 90% | Juiste patiënt/categorie |
|
|
| Fallback usage | < 25% | Picker clicks / totaal |
|
|
| "Notitie Jan medicatie" → save | < 30 sec | Timestamp logging |
|
|
|
|
### Performance criteria
|
|
|
|
| Criterium | Target |
|
|
|-----------|--------|
|
|
| Intent classification | < 500ms |
|
|
| Block render | < 200ms |
|
|
| Voice transcription latency | < 100ms |
|
|
| PatientContextCard laden | < 300ms |
|
|
|
|
### UX criteria
|
|
|
|
| Criterium | Target |
|
|
|-----------|--------|
|
|
| Klikken tot taak compleet | Gemiddeld < 3 |
|
|
| Training nodig | Zero (intuïtief) |
|
|
| "Dit voelt als magie" feedback | Minimaal 1 test user |
|
|
|
|
### Business criteria
|
|
|
|
| Criterium | Target |
|
|
|-----------|--------|
|
|
| Demo-ready | Ja, 3 scenario's foutloos |
|
|
| LinkedIn content | 2+ posts over concept |
|
|
| Stakeholder interesse | Minimaal 1 concrete vervolgvraag |
|
|
|
|
---
|
|
|
|
## 7. Risico's & Mitigatie
|
|
|
|
🎯 **Doel:** Risico's vroeg signaleren en plannen hoe ermee om te gaan.
|
|
|
|
| Risico | Kans | Impact | Mitigatie |
|
|
|--------|------|--------|-----------|
|
|
| **Intent classification onnauwkeurig** | Medium | Hoog | Fallback picker altijd beschikbaar, local-first matching |
|
|
| **Voice niet goed in Nederlands** | Laag | Medium | Deepgram NL model, tekst fallback altijd mogelijk |
|
|
| **Pre-fill verkeerde patiënt** | Medium | Hoog | Altijd confirmation tonen, nooit blind opslaan |
|
|
| **Context engine te complex** | Medium | Medium | Minimale context in v1, uitbreiden in v2 |
|
|
| **Gebruikers missen "overzicht"** | Medium | Medium | Bestaande patiëntenlijst als alternatieve entry |
|
|
| **Performance AI calls** | Medium | Medium | Local-first matching, streaming responses, caching |
|
|
| **Scope creep** | Hoog | Hoog | Strikte MVP scope, parking lot voor ideeën |
|
|
| **Demo deadline druk** | Medium | Hoog | Focus op 3 happy paths, polish later |
|
|
|
|
---
|
|
|
|
## 8. Roadmap / Vervolg (Post-MVP)
|
|
|
|
🎯 **Doel:** Richting geven aan toekomstige uitbreidingen.
|
|
|
|
### Fase 2: Extended Blocks (Post-MVP)
|
|
|
|
- **AgendaBlock** - Afspraken beheren, context bij naderende afspraak
|
|
- **BehandelplanBlock** - Wrapper rond bestaande functionaliteit
|
|
- **MetingenBlock** - Vitale functies invoer met trends
|
|
|
|
### Fase 3: Smart Triggers
|
|
|
|
- **Proactieve alerts** - "3 valincidenten, wil je een risico-analyse?"
|
|
- **Behandelplan reminder** - "Plan verloopt over 2 weken"
|
|
- **Automatische categorisatie** - ML-model voor notitie-types
|
|
|
|
### Fase 4: Team Features
|
|
|
|
- **Shift handover** - Gestructureerde overdracht workflow
|
|
- **Team dashboard** - Overzicht alle patiënten, alerts
|
|
- **Notificaties** - Push bij urgente updates
|
|
|
|
### Fase 5: Integraties
|
|
|
|
- **FHIR export** - Standaard zorgdata uitwisseling
|
|
- **Externe EPD sync** - Koppeling met Nedap, PinkRoccade
|
|
- **Calendar sync** - Google/Outlook afspraken importeren
|
|
|
|
---
|
|
|
|
## 9. Technische Architectuur (Overzicht)
|
|
|
|
### Nieuwe Routes
|
|
|
|
```
|
|
/app
|
|
/(app)
|
|
/command-center
|
|
/page.tsx # Hoofdscherm
|
|
/components/
|
|
CommandInput.tsx # Text + voice input
|
|
BlockContainer.tsx # Generic block wrapper
|
|
FallbackPicker.tsx # Block selection grid
|
|
RecentActions.tsx # Recent badges
|
|
|
|
/api
|
|
/intent
|
|
/classify/route.ts # Intent classification
|
|
/context
|
|
/route.ts # Get/set user context
|
|
/patients
|
|
/search/route.ts # Fuzzy patient search
|
|
```
|
|
|
|
### Building Blocks
|
|
|
|
```
|
|
/components/building-blocks/
|
|
/dagnotitie/
|
|
DagnotatieBlock.tsx
|
|
/zoeken/
|
|
ZoekenBlock.tsx
|
|
PatientCard.tsx
|
|
/rapportage/
|
|
RapportageBlock.tsx
|
|
/overdracht/
|
|
OverdrachtPanel.tsx
|
|
/context/
|
|
PatientContextCard.tsx
|
|
AgendaContextCard.tsx
|
|
/shared/
|
|
BlockContainer.tsx
|
|
BlockHeader.tsx
|
|
```
|
|
|
|
### State Management (Zustand)
|
|
|
|
```typescript
|
|
// stores/context-store.ts
|
|
interface ContextStore {
|
|
// User & shift
|
|
currentUser: User;
|
|
currentShift: Shift;
|
|
|
|
// Active patient (sticky)
|
|
activePatient: Patient | null;
|
|
setActivePatient: (patient: Patient | null) => void;
|
|
|
|
// Recent actions
|
|
recentActions: Action[];
|
|
addRecentAction: (action: Action) => void;
|
|
|
|
// Time-based context
|
|
upcomingAppointment: Appointment | null;
|
|
shiftEndingSoon: boolean;
|
|
}
|
|
|
|
// stores/command-center-store.ts
|
|
interface CommandCenterStore {
|
|
// Active block
|
|
activeBlock: BlockType | null;
|
|
blockPrefill: Record<string, unknown>;
|
|
|
|
// Input state
|
|
inputValue: string;
|
|
isListening: boolean;
|
|
transcript: string;
|
|
|
|
// Actions
|
|
processInput: (text: string) => Promise<void>;
|
|
openBlock: (type: BlockType, prefill?: object) => void;
|
|
closeBlock: () => void;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 10. Fasering & Sprint Planning
|
|
|
|
### Sprint 1: Foundation (Dag 1-2)
|
|
|
|
| Taak | Output | Uren |
|
|
|------|--------|------|
|
|
| Command Center page layout | `/app/command-center/page.tsx` | 2 |
|
|
| CommandInput component | Text + submit | 2 |
|
|
| Voice integratie | Mic button, Deepgram | 2 |
|
|
| Context store setup | Zustand store | 2 |
|
|
| BlockContainer wrapper | Generic frame | 1 |
|
|
|
|
**Deliverable:** Command Center opent, voice werkt, geen blocks nog.
|
|
|
|
### Sprint 2: Intent & Zoeken (Dag 3-4)
|
|
|
|
| Taak | Output | Uren |
|
|
|------|--------|------|
|
|
| Intent API route | `/api/intent/classify` | 3 |
|
|
| Local keyword matching | Quick patterns | 2 |
|
|
| Entity extraction | Patient name uit tekst | 2 |
|
|
| ZoekenBlock | Patient cards + select | 3 |
|
|
| FallbackPicker | Grid met icons | 2 |
|
|
|
|
**Deliverable:** "zoek jan" werkt, patient selectie mogelijk.
|
|
|
|
### Sprint 3: Dagnotitie Flow (Dag 5-6)
|
|
|
|
| Taak | Output | Uren |
|
|
|------|--------|------|
|
|
| DagnotatieBlock | Quick entry form | 3 |
|
|
| Pre-fill logic | Patient + categorie | 2 |
|
|
| Save flow + toast | Feedback | 1 |
|
|
| PatientContextCard | Na selectie tonen | 3 |
|
|
| Recent actions strip | Badges | 2 |
|
|
|
|
**Deliverable:** "notitie jan medicatie" werkt end-to-end.
|
|
|
|
### Sprint 4: Polish & Demo (Dag 7-8)
|
|
|
|
| Taak | Output | Uren |
|
|
|------|--------|------|
|
|
| RapportageBlock | Wrapper rond composer | 3 |
|
|
| OverdrachtPanel | AI-samenvatting | 4 |
|
|
| Animaties | Transitions | 2 |
|
|
| Demo scenario's | 3 happy paths | 2 |
|
|
| Bug fixes | Stability | 3 |
|
|
|
|
**Deliverable:** Demo-ready voor stakeholders.
|
|
|
|
### Totaal: ~42 uur over 8 dagen
|
|
|
|
---
|
|
|
|
## 11. Bijlagen & Referenties
|
|
|
|
🎯 **Doel:** Bronnen koppelen voor context en consistentie.
|
|
|
|
### Gerelateerde documenten
|
|
|
|
| Document | Locatie | Beschrijving |
|
|
|----------|---------|--------------|
|
|
| Ephemeral UI Research | `Ephemeral_UI_for_Healthcare...md` | Achtergrond contextual interfaces |
|
|
| PRD Ephemeral UI EPD | `nextgen-epd-prd-ephemeral-ui-epd.md` | Originele visie document |
|
|
| MVP Prioritering | `nextgen-epd-mvp-prioritering-ephemeral-ui.md` | Scope beslissingen |
|
|
| Waarde-analyse | `nextgen-epd-waarde-analyse-ephemeral-ui.md` | Klant & PO perspectief |
|
|
| FO Mini-ECD v2 | `fo-mini-ecd-v2.md` | Bestaande EPD functionaliteit |
|
|
| TO Mini-ECD | `to-mini-ecd-v1_2.md` | Technische basis |
|
|
|
|
### Bestaande codebase (hergebruik)
|
|
|
|
| Component | Locatie | Hergebruik |
|
|
|-----------|---------|------------|
|
|
| Speech Recorder | `components/speech-recorder.tsx` | 100% |
|
|
| Deepgram API | `api/deepgram/transcribe/route.ts` | 100% |
|
|
| Toast System | `lib/hooks/use-toast.ts` | 100% |
|
|
| Command (cmdk) | `components/ui/command.tsx` | 90% |
|
|
| Dagregistratie Form | `app/epd/dagregistratie/` | 80% |
|
|
| Report Types | `lib/types/report.ts` | 100% |
|
|
|
|
---
|
|
|
|
## Wijzigingslog
|
|
|
|
| Versie | Datum | Wijzigingen |
|
|
|--------|-------|-------------|
|
|
| 1.0 | 23-12-2024 | Initiële versie | |