# 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: `` (grijs) - Actieve kolom ascending: `` (teal) - Actieve kolom descending: `` (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) // 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)