feat(diagnose+agenda): Diagnose module met ICD-10 en agenda uitbreidingen

Diagnose Module:
- Diagnose overzicht pagina met alle patiënt diagnoses
- Diagnosis manager met ICD-10 combobox zoekfunctie
- Diagnose kaarten met hoofddiagnose markering
- Modal voor nieuwe/bewerkte diagnoses
- ICD-10 GGZ codes dataset (lib/data/)
- Zod schemas voor diagnose validatie
- TypeScript types voor ICD-10 (lib/types/icd10.ts)
- Complete documentatie (PRD, FO, TO, Bouwplan)

Agenda Uitbreidingen:
- Patient context card in afspraak modal
- Rapportage composer direct in afspraak modal
- Rapportage bewerken vanuit gekoppelde rapportages
- Verbeterde focus styling voor inputs

Behandelplan:
- Flat componenten structuur (behandeldoel-card, form, planning)
- Context header component
- Uitgebreide types (lib/types/behandelplan.ts)
- Actions voor behandelplan beheer

UI Componenten:
- Command component (shadcn/ui) voor combobox
- Popover component (shadcn/ui)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
colinislit
2025-12-12 13:29:59 +01:00
parent 593bef4dcf
commit 265d3a971f
36 changed files with 6663 additions and 236 deletions

View File

@@ -312,14 +312,17 @@ export async function getDiagnoses(intakeId: string) {
return data || [];
}
type ClinicalStatus = 'active' | 'recurrence' | 'relapse' | 'inactive' | 'remission' | 'resolved';
export interface DiagnosisPayload {
patientId: string;
intakeId: string;
code: string;
description: string;
severity?: string;
status?: string;
status?: ClinicalStatus;
notes?: string;
diagnosisType?: 'primary' | 'secondary';
}
export async function createDiagnosis(payload: DiagnosisPayload) {
@@ -329,26 +332,98 @@ export async function createDiagnosis(payload: DiagnosisPayload) {
encounter_id: payload.intakeId,
code_code: payload.code,
code_display: payload.description,
code_system: 'DSM-5',
clinical_status: 'active',
code_system: 'ICD-10',
clinical_status: payload.status || 'active',
severity_display: payload.severity || null,
category: payload.diagnosisType === 'primary' ? 'primary-diagnosis' : 'encounter-diagnosis',
note: payload.notes,
recorded_date: new Date().toISOString(),
});
if (error) {
console.error('createDiagnosis error', error);
throw new Error(error.message);
throw new Error('Diagnose opslaan mislukt');
}
revalidatePath(buildPath(payload.patientId, payload.intakeId, 'diagnosis'));
revalidatePath(buildPath(payload.patientId, payload.intakeId));
}
export interface DiagnosisUpdatePayload {
code?: string;
description?: string;
severity?: string;
status?: string;
notes?: string;
diagnosisType?: 'primary' | 'secondary';
}
export async function updateDiagnosis(
diagnosisId: string,
payload: DiagnosisUpdatePayload
): Promise<{ success: boolean; error?: string }> {
const supabase = await getSupabase();
// Haal eerst de diagnosis op om patientId en intakeId te krijgen voor revalidatie
const { data: diagnosis, error: fetchError } = await supabase
.from('conditions')
.select('patient_id, encounter_id')
.eq('id', diagnosisId)
.single();
if (fetchError || !diagnosis) {
console.error('updateDiagnosis fetch error', fetchError);
return { success: false, error: 'Diagnose niet gevonden' };
}
const updateData: Record<string, unknown> = {
updated_at: new Date().toISOString(),
};
if (payload.code !== undefined) {
updateData.code_code = payload.code;
}
if (payload.description !== undefined) {
updateData.code_display = payload.description;
}
if (payload.status !== undefined) {
updateData.clinical_status = payload.status;
}
if (payload.severity !== undefined) {
updateData.severity_display = payload.severity;
}
if (payload.notes !== undefined) {
updateData.note = payload.notes;
}
if (payload.diagnosisType !== undefined) {
updateData.category = payload.diagnosisType === 'primary' ? 'primary-diagnosis' : 'encounter-diagnosis';
}
const { error } = await supabase
.from('conditions')
.update(updateData)
.eq('id', diagnosisId);
if (error) {
console.error('updateDiagnosis error', error);
return { success: false, error: 'Diagnose bijwerken mislukt' };
}
// Revalidate paths met correcte patientId en intakeId
const patientId = diagnosis.patient_id;
const intakeId = diagnosis.encounter_id;
if (patientId && intakeId) {
revalidatePath(buildPath(patientId, intakeId, 'diagnosis'));
revalidatePath(buildPath(patientId, intakeId));
}
return { success: true };
}
export async function deleteDiagnosis(patientId: string, intakeId: string, diagnosisId: string) {
const supabase = await getSupabase();
const { error } = await supabase.from('conditions').delete().eq('id', diagnosisId);
if (error) {
console.error('deleteDiagnosis error', error);
throw new Error(error.message);
throw new Error('Diagnose verwijderen mislukt');
}
revalidatePath(buildPath(patientId, intakeId, 'diagnosis'));
revalidatePath(buildPath(patientId, intakeId));