diff --git a/app/epd/patients/[id]/diagnose/actions.ts b/app/epd/patients/[id]/diagnose/actions.ts index 21e1296..31cfcb5 100644 --- a/app/epd/patients/[id]/diagnose/actions.ts +++ b/app/epd/patients/[id]/diagnose/actions.ts @@ -1,9 +1,11 @@ 'use server'; +import { revalidatePath } from 'next/cache'; import { createClient } from '@/lib/auth/server'; import type { Database } from '@/lib/supabase/database.types'; export type Condition = Database['public']['Tables']['conditions']['Row']; +type ClinicalStatus = 'active' | 'recurrence' | 'relapse' | 'inactive' | 'remission' | 'resolved'; export type IntakeInfo = { id: string; @@ -69,3 +71,131 @@ export async function getPatientDiagnoses(patientId: string): Promise { + const supabase = await createClient(); + + const updateData: Record = { + 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('updatePatientDiagnosis error', error); + return { success: false, error: 'Diagnose bijwerken mislukt' }; + } + + revalidatePath(`/epd/patients/${patientId}/diagnose`); + return { success: true }; +} + +export async function deletePatientDiagnosis( + patientId: string, + diagnosisId: string +): Promise<{ success: boolean; error?: string }> { + const supabase = await createClient(); + const { error } = await supabase.from('conditions').delete().eq('id', diagnosisId); + + if (error) { + console.error('deletePatientDiagnosis error', error); + return { success: false, error: 'Diagnose verwijderen mislukt' }; + } + + revalidatePath(`/epd/patients/${patientId}/diagnose`); + return { success: true }; +} diff --git a/app/epd/patients/[id]/diagnose/components/diagnosis-detail-form.tsx b/app/epd/patients/[id]/diagnose/components/diagnosis-detail-form.tsx new file mode 100644 index 0000000..7f310a4 --- /dev/null +++ b/app/epd/patients/[id]/diagnose/components/diagnosis-detail-form.tsx @@ -0,0 +1,435 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { useForm } from 'react-hook-form'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { Loader2, Stethoscope, Trash2 } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { Label } from '@/components/ui/label'; +import { Textarea } from '@/components/ui/textarea'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { toast } from '@/hooks/use-toast'; +import { ICD10Combobox } from '@/app/epd/patients/[id]/intakes/[intakeId]/diagnosis/components/icd10-combobox'; +import { + diagnosisSchema, + diagnosisDefaults, + type DiagnosisFormData, + DIAGNOSIS_SEVERITIES, + DIAGNOSIS_TYPES, + DIAGNOSIS_STATUSES, +} from '@/lib/schemas/diagnosis'; +import { + createPatientDiagnosis, + updatePatientDiagnosis, + deletePatientDiagnosis, + type DiagnosisWithIntake, + type IntakeInfo, +} from '../actions'; +import type { ICD10Code } from '@/lib/types/icd10'; + +interface DiagnosisDetailFormProps { + patientId: string; + intakes: IntakeInfo[]; + diagnosis: DiagnosisWithIntake | null; + isNew: boolean; + onSaved: () => void; + onDeleted: () => void; +} + +const STATUS_LABELS: Record = { + active: 'Actief', + remission: 'In remissie', + resolved: 'Opgelost', + inactive: 'Inactief', +}; + +const SEVERITY_LABELS: Record = { + licht: 'Licht', + matig: 'Matig', + ernstig: 'Ernstig', +}; + +const DIAGNOSIS_TYPE_LABELS: Record = { + primary: 'Hoofddiagnose', + secondary: 'Nevendiagnose', +}; + +export function DiagnosisDetailForm({ + patientId, + intakes, + diagnosis, + isNew, + onSaved, + onDeleted, +}: DiagnosisDetailFormProps) { + const [isSubmitting, setIsSubmitting] = useState(false); + const [isDeleting, setIsDeleting] = useState(false); + const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); + const [selectedICD10Code, setSelectedICD10Code] = useState(null); + const [selectedIntakeId, setSelectedIntakeId] = useState( + diagnosis?.encounter_id || intakes[0]?.id || '' + ); + + const { + register, + handleSubmit, + formState: { errors }, + reset, + setValue, + watch, + } = useForm({ + resolver: zodResolver(diagnosisSchema), + defaultValues: diagnosisDefaults, + }); + + const diagnosisType = watch('diagnosisType'); + const severity = watch('severity'); + const status = watch('status'); + + // Reset form wanneer diagnosis wijzigt + useEffect(() => { + if (diagnosis) { + setValue('code', diagnosis.code_code || ''); + setValue('description', diagnosis.code_display || ''); + setValue('severity', (diagnosis.severity_display as 'licht' | 'matig' | 'ernstig') || 'matig'); + setValue('status', (diagnosis.clinical_status as 'active' | 'remission' | 'resolved' | 'inactive') || 'active'); + setValue('diagnosisType', diagnosis.category === 'primary-diagnosis' ? 'primary' : 'secondary'); + setValue('notes', diagnosis.note || ''); + + if (diagnosis.code_code && diagnosis.code_display) { + setSelectedICD10Code({ + code: diagnosis.code_code, + display: diagnosis.code_display, + keywords: [], + }); + } + setSelectedIntakeId(diagnosis.encounter_id || intakes[0]?.id || ''); + } else { + reset(diagnosisDefaults); + setSelectedICD10Code(null); + setSelectedIntakeId(intakes[0]?.id || ''); + } + setShowDeleteConfirm(false); + }, [diagnosis, reset, setValue, intakes]); + + const handleICD10Select = (code: ICD10Code) => { + setSelectedICD10Code(code); + setValue('code', code.code); + setValue('description', code.display); + }; + + const onSubmit = async (data: DiagnosisFormData) => { + if (!selectedIntakeId) { + toast({ + variant: 'destructive', + title: 'Intake vereist', + description: 'Selecteer een intake om de diagnose aan te koppelen.', + }); + return; + } + + setIsSubmitting(true); + + try { + if (isNew) { + await createPatientDiagnosis({ + patientId, + intakeId: selectedIntakeId, + code: data.code, + description: data.description, + severity: data.severity, + status: data.status, + notes: data.notes || undefined, + diagnosisType: data.diagnosisType, + }); + + toast({ + title: 'Diagnose toegevoegd', + description: `${data.code} — ${data.description}`, + }); + } else if (diagnosis) { + const result = await updatePatientDiagnosis(patientId, diagnosis.id, { + code: data.code, + description: data.description, + severity: data.severity, + status: data.status, + notes: data.notes || undefined, + diagnosisType: data.diagnosisType, + }); + + if (!result.success) { + toast({ + variant: 'destructive', + title: 'Bijwerken mislukt', + description: result.error || 'Er ging iets mis.', + }); + return; + } + + toast({ + title: 'Diagnose bijgewerkt', + description: `${data.code} — ${data.description}`, + }); + } + + onSaved(); + } catch (error) { + toast({ + variant: 'destructive', + title: 'Opslaan mislukt', + description: error instanceof Error ? error.message : 'Er ging iets mis.', + }); + } finally { + setIsSubmitting(false); + } + }; + + const handleDelete = async () => { + if (!diagnosis) return; + + setIsDeleting(true); + + try { + const result = await deletePatientDiagnosis(patientId, diagnosis.id); + + if (!result.success) { + toast({ + variant: 'destructive', + title: 'Verwijderen mislukt', + description: result.error || 'Er ging iets mis.', + }); + return; + } + + toast({ + title: 'Diagnose verwijderd', + description: `${diagnosis.code_code} is verwijderd.`, + }); + + onDeleted(); + } catch (error) { + toast({ + variant: 'destructive', + title: 'Verwijderen mislukt', + description: error instanceof Error ? error.message : 'Er ging iets mis.', + }); + } finally { + setIsDeleting(false); + setShowDeleteConfirm(false); + } + }; + + // Empty state + if (!isNew && !diagnosis) { + return ( +
+
+ +
+

Geen diagnose geselecteerd

+

+ Selecteer een diagnose uit de lijst of voeg een nieuwe toe. +

+
+ ); + } + + const selectedIntake = intakes.find((i) => i.id === selectedIntakeId); + + return ( +
+ {/* Header */} +
+

+ {isNew ? 'Nieuwe diagnose' : 'Diagnose bewerken'} +

+ {!isNew && diagnosis && ( +

+ Gekoppeld aan: {diagnosis.intake?.title || diagnosis.intake?.department || 'Intake'} +

+ )} +
+ + {/* Intake selectie (alleen bij nieuwe diagnose) */} + {isNew && intakes.length > 0 && ( +
+ + +
+ )} + + {/* ICD-10 Code */} +
+ + + {errors.code &&

{errors.code.message}

} + {errors.description &&

{errors.description.message}

} +
+ + {/* Ernst en Type */} +
+
+ + + {errors.severity &&

{errors.severity.message}

} +
+ +
+ +
+ {DIAGNOSIS_TYPES.map((type) => ( + + ))} +
+ {errors.diagnosisType &&

{errors.diagnosisType.message}

} +
+
+ + {/* Status */} +
+ + + {errors.status &&

{errors.status.message}

} +
+ + {/* Onderbouwing */} +
+ +