'use client'; /** * usePatientSelection Hook * * Handles patient selection flow: fetch FHIR data, map to DB format, update store. * Extracted from ZoekenBlock for DRY compliance. * * Epic: E0.S4 (Patient Selectie - Refactor) */ import { useState, useCallback } from 'react'; import { useToast } from '@/hooks/use-toast'; import { useCortexStore } from '@/stores/cortex-store'; import { safeFetch, getErrorInfo } from '@/lib/cortex/error-handler'; import { mapFhirToDbPatient, type Patient } from '@/lib/fhir/patient-mapper'; import type { PatientSearchResult } from './use-patient-search'; interface UsePatientSelectionOptions { /** Callback after successful selection */ onSuccess?: (patient: Patient, patientName: string) => void; /** Callback on error */ onError?: (error: Error) => void; /** Add to recent actions (default: true) */ trackRecentAction?: boolean; /** Show toast on success (default: true) */ showSuccessToast?: boolean; } interface UsePatientSelectionReturn { /** Select a patient by search result */ selectPatient: (patient: PatientSearchResult) => Promise; /** Whether a selection is in progress */ isSelecting: boolean; /** ID of the patient currently being selected */ selectedId: string | null; /** Clear selection state */ clearSelection: () => void; } export function usePatientSelection( options: UsePatientSelectionOptions = {} ): UsePatientSelectionReturn { const { onSuccess, onError, trackRecentAction = true, showSuccessToast = true, } = options; const [isSelecting, setIsSelecting] = useState(false); const [selectedId, setSelectedId] = useState(null); const { toast } = useToast(); const { setActivePatient, addRecentAction } = useCortexStore(); const selectPatient = useCallback( async (patient: PatientSearchResult): Promise => { setIsSelecting(true); setSelectedId(patient.id); try { // Fetch full FHIR patient data const response = await safeFetch( `/api/fhir/Patient/${patient.id}`, undefined, { operation: 'Patient data ophalen' } ); const fhirPatient = await response.json(); // Map to DB format const dbPatient = mapFhirToDbPatient(fhirPatient); // Update store setActivePatient(dbPatient); // Track recent action if (trackRecentAction) { addRecentAction({ intent: 'zoeken', label: `Patient geselecteerd: ${patient.name}`, patientName: patient.name, }); } // Show success toast if (showSuccessToast) { toast({ title: 'Patient geselecteerd', description: `${patient.name} is nu actief`, }); } // Call success callback onSuccess?.(dbPatient, patient.name); return dbPatient; } catch (error) { console.error('Failed to select patient:', error); const errorInfo = getErrorInfo(error, { operation: 'Patient selecteren' }); toast({ variant: 'destructive', title: errorInfo.title, description: errorInfo.description, }); onError?.(error instanceof Error ? error : new Error(String(error))); return null; } finally { setIsSelecting(false); setSelectedId(null); } }, [setActivePatient, addRecentAction, toast, trackRecentAction, showSuccessToast, onSuccess, onError] ); const clearSelection = useCallback(() => { setIsSelecting(false); setSelectedId(null); }, []); return { selectPatient, isSelecting, selectedId, clearSelection, }; }