'use client'; /** * PatientSidebar Component * * Collapsible overlay sidebar for quick patient selection. * Features search and recent patients list. * * Epic: E1.S2 (Patient Selectie - Sidebar) */ import { useEffect, useRef } from 'react'; import { X, Search, Clock, Users } from 'lucide-react'; import { useCortexStore } from '@/stores/cortex-store'; import { usePatientSearch, type PatientSearchResult } from '@/lib/cortex/hooks/use-patient-search'; import { usePatientSelection } from '@/lib/cortex/hooks/use-patient-selection'; import { PatientListItem, PatientListEmpty, PatientListLoading, } from '@/components/cortex/shared/patient-list-item'; import { Input } from '@/components/ui/input'; export function PatientSidebar() { const { patientSidebarOpen, togglePatientSidebar, setPatientSidebarOpen, recentPatients, addRecentPatient, } = useCortexStore(); const { query, setQuery, results, isSearching, clearResults } = usePatientSearch({ debounceMs: 200, limit: 5, }); const { selectPatient, isSelecting, selectedId } = usePatientSelection({ onSuccess: (patient) => { // Add to recent patients and close sidebar addRecentPatient(patient); setPatientSidebarOpen(false); clearResults(); }, showSuccessToast: true, }); const inputRef = useRef(null); // Focus input when sidebar opens useEffect(() => { if (patientSidebarOpen) { // Small delay to ensure DOM is ready const timer = setTimeout(() => { inputRef.current?.focus(); }, 100); return () => clearTimeout(timer); } }, [patientSidebarOpen]); // Close on Escape key useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape' && patientSidebarOpen) { e.preventDefault(); setPatientSidebarOpen(false); clearResults(); } }; document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); }, [patientSidebarOpen, setPatientSidebarOpen, clearResults]); // Don't render if closed if (!patientSidebarOpen) return null; const showResults = query.length >= 2; const showRecent = !showResults && recentPatients.length > 0; // Map DB patient to search result format for PatientListItem const mapPatientToSearchResult = (patient: typeof recentPatients[0]): PatientSearchResult => ({ id: patient.id, name: `${patient.name_given?.[0] || ''} ${patient.name_family || ''}`.trim() || 'Onbekend', birthDate: patient.birth_date || '', identifier_bsn: patient.identifier_bsn || undefined, identifier_client_number: patient.identifier_client_number || undefined, matchScore: 1, }); const handleBackdropClick = () => { setPatientSidebarOpen(false); clearResults(); }; return ( <> {/* Backdrop */}