import { useMemo, useState } from 'react'; import { useNavigate } from 'react-router'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faUser, faMagnifyingGlass, faEye, faCommentDots, faMessageDots, faSidebarFlip, faSidebar } from '@fortawesome/pro-duotone-svg-icons'; import { faIcon } from '@/lib/icon-wrapper'; const SearchLg = faIcon(faMagnifyingGlass); import { Avatar } from '@/components/base/avatar/avatar'; import { Badge } from '@/components/base/badges/badges'; // Button removed — actions are icon-only now import { Input } from '@/components/base/input/input'; import { Table, TableCard } from '@/components/application/table/table'; import { PaginationPageDefault } from '@/components/application/pagination/pagination'; import { TopBar } from '@/components/layout/top-bar'; import { ClickToCallButton } from '@/components/call-desk/click-to-call-button'; import { PatientProfilePanel } from '@/components/shared/patient-profile-panel'; import { useData } from '@/providers/data-provider'; import { getInitials } from '@/lib/format'; import { cx } from '@/utils/cx'; import type { Patient } from '@/types/entities'; const computeAge = (dateOfBirth: string | null): number | null => { if (!dateOfBirth) return null; const dob = new Date(dateOfBirth); const today = new Date(); let age = today.getFullYear() - dob.getFullYear(); const monthDiff = today.getMonth() - dob.getMonth(); if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < dob.getDate())) { age--; } return age; }; const formatGender = (gender: string | null): string => { if (!gender) return ''; switch (gender) { case 'MALE': return 'M'; case 'FEMALE': return 'F'; case 'OTHER': return 'O'; default: return ''; } }; const getPatientDisplayName = (patient: Patient): string => { if (patient.fullName) { return `${patient.fullName.firstName} ${patient.fullName.lastName}`.trim(); } return 'Unknown'; }; const getPatientPhone = (patient: Patient): string => { return patient.phones?.primaryPhoneNumber ?? ''; }; const getPatientEmail = (patient: Patient): string => { return patient.emails?.primaryEmail ?? ''; }; export const PatientsPage = () => { const { patients, loading } = useData(); const navigate = useNavigate(); const [searchQuery, setSearchQuery] = useState(''); const [selectedPatient, setSelectedPatient] = useState(null); const [panelOpen, setPanelOpen] = useState(false); const [currentPage, setCurrentPage] = useState(1); const PAGE_SIZE = 15; const filteredPatients = useMemo(() => { return patients.filter((patient) => { if (searchQuery.trim()) { const query = searchQuery.trim().toLowerCase(); const name = getPatientDisplayName(patient).toLowerCase(); const phone = getPatientPhone(patient).toLowerCase(); const email = getPatientEmail(patient).toLowerCase(); if (!name.includes(query) && !phone.includes(query) && !email.includes(query)) { return false; } } return true; }); }, [patients, searchQuery]); const totalPages = Math.max(1, Math.ceil(filteredPatients.length / PAGE_SIZE)); const pagedPatients = filteredPatients.slice((currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE); const handleSearch = (val: string) => { setSearchQuery(val); setCurrentPage(1); }; return (
} /> {loading ? (

Loading patients...

) : filteredPatients.length === 0 ? (

No patients found

{searchQuery ? 'Try adjusting your search.' : 'No patient records available yet.'}

) : ( {(patient) => { const displayName = getPatientDisplayName(patient); const age = computeAge(patient.dateOfBirth); const gender = formatGender(patient.gender); const phone = getPatientPhone(patient); const email = getPatientEmail(patient); const initials = patient.fullName ? getInitials(patient.fullName.firstName, patient.fullName.lastName) : '?'; return ( { setSelectedPatient(patient); setPanelOpen(true); }} > {/* Patient name + avatar */}
{displayName} {(age !== null || gender) && ( {[ age !== null ? `${age}y` : null, gender || null, ].filter(Boolean).join(' / ')} )}
{/* Contact */}
{phone ? ( {phone} ) : ( No phone )} {email ? ( {email} ) : null}
{/* Type */} {patient.patientType ? ( {patient.patientType} ) : ( )} {/* Gender */} {patient.gender ? patient.gender.charAt(0) + patient.gender.slice(1).toLowerCase() : '—'} {/* Age */} {age !== null ? `${age} yrs` : '—'} {/* Actions */}
{phone && ( <> )}
); }}
)} {totalPages > 1 && (
)}
{/* Patient Profile Panel - collapsible with smooth transition */}
{panelOpen && (

Patient Profile

)}
); };