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>
This commit is contained in:
colinislit
2025-11-24 14:14:06 +01:00
parent 0130e28f1e
commit a789bebe96
37 changed files with 5034 additions and 1977 deletions

View File

@@ -0,0 +1,379 @@
# 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
- [x] **Create:** Nieuwe patiënt aanmaken met validatie
- [x] **Read:** Patiënt gegevens ophalen en tonen
- [x] **Update:** Bestaande patiënt bijwerken
- [x] **Delete:** Patiënt verwijderen met confirmatie
- [x] BSN 11-proef validatie
- [x] Alle verplichte velden (volgens bouwplan)
- [x] John Doe support (crisis opname zonder BSN)
## Implementatie
### 1. Server Actions (actions.ts)
📁 **Locatie:** `app/epd/patients/actions.ts`
**CRUD Functies:**
```typescript
// 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:**
```typescript
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:**
```typescript
{
"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)