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,238 @@
# E3.S2 - Patients lijst pagina
**Epic:** E3 - Patients & Organizations
**Story:** E3.S2 - Patients lijst pagina
**Story Points:** 5
**Status:** ✅ Compleet
## Doel
Patiënten lijst pagina met tabel, search, filters en paginatie.
## Acceptatiecriteria
- [x] `/patients` route met overzichtelijke tabel
- [x] Search functionaliteit op naam en BSN
- [x] Filters (status, gender)
- [x] Paginatie (50 per pagina)
- [x] Sorteer functionaliteit
## Implementatie
### 1. Server Actions (actions.ts)
📁 **Locatie:** `app/epd/patients/actions.ts`
**Updates:**
- ✅ Paginatie parameters toegevoegd (`page`, `pageSize`)
- ✅ Gender filter parameter
- ✅ Sorteer parameters (`sortBy`, `sortOrder`)
- ✅ Return type aangepast naar object met `patients`, `total`, `page`, `pageSize`
**API parameters:**
```typescript
{
search?: string; // Zoek op naam
status?: string; // Filter: planned, active, finished, cancelled
gender?: string; // Filter: male, female, other, unknown
page?: number; // Pagina nummer (default: 1)
pageSize?: number; // Items per pagina (default: 50)
sortBy?: string; // Sorteer kolom
sortOrder?: 'asc' | 'desc'; // Sorteer richting
}
```
### 2. Page Component (page.tsx)
📁 **Locatie:** `app/epd/patients/page.tsx`
**Updates:**
- ✅ SearchParams interface uitgebreid met nieuwe filters
- ✅ Page parameter parsing
- ✅ Props doorgegeven aan PatientList component
### 3. Patient List Component (patient-list.tsx)
📁 **Locatie:** `app/epd/patients/components/patient-list.tsx`
**Features geïmplementeerd:**
#### A. Filters
**Search bar:**
- Zoek op naam of BSN
- Real-time filtering
- Form submit handler
**Status filter:**
- Alle statussen
- Screening (planned)
- Actief (active)
- Afgerond (finished)
- Afgemeld (cancelled)
**Gender filter:**
- Alle geslachten
- Man (male)
- Vrouw (female)
- Anders (other)
- Onbekend (unknown)
#### B. Paginatie
**Implementatie:**
- 50 patiënten per pagina (configureerbaar)
- Pagina navigatie knoppen (vorige/volgende)
- Genummerde pagina buttons (max 7 zichtbaar)
- Smart pagination logica:
- Bij weinig pagina's: toon alle nummers
- Bij begin: toon eerste 7
- Bij einde: toon laatste 7
- In het midden: toon current ± 3
**UI elementen:**
- "Resultaten X-Y van Z" indicator
- Disabled state voor eerste/laatste pagina
- Active state voor huidige pagina
- Hover states voor interactie
#### C. Sortering
**Sorteerbare kolommen:**
- ✅ Naam (`name`)
- ✅ Geboortedatum (`birthDate`)
- ✅ Status (`status`)
- ✅ Laatst gewijzigd (`_lastUpdated`)
**Visual feedback:**
- Inactieve kolommen: `<ArrowUpDown>` (grijs)
- Actieve kolom ascending: `<ArrowUp>` (teal)
- Actieve kolom descending: `<ArrowDown>` (teal)
- Hover effect op sorteerbare headers
**Functionaliteit:**
- Click om te sorteren
- Click opnieuw om richting te wisselen (asc ↔ desc)
- Sortering reset naar pagina 1
#### D. Helper functions
```typescript
// URL parameters builder
buildUrlParams(updates: Record<string, string | number | undefined>)
// Event handlers
handleSearch(e: React.FormEvent)
handleStatusFilterChange(newStatus: string)
handleGenderFilterChange(newGender: string)
handlePageChange(newPage: number)
handleSort(column: string)
// Render helpers
renderSortIcon(column: string)
```
## UI/UX Details
### Layout
- Responsive design (desktop & mobile)
- Flex layout voor filters (wraps op kleine schermen)
- Sticky header mogelijk (voor lange lijsten)
### Colors & Styling
- Teal als primary color (#0d9488)
- Slate voor neutral elements
- Status badges met kleurcodering:
- Amber: Screening
- Emerald: Actief
- Slate: Afgerond
- Red: Afgemeld
### Empty States
- Verschillende berichten voor:
- Geen patiënten (met CTA om toe te voegen)
- Geen resultaten (met suggestie om filters aan te passen)
## Performance
**Optimalisaties:**
- Server-side paginatie (max 50 geladen per keer)
- URL-based state (deep linking, browser back/forward)
- Suspense voor loading states
- No-cache strategie voor realtime data
**Load times (verwacht):**
- Initial load: < 1s
- Filter/sort/page change: < 500ms
- Search debounce: instant (client-side filter)
## Database Queries
De actions maken gebruik van de FHIR API (`/api/fhir/Patient`) met de volgende query parameters:
```
GET /api/fhir/Patient?
name={search_term}&
status={status_filter}&
gender={gender_filter}&
_count={page_size}&
_offset={offset}&
_sort={sort_field}
```
**FHIR-compliant:**
- Gebruikt FHIR search parameters
- FHIR Bundle response format
- FHIR extension voor episode_status
## Testing Checklist
- [ ] Paginatie werkt correct (vorige/volgende/nummers)
- [ ] Search filtert correct op naam
- [ ] Status filter werkt voor alle statussen
- [ ] Gender filter werkt voor alle geslachten
- [ ] Sortering werkt voor alle kolommen
- [ ] URL parameters worden correct bijgewerkt
- [ ] Browser back/forward werkt met filters
- [ ] Empty state toont bij geen resultaten
- [ ] Responsive layout op mobile
- [ ] Loading states tonen bij data fetch
- [ ] Pagination reset bij filter wijziging
## Bekende Beperkingen
1. **FHIR API Afhankelijkheid:**
- Requires `/api/fhir/Patient` endpoint
- Episode status via extension (custom)
- Supabase moet online zijn voor data
2. **Client-side vs Server-side:**
- Search is momenteel client-side gefilterd
- Kan server-side voor betere performance bij grote datasets
3. **BSN Kolom:**
- Niet sorteerbaar (niet in sortBy options)
- Encryption zou performance impact hebben
## Volgende Stappen
Na E3.S2:
- [ ] **E3.S3** - Patient CRUD (Create/Update/Delete + validatie)
- [ ] Eventueel: Advanced filters (leeftijdsbereik, postcode, etc.)
- [ ] Eventueel: Export functionaliteit (CSV/Excel)
- [ ] Eventueel: Bulk actions (selecteer multiple → wijzig status)
## Referenties
- **Bouwplan:** `docs/bouwplan-mini-epd.md` (regel 352-356, E3.S2)
- **Actions:** `app/epd/patients/actions.ts`
- **Page:** `app/epd/patients/page.tsx`
- **Component:** `app/epd/patients/components/patient-list.tsx`
- **FHIR Types:** `lib/fhir/index.ts`
---
**Datum voltooid:** 2025-11-22
**Status:** ✅ Compleet
**Dependencies voltooid:** E2.S4 (Practitioner profile)
**Blokkeert:** E3.S3 (Patient CRUD)