"use client"; import { useEffect, useState, useCallback } from "react"; import Link from "next/link"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { Eye, Edit, Calendar, Trash2, Loader2, MoreVertical } from "lucide-react"; import { api } from "@/services/api.mjs"; import { PatientDetailsModal } from "@/components/ui/patient-details-modal"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Button } from "@/components/ui/button"; import Sidebar from "@/components/Sidebar"; interface Paciente { id: string; nome: string; telefone: string; cidade: string; estado: string; ultimoAtendimento?: string; proximoAtendimento?: string; email?: string; birth_date?: string; cpf?: string; blood_type?: string; weight_kg?: number; height_m?: number; street?: string; number?: string; complement?: string; neighborhood?: string; cep?: string; } export default function PacientesPage() { const [pacientes, setPacientes] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [selectedPatient, setSelectedPatient] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); // --- Lógica de Paginação INÍCIO --- const [itemsPerPage, setItemsPerPage] = useState(5); const [currentPage, setCurrentPage] = useState(1); const totalPages = Math.ceil(pacientes.length / itemsPerPage); const indexOfLastItem = currentPage * itemsPerPage; const indexOfFirstItem = indexOfLastItem - itemsPerPage; const currentItems = pacientes.slice(indexOfFirstItem, indexOfLastItem); const paginate = (pageNumber: number) => setCurrentPage(pageNumber); // Funções de Navegação const goToPrevPage = () => { setCurrentPage((prev) => Math.max(1, prev - 1)); }; const goToNextPage = () => { setCurrentPage((prev) => Math.min(totalPages, prev + 1)); }; // Lógica para gerar os números das páginas visíveis (máximo de 5) const getVisiblePageNumbers = (totalPages: number, currentPage: number) => { const pages: number[] = []; const maxVisiblePages = 5; const halfRange = Math.floor(maxVisiblePages / 2); let startPage = Math.max(1, currentPage - halfRange); let endPage = Math.min(totalPages, currentPage + halfRange); if (endPage - startPage + 1 < maxVisiblePages) { if (endPage === totalPages) { startPage = Math.max(1, totalPages - maxVisiblePages + 1); } if (startPage === 1) { endPage = Math.min(totalPages, maxVisiblePages); } } for (let i = startPage; i <= endPage; i++) { pages.push(i); } return pages; }; const visiblePageNumbers = getVisiblePageNumbers(totalPages, currentPage); // Lógica para mudar itens por página, resetando para a página 1 const handleItemsPerPageChange = (value: string) => { setItemsPerPage(Number(value)); setCurrentPage(1); }; // --- Lógica de Paginação FIM --- const handleOpenModal = (patient: Paciente) => { setSelectedPatient(patient); setIsModalOpen(true); }; const handleCloseModal = () => { setSelectedPatient(null); setIsModalOpen(false); }; const formatDate = (dateString: string | null | undefined) => { if (!dateString) return "N/A"; try { const date = new Date(dateString); return new Intl.DateTimeFormat("pt-BR").format(date); } catch (e) { return dateString; // Retorna o string original se o formato for inválido } }; const fetchPacientes = useCallback(async () => { try { setLoading(true); setError(null); const json = await api.get("/rest/v1/patients"); const items = Array.isArray(json) ? json : Array.isArray(json?.data) ? json.data : []; const mapped: Paciente[] = items.map((p: any) => ({ id: String(p.id ?? ""), nome: p.full_name ?? "—", telefone: p.phone_mobile ?? "N/A", cidade: p.city ?? "N/A", estado: p.state ?? "N/A", ultimoAtendimento: formatDate(p.created_at), proximoAtendimento: "N/A", // Necessita de lógica de agendamento real email: p.email ?? "N/A", birth_date: p.birth_date ?? "N/A", cpf: p.cpf ?? "N/A", blood_type: p.blood_type ?? "N/A", weight_kg: p.weight_kg ?? 0, height_m: p.height_m ?? 0, street: p.street ?? "N/A", number: p.number ?? "N/A", complement: p.complement ?? "N/A", neighborhood: p.neighborhood ?? "N/A", cep: p.cep ?? "N/A", })); setPacientes(mapped); setCurrentPage(1); // Resetar a página ao carregar novos dados } catch (e: any) { console.error("Erro ao carregar pacientes:", e); setError(e?.message || "Erro ao carregar pacientes"); } finally { setLoading(false); } }, []); useEffect(() => { fetchPacientes(); }, [fetchPacientes]); return (
{/* Cabeçalho */}
{/* Ajustado para flex-col em telas pequenas */}

Pacientes

Lista de pacientes vinculados

{/* Controles de filtro e novo paciente */} {/* Alterado para que o Select e o Link ocupem a largura total em telas pequenas e fiquem lado a lado em telas maiores */}
{/* Tabela para Telas Médias e Grandes */}
{/* Esconde em telas pequenas */} {loading ? ( ) : error ? ( ) : pacientes.length === 0 ? ( ) : ( currentItems.map((p) => ( )) )}
Nome Telefone Cidade Estado Último atendimento Próximo atendimento Ações
Carregando pacientes...
{`Erro: ${error}`}
Nenhum paciente encontrado
{p.nome} {p.telefone} {p.cidade} {p.estado} {p.ultimoAtendimento} {p.proximoAtendimento} handleOpenModal(p)}> Ver detalhes Laudos {/* alert(`Agenda para paciente ID: ${p.id}`)}> Ver agenda */} {/* { const newPacientes = pacientes.filter((pac) => pac.id !== p.id); setPacientes(newPacientes); alert(`Paciente ID: ${p.id} excluído`); }} className="text-red-600 focus:bg-red-50 focus:text-red-600" > Excluir */}
{/* Layout em Cards/Lista para Telas Pequenas */}
{/* Visível apenas em telas pequenas */} {loading ? (
Carregando pacientes...
) : error ? (
{`Erro: ${error}`}
) : pacientes.length === 0 ? (
Nenhum paciente encontrado
) : ( currentItems.map((p) => (
{/* Adicionado padding à direita */}
{/* Aumentado a fonte e break-words para evitar corte do nome */} {p.nome || "—"}
{/* Removido o 'truncate' e adicionado 'break-words' no telefone */}
Telefone: **{p.telefone || "N/A"}**
handleOpenModal(p)}> Ver detalhes Laudos alert(`Agenda para paciente ID: ${p.id}`)}> Ver agenda { const newPacientes = pacientes.filter((pac) => pac.id !== p.id); setPacientes(newPacientes); alert(`Paciente ID: ${p.id} excluído`); }} className="text-red-600 focus:bg-red-50 focus:text-red-600" > Excluir
)) )}
{/* Paginação */} {totalPages > 1 && (
{/* Botão Anterior */} {/* Números das Páginas */} {visiblePageNumbers.map((number) => ( ))} {/* Botão Próximo */}
)}
); }