# πŸ“„ 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 => { // 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; // Input state inputValue: string; isListening: boolean; transcript: string; // Actions processInput: (text: string) => Promise; 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 |