# 🧩 Functioneel Ontwerp (FO) – Agenda Module **Projectnaam:** Mini-EPD Agenda Module **Versie:** v1.1 **Datum:** 02-12-2024 **Auteur:** Colin --- ## 1. Doel en relatie met het PRD 🎯 **Doel van dit document:** Dit Functioneel Ontwerp beschrijft **hoe** de Agenda Module uit het PRD functioneel zal werken β€” wat de behandelaar ziet, doet en ervaart. Waar het PRD uitlegt *wat en waarom*, laat dit FO zien *hoe dit in de praktijk werkt*. πŸ“˜ **Relatie met PRD:** - PRD-referentie: `prd-agenda-module-v1_0.md` - Dit FO is de functionele uitwerking van PRD secties 3 (Kernfunctionaliteiten) en 4 (Gebruikersflows) - Scope is afgebakend op MVP-features; nice-to-have items zijn apart gemarkeerd **Kernprincipe:** > De agenda is het kloppend hart van het EPD. Zonder agenda geen dagelijkse workflow, zonder workflow geen AI-integratie in de praktijk. --- ## 2. Overzicht van de belangrijkste onderdelen 🎯 **Doel:** Kort overzicht van schermen en componenten binnen de Agenda Module. ### MVP Onderdelen (Must-Have) | # | Onderdeel | Beschrijving | Prioriteit | |---|-----------|--------------|------------| | 1 | **Kalender View** | Hoofd agenda-weergave met dag/week/werkdagen toggle | πŸ”΄ Kritiek | | 2 | **Afspraak Modal** | Formulier voor maken/bewerken afspraken | πŸ”΄ Kritiek | | 3 | **Patient Zoeken** | Autocomplete voor patient selectie | πŸ”΄ Kritiek | | 4 | **Conflict Dialog** | Waarschuwing bij dubbele boekingen | πŸ”΄ Kritiek | | 5 | **Afspraak Detail Popup** | Quick-view met acties (verslag maken, bewerken) | πŸ”΄ Kritiek | | 6 | **Toolbar** | Datum navigatie, view switcher | 🟑 Hoog | ### Stretch/Nice-to-Have Onderdelen | # | Onderdeel | Beschrijving | Prioriteit | |---|-----------|--------------|------------| | 7 | Mini Kalender Sidebar | Maandoverzicht met navigatie | 🟒 Stretch | | 8 | Recente PatiΓ«nten | Quick-select laatste 5 patiΓ«nten | 🟒 Stretch | | 9 | Kleurcodering | Visuele type-indicator (intake/behandeling/follow-up) | 🟒 Stretch | ### Niet in Scope (Post-MVP) | Onderdeel | Reden exclusie | |-----------|----------------| | Multi-practitioner view | Te complex voor MVP, single-user focus | | Recurring appointments | Beperkte demo-waarde, hoge complexiteit | | Email/SMS notificaties | Aparte infrastructuur nodig | | Wachtlijstbeheer | Buiten scope AI Speedrun | | Video call integratie | Geen core EPD functionaliteit | --- ## 3. User Stories 🎯 **Doel:** Beschrijven wat gebruikers moeten kunnen doen, vanuit hun perspectief. ### MVP User Stories | ID | Als... | Wil ik... | Zodat... | Prio | |----|--------|-----------|----------|------| | **AG-US01** | Behandelaar | Mijn agenda bekijken in dag/week view | Ik weet welke patiΓ«nten vandaag/deze week komen | πŸ”΄ | | **AG-US02** | Behandelaar | Snel een nieuwe afspraak maken door op een tijdslot te klikken | Ik direct kan inplannen tijdens telefoongesprek | πŸ”΄ | | **AG-US03** | Behandelaar | Een patient zoeken tijdens afspraak maken | De afspraak gekoppeld is aan het juiste dossier | πŸ”΄ | | **AG-US04** | Behandelaar | Een waarschuwing zien bij dubbele boeking | Ik niet per ongeluk overlap creΓ«er | πŸ”΄ | | **AG-US05** | Behandelaar | De waarschuwing kunnen overrulen | Ik flexibel kan plannen wanneer nodig | πŸ”΄ | | **AG-US06** | Behandelaar | Een afspraak verzetten via drag-drop | Wijzigingen snel zijn doorgevoerd | 🟑 | | **AG-US07** | Behandelaar | Vanuit een afspraak direct een verslag starten | AI-verslaglegging naadloos in mijn workflow past | πŸ”΄ | | **AG-US08** | Behandelaar | Op een afspraak klikken om details te zien | Ik snel patient info kan checken | 🟑 | | **AG-US09** | Behandelaar | Een afspraak annuleren | Geannuleerde afspraken geregistreerd blijven | 🟑 | ### Stretch User Stories | ID | Als... | Wil ik... | Zodat... | Prio | |----|--------|-----------|----------|------| | **AG-US10** | Behandelaar | Recente patiΓ«nten snel selecteren | Repeat-afspraken extra snel gaan | 🟒 | | **AG-US11** | Behandelaar | Afspraken zien met kleurcodering per type | Ik visueel onderscheid kan maken | 🟒 | | **AG-US12** | Behandelaar | Een mini-kalender in de sidebar zien | Ik snel naar andere weken kan navigeren | 🟒 | --- ## 4. Functionele werking per onderdeel 🎯 **Doel:** Per component beschrijven wat de gebruiker kan doen en wat het systeem doet. --- ### 4.1 Kalender View (MVP) **Locatie:** `/epd/agenda` **Context:** Level 1 navigatie (behandelaar-breed, niet patient-specifiek) #### Functioneel gedrag **Views beschikbaar:** | View | Beschrijving | Standaard | |------|--------------|-----------| | **Dag** | Enkele dag, uren 08:00-18:00 verticaal | Nee | | **Week** | Ma-Zo, 7 kolommen, uren verticaal | Ja βœ“ | | **Werkdagen** | Ma-Vr, 5 kolommen | Nee | **Weergave-elementen:** - **Tijdslots:** 30 minuten interval, visueel onderscheiden met subtle gridlijnen - **Afspraak blokken:** Patient naam (bold), tijd, type indicator (kleur dot) - **Huidige tijd indicator:** Rode lijn op "nu" moment + auto-scroll naar nu bij laden - **Grijze zones:** Tijden buiten werktijden (vΓ³Γ³r 08:00, na 18:00) licht gearceerd - **Vandaag markering:** Huidige dag kolom heeft licht gekleurde achtergrond **Visuele details kalender grid:** ``` Ma 2 Di 3 Wo 4 (vandaag) Do 5 ───────────────────────────────────────────────────── 08:00 β”‚ β”‚ β”‚ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β”‚ β”‚ β”‚ β”‚ β”‚ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β”‚ β”‚ 09:00 β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β”‚ β”‚ β”‚ β”‚Jan de Vβ”‚ β”‚ β”‚ ░─────────────│────────────│ ← Rode "nu" lijn 10:00 β”‚ β”‚Intake β”‚ β”‚ β”‚ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β”‚ β”‚Maria J β”‚ β”‚ 11:00 β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β”‚ β”‚Behandelβ”‚ β”‚ β”‚ β”‚ β”‚Piet K. β”‚ β”‚ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ ``` _Vandaag (wo 4) heeft lichte achtergrondkleur (β–‘)_ **Interacties:** | Actie | Resultaat | Feedback | |-------|-----------|----------| | Klik op leeg tijdslot | Opent Afspraak Modal met datum/tijd pre-filled | Slot krijgt kort highlight | | Klik op afspraak blok | Opent Afspraak Detail Popup | Blok krijgt ring focus | | Drag afspraak naar ander slot | Opent Confirm Dialog voor verzetten | Ghost preview op nieuwe locatie | | Hover op afspraak | Cursor pointer + lichte lift | 100ms delay | | Hover op leeg slot | Subtle "+" icon verschijnt in slot | Fade-in | | Double-click leeg slot | Direct modal openen (sneller dan single click) | β€” | **States:** | State | Weergave | |-------|----------| | Laden | Skeleton loading met shimmer effect | | Leeg (week/dag) | Illustratie + "Geen afspraken" + prominent CTA | | Leeg (eerste gebruik) | Onboarding card met tips | | Gevuld | Afspraak blokken in grid | | Fout | Inline error met retry button | | Offline | Banner: "Je bent offline. Wijzigingen worden gesynchroniseerd." | **Scroll & Navigatie:** - Bij pagina laden: auto-scroll naar huidige tijd (met 1 uur marge boven) - Sticky uur-labels aan linkerkant bij horizontaal scrollen (mobile) - Sticky dag-headers bij verticaal scrollen --- ### 4.2 Afspraak Modal (MVP) **Trigger:** Klik op leeg tijdslot OF "Nieuwe afspraak" button OF bewerk-actie #### Formulier velden | Veld | Type | Verplicht | Pre-fill | Validatie | |------|------|-----------|----------|-----------| | **Patient** | Autocomplete search | βœ“ Ja | Nee (of recent als repeat) | Moet bestaande patient zijn | | **Datum** | Date picker | βœ“ Ja | Geklikte datum of vandaag | Warn bij verleden | | **Starttijd** | Time select (08:00-18:00) | βœ“ Ja | Geklikte tijd of volgende vrije | 30 min intervals | | **Duur** | Select dropdown | βœ“ Ja | Automatisch obv type | 15/30/45/60/90/120 min | | **Type** | Radio buttons | βœ“ Ja | Slim obv patient historie | Intake/Behandeling/Follow-up | | **Notities** | Textarea (collapsed) | Nee | Leeg | Max 500 karakters | #### Smart Defaults **Type β†’ Duur koppeling (automatisch bij wijziging type):** | Type geselecteerd | Duur wordt | |-------------------|------------| | Intake | 60 min | | Behandeling | 45 min | | Follow-up | 30 min | _User kan duur nog steeds handmatig wijzigen na auto-fill_ **Type suggestie obv patient historie:** | Patient situatie | Voorgeselecteerd type | |------------------|----------------------| | Nieuwe patient (geen afspraken) | Intake | | Had intake, geen behandeling | Behandeling | | Had 3+ behandelingen | Follow-up | | Laatste afspraak > 6 maanden | Intake (herintake) | #### Formulier Layout (Progressive Disclosure) ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Nieuwe afspraak βœ• β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ Patient * β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ πŸ” Zoek patient... β”‚ β”‚ ← Auto-focus hier β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ πŸ“… Do 5 dec β”‚ β”‚ πŸ• 14:00 β–Ό β”‚ β”‚ ← Compact: datum + tijd β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ Duur: β—‹ 30 ● 45 β—‹ 60 β—‹ 90 min β”‚ ← Inline radio (niet dropdown) β”‚ β”‚ β”‚ Type: β—‹ Intake ● Behandeling β—‹ Follow β”‚ ← Inline radio β”‚ β”‚ β”‚ [+ Notitie toevoegen] β”‚ ← Collapsed by default β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ [Annuleren] [βœ“ Opslaan] β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` _Bij klik "+ Notitie toevoegen" β†’ expand naar textarea_ #### Inline Validatie | Veld | Wanneer valideren | Feedback | |------|-------------------|----------| | Patient | On blur + na 500ms idle | Rode border + "Selecteer een patient" | | Datum | On change | Gele border + "Let op: verleden datum" | | Tijd | On change | Check conflict realtime, toon inline warning | | Notities | On input | Character counter: "234/500" | **Conflict preview (inline, vΓ³Γ³r submit):** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ⚠️ Overlap met: Jan de Vries 14:00 β”‚ ← Inline warning β”‚ [Andere tijd kiezen] of [Negeren] β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` #### Functionaliteit **Validatie flow (optimized):** ``` 1. Bij elk veld change: inline validatie 2. Conflict check: real-time bij datum/tijd wijziging 3. Bij "Opslaan": a. Final validation sweep b. Als conflict: toon inline warning (niet aparte dialog voor simpele cases) c. Als meerdere conflicts: toon Conflict Dialog d. Opslaan β†’ optimistic update β†’ toast ``` **Acties:** | Knop | Gedrag | State | |------|--------|-------| | **Opslaan** | Valideer β†’ Sla op β†’ Sluit β†’ Toast | Disabled tijdens save, spinner | | **Annuleren** | Check unsaved β†’ Sluit modal | β€” | | **Verwijderen** (edit) | Inline confirm β†’ Soft delete | Rode tekst, niet prominent | **Keyboard shortcuts:** - `Cmd/Ctrl + Enter` = Opslaan (ook vanuit textarea) - `Escape` = Annuleren (met unsaved check) - `Tab` = Volgende veld - `↓` / `↑` in dropdowns = Navigate options --- ### 4.3 Patient Zoeken (MVP) **Locatie:** Autocomplete input in Afspraak Modal #### Functioneel gedrag **Zoeklogica:** - Minimaal 2 karakters voor zoekstart - Zoekt op: achternaam, voornaam, BSN (laatste 4 cijfers), geboortedatum - Resultaten: Max 10, gesorteerd op relevantie (exacte match eerst) - Debounce: 300ms na laatste toetsaanslag **Resultaat weergave:** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ πŸ” "jan de" ⟳ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ ⭐ Recente patiΓ«nten β”‚ ← Sectie header (subtle) β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Jan de Vries ↡ β”‚ ← Recent + keyboard hint β”‚ β™‚ 12-03-1985 (39 jaar) Β· Laatste: 28 nov β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ πŸ” Zoekresultaten β”‚ ← Sectie header β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Jantine de Boer β”‚ β”‚ ♀ 05-08-1972 (52 jaar) β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Jan de Groot β”‚ β”‚ β™‚ 23-07-1990 (34 jaar) β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ + Nieuwe patient aanmaken β”‚ ← Altijd onderaan β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **States:** | State | Weergave | |-------|----------| | Leeg (focus) | Toon recente patiΓ«nten (max 5) als suggestie | | Typen (< 2 chars) | "Typ minimaal 2 karakters..." | | Zoeken | Spinner rechts in input | | Resultaten | Recente patiΓ«nten bovenaan, dan zoekresultaten | | Geen resultaat | "Geen patiΓ«nt gevonden" + link naar patient aanmaken | | Geselecteerd | Chip met patient naam + X om te wissen | | Keyboard navigatie | Highlighted row met subtle achtergrond | **UX verbeteringen:** - **Recente patiΓ«nten:** Bij focus zonder input, toon laatste 5 bezochte patiΓ«nten - **Match highlighting:** Zoekterm bold in resultaten ("**Jan de** Vries") - **Keyboard hints:** Toon "↡" icon bij geselecteerde row - **Laatste afspraak:** Toon "Laatste: 28 nov" voor context - **Focus management:** Auto-focus op input bij modal open --- ### 4.4 Conflict Dialog (MVP) **Trigger:** Automatisch bij opslaan afspraak met overlap #### Functioneel gedrag **Detectie logica:** - Check: Nieuwe afspraak `[start, eind]` overlapt met bestaande afspraak(en)? - Overlap = enige overlap in tijd (inclusief aangrenzend) - Zelfde behandelaar (huidige user) is criterium **Dialog inhoud:** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ⚠️ Dubbele boeking gedetecteerd β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ Je hebt al een afspraak op dit tijdstip: β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ πŸ“… Donderdag 5 dec, 14:00-15:00 β”‚ β”‚ β”‚ β”‚ πŸ‘€ Jan de Vries β”‚ β”‚ β”‚ β”‚ πŸ“‹ Intake β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ Wil je de tijd aanpassen of toch inplannen? β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ [Wijzigen] [Toch inplannen] β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Acties:** | Knop | Gedrag | |------|--------| | **Wijzigen** | Sluit dialog, terug naar modal met tijd veld gefocust | | **Toch inplannen** | Bypass conflict, sla op, sluit alles, toast met waarschuwing | **Business rule:** > Systeem waarschuwt maar blokkeert NIET. Behandelaars hebben valide redenen voor overlap (bijv. administratie-tijd, korte telefoon tussendoor). --- ### 4.5 Afspraak Detail Popup (MVP) **Trigger:** Klik op afspraak blok in kalender #### Functioneel gedrag **Popup inhoud:** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Jan de Vries βœ• β”‚ β”‚ β™‚ 39 jaar Β· Intake #3 β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ πŸ“… Do 5 dec 2024 β”‚ β”‚ πŸ• 14:00 - 15:00 (60 min) β”‚ β”‚ ● Intakegesprek β”‚ ← Kleur dot voor type β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Notities: β”‚ β”‚ Eerste gesprek na verwijzing huisarts. β”‚ β”‚ Verwacht: angstklachten, slaapproblemen. β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ [πŸ“ Maak verslag] [✏️ Bewerken]β”‚ β”‚ β”‚ β”‚ ─────────────────────────────────────── β”‚ β”‚ [πŸ‘€ Naar dossier] [πŸ—‘οΈ Annuleren] β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Acties:** | Knop | Gedrag | Visuele prioriteit | |------|--------|-------------------| | **πŸ“ Maak verslag** | Navigeer naar rapportage met pre-fills | **Primary** (solid button) | | **✏️ Bewerken** | Open Afspraak Modal in edit mode | Secondary (outline) | | **πŸ‘€ Naar dossier** | Navigeer naar patient dossier | Tertiary (text link) | | **πŸ—‘οΈ Annuleren** | Confirm dialog β†’ soft delete | Tertiary (text link, rode tekst) | **Contextuele CTA (slimme primary actie):** | Afspraak status | Primary actie | |-----------------|---------------| | Gepland (toekomst) | "Bewerken" prominent | | Vandaag/nu | "**Maak verslag**" prominent (pulsing) | | Verleden zonder verslag | "**Maak verslag**" prominent + badge "!" | | Verleden met verslag | "Bekijk verslag" + "Bewerken" | **Status indicatoren:** | Status | Badge | Extra visueel | |--------|-------|---------------| | `planned` | πŸ”΅ Blauw | β€” | | Vandaag | 🟒 Groen | Subtle glow effect | | `in-progress` | 🟒 Groen pulsing | "Nu bezig" label | | `on-hold` | 🟠 Oranje | Pauze icon | | `completed` | βšͺ Grijs | Check icon | | `cancelled` | πŸ”΄ Rood | Doorgestreepte tekst | **UX verbeteringen:** - **Quick-action keyboard:** `V` = Verslag maken, `E` = Edit, `D` = Delete - **Positie:** Popup verschijnt naast afspraak blok, niet centered (context behouden) - **Click-outside:** Sluit popup - **Animatie:** Fade-in vanuit afspraak blok positie - **Verslag indicator:** Als verslag bestaat, toon "πŸ“ Verslag (28 nov)" link in popup --- ### 4.6 Toolbar (MVP) **Locatie:** Boven kalender grid, sticky bij scrollen #### Functioneel gedrag **Desktop layout:** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ [β—€] [Vandaag] [β–Ά] πŸ“… Week 49 Β· 2-8 december 2024 [Dag|Week|Werk] β”‚ β”‚ [+ Nieuwe afspraak] β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Tablet layout (768-1024px):** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ [β—€] [Vandaag] [β–Ά] Week 49 [D|W|5] [+ Nieuw] β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Mobile layout (<768px):** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ [β—€] Do 5 december [β–Ά] [+] β”‚ ← Compact, alleen dag β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` | Element | Gedrag | Keyboard | |---------|--------|----------| | **β—€ / β–Ά** | Navigeer 1 periode terug/vooruit | `←` / `β†’` | | **Vandaag** | Spring naar huidige datum + scroll naar nu | `T` | | **Datum label** | Klik β†’ open date picker voor directe navigatie | β€” | | **View toggle** | Switch tussen views | `1`/`2`/`3` | | **+ Nieuwe afspraak** | Open modal zonder pre-fill datum | `N` | **View toggle states:** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ [Dag] Week Werkdagen β”‚ ← Dag geselecteerd β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ na klik op Week β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Dag [Week] Werkdagen β”‚ ← Week geselecteerd, animated underline β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Extra UX details:** - **Vandaag button:** Highlight als niet op vandaag (subtle pulsing dot) - **Datum klik:** Opent kleine kalender picker voor snelle week-jump - **Navigatie animatie:** Smooth slide transition bij periode wisseling - **Loading tijdens navigatie:** Spinner in datum label, grid blijft staan --- ### 4.7 Mini Kalender Sidebar (Stretch) **Locatie:** Linker sidebar op desktop #### Functioneel gedrag (indien gebouwd) ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ December 2024 β”‚ β”‚ Ma Di Wo Do Vr Za Zoβ”‚ β”‚ 1 β”‚ β”‚ 2 3 4 5β€’ 6 7 8β”‚ β”‚ 9 10 11 12 13 14 15β”‚ β”‚ 16 17 18 19 20 21 22β”‚ β”‚ 23 24 25 26 27 28 29β”‚ β”‚ 30 31 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` - **Bullet (β€’)**: Dagen met afspraken - **Highlight**: Geselecteerde dag/week - **Klik op dag**: Navigeer naar die dag in main view --- ## 5. UI-overzicht (visuele structuur) 🎯 **Doel:** Globale schermopbouw communiceren. ### 5.1 Desktop Layout (β‰₯1024px) ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ EPD Sidebar β”‚ Agenda Module β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚ β”‚ β”‚Dashboardβ”‚ β”‚ β”‚ Toolbar: [β—€][Vandaag][β–Ά] Week 49 [Dag|Week|Werk] β”‚β”‚ β”‚ │─────────│ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”‚ β”‚ β”‚CliΓ«nten β”‚ β”‚ β”‚ β”‚β”‚ β”‚ │─────────│ β”‚ β”‚ Ma Di Wo Do Vr Za Zo β”‚β”‚ β”‚ β”‚β–ΊAgenda β”‚ β”‚ β”‚ ───────────────────────────────────────── β”‚β”‚ β”‚ │─────────│ β”‚ β”‚ 08:00 β”‚β”‚ β”‚ β”‚Rapportageβ”‚ β”‚ β”‚ 09:00 β”Œβ”€β”€β”€β”€β” β”‚β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ 10:00 β”‚Jan β”‚ β”Œβ”€β”€β”€β”€β” β”‚β”‚ β”‚ β”‚ β”‚ 11:00 β”‚de Vβ”‚ β”‚Mariβ”‚ β”‚β”‚ β”‚ β”‚ β”‚ 12:00 β””β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚β”‚ β”‚ β”‚ β”‚ 13:00 β””β”€β”€β”€β”€β”˜ β”‚β”‚ β”‚ β”‚ β”‚ 14:00 β”Œβ”€β”€β”€β”€β” β”‚β”‚ β”‚ β”‚ β”‚ 15:00 β”‚Pietβ”‚ β”‚β”‚ β”‚ β”‚ β”‚ 16:00 β””β”€β”€β”€β”€β”˜ β”‚β”‚ β”‚ β”‚ β”‚ 17:00 β”‚β”‚ β”‚ β”‚ β”‚ 18:00 β”‚β”‚ β”‚ β”‚ └──────────────────────────────────────────────────────│ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### 5.2 Mobile Layout (<768px) ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ≑ Agenda + Nieuw β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β—€ Vandaag β–Ά β”‚ β”‚ Do 5 december 2024 β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ 08:00 ──────────────────│ β”‚ 09:00 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Jan de Vries β”‚ β”‚ β”‚ 10:00 β”‚ Intake β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ 11:00 ──────────────────│ β”‚ 12:00 ──────────────────│ β”‚ 13:00 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Maria Jansen β”‚ β”‚ β”‚ 14:00 β”‚ Behandeling β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ 15:00 ──────────────────│ β”‚ ... β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Mobile aanpassingen:** - Alleen dag-view standaard - Geen drag-drop (gebruik edit button) - Swipe links/rechts voor dag navigatie - Hamburger menu voor EPD sidebar ### 5.3 Afspraak Modal (Responsive) ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Nieuwe afspraak βœ• β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ Patient * β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ πŸ” Zoek patient... β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ Datum * Starttijd * β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ πŸ“… 05-12-2024 β”‚ β”‚ 14:00 β–Ό β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ Duur * β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ 60 minuten β–Ό β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ Type afspraak * β”‚ β”‚ β—‹ Intake ● Behandeling β—‹ Follow-up β”‚ β”‚ β”‚ β”‚ Notities β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ [Annuleren] [Opslaan] β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- ## 5.5 UX Richtlijnen & Micro-interacties 🎯 **Doel:** DefiniΓ«ren van de kleine details die de ervaring vloeiend maken. ### 5.5.1 Design Principes | Principe | Toepassing in Agenda | |----------|---------------------| | **Snelheid boven alles** | Afspraak maken < 10 sec, geen onnodige stappen | | **Visuele feedback** | Elke actie toont direct resultaat | | **Foutpreventie > foutcorrectie** | Slim valideren vΓ³Γ³r submit | | **Flexibiliteit** | Waarschuwen, niet blokkeren | | **Context behouden** | Na actie terug naar waar je was | ### 5.5.2 Micro-interacties & Animaties **Afspraak blokken:** | Interactie | Visuele feedback | Timing | |------------|------------------|--------| | Hover | Lichte schaduw + cursor pointer | Instant | | Klik | Scale 0.98 + donkerder | 100ms ease | | Drag start | Opacity 0.7 + verhoogde schaduw | 150ms | | Drag over slot | Doelslot krijgt highlight border | Instant | | Drop | Bounce-in animatie naar nieuwe positie | 200ms spring | **Modals & Dialogs:** | Actie | Animatie | Timing | |-------|----------|--------| | Open | Fade-in + slide-up | 200ms ease-out | | Sluiten | Fade-out + slide-down | 150ms ease-in | | Achtergrond | Blur + dim (opacity 0.5) | 200ms | **Feedback elementen:** | Element | Gedrag | |---------|--------| | Toast success | Slide-in rechtsonder, auto-dismiss 3s | | Toast warning | Slide-in, persist tot dismiss | | Loading spinner | Pulse animatie, centered in context | | Skeleton | Shimmer effect linksβ†’rechts | ### 5.5.3 Optimistic Updates **Principe:** UI update direct, rollback bij fout. | Actie | Optimistic gedrag | Bij fout | |-------|-------------------|----------| | Afspraak opslaan | Direct in kalender tonen | Remove + toast "Opslaan mislukt, probeer opnieuw" | | Afspraak verzetten | Direct naar nieuwe positie | Terug naar origineel + toast | | Afspraak annuleren | Direct doorstrepen (visueel) | Herstel + toast | **Implementatie voorbeeld:** ``` 1. User klikt "Opslaan" 2. Modal sluit, afspraak verschijnt in kalender (grijs/loading state) 3. API call in background 4. Success β†’ afspraak krijgt normale styling 5. Error β†’ afspraak verdwijnt, toast met retry optie ``` ### 5.5.4 Smart Defaults & Auto-fill **Tijdslot klikken:** | Context | Auto-fill | |---------|-----------| | Klik op 14:00 | Datum + tijd pre-filled | | Klik na laatste afspraak | Suggereer aansluitend tijdslot | | Klik op zelfde dag als recente afspraak | Suggereer zelfde patient | **Type selectie:** | Laatste afspraak patient | Suggestie | |--------------------------|-----------| | Geen eerdere afspraken | Intake (standaard) | | Had intake | Behandeling | | Had 3+ behandelingen | Follow-up | **Duur selectie:** | Type | Standaard duur | |------|----------------| | Intake | 60 min | | Behandeling | 45 min | | Follow-up | 30 min | ### 5.5.5 Keyboard Navigatie **Globale shortcuts (wanneer op agenda pagina):** | Shortcut | Actie | |----------|-------| | `N` | Nieuwe afspraak (opent modal) | | `T` | Ga naar vandaag | | `←` / `β†’` | Vorige/volgende periode | | `1` / `2` / `3` | Switch naar Dag/Week/Werkdagen | | `Esc` | Sluit modal/popup | **In Afspraak Modal:** | Shortcut | Actie | |----------|-------| | `Tab` | Volgende veld | | `Shift+Tab` | Vorige veld | | `Enter` | Opslaan (als geen textarea focus) | | `Esc` | Annuleren (met unsaved changes check) | | `↓` / `↑` | Navigeer zoekresultaten | **In Patient zoeken:** | Shortcut | Actie | |----------|-------| | `↓` | Eerste/volgende resultaat selecteren | | `↑` | Vorige resultaat | | `Enter` | Bevestig selectie | | `Esc` | Sluit dropdown, behoud huidige selectie | ### 5.5.6 Empty States & Onboarding **Lege agenda (geen afspraken deze week):** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ πŸ“… β”‚ β”‚ β”‚ β”‚ Geen afspraken deze week β”‚ β”‚ β”‚ β”‚ Klik op een tijdslot om je eerste β”‚ β”‚ afspraak in te plannen, of gebruik: β”‚ β”‚ β”‚ β”‚ [+ Nieuwe afspraak] β”‚ β”‚ β”‚ β”‚ πŸ’‘ Tip: Druk 'N' voor snelle invoer β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Eerste keer agenda openen (onboarding hint):** - Subtle pulse animatie op "+ Nieuwe afspraak" button - Tooltip: "Begin hier met je eerste afspraak" - Verdwijnt na eerste afspraak of dismiss ### 5.5.7 Error Handling & Recovery **Graceful degradation:** | Fout scenario | User ziet | |---------------|-----------| | API timeout | "Even geduld..." β†’ na 5s: "Kon niet laden. [Opnieuw proberen]" | | Conflict check faalt | Sla op zonder conflict check + warning toast | | Patient search faalt | "Zoeken niet beschikbaar. Typ volledige naam." | **Undo functionaliteit:** | Actie | Undo mogelijkheid | |-------|-------------------| | Afspraak verwijderd | Toast met "Ongedaan maken" link (5 sec window) | | Afspraak verzet | Toast met "Ongedaan maken" link (5 sec window) | | Modal gesloten met unsaved | "Je hebt onopgeslagen wijzigingen. Sluiten?" | **Unsaved changes detection:** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Wijzigingen niet opgeslagen β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ Je hebt wijzigingen die nog niet zijn β”‚ β”‚ opgeslagen. Wil je deze verliezen? β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ [Terug naar formulier] [Niet opslaan] β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### 5.5.8 Visual Hierarchy in Kalender **Tijdslot visuele staten:** | Staat | Visuele behandeling | |-------|---------------------| | Beschikbaar | Wit/licht, hover highlight | | Bezet | Afspraak blok | | Verleden | Licht grijs, minder contrast | | Buiten werktijd | Gestreept/gearceerd patroon | | Nu (huidige tijd) | Rode lijn indicator | | Geselecteerd slot | Blue outline | **Afspraak blok informatie hiΓ«rarchie:** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Jan de Vries πŸ“ β”‚ ← Naam (bold) + verslag icon β”‚ 14:00 - 15:00 β”‚ ← Tijd (secondary) β”‚ ● Intake β”‚ ← Type met kleur dot β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Bij weinig ruimte (korte afspraken 15-30 min):** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ J. de Vries 14:00 ● β”‚ ← Compacte weergave β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### 5.5.9 Touch & Mobile Specifiek **Touch targets:** - Minimum 44x44px voor alle interactieve elementen - Afspraak blokken: volledige breedte van kolom **Gestures:** | Gesture | Actie | |---------|-------| | Swipe links/rechts | Volgende/vorige dag | | Long press op afspraak | Open context menu (bewerken/verwijderen) | | Pull down | Refresh agenda data | | Tap op leeg slot | Toon "+" button β†’ tap = nieuwe afspraak | **Mobile-specifieke UI:** - Geen drag-drop (te foutgevoelig op touch) - Bottom sheet ipv centered modal - Sticky header met datum bij scrollen ### 5.5.10 Loading States per Component | Component | Loading state | |-----------|---------------| | Agenda grid | Skeleton met 3-4 placeholder blokken | | Patient search | Spinner in input rechts | | Modal opslaan | Button disabled + spinner + "Opslaan..." | | View switch | Fade-out β†’ skeleton β†’ fade-in | | Datum navigatie | Kort skeleton (200ms max) | **Perceived performance:** - Prefetch volgende/vorige week data bij idle - Cache huidige week, invalidate bij mutatie - Stale-while-revalidate pattern --- ## 6. Interacties met AI (functionele beschrijving) 🎯 **Doel:** Uitleggen waar AI in de agenda flow voorkomt. ### 6.1 AI-integratiepunten in Agenda Module | Locatie | AI-actie | Trigger | Output | |---------|----------|---------|--------| | Afspraak Detail | **β†’ Maak verslag** | Klik op "Maak verslag" button | Navigatie naar Rapportage met pre-fills | | Rapportage (na navigatie) | Transcriptie | Klik "Opname starten" | Audio β†’ tekst via Deepgram | | Rapportage (na navigatie) | Verslag genereren | Klik "AI genereer" | Gestructureerd verslag op basis van transcriptie | ### 6.2 Afspraak β†’ Verslag Flow (Kernintegratie) Dit is de **killer feature** van de agenda integratie: **Stap-voor-stap:** ``` 1. Behandelaar klikt op afspraak in agenda (bijv. "Jan de Vries - 10:00 Intake") 2. Detail popup opent met "πŸ“ Maak verslag" button 3. Behandelaar klikt "Maak verslag" 4. Systeem navigeert naar: /epd/patients/[jan-id]/rapportage?encounter=[afspraak-id] 5. Rapportage module opent met: - Patient: Jan de Vries (pre-filled, read-only) - Type: Intake verslag (pre-selected) - Afspraak referentie: 05-12-2024 10:00 (gelinkt) 6. Behandelaar kan direct: - Audio opnemen β†’ AI transcribeert - AI verslag laten genereren - Handmatig schrijven 7. Bij opslaan: verslag automatisch gekoppeld aan afspraak 8. In agenda: afspraak toont nu πŸ“ icon (verslag aanwezig) ``` **Pre-fill mapping:** | Rapportage veld | Bron uit Afspraak | |-----------------|-------------------| | `patient_id` | `appointment.patient_id` | | `encounter_id` | `appointment.id` | | `report_type` | Gebaseerd op `appointment.type` (intake β†’ "intake_verslag") | | `title` | `"Verslag {type} - {patient_naam} - {datum}"` | ### 6.3 Bidirectionele Linking **Van Agenda naar Dossier:** - Afspraak detail popup bevat link naar patient dossier - Klik "Naar dossier" β†’ `/epd/patients/[id]` **Van Dossier naar Agenda:** - In patient timeline: afspraken weergeven - Klik op afspraak β†’ terug naar agenda met die afspraak geselecteerd **Van Afspraak naar Verslag:** - Afspraak icon toont πŸ“ als verslag bestaat - Klik op icon β†’ direct naar verslag **Van Verslag naar Afspraak:** - Verslag header toont "Gekoppeld aan afspraak: Do 5 dec 14:00" - Klik β†’ terug naar afspraak detail --- ## 7. Gebruikersrollen en rechten 🎯 **Doel:** Beschrijven welke rollen toegang hebben. ### MVP: Single-User Model In de MVP is er **geen rechtenbeheer**. Alle functionaliteit is beschikbaar voor de ingelogde behandelaar. | Rol | Toegang | Beperkingen | |-----|---------|-------------| | **Behandelaar** (enige rol) | Volledige agenda | Alleen eigen afspraken zichtbaar | ### Data Scoping - **Afspraken:** Gefilterd op `practitioner_id = current_user.id` - **PatiΓ«nten:** Alle patiΓ«nten in systeem doorzoekbaar (MVP simplificatie) - **Verslagen:** Alleen eigen verslagen ### Post-MVP: Multi-User Model | Rol | Toegang | Beperkingen | |-----|---------|-------------| | Behandelaar | Eigen agenda | Alleen eigen afspraken bewerken | | Assistent | Alle agenda's | Inplannen voor anderen, niet verwijderen | | Manager | Alle agenda's (readonly) | Geen bewerkingen, wel rapportages | --- ## 8. Data Model (Functionele Entiteiten) 🎯 **Doel:** Functioneel overzicht van data-entiteiten. ### 8.1 Afspraak (Encounter) | Attribuut | Type | Beschrijving | |-----------|------|--------------| | `id` | UUID | Unieke identifier | | `patient_id` | UUID | Gekoppelde patient | | `practitioner_id` | UUID | Behandelaar (current user) | | `period_start` | DateTime | Starttijd afspraak | | `period_end` | DateTime | Eindtijd afspraak | | `type_code` | Enum | intake / treatment / followup | | `type_display` | String | "Intakegesprek", "Behandeling", etc. | | `status` | Enum | planned / in-progress / on-hold / completed / cancelled | | `notes` | Text | Vrije notities | | `created_at` | DateTime | Aanmaakdatum | | `updated_at` | DateTime | Laatste wijziging | ### 8.2 Afspraak Types | Code | Display (NL) | Standaard duur | Kleur (stretch) | |------|--------------|----------------|-----------------| | `intake` | Intakegesprek | 60 min | πŸ”΅ Blauw | | `treatment` | Behandeling | 45 min | 🟒 Groen | | `followup` | Follow-up | 30 min | 🟑 Geel | ### 8.3 Status Lifecycle ``` planned β†’ in-progress β†’ completed ↓ ↓ on-hold cancelled (soft delete) ``` | Status | Betekenis | Automatisch | |--------|-----------|-------------| | `planned` | Ingepland, nog niet gestart | Bij aanmaken | | `in-progress` | Momenteel bezig | Bij starttijd? (post-MVP) | | `on-hold` | Tijdelijk gepauzeerd | Handmatig (post-MVP) | | `completed` | Afgerond | Handmatig of na verslag opslaan | | `cancelled` | Geannuleerd | Bij "Verwijderen" actie | --- ## 9. Flows in Detail 🎯 **Doel:** Gedetailleerde stap-voor-stap beschrijvingen. ### 9.1 Flow: Nieuwe Afspraak (Happy Path) **Scenario:** Behandelaar plant afspraak in tijdens telefoongesprek ```mermaid sequenceDiagram actor B as Behandelaar participant K as Kalender participant M as Afspraak Modal participant S as Systeem participant DB as Database B->>K: Klikt op leeg tijdslot (Do 14:00) K->>M: Opent modal met pre-fill Note over M: Datum: 05-12-2024
Tijd: 14:00 B->>M: Typt "jan de" in patient zoek M->>S: Search request (debounced) S->>DB: Query patients WHERE name LIKE 'jan de%' DB-->>S: [Jan de Vries, Jantine de Boer] S-->>M: Resultaten B->>M: Selecteert "Jan de Vries" B->>M: Selecteert type "Behandeling" B->>M: Klikt "Opslaan" M->>S: Valideer + conflict check S->>DB: Check overlap voor practitioner DB-->>S: Geen conflict S->>DB: INSERT encounter DB-->>S: Success S-->>M: Opslaan OK M-->>K: Sluit modal K->>K: Refresh + toon nieuwe afspraak K-->>B: Toast: "Afspraak opgeslagen" ``` ### 9.2 Flow: Dubbele Boeking **Scenario:** Behandelaar probeert afspraak te maken op bezette tijd ``` 1. Behandelaar klikt op 14:00 (waar al afspraak staat met Jan de Vries) 2. Modal opent, behandelaar vult Maria Jansen in, klikt Opslaan 3. Systeem detecteert overlap: - Nieuwe: Maria 14:00-15:00 - Bestaand: Jan 14:00-15:00 4. Conflict Dialog opent: "⚠️ Je hebt al een afspraak: Jan de Vries - 14:00 (Intake)" 5a. Behandelaar kiest "Wijzigen": β†’ Terug naar modal, tijd veld gefocust β†’ Kiest 15:00, opslaan succesvol 5b. Behandelaar kiest "Toch inplannen": β†’ Beide afspraken op 14:00 β†’ Toast: "Afspraak opgeslagen (dubbele boeking)" ``` ### 9.3 Flow: Afspraak β†’ Verslag **Scenario:** Direct na intake verslag maken via AI ``` 1. Behandelaar klikt op afspraak "Jan de Vries - 10:00 Intake" (zojuist afgelopen) 2. Detail popup opent 3. Behandelaar klikt "πŸ“ Maak verslag" 4. Navigatie naar /epd/patients/[jan-id]/rapportage?encounter=[enc-id] 5. Rapportage module laadt met: - Patient: Jan de Vries (locked) - Type: Intake verslag - Reference: "Afspraak 05-12-2024 10:00" 6. Behandelaar klikt "🎀 Start opname" 7. Behandelaar dicteert verslag van gesprek 8. Behandelaar klikt "Stop" 9. Deepgram transcribeert audio β†’ tekst 10. Behandelaar klikt "AI Genereer verslag" 11. Claude genereert gestructureerd verslag 12. Behandelaar reviewt, past aan, klikt "Opslaan" 13. Verslag opgeslagen met encounter_id link 14. Terug naar agenda: afspraak toont πŸ“ icon ``` ### 9.4 Flow: Drag & Drop Verzetten **Scenario:** Patient belt, moet naar andere tijd ``` 1. Behandelaar ziet afspraak "Maria - Di 14:00" in week view 2. Behandelaar klikt en houdt vast op afspraak card 3. Visuele feedback: card krijgt schaduw, wordt semi-transparant 4. Behandelaar sleept naar "Wo 15:00" 5. Drop β†’ Confirm dialog: "Afspraak verzetten van di 14:00 naar wo 15:00?" [Annuleren] [Bevestigen] 6. Behandelaar klikt "Bevestigen" 7. Systeem checkt conflict (geen) 8. Database update: period_start = wo 15:00 9. Kalender refresh 10. Toast: "Afspraak verzet naar wo 15:00" ``` --- ## 10. Validaties & Business Rules 🎯 **Doel:** Overzicht van validatieregels. ### 10.1 Formulier Validaties | Veld | Regel | Foutmelding | |------|-------|-------------| | Patient | Verplicht, moet bestaan | "Selecteer een patient" | | Datum | Verplicht, format dd-mm-yyyy | "Vul een datum in" | | Datum | Niet in verleden | "Datum ligt in het verleden" (warning, niet block) | | Starttijd | Verplicht, 08:00-18:00 | "Kies een tijd binnen werktijden" | | Duur | Verplicht, 15-120 min | "Kies een geldige duur" | | Type | Verplicht | "Kies een type afspraak" | | Notities | Max 500 karakters | "Notities te lang (max 500)" | ### 10.2 Business Rules | Regel | Type | Gedrag | |-------|------|--------| | **Dubbele boeking** | Warning | Toon dialog, sta override toe | | **Werktijden** | Soft | Waarschuw bij buiten 08:00-18:00, maar allow | | **Verleden datum** | Soft | Waarschuw, maar allow (correcties achteraf) | | **Eigen afspraken** | Hard | Kan alleen eigen afspraken zien/bewerken | | **Soft delete** | Hard | Cancelled afspraken blijven in DB, niet verwijderd | | **Verslag koppeling** | Auto | Verslag maakt automatisch link naar encounter | ### 10.3 Conflict Detectie Logica ``` isConflict = (new.start < existing.end) AND (new.end > existing.start) AND (new.practitioner_id = existing.practitioner_id) AND (existing.status != 'cancelled') ``` --- ## 11. Prioritering MVP vs Post-MVP 🎯 **Doel:** Duidelijke cut-off voor eerste oplevering. ### MVP (Must Ship) | Feature | Reden | |---------|-------| | Week view kalender | Core navigatie | | Dag view kalender | Alternatieve weergave | | Nieuwe afspraak maken | Core functie | | Patient zoeken (autocomplete) | Koppeling nodig | | Afspraak bewerken | Wijzigingen nodig | | Afspraak annuleren (soft delete) | Status management | | Dubbele boeking warning | Foutpreventie | | Conflict override | Flexibiliteit | | "Maak verslag" navigatie | AI-integratie showcase | | Basic drag-drop (desktop) | Snelle wijzigingen | | Responsive mobile view | Demo-proof | ### Stretch (Nice-to-Have voor Demo) | Feature | Reden | |---------|-------| | Werkdagen view | Extra convenience | | Mini kalender sidebar | Navigatie gemak | | Recente patiΓ«nten dropdown | Sneller repeat | | Kleurcodering per type | Visueel | | Verslag icon op afspraak | Status indicator | ### Post-MVP (Later) | Feature | Wanneer | |---------|---------| | Recurring appointments | Na klantfeedback | | Multi-practitioner | Bij team gebruik | | Email/SMS notifications | Bij productie | | Calendar sync (Google/Outlook) | Enterprise | | Wachtlijstbeheer | Productie versie | | Audit logging | Compliance | --- ## 12. Bijlagen & Referenties 🎯 **Doel:** Links naar gerelateerde documenten. ### Interne Documenten | Document | Beschrijving | Status | |----------|--------------|--------| | PRD Agenda Module v1.0 | Productvisie en scope | βœ… Approved | | TO Agenda Module (volgt) | Technische implementatie | πŸ“‹ Te schrijven | | UX Stylesheet | Design tokens en componenten | βœ… Beschikbaar | | Database Types | Supabase schema definities | βœ… Gegenereerd | ### Externe Referenties | Bron | Gebruik | |------|---------| | [FullCalendar Docs](https://fullcalendar.io/docs) | Kalender library | | [shadcn/ui](https://ui.shadcn.com/docs/components) | UI componenten | | [date-fns](https://date-fns.org/) | Datum manipulatie | | [FHIR Encounter](https://www.hl7.org/fhir/encounter.html) | Data model referentie | ### Bestaande Code Patronen Referentie naar bestaande implementaties in codebase: | Pattern | Locatie | Hergebruik voor | |---------|---------|-----------------| | Patient list + search | `app/epd/patients/` | Patient zoeken component | | Form validation | `app/epd/patients/[id]/intakes/` | Afspraak formulier | | Modal dialogs | `components/ui/dialog.tsx` | Afspraak modal | | Toast notifications | `components/ui/toaster.tsx` | Feedback | | Server actions | `app/epd/patients/[id]/intakes/actions.ts` | CRUD operaties | | Type definitions | `lib/types/intake.ts` | Appointment types | --- ## Changelog | Versie | Datum | Auteur | Wijziging | |--------|-------|--------|-----------| | v1.0 | 02-12-2024 | Colin | Initieel FO op basis van PRD v1.0 | | v1.1 | 02-12-2024 | Colin | UX verbeteringen: micro-interacties, smart defaults, keyboard nav, optimistic updates, inline validatie, responsive toolbar, recente patiΓ«nten, contextuele CTAs | --- **Document Status:** βœ… Klaar voor review **Volgende stap:** β†’ Technisch Ontwerp (TO) Agenda Module --- ## Appendix: UX Checklist voor Implementatie Snelle checklist voor developers om UX verbeteringen niet te vergeten: ### Must-Have UX (MVP) - [ ] Auto-scroll naar "nu" bij pagina laden - [ ] Vandaag kolom highlight - [ ] Skeleton loading states - [ ] Optimistic updates met rollback - [ ] Inline validatie (niet alleen op submit) - [ ] Smart defaults: type β†’ duur koppeling - [ ] Keyboard shortcuts: N, T, ←, β†’, Esc - [ ] Focus management: auto-focus patient search in modal - [ ] Toast feedback bij alle acties - [ ] Unsaved changes warning - [ ] Recente patiΓ«nten bij lege search - [ ] Contextuele primary button (verslag maken prominent na afspraak) ### Nice-to-Have UX (Stretch) - [ ] Double-click op slot voor snelle afspraak - [ ] Hover "+" icon op lege slots - [ ] Match highlighting in zoekresultaten - [ ] Slide animaties bij view/datum wisseling - [ ] Undo toast na delete/verzetten (5 sec window) - [ ] Prefetch volgende/vorige week - [ ] Mobile swipe gestures - [ ] Onboarding hints bij eerste gebruik