feat: implement patient list and new patient form (E2.S1 & E2.S2)
Epic 2 - Cliëntenbeheer: Complete implementation of patient list with search/filter functionality and comprehensive new patient form with John Doe crisis admission support. E2.S1 - Cliëntenlijst: - Add client-side search bar with form submission - Implement status filter dropdown (all/screening/active/finished/cancelled) - Create StatusBadge component with color-coded status indicators - Update table columns: Status, Name, BSN, Last Updated - Add status filtering support to FHIR Patient API route - Update FHIR patient transform to include episode-status extension - Sort patients by updated_at descending (newest first) E2.S2 - Nieuwe Cliënt Flow: - Complete rewrite of patient form with all FO-required fields - Implement John Doe checkbox with conditional BSN requirement - Add BSN validation with Dutch Modulo-11 check algorithm - Add comprehensive form fields: * Name fields: prefix, given name, family name * BSN with 9-digit pattern validation * Birth date with max date validation * Gender selection * Address: street, postal code, city * Contact: phone, email * Insurance: company, policy number - Add warning messages for John Doe crisis admissions - Set default episode status to 'planned' for all new patients - Redirect to patient detail page after successful creation - Update FHIR transform bidirectional insurance extension support: * dbPatientToFHIR: serialize insurance to JSON extension * fhirPatientToDB: parse insurance from JSON extension - Pre-populate form fields when editing existing patients Technical changes: - app/api/fhir/Patient/route.ts: Add status query param and sorting - app/epd/patients/actions.ts: Add status filter parameter - app/epd/patients/page.tsx: Pass status searchParam - app/epd/patients/components/patient-list.tsx: Complete UI rewrite - app/epd/patients/components/patient-form.tsx: Complete form rewrite - lib/fhir/transforms/patient.ts: Add insurance extension handling - docs/specs/screening-intake/bouwplan-screening-intake-v1.0.md: Update status 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -131,6 +131,31 @@ export function dbPatientToFHIR(row: PatientRow): FHIRPatient {
|
||||
meta: {
|
||||
lastUpdated: row.updated_at || undefined,
|
||||
},
|
||||
|
||||
// Extension for episode status (non-standard FHIR, but needed for our workflow)
|
||||
extension: [
|
||||
row.status
|
||||
? {
|
||||
url: 'http://mini-epd.local/fhir/StructureDefinition/episode-status',
|
||||
valueCode: row.status,
|
||||
}
|
||||
: undefined,
|
||||
row.is_john_doe
|
||||
? {
|
||||
url: 'http://mini-epd.local/fhir/StructureDefinition/john-doe',
|
||||
valueBoolean: true,
|
||||
}
|
||||
: undefined,
|
||||
row.insurance_company
|
||||
? {
|
||||
url: 'http://mini-epd.local/fhir/StructureDefinition/insurance',
|
||||
valueString: JSON.stringify({
|
||||
company: row.insurance_company,
|
||||
number: row.insurance_number,
|
||||
}),
|
||||
}
|
||||
: undefined,
|
||||
].filter((x): x is NonNullable<typeof x> => x !== undefined),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -172,6 +197,30 @@ export function fhirPatientToDB(fhir: FHIRPatient): PatientInsert {
|
||||
const gpName = gp?.display;
|
||||
const gpAgb = gp?.identifier?.value;
|
||||
|
||||
// Extract status and john_doe from extensions
|
||||
const statusExtension = fhir.extension?.find(
|
||||
(ext) => ext.url === 'http://mini-epd.local/fhir/StructureDefinition/episode-status'
|
||||
);
|
||||
const johnDoeExtension = fhir.extension?.find(
|
||||
(ext) => ext.url === 'http://mini-epd.local/fhir/StructureDefinition/john-doe'
|
||||
);
|
||||
const insuranceExtension = fhir.extension?.find(
|
||||
(ext) => ext.url === 'http://mini-epd.local/fhir/StructureDefinition/insurance'
|
||||
);
|
||||
|
||||
// Parse insurance data from extension
|
||||
let insuranceCompany: string | undefined;
|
||||
let insuranceNumber: string | undefined;
|
||||
if (insuranceExtension?.valueString) {
|
||||
try {
|
||||
const insuranceData = JSON.parse(insuranceExtension.valueString);
|
||||
insuranceCompany = insuranceData.company;
|
||||
insuranceNumber = insuranceData.number;
|
||||
} catch (e) {
|
||||
console.error('Failed to parse insurance extension:', e);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: fhir.id,
|
||||
identifier_bsn: bsn || '999999990', // Default placeholder
|
||||
@@ -194,5 +243,9 @@ export function fhirPatientToDB(fhir: FHIRPatient): PatientInsert {
|
||||
general_practitioner_name: gpName || undefined,
|
||||
general_practitioner_agb: gpAgb || undefined,
|
||||
active: fhir.active ?? true,
|
||||
status: (statusExtension?.valueCode as any) || 'planned',
|
||||
is_john_doe: johnDoeExtension?.valueBoolean || false,
|
||||
insurance_company: insuranceCompany || undefined,
|
||||
insurance_number: insuranceNumber || undefined,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user