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>
239 lines
6.1 KiB
Markdown
239 lines
6.1 KiB
Markdown
# 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)
|