# 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 | ✅ Done | 4 | 8 SP | | E1 | Command Center | Input, voice, context bar | ✅ Done | 5 | 13 SP | | E2 | Intent Classification | Local + AI fallback + wiring | ⏳ In Progress | 5 | 12 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: 28 stories, 70 story points (31 SP done, 39 SP remaining)** **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; // Actions setActivePatient: (patient: Patient | null) => void; openBlock: (type: BlockType, prefill?: Record) => 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 | | E2.S5 | Input → Block wiring | CommandInput submit → API → openBlock | ⏳ | E2.S4 | 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, ], }; // E2.S5: Input → Block wiring // In CommandInput.handleSubmit: const handleSubmit = async () => { const response = await fetch('/api/intent/classify', { method: 'POST', body: JSON.stringify({ input: inputValue }), }); const { intent, confidence, entities } = await response.json(); if (intent !== 'unknown' && confidence >= 0.5) { openBlock(intent, entities); // Open juiste block met prefill } else { // Toon FallbackPicker (E4.S4) } }; ``` --- ### 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 | | v1.1 | 23-12-2024 | Claude | E0 + E1 voltooid (21 SP) | | v1.2 | 23-12-2024 | Claude | E2.S1 + E2.S2 voltooid (27 SP) | | v1.3 | 23-12-2024 | Claude | E2.S3 AI fallback voltooid (29 SP) | | v1.4 | 23-12-2024 | Claude | E2.S1-S4 voltooid (31 SP) | | v1.5 | 24-12-2024 | Claude | E2.S5 toegevoegd: Input → Block wiring (+2 SP) |