987 lines
34 KiB
Markdown
987 lines
34 KiB
Markdown
# 🧩 Functioneel Ontwerp (FO) — Swift: Contextual UI EPD
|
||
|
||
**Projectnaam:** Swift — Contextual UI EPD
|
||
**Versie:** v1.0
|
||
**Datum:** 23-12-2024
|
||
**Auteur:** Colin Lit
|
||
|
||
---
|
||
|
||
## 1. Doel en relatie met het PRD
|
||
|
||
🎯 **Doel van dit document:**
|
||
Dit Functioneel Ontwerp beschrijft **hoe** Swift uit het PRD functioneel werkt — wat de gebruiker ziet, doet en ervaart. Waar het PRD het concept en de architectuur beschrijft, laat dit FO zien hoe elke interactie in de praktijk werkt.
|
||
|
||
📘 **Relatie met andere documenten:**
|
||
- **PRD:** `nextgen-epd-prd-ephemeral-ui-epd.md` — Wat en waarom
|
||
- **UX/UI:** `ux-ui-design-ephemeral-ui-epd-v2.1.md` — Visuele specificaties
|
||
- **Taken analyse:** `taken-en-vragen-analyse.md` — Frequentie en prioritering
|
||
|
||
**Kernprincipe:**
|
||
> De gebruiker navigeert niet door menu's. De gebruiker spreekt of typt een intentie — en het juiste bouwblok verschijnt, voorgevuld met relevante data.
|
||
|
||
---
|
||
|
||
## 2. Overzicht van de belangrijkste onderdelen
|
||
|
||
🎯 **Doel:** Overzicht van alle modules en hun relaties.
|
||
|
||
### 2.1 Systeemcomponenten
|
||
|
||
| # | Component | Beschrijving | Type |
|
||
|---|-----------|--------------|------|
|
||
| 1 | **Command Center** | Hoofdscherm met één input | Scherm |
|
||
| 2 | **Context Bar** | Dienst, patiënt, user info | UI Zone |
|
||
| 3 | **Canvas Area** | Waar blocks verschijnen | UI Zone |
|
||
| 4 | **Recent Strip** | Laatste acties quick access | UI Zone |
|
||
| 5 | **Command Input** | Tekst + voice input | UI Zone |
|
||
| 6 | **Intent Engine** | Classificeert gebruikersinput | Backend |
|
||
| 7 | **Context Manager** | Beheert sessie context | Backend |
|
||
|
||
### 2.2 Bouwblokken (Blocks)
|
||
|
||
| Prio | Block | Functie | Trigger voorbeelden |
|
||
|------|-------|---------|---------------------|
|
||
| P1 | **DagnotatieBlock** | Snelle notitie invoer | "notitie jan medicatie" |
|
||
| P1 | **ZoekenBlock** | Patiënt zoeken | "zoek marie" |
|
||
| P1 | **PatientContextCard** | Patiënt overzicht | Na zoeken / selectie |
|
||
| P1 | **OverdrachtBlock** | Dienst overdracht | "overdracht maken" |
|
||
| P2 | **RapportageBlock** | Behandelrapportage | "gesprek gehad met jan" |
|
||
| P2 | **AgendaBlock** | Afspraken | "mijn afspraken" |
|
||
| P2 | **MetingenBlock** | Vitale functies | "bloeddruk invoeren" |
|
||
| P3 | **IntakeWizard** | Nieuwe patiënt intake | "nieuwe intake" |
|
||
| P3 | **BehandelplanBlock** | Behandelplan | "behandelplan jan" |
|
||
| P3 | **RisicoBlock** | Risicotaxatie | "risico jan" |
|
||
| P3 | **ContactenBlock** | Contactpersonen | "contacten jan" |
|
||
|
||
### 2.3 Systeem Blocks
|
||
|
||
| Block | Functie | Trigger |
|
||
|-------|---------|---------|
|
||
| **HelpBlock** | Hulp en voorbeelden | "help", "wat kan ik" |
|
||
| **FallbackPicker** | Visuele keuze bij onduidelijkheid | Lage confidence |
|
||
|
||
---
|
||
|
||
## 3. User Stories
|
||
|
||
🎯 **Doel:** Beschrijven wat gebruikers moeten kunnen doen, vanuit hun perspectief.
|
||
|
||
### 3.1 P1: Kritieke Stories (MVP Week 1-2)
|
||
|
||
| ID | Rol | Doel / Actie | Verwachte waarde | Prio |
|
||
|----|-----|--------------|------------------|------|
|
||
| US-01 | Verpleegkundige | Dagnotitie maken door te spreken/typen | Registratie in 15 sec ipv 5 min | 🔴 P1 |
|
||
| US-02 | Verpleegkundige | Patiënt zoeken op naam | Direct vinden zonder navigatie | 🔴 P1 |
|
||
| US-03 | Verpleegkundige | Patiënt context zien na selectie | Alles relevante in één oogopslag | 🔴 P1 |
|
||
| US-04 | Verpleegkundige | Overdracht maken einde dienst | Complete overdracht in 5 min | 🔴 P1 |
|
||
| US-05 | Alle gebruikers | Weten wat het systeem kan | "help" toont mogelijkheden | 🔴 P1 |
|
||
| US-06 | Alle gebruikers | Kiezen als systeem niet begrijpt | Visuele fallback picker | 🔴 P1 |
|
||
|
||
### 3.2 P2: Belangrijke Stories (MVP Week 3-4)
|
||
|
||
| ID | Rol | Doel / Actie | Verwachte waarde | Prio |
|
||
|----|-----|--------------|------------------|------|
|
||
| US-07 | Behandelaar | Rapportage schrijven na gesprek | Dicteren + AI samenvatting | 🟡 P2 |
|
||
| US-08 | Behandelaar | Agenda bekijken | Afspraken vandaag/week | 🟡 P2 |
|
||
| US-09 | Verpleegkundige | Meting invoeren | Vitals met trend indicator | 🟡 P2 |
|
||
| US-10 | Behandelaar | Diagnose/plan van patiënt zien | Via PatientContextCard | 🟡 P2 |
|
||
|
||
### 3.3 P3: Post-MVP Stories
|
||
|
||
| ID | Rol | Doel / Actie | Verwachte waarde | Prio |
|
||
|----|-----|--------------|------------------|------|
|
||
| US-11 | Behandelaar | Nieuwe intake starten | Wizard begeleidt proces | 🟢 P3 |
|
||
| US-12 | Behandelaar | Behandelplan maken/bewerken | AI-gegenereerd, bewerkbaar | 🟢 P3 |
|
||
| US-13 | Verpleegkundige | Risicotaxatie invullen | Gestructureerd formulier | 🟢 P3 |
|
||
| US-14 | Behandelaar | Contactpersonen beheren | Noodcontact, familie | 🟢 P3 |
|
||
|
||
---
|
||
|
||
## 4. Functionele werking per onderdeel
|
||
|
||
🎯 **Doel:** Per component beschrijven wat de gebruiker kan doen en wat het systeem doet.
|
||
|
||
### 4.1 Command Center (Hoofdscherm)
|
||
|
||
**Beschrijving:**
|
||
Het enige scherm van de applicatie. Geen sidebar, geen menu's. Alles gebeurt via één input.
|
||
|
||
**Layout:**
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ [Context Bar: Dienst | Patiënt dropdown | User] 48px │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ [Active Block Area] │
|
||
│ Blocks verschijnen hier │
|
||
│ Centered, responsive width │
|
||
│ Flex │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ [Recent Strip: laatste acties als badges] 48px │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ [Command Input: 🎤 Typ of spreek wat je wilt doen...] 64px │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**Gedrag:**
|
||
- Bij laden: Command Input heeft focus
|
||
- Keyboard shortcut `⌘K` focust input vanaf elke plek
|
||
- Blocks verschijnen met fade+scale animatie
|
||
- Slechts één block actief tegelijk (of gestapeld met z-index)
|
||
|
||
---
|
||
|
||
### 4.2 Context Bar
|
||
|
||
**Functie:** Toont essentiële context: welke dienst, welke patiënt actief, wie ingelogd.
|
||
|
||
**Elementen:**
|
||
|
||
| Element | Locatie | Gedrag |
|
||
|---------|---------|--------|
|
||
| Dienst indicator | Links | "🌅 Ochtend \| 8 ptn" — kleur per shift |
|
||
| Actieve patiënt | Midden-rechts | Dropdown voor quick-switch |
|
||
| User | Rechts | Initialen, klik → logout |
|
||
|
||
**Dienst bepaling:**
|
||
|
||
| Dienst | Tijd | Kleur | Icon |
|
||
|--------|------|-------|------|
|
||
| Ochtend | 07:00-15:00 | Amber #F59E0B | 🌅 |
|
||
| Middag | 15:00-23:00 | Blue #3B82F6 | 🌤️ |
|
||
| Nacht | 23:00-07:00 | Indigo #6366F1 | 🌙 |
|
||
|
||
**Patiënt Dropdown:**
|
||
- Toont huidige selectie (of "Geen patiënt")
|
||
- Recent bekeken patiënten (max 5)
|
||
- Zoek optie onderaan
|
||
- "Clear" optie om selectie te wissen
|
||
|
||
---
|
||
|
||
### 4.3 Command Input
|
||
|
||
**Functie:** Het hart van de interface — tekst én voice input.
|
||
|
||
**States:**
|
||
|
||
| State | Weergave | Trigger |
|
||
|-------|----------|---------|
|
||
| Default | "🎤 Typ of spreek wat je wilt doen..." | — |
|
||
| Typing | Cursor, getypte tekst | Keyboard input |
|
||
| Listening | 🔴 + waveform + live transcript | Mic click of spatie (bij leeg) |
|
||
| Processing | ⏳ spinner + "Even kijken..." | Na submit |
|
||
|
||
**Acties:**
|
||
|
||
| Input | Actie |
|
||
|-------|-------|
|
||
| `Enter` | Submit naar Intent Engine |
|
||
| `Escape` | Clear input / close block |
|
||
| `↑` | Vorige command (history) |
|
||
| `Space` (leeg) | Start voice |
|
||
| Mic click | Toggle voice recording |
|
||
|
||
**Voice Flow:**
|
||
1. User klikt mic of drukt spatie (bij lege input)
|
||
2. Deepgram start streaming transcription
|
||
3. Live transcript verschijnt in input
|
||
4. Pauze detectie (1.5 sec stilte) → auto-submit
|
||
5. Of user klikt "Stop" → submit
|
||
|
||
---
|
||
|
||
### 4.4 Intent Engine
|
||
|
||
**Functie:** Classificeert gebruikersinput naar intent + entities.
|
||
|
||
**Input:**
|
||
```typescript
|
||
{
|
||
text: string; // "notitie jan medicatie gegeven"
|
||
context: {
|
||
activePatient?: Patient;
|
||
currentShift: 'ochtend' | 'middag' | 'nacht';
|
||
recentPatients: Patient[];
|
||
}
|
||
}
|
||
```
|
||
|
||
**Output:**
|
||
```typescript
|
||
{
|
||
intent: IntentType; // 'dagnotitie'
|
||
confidence: number; // 0.94
|
||
entities: {
|
||
patientName?: string; // "jan"
|
||
patientId?: string; // "uuid-123" (als gevonden)
|
||
category?: string; // "medicatie"
|
||
content?: string; // "gegeven"
|
||
date?: string;
|
||
};
|
||
clarificationNeeded: boolean;
|
||
clarificationQuestion?: string;
|
||
}
|
||
```
|
||
|
||
**Intent Types:**
|
||
|
||
| Intent | Block | Confidence drempel |
|
||
|--------|-------|-------------------|
|
||
| `dagnotitie` | DagnotatieBlock | 0.7 |
|
||
| `zoeken` | ZoekenBlock | 0.7 |
|
||
| `overdracht` | OverdrachtBlock | 0.8 |
|
||
| `rapportage` | RapportageBlock | 0.7 |
|
||
| `agenda` | AgendaBlock | 0.7 |
|
||
| `metingen` | MetingenBlock | 0.7 |
|
||
| `intake` | IntakeWizard | 0.8 |
|
||
| `behandelplan` | BehandelplanBlock | 0.8 |
|
||
| `risico` | RisicoBlock | 0.8 |
|
||
| `patient_info` | PatientContextCard | 0.7 |
|
||
| `help` | HelpBlock | 0.9 |
|
||
| `onbekend` | FallbackPicker | < 0.5 |
|
||
|
||
**Clarification Flow:**
|
||
- Confidence < drempel → vraag om verduidelijking
|
||
- Meerdere patient matches → toon selector
|
||
- Geen patient bij patient-required intent → vraag welke patient
|
||
|
||
---
|
||
|
||
### 4.5 DagnotatieBlock
|
||
|
||
**Functie:** Snelle notitie invoer — meest gebruikte actie (10-20x per dag).
|
||
|
||
**Trigger patterns:**
|
||
- "notitie [patient]"
|
||
- "[patient] medicatie gegeven"
|
||
- "incident bij [patient]"
|
||
- "[patient] heeft goed gegeten"
|
||
|
||
**Pre-fill logica:**
|
||
|
||
| Extracted | Pre-fill |
|
||
|-----------|----------|
|
||
| patient_name → match | Patient selector |
|
||
| "medicatie" keyword | Category = Medicatie |
|
||
| "gegeten", "ADL" | Category = ADL |
|
||
| "incident", "agressie" | Category = Incident |
|
||
| Overige tekst | Notitie veld |
|
||
|
||
**Form velden:**
|
||
|
||
| Veld | Type | Verplicht | Default |
|
||
|------|------|-----------|---------|
|
||
| Patient | Dropdown + search | Ja | Pre-filled of activePatient |
|
||
| Categorie | Button group | Ja | Extracted of Algemeen |
|
||
| Notitie | Textarea | Ja | Extracted content |
|
||
| Tijd | Time picker | Ja | Nu |
|
||
| In overdracht | Checkbox | Nee | false |
|
||
|
||
**Categorieën:**
|
||
|
||
| Categorie | Icon | Kleur | Keyboard |
|
||
|-----------|------|-------|----------|
|
||
| Medicatie | 💊 | Amber | 1 |
|
||
| ADL | 🍽️ | Green | 2 |
|
||
| Observatie | 👁️ | Blue | 3 |
|
||
| Incident | ⚠️ | Red | 4 |
|
||
| Algemeen | 💬 | Gray | 5 |
|
||
|
||
**Acties:**
|
||
|
||
| Knop | Actie | Keyboard |
|
||
|------|-------|----------|
|
||
| Opslaan | POST naar API, sluit block | `⌘Enter` |
|
||
| Annuleren | Sluit block zonder opslaan | `Escape` |
|
||
|
||
**Na opslaan:**
|
||
1. Toast: "✓ Notitie opgeslagen"
|
||
2. Block verdwijnt (200ms animatie)
|
||
3. Recent strip: badge "[📝 Jan-Med]"
|
||
4. Input krijgt focus voor volgende actie
|
||
|
||
**API:**
|
||
```
|
||
POST /api/reports
|
||
Body: {
|
||
patient_id: string,
|
||
type: 'nursing_log',
|
||
category: string,
|
||
content: string,
|
||
timestamp: datetime,
|
||
include_in_handover: boolean
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 4.6 ZoekenBlock
|
||
|
||
**Functie:** Patiënt zoeken en selecteren.
|
||
|
||
**Trigger patterns:**
|
||
- "zoek [naam]"
|
||
- "wie is [naam]"
|
||
- "vind [naam]"
|
||
|
||
**Gedrag:**
|
||
1. Block opent met zoekterm pre-filled
|
||
2. Live search (debounced 300ms)
|
||
3. Resultaten tonen met relevante info
|
||
4. Klik of Enter selecteert patiënt
|
||
|
||
**Resultaat card bevat:**
|
||
- Naam (highlighted match)
|
||
- Leeftijd
|
||
- Kamer/locatie
|
||
- Laatste activiteit ("2 uur geleden")
|
||
- Alert badge indien aanwezig
|
||
|
||
**Na selectie:**
|
||
1. ZoekenBlock sluit
|
||
2. PatientContextCard opent automatisch
|
||
3. Context Bar update: patient dropdown toont selectie
|
||
4. Recent strip: badge "[🔍 Jan]"
|
||
|
||
**Empty state:**
|
||
"Geen patiënten gevonden voor '[zoekterm]'"
|
||
|
||
**API:**
|
||
```
|
||
GET /api/patients/search?q={zoekterm}
|
||
Response: Patient[] met relevance score
|
||
```
|
||
|
||
---
|
||
|
||
### 4.7 PatientContextCard
|
||
|
||
**Functie:** Compact overzicht van alles relevant voor één patiënt.
|
||
|
||
**Trigger:**
|
||
- Automatisch na patiënt selectie
|
||
- "info [patient]", "dossier [patient]"
|
||
- Klik op patiënt in dropdown
|
||
|
||
**Secties (adaptive - alleen tonen als data aanwezig):**
|
||
|
||
| Sectie | Data | Bron |
|
||
|--------|------|------|
|
||
| Header | Naam, leeftijd, kamer, opnamedatum | patients |
|
||
| Alert | Actieve alerts/risico's | risk_assessments |
|
||
| Laatste notities | 3 meest recente | reports |
|
||
| Vitals | Vandaag gemeten | vitals |
|
||
| Diagnose | Hoofddiagnose + ernst | conditions |
|
||
| Behandelplan | Status, sessie X/Y, volgende eval | care_plans |
|
||
| Contacten | Primaire contact | contacts |
|
||
|
||
**Quick Actions (onderaan):**
|
||
```
|
||
[📝 Notitie] [📋 Rapport] [📊 Meting] [📄 Plan] [📞 Contact]
|
||
```
|
||
|
||
Klik op quick action → opent betreffende block met patient pre-filled.
|
||
|
||
**API:**
|
||
```
|
||
GET /api/patients/{id}/context
|
||
Response: {
|
||
patient: Patient,
|
||
alerts: Alert[],
|
||
recentNotes: Report[],
|
||
vitals: Vital[],
|
||
diagnosis: Condition,
|
||
carePlan: CarePlan,
|
||
contacts: Contact[]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 4.8 OverdrachtBlock
|
||
|
||
**Functie:** Multi-patiënt overdracht met AI-samenvattingen.
|
||
|
||
**Trigger patterns:**
|
||
- "overdracht maken"
|
||
- "dienst klaar"
|
||
- "samenvatting voor collega"
|
||
|
||
**Proactive trigger:**
|
||
- 30 minuten voor dienst einde → suggestie banner
|
||
|
||
**Layout:**
|
||
- Header: "Overdracht [Ochtend] → [Middag]" + tijdrange
|
||
- Accordion per patiënt (expanded als alert aanwezig)
|
||
- AI samenvatting per patiënt
|
||
- Bronverwijzingen naar originele notities
|
||
- Footer: Kopieer / E-mail / Afronden
|
||
|
||
**Per patiënt accordion:**
|
||
|
||
| Element | Beschrijving |
|
||
|---------|--------------|
|
||
| Header | Naam + alert badge |
|
||
| Summary | AI-gegenereerde samenvatting |
|
||
| Bronnen | "📎 3 notities" — klik opent details |
|
||
| Bewerken | Inline edit van samenvatting |
|
||
|
||
**AI Samenvatting:**
|
||
- Gegenereerd op basis van: nursing_logs, vitals, rapportages
|
||
- Tijdrange: huidige dienst (default 8 uur)
|
||
- Max 3 zinnen per patiënt
|
||
- Aandachtspunten prominent
|
||
|
||
**Acties:**
|
||
|
||
| Knop | Actie |
|
||
|------|-------|
|
||
| Kopieer alles | Alle samenvattingen naar clipboard |
|
||
| E-mail | Open mail client met content |
|
||
| Afronden | Markeer overdracht compleet |
|
||
|
||
**API:**
|
||
```
|
||
POST /api/overdracht/generate
|
||
Body: {
|
||
patientIds: string[],
|
||
shiftStart: datetime,
|
||
shiftEnd: datetime
|
||
}
|
||
Response: {
|
||
summaries: { patientId: string, summary: string, sources: Source[] }[]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 4.9 RapportageBlock
|
||
|
||
**Functie:** Uitgebreide behandelrapportage met rich text en AI.
|
||
|
||
**Trigger patterns:**
|
||
- "rapportage"
|
||
- "gesprek gehad met [patient]"
|
||
- "behandelgesprek"
|
||
|
||
**Form velden:**
|
||
|
||
| Veld | Type | Default |
|
||
|------|------|---------|
|
||
| Patient | Dropdown | Pre-filled of activePatient |
|
||
| Type | Button group | Gesprek |
|
||
| Inhoud | Rich text (TipTap) | Leeg of transcript |
|
||
| Datum/tijd | DateTime | Nu |
|
||
|
||
**Rapportage types:**
|
||
- Gesprek
|
||
- Evaluatie
|
||
- Telefonisch
|
||
- Consult
|
||
- Familie
|
||
|
||
**Rich text toolbar:**
|
||
- Bold, Italic
|
||
- Bullet list, Numbered list
|
||
- Quote
|
||
- H1, H2
|
||
- 🎤 Dicteer knop
|
||
|
||
**AI acties:**
|
||
|
||
| Actie | Beschrijving | Output |
|
||
|-------|--------------|--------|
|
||
| ✨ Samenvatten | Bullets van kernpunten | Zijpaneel |
|
||
| 📖 B1-niveau | Herschrijf leesbaar | Zijpaneel |
|
||
| 🔍 Problemen | Extraheer klinische issues | Zijpaneel |
|
||
|
||
**AI Zijpaneel:**
|
||
- Verschijnt rechts van editor
|
||
- Preview van AI output
|
||
- Knoppen: Invoegen, Kopiëren, Verwerp
|
||
|
||
**API:**
|
||
```
|
||
POST /api/reports
|
||
Body: {
|
||
patient_id: string,
|
||
type: 'rapportage',
|
||
subtype: string,
|
||
content: string (HTML),
|
||
timestamp: datetime
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 4.10 AgendaBlock
|
||
|
||
**Functie:** Afspraken overzicht en beheer.
|
||
|
||
**Trigger patterns:**
|
||
- "agenda"
|
||
- "afspraken vandaag"
|
||
- "wie zie ik deze week"
|
||
- "afspraken [patient]"
|
||
|
||
**Layout:**
|
||
- Navigatie: [◀ Gisteren] [Vandaag] [Morgen ▶]
|
||
- View toggle: [Dag] [Week]
|
||
- Lijst van afspraken met tijden
|
||
|
||
**Per afspraak:**
|
||
- Tijd (09:00 - 09:50)
|
||
- Patiëntnaam
|
||
- Type afspraak
|
||
- Quick actions: [Open dossier] [Notitie]
|
||
|
||
**Acties:**
|
||
- Klik op afspraak → open PatientContextCard
|
||
- [+ Nieuwe afspraak] → AfspraakBlock (P4)
|
||
|
||
**API:**
|
||
```
|
||
GET /api/appointments?date={date}&practitionerId={id}
|
||
Response: Appointment[]
|
||
```
|
||
|
||
---
|
||
|
||
### 4.11 MetingenBlock
|
||
|
||
**Functie:** Vitale functies invoeren.
|
||
|
||
**Trigger patterns:**
|
||
- "bloeddruk invoeren"
|
||
- "meting [patient]"
|
||
- "vitals"
|
||
- "temperatuur"
|
||
|
||
**Form velden:**
|
||
|
||
| Veld | Type | Validatie |
|
||
|------|------|-----------|
|
||
| Patient | Dropdown | Verplicht |
|
||
| Type | Button group | Verplicht |
|
||
| Waarde(s) | Number input(s) | Per type |
|
||
| Tijd | DateTime | Default: nu |
|
||
| Opmerking | Textarea | Optioneel |
|
||
|
||
**Meting types:**
|
||
|
||
| Type | Velden | Eenheid |
|
||
|------|--------|---------|
|
||
| Bloeddruk | Systolisch, Diastolisch | mmHg |
|
||
| Pols | BPM | /min |
|
||
| Temperatuur | Temp | °C |
|
||
| Gewicht | Kg | kg |
|
||
| Glucose | mmol/L | mmol/L |
|
||
| Saturatie | % | SpO2 |
|
||
|
||
**Trend indicator:**
|
||
Na invoer: vergelijk met vorige meting
|
||
- ↑ Hoger dan vorige
|
||
- ↓ Lager dan vorige
|
||
- → Gelijk
|
||
|
||
**API:**
|
||
```
|
||
POST /api/vitals
|
||
Body: {
|
||
patient_id: string,
|
||
type: string,
|
||
values: Record<string, number>,
|
||
timestamp: datetime,
|
||
notes?: string
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 4.12 HelpBlock
|
||
|
||
**Functie:** Toont wat het systeem kan.
|
||
|
||
**Trigger patterns:**
|
||
- "help"
|
||
- "wat kan ik doen"
|
||
- "hoe werkt dit"
|
||
|
||
**Inhoud:**
|
||
Gegroepeerde voorbeelden per categorie:
|
||
- 📝 Notities: "notitie jan medicatie"
|
||
- 🔍 Zoeken: "zoek marie"
|
||
- 🔄 Overdracht: "overdracht maken"
|
||
- 📋 Rapportage: "gesprek gehad"
|
||
- 📅 Agenda: "afspraken vandaag"
|
||
- etc.
|
||
|
||
---
|
||
|
||
### 4.13 FallbackPicker
|
||
|
||
**Functie:** Visuele keuze wanneer intent onduidelijk is.
|
||
|
||
**Trigger:**
|
||
- Intent confidence < 0.5
|
||
- Intent = 'onbekend'
|
||
|
||
**Layout:**
|
||
Grid van 8-10 opties met icon + label.
|
||
Keyboard shortcuts 1-9 voor snelle selectie.
|
||
|
||
**Opties:**
|
||
```
|
||
[📝 Notitie] [🔍 Zoeken] [🔄 Overdracht] [📋 Rapport]
|
||
[📅 Agenda] [📊 Meting] [👤 Dossier] [📄 Intake]
|
||
[⚠️ Risico] [💡 Help]
|
||
```
|
||
|
||
---
|
||
|
||
### 4.14 Recent Strip
|
||
|
||
**Functie:** Quick access naar recente acties.
|
||
|
||
**Gedrag:**
|
||
- Max 5 badges zichtbaar
|
||
- Nieuwste links
|
||
- Horizontal scroll voor meer
|
||
- Klik = heropen context
|
||
|
||
**Badge types:**
|
||
|
||
| Type | Icon | Kleur | Klik actie |
|
||
|------|------|-------|------------|
|
||
| Dagnotitie | 📝 | Category kleur | Open PatientContextCard |
|
||
| Zoeken | 🔍 | Gray | Open PatientContextCard |
|
||
| Overdracht | 🔄 | Blue | Open OverdrachtBlock |
|
||
| Rapportage | 📋 | Green | Open RapportageBlock |
|
||
|
||
---
|
||
|
||
## 5. UI-overzicht (visuele structuur)
|
||
|
||
🎯 **Doel:** Globale schermopbouw en component hiërarchie.
|
||
|
||
### 5.1 Hoofdlayout
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ │
|
||
│ ┌───────────────────────────────────────────────────────────┐ │
|
||
│ │ 🌅 Ochtend | 8 ptn Jan de Vries ▼ 👤 SV │ │
|
||
│ └───────────────────────────────────────────────────────────┘ │
|
||
│ CONTEXT BAR (48px) │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ │
|
||
│ ┌─────────────────────┐ │
|
||
│ │ │ │
|
||
│ │ ACTIVE BLOCK │ │
|
||
│ │ (Small: 480px) │ │
|
||
│ │ (Medium: 640px) │ │
|
||
│ │ (Large: 900px) │ │
|
||
│ │ │ │
|
||
│ └─────────────────────┘ │
|
||
│ │
|
||
│ CANVAS AREA (flex) │
|
||
│ │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ ┌───────────────────────────────────────────────────────────┐ │
|
||
│ │ Recent: [📝 Jan-Med] [🔄 Overdracht] [🔍 Marie] │ │
|
||
│ └───────────────────────────────────────────────────────────┘ │
|
||
│ RECENT STRIP (48px) │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ ┌───────────────────────────────────────────────────────────┐ │
|
||
│ │ 🎤 Typ of spreek wat je wilt doen... ⌘K │ │
|
||
│ └───────────────────────────────────────────────────────────┘ │
|
||
│ COMMAND INPUT (64px) │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 5.2 Block Sizes
|
||
|
||
| Size | Max-width | Use case |
|
||
|------|-----------|----------|
|
||
| Small | 480px | Quick entry (notitie, zoeken, meting) |
|
||
| Medium | 640px | Forms (rapportage, behandelplan) |
|
||
| Large | 900px | Overzichten (overdracht, agenda) |
|
||
| XLarge | 1100px | Wizards (intake) |
|
||
|
||
### 5.3 Block Container
|
||
|
||
Alle blocks gebruiken dezelfde wrapper:
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ [Icon] [Title] [−] [×] │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ BLOCK CONTENT │
|
||
│ │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ [Cancel] [Save] │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Interacties met AI (functionele beschrijving)
|
||
|
||
🎯 **Doel:** Waar AI in de flow voorkomt en wat de gebruiker ziet.
|
||
|
||
### 6.1 Intent Classification
|
||
|
||
| Locatie | Trigger | Input | Output |
|
||
|---------|---------|-------|--------|
|
||
| Command Input | Submit | Tekst/transcript | Intent + entities + confidence |
|
||
|
||
### 6.2 Content AI
|
||
|
||
| Locatie | AI-actie | Trigger | Output |
|
||
|---------|----------|---------|--------|
|
||
| RapportageBlock | Samenvatten | Klik knop | Bullets in zijpaneel |
|
||
| RapportageBlock | B1-niveau | Klik knop | Herschreven tekst |
|
||
| RapportageBlock | Extract problemen | Klik knop | Categorie + severity |
|
||
| OverdrachtBlock | Genereer samenvatting | Per patiënt accordion | 3-zin summary |
|
||
| BehandelplanBlock | Genereer plan | Klik knop | Doelen + interventies |
|
||
| IntakeWizard | Suggestie diagnose | Na anamnese stap | ICD-10 code + rationale |
|
||
|
||
### 6.3 AI Response Handling
|
||
|
||
**Alle AI outputs:**
|
||
1. Tonen in dedicated preview area (niet direct in form)
|
||
2. User moet expliciet accepteren/invoegen
|
||
3. Bewerken altijd mogelijk
|
||
4. Annuleren zonder gevolgen
|
||
|
||
**Loading state:**
|
||
- Skeleton loader in output area
|
||
- "AI denkt na..." indicator
|
||
- Non-blocking (user kan annuleren)
|
||
|
||
**Error handling:**
|
||
- "Kon niet verwerken. Probeer opnieuw."
|
||
- Retry knop
|
||
- Fallback naar handmatige invoer
|
||
|
||
---
|
||
|
||
## 7. Proactieve Triggers
|
||
|
||
🎯 **Doel:** Wanneer het systeem zelf UI toont zonder expliciete vraag.
|
||
|
||
| Trigger | Conditie | Actie |
|
||
|---------|----------|-------|
|
||
| Dienst start | Login of shift wissel | Suggestie: OverdrachtLezenBlock |
|
||
| Dienst einde | 30 min voor einde | Banner: "Overdracht maken?" |
|
||
| Patiënt geselecteerd | Na zoeken/klik | Auto-open PatientContextCard |
|
||
| Afspraak nadert | 15 min voor afspraak | Suggestie: patiënt openen |
|
||
| Alert aanwezig | Patiënt met actief risico | Alert banner in PatientContextCard |
|
||
|
||
**Suggestie Banner:**
|
||
```
|
||
┌───────────────────────────────────────────────────────────────┐
|
||
│ 🕐 Dienst eindigt over 30 min. Overdracht maken? │
|
||
│ [Ja] [Later] [×] │
|
||
└───────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
- Niet-blokkerend (user kan negeren)
|
||
- "Later" = herinner over 15 min
|
||
- "×" = niet meer voor deze dienst
|
||
|
||
---
|
||
|
||
## 8. States & Error Handling
|
||
|
||
### 8.1 Block States
|
||
|
||
| State | Weergave |
|
||
|-------|----------|
|
||
| Loading | Skeleton loader |
|
||
| Ready | Form/content |
|
||
| Submitting | Disabled + spinner |
|
||
| Success | Toast + close |
|
||
| Error | Inline error message |
|
||
|
||
### 8.2 Network Errors
|
||
|
||
| Situatie | Gedrag |
|
||
|----------|--------|
|
||
| API timeout | "Verbinding verbroken. Probeer opnieuw." + retry |
|
||
| 401 Unauthorized | Redirect naar login |
|
||
| 500 Server error | "Er ging iets mis. Probeer later opnieuw." |
|
||
| Offline | Banner bovenin: "Geen internetverbinding" |
|
||
|
||
### 8.3 Validation Errors
|
||
|
||
| Veld | Validatie | Foutmelding |
|
||
|------|-----------|-------------|
|
||
| Patient | Verplicht | "Selecteer een patiënt" |
|
||
| Notitie | Min 5 karakters | "Voer een notitie in" |
|
||
| Bloeddruk | 50-250 / 30-150 | "Waarde buiten bereik" |
|
||
|
||
---
|
||
|
||
## 9. Gebruikersrollen en rechten
|
||
|
||
🎯 **Doel:** Welke rollen toegang hebben tot welke onderdelen.
|
||
|
||
| Rol | Toegang | Beperkingen |
|
||
|-----|---------|-------------|
|
||
| Verpleegkundige | Dagnotitie, Zoeken, Overdracht, Metingen | Geen behandelplan bewerken |
|
||
| Behandelaar | Alle blocks | Alleen eigen patiënten bewerken |
|
||
| Psychiater | Alle blocks + diagnose | Alleen eigen patiënten |
|
||
| Demo-user | Alle blocks (fictieve data) | Alleen lezen |
|
||
|
||
---
|
||
|
||
## 10. Keyboard Shortcuts
|
||
|
||
| Shortcut | Actie | Scope |
|
||
|----------|-------|-------|
|
||
| `⌘K` | Focus command input | Global |
|
||
| `Escape` | Sluit actieve block | Block open |
|
||
| `Enter` | Submit form | Form focused |
|
||
| `⌘Enter` | Opslaan | In form |
|
||
| `1-5` | Selecteer categorie | DagnotatieBlock |
|
||
| `1-9` | Selecteer optie | FallbackPicker |
|
||
| `↑` `↓` | Navigeer resultaten | ZoekenBlock |
|
||
| `Space` | Start voice (lege input) | Command Input |
|
||
|
||
---
|
||
|
||
## 11. Navigatie & Toegang
|
||
|
||
🎯 **Doel:** Beschrijven hoe gebruikers Swift bereiken en kiezen.
|
||
|
||
### 11.1 User Journey naar Swift
|
||
|
||
```
|
||
LANDINGSPAGINA (/)
|
||
│
|
||
│ Storytelling + Demo
|
||
│
|
||
▼
|
||
LOGIN PAGINA (/login)
|
||
│
|
||
│ ┌─────────────────────────────────────┐
|
||
│ │ Kies je werkwijze: │
|
||
│ │ │
|
||
│ │ ○ ✨ Swift — Spreek of typ │
|
||
│ │ ○ 📋 Klassiek — Menu's en forms │
|
||
│ │ │
|
||
│ │ ☐ Onthoud mijn keuze │
|
||
│ └─────────────────────────────────────┘
|
||
│
|
||
├──────────────────┬───────────────────┐
|
||
▼ ▼ │
|
||
/epd/swift /epd/dashboard │
|
||
(Command Center) (Klassiek EPD) │
|
||
│
|
||
│
|
||
GEEN TOGGLE ◄──────────┘
|
||
binnen interface
|
||
```
|
||
|
||
### 11.2 Landingspagina Elementen
|
||
|
||
De landingspagina introduceert Swift via storytelling:
|
||
|
||
| Element | Functie |
|
||
|---------|---------|
|
||
| **Hero** | Probleem: "40% admin tijd" → Oplossing: "1 zin, klaar" |
|
||
| **Interactive Demo** | Probeer Swift zonder login |
|
||
| **Side-by-side** | 12 klikken klassiek vs 1 zin Swift |
|
||
| **Video** | Demo van dagnotitie flow |
|
||
| **CTA** | "Aan de slag" → /login |
|
||
|
||
### 11.3 Login Pagina met Interface Keuze
|
||
|
||
De login pagina bevat een interface selector:
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ │
|
||
│ [Bestaand login formulier - email, wachtwoord] │
|
||
│ │
|
||
│ ───────────────────────────────────────────────────────────── │
|
||
│ │
|
||
│ Kies je werkwijze: │
|
||
│ │
|
||
│ ┌───────────────────────┐ ┌───────────────────────┐ │
|
||
│ │ ✨ Swift │ │ 📋 Klassiek │ │
|
||
│ │ │ │ │ │
|
||
│ │ Spreek of typ wat je │ │ Vertrouwde menu's │ │
|
||
│ │ wilt — het systeem │ │ en formulieren │ │
|
||
│ │ begrijpt │ │ │ │
|
||
│ │ │ │ │ │
|
||
│ │ "notitie jan med" → │ │ Dashboard → Patient │ │
|
||
│ │ klaar in 15 sec │ │ → Tab → Form → Save │ │
|
||
│ └───────────────────────┘ └───────────────────────┘ │
|
||
│ │
|
||
│ ☐ Onthoud mijn keuze │
|
||
│ │
|
||
│ [Inloggen] │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 11.4 Redirect Gedrag
|
||
|
||
| Situatie | Gedrag |
|
||
|----------|--------|
|
||
| Nieuwe user, geen preference | Toon keuze op login pagina |
|
||
| User met preference + "onthoud" | Direct door naar gekozen interface |
|
||
| User naar `/epd` | Redirect naar preference of dashboard |
|
||
| Uitgelogd | Terug naar login met keuze optie |
|
||
|
||
### 11.5 Geen Toggle in Interface
|
||
|
||
Er is **geen mogelijkheid** om binnen Swift of Klassiek EPD te wisselen naar de andere interface:
|
||
|
||
- Geen toggle button in Swift
|
||
- Geen toggle button in Klassiek EPD
|
||
- Om te wisselen: uitloggen → opnieuw inloggen → andere keuze
|
||
|
||
**Rationale:**
|
||
- Voorkomt verwarring over "waar ben ik"
|
||
- Gebruiker committed aan één ervaring
|
||
- Admin kan preference aanpassen indien nodig
|
||
|
||
### 11.6 Admin Beheer
|
||
|
||
Alleen admins kunnen de interface preference van andere users wijzigen:
|
||
|
||
| Actie | Wie | Waar |
|
||
|-------|-----|------|
|
||
| Eigen preference instellen | Alle users | Login pagina |
|
||
| Preference andere user wijzigen | Admin | Admin panel |
|
||
| Geforceerd naar Swift/Klassiek | Admin | Admin panel |
|
||
|
||
---
|
||
|
||
## 12. Bijlagen & Referenties
|
||
|
||
**Projectdocumenten:**
|
||
- PRD: `swift-prd.md`
|
||
- UX/UI: `swift-ux-v2.1.md`
|
||
- TO: `to-swift-v1.md`
|
||
- Taken analyse: `taken-en-vragen-analyse.md`
|
||
|
||
**Bestaande documentatie:**
|
||
- Database schema: Supabase migrations
|
||
- Bestaande FO overdracht: `fo-overdracht-dashboard-v1_1.md` (archive)
|
||
|
||
---
|
||
|
||
## Wijzigingslog
|
||
|
||
| Versie | Datum | Wijzigingen |
|
||
|--------|-------|-------------|
|
||
| 1.0 | 23-12-2024 | Initiële versie op basis van PRD en UX/UI v2.1 |
|
||
| 1.1 | 23-12-2024 | Hernoemd naar Swift, toegevoegd: Navigatie & Toegang sectie | |