feat: rapportage API, speech recorder refactor, docs reorganisatie

Multiple features and improvements:

Reports/Rapportage API:
- Created REST API endpoints: /api/reports (GET/POST), /api/reports/[id] (GET/PATCH/DELETE)
- Added /api/reports/classify endpoint for AI classification
- Supabase migrations: reports table + RLS policies
- Server utilities: api-client.ts for DRY fetch logic
- Type definitions: lib/types/report.ts with Zod schemas
- Removed old rapportage-modal component (replaced by split-view)

Speech Recorder Refactor:
- Moved speech-recorder from intake-specific to shared components/
- Updated treatment-advice-form to use new location
- Updated intake actions for speech functionality

UI Components (shadcn):
- Added dialog, dropdown-menu, toast, toaster components
- Added use-toast hook for toast notifications

Documentation:
- Reorganized docs/release/ → docs/reports/ for better structure
- Archived old specs to docs/specs/archive/
- Added screening-system.mdx documentation
- Added rapportage-split-view-design.md
- Added UI screenshots for troubleshooting

Dependencies:
- Updated package.json and pnpm-lock.yaml
- Regenerated database.types.ts from Supabase

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
colinislit
2025-11-24 14:14:06 +01:00
parent 0130e28f1e
commit a789bebe96
37 changed files with 5034 additions and 1977 deletions

View File

@@ -1,45 +0,0 @@
## 2025-11-23 — Clients → Patients datafix + seeds (Colin)
- Clients die na de hoofdrelease nog in `clients` stonden opgespoord met `clients LEFT JOIN patients` sanity check (Supabase SQL editor)
- Idempotente blok uit `20241121_migrate_legacy_to_fhir.sql` opnieuw gedraaid zodat alle ontbrekende clients nu als patients bestaan
- Verification DO-block uitgevoerd zodat de teller op 0 missing clients staat en de migratie gelogd
- Default organisatie opnieuw gezaaid met `pnpm tsx scripts/seed-organization.ts` (env geladen via `.env.local`)
## 2026-02-XX — Screening Intake Fase 1 & 2 (Colin)
- TipTap placeholder hints toegevoegd + styled zodat behandeladvies-sectie guidance toont
- Metadata-sectie, afrondingsworkflow en behandelaarselecties bouwden de behandeladvies-tab af
- Intake-tabs (contact, kindcheck, risico, anamnese, onderzoeken/ROM, diagnose, behandeladvies) compleet met Supabase CRUD
- Status dropdowns gecorrigeerd (bezig/afgerond) en dokument flows afgerond
- Supabase migratiestappen wachten nog op einde maintenance (fase 0 runbook ligt klaar)
## 2025-11-23 — Universele Rapportage backend + modal (Colin)
- API: `/api/reports` (GET/POST) + `/api/reports/[reportId]` (GET/PATCH/DELETE) + `/api/reports/classify` staan, met Zod-validatie en soft delete
- Supabase: `reports` tabel + migratie + RLS policies uitgerold, types toegevoegd in `lib/supabase/database.types.ts`
- Server actions: `app/epd/patients/[id]/rapportage/actions.ts` + gedeelde `lib/server/api-client.ts` houden fetch logic DRY
- UI: shadcn-dialog gebaseerd Rapportage Modal met textarea, speech recorder, AI-analyse en save flow (E2.S1)
## 2025-11-23 — ClientSidebar duplicate cleanup (Colin)
- **Bug fix**: Dubbele sidebar (EPDSidebar + ClientSidebar) in patient detail routes verwijderd
- ClientSidebar (`app/epd/patients/[id]/components/client-sidebar.tsx`) blijkt 100% duplicate van EPDSidebar Level 2 navigatie
- EPDSidebar is al context-aware: detecteert patient routes en switcht automatisch tussen Level 1 (behandelaar) en Level 2 (patient) navigatie
- Verwijderd: ClientSidebar component (117 regels) + EPDLayoutClient wrapper (conditionele sidebar hiding)
- Vereenvoudigd: patient detail layout gebruikt nu alleen PatientLayoutClient zonder eigen sidebar rendering
- Resultaat: Eén sidebar component die automatisch switcht, -117 regels duplicate code, DRY principle hersteld
## 2025-11-23 — EPDHeader patient selector cleanup (Colin)
- **Bug fix**: Dubbele patient naam in UI (EPDHeader top bar + ClientHeader) verwijderd
- Design conflict ontstaan tijdens parallel development: EPDHeader (Epic 1) en ClientHeader (Epic 2) toonden beide patient naam
- EPDHeader's patient selector (center section met naam, ID, geboortedatum) was redundant na toevoegen ClientHeader
- Verwijderd: Patient fetch logic (useState, useEffect), patient selector UI, onnodige imports uit EPDHeader
- Component ownership verduidelijkt: EPDHeader = algemene navigatie (logo, search), ClientHeader = patient context (naam, status, acties)
- Resultaat: EPDHeader vereenvoudigd van 91 naar 34 regels (-57 regels), duidelijke separation of concerns
## 2025-11-23 — Reports created_by foreign key fix (Colin)
- **Bug fix**: Foreign key constraint violation bij opslaan rapportages
- Probleem: `reports.created_by` had FK constraint naar `practitioners.id`, maar code sloeg `auth.uid()` op
- Root cause: Practitioners tabel heeft `user_id` kolom, maar alle demo records hebben `user_id: null` (geen link naar auth users)
- Error: `insert or update on table "reports" violates foreign key constraint "reports_created_by_fkey"`
- Oplossing (prototype): Foreign key constraints verwijderd voor `created_by` en `updated_by` kolommen
- Migratie: `20251123_fix_reports_created_by_constraint.sql` toegepast via Supabase MCP
- Resultaat: Rapportages kunnen nu opgeslagen worden met auth user ID zonder FK constraint
- **Note voor productie**: In productie zou je practitioners.user_id vullen en FK constraints herstellen voor data integriteit

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

View File

@@ -0,0 +1,137 @@
# 🧩 Functioneel Ontwerp (FO) Universele Rapportage Split View MVP
**Projectnaam:** Mini-EPD Universele Rapportage Split View
**Versie:** v0.1 (concept MVP)
**Datum:** 06-03-2025
**Auteur:** Codex Agent
---
## 1. Doel en relatie met het PRD
🎯 **Doel van dit document:**
Beschrijving van de functionele werking voor een MVP waarin behandelaren tegelijk een rapportage kunnen schrijven en eerdere notities kunnen raadplegen, passend binnen het bestaande PRD voor Universele Rapportage.
📘 **Toelichting aan de lezer:**
Het FO focust op de split-view workflow (timeline + composer). Technische keuzes (server actions, Supabase) staan elders. Gebruik dit document om scope-afbakening voor MVP (Week3) af te stemmen.
---
## 2. Overzicht van de belangrijkste onderdelen
1. **Rapportage Header & Navigatie** knop "Nieuwe rapportage" scrollt naar composer en linkt vanaf andere tabs.
2. **KPI Tiles** tonen kernstatistieken (totaal, AI, laatste activiteit).
3. **Filterpaneel** zoekveld, typefilter, (nog toe te voegen) auteur/datum-filter.
4. **Timeline Lijst** scrollbare lijst met kaartjes, selectie, soft delete.
5. **Composer Paneel** tekstarea, spraakinput, AI-classificatie, referenties.
6. **Mobiele Drawer** responsive variant waarin timeline↔composer gewisseld worden. *(Nog te bouwen)*
---
## 3. Userstories
| ID | Rol | Doel / Actie | Waarde | Prioriteit |
|----|-----|--------------|--------|------------|
| UR-01 | Behandelaar | Terwijl ik schrijf wil ik vorige rapportages kunnen inzien | Context houden, fouten voorkomen | Hoog |
| UR-02 | Behandelaar | Ik wil via filters snel de juiste notitie van collega vinden | Tijdsbesparing | Hoog |
| UR-03 | Behandelaar | Ik wil AI laten bepalen welk type rapport ik schrijf | Consistentie, minder fouten | Hoog |
| UR-04 | Behandelaar | Ik wil een geselecteerde notitie als quote aan mijn verslag toevoegen | Bronverwijzing, samenwerking | Middel |
| UR-05 | Behandelaar | Op mobiel wil ik vloeiend wisselen tussen lezen en schrijven | Onderweg kunnen rapporteren | Middel |
| UR-06 | PO | Ik wil weten hoeveel AI-notities er zijn per client | KPI/usage | Laag |
---
## 4. Functionele werking per onderdeel
### 4.1 Rapportage Header & Navigatie
* Header toont cliëntnaam, status, laatste wijziging; knop "Nieuwe rapportage".
* Knop logica: staat gebruiker al op `/rapportage`, scroll dan naar composer (`#rapportage-composer` focus). Zo niet, navigeer naar rapportage en append hash zodat browser direct scrolt.
* ID van de composer moet focusbaar zijn (`tabIndex=-1` zodat `focus()` werkt).
### 4.2 KPI Tiles
* Toont 3 cards (totaal rapportages, AI-geclassificeerde rapportages, laatste activiteit).
* Data wordt client-side afgeleid uit `initialReports`.
* Wanneer nieuwe rapportage wordt aangemaakt of verwijderd worden tiles realtime herberekend.
* Lege état: tekst "Nog geen rapportages" + `—` voor laatste activiteit.
### 4.3 Filterpaneel
* Zoekveld filtert op tekst in body of AI reason.
* Type-filter (dropdown) toont alle rapporttypes, standaard "Alle".
* MVP-toevoegingen:
- Auteur-filter (dropdown met lijst van `created_by`).
- Datumfilter (van/tot) met quick-pills (Vandaag, 7d, 30d).
- Resetknop.
### 4.4 Timeline Lijst
* Kaartjes tonen type-badge, timestamp, maker, AI-confidence en contentpreview.
* Klik of Enter/Space selecteert item en highlight border.
* Delete-knop voert soft delete uit via server action, toont toast en verwijdert item lokaal.
* MVP-toevoegingen:
- Inline "Expand" om volledige tekst te lezen zonder composer te verlaten.
- Paginatie of virtual scroll voor >50 items.
- Indicator welke notities AI-gegenereerd zijn (badge).
- Autorisatie-check (alleen eigen dossiers, reeds door Supabase RLS, maar lege states voor forbidden).
### 4.5 Composer Paneel
* Tekstveld (205000 chars), spraakrecorder (Deepgram), AI-classificatie, type dropdown.
* Bottom bar toont status: "Concept wordt lokaal bijgehouden".
* Opslaan: server action `createReport` → toast success, reset state, highlight nieuwe entry.
* MVP-toevoegingen:
- Draft/autosave naar localStorage (per client) + timestamp, warning bij weg navigeren.
- Undo/redo per sessie.
- Attachments (placeholder).
- Loading skeleton zodat composer niet flasht bij SSR.
### 4.6 Referentie toevoegen
* Wanneer timeline-entry geselecteerd is, toont composer een "Geselecteerde rapportage" kaart.
* "Voeg referentie toe" voegt quote block in met snippet + meta.
* MVP: markeer binnen editor dat het een referentie is (bijv. blockquote-styling) en zorg dat quote 1-op-1 linkt terug naar bron (ID link).
* Bij wisselen van selectie mag composer vragen of huidige quote moet worden vervangen.
### 4.7 Mobiele Drawer (nog bouwen)
* Tabbed header `[Timeline] [Rapportage+]`.
* Timeline tab = stack van kaarten; verkeer identiek.
* Rapportage tab opent composer in drawer (~75% hoogte) met drag handle en "Terug".
* Autosave badge en AI-knoppen bewegen mee.
* Sticky CTA in footer.
---
## 5. UI-overzicht (visuele structuur)
```
┌───────────────────────────────────────────────┐
│ Topbalk: cliëntnaam, acties, zoeken │
├───────────────┬──────────────────────────────┤
│ Filters + │ Composer │
│ Timeline (L) │ - Header "Nieuwe ..." │
│ - Search │ - Textarea + speech │
│ - Type pills │ - AI badge + dropdown │
│ - Timeline │ - Referentie card │
│ │ - Sticky buttons │
├───────────────┴──────────────────────────────┤
│ Footer/Toasts │ Autosave msgs │
└───────────────────────────────────────────────┘
```
Mobiel: tabs bovenaan, composer als drawer.
---
## 6. Interacties met AI
| Locatie | AI-actie | Trigger | Output |
|---------|----------|---------|--------|
| Composer | Classificatie | Knop "Analyseer met AI" | JSON `{ type, confidence, reasoning }`, toont in badge + dropdown default |
| Composer | Typekeuze | User accepteert AI-type | Dropdown wordt vooringevuld, user kan overschrijven |
| (Toekomst) Timeline filter | AI context chips | Klik op AI badge in kaart | Filtert timeline op dat type |
---
## 7. Gebruikersrollen en rechten
| Rol | Toegang | Beperkingen |
|-----|---------|-------------|
| Behandelaar | Rapportage workspace voor eigen cliënten | Alleen RLS-toegelaten dossiers, soft delete alleen eigen rapportages |
| Supervisor (optioneel) | Timeline lezen | Geen composer, geen delete |
---
## 8. Bijlagen & Referenties
- PRD Universele Rapportage v1.0
- TO Universele Rapportage v1.0
- Bouwplan Universele Rapportage v1.0
- Rapportage Split View ontwerpnotities (docs/specs/screening-intake/rapportage-split-view-design.md)

View File

@@ -0,0 +1,935 @@
# 🧩 Functioneel Ontwerp (FO) — Universele Rapportage
**Projectnaam:** Mini-ECD - Universele Rapportage Functie
**Versie:** v1.0 (Week 2 MVP)
**Datum:** 23-11-2024
**Auteur:** Colin van der Heijden (AI Speedrun)
---
## 1. Doel en relatie met het PRD
🎯 **Doel van dit document:**
Het Functioneel Ontwerp (FO) beschrijft **hoe** de Universele Rapportage functie werkt — dus wat de gebruiker ziet, doet en ervaart. Waar het PRD uitlegt *wat en waarom*, laat het FO zien *hoe dit in de praktijk werkt*.
📘 **Toelichting aan de lezer:**
De Universele Rapportage functie is een fundamenteel andere benadering van verslaglegging in EPD-systemen. In plaats van "zoek het juiste formulier → vul velden in → save", wordt het: "rapporteer wat je wilt vastleggen → AI begrijpt de context → klaar".
**Relatie met PRD v1.2:**
- Core thesis: "Software on Demand" — AI-first workflow design
- User Story: "Als behandelaar wil ik snel rapporteren zonder te zoeken naar formulieren"
- Succes criterium: "Van idee naar opgeslagen verslag in <30 seconden"
**Context binnen AI Speedrun:**
- **Week 2 MVP:** Text input + behandeladvies classificatie + tijdlijn
- **Week 3:** Voice input (Deepgram) + meerdere rapportage types
- **Week 4:** Structured data extraction + dashboard metrics
**Waarom dit anders is dan traditionele EPD's:**
- Traditioneel: 47 verschillende formulieren, elk met specifieke velden
- AI Speedrun: 1 universele functie, AI routeert automatisch naar juiste context
---
## 2. Overzicht van de belangrijkste onderdelen
🎯 **Doel:** kort overzicht van de modules en componenten binnen deze feature.
**Nieuwe componenten (Week 2):**
1. **Floating Action Button** — Universele toegang tot rapportage functie
2. **Rapportage Modal** — Input interface voor verslaglegging
3. **AI Classificatie Engine** — Detecteert type rapportage
4. **Tijdlijn Component** — Chronologische weergave alle rapportages
5. **Context Routing** — Automatisch plaatsen in juiste sectie
**Integratie met bestaande structuur:**
- Client Dashboard — tijdlijn widget + snelkoppeling
- Behandelplan tab — automatisch gevulde behandeladviezen
- Database — nieuwe `reports` tabel
---
## 3. User Stories (Week 2 MVP scope)
🎯 **Doel:** beschrijven wat gebruikers moeten kunnen doen, vanuit hun perspectief.
**User Story Template:**
> Als [rol/gebruiker] wil ik [doel of actie] zodat [reden/waarde].
**MVP Stories:**
| ID | Rol | Doel / Actie | Verwachte waarde | Prioriteit |
|----|------|---------------|------------------|-------------|
| US-20 | Behandelaar | Snel rapporteren vanaf elke plek in dossier | Geen zoeken naar juiste formulier | Hoog |
| US-21 | Behandelaar | AI laten detecteren wat voor type rapportage het is | Geen handmatig categoriseren | Hoog |
| US-22 | Behandelaar | Type handmatig kunnen wijzigen als AI verkeerd zit | Controle over eindresultaat | Hoog |
| US-23 | Behandelaar | Chronologische tijdlijn zien van alle rapportages | Overzicht van historiek | Hoog |
| US-24 | Behandelaar | Behandeladviezen automatisch in juiste sectie zien | Geen dubbel werk | Hoog |
| US-25 | Demo-bezoeker | Concept zien werken in <30 seconden | Begrijpen waarom dit beter is | Kritiek |
| US-26 | Product Owner | Uitbreidbaarheid naar meer types zien | Vertrouwen in schaalbaarheid | Middel |
**Post-MVP Stories (Week 3+):**
| ID | Rol | Doel / Actie | Verwachte waarde | Prioriteit |
|----|------|---------------|------------------|-------------|
| US-27 | Behandelaar | Voice input gebruiken tijdens gesprek | Handen vrij voor aantekeningen | Middel |
| US-28 | Behandelaar | Filteren op rapportage type | Snel specifieke verslagen vinden | Middel |
| US-29 | Behandelaar | Keyboard shortcut gebruiken | Nog sneller toegang | Laag |
| US-30 | Behandelaar | Structured data automatisch extraheren | Geen handmatig invullen velden | Middel |
---
## 4. Functionele werking per onderdeel
🎯 **Doel:** per hoofdonderdeel beschrijven wat de gebruiker kan doen en wat het systeem doet.
### 4.1 Floating Action Button (FAB)
**Doel:**
Universele, altijd beschikbare toegang tot rapportage functie vanuit elk scherm binnen het clientdossier.
**Locatie:**
- Rechterboven in clientdossier interface
- Persistent (blijft zichtbaar bij scrollen)
- Alleen zichtbaar binnen clientdossier context
**Visueel:**
- Icoon: 🎤 (microfoon voor toekomstige voice functie)
- Label: "Rapporteer"
- Styling: Primary brand color, elevated (shadow)
- Hover state: Subtle scale + glow effect
**Gedrag:**
- Klik → opent Rapportage Modal
- Disabled state: Als geen client geselecteerd
- Tooltip (hover): "Snel rapporteren (Cmd+Shift+R)" *[Week 3]*
**States:**
```
Normal: [🎤 Rapporteer]
Hover: [🎤 Rapporteer] (110% scale)
Loading: [⏳ Bezig...]
Disabled: [🎤 Rapporteer] (50% opacity, geen pointer)
```
---
### 4.2 Rapportage Modal (Week 2 MVP)
**Doel:**
Centrale interface voor het invoeren van rapportages met AI-ondersteuning.
**Trigger:**
- Klik op FAB
- Keyboard shortcut (Week 3): `Cmd+Shift+R` / `Ctrl+Shift+R`
**Modal structuur:**
**Header:**
```
┌─────────────────────────────────────────┐
│ 🎤 Nieuwe rapportage voor Emma de Vries│
│ [X] │
└─────────────────────────────────────────┘
```
**Body (lege staat):**
```
┌─────────────────────────────────────────┐
│ │
│ ┌───────────────────────────────────┐ │
│ │ │ │
│ │ Beschrijf wat je wilt │ │
│ │ vastleggen... │ │
│ │ │ │
│ │ (minimaal 20 karakters) │ │
│ │ │ │
│ └───────────────────────────────────┘ │
│ │
│ 💡 Tip: Schrijf gewoon wat je wilt │
│ vastleggen. AI herkent automatisch │
│ of het een behandeladvies is. │
│ │
├─────────────────────────────────────────┤
│ [Analyseer met AI] │
└─────────────────────────────────────────┘
```
**Body (na invoer tekst):**
```
┌─────────────────────────────────────────┐
│ ┌───────────────────────────────────┐ │
│ │ Op basis van het intakegesprek │ │
│ │ advies ik een CGT traject van │ │
│ │ 12 sessies met focus op... │ │
│ │ ▼ │ │
│ └───────────────────────────────────┘ │
│ │
│ Characters: 156 / 5000 │
│ │
├─────────────────────────────────────────┤
│ [Annuleren] [Analyseer] │
└─────────────────────────────────────────┘
```
**Body (AI classificatie):**
```
┌─────────────────────────────────────────┐
│ ┌───────────────────────────────────┐ │
│ │ Op basis van het intakegesprek │ │
│ │ advies ik een CGT traject van │ │
│ │ 12 sessies met focus op... │ │
│ └───────────────────────────────────┘ │
│ │
│ ✓ AI detecteert: 🎯 Behandeladvies │
│ │
│ Type wijzigen: │
│ ┌─────────────────────────────────┐ │
│ │ 🎯 Behandeladvies ▼ │ │
│ └─────────────────────────────────┘ │
│ │
│ └─ 🎯 Behandeladvies │
│ 📝 Vrije notitie │
│ │
├─────────────────────────────────────────┤
│ [Annuleren] [Opslaan] │
└─────────────────────────────────────────┘
```
**Velden:**
- **Text Area**: Multi-line, auto-resize, 5000 character limit
- **Character Counter**: Live update, warning bij >4500 chars
- **Type Dropdown**: Manual override optie (Week 2: 2 types)
- **AI Confidence Badge**: Visual feedback (alleen intern, niet getoond)
**Validation:**
- Minimaal 20 karakters (voorkom "test" spam)
- Maximaal 5000 karakters
- Lege tekst → "Analyseer" knop disabled
- <20 chars → Error: "Te kort voor analyse (min. 20)"
**Button states:**
```
[Analyseer met AI] → Primary, default
[⏳ Analyseren...] → Loading state (1-2 sec)
[✓ Geanalyseerd] → Success state (2 sec)
[Opslaan] → Primary, na classificatie
[💾 Opslaan...] → Loading tijdens save
[✓ Opgeslagen] → Success, auto-close na 1 sec
```
**Edge cases:**
- AI error → Fallback: "Vrije notitie" + melding
- Netwerk timeout → Retry button + melding
- Client context verloren → Error: "Selecteer eerst een cliënt"
---
### 4.3 AI Classificatie (Week 2 MVP)
**Doel:**
Automatisch herkennen of een rapportage een behandeladvies is of een vrije notitie.
**Technische flow:**
```
User input
Validate (>20 chars)
Send to Claude API
Parse JSON response
Show classification + confidence
User confirms/overrides
Save to database
```
**AI Prompt (approximately):**
```typescript
const CLASSIFICATION_PROMPT = `
Je bent een classificatie-assistent voor een GGZ EPD-systeem.
Classificeer de volgende rapportage als één van deze types:
**Behandeladvies:**
- Bevat een concreet behandelplan of voorstel
- Noemt doelen, interventies, aanpak
- Woorden zoals: "advies", "plan", "traject", "sessies", "behandeling"
- Voorbeelden: "Ik stel voor CGT, 12 sessies", "Behandelplan: ..."
**Vrije notitie:**
- Alles wat niet duidelijk een behandeladvies is
- Algemene observaties, opmerkingen, aantekeningen
- Geen concreet plan of voorstel
RAPPORTAGE:
"""
${userInput}
"""
Return ALLEEN dit JSON format, niets anders:
{
"type": "behandeladvies" | "vrije_notitie",
"confidence": 0.0 - 1.0,
"reasoning": "Korte uitleg waarom (optioneel)"
}
`;
```
**Response handling:**
```typescript
type ClassificationResult = {
type: 'behandeladvies' | 'vrije_notitie';
confidence: number; // 0.0 - 1.0
reasoning?: string;
}
// Confidence thresholds
if (confidence >= 0.85) {
// High confidence - auto-suggest
showClassification(result.type);
} else if (confidence >= 0.60) {
// Medium confidence - show with warning
showClassification(result.type, "AI is niet zeker, controleer type");
} else {
// Low confidence - fallback
showClassification('vrije_notitie', "AI kon type niet bepalen");
}
```
**Fallback scenario's:**
- API timeout → Default: "vrije_notitie"
- Parse error → Default: "vrije_notitie"
- Network error → Retry optie + fallback
**Performance target:**
- Response time: <2 seconden (95th percentile)
- Accuracy target: >85% correct classifications
---
### 4.4 Tijdlijn Component
**Doel:**
Chronologische weergave van alle rapportages voor een cliënt, met snelle toegang tot details.
**Locatie:**
- Tab in clientdossier: "Tijdlijn"
- Widget op dashboard (laatste 3 items)
**Structuur:**
**Header:**
```
┌─────────────────────────────────────────┐
│ 📋 Tijdlijn │
│ │
│ Filter: [Alle types ▼] [Zoeken 🔍] │
└─────────────────────────────────────────┘
```
**Tijdlijn items:**
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
23 nov 2024 14:30
🎯 Behandeladvies
"Op basis van het intakegesprek advies
ik een CGT traject van 12 sessies met
focus op slaapproblematiek en..."
Door: Dr. van Dam
[Bekijk volledig] [Bewerk] [...]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
22 nov 2024 10:15
📝 Vrije notitie
"Telefonisch contact met cliënt.
Afspraak verzet naar donderdag..."
Door: Dr. van Dam
[Bekijk volledig] [Bewerk] [...]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
**Item componenten:**
- **Timestamp**: Datum + tijd (relatief: "2 uur geleden")
- **Type badge**: Icoon + label
- **Preview**: Eerste 120 karakters + "..."
- **Metadata**: Auteur (Week 3: + versie nummer)
- **Actions**: Bekijk, Bewerk, Menu (...)
**States:**
```
Normal: Standaard weergave
Hover: Subtle highlight + cursor pointer
Loading: Skeleton placeholders
Empty: "Nog geen rapportages voor deze cliënt"
```
**Interacties:**
- Klik op item → Open detail view (modal of side panel)
- Klik "Bewerk" → Open in rapportage modal (edit mode)
- Menu (...) → Verwijderen (met confirmatie)
**Lazy loading:**
- Toon eerste 10 items
- "Meer laden" knop onderaan
- Infinite scroll optie (Week 3)
---
### 4.5 Context Routing (automatische plaatsing)
**Doel:**
Rapportages automatisch op de juiste plek in het dossier tonen, naast de chronologische tijdlijn.
**Week 2 scope:**
- Behandeladviezen verschijnen automatisch in "Behandelplan" tab
- Vrije notities blijven alleen in tijdlijn
**Behandelplan tab integratie:**
```
┌─────────────────────────────────────────┐
│ 🎯 Behandelplan │
│ │
│ Laatste advies: 23 nov 2024 14:30 │
│ │
│ ┌─────────────────────────────────┐ │
│ │ CGT traject, 12 sessies │ │
│ │ Focus: slaapproblematiek │ │
│ │ │ │
│ │ Doelen: │ │
│ │ - Verbeteren slaapkwaliteit │ │
│ │ - Verminderen ruminatie │ │
│ │ │ │
│ │ [Bewerk] [Nieuwe versie] │ │
│ └─────────────────────────────────┘ │
│ │
│ Eerdere adviezen: │
│ - 20 nov 2024 (v1.0) [Bekijk] │
└─────────────────────────────────────────┘
```
**Routing logica:**
```typescript
function routeReport(report: Report) {
// Week 2: Simple routing
if (report.type === 'behandeladvies') {
// Show in both timeline AND behandelplan tab
saveToTimeline(report);
linkToBehandelplan(report);
} else {
// Only in timeline
saveToTimeline(report);
}
// Week 3+: More types
// 'intake' → Intake tab
// 'voortgang' → Voortgang tab
// 'crisis' → Crisis log + notification
// etc.
}
```
**Versioning (Week 3):**
- Behandeladviezen krijgen versienummer (v1.0, v1.1, v2.0)
- Nieuwe rapportage = nieuwe versie of wijziging bestaande?
- User kan kiezen: "Nieuwe versie" vs "Bestaande bijwerken"
---
## 5. UI-overzicht (visuele structuur)
🎯 **Doel:** eenvoudig inzicht geven in de globale schermopbouw.
**Clientdossier met Universele Rapportage:**
```
┌──────────────────────────────────────────────────────────┐
│ Logo Emma de Vries (34j, F) [Zoeken] [User ▼] │
├──────────────────────────────────────────────────────────┤
│ │
│ ┌────────────┐ ┌─────────────────────────────────┐ │
│ │ Dashboard │ │ │ │
│ │ Intake │ │ Client Dashboard │ │
│ │ Diagnose │ │ │ │
│ │ Behandel │ │ [Laatste activiteit widgets] │ │
│ │ Tijdlijn │ │ │ │
│ │ │ │ │ │
│ │ │ │ │ │
│ │ │ │ │ │
│ └────────────┘ └─────────────────────────────────┘ │
│ │
│ ┌──────────────────┐ │
│ │ 🎤 Rapporteer │ ←FAB │
│ └──────────────────┘ │
└──────────────────────────────────────────────────────────┘
```
**Rapportage Modal (overlay):**
```
┌────────────────────────────────────────┐
│ 🎤 Nieuwe rapportage voor Emma [X]│
├────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────┐ │
│ │ [User input text area] │ │
│ │ │ │
│ └──────────────────────────────────┘ │
│ │
│ ✓ AI detecteert: 🎯 Behandeladvies │
│ │
│ Type: [Behandeladvies ▼] │
│ │
├────────────────────────────────────────┤
│ [Annuleren] [Opslaan] │
└────────────────────────────────────────┘
```
**Tijdlijn tab:**
```
┌──────────────────────────────────────────────────────────┐
│ 📋 Tijdlijn [Alle types ▼] [Zoeken 🔍] │
├──────────────────────────────────────────────────────────┤
│ │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ 23 nov 2024 14:30 │
│ 🎯 Behandeladvies │
│ │
│ "Op basis van intakegesprek advies ik CGT..." │
│ │
│ Door: Dr. van Dam │
│ [Bekijk volledig] [Bewerk] [...] │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ │
│ 22 nov 2024 10:15 │
│ 📝 Vrije notitie │
│ ... │
│ │
└──────────────────────────────────────────────────────────┘
```
---
## 6. Interacties met AI (functionele beschrijving)
🎯 **Doel:** uitleggen waar AI in de flow voorkomt en wat de gebruiker ziet of verwacht.
| Locatie | AI-actie | Trigger | Input | Output | Response tijd |
|---------|----------|---------|-------|--------|---------------|
| Rapportage Modal | Classificatie | Klik "Analyseer" | User text (20-5000 chars) | Type + confidence | <2 sec |
| Behandelplan (Week 3) | Extractie | Auto na save | Behandeladvies text | SMART doelen, interventies | <3 sec |
| Tijdlijn (Week 3) | Samenvatting | Klik "Samenvatten" | Lang verslag | Bullets, highlights | <2 sec |
**Week 2 MVP: Alleen classificatie**
**Prompt structure:**
```typescript
System: "Je bent classificatie-assistent voor GGZ EPD"
User: "Classificeer: [user_text]"
Expected response: { type, confidence, reasoning }
```
**Error handling:**
- Timeout (>5 sec) → Retry once → Fallback to "vrije_notitie"
- Invalid JSON → Parse error → Fallback to "vrije_notitie"
- Rate limit → Queue request → Show "Even geduld..."
**User feedback:**
```
[Analyseren...] ← Loading (spinner)
[✓ Geanalyseerd] ← Success (1 sec)
[⚠️ Opnieuw proberen] ← Error (retry button)
```
---
## 7. Database Schema (Week 2 MVP)
🎯 **Doel:** Gestructureerde opslag van rapportages met uitbreidbaarheid.
**Tabel: `reports`**
```sql
CREATE TABLE reports (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
client_id UUID NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
-- Content
type VARCHAR(50) NOT NULL, -- 'behandeladvies', 'vrije_notitie'
content TEXT NOT NULL, -- Raw user input
-- AI metadata
ai_confidence DECIMAL(3,2), -- 0.00 - 1.00
ai_reasoning TEXT, -- Optional AI explanation
-- Structured data (Week 3+)
structured_data JSONB, -- Extracted entities, dates, etc.
-- Metadata
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID NOT NULL REFERENCES users(id),
updated_at TIMESTAMPTZ,
updated_by UUID REFERENCES users(id),
-- Versioning (Week 3+)
version VARCHAR(10), -- e.g., "v1.0", "v2.1"
parent_report_id UUID REFERENCES reports(id), -- For versioning
-- Audio (Week 3+)
audio_url TEXT, -- Supabase Storage URL
audio_duration_seconds INT,
-- Soft delete
deleted_at TIMESTAMPTZ,
-- Indexes
INDEX idx_reports_client (client_id),
INDEX idx_reports_type (type),
INDEX idx_reports_created (created_at DESC)
);
```
**Type values (Week 2):**
- `behandeladvies`: Treatment plan/advice
- `vrije_notitie`: Free-form note
**Type values (Week 3+):**
- `intake`: Initial intake report
- `voortgang`: Progress report
- `crisis`: Crisis/incident report
- `contact`: Contact moment (call, email)
- `medicatie`: Medication changes
- `mdo`: Multidisciplinary consultation
**Example data:**
```json
{
"id": "abc-123",
"client_id": "client-456",
"type": "behandeladvies",
"content": "Op basis van intakegesprek advies ik CGT traject...",
"ai_confidence": 0.92,
"ai_reasoning": "Bevat woorden: advies, traject, sessies",
"structured_data": null, // Week 3+
"created_at": "2024-11-23T14:30:00Z",
"created_by": "user-789"
}
```
---
## 8. Gebruikersrollen en rechten
🎯 **Doel:** beschrijven welke rollen toegang hebben tot welke onderdelen.
| Rol | Toegang | Acties | Beperkingen |
|-----|---------|--------|-------------|
| **Behandelaar** | Eigen cliënten | Aanmaken, lezen, bewerken, verwijderen rapportages | Alleen eigen rapportages bewerken |
| **Manager** | Alle cliënten (read-only) | Lezen tijdlijnen | Geen wijzigingen |
| **Demo User** | Demo cliënten | Volledige toegang | Fictieve data only |
**Permissions check:**
```typescript
canCreateReport(user, client) {
return user.clients.includes(client.id) || user.role === 'admin';
}
canEditReport(user, report) {
return report.created_by === user.id || user.role === 'admin';
}
canDeleteReport(user, report) {
return report.created_by === user.id || user.role === 'admin';
}
```
---
## 9. Flows & Scenario's
🎯 **Doel:** Concrete gebruiksscenario's uitwerken.
### 9.1 Happy Flow: Behandeladvies rapporteren
**Context:** Behandelaar heeft net intakegesprek gehad met nieuwe cliënt Emma (34j).
**Stappen:**
1. Open clientdossier Emma de Vries
2. Klik floating button "🎤 Rapporteer" (rechtsonder)
3. Modal opent met focus op text area
4. Typ: *"Op basis van het intakegesprek van vandaag advies ik een CGT traject van 12 sessies. Focus op slaapproblematiek en verminderen van ruminatie. Start met psycho-educatie over depressie en slaaphygiëne. Evaluatie na 6 sessies. Bij onvoldoende verbetering overleg met psychiater voor eventuele medicatie."*
5. Klik "Analyseer met AI"
6. Spinner 1-2 seconden
7. AI toont: "✓ AI detecteert: 🎯 Behandeladvies (92% zeker)"
8. Dropdown toont: "🎯 Behandeladvies" (pre-selected)
9. Klik "Opslaan"
10. Success melding: "✓ Opgeslagen"
11. Modal sluit automatisch na 1 sec
12. Rapportage verschijnt:
- In tijdlijn (bovenaan)
- In "Behandelplan" tab
13. Behandelaar ziet bevestiging toast: "Behandeladvies opgeslagen"
**Tijdsduur:** ~25 seconden (inclusief typen)
---
### 9.2 Alternative Flow: AI classificeert verkeerd
**Context:** Behandelaar schrijft verslag, maar AI herkent verkeerd type.
**Stappen:**
1. Open rapportage modal
2. Typ: *"Kort telefoontje gehad met Emma. Ze kan volgende week niet, afspraak verzet naar donderdag 15:00. Ze klonk opgeruimd."*
3. Klik "Analyseer"
4. AI toont: "✓ AI detecteert: 🎯 Behandeladvies (68% zeker)"
- (AI ziet "afspraak" en "opgeruimd" als mogelijk behandelcontext)
5. **Gebruiker klikt dropdown**
6. Kiest: "📝 Vrije notitie"
7. Klik "Opslaan"
8. Verslag opgeslagen als vrije notitie
9. **Leermoment:** AI wordt niet getraind (out of scope), maar gebruiker had controle
**Tijdsduur:** ~30 seconden
---
### 9.3 Error Flow: Netwerk timeout
**Context:** Slechte internetverbinding tijdens classificatie.
**Stappen:**
1. Typ rapportage
2. Klik "Analyseer"
3. Spinner > 5 seconden
4. Timeout error
5. Melding: "⚠️ AI niet bereikbaar. Probeer opnieuw of kies handmatig een type."
6. Knoppen:
- [Opnieuw proberen] ← Retry
- [Handmatig kiezen] ← Skip AI, direct dropdown
7. Gebruiker kiest "Handmatig kiezen"
8. Dropdown actief, kiest type
9. Opslaan werkt normaal
**Fallback:** Rapportage wordt opgeslagen zonder AI-metadata, maar blijft functioneel.
---
### 9.4 Demo Scenario (LinkedIn video)
**Context:** 30-seconden demo voor LinkedIn post.
**Script:**
```
[Scherm: Client dossier open]
Voiceover: "Traditionele EPD's hebben 47 formulieren."
[Klik Rapporteer button]
Voiceover: "Wij hebben 1 knop."
[Typ snel behandeladvies]
Voiceover: "Je typt wat je denkt."
[Klik Analyseer]
Voiceover: "AI begrijpt wat het is."
[Klik Opslaan]
Voiceover: "En zet het automatisch op de juiste plek."
[Toon tijdlijn + behandelplan tab]
Voiceover: "25 seconden. Klaar."
[Fade to logo]
Text: "AI Speedrun EPD - Software on Demand"
```
**Belangrijke visuele elementen:**
- Smooth animaties
- Duidelijke button clicks
- AI classificatie badge (92%)
- Dual placement (tijdlijn + behandelplan)
---
## 10. Technische constraints & dependencies
🎯 **Doel:** Technische randvoorwaarden en afhankelijkheden.
**API Dependencies:**
- **Claude 3.5 Sonnet** (Anthropic API)
- Endpoint: `/v1/messages`
- Model: `claude-sonnet-4-20250514`
- Rate limit: 50 requests/minute (tier 1)
- Fallback: Queue + retry
**Database:**
- **Supabase PostgreSQL**
- Row Level Security (RLS) enabled
- Real-time subscriptions (Week 3+)
**Frontend:**
- **Next.js 15** (App Router)
- **React 19** (Server Components waar mogelijk)
- **shadcn/ui** components
- **TailwindCSS** styling
**Performance targets:**
- Modal open: <100ms
- AI classification: <2 sec (p95)
- Database save: <500ms
- Timeline render: <200ms (10 items)
**Browser support:**
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Mobile: iOS Safari 14+, Chrome Android
---
## 11. Privacy & Security (AVG compliance)
🎯 **Doel:** Waarborgen van privacy en beveiliging.
**Data opslag:**
- Rapportages bevatten potentieel gevoelige medische informatie
- Encryptie at rest (Supabase default)
- Encryptie in transit (HTTPS/TLS 1.3)
**API communicatie:**
- Claude API: Data wordt NIET gebruikt voor training
- Anthropic heeft SOC 2 Type II certificering
- Data residency: EU servers waar mogelijk
**Toegangscontrole:**
- Row Level Security (RLS) op client_id
- User kan alleen eigen cliënten zien/bewerken
- Audit log voor alle wijzigingen (Week 3+)
**Soft delete:**
- Rapportages krijgen `deleted_at` timestamp
- Niet permanent verwijderd (herstel mogelijk)
- Permanent purge na 30 dagen (Week 4)
**GDPR rechten:**
- Recht op inzage: Tijdlijn export (Week 3+)
- Recht op verwijdering: Soft delete functie
- Recht op dataportabiliteit: JSON export (Week 4)
---
## 12. Testing & Acceptance Criteria
🎯 **Doel:** Definiëren wanneer de feature "klaar" is.
**Functional Tests:**
- [ ] FAB zichtbaar in alle clientdossier paginas
- [ ] Modal opent/sluit correct
- [ ] Text area accepteert 20-5000 karakters
- [ ] Validation errors tonen bij <20 chars
- [ ] AI classificatie werkt in >85% van testcases
- [ ] Dropdown manual override functioneert
- [ ] Save functie slaat op in database
- [ ] Tijdlijn toont nieuwe items direct
- [ ] Behandeladviezen verschijnen in Behandelplan tab
- [ ] Vrije notities alleen in tijdlijn
**Performance Tests:**
- [ ] Modal open <100ms
- [ ] AI response <2 sec (p95)
- [ ] Save operation <500ms
- [ ] Timeline render <200ms (10 items)
**Edge Cases:**
- [ ] Netwerk timeout handling
- [ ] AI parse error handling
- [ ] Concurrent edits (multiple tabs)
- [ ] Very long text (4900 chars)
- [ ] Special characters (emoji, unicode)
**Accessibility:**
- [ ] Keyboard navigatie werkt
- [ ] Screen reader compatible
- [ ] Focus states duidelijk
- [ ] ARIA labels correct
**Cross-browser:**
- [ ] Chrome/Edge latest
- [ ] Firefox latest
- [ ] Safari 14+
- [ ] Mobile Chrome/Safari
**Demo Readiness:**
- [ ] 30-sec demo scenario werkt smooth
- [ ] No bugs in happy flow
- [ ] Visual polish (animaties, spacing)
- [ ] Recording-ready UI
---
## 13. Roadmap & Uitbreidingen
🎯 **Doel:** Toekomstige iteraties en uitbreidmogelijkheden.
### Week 3 (Voice + Types)
- 🎤 Deepgram voice input integration
- 📋 Meer rapportage types (intake, voortgang, crisis, contact)
- 🔍 Filter/zoek functionaliteit in tijdlijn
- ⌨️ Keyboard shortcut (Cmd+Shift+R)
- 📊 Structured data extraction (DSM codes, medicatie)
### Week 4 (Polish + Analytics)
- ✨ Rich editor formatting in rapportages
- 📈 Dashboard widgets (rapportage stats)
- 🔔 Notificaties bij crisis rapportages
- 📄 PDF export van rapportages
- 🎬 Marketing video + LinkedIn posts
### Post-MVP (Future)
- 🧠 AI leren van correcties (feedback loop)
- 🔗 Cross-client insights (anonymized patterns)
- 📱 Mobile app (React Native)
- 🌐 Multi-language support (Engels)
- 🔐 Advanced permissions (team-based access)
- 📊 BI dashboard voor managers
- 🔄 Integraties (Zorgdomein, Ggz Standaarden)
---
## 14. Bijlagen & Referenties
🎯 **Doel:** linken naar de overige documenten binnen Mission Control.
**Interne documenten:**
- [PRD v1.2](./prd-mini-ecd-v1_2.md) - Product Requirements Document
- [TO v1.2](./to-mini-ecd-v1_2.md) - Technisch Ontwerp
- [FO v2.0](./fo-mini-ecd-v2.md) - Functioneel Ontwerp (basis applicatie)
- [FO Live Transcriptie](./fo-live-transcriptie-v1.md) - Voice input (Week 3)
- [UX Stylesheet](./ux-stylesheet.md) - Design system
- [Bouwplan v1.1](./bouwplan-ai-speedrun-v1.md) - Development roadmap
- [API Access](./api-access-mini-ecd.md) - Credentials en setup
**Externe referenties:**
- [Anthropic Claude API](https://docs.anthropic.com/claude/reference)
- [Supabase Docs](https://supabase.com/docs)
- [Next.js 15 Docs](https://nextjs.org/docs)
- [shadcn/ui Components](https://ui.shadcn.com/)
**Demo assets:**
- LinkedIn post templates
- 30-second demo script
- Test rapportages (NL samples)
- Figma wireframes (optional)
---
**Versiehistorie:**
| Versie | Datum | Auteur | Wijziging |
|--------|-------|--------|-----------|
| v1.0 | 23-11-2024 | Colin van der Heijden | Initiële versie - Week 2 MVP scope |
---
**Einde Functioneel Ontwerp - Universele Rapportage Functie**

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,93 @@
# Universele Rapportage — Split Timeline Composer
Context: gesprek met behandelaren/psychiaters toonde dat rapportages schrijven en overzicht houden tegelijk nodig is. Deze mock beschrijft een layout waarbij timeline en composer gelijktijdig zichtbaar blijven.
## UX Principes
1. **Context behouden** timeline altijd zichtbaar; geen modal die context blokkeert.
2. **Snelle wissel** klik op entry synchroniseert composer en toont referenties.
3. **Mobiele pariteit** tabs/drawer zodat schrijven en lezen in één flow blijft.
4. **State veilig** concepten autosaven; switching verliest content niet.
## Desktop Mock
```
┌───────────────────────────────┬───────────────────────────────┐
│ Timeline kolom (40%) │ Composer kolom (60%) │
│ ┌────────── Rapportage filter │ ┌──────────── Nieuwe rapportage│
│ │ Zoeken [🔍___________] │ │ Emma de Vries • Vrije notitie│
│ │ Type [• Alle ▼] │ │ --------------------------- │
│ └──────────────────────────── │ │ [textarea................] │
│ ┌── Entry ─────────────────── │ │ AI badge + dropdown │
│ │ 09:12 • Sophie (AI 92%) │ │ Rapportagetype [▼] │
│ │ Behandeladvies snippet │ │ Speech recorder + attach │
│ └──────────────────────────── │ │ Footer: Opslaan • Analyseer │
│ Scrollbare lijst met badges │ │ Sticky action bar │
└───────────────────────────────┴───────────────────────────────┘
```
- Clicking an entry previews full text in a slide-out panel or inline expansion.
- Filters (type, author, date) pin to top of timeline.
- Composer sticky footer shows save status + autosave timestamp.
## Mobile Mock
```
┌──────────────┐
│ Tabs │
│ [Timeline] [Rapportage+] │
├──────────────┤
│ Timeline tab │
│ cards stack │
└────┬─────────┘
▼ swipe up opens composer drawer
┌──────────────┐
│ Rapportage │
│ textarea │
│ AI panel │
│ Save / AI btn│
└──────────────┘
```
- Drawer covers 75% height so top timeline remains slightly visible.
- Swipe down or "Terug naar timeline" button closes drawer without losing draft.
## Interacties
- **Select entry → composer reference**: clicking "Referentie toevoegen" inserts a quote block with metadata (author, time).
- **Autosave badge**: top-right of composer shows "Automatisch opgeslagen 13:42".
- **AI context chips**: timeline entries show AI confidence badges; clicking them filters timeline by type.
## Open vragen
1. Hoeveel entries tonen we per pagina? (voorstel: 50 + virtuele scroll)
2. Benodigd? inline edit van bestaande rapportages? (nu read-only)
3. Notificatie bij gelijktijdig schrijven door meerdere behandelaren?
Deze mock dient als richting voor UI implementatie; visuele uitwerking kan in Figma plaatsvinden met shadcn/ui componenten.
## Actieplan
1. **UX refinement**
- Bouw Figma-variant voor desktop split view en mobiele drawer.
- Valideer met 2 behandelaren of de voorgestelde flows voldoen.
2. **Component architectuur**
- Refactor rapportage route naar layout met `TimelinePane` + `ComposerPane`.
- Introduceer context/state voor draft + selectie (bijv. `useReportDraft`).
3. **Timeline functionaliteit**
- Implement filters (zoek, type, auteur, datum).
- Voeg inline preview/slide-out voor entries toe.
- Onderzoek virtualized list (React Virtual) voor >50 items.
4. **Composer upgrades**
- Sticky footer met status + autosave indicator.
- "Referentie toevoegen" waarmee geselecteerde entry als quote block wordt ingevoegd.
- Drawer/tab ervaring op mobiel.
5. **State & autosave**
- Drafts opslaan in localStorage of Supabase temp table.
- Toon laatste autosave + unsaved changes waarschuwing bij navigeren.
6. **Testing & rollout**
- Schrijf QA checklist (desktop/mobile).
- Monitor gebruikersfeedback tijdens pilot, focus op contextswitch-snelheid.

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB