import { useEffect, useMemo, useState } from "react"; import { useNavigate, useParams } from "react-router-dom"; import toast from "react-hot-toast"; import { consultasService, type Consulta } from "../services/consultasService"; import { getPatientById, listPatientAttachments, addPatientAttachment, removePatientAttachment, type Paciente as PacienteServiceModel, type Anexo, } from "../services/pacienteService"; interface ExtendedPacienteMeta { rg?: string; estado_civil?: string; profissao?: string; telefoneSecundario?: string; telefoneReferencia?: string; codigo_legado?: string; responsavel_nome?: string; responsavel_cpf?: string; documentos?: { tipo: string; numero: string }[]; } type TabId = "resumo" | "dados" | "consultas" | "anexos" | "historico"; interface HistoricoItem { id: string; data: string; // ISO campo: string; de?: string; para?: string; usuario?: string; } const ProntuarioPaciente = () => { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const [loading, setLoading] = useState(true); const [paciente, setPaciente] = useState(null); const [meta, setMeta] = useState(null); const [consultas, setConsultas] = useState([]); const [anexos, setAnexos] = useState([]); const [tab, setTab] = useState("resumo"); const [historico, setHistorico] = useState([]); // placeholder local const [uploading, setUploading] = useState(false); // Carregar paciente + meta + consultas + anexos useEffect(() => { let mounted = true; const load = async () => { if (!id) return; setLoading(true); try { const respPaciente = await getPatientById(id); if (!mounted) return; if (respPaciente.success && respPaciente.data) { setPaciente(respPaciente.data); } else { throw new Error(respPaciente.error || "Paciente não encontrado"); } // metadata local try { const raw = localStorage.getItem("pacientes_meta") || "{}"; const parsed = JSON.parse(raw) as Record< string, ExtendedPacienteMeta >; setMeta(parsed[id] || null); } catch { setMeta(null); } // consultas (últimas + futuras limitadas) const respConsultas = await consultasService.listarPorPaciente(id, { limit: 20, }); if (respConsultas.success && respConsultas.data) setConsultas(respConsultas.data); // anexos try { const anexosList = await listPatientAttachments(id); setAnexos(anexosList); } catch { console.warn("Falha ao carregar anexos"); } // histórico (placeholder - poderá ser alimentado quando audit trail existir) const histRaw = localStorage.getItem(`paciente_hist_${id}`) || "[]"; try { setHistorico(JSON.parse(histRaw)); } catch { setHistorico([]); } } catch { toast.error("Paciente não encontrado"); navigate("/painel-secretaria"); } finally { if (mounted) setLoading(false); } }; load(); return () => { mounted = false; }; }, [id, navigate]); const consultasOrdenadas = useMemo(() => { return [...consultas].sort((a, b) => b.dataHora.localeCompare(a.dataHora)); }, [consultas]); const ultimaConsulta = consultasOrdenadas.find(() => true); const proximaConsulta = useMemo(() => { const agora = new Date().toISOString(); return consultasOrdenadas .filter((c) => c.dataHora >= agora) .sort((a, b) => a.dataHora.localeCompare(b.dataHora))[0]; }, [consultasOrdenadas]); const idade = useMemo(() => { if (!paciente?.dataNascimento) return null; const d = new Date(paciente.dataNascimento); if (Number.isNaN(d.getTime())) return null; const diff = Date.now() - d.getTime(); return Math.floor(diff / (1000 * 60 * 60 * 24 * 365.25)); }, [paciente?.dataNascimento]); const handleUpload = async (ev: React.ChangeEvent) => { if (!id) return; const files = ev.target.files; if (!files || files.length === 0) return; setUploading(true); try { for (const file of Array.from(files)) { const anexo = await addPatientAttachment(id, file); setAnexos((a) => [...a, anexo]); } toast.success("Anexo(s) enviado(s) com sucesso"); } catch { toast.error("Falha ao enviar anexo"); } finally { setUploading(false); ev.target.value = ""; // reset } }; const handleRemoveAnexo = async (anexo: Anexo) => { if (!id) return; if (!confirm(`Remover anexo "${anexo.nome || anexo.id}"?`)) return; try { await removePatientAttachment(id, anexo.id); setAnexos((as) => as.filter((a) => a.id !== anexo.id)); toast.success("Anexo removido"); } catch { toast.error("Erro ao remover anexo"); } }; const formatDataHora = (iso?: string) => { if (!iso) return "—"; const d = new Date(iso); if (Number.isNaN(d.getTime())) return iso; return new Intl.DateTimeFormat("pt-BR", { dateStyle: "short", timeStyle: "short", }).format(d); }; const TabButton = ({ id: tabId, label }: { id: TabId; label: string }) => ( ); if (loading) { return (
); } if (!paciente) return null; return (

Prontuário: {paciente.nome}

CPF: {paciente.cpf || "—"} {idade ? `• ${idade} anos` : ""}

{tab === "resumo" && (

Visão Geral

  • Última consulta: {formatDataHora(ultimaConsulta?.dataHora)}
  • Próxima consulta: {formatDataHora(proximaConsulta?.dataHora)}
  • Convênio: {paciente.convenio || "Particular"}
  • VIP: {paciente.vip ? "Sim" : "Não"}
  • Tipo sanguíneo: {paciente.tipoSanguineo || "—"}

Contato

  • Email: {paciente.email || "—"}
  • Telefone: {paciente.telefone || "—"}
  • Endereço:{" "} {paciente.endereco?.rua ? `${paciente.endereco.rua}, ${ paciente.endereco.numero || "s/n" } - ${paciente.endereco.bairro || ""}` : "—"}
  • Cidade/UF: {paciente.endereco?.cidade || ""} {paciente.endereco?.estado ? `/${paciente.endereco.estado}` : ""}
)} {tab === "dados" && (

Dados Completos

RG

{meta?.rg || "—"}

Estado Civil

{meta?.estado_civil || "—"}

Profissão

{meta?.profissao || "—"}

Responsável

{meta?.responsavel_nome || "—"}

Responsável CPF

{meta?.responsavel_cpf || "—"}

Código Legado

{meta?.codigo_legado || "—"}

Documentos Extras

{meta?.documentos && meta.documentos.length > 0 ? (
    {meta.documentos.map((d, idx) => (
  • {d.tipo}: {d.numero}
  • ))}
) : (

)}
)} {tab === "consultas" && (

Consultas

{consultasOrdenadas.length === 0 && (

Nenhuma consulta encontrada.

)}
    {consultasOrdenadas.map((c) => (
  • {formatDataHora(c.dataHora)} {c.tipo && `• ${c.tipo}`}

    Status: {c.status}

  • ))}
)} {tab === "anexos" && (

Anexos

{anexos.length === 0 && (

Nenhum anexo.

)}
    {anexos.map((a) => (
  • {a.nome || a.id}

    {a.tipo || a.categoria || "arquivo"}{" "} {a.tamanho ? `• ${(a.tamanho / 1024).toFixed(1)} KB` : ""}

    {a.url && ( Abrir )}
  • ))}
)} {tab === "historico" && (

Histórico de Alterações (Local)

{historico.length === 0 && (

Nenhum registro ainda.

)}
    {historico.map((item) => (
  • {item.campo} alterado{" "} {item.de ? `de "${item.de}" ` : ""}para "{item.para}"

    {formatDataHora(item.data)}{" "} {item.usuario && `• ${item.usuario}`}

  • ))}
)}
); }; export default ProntuarioPaciente;