Files
triqura-ecd/docs/reports/E3.S3-patient-crud.md
colinislit a789bebe96 feat: rapportage API, speech recorder refactor, docs reorganisatie
Multiple features and improvements:

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

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

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

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

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

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 14:14:06 +01:00

9.7 KiB

E3.S3 - Patient CRUD

Epic: E3 - Patients & Organizations Story: E3.S3 - Patient CRUD Story Points: 6 Status: Compleet

Doel

Volledige CRUD operaties voor patiënten met validatie.

Acceptatiecriteria

  • Create: Nieuwe patiënt aanmaken met validatie
  • Read: Patiënt gegevens ophalen en tonen
  • Update: Bestaande patiënt bijwerken
  • Delete: Patiënt verwijderen met confirmatie
  • BSN 11-proef validatie
  • Alle verplichte velden (volgens bouwplan)
  • John Doe support (crisis opname zonder BSN)

Implementatie

1. Server Actions (actions.ts)

📁 Locatie: app/epd/patients/actions.ts

CRUD Functies:

// Create
export async function createPatient(fhirPatient: FHIRPatient): Promise<FHIRPatient>

// Read
export async function getPatient(id: string): Promise<FHIRPatient>
export async function getPatients(filters): Promise<{ patients, total, page, pageSize }>

// Update
export async function updatePatient(id: string, fhirPatient: FHIRPatient): Promise<FHIRPatient>

// Delete
export async function deletePatient(id: string): Promise<{ success: boolean }>

FHIR API Integration:

  • POST /api/fhir/Patient - Create
  • GET /api/fhir/Patient/:id - Read one
  • GET /api/fhir/Patient?params - Read many (met paginatie)
  • PUT /api/fhir/Patient/:id - Update
  • DELETE /api/fhir/Patient/:id - Delete

2. Patient Form Component

📁 Locatie: app/epd/patients/components/patient-form.tsx

Features:

A. BSN Validatie

11-proef Check:

function validateBSN(bsn: string): boolean {
  if (!bsn || bsn.length !== 9) return false;

  const digits = bsn.split('').map(Number);
  if (digits.some(isNaN)) return false;

  // Modulo-11 check
  const sum = digits.reduce((acc, digit, index) => {
    if (index < 8) {
      return acc + digit * (9 - index);
    }
    return acc - digit;
  }, 0);

  return sum % 11 === 0;
}

Validatie regels:

  • 9 cijfers verplicht
  • Alleen numerieke karakters
  • Modulo-11 proef moet kloppen
  • Optioneel bij John Doe registratie

B. Form Secties

Stap 1: Persoonlijke gegevens

  • Voorvoegsel (optioneel)
  • Voornaam (verplicht)
  • Achternaam (verplicht)
  • BSN (9 cijfers, 11-proef) - verplicht tenzij John Doe
  • Geboortedatum (verplicht, max vandaag)
  • Geslacht (verplicht): Man, Vrouw, Anders, Onbekend

Stap 2: Adresgegevens

  • Straat + huisnummer (optioneel)
  • Postcode (optioneel)
  • Woonplaats (optioneel)

Stap 3: Contactgegevens

  • Telefoonnummer (optioneel)
  • E-mail (optioneel, email validatie)

Stap 4: Verzekering

  • Verzekeraar (optioneel)
  • Polisnummer (optioneel)
  • Huisarts naam (optioneel)
  • Huisarts AGB-code (optioneel, 8 cijfers)

Stap 5: Noodcontact

  • Naam contactpersoon (optioneel)
  • Relatie (optioneel)
  • Telefoonnummer (optioneel)

C. John Doe Support

Features:

  • Checkbox om John Doe aan te geven
  • BSN wordt optioneel bij John Doe
  • Warning indicator voor incomplete gegevens
  • Mogelijkheid om later BSN aan te vullen
  • Custom FHIR extension: john-doe

Use case:

  • Crisis opnames waarbij identiteit niet direct bekend is
  • Patiënt kan later worden geüpdatet met volledige gegevens

D. FHIR Mapping

Extensions gebruikt:

{
  "extension": [
    // Episode status
    {
      "url": "http://mini-epd.local/fhir/StructureDefinition/episode-status",
      "valueCode": "planned" | "active" | "finished" | "cancelled"
    },
    // John Doe flag
    {
      "url": "http://mini-epd.local/fhir/StructureDefinition/john-doe",
      "valueBoolean": true | false
    },
    // Insurance (custom)
    {
      "url": "http://mini-epd.local/fhir/StructureDefinition/insurance",
      "valueString": "{\"company\":\"...\",\"number\":\"...\"}"
    },
    // General Practitioner (custom)
    {
      "url": "http://mini-epd.local/fhir/StructureDefinition/general-practitioner",
      "valueString": "{\"name\":\"...\",\"agb\":\"...\"}"
    }
  ],
  "contact": [
    // Emergency contact (FHIR standard)
    {
      "relationship": [{
        "coding": [{
          "system": "http://terminology.hl7.org/CodeSystem/v2-0131",
          "code": "C",
          "display": "Emergency Contact"
        }],
        "text": "Partner" | "Ouder" | "Kind" | etc.
      }],
      "name": { "text": "..." },
      "telecom": [{ "system": "phone", "value": "...", "use": "home" }]
    }
  ]
}

3. Delete Patient Component

📁 Locatie: app/epd/patients/components/delete-patient-button.tsx

Features:

A. Two-Step Confirmation

Step 1: Initial Warning

  • Rode "Gevaarlijke zone" sectie
  • Waarschuwing dat actie niet ongedaan gemaakt kan worden
  • "Patiënt verwijderen" button

Step 2: Final Confirmation

  • Gedetailleerde lijst van wat wordt verwijderd:
    • Alle persoonlijke gegevens
    • Alle screening en intake informatie
    • Alle diagnoses en observaties
    • Alle behandelplannen en doelen
    • Alle documenten en rapportages
  • Patiëntnaam wordt getoond
  • "Ja, verwijder permanent" button
  • Annuleren button

B. Safety Features

  • Disabled state tijdens verwijderen
  • Loading indicator
  • Error handling met feedback
  • Redirect naar overzichtspagina na succes
  • Cache revalidation

4. Page Implementations

Create Page:

  • 📁 app/epd/patients/new/page.tsx
  • Gebruikt PatientForm zonder patient prop
  • "Terug naar patiënten" link
  • Clear page title en beschrijving

Read Page:

  • 📁 app/epd/patients/[id]/page.tsx
  • Toont patiënt detail met tabs
  • Basisgegevens tab voor view/edit

Update Page:

  • 📁 app/epd/patients/[id]/basisgegevens/page.tsx
  • Gebruikt PatientForm met patient prop
  • John Doe warning indien van toepassing
  • Missing BSN warning
  • Delete button onderaan

List Page:

  • 📁 app/epd/patients/page.tsx
  • Tabel met alle patiënten (zie E3.S2)
  • "Nieuwe patiënt" button

Validatie

Client-side (HTML5)

Built-in validatie:

  • required attribute voor verplichte velden
  • type="email" voor email validatie
  • type="tel" voor telefoonnummer
  • type="date" met max voor geboortedatum
  • maxLength en pattern voor BSN/AGB
  • pattern="[0-9]{9}" voor BSN
  • pattern="[0-9]{8}" voor AGB

Server-side (Actions)

Validatie in handleSubmit:

  • BSN 11-proef check (tenzij John Doe)
  • Error throwing bij ongeldige data
  • FHIR API valideert ook server-side

Error handling:

  • Try-catch om alle errors
  • User-friendly error messages
  • Error state in UI

UI/UX Details

Form Layout

Desktop (md+):

  • Grid layouts: 2-3 kolommen voor gerelateerde velden
  • Grouped sections met headers
  • Visual separation met borders

Mobile:

  • Stack layout (1 kolom)
  • Responsive grid → stack
  • Touch-friendly input sizes

Visual Feedback

States:

  • Focus ring (teal) op inputs
  • Hover states op buttons
  • Loading states tijdens submit/delete
  • Disabled states
  • Error states (red border + message)

Colors:

  • Teal: Primary actions, focus
  • Red: Danger (delete), errors
  • Amber: Warnings (John Doe)
  • Orange: Info (incomplete BSN)
  • Slate: Neutral elements

Accessibility

Features:

  • Label voor alle inputs
  • Aria-labels waar nodig
  • Keyboard navigation (Tab, Enter)
  • Clear error messages
  • Confirmation voor destructieve acties

Testing Checklist

Create

  • Nieuwe patiënt aanmaken met alle velden
  • Nieuwe patiënt aanmaken met minimale velden
  • BSN validatie werkt (reject invalid)
  • John Doe aanmaken zonder BSN
  • Form validatie toont errors
  • Redirect naar detail pagina na succes

Read

  • Patiënt detail pagina toont alle gegevens
  • Lijst pagina toont alle patiënten
  • Missing gegevens worden correct getoond (-)
  • John Doe indicator zichtbaar

Update

  • Bestaande patiënt bewerken werkt
  • Velden pre-filled met huidige waarden
  • John Doe → regulier (BSN toevoegen)
  • Update success toont correcte data
  • John Doe warning verdwijnt na BSN toevoegen

Delete

  • Delete button zichtbaar op basisgegevens
  • First confirmation shows warning
  • Second confirmation toont details
  • Annuleren werkt op beide stappen
  • Delete success redirect naar lijst
  • Patiënt is echt verwijderd

Validation

  • BSN 11-proef reject: 123456789
  • BSN 11-proef accept: 111222333 (example valid)
  • Email validatie werkt
  • Geboortedatum niet in toekomst
  • Required velden kunnen niet leeg
  • AGB moet 8 cijfers zijn

Bekende Beperkingen

  1. FHIR API Afhankelijkheid:

    • Alle CRUD werkt via /api/fhir/Patient
    • API moet volledig geïmplementeerd zijn
    • Cascade delete moet in API geregeld zijn
  2. Validatie:

    • Momenteel alleen HTML5 + BSN check
    • Geen Zod schema validatie (toekomstige verbetering)
    • Server-side validatie in FHIR API
  3. Multi-step Wizard:

    • Bouwplan suggereert wizard
    • Huidige implementatie: single page form
    • Werkt goed, maar kan verbeterd naar wizard UX
  4. Soft Delete:

    • Momenteel hard delete
    • Toekomstige verbetering: soft delete met archivering

Volgende Stappen

Na E3.S3:

  • E4.S1 - Encounter tijdlijn
  • Eventueel: Zod validation schema
  • Eventueel: Multi-step wizard UX
  • Eventueel: Soft delete / archivering
  • Eventueel: Audit trail (wie/wanneer gewijzigd)

Referenties

  • Bouwplan: docs/bouwplan-mini-epd.md (regel 356, E3.S3)
  • Patient Form: app/epd/patients/components/patient-form.tsx
  • Delete Button: app/epd/patients/components/delete-patient-button.tsx
  • Actions: app/epd/patients/actions.ts
  • New Page: app/epd/patients/new/page.tsx
  • Edit Page: app/epd/patients/[id]/basisgegevens/page.tsx
  • FHIR Types: lib/fhir/index.ts

Datum voltooid: 2025-11-22 Status: Compleet Dependencies voltooid: E3.S2 (Patients lijst) Blokkeert: E4.S1 (Encounter tijdlijn)