feat(swift): E0 Setup & Foundation + documentatie
Swift - Contextual UI EPD: "Van 12 klikken naar 1 zin" Documentatie: - PRD, FO, TO, UX specificaties - Bouwplan met 6 epics, 27 stories (68 SP) - Analyse en onderzoeksdocumenten E0 Setup & Foundation: - E0.S1: Zustand v5.0.9 geïnstalleerd - E0.S2: Swift store met context, blocks, input state - E0.S3: /epd/swift route met eigen layout (dark theme) - E0.S4: Folder structuur components/swift/, lib/swift/ Components: - CommandCenter (container) - ContextBar (shift, patient) - CommandInput (text + voice button) - RecentStrip (laatste 5 acties) - BlockContainer (wrapper voor blocks) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
532
docs/swift/bouwplan-swift-v1.md
Normal file
532
docs/swift/bouwplan-swift-v1.md
Normal file
@@ -0,0 +1,532 @@
|
||||
# Mission Control — Bouwplan Swift v1.0
|
||||
|
||||
**Projectnaam:** Swift — Contextual UI EPD
|
||||
**Versie:** v1.0
|
||||
**Datum:** 23-12-2024
|
||||
**Auteur:** Colin Lit / Development Team
|
||||
|
||||
---
|
||||
|
||||
## 1. Doel en context
|
||||
|
||||
### 1.1 Projectdoel
|
||||
|
||||
Swift is een **Contextual UI** interface voor het Mini-EPD systeem. In plaats van navigatie door menu's spreekt of typt de gebruiker een intentie — en het juiste UI-blok verschijnt voorgevuld met relevante data.
|
||||
|
||||
**Kernbelofte:**
|
||||
> Van 12 klikken en 3 minuten naar 1 zin en 15 seconden.
|
||||
|
||||
### 1.2 Business Case
|
||||
|
||||
| Metric | Huidig | Met Swift | Besparing |
|
||||
|--------|--------|-----------|-----------|
|
||||
| Dagnotitie maken | 3-5 min | 15 sec | 95% |
|
||||
| Patiënt zoeken | 1-2 min | 5 sec | 95% |
|
||||
| Overdracht maken | 20-30 min | 5 min | 80% |
|
||||
| Rapportage schrijven | 8-15 min | 2-3 min | 75% |
|
||||
|
||||
**Per verpleegkundige per dag: ~4 uur terug naar zorg**
|
||||
|
||||
### 1.3 Relatie met Documentatie
|
||||
|
||||
| Document | Beschrijft | Locatie |
|
||||
|----------|------------|---------|
|
||||
| PRD | Product visie, requirements | `swift-prd.md` |
|
||||
| FO | Functionele flows, blocks | `swift-fo-ai.md` |
|
||||
| TO | Technische architectuur | `to-swift-v1.md` |
|
||||
| UX | Visuele specificaties | `swift-ux-v2.1.md` |
|
||||
|
||||
---
|
||||
|
||||
## 2. Uitgangspunten
|
||||
|
||||
### 2.1 Technische Stack
|
||||
|
||||
**Bestaand (hergebruiken):**
|
||||
| Component | Technologie | Versie |
|
||||
|-----------|-------------|--------|
|
||||
| Framework | Next.js | 14.2.18 |
|
||||
| UI Library | React | 18.3.1 |
|
||||
| Styling | TailwindCSS | 3.4.18 |
|
||||
| Components | shadcn/ui | - |
|
||||
| Command Palette | cmdk | 1.1.1 |
|
||||
| Animations | framer-motion | 12.23.24 |
|
||||
| Database | Supabase | 2.81.1 |
|
||||
| Speech-to-Text | Deepgram | 4.11.2 |
|
||||
| AI | Claude API | - |
|
||||
| Validation | Zod | 4.1.12 |
|
||||
| Forms | react-hook-form | 7.66.1 |
|
||||
|
||||
**Nieuw toe te voegen:**
|
||||
| Component | Technologie | Versie | Reden |
|
||||
|-----------|-------------|--------|-------|
|
||||
| State Management | Zustand | ^4.5.0 | Lightweight, TypeScript-first |
|
||||
|
||||
### 2.2 Projectkaders
|
||||
|
||||
| Kader | Waarde |
|
||||
|-------|--------|
|
||||
| **Bouwtijd** | 4 weken (4 sprints) |
|
||||
| **Team** | 1 developer |
|
||||
| **Scope** | MVP: P1 blocks (dagnotitie, zoeken, overdracht) |
|
||||
| **Data** | Bestaande Supabase database |
|
||||
| **Doel** | Werkende demo + user testing |
|
||||
|
||||
### 2.3 Programmeer Uitgangspunten
|
||||
|
||||
**Code Quality Principles:**
|
||||
|
||||
- **DRY (Don't Repeat Yourself)**
|
||||
- Herbruikbare block componenten
|
||||
- Centrale intent classificatie logica
|
||||
- Shared hooks voor common patterns
|
||||
|
||||
- **KISS (Keep It Simple, Stupid)**
|
||||
- Local-first intent classificatie (regex)
|
||||
- AI alleen als fallback
|
||||
- Minimale state complexity
|
||||
|
||||
- **SOC (Separation of Concerns)**
|
||||
- UI blocks gescheiden van intent logic
|
||||
- API routes gescheiden van business logic
|
||||
- Store slices per domein
|
||||
|
||||
- **YAGNI (You Aren't Gonna Need It)**
|
||||
- Alleen P1 blocks in MVP
|
||||
- Geen toggle tussen interfaces
|
||||
- Geen advanced analytics in v1
|
||||
|
||||
**Development Practices:**
|
||||
|
||||
```typescript
|
||||
// ✅ Goede structuur voor Swift components
|
||||
components/
|
||||
├── swift/
|
||||
│ ├── command-center/
|
||||
│ │ ├── command-center.tsx // Main container
|
||||
│ │ ├── command-input.tsx // Input component
|
||||
│ │ └── index.ts // Barrel export
|
||||
│ └── blocks/
|
||||
│ ├── dagnotitie-block.tsx
|
||||
│ ├── zoeken-block.tsx
|
||||
│ └── index.ts
|
||||
|
||||
// ✅ Store slice pattern
|
||||
stores/
|
||||
└── swift-store.ts // Single store file
|
||||
|
||||
// ✅ Intent classification
|
||||
lib/
|
||||
└── swift/
|
||||
├── intent-classifier.ts // Local classification
|
||||
├── intent-classifier-ai.ts // AI fallback
|
||||
└── types.ts // Type definitions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Epics & Stories Overzicht
|
||||
|
||||
| Epic ID | Titel | Doel | Status | Stories | Effort |
|
||||
|---------|-------|------|--------|---------|--------|
|
||||
| E0 | Setup & Foundation | Zustand, routing, base layout | ⏳ To Do | 4 | 8 SP |
|
||||
| E1 | Command Center | Input, voice, context bar | ⏳ To Do | 5 | 13 SP |
|
||||
| E2 | Intent Classification | Local + AI fallback | ⏳ To Do | 4 | 10 SP |
|
||||
| E3 | P1 Blocks | Dagnotitie, Zoeken, Overdracht | ⏳ To Do | 6 | 21 SP |
|
||||
| E4 | Navigation & Auth | Login keuze, routing, preferences | ⏳ To Do | 4 | 8 SP |
|
||||
| E5 | Polish & Testing | Animaties, error handling, tests | ⏳ To Do | 4 | 8 SP |
|
||||
|
||||
**Totaal: 27 stories, 68 story points**
|
||||
|
||||
**Belangrijk:**
|
||||
- Bouw per epic en per story, niet alles tegelijk
|
||||
- Dependencies installeren: eerst aan Colin melden
|
||||
- Database migraties: eerst aan Colin melden
|
||||
|
||||
---
|
||||
|
||||
## 4. Epics & Stories (Uitwerking)
|
||||
|
||||
### Epic 0 — Setup & Foundation
|
||||
**Epic Doel:** Werkende development omgeving met Zustand store en Swift routing.
|
||||
|
||||
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afh. | SP |
|
||||
|----------|--------------|---------------------|--------|------|----|
|
||||
| E0.S1 | Zustand installeren | `pnpm add zustand` succesvol, import werkt | ⏳ | — | 1 |
|
||||
| E0.S2 | Swift store opzetten | `stores/swift-store.ts` met basis state | ⏳ | E0.S1 | 2 |
|
||||
| E0.S3 | Swift route aanmaken | `/epd/swift` route met eigen layout | ⏳ | E0.S2 | 2 |
|
||||
| E0.S4 | Swift folder structuur | `components/swift/`, `lib/swift/` aangemaakt | ⏳ | E0.S3 | 3 |
|
||||
|
||||
**Technical Notes:**
|
||||
```bash
|
||||
# E0.S1: Dependency installatie
|
||||
pnpm add zustand
|
||||
```
|
||||
|
||||
```typescript
|
||||
// E0.S2: Store structuur
|
||||
// stores/swift-store.ts
|
||||
import { create } from 'zustand';
|
||||
import { devtools } from 'zustand/middleware';
|
||||
|
||||
interface SwiftStore {
|
||||
// Context
|
||||
activePatient: Patient | null;
|
||||
shift: 'nacht' | 'ochtend' | 'middag' | 'avond';
|
||||
|
||||
// Block state
|
||||
activeBlock: BlockType | null;
|
||||
prefillData: Record<string, unknown>;
|
||||
|
||||
// Actions
|
||||
setActivePatient: (patient: Patient | null) => void;
|
||||
openBlock: (type: BlockType, prefill?: Record<string, unknown>) => void;
|
||||
closeBlock: () => void;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Epic 1 — Command Center
|
||||
**Epic Doel:** Werkende command center met tekst en voice input.
|
||||
|
||||
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afh. | SP |
|
||||
|----------|--------------|---------------------|--------|------|----|
|
||||
| E1.S1 | Command Center layout | 4-zone layout (context, canvas, recent, input) | ⏳ | E0.S4 | 3 |
|
||||
| E1.S2 | Context Bar | Dienst, patiënt dropdown, user info | ⏳ | E1.S1 | 2 |
|
||||
| E1.S3 | Command Input | Tekst input met placeholder, focus state | ⏳ | E1.S1 | 2 |
|
||||
| E1.S4 | Voice Input integratie | Deepgram streaming in command input | ⏳ | E1.S3 | 3 |
|
||||
| E1.S5 | Recent Strip | Laatste 5 acties als chips | ⏳ | E1.S1 | 3 |
|
||||
|
||||
**Technical Notes:**
|
||||
```
|
||||
Command Center Layout:
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Context Bar (48px) │
|
||||
├─────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Canvas Area (flex) │
|
||||
│ │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Recent Strip (48px) │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Command Input (64px, fixed bottom) │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Epic 2 — Intent Classification
|
||||
**Epic Doel:** Two-tier intent classificatie (local + AI fallback).
|
||||
|
||||
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afh. | SP |
|
||||
|----------|--------------|---------------------|--------|------|----|
|
||||
| E2.S1 | Local classifier | Regex patterns voor P1 intents, <50ms | ⏳ | E0.S4 | 3 |
|
||||
| E2.S2 | Entity extraction | Patient naam, categorie uit input | ⏳ | E2.S1 | 3 |
|
||||
| E2.S3 | AI fallback | Claude Haiku bij confidence <0.8 | ⏳ | E2.S2 | 2 |
|
||||
| E2.S4 | Intent API route | POST /api/intent/classify | ⏳ | E2.S3 | 2 |
|
||||
|
||||
**Technical Notes:**
|
||||
```typescript
|
||||
// E2.S1: Local classifier patterns
|
||||
const INTENT_PATTERNS = {
|
||||
dagnotitie: [
|
||||
/^notitie\s+(\w+)/i,
|
||||
/^(\w+)\s+(medicatie|adl|gedrag|incident)/i,
|
||||
/dagnotitie/i,
|
||||
],
|
||||
zoeken: [
|
||||
/^zoek\s+(\w+)/i,
|
||||
/^wie is\s+(\w+)/i,
|
||||
/^vind\s+(\w+)/i,
|
||||
],
|
||||
overdracht: [
|
||||
/^overdracht/i,
|
||||
/^dienst (klaar|afronden)/i,
|
||||
/^wat moet ik weten/i,
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Epic 3 — P1 Blocks
|
||||
**Epic Doel:** Werkende DagnotatieBlock, ZoekenBlock en OverdrachtBlock.
|
||||
|
||||
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afh. | SP |
|
||||
|----------|--------------|---------------------|--------|------|----|
|
||||
| E3.S1 | Block Container | Animatie wrapper, close button, sizes | ⏳ | E1.S1 | 2 |
|
||||
| E3.S2 | DagnotatieBlock | Patient, categorie, tekst, opslaan | ⏳ | E3.S1, E2.S2 | 5 |
|
||||
| E3.S3 | Patient search API | GET /api/patients/search?q= fuzzy search | ⏳ | E0.S4 | 3 |
|
||||
| E3.S4 | ZoekenBlock | Input, resultaten, selectie → store | ⏳ | E3.S1, E3.S3 | 3 |
|
||||
| E3.S5 | PatientContextCard | Na selectie: notities, vitals, diagnose | ⏳ | E3.S4 | 5 |
|
||||
| E3.S6 | OverdrachtBlock | AI samenvatting per patiënt (bestaande API) | ⏳ | E3.S1 | 3 |
|
||||
|
||||
**Technical Notes:**
|
||||
```typescript
|
||||
// E3.S2: DagnotatieBlock prefill
|
||||
interface DagnotitieBlockProps {
|
||||
prefill?: {
|
||||
patientId?: string;
|
||||
patientName?: string;
|
||||
category?: VerpleegkundigCategory;
|
||||
content?: string;
|
||||
};
|
||||
onSave: () => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
// Gebruikt bestaande POST /api/reports
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Epic 4 — Navigation & Auth
|
||||
**Epic Doel:** Login pagina met interface keuze, routing naar Swift/Klassiek.
|
||||
|
||||
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afh. | SP |
|
||||
|----------|--------------|---------------------|--------|------|----|
|
||||
| E4.S1 | Login form uitbreiden | Interface selector (Swift/Klassiek) | ⏳ | E0.S3 | 2 |
|
||||
| E4.S2 | Preference opslag | user_metadata.preferred_interface | ⏳ | E4.S1 | 2 |
|
||||
| E4.S3 | Redirect middleware | /epd → preference route | ⏳ | E4.S2 | 2 |
|
||||
| E4.S4 | Fallback Picker | Visuele keuze bij lage confidence | ⏳ | E3.S1 | 2 |
|
||||
|
||||
**Technical Notes:**
|
||||
```typescript
|
||||
// E4.S2: Preference in Supabase
|
||||
await supabase.auth.updateUser({
|
||||
data: {
|
||||
preferred_interface: 'swift', // of 'classic'
|
||||
remember_interface_choice: true,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Epic 5 — Polish & Testing
|
||||
**Epic Doel:** Gepolijste UX met animaties, error handling en tests.
|
||||
|
||||
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afh. | SP |
|
||||
|----------|--------------|---------------------|--------|------|----|
|
||||
| E5.S1 | Block animaties | Slide up/down met framer-motion | ⏳ | E3.S1 | 2 |
|
||||
| E5.S2 | Error handling | Network errors, validation, toasts | ⏳ | E3.S6 | 2 |
|
||||
| E5.S3 | Keyboard shortcuts | Cmd+K focus, Escape close, Enter submit | ⏳ | E1.S3 | 2 |
|
||||
| E5.S4 | Smoke tests | Happy flow tests voor alle P1 blocks | ⏳ | E5.S2 | 2 |
|
||||
|
||||
**Technical Notes:**
|
||||
```typescript
|
||||
// E5.S1: Framer Motion animaties
|
||||
const blockVariants = {
|
||||
hidden: { opacity: 0, y: 20, scale: 0.95 },
|
||||
visible: { opacity: 1, y: 0, scale: 1 },
|
||||
exit: { opacity: 0, y: 20, scale: 0.95 },
|
||||
};
|
||||
|
||||
// E5.S3: Keyboard shortcuts
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
||||
e.preventDefault();
|
||||
inputRef.current?.focus();
|
||||
}
|
||||
if (e.key === 'Escape') {
|
||||
closeBlock();
|
||||
}
|
||||
};
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||
}, []);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Kwaliteit & Testplan
|
||||
|
||||
### 5.1 Test Types
|
||||
|
||||
| Test Type | Scope | Tools | Wanneer |
|
||||
|-----------|-------|-------|---------|
|
||||
| Unit Tests | Intent classifier, entity extraction | Vitest | E2 |
|
||||
| Integration Tests | API endpoints | Vitest + MSW | E2, E3 |
|
||||
| Component Tests | Blocks, Command Center | React Testing Library | E3, E5 |
|
||||
| E2E Tests | Complete flows | Playwright (optioneel) | E5 |
|
||||
| Manual Tests | Demo scenarios | Checklist | E5 |
|
||||
|
||||
### 5.2 Test Coverage Targets
|
||||
|
||||
| Area | Target | Reden |
|
||||
|------|--------|-------|
|
||||
| Intent classifier | 90%+ | Kritiek voor UX |
|
||||
| API routes | 80%+ | Data integrity |
|
||||
| UI components | 60%+ | Belangrijkste flows |
|
||||
|
||||
### 5.3 Manual Test Checklist (MVP Demo)
|
||||
|
||||
**Happy Flows:**
|
||||
- [ ] User kan inloggen en Swift kiezen
|
||||
- [ ] Command input krijgt focus met Cmd+K
|
||||
- [ ] "notitie jan medicatie" → DagnotatieBlock opent met prefill
|
||||
- [ ] Dagnotitie opslaan → toast + block sluit
|
||||
- [ ] "zoek marie" → ZoekenBlock met resultaten
|
||||
- [ ] Patiënt selecteren → PatientContextCard
|
||||
- [ ] "overdracht" → OverdrachtBlock met AI samenvatting
|
||||
- [ ] Voice input → transcript in command input
|
||||
|
||||
**Error Scenarios:**
|
||||
- [ ] Onbekende intent → FallbackPicker
|
||||
- [ ] Network error → toast met retry
|
||||
- [ ] Lege notitie → validation error
|
||||
- [ ] Geen zoekresultaten → "Geen patiënten gevonden"
|
||||
|
||||
---
|
||||
|
||||
## 6. Demo & Presentatieplan
|
||||
|
||||
### 6.1 Demo Scenario
|
||||
|
||||
**Duur:** 10 minuten
|
||||
**Doelgroep:** Zorgprofessionals, management
|
||||
**Locatie:** Live op Vercel
|
||||
|
||||
**Flow:**
|
||||
|
||||
```
|
||||
1. INTRO (1 min)
|
||||
"40% van je tijd gaat naar administratie.
|
||||
Wat als je gewoon kon zeggen wat je wilt?"
|
||||
|
||||
2. CONTRAST (2 min)
|
||||
Klassiek EPD: Dashboard → Patiënten → Jan → Rapportages →
|
||||
Nieuwe → Type → Tekst → Opslaan
|
||||
Swift: "notitie jan medicatie gegeven" → Opslaan
|
||||
|
||||
3. DAGNOTITIE FLOW (2 min)
|
||||
- Typ: "notitie jan medicatie uitgereikt"
|
||||
- Block verschijnt voorgevuld
|
||||
- Één klik: opgeslagen
|
||||
|
||||
4. VOICE DEMO (2 min)
|
||||
- Klik microfoon
|
||||
- Spreek: "marie had een rustige nacht, goed geslapen"
|
||||
- Block verschijnt met transcript
|
||||
|
||||
5. OVERDRACHT (2 min)
|
||||
- "overdracht"
|
||||
- AI genereert samenvatting per patiënt
|
||||
- Toon bronverwijzingen
|
||||
|
||||
6. AFSLUITING (1 min)
|
||||
- Tijdsbesparing recap
|
||||
- Vragen
|
||||
```
|
||||
|
||||
### 6.2 Backup Plan
|
||||
|
||||
| Probleem | Oplossing |
|
||||
|----------|-----------|
|
||||
| Internet issues | Localhost met demo data |
|
||||
| Voice niet werkt | Type-only demo |
|
||||
| AI API down | Pre-cached responses |
|
||||
| Complete failure | Video recording |
|
||||
|
||||
---
|
||||
|
||||
## 7. Risico's & Mitigatie
|
||||
|
||||
| Risico | Kans | Impact | Mitigatie | Owner |
|
||||
|--------|------|--------|-----------|-------|
|
||||
| Voice accuracy NL | Middel | Hoog | Deepgram NL model, fallback naar tekst | Dev |
|
||||
| Intent misclassificatie | Middel | Hoog | Two-tier systeem, FallbackPicker | Dev |
|
||||
| AI latency | Laag | Middel | Local-first, Haiku model | Dev |
|
||||
| User adoption | Middel | Middel | Keuze behouden, geen dwang | Product |
|
||||
| Scope creep | Hoog | Hoog | Strict P1-only, backlog voor rest | Dev |
|
||||
| Performance | Laag | Middel | Code splitting, lazy loading | Dev |
|
||||
|
||||
---
|
||||
|
||||
## 8. Sprint Planning
|
||||
|
||||
### Sprint 1 (Week 1): Foundation
|
||||
- E0: Setup & Foundation (8 SP)
|
||||
- E1.S1-S3: Command Center basics (7 SP)
|
||||
- **Deliverable:** Swift route met command input
|
||||
|
||||
### Sprint 2 (Week 2): Intent & Blocks
|
||||
- E1.S4-S5: Voice + Recent (6 SP)
|
||||
- E2: Intent Classification (10 SP)
|
||||
- **Deliverable:** Werkende intent classificatie
|
||||
|
||||
### Sprint 3 (Week 3): P1 Blocks
|
||||
- E3: Alle P1 blocks (21 SP)
|
||||
- **Deliverable:** DagnotatieBlock, ZoekenBlock, OverdrachtBlock
|
||||
|
||||
### Sprint 4 (Week 4): Polish & Ship
|
||||
- E4: Navigation & Auth (8 SP)
|
||||
- E5: Polish & Testing (8 SP)
|
||||
- **Deliverable:** Demo-ready MVP
|
||||
|
||||
---
|
||||
|
||||
## 9. Definition of Done
|
||||
|
||||
Een story is **Done** wanneer:
|
||||
- [ ] Code geschreven en werkend
|
||||
- [ ] TypeScript types correct
|
||||
- [ ] Component responsive (mobile + desktop)
|
||||
- [ ] Error states afgehandeld
|
||||
- [ ] Toegankelijkheid basics (focus, labels)
|
||||
- [ ] Getest in Chrome + Safari
|
||||
- [ ] PR reviewed (indien team)
|
||||
- [ ] Gemerged naar main
|
||||
|
||||
Een epic is **Done** wanneer:
|
||||
- [ ] Alle stories Done
|
||||
- [ ] Integration test passed
|
||||
- [ ] Demo scenario werkt
|
||||
|
||||
---
|
||||
|
||||
## 10. Referenties
|
||||
|
||||
### Project Documenten
|
||||
- PRD: `docs/swift/swift-prd.md`
|
||||
- FO: `docs/swift/swift-fo-ai.md`
|
||||
- TO: `docs/swift/to-swift-v1.md`
|
||||
- UX: `docs/swift/swift-ux-v2.1.md`
|
||||
|
||||
### Bestaande Code Referenties
|
||||
- Command component: `components/ui/command.tsx`
|
||||
- Speech streaming: `components/speech-recorder-streaming.tsx`
|
||||
- Overdracht API: `app/api/overdracht/generate/route.ts`
|
||||
- Report types: `lib/types/report.ts`
|
||||
|
||||
### External
|
||||
- Zustand: https://zustand-demo.pmnd.rs/
|
||||
- cmdk: https://cmdk.paco.me/
|
||||
- Deepgram: https://developers.deepgram.com/docs
|
||||
- Claude API: https://docs.anthropic.com/
|
||||
|
||||
---
|
||||
|
||||
## 11. Glossary
|
||||
|
||||
| Term | Betekenis |
|
||||
|------|-----------|
|
||||
| Swift | Projectnaam voor Contextual UI EPD |
|
||||
| Command Center | Hoofdscherm met één input |
|
||||
| Block | Ephemeral UI component (dagnotitie, zoeken, etc.) |
|
||||
| Intent | Gebruikersintentie (dagnotitie, zoeken, overdracht) |
|
||||
| Entity | Geëxtraheerde data (patiëntnaam, categorie) |
|
||||
| Prefill | Vooraf ingevulde data in block |
|
||||
| Klassiek EPD | Traditionele menu-gebaseerde interface |
|
||||
| P1 | Prioriteit 1 (MVP scope) |
|
||||
| SP | Story Points (Fibonacci: 1, 2, 3, 5, 8) |
|
||||
|
||||
---
|
||||
|
||||
**Versiehistorie:**
|
||||
|
||||
| Versie | Datum | Auteur | Wijziging |
|
||||
|--------|-------|--------|-----------|
|
||||
| v1.0 | 23-12-2024 | Colin Lit | Initiële versie |
|
||||
675
docs/swift/nextgen-epd-analyse-ephemeral-ui-perspectieven.md
Normal file
675
docs/swift/nextgen-epd-analyse-ephemeral-ui-perspectieven.md
Normal file
@@ -0,0 +1,675 @@
|
||||
# Analyse Ephemeral UI EPD - Multi-Perspectief Review
|
||||
|
||||
**Document:** Analyse PRD Ephemeral UI EPD v1.0
|
||||
**Datum:** december 2024
|
||||
**Reviewers:** Lead Developer, UX Designer, Frontend Developer, Product Owner
|
||||
|
||||
---
|
||||
|
||||
## 1. Lead Developer Perspectief
|
||||
|
||||
### 1.1 Technische Haalbaarheid
|
||||
|
||||
**Verdict:** ✅ Haalbaar met bestaande stack
|
||||
|
||||
De PRD vraagt om functionaliteit die grotendeels al bestaat in de codebase. De technische uitdaging zit niet in de bouwblokken zelf, maar in de orchestratielaag.
|
||||
|
||||
**Wat we al hebben:**
|
||||
| Component | Status | Kwaliteit |
|
||||
|-----------|--------|-----------|
|
||||
| Next.js 14 App Router | ✅ | Production-ready |
|
||||
| Supabase Auth + RLS | ✅ | Volledig geconfigureerd |
|
||||
| Claude API integratie | ✅ | Werkt voor behandelplan + overdracht |
|
||||
| Deepgram STT | ✅ | Streaming + batch transcriptie |
|
||||
| TipTap Rich Text | ✅ | Met voice-insert support |
|
||||
| shadcn/ui + Tailwind | ✅ | 20+ componenten |
|
||||
|
||||
**Wat nieuw gebouwd moet worden:**
|
||||
|
||||
```
|
||||
Prioriteit 1 (Kritiek):
|
||||
├── /api/intent/classify # AI intent classificatie
|
||||
├── /app/command-center # Nieuwe entry point
|
||||
└── stores/commandCenter.ts # State management
|
||||
|
||||
Prioriteit 2 (Bouwblok wrappers):
|
||||
├── components/building-blocks/BlockContainer.tsx
|
||||
├── components/building-blocks/PatientResolver.tsx
|
||||
└── components/building-blocks/EntityExtractor.tsx
|
||||
|
||||
Prioriteit 3 (Nieuwe blokken):
|
||||
├── ZoekenBlock.tsx # Patient search UI
|
||||
└── MetingenBlock.tsx # Vitals input form
|
||||
```
|
||||
|
||||
### 1.2 Architectuurbeslissingen
|
||||
|
||||
**State Management:**
|
||||
Aanbeveling: **Zustand** boven Context API
|
||||
- Command Center heeft complexe state (activeBlock, activePatient, transcript, recentActions)
|
||||
- Zustand is al impliciet beschikbaar via React patterns in codebase
|
||||
- Geen prop drilling, geen provider nesting
|
||||
|
||||
```typescript
|
||||
// Voorgestelde store structuur
|
||||
interface CommandCenterStore {
|
||||
// UI State
|
||||
activeBlock: BlockType | null;
|
||||
isListening: boolean;
|
||||
transcript: string;
|
||||
|
||||
// Context
|
||||
activePatient: Patient | null;
|
||||
recentActions: Action[];
|
||||
shiftInfo: ShiftInfo;
|
||||
|
||||
// Pre-fill data extracted from intent
|
||||
prefillData: Record<string, unknown>;
|
||||
}
|
||||
```
|
||||
|
||||
**Intent Classification:**
|
||||
Aanbeveling: **Streaming response** met confidence threshold
|
||||
|
||||
```typescript
|
||||
// Twee-staps flow
|
||||
1. Quick classification (<100ms): regex + keyword matching
|
||||
2. AI fallback (>100ms): Claude voor ambigue input
|
||||
|
||||
// Voorbeeld
|
||||
"notitie jan" → Quick match: intent=dagnotitie, patient="jan"
|
||||
"ik heb net iets besproken" → AI needed: wat? met wie?
|
||||
```
|
||||
|
||||
**API Design:**
|
||||
```
|
||||
POST /api/intent/classify
|
||||
Input: { text: string, context: { activePatient?, shift? } }
|
||||
Output: { intent, confidence, entities, clarification? }
|
||||
|
||||
GET /api/context
|
||||
Output: { user, shift, patients, pendingItems }
|
||||
```
|
||||
|
||||
### 1.3 Risico's & Mitigaties
|
||||
|
||||
| Risico | Impact | Mitigatie |
|
||||
|--------|--------|-----------|
|
||||
| Intent misclassificatie | Hoog | Fallback naar blok-selector UI |
|
||||
| Latency AI calls | Medium | Local-first matching, AI als fallback |
|
||||
| Entity extraction fout | Medium | "Bedoelde je X?" confirmation flow |
|
||||
| State sync issues | Medium | Optimistic UI + server reconciliation |
|
||||
| Voice in lawaaierige omgeving | Medium | Push-to-talk, geen continuous listening |
|
||||
|
||||
### 1.4 Technische Schuld Risico
|
||||
|
||||
**Laag risico** - We bouwen bovenop bestaande patterns:
|
||||
- Bestaande API routes blijven werken
|
||||
- Bouwblokken zijn wrappers rond bestaande componenten
|
||||
- Geen database schema wijzigingen nodig
|
||||
- Geen breaking changes voor huidige EPD flows
|
||||
|
||||
### 1.5 Aanbeveling
|
||||
|
||||
**Go/No-Go:** ✅ GO
|
||||
|
||||
Start met Command Center + Intent API + 2 blokken (Rapportage, Dagnotitie).
|
||||
Itereer op basis van intent accuracy metrics voordat we alle 8 blokken bouwen.
|
||||
|
||||
---
|
||||
|
||||
## 2. UX Designer Perspectief
|
||||
|
||||
### 2.1 Concept Evaluatie
|
||||
|
||||
**De belofte:** Van 12 klikken naar 1 zin.
|
||||
|
||||
Dit is een fundamentele paradigma-shift. Geen menu's, geen navigatie-leren, geen "waar zit dat ook alweer?" De gebruiker spreekt intentie, het systeem reageert.
|
||||
|
||||
**Sterktes van het concept:**
|
||||
|
||||
1. **Cognitive load reductie** - Zorgverleners hoeven geen mentaal model van het EPD te hebben
|
||||
2. **Context-awareness** - Systeem weet wie je bent, welke dienst, welke patiënten
|
||||
3. **Hands-free potentieel** - Voice-first past bij zorg (handschoenen, hygiëne)
|
||||
4. **Ephemeral = focus** - Alleen wat je nu nodig hebt, geen afleiding
|
||||
|
||||
**Zorgen:**
|
||||
|
||||
1. **Discoverability** - Hoe weet de gebruiker wat mogelijk is?
|
||||
2. **Error recovery** - Wat als het systeem verkeerd begrijpt?
|
||||
3. **Power users** - Willen sommigen toch sneltoetsen/directe toegang?
|
||||
4. **Trust** - "Heeft het systeem mijn notitie wel opgeslagen?"
|
||||
|
||||
### 2.2 Interaction Design Analyse
|
||||
|
||||
**Command Center Flow:**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ 🎤 Wat wil je doen? │ │
|
||||
│ │ ____________________________________________ │ │
|
||||
│ │ │ │
|
||||
│ │ 💡 Voorbeelden: "notitie voor Jan", "overdracht", │ │
|
||||
│ │ "mijn afspraken", "zoek Marie" │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Context: Ochtend dienst · 8 patiënten · 2 actiepunten │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ [ Actief bouwblok verschijnt hier ] │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Recent: [Jan - Notitie ✓] [Overdracht 14:00] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Kritieke UX Momenten:**
|
||||
|
||||
| Moment | Risico | Design Oplossing |
|
||||
|--------|--------|------------------|
|
||||
| Eerste gebruik | "Wat kan ik zeggen?" | Voorbeelden tonen, onboarding hints |
|
||||
| Ambigue input | Frustratie bij verkeerde interpretatie | "Bedoelde je..." met opties |
|
||||
| Mid-task switch | Context verlies | "Opslaan als concept?" modal |
|
||||
| Na voltooiing | Onzekerheid of het werkte | Duidelijke bevestiging + undo optie |
|
||||
| Geen match | Doodlopende straat | Fallback naar visuele blok-picker |
|
||||
|
||||
### 2.3 Microinteracties
|
||||
|
||||
**Voice Input Feedback:**
|
||||
```
|
||||
[Idle] → Grijze microfoon
|
||||
[Listening] → Pulserende blauwe ring + live transcript
|
||||
[Processing]→ Spinner + "Even denken..."
|
||||
[Matched] → Groene check + smooth transition naar blok
|
||||
[Unclear] → Oranje indicator + clarificatie vraag
|
||||
```
|
||||
|
||||
**Blok Transities:**
|
||||
- **In:** Slide-up met fade (200ms)
|
||||
- **Minimize:** Collapse naar badge in "Recent" row
|
||||
- **Close:** Fade-out met success toast
|
||||
|
||||
**Pre-fill Animatie:**
|
||||
Wanneer systeem velden invult op basis van intent:
|
||||
- Velden highlighten kort (geel flash)
|
||||
- Sequential fill (niet alles tegelijk)
|
||||
- "Automatisch ingevuld" label bij pre-filled velden
|
||||
|
||||
### 2.4 Accessibility Overwegingen
|
||||
|
||||
| Aspect | Vereiste | Implementatie |
|
||||
|--------|----------|---------------|
|
||||
| Keyboard-only | Moet volledig werken zonder voice | Tab navigation, Enter to submit |
|
||||
| Screen readers | Blok-wissels aangekondigd | ARIA live regions |
|
||||
| Motor impairments | Grote touch targets | Min 44x44px buttons |
|
||||
| Cognitieve load | Niet te veel tegelijk | Max 1 actief blok |
|
||||
|
||||
### 2.5 Fallback Strategie
|
||||
|
||||
**De "Noodrem":**
|
||||
Als conversational interface faalt, moet er altijd een visuele fallback zijn.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Ik begreep dat niet helemaal. Wat wil je doen? │
|
||||
│ │
|
||||
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||||
│ │ 📝 │ │ 👤 │ │ 📋 │ │ 🔄 │ │
|
||||
│ │Notitie │ │ Intake │ │ Plan │ │Overdracht│ │
|
||||
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
|
||||
│ │
|
||||
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||||
│ │ 🔍 │ │ 📅 │ │ 💊 │ │ 📊 │ │
|
||||
│ │ Zoeken │ │ Agenda │ │Medicatie│ │Metingen │ │
|
||||
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.6 Aanbeveling
|
||||
|
||||
**Go/No-Go:** ✅ GO met voorwaarden
|
||||
|
||||
1. Bouw de fallback picker EERST - dit is je vangnet
|
||||
2. Investeer in microinteracties - ze maken of breken de "magie"
|
||||
3. User testing na eerste 2 blokken - niet na alle 8
|
||||
4. Metrics verzamelen: intent accuracy, tijd-tot-taak, fallback usage
|
||||
|
||||
---
|
||||
|
||||
## 3. Frontend Developer Perspectief
|
||||
|
||||
### 3.1 Component Architectuur
|
||||
|
||||
**Huidige staat:** Goed gestructureerd, maar bouwblok-specifiek
|
||||
|
||||
We moeten bestaande componenten wrappen om ze "ephemeral" te maken. Dit vereist een abstractielaag.
|
||||
|
||||
**Voorgestelde structuur:**
|
||||
|
||||
```
|
||||
components/
|
||||
├── building-blocks/
|
||||
│ ├── core/
|
||||
│ │ ├── BlockContainer.tsx # Wrapper met header, minimize, close
|
||||
│ │ ├── BlockHeader.tsx # Titel + acties
|
||||
│ │ ├── BlockFooter.tsx # Save/Cancel buttons
|
||||
│ │ └── PrefilledField.tsx # Highlight voor auto-filled
|
||||
│ │
|
||||
│ ├── rapportage/
|
||||
│ │ ├── RapportageBlock.tsx # Wrapper rond ReportComposer
|
||||
│ │ └── RapportageBlock.types.ts
|
||||
│ │
|
||||
│ ├── dagnotitie/
|
||||
│ │ ├── DagnotitieBlock.tsx # Quick entry form
|
||||
│ │ └── DagnotitieBlock.types.ts
|
||||
│ │
|
||||
│ ├── zoeken/
|
||||
│ │ ├── ZoekenBlock.tsx # cmdk-based search
|
||||
│ │ ├── PatientCard.tsx # Search result card
|
||||
│ │ └── ZoekenBlock.types.ts
|
||||
│ │
|
||||
│ └── ... (andere blokken)
|
||||
│
|
||||
├── command-center/
|
||||
│ ├── CommandInput.tsx # Text + voice input
|
||||
│ ├── VoiceIndicator.tsx # Listening state UI
|
||||
│ ├── ContextBar.tsx # Shift info, patient count
|
||||
│ ├── RecentActions.tsx # Minimized blocks
|
||||
│ ├── BlockPicker.tsx # Fallback grid
|
||||
│ └── ClarificationDialog.tsx # "Bedoelde je...?"
|
||||
```
|
||||
|
||||
### 3.2 Hergebruik Analyse
|
||||
|
||||
**Direct herbruikbaar (copy):**
|
||||
```typescript
|
||||
// Volledig herbruikbaar
|
||||
import { RichTextEditor } from '@/components/rich-text-editor'
|
||||
import { SpeechRecorder } from '@/components/speech-recorder'
|
||||
import { Timeline } from '@/components/ui/timeline'
|
||||
import { Command } from '@/components/ui/command' // voor zoeken
|
||||
|
||||
// Bestaande forms met minimale aanpassing
|
||||
ReportComposer → RapportageBlock (wrap + simplify)
|
||||
BehandelplanView → BehandelplanBlock (read-only + edit mode toggle)
|
||||
AgendaCalendar → AgendaBlock (date-filtered view)
|
||||
```
|
||||
|
||||
**Moet gerefactored worden:**
|
||||
```typescript
|
||||
// Te gekoppeld aan page-specifieke logica
|
||||
IntakeTabs → Moet ontkoppeld van [intakeId] routing
|
||||
VitalsBlock → Alleen display, geen input form
|
||||
PatientList → Moet naar PatientCard + search results
|
||||
```
|
||||
|
||||
**Nieuw te bouwen:**
|
||||
```typescript
|
||||
// Helemaal nieuw
|
||||
CommandInput.tsx // ~150 lines
|
||||
BlockContainer.tsx // ~100 lines
|
||||
ZoekenBlock.tsx // ~200 lines
|
||||
MetingenBlock.tsx // ~150 lines
|
||||
DagnotitieBlock.tsx // ~120 lines (simplified from ReportComposer)
|
||||
ClarificationDialog.tsx // ~80 lines
|
||||
```
|
||||
|
||||
### 3.3 State Management Implementatie
|
||||
|
||||
**Keuze: Zustand**
|
||||
|
||||
```typescript
|
||||
// stores/command-center-store.ts
|
||||
import { create } from 'zustand'
|
||||
import { devtools, persist } from 'zustand/middleware'
|
||||
|
||||
interface CommandCenterState {
|
||||
// Block state
|
||||
activeBlock: BlockType | null
|
||||
blockData: Record<string, unknown>
|
||||
minimizedBlocks: MinimizedBlock[]
|
||||
|
||||
// Context
|
||||
activePatient: Patient | null
|
||||
shiftInfo: ShiftInfo | null
|
||||
|
||||
// Voice
|
||||
isListening: boolean
|
||||
transcript: string
|
||||
interimTranscript: string
|
||||
|
||||
// Recent
|
||||
recentActions: Action[]
|
||||
|
||||
// Actions
|
||||
openBlock: (type: BlockType, prefill?: Record<string, unknown>) => void
|
||||
closeBlock: () => void
|
||||
minimizeBlock: () => void
|
||||
setActivePatient: (patient: Patient | null) => void
|
||||
setTranscript: (text: string) => void
|
||||
addRecentAction: (action: Action) => void
|
||||
}
|
||||
|
||||
export const useCommandCenter = create<CommandCenterState>()(
|
||||
devtools(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
// ... implementation
|
||||
}),
|
||||
{ name: 'command-center' }
|
||||
)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
### 3.4 Intent Handling Flow
|
||||
|
||||
```typescript
|
||||
// hooks/use-intent.ts
|
||||
export function useIntent() {
|
||||
const { openBlock, setActivePatient, activePatient } = useCommandCenter()
|
||||
|
||||
const processInput = async (text: string) => {
|
||||
// 1. Quick local match
|
||||
const quickMatch = quickClassify(text)
|
||||
if (quickMatch.confidence > 0.9) {
|
||||
return handleIntent(quickMatch)
|
||||
}
|
||||
|
||||
// 2. AI classification
|
||||
const result = await fetch('/api/intent/classify', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
text,
|
||||
context: { activePatient }
|
||||
})
|
||||
}).then(r => r.json())
|
||||
|
||||
// 3. Handle result
|
||||
if (result.clarification_needed) {
|
||||
return { type: 'clarify', question: result.clarification_question }
|
||||
}
|
||||
|
||||
if (result.entities.patient_name && !activePatient) {
|
||||
const patient = await resolvePatient(result.entities.patient_name)
|
||||
if (patient.length > 1) {
|
||||
return { type: 'select_patient', options: patient }
|
||||
}
|
||||
setActivePatient(patient[0])
|
||||
}
|
||||
|
||||
openBlock(result.intent, result.entities)
|
||||
return { type: 'success', block: result.intent }
|
||||
}
|
||||
|
||||
return { processInput }
|
||||
}
|
||||
```
|
||||
|
||||
### 3.5 Performance Optimalisatie
|
||||
|
||||
**Bundle splitting:**
|
||||
```typescript
|
||||
// Lazy load blokken
|
||||
const RapportageBlock = dynamic(
|
||||
() => import('@/components/building-blocks/rapportage/RapportageBlock'),
|
||||
{ loading: () => <BlockSkeleton /> }
|
||||
)
|
||||
|
||||
const BehandelplanBlock = dynamic(
|
||||
() => import('@/components/building-blocks/behandelplan/BehandelplanBlock'),
|
||||
{ loading: () => <BlockSkeleton /> }
|
||||
)
|
||||
```
|
||||
|
||||
**Prefetching:**
|
||||
```typescript
|
||||
// Prefetch meest gebruikte blokken bij mount
|
||||
useEffect(() => {
|
||||
import('@/components/building-blocks/rapportage/RapportageBlock')
|
||||
import('@/components/building-blocks/dagnotitie/DagnotitieBlock')
|
||||
}, [])
|
||||
```
|
||||
|
||||
**Voice optimization:**
|
||||
```typescript
|
||||
// Reuse Deepgram connection
|
||||
const deepgramRef = useRef<DeepgramConnection | null>(null)
|
||||
|
||||
// Start listening immediately on mic click (no API call delay)
|
||||
// Token already fetched at mount
|
||||
```
|
||||
|
||||
### 3.6 Testing Strategy
|
||||
|
||||
```typescript
|
||||
// Kritieke test scenarios
|
||||
describe('CommandCenter', () => {
|
||||
it('opens RapportageBlock for "notitie voor jan"')
|
||||
it('asks clarification for ambiguous input')
|
||||
it('pre-fills patient when mentioned by name')
|
||||
it('falls back to BlockPicker on unknown intent')
|
||||
it('minimizes block and shows in recent')
|
||||
it('restores minimized block on click')
|
||||
})
|
||||
|
||||
describe('Intent Classification', () => {
|
||||
it('handles Dutch medical vocabulary')
|
||||
it('extracts patient name from natural speech')
|
||||
it('returns low confidence for gibberish')
|
||||
})
|
||||
```
|
||||
|
||||
### 3.7 Aanbeveling
|
||||
|
||||
**Go/No-Go:** ✅ GO
|
||||
|
||||
**Geschatte effort:**
|
||||
|
||||
| Component | Uren | Complexiteit |
|
||||
|-----------|------|--------------|
|
||||
| CommandCenter layout | 4h | Low |
|
||||
| CommandInput + Voice | 6h | Medium |
|
||||
| BlockContainer abstraction | 4h | Medium |
|
||||
| RapportageBlock wrapper | 3h | Low |
|
||||
| DagnotitieBlock (new) | 5h | Medium |
|
||||
| ZoekenBlock (new) | 6h | Medium |
|
||||
| Intent API route | 4h | Medium |
|
||||
| Zustand store | 3h | Low |
|
||||
| Animations/transitions | 4h | Low |
|
||||
| **Totaal MVP** | **~40h** | - |
|
||||
|
||||
---
|
||||
|
||||
## 4. Product Owner Perspectief
|
||||
|
||||
### 4.1 Business Case Analyse
|
||||
|
||||
**Doelstelling:** Demo-ready voor Nedap gesprek (7 jan)
|
||||
|
||||
Dit is een **showcase project** met twee doelen:
|
||||
1. Thought leadership positionering
|
||||
2. Concrete gespreksstarter voor enterprise partnerships
|
||||
|
||||
**ROI Potentieel:**
|
||||
|
||||
| Metric | Traditioneel EPD | Ephemeral UI | Impact |
|
||||
|--------|------------------|--------------|--------|
|
||||
| Tijd per rapportage | 3-5 min | <1 min | 70% reductie |
|
||||
| Klikken per actie | 8-15 | 1-3 | 80% reductie |
|
||||
| Training tijd | 2-4 dagen | 1 uur | 90% reductie |
|
||||
| Error rate (verkeerde scherm) | 15% | <5% | 70% reductie |
|
||||
|
||||
### 4.2 Scope Prioritering
|
||||
|
||||
**Must Have (Demo MVP):**
|
||||
- [ ] Command Center met text input
|
||||
- [ ] Voice input (Deepgram werkt al)
|
||||
- [ ] 2 werkende blokken: Rapportage + Dagnotitie
|
||||
- [ ] Intent classification (happy path)
|
||||
- [ ] Pre-fill van patient naam
|
||||
- [ ] Visuele fallback (blok picker)
|
||||
|
||||
**Should Have (Demo Enhanced):**
|
||||
- [ ] Overdracht blok met AI samenvatting
|
||||
- [ ] Zoeken blok
|
||||
- [ ] Recent actions tracking
|
||||
- [ ] Context bar (dienst info)
|
||||
- [ ] Animaties en polish
|
||||
|
||||
**Could Have (Post-Demo):**
|
||||
- [ ] Behandelplan blok
|
||||
- [ ] Agenda blok
|
||||
- [ ] Metingen blok
|
||||
- [ ] Intake blok
|
||||
- [ ] Multi-patient context switching
|
||||
|
||||
**Won't Have (v1):**
|
||||
- Offline mode
|
||||
- Mobile native app
|
||||
- Multi-user realtime
|
||||
- FHIR integratie
|
||||
- Full ambient listening
|
||||
|
||||
### 4.3 Risico Assessment
|
||||
|
||||
| Risico | Waarschijnlijkheid | Impact | Mitigatie |
|
||||
|--------|-------------------|--------|-----------|
|
||||
| Demo niet klaar 7 jan | Medium | Hoog | Focus op 2 blokken, polish later |
|
||||
| Intent accuracy <85% | Medium | Hoog | Fallback UI prominent aanwezig |
|
||||
| Voice werkt niet live | Laag | Medium | Tekst input als backup |
|
||||
| Nedap niet geïnteresseerd | Medium | Medium | Parallel outreach naar andere partijen |
|
||||
| "Speeltje" perceptie | Medium | Medium | Focus op tijdsbesparing metrics |
|
||||
|
||||
### 4.4 Stakeholder Waarde
|
||||
|
||||
**Voor Zorgverleners:**
|
||||
- Minder administratie, meer tijd voor zorg
|
||||
- Geen menu-navigatie stress
|
||||
- Voice input tijdens handeling
|
||||
|
||||
**Voor Zorgorganisaties:**
|
||||
- Lagere training kosten
|
||||
- Hogere EPD adoptie
|
||||
- Minder documentatie-fouten
|
||||
|
||||
**Voor IT/Beheer:**
|
||||
- Moderne tech stack (Next.js, Supabase)
|
||||
- AI-first architectuur
|
||||
- Schaalbaar en maintainable
|
||||
|
||||
### 4.5 Demo Scenario's
|
||||
|
||||
**Scenario 1: De Drukke Ochtend (2 min)**
|
||||
```
|
||||
Verpleegkundige start dienst → Command Center opent
|
||||
"Mijn patiënten vandaag" → Overzicht met prioriteiten
|
||||
"Notitie voor Jan de Vries: medicatie uitgereikt, geen bijzonderheden"
|
||||
→ Dagnotitie pre-filled, 1-click save
|
||||
```
|
||||
|
||||
**Scenario 2: Na een Gesprek (1 min)**
|
||||
```
|
||||
Behandelaar na sessie → Voice inspreken
|
||||
"Ik heb net een gesprek gehad met mevrouw Jansen over haar angstklachten"
|
||||
→ Rapportage blok opent, patient pre-filled
|
||||
→ AI structureert de dictatie
|
||||
→ Save
|
||||
```
|
||||
|
||||
**Scenario 3: Overdracht (1 min)**
|
||||
```
|
||||
Dienst eindigt → "Overdracht"
|
||||
→ AI genereert samenvatting van de dag
|
||||
→ Aandachtspunten gemarkeerd
|
||||
→ Klaar voor collega
|
||||
```
|
||||
|
||||
### 4.6 Success Metrics
|
||||
|
||||
**Demo Success:**
|
||||
- [ ] 3 scenario's foutloos uitvoeren
|
||||
- [ ] <5 seconden van input tot blok open
|
||||
- [ ] "Wow" reactie van stakeholders
|
||||
- [ ] Concrete vervolgafspraak
|
||||
|
||||
**Product Success (post-launch):**
|
||||
- Intent accuracy >85%
|
||||
- Fallback usage <20%
|
||||
- Tijd-tot-taak 50% lager dan traditioneel
|
||||
- User satisfaction >4/5
|
||||
|
||||
### 4.7 Go-to-Market
|
||||
|
||||
**Fase 1: Internal Demo (Week 1-2)**
|
||||
- Bouwen MVP
|
||||
- Interne testing
|
||||
|
||||
**Fase 2: Stakeholder Demo (Week 3)**
|
||||
- Nedap presentatie (7 jan)
|
||||
- LinkedIn content (4 posts gepland)
|
||||
|
||||
**Fase 3: Pilot (Q1 2025)**
|
||||
- 1 zorginstelling
|
||||
- Real user feedback
|
||||
- Iteratie op intent accuracy
|
||||
|
||||
**Fase 4: Scale (Q2 2025)**
|
||||
- Meerdere instellingen
|
||||
- Enterprise features
|
||||
- Mogelijke partnership/overname gesprekken
|
||||
|
||||
### 4.8 Aanbeveling
|
||||
|
||||
**Go/No-Go:** ✅ GO
|
||||
|
||||
**Voorwaarden:**
|
||||
1. Scope beperken tot 2-3 blokken voor demo
|
||||
2. Fallback UI is verplicht (geen "het werkt alleen met AI")
|
||||
3. Realistische demo verwachtingen (happy path)
|
||||
4. LinkedIn content parallel voorbereiden
|
||||
|
||||
---
|
||||
|
||||
## 5. Gezamenlijke Conclusie
|
||||
|
||||
### Consensus: ✅ GO
|
||||
|
||||
Alle vier de perspectieven zijn positief, met de volgende gedeelde voorwaarden:
|
||||
|
||||
**Kritieke Succesfactoren:**
|
||||
1. **Fallback first** - Bouw de visuele blok-picker voordat je intent bouwt
|
||||
2. **Scope discipline** - 2 blokken voor demo, niet 8
|
||||
3. **Intent accuracy** - Meet en optimaliseer continue
|
||||
4. **User testing vroeg** - Niet wachten tot alles "af" is
|
||||
|
||||
**Gedeelde Risico's:**
|
||||
- Intent misclassificatie (mitigatie: fallback UI)
|
||||
- Demo deadline druk (mitigatie: scope beperken)
|
||||
- "Speeltje" perceptie (mitigatie: focus op metrics)
|
||||
|
||||
**Next Steps:**
|
||||
1. [ ] Command Center basis layout (Frontend)
|
||||
2. [ ] Intent classification API (Lead Dev)
|
||||
3. [ ] UX mockups voor microinteracties (UX)
|
||||
4. [ ] Demo scenario scripts (PO)
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Decision Log
|
||||
|
||||
| Beslissing | Optie Gekozen | Rationale |
|
||||
|------------|---------------|-----------|
|
||||
| State management | Zustand | Lightweight, geen provider nesting |
|
||||
| Intent approach | Local + AI fallback | Snelheid + accuracy balans |
|
||||
| Voice library | Deepgram (bestaand) | Al geïntegreerd, werkt goed |
|
||||
| Blok architectuur | Wrapper pattern | Maximaal hergebruik bestaande code |
|
||||
| Demo scope | 2-3 blokken | Realistische deadline |
|
||||
|
||||
---
|
||||
|
||||
*Document gegenereerd op basis van PRD analyse en codebase review.*
|
||||
217
docs/swift/nextgen-epd-claude-vision-epd.txt
Normal file
217
docs/swift/nextgen-epd-claude-vision-epd.txt
Normal file
@@ -0,0 +1,217 @@
|
||||
> denk even mee als innovatie-expert en visonair. We hebben met moderne ai-tooling (jij, claude) een epd vrij traditioneel epd gebouwd. maar hoe zou een epd er over 5
|
||||
jaar uit zien?
|
||||
|
||||
● Goede vraag. Laat me meedenken over waar EPD's naartoe gaan.
|
||||
|
||||
Het huidige paradigma: formulieren invullen
|
||||
|
||||
Wat we nu gebouwd hebben (en wat 95% van de EPD's doet):
|
||||
- Mens vult data in → systeem slaat op → mens leest later terug
|
||||
- Gestructureerde formulieren, dropdown menus, verplichte velden
|
||||
- De zorgverlener werkt voor het systeem
|
||||
|
||||
Het paradigma over 5 jaar: ambient intelligence
|
||||
|
||||
1. Van input naar capture
|
||||
|
||||
Geen formulieren meer. Het systeem luistert mee tijdens zorgmomenten:
|
||||
- Gesprekken met patiënten worden real-time getranscribeerd
|
||||
- Computer vision herkent handelingen (ADL, medicatie toediening)
|
||||
- Wearables van patiënten streamen continuous vitals
|
||||
- De AI stelt: "Ik zag dat je mevrouw Jansen hielp met wassen en zij klaagde over pijn in haar heup - klopt dat?"
|
||||
|
||||
2. Van dossier naar co-piloot
|
||||
|
||||
Het EPD is niet meer een archief maar een assistent:
|
||||
- "Meneer de Vries heeft 3 nachten slecht geslapen, zijn medicatie is vorige week aangepast, en zijn dochter belt morgen. Wil je dit bespreken in de overdracht?"
|
||||
- Proactieve alerts: "Dit gedragspatroon lijkt op wat we 6 maanden geleden zagen voor de crisis"
|
||||
- Real-time beslissingsondersteuning tijdens het zorgmoment, niet achteraf
|
||||
|
||||
3. Van silos naar netwerk
|
||||
|
||||
- Alle zorgverleners (huisarts, specialist, thuiszorg, apotheek) zien dezelfde patiënt
|
||||
- AI vertaalt tussen domeinen: "De cardioloog schreef X, dat betekent voor jullie verpleegkundige zorg: Y"
|
||||
- Patiënt heeft eigen toegang en kan toevoegen aan hun dossier
|
||||
|
||||
4. Van reactief naar predictief
|
||||
|
||||
- Machine learning op populatieniveau voorspelt: "Patiënten met dit profiel hebben 40% kans op val binnen 2 weken"
|
||||
- Preventieve interventies worden voorgesteld vóór het incident
|
||||
- Resource planning: "Volgende week verwachten we 3 extra high-care momenten"
|
||||
|
||||
5. Van documentatie naar narratief
|
||||
|
||||
- AI genereert leesbare verhalen in plaats van bullet points
|
||||
- Automatische samenvatting op het juiste niveau (arts krijgt andere view dan familie)
|
||||
- Voice-first interface: "Wat is er gebeurd met mevrouw Jansen deze week?"
|
||||
|
||||
Concrete features die we nu al zouden kunnen bouwen
|
||||
|
||||
| Nu haalbaar | 2-3 jaar | 5 jaar |
|
||||
|--------------------------|--------------------------|-----------------------------|
|
||||
| Voice-to-text rapportage | Ambient transcriptie | Volledig hands-free capture |
|
||||
| AI-samenvattingen | Proactieve alerts | Predictieve interventies |
|
||||
| Gestructureerde data | Cross-systeem integratie | Unified patient graph |
|
||||
| Dashboard views | Conversational interface | AR/spatial computing |
|
||||
|
||||
De fundamentele shift
|
||||
|
||||
Nu: De zorgverlener is een data-entry clerk die ook zorg levert
|
||||
Straks: De zorgverlener levert zorg, het systeem observeert en ondersteunt
|
||||
|
||||
---
|
||||
Welke richting spreekt je aan? Ik kan dieper ingaan op een specifiek aspect, of we kunnen brainstormen over wat we nu al kunnen toevoegen aan dit prototype dat richting die visie beweegt.
|
||||
|
||||
> Hoe ziet dat er dan ongeveer uit? Wat voor forntend heb je dan?
|
||||
|
||||
● Goede vraag. Laat me het concreet maken.
|
||||
|
||||
Het huidige model: "Cockpit met 100 knoppen"
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ [Menu] [Patiënten] [Agenda] [Rapportage] [Medicatie] [...] │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ ┌──────────┐ ┌─────────────────────────────────────────┐ │
|
||||
│ │ Patient │ │ Formulier │ │
|
||||
│ │ Lijst │ │ ┌─────────────────────────────────────┐ │ │
|
||||
│ │ │ │ │ Categorie: [Dropdown ▼] │ │ │
|
||||
│ │ > Jansen │ │ │ Datum: [__/__/____] │ │ │
|
||||
│ │ Vries │ │ │ Tijd: [__:__] │ │ │
|
||||
│ │ Berg │ │ │ Beschrijving: │ │ │
|
||||
│ │ │ │ │ ┌─────────────────────────────────┐ │ │ │
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
│ │ │ │ │ └─────────────────────────────────┘ │ │ │
|
||||
│ │ │ │ │ [Opslaan] [Annuleren] │ │ │
|
||||
│ └──────────┘ └─────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
De zorgverlener moet: navigeren → zoeken → klikken → typen → valideren → opslaan
|
||||
|
||||
---
|
||||
Het toekomstige model: "Intelligente gesprekspartner"
|
||||
|
||||
Primaire interface: Conversationeel + Contextueel
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ Goedemiddag Marieke. Je hebt dienst op afdeling 2. │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ 🔴 Mevr. Jansen (K204) - onrustige nacht, 2x geval- │ │
|
||||
│ │ len, dochter belt om 14:00 │ │
|
||||
│ │ │ │
|
||||
│ │ 🟡 Dhr. de Vries (K208) - nieuwe medicatie sinds │ │
|
||||
│ │ gisteren, monitor bijwerkingen │ │
|
||||
│ │ │ │
|
||||
│ │ 🟢 6 andere patiënten - geen bijzonderheden │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ 🎤 "Ik kom net bij mevrouw Jansen, ze is wat │ │
|
||||
│ │ rustiger nu maar klaagt over hoofdpijn" │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ 💬 Genoteerd. Gezien de valincidenten vannacht en │ │
|
||||
│ │ de hoofdpijn - wil je dat ik de arts informeer? │ │
|
||||
│ │ │ │
|
||||
│ │ [Ja, informeer arts] [Nee, ik monitor zelf] │ │
|
||||
│ │ │ │
|
||||
│ │ 📋 Ik heb alvast toegevoegd: │ │
|
||||
│ │ • Observatie: rustiger, hoofdpijnklacht │ │
|
||||
│ │ • Link naar valincidenten vannacht │ │
|
||||
│ │ • Reminder: bel dochter 14:00 │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
---
|
||||
De shift in UI-paradigma's
|
||||
|
||||
| Aspect | Nu | Straks |
|
||||
|-----------|---------------------------|-------------------------------------------|
|
||||
| Navigatie | Menu's, tabs, breadcrumbs | Context-aware, AI bepaalt wat relevant is |
|
||||
| Input | Formulieren, dropdowns | Voice-first, bevestig/corrigeer |
|
||||
| Schermen | 50+ verschillende views | 2-3 adaptieve views |
|
||||
| Zoeken | Filters, queries | "Wat wil je weten?" |
|
||||
| Actie | Klik-klik-klik-opslaan | Conversatie → bevestiging |
|
||||
|
||||
---
|
||||
Drie hoofdmodi
|
||||
|
||||
1. Ambient modus (tijdens zorgverlening)
|
||||
┌──────────────────────────────┐
|
||||
│ 🎤 Luistert... │
|
||||
│ │
|
||||
│ Mevr. Jansen - K204 │
|
||||
│ ──────────────────────── │
|
||||
│ "...doet pijn als ik │
|
||||
│ zo beweeg..." │
|
||||
│ │
|
||||
│ 📝 Concept: │
|
||||
│ • Pijnklacht bij beweging │
|
||||
│ • Locatie: [vul aan] │
|
||||
│ │
|
||||
│ [Pauzeer] [Corrigeer] │
|
||||
└──────────────────────────────┘
|
||||
Klein, onopvallend, draait op telefoon/tablet/smart display in de kamer.
|
||||
|
||||
2. Overdracht modus (briefing)
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ OVERDRACHT 15:00 │
|
||||
│ │
|
||||
│ "Drie patiënten hebben aandacht nodig deze dienst. │
|
||||
│ Mevrouw Jansen heeft een onrustige nacht gehad met │
|
||||
│ twee valincidenten. Ze is nu rustiger maar klaagt │
|
||||
│ over hoofdpijn. Haar dochter belt om 14:00..." │
|
||||
│ │
|
||||
│ ▶️ 🔊 ●●●○○○○○○○ │
|
||||
│ │
|
||||
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||||
│ │ Jansen │ │ Vries │ │ Berg │ │
|
||||
│ │ 🔴 Hoog │ │ 🟡 Mid │ │ 🟢 Laag │ │
|
||||
│ └─────────┘ └─────────┘ └─────────┘ │
|
||||
│ │
|
||||
│ "Vertel me meer over mevrouw Jansen" │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
Voice-navigatie, visuele ondersteuning, drill-down on demand.
|
||||
|
||||
3. Deep-dive modus (wanneer je écht moet graven)
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 🔍 "Toon me alle valincidenten van Jansen afgelopen maand" │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 📊 Analyse: 4 incidenten in 30 dagen (verhoogd risico) │
|
||||
│ │
|
||||
│ Tijdlijn: Correlaties: │
|
||||
│ ────────── ───────────── │
|
||||
│ 12 dec (nacht) → Na slaapmed aanpassing │
|
||||
│ 18 dec (nacht) → Na slaapmed aanpassing │
|
||||
│ 18 dec (nacht) → Na slaapmed aanpassing │
|
||||
│ 8 dec (ochtend) → Lage bloeddruk gemeten │
|
||||
│ │
|
||||
│ 💡 Suggestie: Medicatiereview aanvragen? De incidenten │
|
||||
│ correleren met de slaapmed aanpassing van 10 dec. │
|
||||
│ │
|
||||
│ [Vraag medicatiereview aan] [Meer context] [Exporteer] │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
Nog steeds conversationeel, maar met rijke visualisatie.
|
||||
|
||||
---
|
||||
Technisch: wat verandert er?
|
||||
|
||||
| Component | Nu | Straks |
|
||||
|--------------------|--------------------|-------------------------------------|
|
||||
| Frontend framework | React + forms | React + conversational UI + voice |
|
||||
| State | Form state, CRUD | Conversation context, AI memory |
|
||||
| API | REST endpoints | Streaming, real-time, WebSocket |
|
||||
| Database | Relational queries | Vector search + semantic queries |
|
||||
| Auth | Login + RLS | Continuous auth (voice, biometrics) |
|
||||
|
||||
---
|
||||
Wat kunnen we nu bouwen als proof-of-concept?
|
||||
|
||||
1. Conversational rapportage - voice input → AI structureert → bevestig
|
||||
2. Smart overdracht - niet alleen samenvatten, maar prioriteren en adviseren
|
||||
3. Vraag-antwoord interface - "Wat is er gebeurd met Jansen deze week?"
|
||||
512
docs/swift/nextgen-epd-mvp-prioritering-ephemeral-ui.md
Normal file
512
docs/swift/nextgen-epd-mvp-prioritering-ephemeral-ui.md
Normal file
@@ -0,0 +1,512 @@
|
||||
# MVP & Prioritering Ephemeral UI EPD
|
||||
|
||||
**Document:** MVP Scope en Implementatie Prioritering
|
||||
**Datum:** december 2024
|
||||
**Status:** Definitief
|
||||
|
||||
---
|
||||
|
||||
## 1. MVP Definitie
|
||||
|
||||
### 1.1 Eén Zin
|
||||
|
||||
> **MVP = Een Command Center waarmee je met tekst of voice een dagnotitie of rapportage maakt, met automatische patient herkenning.**
|
||||
|
||||
### 1.2 MVP Scope
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ MVP SCOPE │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ IN SCOPE (Must Have) │
|
||||
│ ───────────────────── │
|
||||
│ ✓ Command Center pagina │
|
||||
│ ✓ Text input met intent herkenning │
|
||||
│ ✓ Voice input (Deepgram - bestaat al) │
|
||||
│ ✓ Dagnotitie blok │
|
||||
│ ✓ Zoeken blok │
|
||||
│ ✓ Patient pre-fill uit input │
|
||||
│ ✓ Fallback blok-picker │
|
||||
│ │
|
||||
│ SHOULD HAVE (Demo Enhanced) │
|
||||
│ ─────────────────────────── │
|
||||
│ ○ Rapportage blok │
|
||||
│ ○ Overdracht blok met AI │
|
||||
│ ○ Recent actions tracking │
|
||||
│ ○ Context bar (dienst info) │
|
||||
│ │
|
||||
│ OUT OF SCOPE (v1) │
|
||||
│ ───────────────── │
|
||||
│ ✗ Behandelplan blok │
|
||||
│ ✗ Intake blok │
|
||||
│ ✗ Agenda blok │
|
||||
│ ✗ Metingen blok │
|
||||
│ ✗ Ambient listening │
|
||||
│ ✗ Multi-user realtime │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.3 Waarom Deze Scope?
|
||||
|
||||
| Keuze | Rationale |
|
||||
|-------|-----------|
|
||||
| Dagnotitie eerst | Hoogste frequentie (20x/dag), simpelste form |
|
||||
| Zoeken als fundament | Elke actie begint met "wie" - zonder zoeken geen pre-fill |
|
||||
| Voice must-have | "Ik draag handschoenen" - zorg context vereist hands-free |
|
||||
| Fallback verplicht | Vertrouwen: nooit een doodlopende straat |
|
||||
| Geen behandelplan | Te complex, lage frequentie, bestaande UI voldoet |
|
||||
|
||||
---
|
||||
|
||||
## 2. Hergebruik Bestaande Code
|
||||
|
||||
### 2.1 Direct Herbruikbaar
|
||||
|
||||
| Component | Locatie | Hergebruik |
|
||||
|-----------|---------|------------|
|
||||
| **Speech Recorder** | `components/speech-recorder.tsx` | 100% - drop-in |
|
||||
| **Deepgram API** | `api/deepgram/transcribe/route.ts` | 100% - werkt |
|
||||
| **Toast System** | `lib/hooks/use-toast.ts` | 100% - feedback |
|
||||
| **Command (cmdk)** | `components/ui/command.tsx` | 90% - zoek basis |
|
||||
| **Dagregistratie Form** | `app/epd/dagregistratie/` | 80% - wrap als blok |
|
||||
| **Report Types** | `lib/types/report.ts` | 100% - validatie |
|
||||
| **Verpleegkundig API** | `api/reports/route.ts` | 100% - save |
|
||||
|
||||
### 2.2 Gedeeltelijk Herbruikbaar
|
||||
|
||||
| Component | Locatie | Aanpassing Nodig |
|
||||
|-----------|---------|------------------|
|
||||
| **Patient List** | `app/epd/verpleegrapportage/` | → PatientCard voor zoeken |
|
||||
| **EPD Layout** | `app/epd/layout.tsx` | → Command Center layout |
|
||||
| **Report Composer** | `app/epd/patients/[id]/rapportage/` | → RapportageBlock wrapper |
|
||||
|
||||
### 2.3 Nieuw te Bouwen
|
||||
|
||||
| Component | Geschatte Effort | Prioriteit |
|
||||
|-----------|------------------|------------|
|
||||
| `/app/command-center/page.tsx` | 4h | P1 |
|
||||
| `/api/intent/classify/route.ts` | 6h | P1 |
|
||||
| `CommandInput.tsx` | 3h | P1 |
|
||||
| `BlockContainer.tsx` | 2h | P1 |
|
||||
| `DagnotitieBlock.tsx` | 3h | P1 |
|
||||
| `ZoekenBlock.tsx` | 4h | P1 |
|
||||
| `FallbackPicker.tsx` | 2h | P1 |
|
||||
| `PatientResolver.ts` | 2h | P1 |
|
||||
| `useCommandCenter.ts` (store) | 3h | P1 |
|
||||
| **Totaal MVP** | **~29h** | - |
|
||||
|
||||
---
|
||||
|
||||
## 3. Prioritering: MoSCoW
|
||||
|
||||
### 3.1 Must Have (Release Blocker)
|
||||
|
||||
```
|
||||
M1. Command Center Layout
|
||||
└── Centrale pagina met input field
|
||||
└── Route: /command-center
|
||||
|
||||
M2. Intent Classification
|
||||
└── API endpoint dat input analyseert
|
||||
└── Returns: { intent, entities, confidence }
|
||||
|
||||
M3. Dagnotitie Blok
|
||||
└── Simpele form: patient, categorie, tekst
|
||||
└── Pre-fill support
|
||||
└── 1-click save
|
||||
|
||||
M4. Zoeken Blok
|
||||
└── Patient search met cmdk
|
||||
└── PatientCard met quick actions
|
||||
└── Set active patient
|
||||
|
||||
M5. Voice Input
|
||||
└── Deepgram integratie in Command input
|
||||
└── Live transcript display
|
||||
|
||||
M6. Fallback Picker
|
||||
└── Grid met blok icons
|
||||
└── Toont bij lage confidence of onbekende intent
|
||||
|
||||
M7. Patient Pre-fill
|
||||
└── Entity extraction uit input
|
||||
└── Patient name → ID resolver
|
||||
```
|
||||
|
||||
### 3.2 Should Have (Demo Value)
|
||||
|
||||
```
|
||||
S1. Rapportage Blok
|
||||
└── Wrapper rond bestaande ReportComposer
|
||||
└── Voice dictation in editor
|
||||
└── AI structurering knop
|
||||
|
||||
S2. Overdracht Blok
|
||||
└── AI samenvatting (API bestaat)
|
||||
└── Multi-patient view
|
||||
└── Bronverwijzingen
|
||||
|
||||
S3. Recent Actions
|
||||
└── Badge strip onder input
|
||||
└── Click to re-open
|
||||
|
||||
S4. Context Bar
|
||||
└── "Ochtend dienst | 8 patiënten"
|
||||
└── Shift awareness
|
||||
```
|
||||
|
||||
### 3.3 Could Have (Nice to Have)
|
||||
|
||||
```
|
||||
C1. Categorie Herkenning
|
||||
└── "medicatie" → Medicatie category
|
||||
└── Keyword mapping
|
||||
|
||||
C2. Animaties
|
||||
└── Block slide-in
|
||||
└── Pre-fill highlight
|
||||
└── Success celebration
|
||||
|
||||
C3. Keyboard Shortcuts
|
||||
└── Cmd+K → focus input
|
||||
└── Enter → submit
|
||||
└── Esc → close block
|
||||
|
||||
C4. Onboarding Hints
|
||||
└── "Probeer: notitie jan"
|
||||
└── First-time user guidance
|
||||
```
|
||||
|
||||
### 3.4 Won't Have (Explicit Out)
|
||||
|
||||
```
|
||||
W1. Behandelplan Blok - te complex, lage frequentie
|
||||
W2. Intake Blok - wizard is complex, 1x/maand
|
||||
W3. Agenda Blok - bestaande werkt, lage urgentie
|
||||
W4. Metingen Blok - lage waarde-perceptie
|
||||
W5. Ambient Listening - v2+ feature
|
||||
W6. Offline Mode - v2+ feature
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Implementatie Volgorde
|
||||
|
||||
### 4.1 Dependency Graph
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ Command Center │
|
||||
│ Layout │
|
||||
└────────┬────────┘
|
||||
│
|
||||
┌──────────────┼──────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ Voice │ │ Intent │ │ Fallback │
|
||||
│ Input │ │ API │ │ Picker │
|
||||
└────┬─────┘ └────┬─────┘ └──────────┘
|
||||
│ │
|
||||
│ ┌───────┴───────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ Zoeken │ │ Dagnotitie │
|
||||
│ Blok │ │ Blok │
|
||||
└──────┬───────┘ └──────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ Pre-fill │
|
||||
│ Logic │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
### 4.2 Sprint Planning
|
||||
|
||||
#### Sprint 1: Foundation (Dag 1-3)
|
||||
|
||||
| # | Taak | Afhankelijk van | Output |
|
||||
|---|------|-----------------|--------|
|
||||
| 1.1 | Command Center page layout | - | `/app/command-center/page.tsx` |
|
||||
| 1.2 | CommandInput component | 1.1 | Text input met submit |
|
||||
| 1.3 | BlockContainer wrapper | 1.1 | Generic block frame |
|
||||
| 1.4 | Zustand store setup | - | `useCommandCenter` hook |
|
||||
| 1.5 | Voice integratie | 1.2 | Mic button in input |
|
||||
|
||||
**Deliverable:** Command Center opent, voice werkt, geen blokken nog.
|
||||
|
||||
#### Sprint 2: Intent & Zoeken (Dag 4-6)
|
||||
|
||||
| # | Taak | Afhankelijk van | Output |
|
||||
|---|------|-----------------|--------|
|
||||
| 2.1 | Intent API route | - | `/api/intent/classify` |
|
||||
| 2.2 | Entity extraction | 2.1 | Patient name uit tekst |
|
||||
| 2.3 | Patient search API | - | `/api/patients/search` |
|
||||
| 2.4 | ZoekenBlock | 1.3, 2.3 | Patient cards + select |
|
||||
| 2.5 | Fallback picker | 1.3 | Grid met blok icons |
|
||||
|
||||
**Deliverable:** "zoek jan" werkt, patient selectie mogelijk.
|
||||
|
||||
#### Sprint 3: Dagnotitie Flow (Dag 7-9)
|
||||
|
||||
| # | Taak | Afhankelijk van | Output |
|
||||
|---|------|-----------------|--------|
|
||||
| 3.1 | DagnotitieBlock | 1.3 | Quick entry form |
|
||||
| 3.2 | Pre-fill logic | 2.2, 3.1 | Patient + categorie auto |
|
||||
| 3.3 | Save flow | 3.1 | Toast + recent badge |
|
||||
| 3.4 | Intent → Block routing | 2.1, 3.1 | "notitie jan" → block |
|
||||
|
||||
**Deliverable:** "notitie voor jan: medicatie gegeven" werkt end-to-end.
|
||||
|
||||
#### Sprint 4: Polish & Demo (Dag 10-12)
|
||||
|
||||
| # | Taak | Afhankelijk van | Output |
|
||||
|---|------|-----------------|--------|
|
||||
| 4.1 | RapportageBlock | 1.3 | Wrapper rond composer |
|
||||
| 4.2 | Recent actions strip | 3.3 | Clickable badges |
|
||||
| 4.3 | Animaties | All | Smooth transitions |
|
||||
| 4.4 | Demo scenarios | All | 3 happy paths |
|
||||
| 4.5 | Bug fixes | All | Stability |
|
||||
|
||||
**Deliverable:** Demo-ready voor stakeholders.
|
||||
|
||||
---
|
||||
|
||||
## 5. Technische Beslissingen
|
||||
|
||||
### 5.1 State Management
|
||||
|
||||
**Besluit:** Zustand
|
||||
|
||||
```typescript
|
||||
// stores/command-center.ts
|
||||
interface CommandCenterState {
|
||||
// Active state
|
||||
activeBlock: 'dagnotitie' | 'zoeken' | 'rapportage' | 'overdracht' | null
|
||||
activePatient: Patient | null
|
||||
|
||||
// Input state
|
||||
inputValue: string
|
||||
isListening: boolean
|
||||
transcript: string
|
||||
|
||||
// Pre-fill data
|
||||
prefillData: {
|
||||
patientName?: string
|
||||
category?: string
|
||||
text?: string
|
||||
}
|
||||
|
||||
// History
|
||||
recentActions: Action[]
|
||||
|
||||
// Actions
|
||||
processInput: (text: string) => Promise<void>
|
||||
openBlock: (type: BlockType, prefill?: object) => void
|
||||
closeBlock: () => void
|
||||
setActivePatient: (patient: Patient) => void
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 Intent Classification
|
||||
|
||||
**Besluit:** Two-tier approach
|
||||
|
||||
```typescript
|
||||
// Tier 1: Local keyword matching (instant)
|
||||
const quickMatch = (input: string) => {
|
||||
if (/notitie|dagnotitie/i.test(input)) return { intent: 'dagnotitie', confidence: 0.9 }
|
||||
if (/zoek|vind|wie is/i.test(input)) return { intent: 'zoeken', confidence: 0.9 }
|
||||
if (/overdracht|dienst/i.test(input)) return { intent: 'overdracht', confidence: 0.9 }
|
||||
if (/rapport|gesprek/i.test(input)) return { intent: 'rapportage', confidence: 0.85 }
|
||||
return null
|
||||
}
|
||||
|
||||
// Tier 2: Claude API (fallback)
|
||||
const aiClassify = async (input: string) => {
|
||||
// Only called if quickMatch returns null or low confidence
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 Patient Resolution
|
||||
|
||||
**Besluit:** Fuzzy search met Supabase
|
||||
|
||||
```typescript
|
||||
// Fuzzy match op naam
|
||||
const searchPatients = async (query: string) => {
|
||||
const { data } = await supabase
|
||||
.from('patients')
|
||||
.select('id, name, birth_date')
|
||||
.ilike('name', `%${query}%`)
|
||||
.limit(5)
|
||||
return data
|
||||
}
|
||||
|
||||
// Als 1 match → auto-select
|
||||
// Als >1 match → toon ZoekenBlock
|
||||
// Als 0 matches → "Geen patient gevonden"
|
||||
```
|
||||
|
||||
### 5.4 Block Architecture
|
||||
|
||||
**Besluit:** Wrapper pattern
|
||||
|
||||
```typescript
|
||||
// Elk blok krijgt dezelfde interface
|
||||
interface BlockProps {
|
||||
prefill?: Record<string, unknown>
|
||||
onComplete: (result: unknown) => void
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
// BlockContainer handelt header, minimize, close
|
||||
<BlockContainer title="Dagnotitie" icon={FileText}>
|
||||
<DagnotitieBlock prefill={prefill} onComplete={handleComplete} />
|
||||
</BlockContainer>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Risico's & Mitigaties
|
||||
|
||||
| Risico | Kans | Impact | Mitigatie |
|
||||
|--------|------|--------|-----------|
|
||||
| Intent accuracy <80% | Medium | Hoog | Fallback picker altijd zichtbaar |
|
||||
| Voice niet goed in NL | Laag | Medium | Deepgram NL model + tekst fallback |
|
||||
| Pre-fill verkeerde patient | Medium | Hoog | Altijd confirmation, nooit blind save |
|
||||
| Latency AI calls | Medium | Medium | Local-first matching, AI als backup |
|
||||
| Demo deadline druk | Medium | Hoog | Scope strict houden, no feature creep |
|
||||
|
||||
---
|
||||
|
||||
## 7. Success Metrics
|
||||
|
||||
### 7.1 MVP Success (Must Hit)
|
||||
|
||||
| Metric | Target | Hoe Meten |
|
||||
|--------|--------|-----------|
|
||||
| "notitie jan" → save | <30 sec | Timestamp logs |
|
||||
| Intent accuracy | >85% | Correct block / total |
|
||||
| Voice transcription | >90% accuracy | Manual review sample |
|
||||
| Fallback usage | <25% | Picker clicks / total |
|
||||
|
||||
### 7.2 Demo Success
|
||||
|
||||
| Metric | Target |
|
||||
|--------|--------|
|
||||
| 3 scenario's foutloos | 100% |
|
||||
| Stakeholder "wow" moment | Ja |
|
||||
| Concrete vervolgafspraak | Ja |
|
||||
|
||||
---
|
||||
|
||||
## 8. Definition of Done
|
||||
|
||||
### 8.1 Per Sprint
|
||||
|
||||
- [ ] Alle taken in sprint completed
|
||||
- [ ] Geen console errors
|
||||
- [ ] Happy path werkt
|
||||
- [ ] Code reviewed
|
||||
|
||||
### 8.2 MVP Done
|
||||
|
||||
- [ ] Command Center bereikbaar op `/command-center`
|
||||
- [ ] Voice input werkt
|
||||
- [ ] "notitie voor [patient]" opent DagnotitieBlock
|
||||
- [ ] "zoek [naam]" toont PatientCards
|
||||
- [ ] Pre-fill werkt voor patient naam
|
||||
- [ ] Fallback picker werkt
|
||||
- [ ] Save + toast feedback werkt
|
||||
- [ ] Geen blocking bugs
|
||||
- [ ] 3 demo scenario's gedocumenteerd
|
||||
|
||||
---
|
||||
|
||||
## 9. Demo Scenario's
|
||||
|
||||
### Scenario 1: Snelle Dagnotitie (30 sec)
|
||||
|
||||
```
|
||||
1. Open Command Center
|
||||
2. Type of spreek: "notitie voor Jan de Vries: medicatie uitgereikt"
|
||||
3. System:
|
||||
- Herkent intent: dagnotitie
|
||||
- Herkent patient: Jan de Vries
|
||||
- Pre-fills categorie: Medicatie
|
||||
- Pre-fills tekst: "medicatie uitgereikt"
|
||||
4. User: Review → Opslaan
|
||||
5. Toast: "Notitie opgeslagen"
|
||||
6. Recent badge verschijnt
|
||||
```
|
||||
|
||||
### Scenario 2: Patient Zoeken + Notitie (45 sec)
|
||||
|
||||
```
|
||||
1. Type: "notitie marie"
|
||||
2. System: Meerdere "Marie" gevonden
|
||||
3. Toont: ZoekenBlock met 3 matches
|
||||
4. User: Selecteert "Marie van den Berg"
|
||||
5. System: Opent DagnotitieBlock met patient ingevuld
|
||||
6. User: Typt notitie → Opslaan
|
||||
```
|
||||
|
||||
### Scenario 3: Voice Flow (40 sec)
|
||||
|
||||
```
|
||||
1. Klik mic button
|
||||
2. Spreek: "Mevrouw Jansen heeft goed gegeten en haar medicatie ingenomen"
|
||||
3. System:
|
||||
- Transcribeert real-time
|
||||
- Herkent: patient = Jansen, categorie = ADL + Medicatie
|
||||
4. Toont: DagnotitieBlock met alles ingevuld
|
||||
5. User: Review → Opslaan
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Appendix: File Structure
|
||||
|
||||
```
|
||||
app/
|
||||
├── command-center/
|
||||
│ ├── page.tsx # Main Command Center
|
||||
│ └── components/
|
||||
│ ├── command-input.tsx # Text + voice input
|
||||
│ ├── voice-indicator.tsx # Listening state UI
|
||||
│ ├── block-container.tsx # Generic block wrapper
|
||||
│ ├── fallback-picker.tsx # Block selection grid
|
||||
│ └── recent-actions.tsx # Recent badges strip
|
||||
|
||||
├── api/
|
||||
│ └── intent/
|
||||
│ └── classify/
|
||||
│ └── route.ts # Intent classification API
|
||||
|
||||
components/
|
||||
└── building-blocks/
|
||||
├── dagnotitie-block.tsx # Quick entry form
|
||||
├── zoeken-block.tsx # Patient search
|
||||
├── rapportage-block.tsx # Report composer wrapper
|
||||
└── overdracht-block.tsx # Handover summary
|
||||
|
||||
stores/
|
||||
└── command-center.ts # Zustand store
|
||||
|
||||
lib/
|
||||
├── intent/
|
||||
│ ├── classifier.ts # Intent classification logic
|
||||
│ ├── entity-extractor.ts # Extract patient, category
|
||||
│ └── patient-resolver.ts # Name → Patient lookup
|
||||
└── types/
|
||||
└── command-center.ts # TypeScript types
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Dit document is de single source of truth voor MVP scope en prioritering.*
|
||||
430
docs/swift/nextgen-epd-onderzoeksverslag-ux-ui-patterns.md
Normal file
430
docs/swift/nextgen-epd-onderzoeksverslag-ux-ui-patterns.md
Normal file
@@ -0,0 +1,430 @@
|
||||
# Onderzoeksverslag: UX/UI Patterns voor Ephemeral UI EPD
|
||||
|
||||
**Document:** UX/UI Research & Best Practices
|
||||
**Datum:** december 2024
|
||||
**Status:** Definitief
|
||||
**Onderzoeksmethode:** Desk research, marktanalyse, design pattern analyse
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive Summary
|
||||
|
||||
Dit onderzoek analyseert de beste UX/UI patterns voor het Ephemeral UI EPD concept. De conclusie is dat een **hybrid approach** de beste keuze is: natural language input gecombineerd met voorgedefinieerde, gestructureerde UI-bouwblokken.
|
||||
|
||||
**Kernbevindingen:**
|
||||
- Ambient Clinical Intelligence is de dominante trend (markt groeit 37% per jaar)
|
||||
- Pure conversational UI is te onvoorspelbaar voor zorg
|
||||
- Command palette pattern (cmdk) is de beste basis voor intent-input
|
||||
- Two-tier intent classification (local + AI fallback) biedt optimale snelheid
|
||||
- Fallback UI is essentieel voor vertrouwen
|
||||
|
||||
---
|
||||
|
||||
## 2. Marktanalyse: Ambient Clinical Intelligence
|
||||
|
||||
### 2.1 Marktomvang & Groei
|
||||
|
||||
| Metric | Waarde | Bron |
|
||||
|--------|--------|------|
|
||||
| Marktwaarde 2024 | $468 miljoen | Nova One Advisor |
|
||||
| Verwacht 2034 | $11,5 miljard | Nova One Advisor |
|
||||
| CAGR | 37,87% | Nova One Advisor |
|
||||
| Clinical documentation share | 18% van markt | Nova One Advisor |
|
||||
| NLP-powered agents | 33% marktaandeel | Nova One Advisor |
|
||||
|
||||
### 2.2 Belangrijkste Spelers
|
||||
|
||||
| Vendor | Product | Aanpak | Adoptie |
|
||||
|--------|---------|--------|---------|
|
||||
| **Microsoft/Nuance** | DAX Copilot | Ambient listening → full note | Stanford, Kaiser |
|
||||
| **Suki AI** | Suki Assistant | Voice commands + dictatie | 72% sneller documentatie |
|
||||
| **Abridge** | Abridge | Ambient → structured notes | Sutter Health, UPMC |
|
||||
| **DeepScribe** | DeepScribe | Specialty-focused (oncologie) | Enterprise |
|
||||
| **Ambience** | AI Scribe | Ambient + Epic integratie | Cleveland Clinic (4000+ artsen) |
|
||||
|
||||
### 2.3 Adoptie bij Grote Zorginstellingen (2024)
|
||||
|
||||
| Instelling | Tool | Schaal | Resultaat |
|
||||
|------------|------|--------|-----------|
|
||||
| Stanford Health | DAX Copilot | Volledig uitgerold | Significante tijdsbesparing |
|
||||
| Cleveland Clinic | Ambience AI Scribe | 4000+ providers | 80+ specialismen |
|
||||
| Sutter Health | Abridge | 100 clinici pilot | April 2024 start |
|
||||
| Kaiser/TPMG | Ambient AI | 10.000 artsen | 303.266 encounters in 10 weken |
|
||||
|
||||
### 2.4 Kernprobleem dat Wordt Opgelost
|
||||
|
||||
> "Artsen besteden tot **4,5 uur per dag** aan EHR data invoer"
|
||||
> — NEJM Catalyst Research
|
||||
|
||||
> "De flow van EHR systemen matcht niet met de workflow van de clinicus, wat frustratie en tijdverlies veroorzaakt"
|
||||
> — Healthcare IT News
|
||||
|
||||
---
|
||||
|
||||
## 3. UX Pattern Analyse
|
||||
|
||||
### 3.1 Ephemeral UI Concept
|
||||
|
||||
**Definitie** (Hilal Koyuncu, ex-Google designer):
|
||||
> "UI die alleen verschijnt wanneer nodig en verdwijnt na gebruik"
|
||||
|
||||
**Kenmerken:**
|
||||
| Eigenschap | Beschrijving |
|
||||
|------------|--------------|
|
||||
| On-demand | Interface materialiseert bij intentie |
|
||||
| Hyper-contextual | Gebouwd voor één gebruiker's momentane doel |
|
||||
| Transient | Vernietigd wanneer doel bereikt is |
|
||||
| Task-optimal | Elk element dient het directe doel |
|
||||
|
||||
**Voordelen:**
|
||||
- Zero learning curve
|
||||
- Infinite scalability
|
||||
- Accessibility by default (past zich aan)
|
||||
|
||||
**Risico's:**
|
||||
> "Constant veranderende UIs kunnen usability problemen veroorzaken. Gebruikers leunen op design standaarden."
|
||||
> — Roger Wong, Generative UI Analysis
|
||||
|
||||
**Mitigatie:** Gebruik voorgedefinieerde bouwblokken, geen AI-gegenereerde UI.
|
||||
|
||||
### 3.2 Command Palette Pattern
|
||||
|
||||
**Oorsprong:** Sublime Text, VS Code (IDE's voor developers)
|
||||
|
||||
**Moderne adoptie:** Superhuman, Linear, Figma, Slack, Raycast, Notion
|
||||
|
||||
**Best Practices (Superhuman):**
|
||||
|
||||
| Principe | Implementatie |
|
||||
|----------|---------------|
|
||||
| Fuzzy search | "jn dvr" matcht "Jan de Vries" |
|
||||
| Recent first | Laatst gebruikte items bovenaan |
|
||||
| Keyboard-first | Enter = bevestigen, Esc = annuleren |
|
||||
| Single source | Alles op één plek |
|
||||
| Contextual | Relevante acties per context |
|
||||
|
||||
**Wanneer gebruiken:**
|
||||
- Producten met veel features
|
||||
- Power users die efficiency waarderen
|
||||
- Keyboard-heavy workflows
|
||||
|
||||
**Libraries:**
|
||||
| Library | Kenmerken |
|
||||
|---------|-----------|
|
||||
| cmdk | Fast, unstyled, React, headless |
|
||||
| Kbar | Portable, extensible |
|
||||
| Kmenu | Animated, accessible |
|
||||
|
||||
### 3.3 Natural Language Interface (NLI) Patterns
|
||||
|
||||
**Definitie:**
|
||||
> "Een platform dat interactie tussen computer en mens mogelijk maakt via natuurlijke taal"
|
||||
|
||||
**Best Practices:**
|
||||
|
||||
| Principe | Beschrijving |
|
||||
|----------|--------------|
|
||||
| Focus op intent | Begrijp wat de gebruiker wil bereiken |
|
||||
| Handle ambiguity | Vraag verduidelijking bij onduidelijkheid |
|
||||
| Define scope | Maak duidelijk wat het systeem kan |
|
||||
| Confidence thresholds | Stel drempels in voor zekerheid |
|
||||
| Balanced training | Voorkom bias in intent herkenning |
|
||||
|
||||
**Reader vs Writer Intents:**
|
||||
- **Reader intent:** Informatie ophalen, geen actie
|
||||
- **Writer intent:** Actie uitvoeren, geen informatie tonen
|
||||
|
||||
**Belangrijke waarschuwing:**
|
||||
> "NLIs presteren het best in nauw gedefinieerde domeinen. Open-ended interactions overschrijden hun capaciteiten."
|
||||
> — Explosion AI
|
||||
|
||||
### 3.4 Voice Interface Patterns
|
||||
|
||||
**Push-to-Talk vs Ambient:**
|
||||
|
||||
| Aspect | Push-to-Talk | Ambient Listening |
|
||||
|--------|--------------|-------------------|
|
||||
| Privacy | Hoog (expliciet) | Laag (altijd aan) |
|
||||
| Nauwkeurigheid | Hoger (gericht) | Lager (ruis) |
|
||||
| Gebruiksgemak | Actie vereist | Hands-free |
|
||||
| Batterij/resources | Laag | Hoog |
|
||||
| Enterprise adoptie | Growing | Dominant (Suki, Abridge) |
|
||||
|
||||
**Aanbeveling voor MVP:** Push-to-talk (privacy, nauwkeurigheid, eenvoudiger te bouwen)
|
||||
|
||||
---
|
||||
|
||||
## 4. Healthcare UX Trends 2024-2025
|
||||
|
||||
### 4.1 Dominante Trends
|
||||
|
||||
| Trend | Beschrijving | Relevantie |
|
||||
|-------|--------------|------------|
|
||||
| **AI-powered documentation** | Ambient listening, auto-notes | Direct relevant |
|
||||
| **Reduced cognitive load** | Minder klikken, minder schermen | Kernprincipe |
|
||||
| **Voice-first input** | Hands-free tijdens zorg | Must-have |
|
||||
| **Personalization** | Interface past zich aan gebruiker aan | Nice-to-have |
|
||||
| **Mobile-responsive** | Werkt op alle devices | Vereist |
|
||||
|
||||
### 4.2 Anti-Patterns (Wat te Vermijden)
|
||||
|
||||
| Anti-pattern | Waarom slecht | Alternatief |
|
||||
|--------------|---------------|-------------|
|
||||
| Modal op modal | Cognitive overload | Max 1 laag diep |
|
||||
| "Weet je het zeker?" | Vertraagt, twijfel zaaien | Undo in plaats van confirm |
|
||||
| Verplichte velden overal | Blokkeert snelle invoer | Alleen essentiële velden |
|
||||
| Loading spinners | Wachten = frustratie | Optimistic UI |
|
||||
| Sessie verlopen | Werk kwijt | Auto-save drafts |
|
||||
|
||||
### 4.3 EHR-Specifieke UX Principes
|
||||
|
||||
**Van Arkenea EHR Interface Guide:**
|
||||
- Streamlined dashboards met customizable workflows
|
||||
- Responsive designs voor verschillende schermgroottes
|
||||
- Enhanced visual hierarchy met betere typografie
|
||||
- Eliminatie van onnodige klikken en context switching
|
||||
- Generous white space
|
||||
|
||||
---
|
||||
|
||||
## 5. Aanbevolen Architectuur
|
||||
|
||||
### 5.1 Hybrid Approach
|
||||
|
||||
De beste UX combineert:
|
||||
1. **Natural language input** (command palette + voice)
|
||||
2. **Structured UI output** (voorgedefinieerde bouwblokken)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ INPUT LAYER: Natural Language │
|
||||
│ ───────────────────────────────────────────────────── │
|
||||
│ "notitie jan: medicatie gegeven" │
|
||||
│ │
|
||||
│ ↓ Intent Classification │
|
||||
│ │
|
||||
│ OUTPUT LAYER: Structured UI │
|
||||
│ ───────────────────────────────────────────────────── │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Patient: [Jan de Vries ▼] ← pre-filled │ │
|
||||
│ │ Categorie: [Medicatie ▼] ← pre-filled │ │
|
||||
│ │ Tekst: medicatie gegeven ← pre-filled │ │
|
||||
│ │ │ │
|
||||
│ │ [Opslaan] [Aanpassen] │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Waarom hybrid:**
|
||||
- Natural language voor snelle input
|
||||
- Structured UI voor verificatie en correctie
|
||||
- Best of both worlds: snelheid + controle
|
||||
|
||||
### 5.2 Two-Tier Intent Classification
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ TIER 1: Local Pattern Matching (<50ms) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Input → Intent → Entities │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ "notitie jan" → dagnotitie → patient: jan │
|
||||
│ "zoek marie" → zoeken → query: marie │
|
||||
│ "overdracht" → overdracht → (none) │
|
||||
│ "gesprek met piet" → rapportage → patient: piet │
|
||||
│ │
|
||||
│ Confidence: >0.9 → Direct uitvoeren │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
Als geen match of <0.9 confidence
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ TIER 2: AI Classification (<500ms) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Input: "ik heb net iets besproken" │
|
||||
│ │
|
||||
│ AI Output: │
|
||||
│ { │
|
||||
│ "intent": "rapportage", │
|
||||
│ "confidence": 0.75, │
|
||||
│ "clarification_needed": true, │
|
||||
│ "clarification": "Met welke patiënt?" │
|
||||
│ } │
|
||||
│ │
|
||||
│ 0.7-0.9 → "Bedoelde je...?" met opties │
|
||||
│ <0.7 → Fallback naar visuele picker │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5.3 UI Layout Aanbeveling
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ COMMAND CENTER │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ 🎤 Wat wil je doen? [Cmd+K] │ │
|
||||
│ │ ________________________________________________│ │
|
||||
│ │ │ │
|
||||
│ │ 💡 notitie jan · zoek marie · overdracht │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Context: Ochtend dienst · 8 patiënten · Dr. Jansen │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ ACTIEF BOUWBLOK (ephemeral) │ │
|
||||
│ │ │ │
|
||||
│ │ - Voorgedefinieerde structured form │ │
|
||||
│ │ - Pre-filled velden highlighted (gele flash) │ │
|
||||
│ │ - Minimal required fields │ │
|
||||
│ │ - 1-click save │ │
|
||||
│ │ - Undo beschikbaar (geen confirm dialog) │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Recent: [Jan ✓ 14:32] [Marie ✓ 14:28] [Overdracht 14:00] │
|
||||
│ │
|
||||
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │ 📝 │ │ 🔍 │ │ 📋 │ │ 🔄 │ FALLBACK │
|
||||
│ │Notitie │ │ Zoeken │ │Rapport │ │Overdr. │ PICKER │
|
||||
│ └────────┘ └────────┘ └────────┘ └────────┘ (altijd) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Differentiatie t.o.v. Markt
|
||||
|
||||
### 6.1 Vergelijking met Bestaande Oplossingen
|
||||
|
||||
| Aspect | Suki/Abridge/DAX | Ephemeral UI EPD |
|
||||
|--------|------------------|------------------|
|
||||
| Luistermodus | Ambient (altijd aan) | Push-to-talk (expliciet) |
|
||||
| Output | Full generated notes | Pre-filled structured forms |
|
||||
| Pricing | Enterprise ($$$) | Open source / self-hosted |
|
||||
| Markt | US healthcare | Nederlandse GGZ |
|
||||
| Scope | Alleen documentatie | Multi-task intent routing |
|
||||
| Verificatie | Post-hoc review | Inline confirmation |
|
||||
| EHR integratie | Epic, Cerner focus | Supabase (eigen) |
|
||||
|
||||
### 6.2 Unique Selling Points
|
||||
|
||||
1. **Intent-based routing** - Niet alleen transcriberen, maar routeren naar juiste bouwblok
|
||||
2. **Pre-fill magic** - Velden automatisch ingevuld, gebruiker bevestigt alleen
|
||||
3. **GGZ vocabulaire** - Getraind op Nederlandse GGZ terminologie
|
||||
4. **Privacy-first** - Push-to-talk, geen ambient listening
|
||||
5. **Open architectuur** - Niet locked-in bij enterprise vendor
|
||||
|
||||
---
|
||||
|
||||
## 7. Implementatie Aanbevelingen
|
||||
|
||||
### 7.1 Technology Stack
|
||||
|
||||
| Component | Aanbeveling | Rationale |
|
||||
|-----------|-------------|-----------|
|
||||
| Command input | cmdk library | Industry standard, headless, accessible |
|
||||
| Voice | Deepgram (bestaand) | Al geïntegreerd, goed Nederlands |
|
||||
| Intent (local) | Regex + keyword matching | <50ms, geen API call |
|
||||
| Intent (AI) | Claude API | Al geïntegreerd, goed Nederlands |
|
||||
| State | Zustand | Lightweight, geen provider nesting |
|
||||
| UI blocks | shadcn/ui (bestaand) | Consistent met rest van app |
|
||||
|
||||
### 7.2 Implementatie Volgorde
|
||||
|
||||
| Fase | Component | Prioriteit |
|
||||
|------|-----------|------------|
|
||||
| 1 | Command Center layout | Must have |
|
||||
| 1 | Fallback picker | Must have |
|
||||
| 1 | Local intent matching | Must have |
|
||||
| 2 | Voice input integratie | Must have |
|
||||
| 2 | Dagnotitie block | Must have |
|
||||
| 2 | Zoeken block | Must have |
|
||||
| 3 | AI intent fallback | Should have |
|
||||
| 3 | Rapportage block | Should have |
|
||||
| 4 | Overdracht block | Could have |
|
||||
| 4 | Animaties & polish | Could have |
|
||||
|
||||
### 7.3 Success Metrics
|
||||
|
||||
| Metric | Target | Meetmethode |
|
||||
|--------|--------|-------------|
|
||||
| Time-to-first-input | <2 sec | Timestamp logging |
|
||||
| Task completion (notitie) | <30 sec | Timestamp logging |
|
||||
| Intent accuracy | >90% | Correct block / total |
|
||||
| Fallback usage | <15% | Picker clicks / total |
|
||||
| Voice adoption | >40% | Voice / total inputs |
|
||||
|
||||
---
|
||||
|
||||
## 8. Bronnen
|
||||
|
||||
### Marktonderzoek
|
||||
- [AI Voice Agents in Healthcare Market](https://www.novaoneadvisor.com/report/ai-voice-agents-in-healthcare-market) - Nova One Advisor
|
||||
- [Healthcare UX/UI Design Trends 2025](https://www.excellentwebworld.com/healthcare-ux-ui-design-trends/) - Excellent WebWorld
|
||||
- [AI and Healthcare UX/UI 2024-2025](https://www.graphitedigital.com/insights/ai-impact-ux-ui-design-healthcare) - Graphite Digital
|
||||
|
||||
### Ambient Clinical Intelligence
|
||||
- [Stanford DAX Implementation](https://med.stanford.edu/news/all-news/2024/03/ambient-listening-notes.html) - Stanford Medicine
|
||||
- [Cleveland Clinic Ambient AI](https://consultqd.clevelandclinic.org/less-typing-more-talking-how-ambient-ai-is-reshaping-clinical-workflow-at-cleveland-clinic) - Cleveland Clinic
|
||||
- [Ambient AI Scribes - NEJM](https://catalyst.nejm.org/doi/full/10.1056/CAT.23.0404) - NEJM Catalyst
|
||||
- [Ambient Listening in Healthcare](https://healthtechmagazine.net/article/2024/08/ambient-listening-in-healthcare-perfcon) - HealthTech Magazine
|
||||
|
||||
### Ephemeral UI
|
||||
- [Ephemeral UI in AI-Generated Interfaces](https://isolutions.medium.com/ephemeral-ui-in-ai-generated-on-demand-interfaces-81dbc8cd4579) - iSolutions
|
||||
- [Generative UI and the Ephemeral Interface](https://rogerwong.me/2025/11/generative-ui-and-the-ephemeral-interface/) - Roger Wong
|
||||
- [Ephemeral Web-Based Applications](https://www.nngroup.com/articles/ephemeral-web-based-applications/) - Nielsen Norman Group
|
||||
- [Future of AI UI/UX: Ephemeral Interfaces](https://hertzfelt.io/blog/the-future-of-ai-ui-ux-ephemeral-interfaces-and-stateless-design-paradigms) - Hertzfelt Labs
|
||||
|
||||
### Command Palette
|
||||
- [Command Palette UX Patterns](https://medium.com/design-bootcamp/command-palette-ux-patterns-1-d6b6e68f30c1) - Alicja Suska
|
||||
- [How to Build a Remarkable Command Palette](https://blog.superhuman.com/how-to-build-a-remarkable-command-palette/) - Superhuman
|
||||
- [Command Palette UI Design](https://mobbin.com/glossary/command-palette) - Mobbin
|
||||
- [Command Palette Resources](https://www.commandpalette.org/) - commandpalette.org
|
||||
|
||||
### Natural Language Interfaces
|
||||
- [5 Principles for Good NLU Design](https://www.voiceflow.com/pathways/5-principles-for-good-natural-language-understanding-nlu-design) - Voiceflow
|
||||
- [Natural Language Interface](https://www.uxtweak.com/ux-glossary/natural-language-interface/) - UXtweak
|
||||
- [A Natural Language UI is Just a UI](https://explosion.ai/blog/natural-user-interface) - Explosion AI
|
||||
|
||||
### Healthcare AI Vendors
|
||||
- [Suki AI](https://www.suki.ai/) - Suki Assistant
|
||||
- [DeepScribe](https://www.deepscribe.ai/resources/best-ai-medical-scribes) - AI Medical Scribes
|
||||
- [Abridge](https://www.trendingaitools.com/ai-tools/abridge/) - Clinical Documentation
|
||||
|
||||
### EHR Design
|
||||
- [EHR Interface Design Guide 2026](https://arkenea.com/blog/ehr-interface/) - Arkenea
|
||||
- [EMR/EHR UI/UX Principles](https://www.purrweb.com/blog/emr-ehr-interface-design/) - Purrweb
|
||||
- [EHR Redesign for Burnout](https://www.healthcareitnews.com/news/pandemic-era-burnout-how-ehr-vendors-are-redesigning-ui-and-ux-battle-stress) - Healthcare IT News
|
||||
|
||||
---
|
||||
|
||||
## 9. Conclusie
|
||||
|
||||
De beste UX/UI voor het Ephemeral UI EPD is een **hybrid approach**:
|
||||
|
||||
1. **Input:** Command palette (cmdk) + push-to-talk voice
|
||||
2. **Processing:** Two-tier intent classification (local-first, AI-fallback)
|
||||
3. **Output:** Voorgedefinieerde, structured UI-bouwblokken met pre-fill
|
||||
4. **Safety net:** Altijd zichtbare fallback picker
|
||||
|
||||
Deze aanpak combineert:
|
||||
- De snelheid van natural language input
|
||||
- De voorspelbaarheid van structured UI
|
||||
- De betrouwbaarheid van voorgedefinieerde componenten
|
||||
- De flexibiliteit van AI-assisted intent recognition
|
||||
|
||||
Het resultaat: een interface die **voelt als magie** ("het begrijpt me!") maar **werkt als een betrouwbaar tool** (geen verrassingen, altijd een uitweg).
|
||||
|
||||
---
|
||||
|
||||
*Onderzoeksverslag gegenereerd op basis van desk research december 2024*
|
||||
607
docs/swift/nextgen-epd-prd-ephemeral-ui-epd.md
Normal file
607
docs/swift/nextgen-epd-prd-ephemeral-ui-epd.md
Normal file
@@ -0,0 +1,607 @@
|
||||
# 📄 Product Requirements Document (PRD)
|
||||
|
||||
**Product:** Ephemeral UI EPD - "Het Vergankelijke EPD"
|
||||
**Doel:** AI Speedrun Deel 2 - Demonstreren van context-aware, on-demand interfaces voor GGZ
|
||||
**Versie:** 1.0
|
||||
**Datum:** december 2024
|
||||
|
||||
---
|
||||
|
||||
## 1. Doelstelling
|
||||
|
||||
### Primair doel
|
||||
Bouwen van een **Ephemeral UI EPD**: een systeem waarin de interface niet permanent is, maar **on-demand verschijnt** op basis van wat de gebruiker wil doen. De gebruiker navigeert niet door menu's, maar spreekt of typt een intentie - en het juiste "bouwblok" verschijnt.
|
||||
|
||||
### Het contrast met traditionele EPD's
|
||||
|
||||
| Aspect | Traditioneel EPD | Ephemeral UI EPD |
|
||||
|--------|------------------|------------------|
|
||||
| Navigatie | 47 menu-items, tabbladen, submenu's | Eén input: "wat wil je doen?" |
|
||||
| Interface | Altijd alles zichtbaar | Alleen wat je nu nodig hebt |
|
||||
| Leren | 200-pagina handleiding | Zero learning curve |
|
||||
| Klikken | 12 klikken voor rapportage | 1 zin of voice command |
|
||||
| Context | Gebruiker moet context onthouden | Systeem begrijpt context |
|
||||
|
||||
### Secundair doel
|
||||
- Positioneren als thought leader op het snijvlak van AI en healthcare UX
|
||||
- Demonstreren van Vercel AI SDK Generative UI capabilities
|
||||
- Concrete showcase voor gesprekken met Nedap, Medicore, etc.
|
||||
|
||||
---
|
||||
|
||||
## 2. Wat is Ephemeral UI?
|
||||
|
||||
### Definitie
|
||||
Ephemeral UI ("vergankelijke interface") betekent dat interface-elementen:
|
||||
1. **On-demand verschijnen** - alleen wanneer nodig
|
||||
2. **Context-aware zijn** - weten wie je bent, welke patiënt, welk moment
|
||||
3. **Verdwijnen na gebruik** - geen permanente schermvervuiling
|
||||
4. **Voorgedefinieerd zijn** - geen willekeurig gegenereerde UI, maar geteste bouwblokken
|
||||
|
||||
### Onze interpretatie voor GGZ
|
||||
We bouwen **geen** volledig AI-gegenereerde interfaces (te onvoorspelbaar voor zorg).
|
||||
We bouwen **wel** een set van **voorgedefinieerde UI-bouwblokken** die:
|
||||
- Door AI worden geselecteerd op basis van gebruikersintentie
|
||||
- Automatisch worden gevuld met relevante data
|
||||
- Na voltooiing verdwijnen of minimaliseren
|
||||
|
||||
---
|
||||
|
||||
## 3. Bestaande basis (uit Speedrun 1)
|
||||
|
||||
### Wat we al hebben
|
||||
Uit het Mini-ECD en Overdracht Dashboard:
|
||||
|
||||
**Database (Supabase PostgreSQL):**
|
||||
- `clients` - patiëntgegevens
|
||||
- `intakes` - intakeverslagen
|
||||
- `problem_profiles` - DSM-light classificaties
|
||||
- `treatment_plans` - behandelplannen met versioning
|
||||
- `nursing_logs` - verpleegkundige dagregistraties
|
||||
- `appointments` - afspraken (basis)
|
||||
- `vitals` - vitale functies metingen
|
||||
- `risk_assessments` - risicotaxaties
|
||||
|
||||
**AI Functionaliteit:**
|
||||
- Samenvatten van tekst
|
||||
- Leesbaarheid verbeteren (B1)
|
||||
- Problemen extraheren uit intake
|
||||
- Behandelplan genereren
|
||||
- Overdracht samenvatting genereren
|
||||
|
||||
**Tech Stack:**
|
||||
- Next.js 15 (App Router)
|
||||
- Supabase (Auth + DB)
|
||||
- Claude API (Anthropic)
|
||||
- TailwindCSS + shadcn/ui
|
||||
- TipTap rich text editor
|
||||
- Deepgram (speech-to-text)
|
||||
|
||||
### Wat we hergebruiken
|
||||
- Volledige database schema
|
||||
- Alle bestaande API routes
|
||||
- AI prompts en functionaliteit
|
||||
- Authenticatie en autorisatie
|
||||
- Bestaande UI componenten (als bouwblokken)
|
||||
|
||||
---
|
||||
|
||||
## 4. De Bouwblokken
|
||||
|
||||
### 4.1 Overzicht van UI Bouwblokken
|
||||
|
||||
| # | Bouwblok | Trigger voorbeelden | Data input | Output |
|
||||
|---|----------|---------------------|------------|--------|
|
||||
| 1 | **Rapportage** | "gesprek gehad", "notitie maken" | patient_id, transcript/tekst | Opgeslagen rapportage |
|
||||
| 2 | **Intake** | "nieuwe cliënt", "intake" | basisgegevens, verwijzing | Intake + patient record |
|
||||
| 3 | **Behandelplan** | "behandelplan", "doelen opstellen" | patient_id, diagnose | Treatment plan |
|
||||
| 4 | **Overdracht** | "overdracht", "dienst eindigt" | patient_id[], tijdrange | Samenvatting |
|
||||
| 5 | **Dagnotitie** | "medicatie gegeven", "incident" | patient_id, categorie | Nursing log entry |
|
||||
| 6 | **Zoeken** | "zoek", "wie is", "vind" | zoekterm | Patient card(s) |
|
||||
| 7 | **Agenda** | "afspraken", "planning", "wanneer" | datum, behandelaar | Agenda view |
|
||||
| 8 | **Metingen** | "vitale functies", "meting invoeren" | patient_id, type | Vitals entry |
|
||||
|
||||
### 4.2 Bouwblok Specificaties
|
||||
|
||||
#### Bouwblok 1: Rapportage
|
||||
**Trigger patterns:**
|
||||
- "Ik heb net een gesprek gehad met [naam]"
|
||||
- "Notitie voor [naam]"
|
||||
- "Rapportage maken"
|
||||
|
||||
**UI Componenten:**
|
||||
- Patient selector (indien niet gespecificeerd)
|
||||
- Rich text editor (TipTap)
|
||||
- AI-knoppen: Samenvatten, Structureren, B1-niveau
|
||||
- Tag selector (Gesprek/Observatie/Telefonisch/etc.)
|
||||
- Save + Close actie
|
||||
|
||||
**Pre-fill logica:**
|
||||
- Als patient genoemd: voorselect patient
|
||||
- Als "gesprek": tag = Gesprek
|
||||
- Als transcript meegegeven: vul editor
|
||||
|
||||
**Na voltooiing:**
|
||||
- Opslaan in `intakes` of `nursing_logs`
|
||||
- Toon bevestiging
|
||||
- Minimaliseer naar "Laatste: [titel]" badge
|
||||
- Klaar voor volgende actie
|
||||
|
||||
---
|
||||
|
||||
#### Bouwblok 2: Intake
|
||||
**Trigger patterns:**
|
||||
- "Nieuwe cliënt"
|
||||
- "Intake starten"
|
||||
- "Aanmelding verwerken"
|
||||
|
||||
**UI Componenten:**
|
||||
- Stap 1: Basisgegevens (naam, geboortedatum)
|
||||
- Stap 2: Verwijsgegevens (optioneel)
|
||||
- Stap 3: Intake editor met AI-ondersteuning
|
||||
- Stap 4: AI-suggestie voor probleemprofiel
|
||||
|
||||
**Pre-fill logica:**
|
||||
- Als naam genoemd: vul naam in
|
||||
- Als verwijsbrief geüpload: extract data
|
||||
|
||||
**Na voltooiing:**
|
||||
- Patient aangemaakt
|
||||
- Intake opgeslagen
|
||||
- Probleemprofiel concept aangemaakt
|
||||
- Navigeer naar volgende stap of minimaliseer
|
||||
|
||||
---
|
||||
|
||||
#### Bouwblok 3: Behandelplan
|
||||
**Trigger patterns:**
|
||||
- "Behandelplan opstellen voor [naam]"
|
||||
- "Doelen formuleren"
|
||||
- "Plan maken"
|
||||
|
||||
**UI Componenten:**
|
||||
- Patient context header
|
||||
- Diagnose/probleemprofiel samenvatting
|
||||
- AI-gegenereerd plan (bewerkbaar)
|
||||
- SMART doelen editor
|
||||
- Interventies selector
|
||||
- Versie management (concept/gepubliceerd)
|
||||
|
||||
**Pre-fill logica:**
|
||||
- Laad bestaand probleemprofiel
|
||||
- Laad recente intakes voor context
|
||||
- Genereer voorstel met AI
|
||||
|
||||
**Na voltooiing:**
|
||||
- Plan opgeslagen (concept of gepubliceerd)
|
||||
- Toon bevestiging met versienummer
|
||||
|
||||
---
|
||||
|
||||
#### Bouwblok 4: Overdracht
|
||||
**Trigger patterns:**
|
||||
- "Overdracht maken"
|
||||
- "Dienst eindigt"
|
||||
- "Samenvatting voor collega"
|
||||
|
||||
**UI Componenten:**
|
||||
- Multi-patient selector (of "mijn patiënten vandaag")
|
||||
- Tijdrange selector (afgelopen X uur)
|
||||
- Per patient: collapsible summary
|
||||
- AI-samenvatting met bronverwijzingen
|
||||
- Export/print optie
|
||||
|
||||
**Pre-fill logica:**
|
||||
- Selecteer patiënten van huidige gebruiker
|
||||
- Default tijdrange: afgelopen 8 uur
|
||||
- Laad relevante nursing_logs, vitals, rapportages
|
||||
|
||||
**Na voltooiing:**
|
||||
- Overdracht gemarkeerd als compleet
|
||||
- Optioneel: doorsturen naar collega
|
||||
|
||||
---
|
||||
|
||||
#### Bouwblok 5: Dagnotitie (Quick Entry)
|
||||
**Trigger patterns:**
|
||||
- "Medicatie gegeven aan [naam]"
|
||||
- "Incident bij [naam]"
|
||||
- "[naam] heeft goed gegeten"
|
||||
|
||||
**UI Componenten:**
|
||||
- Minimale form: categorie, tekst, tijd
|
||||
- Categorieën: Medicatie, ADL, Gedrag, Incident, Observatie
|
||||
- Checkbox: "Opnemen in overdracht"
|
||||
- Quick save (enter = opslaan)
|
||||
|
||||
**Pre-fill logica:**
|
||||
- Extract patient uit zin
|
||||
- Extract categorie uit keywords
|
||||
- Tijd = nu (aanpasbaar)
|
||||
|
||||
**Na voltooiing:**
|
||||
- Direct opgeslagen
|
||||
- Toast bevestiging
|
||||
- Klaar voor volgende notitie
|
||||
|
||||
---
|
||||
|
||||
#### Bouwblok 6: Zoeken
|
||||
**Trigger patterns:**
|
||||
- "Zoek [naam]"
|
||||
- "Wie is [naam]"
|
||||
- "Toon patiënt [naam]"
|
||||
|
||||
**UI Componenten:**
|
||||
- Search results cards
|
||||
- Per card: naam, geboortedatum, laatste contact, status
|
||||
- Klik = open patient context
|
||||
- "Geen resultaten" state
|
||||
|
||||
**Na selectie:**
|
||||
- Set active patient context
|
||||
- Toon relevante vervolgacties: "Wat wil je doen met [naam]?"
|
||||
|
||||
---
|
||||
|
||||
#### Bouwblok 7: Agenda
|
||||
**Trigger patterns:**
|
||||
- "Mijn afspraken vandaag"
|
||||
- "Afspraken voor [naam]"
|
||||
- "Planning deze week"
|
||||
|
||||
**UI Componenten:**
|
||||
- Dag/week view toggle
|
||||
- Afsprakenlijst met tijden
|
||||
- Patient naam + type afspraak
|
||||
- Quick actions: afspraak toevoegen
|
||||
|
||||
**Pre-fill logica:**
|
||||
- Default: vandaag, huidige gebruiker
|
||||
- Als patient genoemd: filter op patient
|
||||
|
||||
---
|
||||
|
||||
#### Bouwblok 8: Metingen
|
||||
**Trigger patterns:**
|
||||
- "Bloeddruk invoeren"
|
||||
- "Vitale functies [naam]"
|
||||
- "Gewicht meten"
|
||||
|
||||
**UI Componenten:**
|
||||
- Meting type selector
|
||||
- Waarde input met validatie
|
||||
- Trend indicator (vs vorige meting)
|
||||
- Quick save
|
||||
|
||||
---
|
||||
|
||||
## 5. De Orchestratielaag
|
||||
|
||||
### 5.1 Command Center Interface
|
||||
|
||||
**Het centrale scherm:**
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ [🎤] Wat wil je doen? [user] │
|
||||
│ _____________________________________________________ │
|
||||
│ │
|
||||
│ Context: Dienst ochtend | 8 patiënten | 3 todo's │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ [Actief Bouwblok verschijnt hier] │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Recent: [Jan - Rapportage] [Overdracht 14:00] │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5.2 Intent Classification
|
||||
|
||||
**Flow:**
|
||||
```
|
||||
[User Input: tekst of voice]
|
||||
↓
|
||||
[AI Intent Classifier]
|
||||
↓
|
||||
┌────┴────┐
|
||||
↓ ↓
|
||||
[Intent] [Entities]
|
||||
↓ ↓
|
||||
[Route naar Bouwblok + Pre-fill data]
|
||||
↓
|
||||
[Render Bouwblok Component]
|
||||
```
|
||||
|
||||
**Intent Classification Prompt:**
|
||||
```
|
||||
Je bent een intent classifier voor een GGZ EPD systeem.
|
||||
|
||||
Analyseer de gebruikersinput en return JSON:
|
||||
{
|
||||
"intent": "rapportage|intake|behandelplan|overdracht|dagnotitie|zoeken|agenda|metingen|onbekend",
|
||||
"confidence": 0.0-1.0,
|
||||
"entities": {
|
||||
"patient_name": string | null,
|
||||
"date": string | null,
|
||||
"category": string | null,
|
||||
"action_type": string | null
|
||||
},
|
||||
"clarification_needed": boolean,
|
||||
"clarification_question": string | null
|
||||
}
|
||||
|
||||
Gebruikersinput: "{input}"
|
||||
```
|
||||
|
||||
### 5.3 Context Management
|
||||
|
||||
**Actieve context bevat:**
|
||||
- `current_user`: ingelogde behandelaar
|
||||
- `active_patient`: laatst geselecteerde patiënt (sticky)
|
||||
- `active_shift`: huidige dienst info
|
||||
- `recent_actions`: laatste 5 acties (voor "recent" badge)
|
||||
- `pending_items`: openstaande taken
|
||||
|
||||
**Context wordt gebruikt voor:**
|
||||
- Pre-filling van bouwblokken
|
||||
- Suggesties bij ambigue input
|
||||
- "Bedoelde je [patient X]?" bij onduidelijkheid
|
||||
|
||||
---
|
||||
|
||||
## 6. Voice Interface
|
||||
|
||||
### 6.1 Speech-to-Text Flow
|
||||
```
|
||||
[Mic Button Click]
|
||||
↓
|
||||
[Deepgram Streaming STT]
|
||||
↓
|
||||
[Live Transcription Display]
|
||||
↓
|
||||
[User confirms / auto-submit na pauze]
|
||||
↓
|
||||
[Intent Classification]
|
||||
↓
|
||||
[Bouwblok]
|
||||
```
|
||||
|
||||
### 6.2 Voice Commands
|
||||
- Wake phrase niet nodig (expliciete mic button)
|
||||
- Continu luisteren tijdens bouwblok voor dicteren
|
||||
- "Klaar" of "Opslaan" als voice command
|
||||
|
||||
---
|
||||
|
||||
## 7. Technische Architectuur
|
||||
|
||||
### 7.1 Nieuwe Routes
|
||||
|
||||
```
|
||||
/app
|
||||
/(app)
|
||||
/command-center
|
||||
/page.tsx # Hoofdscherm met input
|
||||
/components/
|
||||
CommandInput.tsx # Tekst + voice input
|
||||
BuildingBlock.tsx # Container voor actief blok
|
||||
ContextBar.tsx # Context info display
|
||||
RecentActions.tsx # Recent items
|
||||
|
||||
/api
|
||||
/intent
|
||||
/classify/route.ts # AI intent classification
|
||||
/context
|
||||
/route.ts # Get/set user context
|
||||
```
|
||||
|
||||
### 7.2 Building Blocks als Components
|
||||
|
||||
```
|
||||
/components/building-blocks/
|
||||
/rapportage/
|
||||
RapportageBlock.tsx
|
||||
RapportageBlock.types.ts
|
||||
/intake/
|
||||
IntakeBlock.tsx
|
||||
IntakeBlock.types.ts
|
||||
/behandelplan/
|
||||
BehandelplanBlock.tsx
|
||||
/overdracht/
|
||||
OverdrachtBlock.tsx
|
||||
/dagnotitie/
|
||||
DagnotitieBlock.tsx
|
||||
/zoeken/
|
||||
ZoekenBlock.tsx
|
||||
/agenda/
|
||||
AgendaBlock.tsx
|
||||
/metingen/
|
||||
MetingenBlock.tsx
|
||||
|
||||
/shared/
|
||||
BlockContainer.tsx # Wrapper met header, minimize, close
|
||||
BlockHeader.tsx
|
||||
PatientSelector.tsx
|
||||
ConfirmationToast.tsx
|
||||
```
|
||||
|
||||
### 7.3 State Management
|
||||
|
||||
```typescript
|
||||
// stores/commandCenterStore.ts
|
||||
interface CommandCenterState {
|
||||
// Active block
|
||||
activeBlock: BlockType | null;
|
||||
blockData: Record<string, any>;
|
||||
|
||||
// Context
|
||||
activePatient: Patient | null;
|
||||
recentActions: Action[];
|
||||
|
||||
// Input
|
||||
inputMode: 'text' | 'voice';
|
||||
isListening: boolean;
|
||||
transcript: string;
|
||||
|
||||
// Actions
|
||||
setActiveBlock: (block: BlockType, data?: any) => void;
|
||||
closeBlock: () => void;
|
||||
setActivePatient: (patient: Patient) => void;
|
||||
addRecentAction: (action: Action) => void;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. User Flows
|
||||
|
||||
### 8.1 Happy Path: Rapportage na gesprek
|
||||
|
||||
```
|
||||
1. User opent Command Center
|
||||
2. Ziet: lege input, context "Ochtend dienst, 8 patiënten"
|
||||
3. Spreekt: "Ik heb net een gesprek gehad met Jan de Vries"
|
||||
4. Systeem:
|
||||
- Herkent intent: rapportage
|
||||
- Herkent entity: patient = "Jan de Vries"
|
||||
- Zoekt patient in DB
|
||||
- Opent Rapportage bouwblok met Jan geselecteerd
|
||||
5. User dicteert inhoud gesprek
|
||||
6. Klikt "AI Samenvatten"
|
||||
7. Review en opslaan
|
||||
8. Bouwblok minimaliseert
|
||||
9. Klaar voor volgende actie
|
||||
```
|
||||
|
||||
### 8.2 Ambigue Input
|
||||
|
||||
```
|
||||
1. User typt: "notitie"
|
||||
2. Systeem: confidence < 0.7, geen patient
|
||||
3. Toont: "Voor welke patiënt wil je een notitie maken?"
|
||||
4. User: "Jan"
|
||||
5. Systeem: meerdere "Jan" in DB
|
||||
6. Toont: selector met matches
|
||||
7. User selecteert
|
||||
8. Opent Dagnotitie bouwblok
|
||||
```
|
||||
|
||||
### 8.3 Context Switch
|
||||
|
||||
```
|
||||
1. User werkt in Rapportage voor Jan
|
||||
2. Spreekt: "Wacht, even medicatie noteren voor Piet"
|
||||
3. Systeem:
|
||||
- Herkent nieuwe intent + patient
|
||||
- Vraagt: "Rapportage voor Jan opslaan als concept?"
|
||||
4. User: "Ja"
|
||||
5. Rapportage minimized als "Jan - Concept"
|
||||
6. Dagnotitie opent voor Piet
|
||||
7. Na opslaan: "Terug naar Jan's rapportage?"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Niet in Scope (v1)
|
||||
|
||||
- Volledige voice-only mode (voice is input, niet navigatie)
|
||||
- Multi-user realtime collaboration
|
||||
- Offline mode
|
||||
- Native mobile app (wel responsive web)
|
||||
- Integratie met externe EPD's (later: FHIR)
|
||||
- Volledig geautomatiseerde workflows (user blijft in control)
|
||||
- AI-gegenereerde UI componenten (alleen voorgedefinieerde blokken)
|
||||
|
||||
---
|
||||
|
||||
## 10. Succescriteria
|
||||
|
||||
### Functioneel
|
||||
- [ ] 8 bouwblokken werkend met pre-fill
|
||||
- [ ] Intent classification >85% accuracy op test set
|
||||
- [ ] Voice input werkend met Deepgram
|
||||
- [ ] Context persistence binnen sessie
|
||||
- [ ] Gemiddeld <3 interacties tot taak compleet
|
||||
|
||||
### Performance
|
||||
- [ ] Intent classification <500ms
|
||||
- [ ] Bouwblok render <200ms
|
||||
- [ ] Voice transcription realtime (<100ms latency)
|
||||
|
||||
### UX
|
||||
- [ ] Zero training needed voor basis flows
|
||||
- [ ] "Dit voelt als magie" feedback van test users
|
||||
- [ ] 50% minder klikken vs traditionele navigatie (gemeten)
|
||||
|
||||
### Business
|
||||
- [ ] Demo-ready voor Nedap gesprek (7 jan)
|
||||
- [ ] LinkedIn content: 4 posts over ephemeral UI concept
|
||||
- [ ] Minimaal 2 concrete interesse-uitingen van GGZ partijen
|
||||
|
||||
---
|
||||
|
||||
## 11. Fasering
|
||||
|
||||
### Fase 1: Foundation (Week 1)
|
||||
- [ ] Command Center basis UI
|
||||
- [ ] Intent classification API
|
||||
- [ ] 2 bouwblokken: Rapportage + Dagnotitie
|
||||
- [ ] Context management basis
|
||||
|
||||
### Fase 2: Core Blocks (Week 2)
|
||||
- [ ] Voice input integratie
|
||||
- [ ] Bouwblokken: Zoeken, Overdracht, Behandelplan
|
||||
- [ ] Pre-fill logica uitbreiden
|
||||
- [ ] Recent actions tracking
|
||||
|
||||
### Fase 3: Polish (Week 3)
|
||||
- [ ] Bouwblokken: Intake, Agenda, Metingen
|
||||
- [ ] Animaties en transitions
|
||||
- [ ] Error handling en edge cases
|
||||
- [ ] Performance optimalisatie
|
||||
|
||||
### Fase 4: Demo Ready (Week 4)
|
||||
- [ ] End-to-end testing
|
||||
- [ ] Demo script en scenario's
|
||||
- [ ] Documentation
|
||||
- [ ] LinkedIn content
|
||||
|
||||
---
|
||||
|
||||
## 12. Risico's
|
||||
|
||||
| Risico | Impact | Mitigatie |
|
||||
|--------|--------|-----------|
|
||||
| Intent classification onnauwkeurig | Hoog | Fallback naar handmatige selectie, train op GGZ vocabulaire |
|
||||
| Voice transcription slecht in Nederlands | Middel | Deepgram NL model testen, fallback naar tekst |
|
||||
| Gebruikers missen "overzicht" | Middel | Dashboard/overzicht als alternatieve entry point |
|
||||
| Te veel edge cases | Hoog | Focus op 3-5 happy paths voor demo |
|
||||
| Performance AI calls | Middel | Caching, streaming responses |
|
||||
|
||||
---
|
||||
|
||||
## 13. Appendix: Intent Training Data (voorbeelden)
|
||||
|
||||
```json
|
||||
[
|
||||
{"input": "gesprek gehad met jan de vries", "intent": "rapportage", "entities": {"patient_name": "jan de vries"}},
|
||||
{"input": "notitie maken", "intent": "dagnotitie", "entities": {}},
|
||||
{"input": "nieuwe patient aanmelden", "intent": "intake", "entities": {}},
|
||||
{"input": "overdracht voor de avonddienst", "intent": "overdracht", "entities": {}},
|
||||
{"input": "zoek marie", "intent": "zoeken", "entities": {"patient_name": "marie"}},
|
||||
{"input": "mijn afspraken vandaag", "intent": "agenda", "entities": {"date": "today"}},
|
||||
{"input": "bloeddruk 140/90 bij piet", "intent": "metingen", "entities": {"patient_name": "piet", "measurement_type": "bloeddruk"}},
|
||||
{"input": "behandelplan opstellen", "intent": "behandelplan", "entities": {}}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Wijzigingslog
|
||||
|
||||
| Versie | Datum | Wijzigingen |
|
||||
|--------|-------|-------------|
|
||||
| 1.0 | dec 2024 | Initiële versie |
|
||||
551
docs/swift/nextgen-epd-waarde-analyse-ephemeral-ui.md
Normal file
551
docs/swift/nextgen-epd-waarde-analyse-ephemeral-ui.md
Normal file
@@ -0,0 +1,551 @@
|
||||
# Waarde-Analyse Ephemeral UI EPD
|
||||
|
||||
**Document:** Waar ligt de waarde en hoe implementeren?
|
||||
**Datum:** december 2024
|
||||
**Auteurs:** Product Owner, Klant (GGZ Zorginstelling), UX Designer
|
||||
|
||||
---
|
||||
|
||||
## 1. Klant Perspectief: De Zorginstelling
|
||||
|
||||
### 1.1 De Pijn van Vandaag
|
||||
|
||||
**Citaten uit het veld:**
|
||||
|
||||
> "Mijn verpleegkundigen besteden 40% van hun tijd aan administratie. Dat is tijd die niet naar de cliënt gaat."
|
||||
> — Teamleider GGZ
|
||||
|
||||
> "We hebben een EPD met 200 schermen. Niemand kent ze allemaal. Nieuwe medewerkers doen er 3 maanden over om het te leren."
|
||||
> — ICT Manager
|
||||
|
||||
> "Na een crisis-interventie moet ik 20 minuten typen. Terwijl ik eigenlijk bij de volgende cliënt moet zijn."
|
||||
> — SPV'er
|
||||
|
||||
### 1.2 Waar Ligt de Echte Waarde?
|
||||
|
||||
**Waarde = Tijd terug naar de zorg**
|
||||
|
||||
| Activiteit | Nu (minuten) | Ephemeral (minuten) | Besparing |
|
||||
|------------|--------------|---------------------|-----------|
|
||||
| Dagnotitie na ADL | 3-5 | 0.5 | **80%** |
|
||||
| Rapportage na gesprek | 8-15 | 2-3 | **75%** |
|
||||
| Overdracht maken | 20-30 | 5 | **80%** |
|
||||
| Patiënt opzoeken | 1-2 | 0.2 | **85%** |
|
||||
| Navigeren naar juiste scherm | 0.5-1 per actie | 0 | **100%** |
|
||||
|
||||
**Rekenvoorbeeld voor 1 afdeling (10 FTE):**
|
||||
- 10 medewerkers × 8 notities/dag × 3 min besparing = **4 uur/dag terug**
|
||||
- Per jaar: **1000+ uur** extra zorgcontact
|
||||
|
||||
### 1.3 Wat de Klant Wil Zien
|
||||
|
||||
**Primair:**
|
||||
1. **Snelheid** - "Ik zeg iets, het staat erin"
|
||||
2. **Betrouwbaarheid** - "Het begrijpt me, ook in GGZ-taal"
|
||||
3. **Geen gedoe** - "Ik hoef niet na te denken over het systeem"
|
||||
|
||||
**Secundair:**
|
||||
4. Overdracht die zichzelf schrijft
|
||||
5. Minder training voor nieuwe medewerkers
|
||||
6. Voice input (handsfree tijdens zorg)
|
||||
|
||||
**Niet gevraagd maar wel gewaardeerd:**
|
||||
- AI-suggesties ("wil je de arts informeren?")
|
||||
- Proactieve alerts ("let op: 3 valincidenten deze week")
|
||||
|
||||
### 1.4 Waarde Prioritering door Klant
|
||||
|
||||
```
|
||||
████████████████████████████████ HOOGSTE WAARDE
|
||||
█ 1. Snelle dagnotities (voice)
|
||||
█ 2. Rapportage na gesprek
|
||||
█ 3. Automatische overdracht
|
||||
████████████████████████████ HOGE WAARDE
|
||||
█ 4. Patiënt snel vinden
|
||||
█ 5. Context-aware (weet welke dienst)
|
||||
████████████████████ GEMIDDELDE WAARDE
|
||||
█ 6. Behandelplan assistentie
|
||||
█ 7. Agenda integratie
|
||||
████████████ LAGERE WAARDE
|
||||
█ 8. Metingen invoer
|
||||
█ 9. Intake ondersteuning
|
||||
```
|
||||
|
||||
### 1.5 Klant Conclusie
|
||||
|
||||
**Meeste waarde:** De drie "high-frequency, low-complexity" taken:
|
||||
1. **Dagnotitie** - 10-20x per dag per medewerker
|
||||
2. **Rapportage** - 3-5x per dag per behandelaar
|
||||
3. **Overdracht** - 2-3x per dag per afdeling
|
||||
|
||||
**Implementatie advies:** Begin hier. Dit is waar 80% van de tijdwinst zit.
|
||||
|
||||
---
|
||||
|
||||
## 2. Product Owner Perspectief: Waarde vs. Effort
|
||||
|
||||
### 2.1 Value/Effort Matrix
|
||||
|
||||
```
|
||||
HOGE WAARDE
|
||||
│
|
||||
┌───────────────────┼───────────────────┐
|
||||
│ │ │
|
||||
│ QUICK WINS │ BIG BETS │
|
||||
│ ──────────── │ ──────────── │
|
||||
│ • Dagnotitie │ • Intent API │
|
||||
│ • Zoeken │ • Voice flow │
|
||||
│ • Context bar │ • Overdracht AI │
|
||||
│ │ │
|
||||
LAGE ├───────────────────┼───────────────────┤ HOGE
|
||||
EFFORT │ │ EFFORT
|
||||
│ │ │
|
||||
│ FILL-INS │ MONEY PITS │
|
||||
│ ──────────── │ ──────────── │
|
||||
│ • Metingen │ • Intake wizard │
|
||||
│ • Agenda view │ • Behandelplan │
|
||||
│ • Recent badges │ • Full ambient │
|
||||
│ │ │
|
||||
└───────────────────┼───────────────────┘
|
||||
│
|
||||
LAGE WAARDE
|
||||
```
|
||||
|
||||
### 2.2 Waarde Drivers per Bouwblok
|
||||
|
||||
| Bouwblok | Frequentie | Tijdwinst | Effort | **Waarde Score** |
|
||||
|----------|------------|-----------|--------|------------------|
|
||||
| **Dagnotitie** | 20x/dag | 80% | Laag | ⭐⭐⭐⭐⭐ |
|
||||
| **Zoeken** | 15x/dag | 85% | Laag | ⭐⭐⭐⭐⭐ |
|
||||
| **Rapportage** | 5x/dag | 75% | Medium | ⭐⭐⭐⭐ |
|
||||
| **Overdracht** | 2x/dag | 80% | Medium | ⭐⭐⭐⭐ |
|
||||
| **Agenda** | 3x/dag | 50% | Laag | ⭐⭐⭐ |
|
||||
| **Metingen** | 2x/dag | 60% | Laag | ⭐⭐⭐ |
|
||||
| **Behandelplan** | 1x/week | 40% | Hoog | ⭐⭐ |
|
||||
| **Intake** | 1x/maand | 30% | Hoog | ⭐ |
|
||||
|
||||
### 2.3 MVP Definitie op Basis van Waarde
|
||||
|
||||
**MVP = Hoogste waarde, laagste effort**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ MVP SCOPE │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ MUST: Command Center + Intent │
|
||||
│ ├── Text input │
|
||||
│ ├── Voice input (Deepgram bestaand) │
|
||||
│ └── Fallback blok-picker │
|
||||
│ │
|
||||
│ MUST: Dagnotitie Blok ⭐⭐⭐⭐⭐ │
|
||||
│ ├── Quick entry form │
|
||||
│ ├── Categorie pre-select uit intent │
|
||||
│ ├── Patient pre-fill │
|
||||
│ └── 1-click save │
|
||||
│ │
|
||||
│ MUST: Zoeken Blok ⭐⭐⭐⭐⭐ │
|
||||
│ ├── Patient search (cmdk) │
|
||||
│ ├── Quick actions per result │
|
||||
│ └── Set active patient │
|
||||
│ │
|
||||
│ SHOULD: Rapportage Blok ⭐⭐⭐⭐ │
|
||||
│ ├── Wrapper rond bestaande ReportComposer │
|
||||
│ ├── Voice dictation │
|
||||
│ └── AI structurering │
|
||||
│ │
|
||||
│ COULD: Overdracht Blok ⭐⭐⭐⭐ │
|
||||
│ └── AI samenvatting (API bestaat al) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.4 Wat NIET in MVP
|
||||
|
||||
| Blok | Reden voor uitstel |
|
||||
|------|-------------------|
|
||||
| Behandelplan | Laag-frequent, hoog-complex, bestaande UI voldoet |
|
||||
| Intake | Zeer laag-frequent, wizard is complex |
|
||||
| Metingen | Lage waarde-perceptie bij klant |
|
||||
| Agenda | Bestaande agenda werkt, lage urgentie |
|
||||
|
||||
### 2.5 Release Strategie
|
||||
|
||||
**Week 1-2: Foundation**
|
||||
- Command Center shell
|
||||
- Intent API (basic)
|
||||
- Dagnotitie blok
|
||||
|
||||
**Week 3: Core Value**
|
||||
- Zoeken blok
|
||||
- Rapportage blok
|
||||
- Voice refinement
|
||||
|
||||
**Week 4: Demo Polish**
|
||||
- Overdracht blok
|
||||
- Animaties
|
||||
- Demo scenario's
|
||||
|
||||
**Post-Demo: Iterate**
|
||||
- Metrics verzamelen
|
||||
- Intent accuracy verbeteren
|
||||
- Overige blokken op basis van feedback
|
||||
|
||||
---
|
||||
|
||||
## 3. UX Designer Perspectief: Waarde in de Interactie
|
||||
|
||||
### 3.1 Waar Ontstaat Waarde in de UX?
|
||||
|
||||
**Waarde = Friction verwijderen**
|
||||
|
||||
De grootste UX-waarde zit niet in features, maar in het **elimineren van stappen**:
|
||||
|
||||
```
|
||||
TRADITIONEEL EPD:
|
||||
Login → Dashboard → Menu → Submenu → Patiënten → Zoeken →
|
||||
Selecteer → Menu → Rapportage → Type selecteren → Formulier →
|
||||
Invullen → Validatie fixen → Opslaan → Bevestiging
|
||||
|
||||
= 14 stappen, 12+ klikken, 3-5 minuten
|
||||
|
||||
EPHEMERAL UI:
|
||||
Command Center → "Notitie voor Jan" → Invullen → Opslaan
|
||||
|
||||
= 4 stappen, 2 klikken, 30 seconden
|
||||
```
|
||||
|
||||
### 3.2 De Vijf Waarde-Momenten
|
||||
|
||||
**Moment 1: De Eerste Seconde**
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ Goedemiddag. Wat wil je doen? │
|
||||
│ ___________________________________________________ │
|
||||
│ │
|
||||
│ 💡 "notitie jan", "overdracht", "zoek marie" │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
WAARDE: Geen keuze-stress. Geen menu's. Eén vraag.
|
||||
```
|
||||
|
||||
**Moment 2: De Herkenning**
|
||||
```
|
||||
User: "notitie voor Jan"
|
||||
|
||||
System:
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 📝 Dagnotitie voor Jan de Vries │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ Categorie: [ADL ▼] Tijd: [14:32] │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ _ │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ [Opslaan] │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
WAARDE: "Het begreep me!" Patient al ingevuld. Direct typen.
|
||||
```
|
||||
|
||||
**Moment 3: De Voice Flow**
|
||||
```
|
||||
User klikt 🎤
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 🔴 Luistert... │
|
||||
│ │
|
||||
│ "Mevrouw heeft goed gegeten, medicatie ingenomen, │
|
||||
│ was wat onrustig vanmorgen maar nu stabiel" │
|
||||
│ │
|
||||
│ [Stop] [Opnieuw] │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
WAARDE: Handen vrij. Praten is sneller dan typen.
|
||||
Natuurlijke taal, geen formulier-denken.
|
||||
```
|
||||
|
||||
**Moment 4: De Bevestiging**
|
||||
```
|
||||
Na opslaan:
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ ✓ Notitie opgeslagen [Ongedaan] │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
Recent: [Jan - Notitie ✓ 14:32]
|
||||
|
||||
WAARDE: Zekerheid. "Het staat erin." Undo als vangnet.
|
||||
```
|
||||
|
||||
**Moment 5: De Volgende Actie**
|
||||
```
|
||||
System: Klaar. Wat nu?
|
||||
___________________________________________________
|
||||
|
||||
Suggestie: Je hebt nog 2 patiënten met openstaande notities
|
||||
|
||||
WAARDE: Flow behouden. Niet terug naar start.
|
||||
Proactief helpen.
|
||||
```
|
||||
|
||||
### 3.3 Waarde-Killers (Anti-Patterns)
|
||||
|
||||
| Anti-Pattern | Waarom Slecht | Oplossing |
|
||||
|--------------|---------------|-----------|
|
||||
| "Weet je het zeker?" dialoog | Vertraagt, twijfel zaaien | Undo in plaats van confirm |
|
||||
| Verplichte velden | Blokkeert snelle invoer | Alleen patient verplicht |
|
||||
| Modal op modal | Cognitive overload | Max 1 laag diep |
|
||||
| Laden... spinner | Wachten = frustratie | Optimistic UI |
|
||||
| "Sessie verlopen" | Werk kwijt | Auto-save drafts |
|
||||
|
||||
### 3.4 Implementatie: Waarde-First Design
|
||||
|
||||
**Principe 1: Progressive Disclosure**
|
||||
```
|
||||
Stap 1: Minimaal formulier (alleen tekst)
|
||||
↓
|
||||
Stap 2: Optionele details (categorie, tijd) - collapsed
|
||||
↓
|
||||
Stap 3: Geavanceerd (tags, links) - hidden by default
|
||||
```
|
||||
|
||||
**Principe 2: Defaults die Kloppen**
|
||||
```typescript
|
||||
// Pre-fill logica
|
||||
const defaults = {
|
||||
patient: context.activePatient || extractFromIntent(input),
|
||||
category: inferCategory(input), // "medicatie" → Medicatie
|
||||
time: new Date(), // Nu
|
||||
includeInHandover: true, // Standaard aan
|
||||
}
|
||||
```
|
||||
|
||||
**Principe 3: Keyboard-First, Voice-Enhanced**
|
||||
```
|
||||
Enter = Opslaan (als er tekst is)
|
||||
Escape = Sluiten (met draft save)
|
||||
Tab = Volgende veld
|
||||
Cmd+K = Terug naar Command input
|
||||
Spacebar = Start/stop voice (in input)
|
||||
```
|
||||
|
||||
**Principe 4: Feedback Loops**
|
||||
```
|
||||
Input → Instant echo (wat het systeem hoorde)
|
||||
Processing→ Subtle indicator (geen blocking spinner)
|
||||
Success → Toast + sound + Recent update
|
||||
Error → Inline, niet modal, met fix-suggestie
|
||||
```
|
||||
|
||||
### 3.5 Waarde Meten
|
||||
|
||||
**Metrics die waarde bewijzen:**
|
||||
|
||||
| Metric | Target | Hoe Meten |
|
||||
|--------|--------|-----------|
|
||||
| Time-to-first-input | <2 sec | Timestamp command → blok open |
|
||||
| Task completion time | <30 sec (notitie) | Blok open → save |
|
||||
| Intent accuracy | >90% | Correct blok / totaal attempts |
|
||||
| Voice adoption | >40% | Voice inputs / totaal inputs |
|
||||
| Fallback usage | <15% | Blok-picker clicks / totaal |
|
||||
| Error rate | <5% | Failed saves / totaal saves |
|
||||
|
||||
### 3.6 UX Implementatie Prioriteit
|
||||
|
||||
```
|
||||
WEEK 1: Core Interaction
|
||||
├── Command input component
|
||||
├── Voice indicator states
|
||||
├── Block container met animaties
|
||||
└── Success/error feedback
|
||||
|
||||
WEEK 2: Waarde-Blokken
|
||||
├── Dagnotitie (minimalist form)
|
||||
├── Zoeken (cmdk + patient cards)
|
||||
└── Pre-fill animations
|
||||
|
||||
WEEK 3: Polish
|
||||
├── Microinteracties
|
||||
├── Keyboard shortcuts
|
||||
├── Fallback blok-picker
|
||||
└── Onboarding hints
|
||||
|
||||
WEEK 4: Demo Ready
|
||||
├── Happy path perfectioneren
|
||||
├── Edge case handling
|
||||
├── Performance tuning
|
||||
└── Demo scenario walkthroughs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Gezamenlijke Waarde-Conclusie
|
||||
|
||||
### 4.1 Waar Ligt de Meeste Waarde?
|
||||
|
||||
**Top 3 Waarde-Dragers:**
|
||||
|
||||
| # | Feature | Waarde Reden |
|
||||
|---|---------|--------------|
|
||||
| 1 | **Voice Dagnotitie** | Hoogste frequentie (20x/dag), grootste tijdwinst (80%), laagste effort |
|
||||
| 2 | **Instant Zoeken** | Elimineert navigatie volledig, elke actie begint met "wie" |
|
||||
| 3 | **Smart Pre-fill** | "Het systeem begrijpt me" - emotionele waarde + tijdwinst |
|
||||
|
||||
**Waarde Piramide:**
|
||||
|
||||
```
|
||||
▲
|
||||
/│\
|
||||
/ │ \
|
||||
/ │ \
|
||||
/ │ \ DELIGHT
|
||||
/ AI │ \ "Het systeem denkt mee"
|
||||
/ suggestie \
|
||||
/──────────────\
|
||||
/ \
|
||||
/ Pre-fill \ SATISFACTION
|
||||
/ Voice input \ "Het begrijpt me"
|
||||
/ Snelle feedback \
|
||||
/────────────────────────\
|
||||
/ \
|
||||
/ Intent herkenning \ BASIC
|
||||
/ Blok openen \ "Het werkt"
|
||||
/ Opslaan lukt \
|
||||
/──────────────────────────────────\
|
||||
```
|
||||
|
||||
### 4.2 Implementatie Volgorde op Basis van Waarde
|
||||
|
||||
```
|
||||
FASE 1: "Het werkt" (Basic)
|
||||
─────────────────────────
|
||||
• Command Center layout
|
||||
• Text input → Intent → Blok openen
|
||||
• Dagnotitie blok (simpel form)
|
||||
• Opslaan + bevestiging
|
||||
|
||||
FASE 2: "Het begrijpt me" (Satisfaction)
|
||||
────────────────────────────────────────
|
||||
• Voice input integratie
|
||||
• Patient pre-fill uit intent
|
||||
• Categorie herkenning
|
||||
• Zoeken blok
|
||||
|
||||
FASE 3: "Het denkt mee" (Delight)
|
||||
─────────────────────────────────
|
||||
• Rapportage met AI structurering
|
||||
• Overdracht met AI samenvatting
|
||||
• Suggesties ("wil je ook...?")
|
||||
• Context-aware hints
|
||||
```
|
||||
|
||||
### 4.3 Concrete Implementatie Aanbevelingen
|
||||
|
||||
**1. Start met Dagnotitie, niet Rapportage**
|
||||
|
||||
*Waarom:*
|
||||
- Dagnotitie is simpeler (1 tekstveld)
|
||||
- Hogere frequentie = sneller feedback
|
||||
- Sneller "waarde-bewijs" voor stakeholders
|
||||
- Rapportage kan als "upgrade" komen
|
||||
|
||||
**2. Bouw Zoeken als Fundament**
|
||||
|
||||
```typescript
|
||||
// Zoeken is de basis voor alles
|
||||
"notitie jan" → Zoek Jan → Open Dagnotitie
|
||||
"gesprek met jan" → Zoek Jan → Open Rapportage
|
||||
"overdracht jan" → Zoek Jan → Open Overdracht
|
||||
|
||||
// Zonder goede zoek = geen pre-fill = geen waarde
|
||||
```
|
||||
|
||||
**3. Voice is Must-Have, niet Nice-to-Have**
|
||||
|
||||
*Klant citaat:*
|
||||
> "Ik draag handschoenen, ik heb net iemand gewassen,
|
||||
> ik kan niet gaan typen. Voice is geen luxe."
|
||||
|
||||
*Implementatie:*
|
||||
- Voice input in Command Center (dag 1)
|
||||
- Voice in Dagnotitie tekstveld (dag 1)
|
||||
- Deepgram werkt al - alleen UI koppelen
|
||||
|
||||
**4. Pre-fill is de "Magie"**
|
||||
|
||||
```typescript
|
||||
// Dit is het WOW-moment
|
||||
Input: "Jan heeft medicatie gehad"
|
||||
|
||||
Resultaat:
|
||||
├── Patient: Jan de Vries (auto-selected)
|
||||
├── Categorie: Medicatie (auto-selected)
|
||||
├── Tekst: "heeft medicatie gehad" (pre-filled)
|
||||
└── Tijd: 14:32 (current time)
|
||||
|
||||
// User hoeft alleen: review → save
|
||||
```
|
||||
|
||||
**5. Fallback = Vertrouwen**
|
||||
|
||||
```
|
||||
Als intent mislukt:
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Ik begreep dat niet helemaal. │
|
||||
│ │
|
||||
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │ 📝 │ │ 🔍 │ │ 📋 │ │ 🔄 │ │
|
||||
│ │Notitie │ │ Zoeken │ │Rapport │ │Overdr. │ │
|
||||
│ └────────┘ └────────┘ └────────┘ └────────┘ │
|
||||
│ │
|
||||
│ Of probeer opnieuw: ____________________________ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
// Nooit een doodlopende straat
|
||||
```
|
||||
|
||||
### 4.4 Success Criteria (Waarde-Based)
|
||||
|
||||
| Stakeholder | Success = |
|
||||
|-------------|-----------|
|
||||
| **Klant** | "Mijn team is 30 min/dag sneller klaar met admin" |
|
||||
| **Zorgverlener** | "Ik hoef niet meer na te denken over het systeem" |
|
||||
| **PO** | "Demo leidt tot concrete vervolgafspraak" |
|
||||
| **UX** | "Users raken de fallback-picker zelden aan" |
|
||||
|
||||
---
|
||||
|
||||
## 5. Actieplan
|
||||
|
||||
### Week 1: Foundation + Eerste Waarde
|
||||
- [ ] Command Center layout
|
||||
- [ ] Dagnotitie blok (simpel)
|
||||
- [ ] Basic intent classification
|
||||
- [ ] Voice input in Command
|
||||
|
||||
### Week 2: Core Waarde
|
||||
- [ ] Zoeken blok (cmdk)
|
||||
- [ ] Patient pre-fill
|
||||
- [ ] Categorie herkenning
|
||||
- [ ] Fallback blok-picker
|
||||
|
||||
### Week 3: Waarde Uitbreiden
|
||||
- [ ] Rapportage blok
|
||||
- [ ] AI structurering
|
||||
- [ ] Overdracht blok
|
||||
- [ ] Microinteracties
|
||||
|
||||
### Week 4: Demo + Metrics
|
||||
- [ ] Demo scenario's perfectioneren
|
||||
- [ ] Waarde-metrics implementeren
|
||||
- [ ] LinkedIn content
|
||||
- [ ] Stakeholder presentatie
|
||||
|
||||
---
|
||||
|
||||
*De meeste waarde zit in de eenvoudigste dingen: snel een notitie maken,
|
||||
snel iemand vinden, en het gevoel dat het systeem je begrijpt.*
|
||||
987
docs/swift/swift-fo-ai.md
Normal file
987
docs/swift/swift-fo-ai.md
Normal file
@@ -0,0 +1,987 @@
|
||||
# 🧩 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 |
|
||||
632
docs/swift/swift-prd.md
Normal file
632
docs/swift/swift-prd.md
Normal file
@@ -0,0 +1,632 @@
|
||||
# 📄 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 |
|
||||
1070
docs/swift/swift-ux-v2.1.md
Normal file
1070
docs/swift/swift-ux-v2.1.md
Normal file
File diff suppressed because it is too large
Load Diff
486
docs/swift/taken-en-vragen-analyse.md
Normal file
486
docs/swift/taken-en-vragen-analyse.md
Normal file
@@ -0,0 +1,486 @@
|
||||
# Taken & Vragen Analyse: EPD Functionaliteit
|
||||
|
||||
**Document:** Wat moet de nieuwe UI kunnen?
|
||||
**Datum:** december 2024
|
||||
**Doel:** Inventarisatie van alle taken en vragen die het EPD beantwoordt
|
||||
|
||||
---
|
||||
|
||||
## 1. Overzicht Huidige EPD Modules
|
||||
|
||||
Op basis van de codebase analyse:
|
||||
|
||||
```
|
||||
/epd
|
||||
├── dashboard/ # Overzicht
|
||||
├── patients/ # Patiëntbeheer
|
||||
│ ├── [id]/
|
||||
│ │ ├── basisgegevens/ # NAW, contactgegevens
|
||||
│ │ ├── intakes/ # Intake trajecten
|
||||
│ │ │ └── [intakeId]/
|
||||
│ │ │ ├── anamnese/ # Voorgeschiedenis
|
||||
│ │ │ ├── examination/ # Onderzoek
|
||||
│ │ │ ├── diagnosis/ # Diagnose (ICD-10)
|
||||
│ │ │ ├── risk/ # Risicotaxatie
|
||||
│ │ │ ├── kindcheck/ # Kindcheck
|
||||
│ │ │ ├── contacts/ # Contactpersonen
|
||||
│ │ │ ├── behandeladvies/# Behandeladvies
|
||||
│ │ │ └── rom/ # ROM vragenlijsten
|
||||
│ │ ├── diagnose/ # Diagnosebeheer
|
||||
│ │ ├── behandelplan/ # Behandelplan
|
||||
│ │ ├── rapportage/ # Rapportages
|
||||
│ │ └── screening/ # Screening
|
||||
├── verpleegrapportage/ # Verpleegkundig overzicht
|
||||
│ ├── overdracht/ # Overdrachtsrapportage
|
||||
│ └── rapportage/ # Dagrapportage per patiënt
|
||||
├── agenda/ # Afspraken
|
||||
├── clients/ # Client overzicht
|
||||
└── reports/ # Rapportages overzicht
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Categorieën van Vragen
|
||||
|
||||
### 2.1 ZOEKEN & VINDEN (Wie/Wat/Waar)
|
||||
|
||||
| Vraag | Huidige UI | Data |
|
||||
|-------|------------|------|
|
||||
| Wie is [naam]? | patients/ → zoeken | patients |
|
||||
| Waar is [patiënt] opgenomen? | patients/[id] | encounters |
|
||||
| Welke diagnoses heeft [patiënt]? | patients/[id]/diagnose | conditions |
|
||||
| Wat is het behandelplan van [patiënt]? | patients/[id]/behandelplan | care_plans |
|
||||
| Welke medicatie gebruikt [patiënt]? | - (nog niet) | - |
|
||||
| Wie zijn de contactpersonen van [patiënt]? | intakes/[id]/contacts | contacts |
|
||||
| Wat is de risicoscore van [patiënt]? | intakes/[id]/risk | risk_assessments |
|
||||
|
||||
### 2.2 RAPPORTEREN & DOCUMENTEREN (Vastleggen)
|
||||
|
||||
| Taak | Huidige UI | Data |
|
||||
|------|------------|------|
|
||||
| Dagnotitie maken | verpleegrapportage/rapportage | reports (type: verpleegkundig) |
|
||||
| Rapportage schrijven | patients/[id]/rapportage | reports |
|
||||
| Intake vastleggen | patients/[id]/intakes/new | intakes |
|
||||
| Anamnese invullen | intakes/[id]/anamnese | anamneses |
|
||||
| Onderzoek documenteren | intakes/[id]/examination | examinations |
|
||||
| Diagnose toevoegen | patients/[id]/diagnose | conditions |
|
||||
| Behandeladvies schrijven | intakes/[id]/behandeladvies | - |
|
||||
| Risicotaxatie invullen | intakes/[id]/risk | risk_assessments |
|
||||
| Kindcheck uitvoeren | intakes/[id]/kindcheck | - |
|
||||
|
||||
### 2.3 SAMENVATTEN & OVERDRAGEN (Communiceren)
|
||||
|
||||
| Taak | Huidige UI | Data |
|
||||
|------|------------|------|
|
||||
| Overdracht maken | verpleegrapportage/overdracht | AI samenvatting |
|
||||
| Samenvatting van vandaag | - | reports (shift_date) |
|
||||
| Wat is er gebeurd met [patiënt]? | verpleegrapportage/rapportage | reports, vitals |
|
||||
| Aandachtspunten voor collega | overdracht | include_in_handover |
|
||||
|
||||
### 2.4 PLANNEN & ORGANISEREN (Agenda)
|
||||
|
||||
| Taak | Huidige UI | Data |
|
||||
|------|------------|------|
|
||||
| Mijn afspraken vandaag | agenda/ | appointments |
|
||||
| Afspraken van [patiënt] | - | appointments |
|
||||
| Afspraak inplannen | agenda/ (FullCalendar) | appointments |
|
||||
| Wie zie ik deze week? | agenda/ | appointments |
|
||||
|
||||
### 2.5 BEHANDELEN & VOLGEN (Zorgpad)
|
||||
|
||||
| Taak | Huidige UI | Data |
|
||||
|------|------------|------|
|
||||
| Behandelplan opstellen | patients/[id]/behandelplan | care_plans |
|
||||
| Doelen formuleren | behandelplan | care_plans.goals |
|
||||
| Voortgang evalueren | - | - |
|
||||
| ROM afnemen | intakes/[id]/rom | - |
|
||||
|
||||
---
|
||||
|
||||
## 3. Frequentie & Prioriteit Matrix
|
||||
|
||||
### 3.1 Hoogfrequent (meerdere keren per dag)
|
||||
|
||||
| Taak | Freq/dag | Huidige klikken | Ephemeral target |
|
||||
|------|----------|-----------------|------------------|
|
||||
| **Dagnotitie maken** | 10-20x | 5-8 | 1 zin |
|
||||
| **Patiënt zoeken** | 15-20x | 3-5 | 1 zin |
|
||||
| **Laatste notities bekijken** | 10-15x | 4-6 | 1 zin |
|
||||
| **Overdracht maken** | 2-3x | 8-12 | 1 zin |
|
||||
|
||||
### 3.2 Middenfrequent (dagelijks)
|
||||
|
||||
| Taak | Freq/dag | Huidige klikken | Ephemeral target |
|
||||
|------|----------|-----------------|------------------|
|
||||
| **Rapportage schrijven** | 3-5x | 6-10 | 1 zin + dicteren |
|
||||
| **Diagnose bekijken** | 3-5x | 4-6 | 1 zin |
|
||||
| **Behandelplan raadplegen** | 2-3x | 4-6 | 1 zin |
|
||||
| **Afspraken bekijken** | 2-3x | 3-4 | 1 zin |
|
||||
|
||||
### 3.3 Laagfrequent (wekelijks/maandelijks)
|
||||
|
||||
| Taak | Frequentie | Huidige klikken | Ephemeral target |
|
||||
|------|------------|-----------------|------------------|
|
||||
| **Intake starten** | 1x/week | 10-15 | Wizard |
|
||||
| **Behandelplan maken** | 1x/maand | 15-20 | Wizard + AI |
|
||||
| **Diagnose toevoegen** | 1x/week | 6-8 | 1 zin |
|
||||
| **Risicotaxatie** | 1x/maand | 10-15 | Wizard |
|
||||
|
||||
---
|
||||
|
||||
## 4. Mapping naar Ephemeral UI Bouwblokken
|
||||
|
||||
### 4.1 Must Have (MVP)
|
||||
|
||||
| Bouwblok | Beantwoordt vragen | Prioriteit |
|
||||
|----------|-------------------|------------|
|
||||
| **Dagnotitie** | "notitie voor jan: medicatie gegeven" | P1 |
|
||||
| **Zoeken** | "wie is jan", "zoek marie" | P1 |
|
||||
| **Overdracht** | "overdracht maken", "samenvatting dienst" | P1 |
|
||||
|
||||
### 4.2 Should Have
|
||||
|
||||
| Bouwblok | Beantwoordt vragen | Prioriteit |
|
||||
|----------|-------------------|------------|
|
||||
| **Rapportage** | "gesprek gehad met jan", "rapportage maken" | P2 |
|
||||
| **Patiënt Info** | "diagnoses van jan", "behandelplan jan" | P2 |
|
||||
| **Agenda** | "mijn afspraken", "wanneer zie ik jan" | P2 |
|
||||
|
||||
### 4.3 Could Have
|
||||
|
||||
| Bouwblok | Beantwoordt vragen | Prioriteit |
|
||||
|----------|-------------------|------------|
|
||||
| **Behandelplan** | "plan opstellen voor jan" | P3 |
|
||||
| **Diagnose** | "diagnose toevoegen: F41.1" | P3 |
|
||||
| **Risico** | "risicotaxatie jan" | P3 |
|
||||
| **Intake** | "nieuwe intake starten" | P3 |
|
||||
|
||||
---
|
||||
|
||||
## 5. Intent Classificatie Mapping
|
||||
|
||||
### 5.1 Schrijf-intents (Writer)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ INTENT: dagnotitie │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Trigger patterns: │
|
||||
│ • "notitie [patient]" │
|
||||
│ • "dagnotitie" │
|
||||
│ • "[patient] medicatie gegeven" │
|
||||
│ • "[patient] heeft gegeten" │
|
||||
│ • "incident bij [patient]" │
|
||||
│ │
|
||||
│ Entities: │
|
||||
│ • patient_name: string │
|
||||
│ • category: medicatie|adl|gedrag|incident|observatie │
|
||||
│ • content: string (optioneel) │
|
||||
│ │
|
||||
│ Pre-fill: │
|
||||
│ • Patient selector │
|
||||
│ • Category dropdown │
|
||||
│ • Tekstveld │
|
||||
│ • include_in_handover checkbox │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ INTENT: rapportage │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Trigger patterns: │
|
||||
│ • "rapportage [patient]" │
|
||||
│ • "gesprek gehad met [patient]" │
|
||||
│ • "verslag maken" │
|
||||
│ • "sessie met [patient]" │
|
||||
│ │
|
||||
│ Entities: │
|
||||
│ • patient_name: string │
|
||||
│ • report_type: voortgang|observatie|contact|crisis │
|
||||
│ │
|
||||
│ Pre-fill: │
|
||||
│ • Patient selector │
|
||||
│ • Type dropdown │
|
||||
│ • Rich text editor │
|
||||
│ • AI structureren knop │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ INTENT: diagnose_toevoegen │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Trigger patterns: │
|
||||
│ • "diagnose [patient]: [code]" │
|
||||
│ • "diagnose toevoegen" │
|
||||
│ • "[patient] heeft [diagnose]" │
|
||||
│ │
|
||||
│ Entities: │
|
||||
│ • patient_name: string │
|
||||
│ • icd10_code: string (optioneel) │
|
||||
│ • diagnosis_text: string (optioneel) │
|
||||
│ │
|
||||
│ Pre-fill: │
|
||||
│ • Patient selector │
|
||||
│ • ICD-10 zoeken combobox │
|
||||
│ • Clinical status │
|
||||
│ • Severity │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5.2 Lees-intents (Reader)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ INTENT: zoeken │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Trigger patterns: │
|
||||
│ • "zoek [naam]" │
|
||||
│ • "wie is [naam]" │
|
||||
│ • "vind [naam]" │
|
||||
│ • "[naam]" (als geen andere intent matcht) │
|
||||
│ │
|
||||
│ Entities: │
|
||||
│ • search_query: string │
|
||||
│ │
|
||||
│ Output: │
|
||||
│ • PatientCards met quick actions │
|
||||
│ • Selectie → set active patient │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ INTENT: patient_info │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Trigger patterns: │
|
||||
│ • "diagnoses van [patient]" │
|
||||
│ • "behandelplan [patient]" │
|
||||
│ • "info [patient]" │
|
||||
│ • "dossier [patient]" │
|
||||
│ • "risico's [patient]" │
|
||||
│ │
|
||||
│ Entities: │
|
||||
│ • patient_name: string │
|
||||
│ • info_type: diagnoses|behandelplan|risico|alles │
|
||||
│ │
|
||||
│ Output: │
|
||||
│ • Collapsible info cards │
|
||||
│ • Quick actions (bewerken, toevoegen) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ INTENT: overdracht │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Trigger patterns: │
|
||||
│ • "overdracht" │
|
||||
│ • "overdracht maken" │
|
||||
│ • "samenvatting dienst" │
|
||||
│ • "wat is er gebeurd vandaag" │
|
||||
│ │
|
||||
│ Entities: │
|
||||
│ • time_range: afgelopen 8 uur (default) │
|
||||
│ • patient_filter: string[] (optioneel) │
|
||||
│ │
|
||||
│ Output: │
|
||||
│ • AI-samenvatting per patiënt │
|
||||
│ • Bronverwijzingen │
|
||||
│ • Aandachtspunten │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ INTENT: agenda │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Trigger patterns: │
|
||||
│ • "mijn afspraken" │
|
||||
│ • "afspraken vandaag" │
|
||||
│ • "wanneer zie ik [patient]" │
|
||||
│ • "planning deze week" │
|
||||
│ │
|
||||
│ Entities: │
|
||||
│ • date_range: vandaag|deze week|datum │
|
||||
│ • patient_name: string (optioneel) │
|
||||
│ │
|
||||
│ Output: │
|
||||
│ • Afsprakenlijst │
|
||||
│ • Quick action: nieuwe afspraak │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Data Requirements per Intent
|
||||
|
||||
### 6.1 Database Tabellen per Bouwblok
|
||||
|
||||
| Bouwblok | Read | Write |
|
||||
|----------|------|-------|
|
||||
| **Dagnotitie** | patients | reports |
|
||||
| **Zoeken** | patients, conditions, care_plans | - |
|
||||
| **Rapportage** | patients, intakes | reports |
|
||||
| **Overdracht** | patients, reports, vitals, risk_assessments | - |
|
||||
| **Patient Info** | patients, conditions, care_plans, risk_assessments | - |
|
||||
| **Diagnose** | patients, conditions | conditions |
|
||||
| **Agenda** | patients, appointments, practitioners | appointments |
|
||||
| **Behandelplan** | patients, conditions, intakes, anamneses | care_plans |
|
||||
|
||||
### 6.2 API Routes per Bouwblok
|
||||
|
||||
| Bouwblok | Bestaande API | Nieuw nodig? |
|
||||
|----------|---------------|--------------|
|
||||
| **Dagnotitie** | POST /api/reports | Nee |
|
||||
| **Zoeken** | GET /api/patients/search | Ja (fuzzy) |
|
||||
| **Rapportage** | POST /api/reports | Nee |
|
||||
| **Overdracht** | GET /api/overdracht, POST /api/overdracht/generate | Nee |
|
||||
| **Patient Info** | GET /api/verpleegrapportage/[patientId] | Uitbreiden |
|
||||
| **Diagnose** | - | Ja |
|
||||
| **Agenda** | - | Ja |
|
||||
| **Behandelplan** | POST /api/behandelplan/generate | Nee |
|
||||
|
||||
---
|
||||
|
||||
## 7. Contextual Awareness
|
||||
|
||||
### 7.1 Impliciete Context
|
||||
|
||||
| Context | Bron | Gebruik |
|
||||
|---------|------|---------|
|
||||
| **Huidige gebruiker** | Auth session | Filter "mijn patiënten" |
|
||||
| **Huidige dienst** | Tijd (ochtend/middag/avond/nacht) | Shift-based filtering |
|
||||
| **Laatst bekeken patiënt** | Session state | Pre-fill suggestie |
|
||||
| **Recente acties** | Session state | Quick access |
|
||||
|
||||
### 7.2 Expliciete Context
|
||||
|
||||
| Context | Trigger | Effect |
|
||||
|---------|---------|--------|
|
||||
| **Actieve patiënt** | Zoeken + selecteren | Pre-fill alle volgende acties |
|
||||
| **Dienst overdracht** | "overdracht" | Filter op afgelopen X uur |
|
||||
| **Specifieke datum** | "afspraken morgen" | Filter op datum |
|
||||
|
||||
---
|
||||
|
||||
## 8. Voice Command Examples
|
||||
|
||||
### 8.1 Dagnotitie Flow
|
||||
|
||||
```
|
||||
Voice: "Jan de Vries heeft zijn medicatie ingenomen, geen bijzonderheden"
|
||||
|
||||
Intent: dagnotitie
|
||||
Entities:
|
||||
- patient_name: "Jan de Vries"
|
||||
- category: "medicatie" (extracted from "medicatie ingenomen")
|
||||
- content: "heeft zijn medicatie ingenomen, geen bijzonderheden"
|
||||
|
||||
Pre-fill:
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 📝 Dagnotitie voor Jan de Vries │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ Categorie: [Medicatie ▼] ← auto-selected │
|
||||
│ Tijd: [14:32] │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ heeft zijn medicatie ingenomen, geen bijzonderheden │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ☑ Opnemen in overdracht │
|
||||
│ │
|
||||
│ [Opslaan] │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 8.2 Zoeken Flow
|
||||
|
||||
```
|
||||
Voice: "Zoek Marie"
|
||||
|
||||
Intent: zoeken
|
||||
Entities:
|
||||
- search_query: "Marie"
|
||||
|
||||
Output:
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 🔍 Zoekresultaten voor "Marie" │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Marie van den Berg │ │
|
||||
│ │ 15-03-1985 · Kamer 12 · F41.1 Gegeneraliseerde angst│ │
|
||||
│ │ [Notitie] [Dossier] [Rapportage] │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Marie Jansen │ │
|
||||
│ │ 22-08-1972 · Kamer 8 · F32.1 Depressieve episode │ │
|
||||
│ │ [Notitie] [Dossier] [Rapportage] │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 8.3 Overdracht Flow
|
||||
|
||||
```
|
||||
Voice: "Overdracht maken"
|
||||
|
||||
Intent: overdracht
|
||||
Entities:
|
||||
- time_range: "afgelopen 8 uur" (default)
|
||||
|
||||
Output:
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 🔄 Overdracht Ochtend dienst │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ 06:00 - 14:00 · 5 patiënten met updates │
|
||||
│ │
|
||||
│ ▼ Jan de Vries (3 notities) │
|
||||
│ ⚠ Aandachtspunt: onrustig vannacht │
|
||||
│ • 07:30 Medicatie uitgereikt ✓ │
|
||||
│ • 08:45 Ontbijt genuttigd │
|
||||
│ • 11:00 Gesprek met psycholoog │
|
||||
│ │
|
||||
│ ▼ Marie van den Berg (2 notities) │
|
||||
│ • 08:00 ADL ondersteuning │
|
||||
│ • 10:30 Bezoek familie │
|
||||
│ │
|
||||
│ ─────────────────────────────────────────────────────── │
|
||||
│ AI Samenvatting: │
|
||||
│ "Rustige ochtend. Aandacht voor Jan de Vries die │
|
||||
│ vannacht onrustig was. Marie ontving familiebezoek..." │
|
||||
│ │
|
||||
│ [Kopiëren] [Printen] [Doorsturen] │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Conclusie: Minimale Intent Set
|
||||
|
||||
### 9.1 MVP (6 intents)
|
||||
|
||||
| Intent | Type | Frequentie | Complexiteit |
|
||||
|--------|------|------------|--------------|
|
||||
| `dagnotitie` | Writer | Zeer hoog | Laag |
|
||||
| `zoeken` | Reader | Zeer hoog | Laag |
|
||||
| `overdracht` | Reader | Hoog | Medium |
|
||||
| `rapportage` | Writer | Hoog | Medium |
|
||||
| `patient_info` | Reader | Hoog | Laag |
|
||||
| `agenda` | Reader | Medium | Laag |
|
||||
|
||||
### 9.2 Fallback
|
||||
|
||||
| Intent | Actie |
|
||||
|--------|-------|
|
||||
| `onbekend` | Toon blok-picker met 6 opties |
|
||||
| `ambigue` | "Bedoelde je...?" met opties |
|
||||
| `lage_confidence` | Toon blok-picker |
|
||||
|
||||
### 9.3 Training Data Nodig
|
||||
|
||||
Per intent minimaal 20-30 voorbeeldzinnen in het Nederlands, inclusief:
|
||||
- Formele vorm ("Ik wil een notitie maken")
|
||||
- Informele vorm ("notitie jan")
|
||||
- Met context ("jan medicatie")
|
||||
- Zonder context ("notitie maken")
|
||||
- Met typo's ("noitie jan")
|
||||
- Voice transcriptie varianten
|
||||
|
||||
---
|
||||
|
||||
*Dit document dient als basis voor de intent classificatie en UI bouwblokken.*
|
||||
1257
docs/swift/to-swift-v1.md
Normal file
1257
docs/swift/to-swift-v1.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user