import { useState, useEffect } from "react"; import toast from "react-hot-toast"; import { Search, Plus, Eye, Edit, Trash2 } from "lucide-react"; import { appointmentService, type Appointment, patientService, type Patient, doctorService, type Doctor, } from "../../services"; import { Avatar } from "../ui/Avatar"; interface AppointmentWithDetails extends Appointment { patient?: Patient; doctor?: Doctor; } export function SecretaryAppointmentList() { const [appointments, setAppointments] = useState( [] ); const [loading, setLoading] = useState(false); const [searchTerm, setSearchTerm] = useState(""); const [statusFilter, setStatusFilter] = useState("Todos"); const [typeFilter, setTypeFilter] = useState("Todos"); const [showCreateModal, setShowCreateModal] = useState(false); const [patients, setPatients] = useState([]); const [doctors, setDoctors] = useState([]); const [formData, setFormData] = useState({ patient_id: "", doctor_id: "", scheduled_at: "", appointment_type: "presencial", notes: "", }); const loadAppointments = async () => { setLoading(true); try { const data = await appointmentService.list(); // Buscar detalhes de pacientes e médicos const appointmentsWithDetails = await Promise.all( (Array.isArray(data) ? data : []).map(async (appointment) => { try { const [patient, doctor] = await Promise.all([ appointment.patient_id ? patientService.getById(appointment.patient_id) : null, appointment.doctor_id ? doctorService.getById(appointment.doctor_id) : null, ]); return { ...appointment, patient: patient || undefined, doctor: doctor || undefined, }; } catch (error) { console.error("Erro ao carregar detalhes:", error); return appointment; } }) ); setAppointments(appointmentsWithDetails); console.log("✅ Consultas carregadas:", appointmentsWithDetails); } catch (error) { console.error("❌ Erro ao carregar consultas:", error); toast.error("Erro ao carregar consultas"); setAppointments([]); } finally { setLoading(false); } }; useEffect(() => { loadAppointments(); loadDoctorsAndPatients(); }, []); // Função de filtro const filteredAppointments = appointments.filter((appointment) => { // Filtro de busca por nome do paciente ou médico const searchLower = searchTerm.toLowerCase(); const matchesSearch = !searchTerm || appointment.patient?.full_name?.toLowerCase().includes(searchLower) || appointment.doctor?.full_name?.toLowerCase().includes(searchLower) || appointment.order_number?.toString().includes(searchTerm); // Filtro de status const matchesStatus = statusFilter === "Todos" || appointment.status === statusFilter; // Filtro de tipo const matchesType = typeFilter === "Todos" || appointment.appointment_type === typeFilter; return matchesSearch && matchesStatus && matchesType; }); const loadDoctorsAndPatients = async () => { try { const [patientsData, doctorsData] = await Promise.all([ patientService.list(), doctorService.list(), ]); setPatients(Array.isArray(patientsData) ? patientsData : []); setDoctors(Array.isArray(doctorsData) ? doctorsData : []); } catch (error) { console.error("Erro ao carregar pacientes e médicos:", error); } }; const handleOpenCreateModal = () => { setFormData({ patient_id: "", doctor_id: "", scheduled_at: "", appointment_type: "presencial", notes: "", }); setShowCreateModal(true); }; const handleCreateAppointment = async (e: React.FormEvent) => { e.preventDefault(); if (!formData.patient_id || !formData.doctor_id || !formData.scheduled_at) { toast.error("Preencha todos os campos obrigatórios"); return; } try { await appointmentService.create({ patient_id: formData.patient_id, doctor_id: formData.doctor_id, scheduled_at: new Date(formData.scheduled_at).toISOString(), appointment_type: formData.appointment_type as | "presencial" | "telemedicina", }); toast.success("Consulta agendada com sucesso!"); setShowCreateModal(false); loadAppointments(); } catch (error) { console.error("Erro ao criar consulta:", error); toast.error("Erro ao agendar consulta"); } }; const handleSearch = () => { loadAppointments(); }; const handleClear = () => { setSearchTerm(""); setStatusFilter("Todos"); setTypeFilter("Todos"); loadAppointments(); }; const getStatusBadge = (status: string) => { const statusMap: Record = { confirmada: { label: "Confirmada", className: "bg-green-100 text-green-700", }, agendada: { label: "Agendada", className: "bg-blue-100 text-blue-700" }, cancelada: { label: "Cancelada", className: "bg-red-100 text-red-700" }, concluida: { label: "Concluída", className: "bg-gray-100 text-gray-700" }, }; const config = statusMap[status] || { label: status, className: "bg-gray-100 text-gray-700", }; return ( {config.label} ); }; const formatDate = (dateString: string) => { try { const date = new Date(dateString); return date.toLocaleDateString("pt-BR", { day: "2-digit", month: "2-digit", year: "numeric", }); } catch { return "—"; } }; const formatTime = (dateString: string) => { try { const date = new Date(dateString); return date.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit", }); } catch { return "—"; } }; return (
{/* Header */}

Consultas

Gerencie as consultas agendadas

{/* Search and Filters */}
setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-2.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent" />
Status:
Tipo:
{/* Table */}
{loading ? ( ) : filteredAppointments.length === 0 ? ( ) : ( filteredAppointments.map((appointment) => ( )) )}
Paciente Médico Data/Hora Tipo Status Ações
Carregando consultas...
{searchTerm || statusFilter !== "Todos" || typeFilter !== "Todos" ? "Nenhuma consulta encontrada com esses filtros" : "Nenhuma consulta encontrada"}

{appointment.patient?.full_name || "Paciente não encontrado"}

{appointment.patient?.email || "—"}

{appointment.doctor?.full_name || "Médico não encontrado"}

{appointment.doctor?.specialty || "—"}

{appointment.scheduled_at ? ( <>
{formatDate(appointment.scheduled_at)}
{formatTime(appointment.scheduled_at)}
) : ( "—" )}
{appointment.appointment_type === "telemedicina" ? "Telemedicina" : "Presencial"} {getStatusBadge(appointment.status || "agendada")}
{/* Modal de Criar Consulta */} {showCreateModal && (

Nova Consulta

setFormData({ ...formData, scheduled_at: e.target.value }) } className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500" required />
)}
); }