88 lines
2.7 KiB
TypeScript
88 lines
2.7 KiB
TypeScript
'use client';
|
|
|
|
import { Search } from 'lucide-react';
|
|
import { Button } from '@/components/ui/common/Button';
|
|
import { Input } from '@/components/ui/common/Input';
|
|
import type { Patient } from '@/types/patient';
|
|
|
|
interface AppointmentsPatientSearchProps {
|
|
search: string;
|
|
onSearchChange: (value: string) => void;
|
|
patients: Patient[];
|
|
selectedPatientId?: string;
|
|
onSelectPatient: (patient: Patient) => void;
|
|
loading?: boolean;
|
|
canAddPatient: boolean;
|
|
onAddPatient: () => void;
|
|
}
|
|
|
|
export function AppointmentsPatientSearch({
|
|
search,
|
|
onSearchChange,
|
|
patients,
|
|
selectedPatientId,
|
|
onSelectPatient,
|
|
loading = false,
|
|
canAddPatient,
|
|
onAddPatient,
|
|
}: AppointmentsPatientSearchProps) {
|
|
const trimmed = search.trim();
|
|
const showAddForEmptyResults =
|
|
trimmed.length > 0 && !loading && patients.length === 0;
|
|
|
|
return (
|
|
<div className="surface-card p-4 space-y-4">
|
|
<div className="flex flex-col sm:flex-row gap-3 sm:items-center">
|
|
<div className="flex-1">
|
|
<Input
|
|
placeholder="Search existing patients"
|
|
value={search}
|
|
onChange={(e) => onSearchChange(e.target.value)}
|
|
icon={<Search className="h-4 w-4 icon-flat" />}
|
|
/>
|
|
</div>
|
|
{showAddForEmptyResults && (
|
|
<Button
|
|
type="button"
|
|
variant="primary"
|
|
disabled={!canAddPatient}
|
|
onClick={onAddPatient}
|
|
title={!canAddPatient ? 'You do not have permission to add patients.' : undefined}
|
|
>
|
|
+ Add New Patient
|
|
</Button>
|
|
)}
|
|
</div>
|
|
|
|
<div className="space-y-2 max-h-72 overflow-y-auto">
|
|
{loading && <p className="text-sm text-text-muted">Searching…</p>}
|
|
|
|
{!loading && trimmed.length === 0 && (
|
|
<p className="text-sm text-text-muted">Type to search patients by name, phone, or email.</p>
|
|
)}
|
|
|
|
{patients.map((patient) => {
|
|
const isSelected = selectedPatientId === patient.id;
|
|
return (
|
|
<button
|
|
key={patient.id}
|
|
type="button"
|
|
onClick={() => onSelectPatient(patient)}
|
|
className={`w-full text-left rounded-[var(--radius-sm)] border px-3 py-2 transition-colors ${
|
|
isSelected
|
|
? 'bg-primary-soft border-primary/60'
|
|
: 'border-border/60 hover:bg-background-card/70'
|
|
}`}
|
|
>
|
|
<p className="text-sm font-medium text-text-primary">
|
|
{patient.firstName} {patient.lastName}
|
|
</p>
|
|
<p className="text-xs text-text-muted">{patient.phone || patient.email || 'No contact'}</p>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|