2025-10-07 14:53:47 -03:00

191 lines
6.6 KiB
TypeScript

import React from "react";
import { AvatarInitials } from "../AvatarInitials";
export interface PatientListItem {
id: string;
nome: string;
cpf?: string;
email?: string;
telefoneFormatado?: string; // já formatado externamente
convenio?: string | null;
vip?: boolean;
cidade?: string;
estado?: string;
// placeholders a serem preenchidos quando consultasService estiver pronto
ultimoAtendimento?: string | null; // ISO ou texto humanizado
proximoAtendimento?: string | null;
}
interface PatientListTableProps {
pacientes: PatientListItem[];
onEdit: (paciente: PatientListItem) => void;
onDelete: (paciente: PatientListItem) => void;
onView?: (paciente: PatientListItem) => void;
onSchedule?: (paciente: PatientListItem) => void;
emptyMessage?: string;
}
const PatientListTable: React.FC<PatientListTableProps> = ({
pacientes,
onEdit,
onDelete,
onView,
onSchedule,
emptyMessage = "Nenhum paciente encontrado.",
}) => {
return (
<div
className="overflow-x-auto"
role="region"
aria-label="Lista de pacientes"
>
<table
className="min-w-full divide-y divide-gray-200 dark:divide-gray-700"
role="table"
>
<thead className="bg-gray-50 dark:bg-gray-800" role="rowgroup">
<tr>
<th
scope="col"
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"
>
Paciente
</th>
<th
scope="col"
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"
>
Contato
</th>
<th
scope="col"
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"
>
Local
</th>
<th
scope="col"
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"
>
Último Atendimento
</th>
<th
scope="col"
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"
>
Próximo Atendimento
</th>
<th
scope="col"
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"
>
Convênio
</th>
<th
scope="col"
className="px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"
>
Ações
</th>
</tr>
</thead>
<tbody
className="bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700"
role="rowgroup"
>
{pacientes.map((p) => (
<tr
key={p.id}
className="hover:bg-gray-50 dark:hover:bg-gray-800"
role="row"
>
<td className="px-6 py-4">
<div className="flex items-start gap-3">
<AvatarInitials name={p.nome} size={40} />
<div>
<div
className="text-sm font-medium text-gray-900 dark:text-gray-100 cursor-pointer hover:underline"
onClick={() => onView?.(p)}
>
{p.nome || "Sem nome"}
</div>
<div className="text-sm text-gray-500 dark:text-gray-400">
{p.cpf || "CPF não informado"}
</div>
{p.vip && (
<div
className="mt-2 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-800 dark:bg-yellow-200 dark:text-yellow-900"
aria-label="Paciente VIP"
>
VIP
</div>
)}
</div>
</div>
</td>
<td className="px-6 py-4 text-sm">
<div className="text-gray-900 dark:text-gray-100">
{p.email || "Não informado"}
</div>
<div className="text-gray-500 dark:text-gray-400">
{p.telefoneFormatado || "Telefone não informado"}
</div>
</td>
<td className="px-6 py-4 text-sm text-gray-500 dark:text-gray-400">
{p.cidade || p.estado
? `${p.cidade || ""}${p.cidade && p.estado ? "/" : ""}${
p.estado || ""
}`
: "—"}
</td>
<td className="px-6 py-4 text-sm text-gray-500 dark:text-gray-400">
{p.ultimoAtendimento || "—"}
</td>
<td className="px-6 py-4 text-sm text-gray-500 dark:text-gray-400">
{p.proximoAtendimento || "—"}
</td>
<td className="px-6 py-4 text-sm text-gray-500 dark:text-gray-400">
{p.convenio || "Particular"}
</td>
<td className="px-6 py-4 text-right text-sm font-medium space-x-3">
{onSchedule && (
<button
onClick={() => onSchedule(p)}
className="text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300"
>
Agendar
</button>
)}
<button
onClick={() => onEdit(p)}
className="text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300"
>
Editar
</button>
<button
onClick={() => onDelete(p)}
className="text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300"
>
Excluir
</button>
</td>
</tr>
))}
{pacientes.length === 0 && (
<tr>
<td
colSpan={7}
className="px-6 py-10 text-center text-sm text-gray-500 dark:text-gray-400"
>
{emptyMessage}
</td>
</tr>
)}
</tbody>
</table>
</div>
);
};
export default PatientListTable;