Files
triqura-ecd/docs/swift/bouwplan-swift-agenda-planning.md
colinislit a6b63665e1 feat(swift): implement agenda planning module (Epic 4 UI)
- Add AgendaBlock core component with list, create, cancel, reschedule modes
- Implement AgendaListView with patient/type/location details and actions
- Implement AgendaCreateForm with fuzzy patient search and validation
- Implement AgendaCancelView with disambiguation support
- Implement AgendaRescheduleForm with date/time picker
- Integrate with server actions (create, cancel, reschedule)
- Add radio-group UI component
- Update documentation and status
2025-12-27 22:29:11 +01:00

32 KiB
Raw Blame History

Mission Control - Bouwplan

Projectnaam: Swift Agenda Planning Module
Versie: v1.0
Datum: 27-12-2025
Auteur: Colin Lit


1. Doel en context

Doel: een Swift Agenda Planning module bouwen waarmee gebruikers via chat afspraken kunnen opvragen, aanmaken, annuleren en verzetten, met een AgendaBlock artifact als visuele bevestiging.
Toelichting: dit bouwt voort op het Swift conversatiemodel en hergebruikt de klassieke agenda (/app/epd/agenda) als full view. De Swiftvariant focust op snelle queries en quick actions.


2. Uitgangspunten

2.1 Technische Stack

  • Frontend: Next.js App Router + React + TypeScript
  • Styling: Tailwind CSS + shadcn/ui components
  • State: Zustand (Swift store) + React Query for data caching
  • Backend: Next.js route handlers + Supabase (encounters table)
  • AI/Intent: Two-tier system (Local regex <50ms + Claude Haiku fallback ~400ms)
  • Date/Time: date-fns library (al aanwezig)
  • Auth: Supabase Auth (server-side guard via lib/auth/server.ts)
  • Voice: Deepgram (existing integration voor voice input)

2.2 Projectkaders

  • Scope (MVP): agenda_query, create_appointment, cancel_appointment, reschedule_appointment + AgendaBlock.
  • Out of scope: drag-and-drop, recurring, availability, conflict resolution UI, multi-practitioner.
  • Geen nieuwe dependencies zonder akkoord.
  • Geen database migraties in MVP.
  • Reuse bestaande agenda actions waar mogelijk.

2.3 Programmeer uitgangspunten

  • DRY: hergebruik app/epd/agenda/actions.ts (getEncounters, createEncounter, cancelEncounter, rescheduleEncounter).
  • KISS: snelle API routes + simpele AgendaBlock UI.
  • SOC: intent parsing, data fetching en UI gescheiden.
  • YAGNI: alleen P1/P2 uit FO, geen extra planner features.

2.4 Performance Targets

Metric Target Actual (Expected)
Local pattern match <50ms ~10-15ms
Local + entity extraction <100ms ~30-50ms
AI fallback (cold) <800ms ~400-600ms
AI fallback (warm) <500ms ~200-400ms
Total (local path) <150ms ~50-80ms
Total (AI path) <1000ms ~500-700ms

2.5 Confidence Thresholds

Confidence Actie Voorbeeld
>0.9 Direct artifact openen met prefill "afspraken vandaag"
0.7-0.9 Artifact + bevestigingsvraag "maak afspraak jan morgen" (tijd ontbreekt)
0.5-0.7 Verduidelijkingsvraag in chat "maak afspraak" (patient/tijd ontbreekt)
<0.5 Fallback: "Ik begrijp het niet" Gibberish input

3. Epics & Stories Overzicht

Epic ID Titel Doel Status Stories Opmerkingen
E0 Alignment & scope MVP afbakenen en keuzes vastleggen Done 2 FObased
E1 Intent & entity layer Agenda intents + entities toevoegen Done 4 Swift intent stack
E2 Date/time parsing NLPhelpers voor datum/tijd Done 3 Geen nieuwe deps
E3 Backend integratie Agenda data APIs + reuse actions Done 4 Auth vereist
E4 AgendaBlock UI List/create/cancel/reschedule views To Do 5 Swift artifact
E5 Chat orchestration Action routing + prompt update To Do 3 Swift chat API
E6 QA & docs Testplan + docs update To Do 3 Manual QA

4. Epics & Stories (Uitwerking)

Epic 0 — Alignment & scope

Epic doel: MVP scope, UX flows en beslissingen vastleggen.

Story ID Beschrijving Acceptatiecriteria Status Afhankelijkheden Story Points
E0.S1 Scope + out-of-scope vastleggen P1/P2 lijst bevestigd, OOS lijst bevestigd Done - 1
E0.S2 UX flow beschrijven Entry/exit, artifact gedrag en fallback flows gedocumenteerd Done E0.S1 2

UX flow (MVP):

  • Entry: user is in Swift chat; agenda intents open AgendaBlock when confidence >= 0.7.
  • Exit: close artifact via tab close; for full view use link to /epd/agenda from the AgendaBlock footer.
  • Queries: default to today when clear; ask a clarification question when date range is missing or ambiguous.
  • Create: require patient + date + time; use active patient when user says "deze patient"; otherwise ask in chat.
  • Cancel/reschedule: if multiple matches, show disambiguation list in AgendaBlock; confirm before final action.
  • Fallback: if intent confidence < 0.7, keep artifact closed and ask for missing details.

Epic 1 — Intent & entity layer

Epic doel: agenda intent types en entities toevoegen aan Swift.

Story ID Beschrijving Acceptatiecriteria Status Afhankelijkheden Story Points
E1.S1 SwiftIntent uitbreiden Agenda intent names toegevoegd in types/store Done E0.S1 2
E1.S2 Local intent patterns Regex patterns voor agenda intents in intent-classifier.ts Done E1.S1 3
E1.S3 AI fallback prompt Prompt in intent-classifier-ai.ts uitgebreid met agenda intents Done E1.S1 3
E1.S4 Entities schema ExtractedEntities uitgebreid met date/time/identifier Done E1.S1 2

Technical notes:

E1.S1 - SwiftIntent type uitbreiding:

  • File: lib/swift/types.ts
  • Houd SwiftIntent single source of truth (voorkom duplicatie).
  • SwiftIntent (na uitbreiding):
    type SwiftIntent =
      | 'dagnotitie'
      | 'zoeken'
      | 'overdracht'
      | 'agenda_query'          // 🆕
      | 'create_appointment'    // 🆕
      | 'cancel_appointment'    // 🆕
      | 'reschedule_appointment'// 🆕
      | 'unknown';
    

E1.S2 - Local pattern examples:

  • File: lib/swift/intent-classifier.ts
  • Toevoegen aan INTENT_PATTERNS:
    agenda_query: [
      { pattern: /^afspraken?\\b/i, weight: 1.0 },
      { pattern: /^agenda\\b/i, weight: 1.0 },
      { pattern: /^(wat|wanneer)\\s+is\\s+(mijn\\s+)?volgende\\s+afspraak/i, weight: 1.0 },
    ],
    create_appointment: [
      { pattern: /^maak\\s+afspraak\\b/i, weight: 1.0 },
      { pattern: /^plan\\s+(een\\s+)?(intake|afspraak)\\b/i, weight: 1.0 },
    ],
    cancel_appointment: [
      { pattern: /^annuleer\\s+(de\\s+)?afspraak/i, weight: 1.0 },
    ],
    reschedule_appointment: [
      { pattern: /^verzet\\s+(de\\s+)?afspraak/i, weight: 1.0 },
      { pattern: /^\\d{1,2}:\\d{2}\\s+naar\\s+\\d{1,2}:\\d{2}/i, weight: 0.9 },
    ],
    

E1.S3 - AI System Prompt addition:

  • File: lib/swift/intent-classifier-ai.ts
  • Toevoegen aan INTENT_CLASSIFIER_SYSTEM_PROMPT:
    • Agenda intent descriptions + voorbeelden
    • Entity extraction instructies (patientName, dateRange, datetime, type, identifier, newDatetime)
    • Response format met nieuwe entities

E1.S4 - ExtractedEntities uitbreiding:

  • File: lib/swift/types.ts
  • Toevoegen:
    interface ExtractedEntities {
      // Bestaande entities
      patientName?: string;
      category?: VerpleegkundigCategory;
      content?: string;
    
      // 🆕 Agenda entities
      dateRange?: {
        start: Date;
        end: Date;
        label: 'vandaag' | 'morgen' | 'deze week' | 'volgende week' | 'custom';
      };
      datetime?: {
        date: Date;
        time: string; // "HH:mm" format
      };
      appointmentType?: 'intake' | 'behandeling' | 'follow-up' | 'telefonisch' |
                        'huisbezoek' | 'online' | 'crisis' | 'overig';
      location?: 'praktijk' | 'online' | 'thuis';
      identifier?: {
        type: 'patient' | 'time' | 'both';
        patientName?: string;
        patientId?: string;
        time?: string;
        date?: Date;
        encounterId?: string;
      };
      newDatetime?: {
        date: Date;
        time: string;
      };
    }
    

Epic 2 — Date/time parsing

Epic doel: datum/tijd interpretatie uit natuurlijke taal.

Story ID Beschrijving Acceptatiecriteria Status Afhankelijkheden Story Points
E2.S1 Date parser utility lib/swift/date-time-parser.ts met relatieve datums Done E1.S4 3
E2.S2 Time parser utility Tijd normalisatie (14:00, half drie) Done E2.S1 2
E2.S3 Entity extraction hook Entity extractor gebruikt parser output Done E2.S2 2

Technical notes:

E2.S1 - Date parser implementation:

  • File: lib/swift/date-time-parser.ts
  • Functie: parseRelativeDate(input: string): Date | DateRange | null
  • Ondersteunt:
    • "vandaag", "morgen", "overmorgen"
    • "maandag", "dinsdag", ... (next weekday)
    • "deze week", "volgende week" (returns DateRange)
    • Fallback naar date-fns parse() voor "30 december", "28-12-2024"
  • Gebruik date-fns helpers: addDays(), startOfWeek(), endOfWeek(), addWeeks()

E2.S2 - Time parser implementation:

  • Functie: parseTime(input: string): string | null
  • Ondersteunt:
    • "14:00" → "14:00"
    • "14" → "14:00"
    • "twee uur" → "14:00"
    • "half drie" → "14:30"
    • "kwart voor drie" → "14:45"
  • Returns HH:mm format string

E2.S3 - Integration:

  • Parser functies worden aangeroepen in entity extraction flow
  • Local pattern matching extraheert ruwe strings ("morgen", "14:00")
  • Parser functies normaliseren naar Date/time formats
  • AI fallback gebruikt parser voor validation

Epic 3 — Backend integratie

Epic doel: agenda data ontsluiten voor Swift blocks.

Story ID Beschrijving Acceptatiecriteria Status Afhankelijkheden Story Points
E3.S1 Agenda query API Endpoint voor afspraken op datumrange (auth) Done E1.S4 3
E3.S2 Create appointment API Endpoint die createEncounter aanroept Done E3.S1 3
E3.S3 Cancel/reschedule API Endpoints die cancelEncounter/rescheduleEncounter aanroepen Done E3.S1 3
E3.S4 Patient match API Fuzzy patiënt matching + disambiguation lijst Done E1.S4 2

Technical notes:

E3.S1 - Agenda query endpoint:

  • Route: GET /api/swift/agenda?start=2024-12-27&end=2024-12-27
  • Auth: via createClient() from lib/auth/server.ts
  • Hergebruik: getEncounters() from app/epd/agenda/actions.ts
  • Response: { appointments: Encounter[] }
  • Filters: practitioner_id = current user, status = 'planned', period_start in range
  • Order: chronological (period_start ASC)

E3.S2 - Create appointment endpoint:

  • Route: POST /api/swift/agenda/create
  • Body: { patientId, datetime: { date, time }, type, location, notes? }
  • Validation: Zod schema, Dutch error messages
  • Hergebruik: createEncounter() from app/epd/agenda/actions.ts
  • Mapping:
    • type → typeCode (FHIR encounter type)
    • location → classCode ('AMB' = praktijk, 'VR' = online, 'HH' = thuis)
    • datetime → periodStart/periodEnd (1 hour duration default)
  • Response: { encounterId, success: true }

E3.S3 - Cancel/Reschedule endpoints:

  • Route: POST /api/swift/agenda/cancel

  • Body: { encounterId }

  • Hergebruik: cancelEncounter(encounterId) (soft delete: status → 'cancelled')

  • Route: POST /api/swift/agenda/reschedule

  • Body: { encounterId, newDatetime: { date, time } }

  • Hergebruik: rescheduleEncounter(encounterId, periodStart, periodEnd)

E3.S4 - Patient search endpoint:

  • Route: GET /api/swift/patients/search?q=jan
  • Fuzzy match op patient name (ILIKE %query%)
  • Response: { patients: Array<{ id, name, bsn }> }
  • Limit: 10 resultaten
  • Used voor: disambiguation bij meerdere matches

Epic 4 — AgendaBlock UI

Epic doel: Swift artifact voor agenda flows.

Story ID Beschrijving Acceptatiecriteria Status Afhankelijkheden Story Points
E4.S1 AgendaBlock skeleton Block met tabs/modes (list/create/cancel/reschedule) Done E3.S1 3
E4.S2 List view Lijst met afspraken + empty state Done E4.S1 3
E4.S3 Create form Prefill + validatie + submit Done E4.S1 5
E4.S4 Cancel view Disambiguation + confirm flow Done E4.S1 3
E4.S5 Reschedule view Edit form met nieuwe tijd Done E4.S1 3

Technical notes:

E4.S1 - AgendaBlock component structure:

  • File: components/swift/artifacts/blocks/agenda-block.tsx
  • Props interface:
    interface AgendaBlockProps {
      mode: 'list' | 'create' | 'cancel' | 'reschedule';
      appointments?: Encounter[];
      dateRange?: { start: Date; end: Date; label: string };
      prefillData?: {
        patient?: { id: string; name: string };
        datetime?: { date: Date; time: string };
        type?: EncounterType;
        location?: EncounterLocation;
      };
      disambiguationOptions?: Encounter[];
      onClose?: () => void;
    }
    
  • Architecture: switch statement op mode → render juiste sub-component
  • Styling: max-width 600px, max-height 80vh, overflow-y auto

E4.S2 - List view:

  • Component: <AgendaListView />
  • Layout:
    • Header: Datum label (e.g., "Afspraken Vandaag - 27 december") + close button
    • Body: Scrollable lijst van appointment cards
    • Footer: Link naar /epd/agenda ("📅 Open volledige agenda →")
  • Appointment card bevat:
    • Tijd (09:00 - 10:00)
    • Patient naam (klikbaar → opens PatientContextCard)
    • Type badge met color coding (intake=blauw, behandeling=groen, crisis=rood)
    • Locatie icon (📍 Praktijk, 🌐 Online, 🏠 Thuis)
    • Actions: [Details] [Annuleren]
  • Empty state: "📭 Geen afspraken gevonden" + [Maak nieuwe afspraak] button

E4.S3 - Create form:

  • Component: <AgendaCreateForm />
  • Fields:
    • Patiënt* (autocomplete, pre-filled)
    • Datum* (date picker, pre-filled)
    • Tijd* (time picker 07:00-20:00, pre-filled)
    • Type* (radio buttons: Intake, Behandeling, Vervolg, Telefonisch, Huisbezoek, Crisis)
    • Locatie* (radio buttons: Praktijk, Online, Thuis)
    • Notities (textarea, optioneel, max 500 chars)
  • Validation:
    • Patient required
    • Date cannot be in past
    • Time within 07:00-20:00
  • Conflict warning: "⚠️ Conflict: Je hebt al een afspraak om 14:00 met Marie" (optional feature)
  • Submit: [Annuleren] [✓ Afspraak maken]
  • States: initial → validating → submitting → success/error

E4.S4 - Cancel view:

  • Component: <AgendaCancelView />
  • Submode 1: Disambiguation (multiple matches)
    • Radio list met opties: "○ 28-12-2024 09:00 - Jan de Vries (Intake)"
    • [Annuleren] [Volgende →] buttons
  • Submode 2: Confirmation (single match or after disambiguation)
    • Appointment details card
    • Warning: "⚠️ Deze actie kan niet ongedaan worden gemaakt."
    • [Terug] [✓ Annuleren] buttons

E4.S5 - Reschedule view:

  • Component: <AgendaRescheduleForm />
  • Layout:
    • Afspraak details (readonly)
    • Huidige datum/tijd (readonly, strikethrough styling)
    • Nieuwe datum/tijd* (editable date + time pickers, pre-filled)
    • Conflict check: " Geen conflicten gevonden" or warning
    • [Annuleren] [✓ Verzetten] buttons

Styling specs:

  • Colors: Teal-700 primary, appointment type badges (zie FO sectie 13.3)
  • Animations: slide-in from right 200ms, fade-out on close
  • Typography: text-sm voor body, text-base voor headers
  • Spacing: 16px padding, 12px card gaps

Epic 5 — Chat orchestration

Epic doel: agenda intents laten landen in juiste artifact.

Story ID Beschrijving Acceptatiecriteria Status Afhankelijkheden Story Points
E5.S1 Action routing Agenda intents openen AgendaBlock met juiste mode To Do E4.S1 2
E5.S2 Chat prompt update /api/swift/chat prompt bevat agenda sectie + action format To Do E1.S3 2
E5.S3 Error states User-friendly errors + link naar /epd/agenda To Do E3.S1 2

Technical notes:

E5.S1 - Intent router implementation:

  • Location: Swift store of artifact manager
  • Functie: openArtifactForIntent(intent, entities, confidence)
  • Logic:
    if (confidence < 0.7) return null; // Trigger verduidelijkingsvraag
    
    switch (intent) {
      case 'agenda_query':
        return { type: 'AgendaBlock', mode: 'list', prefill: { dateRange } };
      case 'create_appointment':
        if (!entities.patientName) return null; // Need patient
        return { type: 'AgendaBlock', mode: 'create', prefill: { patient, datetime, type, location } };
      case 'cancel_appointment':
        return { type: 'AgendaBlock', mode: 'cancel', prefill: { identifier } };
      case 'reschedule_appointment':
        if (!entities.identifier) return null; // Need to know which appointment
        return { type: 'AgendaBlock', mode: 'reschedule', prefill: { identifier, newDatetime } };
    }
    

E5.S2 - Chat API system prompt addition:

  • File: app/api/swift/chat/route.ts
  • Toevoegen aan system prompt:
    ## Agenda & Afspraken Beheer
    
    Je helpt gebruikers met agenda-gerelateerde taken.
    
    ### Intents die je herkent:
    1. **agenda_query** - Afspraken opvragen
       Voorbeelden: "afspraken vandaag", "wat is volgende", "agenda morgen"
       Actie: Toon lijst van afspraken in AgendaBlock
    
    2. **create_appointment** - Nieuwe afspraak maken
       Voorbeelden: "maak afspraak met Jan morgen 14:00", "plan intake"
       Required: patient, date, time
       Optional: type (default: behandeling), location (default: praktijk)
    
    3. **cancel_appointment** - Afspraak annuleren
       Voorbeelden: "annuleer afspraak Jan", "cancel 14:00"
       Actie: Toon confirmation dialog
    
    4. **reschedule_appointment** - Afspraak verzetten
       Voorbeelden: "verzet 14:00 naar 15:00", "verzet Jan naar dinsdag"
       Actie: Toon edit form met oude + nieuwe tijd
    
    ### Entity Extraction:
    - Patient: extraheer volledige naam, gebruik activePatient als user zegt "deze patiënt"
    - Date/Time: parse relatieve datums ("morgen", "dinsdag"), validate geen verleden
    - Type: intake, behandeling, follow-up, telefonisch (default: behandeling)
    - Location: praktijk, online, thuis (default: praktijk)
    
    ### Verduidelijkingsvragen:
    Stel vragen bij:
    - Meerdere patiënten met zelfde naam
    - Onduidelijke datum
    - Ontbrekende tijd bij create
    - Meerdere matches bij cancel/reschedule
    

E5.S3 - Error handling:

  • Server errors: "Er ging iets mis bij het ophalen van je afspraken. Probeer het opnieuw of open de volledige agenda."
  • Auth errors: Redirect naar /login
  • Validation errors: Dutch messages ("Datum kan niet in het verleden liggen")
  • Network errors: Retry logic + user-friendly message

Epic 6 — QA & docs

Epic doel: kwaliteit borgen en documentatie updaten.

Story ID Beschrijving Acceptatiecriteria Status Afhankelijkheden Story Points
E6.S1 Manual test checklist Scenarios uit FO opgenomen To Do E5.S3 2
E6.S2 Docs update Bouwplan + release note bijgewerkt To Do E6.S1 1
E6.S3 Regression checks Swift en klassieke agenda blijven werken To Do E6.S1 2

5. Kwaliteit & Testplan

Test types:

Test Type Scope Tools Verantwoordelijke
Lint App code pnpm lint Developer
Type check TypeScript pnpm build Developer
Smoke tests Agenda intents + artifact flows Manual checklist (20 scenarios) Developer/UX
Regression /epd/agenda klassiek Manual checklist Developer

Manual Test Checklist (uit FO, 20 scenarios):

# Scenario Expected Result Priority Status
1 "afspraken vandaag" AgendaBlock list view, toont vandaag's afspraken P1
2 "wat is volgende afspraak" Chat response met eerstvolgende, AgendaBlock toont details P1
3 "maak afspraak jan morgen 14:00" Create form met prefill, patient gevonden P1
4 Voice: "maak intake marie vrijdag 10:00" Transcript correct, create form opent P2
5 "maak afspraak" (incomplete) Verduidelijkingsvraag: "Met welke patiënt?" P1
6 "maak afspraak onbekende patient" Patient search fallback, suggesties P2
7 Create form submit → success Toast, chat confirmation, artifact sluit P1
8 "annuleer afspraak jan" (1 match) Confirmation dialog, direct match P1
9 "annuleer afspraak jan" (3 matches) Disambiguation radio list P1
10 Cancel confirm → success Afspraak status=cancelled, toast P1
11 "verzet 14:00 naar 15:00" Reschedule form, tijd pre-filled P1
12 Reschedule submit → success Tijd updated, toast confirmation P1
13 Conflict warning (overlapping) Warning banner in create form P2
14 Click patient name in list PatientContextCard opent P2
15 Click "Details" button Navigates to /epd/agenda with filter P2
16 Empty state (geen afspraken) Placeholder met "Maak nieuwe afspraak" P1
17 Server error tijdens query Error in chat, geen artifact P1
18 Date in past validation "Kan geen afspraken in verleden maken" P1
19 Context-aware: "maak afspraak deze patient" Gebruikt active patient uit context P2
20 Multiple artifacts (3 max) Agenda + Dagnotitie + Context card, tabs P2

Regression Test Checklist:

# Test Expected Result Status
R1 Klassieke agenda /epd/agenda werkt nog Kan afspraken zien/maken/wijzigen
R2 Swift dagnotitie intent ongewijzigd "dagnotitie jan medicatie" opent DagnotatieBlock
R3 Swift zoeken intent ongewijzigd "zoek jan" opent ZoekenBlock
R4 Swift overdracht intent ongewijzigd "overdracht" opent OverdrachtBlock
R5 Auth guard op alle endpoints Geen auth → 401/redirect

Performance Test Targets:

Metric Target Test Method
Local pattern match <50ms Browser DevTools Network tab
Create form open <150ms total Lighthouse/manual timing
AI fallback <1000ms DevTools, onduidelijke input
List view render (10 items) <100ms React DevTools Profiler

6. User Stories (uit FO)

Primaire User Stories (P1 - MVP):

ID Als Wil ik Zodat Acceptatie
US-24 Verpleegkundige Snel overzicht afspraken vandaag Ik weet waar ik moet zijn "afspraken vandaag" → lijst in AgendaBlock, <3 sec
US-25 Verpleegkundige Check volgende afspraak tijdens werk Ik op tijd ben "wat is mijn volgende afspraak?" → directe info
US-27 Verpleegkundige Snelle afspraak tijdens telefoongesprek Ik direct kan plannen "maak afspraak jan morgen 14:00" → prefilled form, <15 sec
US-28 Verpleegkundige Context-aware planning Ik niet steeds naam hoef te typen "maak afspraak met deze patiënt" → gebruikt actieve patiënt
US-29 Verpleegkundige Voice input tijdens consult Ik hands-free kan werken Spraak → afspraak maken
US-30 Verpleegkundige Annuleren via chat Ik snel kan annuleren "annuleer afspraak jan" → confirmation → done
US-31 Verpleegkundige Snel verzetten Ik afspraken flexibel kan aanpassen "verzet 14:00 naar 15:00" → tijd update

Secundaire User Stories (P2 - Nice to Have):

ID Als Wil ik Zodat Acceptatie
US-26 Verpleegkundige Weekoverzicht bekijken Ik kan plannen "agenda deze week" → gefilterde lijst
US-32 Verpleegkundige Disambiguation bij meerdere matches Systeem helpt kiezen Systeem vraagt "Welke Jan?" → lijst opties

7. File Structuur (na implementatie)

lib/swift/
├── types.ts                         # SwiftIntent + ExtractedEntities uitbreidingen
├── intent-classifier.ts              # Local patterns voor agenda intents
├── intent-classifier-ai.ts           # AI prompt uitbreidingen
└── date-time-parser.ts               # 🆕 Date/time parsing utilities

app/api/swift/
├── agenda/
│   ├── route.ts                      # 🆕 GET agenda query endpoint
│   ├── create/route.ts               # 🆕 POST create appointment
│   ├── cancel/route.ts               # 🆕 POST cancel appointment
│   └── reschedule/route.ts           # 🆕 POST reschedule appointment
├── patients/
│   └── search/route.ts               # 🆕 GET fuzzy patient search
└── chat/route.ts                     # Updated: agenda system prompt

components/swift/artifacts/blocks/
├── agenda-block.tsx                  # 🆕 Main AgendaBlock component
├── agenda-list-view.tsx              # 🆕 List mode
├── agenda-create-form.tsx            # 🆕 Create mode
├── agenda-cancel-view.tsx            # 🆕 Cancel mode
└── agenda-reschedule-form.tsx        # 🆕 Reschedule mode

app/epd/agenda/
└── actions.ts                        # ♻️ Hergebruikt (getEncounters, createEncounter, etc.)

8. Demo & Presentatieplan

Doel: korte demo van agenda planning via Swift (5 minuten).

Demo Flow:

  1. Agenda query: "afspraken vandaag" → lijst met 3 afspraken
  2. Quick create: "maak afspraak met Jan morgen 14:00" → create form → submit → success toast
  3. Cancel flow: "annuleer afspraak Jan" → disambiguation (3 matches) → select → confirm → success
  4. Reschedule: "verzet de 14:00 naar 15:00" → edit form → submit → success
  5. Fallback: Link naar klassieke agenda tonen via footer

Key Messaging:

  • Swift = snelle queries en actions (10-15 sec)
  • Klassieke agenda = visuele planning en overzicht
  • Voice input = hands-free werken tijdens consult

9. Risico's & Mitigatie

Risico Kans Impact Mitigatie Owner
Intent ambigu Hoog Middel Disambiguation + fallback prompt UX
Date/time parsing faalt Middel Middel AI fallback + clear prompts Dev
API auth issues Laag Hoog Central auth guard + error messaging Dev
Scope creep Hoog Middel MVP guardrails PO

10. Sprint Planning & Implementatie Volgorde

Voorgestelde Sprint Indeling (3 sprints):

Sprint 1: Foundation (E1 + E2)

  • Focus: Intent layer + date/time parsing
  • Stories: E1.S1, E1.S2, E1.S3, E1.S4, E2.S1, E2.S2, E2.S3
  • Total: 17 SP
  • Oplevering: Intent detection + entity extraction werkend, nog geen UI
  • Test: Console log check van extracted entities

Sprint 2: Backend + UI Foundation (E3 + E4.S1-S2)

  • Focus: API endpoints + AgendaBlock basis
  • Stories: E3.S1, E3.S2, E3.S3, E3.S4, E4.S1, E4.S2
  • Total: 14 SP
  • Oplevering: Agenda query werkend met list view
  • Test: "afspraken vandaag" end-to-end

Sprint 3: UI Completion + Integration (E4.S3-S5 + E5 + E6)

  • Focus: Create/cancel/reschedule forms + orchestration
  • Stories: E4.S3, E4.S4, E4.S5, E5.S1, E5.S2, E5.S3, E6.S1, E6.S2, E6.S3
  • Total: 20 SP
  • Oplevering: MVP compleet
  • Test: Alle 20 test scenarios

Total MVP: 51 SP (~3 sprints à 2 weken = 6 weken)

Implementatie Volgorde (binnen stories):

Voor elke story, volg deze volgorde:

  1. Types first: Definieer interfaces/types
  2. Backend: API endpoints + server actions
  3. Frontend: UI components
  4. Integration: Wire backend ↔ frontend
  5. Test: Manual test scenario's

Critical Path:

E1.S1 (types) → E1.S2 (patterns) → E1.S4 (entities) → E2 (parsers) →
E3.S1 (query API) → E4.S1 (skeleton) → E4.S2 (list view) →
E5.S1 (routing) → Milestone: Basic Query Werkend

E3.S2 (create API) → E4.S3 (create form) → Milestone: Create Werkend

E3.S3 (cancel API) → E4.S4 (cancel view) → Milestone: Cancel Werkend

E4.S5 (reschedule) → E5.S2 (prompt) → E6 (QA) → MVP Done

11. Evaluatie & Lessons Learned

Te documenteren na oplevering:

  • Welke intents vaak misclassificeren?
  • Hoe snel users afspraken kunnen plannen?
  • Zijn extra agenda features nodig?

12. Referenties & Documentatie

Primaire Documenten:

  • FO Agenda Afspraken: docs/swift/fo-agenda-afspraken.md - Gebruikersgericht FO
  • FO Agenda Planning: docs/swift/fo-swift-agenda-planning.md - Technisch FO met detailed specs
  • Swift FO v3: docs/swift/fo-swift-medical-scribe-v3.md - Basis conversational interface
  • Swift Bouwplan Core: docs/swift/bouwplan-swift-standalone-module.md - Development roadmap

Code Referenties:

  • Bestaande Agenda: app/epd/agenda - Klassieke kalender (wordt hergebruikt)
  • Agenda Actions: app/epd/agenda/actions.ts - Server actions (getEncounters, createEncounter, etc.)
  • Swift Chat API: app/api/swift/chat/route.ts - Conversational endpoint
  • Intent Classifier: lib/swift/intent-classifier.ts - Local pattern matching
  • AI Classifier: lib/swift/intent-classifier-ai.ts - Claude Haiku fallback
  • Swift Types: lib/swift/types.ts - SwiftIntent & ExtractedEntities

Libraries & Dependencies:

  • date-fns: Date/time utilities (already installed)
  • Zod: API validation schemas (already installed)
  • React Query: Data caching (already installed)
  • shadcn/ui: UI components (already installed)
  • Deepgram: Voice input (already integrated)

External References:


13. Glossary & Abbreviations

Term Betekenis
Epic Grote feature of fase, bevat meerdere stories
Story Kleine uitvoerbare taak (user story)
SP Story Points - schatting van complexiteit
MVP Minimum Viable Product
FO Functioneel Ontwerp
P1/P2 Priority 1 (must have) / Priority 2 (nice to have)
SSE Server-Sent Events
RLS Row Level Security (Supabase)
NLP Natural Language Processing
Artifact Swift UI component (AgendaBlock, DagnotatieBlock, etc.)
Intent Gebruikersintentie (agenda_query, create_appointment, etc.)
Entity Geëxtraheerde data uit user input (patient, date, time)
Disambiguation Verduidelijking bij meerdere matches
Confidence Zekerheid van intent classificatie (0.0-1.0)
Two-tier Local pattern matching + AI fallback systeem
FHIR Fast Healthcare Interoperability Resources
Encounter Afspraak/contact in FHIR terminologie

Domain-Specific Terms:

Term Betekenis
Klassieke Agenda Bestaande visuele kalender in /epd/agenda
Swift Agenda Nieuwe conversational agenda interface
AgendaBlock Swift artifact voor agenda functionaliteit
Verpleegkundige Primaire gebruikersrol (nurse/healthcare provider)
Practitioner FHIR term voor zorgverlener
Quick Create Snel afspraak maken via natuurlijke taal
Hands-free Werken met voice input (geen typen nodig)

Versiehistorie

Versie Datum Auteur Wijziging
v1.0 27-12-2025 Colin Lit Initiele versie - basis epics en stories
v1.1 27-12-2025 Claude Code Uitgebreid met technische details uit FO's: patterns, entities, API specs, UI components, test scenarios, sprint planning, file structuur

Quick Reference Card

Voor Developers - Start Here:

  1. Lees Epic 0 voor scope
  2. Begin met E1.S1 (types uitbreiden)
  3. Volg implementatie volgorde (sectie 10)
  4. Check test scenarios (sectie 5)
  5. Zie file structuur (sectie 7) voor waar code moet komen

Voor Product Owners:

  • MVP scope: sectie 2.2
  • User stories: sectie 6
  • Demo plan: sectie 8
  • Risico's: sectie 9

Voor QA:

  • Test checklist: sectie 5 (20 scenarios)
  • Regression tests: sectie 5
  • Performance targets: sectie 2.4

Voor Designers:

  • UI components: Epic 4 technical notes
  • Styling specs: E4.S1-E4.S5
  • User flows: FO documenten (zie sectie 12)