import React, { useState, useMemo, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import API_KEY from '../components/utils/apiKeys.js'; import AgendamentoCadastroManager from './AgendamentoCadastroManager.jsx'; import TabelaAgendamentoDia from '../components/AgendarConsulta/TabelaAgendamentoDia'; import TabelaAgendamentoSemana from '../components/AgendarConsulta/TabelaAgendamentoSemana'; import TabelaAgendamentoMes from '../components/AgendarConsulta/TabelaAgendamentoMes'; import FormNovaConsulta from '../components/AgendarConsulta/FormNovaConsulta'; // Importação de endpoints para lógica da Fila de Espera e Médicos (versão main) import { GetPatientByID } from '../components/utils/Functions-Endpoints/Patient.js'; import { GetAllDoctors, GetDoctorByID } from '../components/utils/Functions-Endpoints/Doctor.js'; import { useAuth } from '../components/utils/AuthProvider.js'; // ✨ NOVO: Caminho de importação corrigido com base na sua estrutura de pastas import AgendamentosMes from '../components/AgendarConsulta/DadosConsultasMock.js'; import dayjs from 'dayjs'; import "./style/Agendamento.css"; import './style/FilaEspera.css'; import { Search } from 'lucide-react'; import Spinner from '../components/Spinner.jsx'; const Agendamento = ({ setDictInfo }) => { const navigate = useNavigate(); const [listaTodosAgendamentos, setListaTodosAgendamentos] = useState([]) const [selectedID, setSelectedId] = useState('0') const [filaEsperaData, setFilaEsperaData] = useState([]) const [FiladeEspera, setFiladeEspera] = useState(false); const [tabela, setTabela] = useState('diario'); const [PageNovaConsulta, setPageConsulta] = useState(false); const [searchTerm, setSearchTerm] = useState(''); const [agendamentos, setAgendamentos] = useState() const { getAuthorizationHeader } = useAuth() const [DictAgendamentosOrganizados, setAgendamentosOrganizados] = useState({}) const [showDeleteModal, setShowDeleteModal] = useState(false) const [AgendamentoFiltrado, setAgendamentoFiltrado] = useState() const [ListaDeMedicos, setListaDeMedicos] = useState([]) const [FiltredTodosMedicos, setFiltredTodosMedicos] = useState([]) const [searchTermDoctor, setSearchTermDoctor] = useState(''); const [MedicoFiltrado, setMedicoFiltrado] = useState({ id: "vazio" }) const [cacheAgendamentos, setCacheAgendamentos] = useState([]) const [showConfirmModal, setShowConfirmModal] = useState(false) const [motivoCancelamento, setMotivoCancelamento] = useState("") const [corModal, setCorModal] = useState("") const [listaConsultasID, setListaConsultaID] = useState([]) const [coresConsultas, setCoresConsultas] = useState([]) // Estados para a tabela da fila de espera const [searchTermFila, setSearchTermFila] = useState(''); const [filtroMedicoFila, setFiltroMedicoFila] = useState('Todos'); const [paginaAtualFila, setPaginaAtualFila] = useState(1); const [itensPorPaginaFila, setItensPorPaginaFila] = useState(10); let authHeader = getAuthorizationHeader() const cacheMedicos = {}; const cachePacientes = {}; useMemo(() => { if (!listaTodosAgendamentos.length) return { agendamentosOrganizados: {}, filaEsperaData: [] }; console.log("recarregando") const DictAgendamentosOrganizados = {}; const ListaFilaDeEspera = []; const fetchDados = async () => { for (const agendamento of listaTodosAgendamentos) { if (agendamento.status === "requested") { // Cache de médico e paciente if (!cacheMedicos[agendamento.doctor_id]) { cacheMedicos[agendamento.doctor_id] = await GetDoctorByID(agendamento.doctor_id, authHeader); } if (!cachePacientes[agendamento.patient_id]) { cachePacientes[agendamento.patient_id] = await GetPatientByID(agendamento.patient_id, authHeader); } const medico = cacheMedicos[agendamento.doctor_id]; const paciente = cachePacientes[agendamento.patient_id]; ListaFilaDeEspera.push({ agendamento, Infos: { nome_medico: medico[0]?.full_name, doctor_id: medico[0]?.id, patient_id: paciente[0]?.id, paciente_nome: paciente[0]?.full_name, paciente_cpf: paciente[0]?.cpf, }, }); } else { const DiaAgendamento = agendamento.scheduled_at.split("T")[0]; if (DiaAgendamento in DictAgendamentosOrganizados) { DictAgendamentosOrganizados[DiaAgendamento].push(agendamento); } else { DictAgendamentosOrganizados[DiaAgendamento] = [agendamento]; } } } // Ordenar por data for (const DiaAgendamento in DictAgendamentosOrganizados) { DictAgendamentosOrganizados[DiaAgendamento].sort((a, b) => a.scheduled_at.localeCompare(b.scheduled_at)); } const chavesOrdenadas = Object.keys(DictAgendamentosOrganizados).sort(); const DictAgendamentosFinal = {}; for (const data of chavesOrdenadas) { DictAgendamentosFinal[data] = DictAgendamentosOrganizados[data]; } setAgendamentosOrganizados(DictAgendamentosFinal); setFilaEsperaData(ListaFilaDeEspera); }; fetchDados(); return { agendamentosOrganizados: DictAgendamentosOrganizados, filaEsperaData: ListaFilaDeEspera }; }, [listaTodosAgendamentos]); // 👉 só recalcula quando a lista muda useEffect(() => { var myHeaders = new Headers(); myHeaders.append("Authorization", authHeader); myHeaders.append("apikey", API_KEY) var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?select&doctor_id&patient_id&status&scheduled_at&order&limit&offset", requestOptions) .then(response => response.json()) .then(result => { setListaTodosAgendamentos(result); console.log(result) }) .catch(error => console.log('error', error)); const PegarTodosOsMedicos = async () => { let lista = [] const TodosOsMedicos = await GetAllDoctors(authHeader) for (let d = 0; TodosOsMedicos.length > d; d++) { lista.push({ nomeMedico: TodosOsMedicos[d].full_name, idMedico: TodosOsMedicos[d].id }) } setListaDeMedicos(lista) } PegarTodosOsMedicos() }, []) const deleteConsulta = (selectedPatientId) => { var myHeaders = new Headers(); myHeaders.append("Content-Type", "application/json"); myHeaders.append('apikey', API_KEY) myHeaders.append("authorization", authHeader) var raw = JSON.stringify({ "status": "cancelled", "cancellation_reason": motivoCancelamento }); var requestOptions = { method: 'PATCH', headers: myHeaders, body: raw, redirect: 'follow' }; fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?id=eq.${selectedPatientId}`, requestOptions) .then(response => { if (response.status !== 200) (console.log(response)) }) .then(result => console.log(result)) .catch(error => console.log('error', error)); } const confirmConsulta = (selectedPatientId) => { var myHeaders = new Headers(); myHeaders.append("Content-Type", "application/json"); myHeaders.append('apikey', API_KEY) myHeaders.append("authorization", authHeader) var raw = JSON.stringify({ "status": "confirmed" }); var requestOptions = { method: 'PATCH', headers: myHeaders, body: raw, redirect: 'follow' }; fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?id=eq.${selectedPatientId}`, requestOptions) .then(response => { if (response.status !== 200) (console.log(response)) }) .then(result => console.log(result)) .catch(error => console.log('error', error)); } const filteredAgendamentos = useMemo(() => { if (!searchTerm.trim()) { return AgendamentosMes; } const lowerCaseSearchTerm = searchTerm.toLowerCase(); const filteredData = {}; for (const semana in AgendamentosMes) { filteredData[semana] = {}; for (const dia in AgendamentosMes[semana]) { filteredData[semana][dia] = AgendamentosMes[semana][dia].filter(agendamento => agendamento.status === 'vazio' || (agendamento.paciente && agendamento.paciente.toLowerCase().includes(lowerCaseSearchTerm)) ); } } return filteredData; }, [searchTerm]); const ListarDiasdoMes = (ano, mes) => { let segundas = []; let tercas = []; let quartas = []; let quintas = []; let sextas = [] const base = dayjs(`${ano}-${mes}-01`) const DiasnoMes = base.daysInMonth() for (let d = 1; d <= DiasnoMes; d++) { const data = dayjs(`${ano}-${mes}-${d}`) const dia = data.format('dddd') switch (dia) { case 'Monday': segundas.push(d); break case 'Tuesday': tercas.push(d); break case 'Wednesday': quartas.push(d); break case 'Thursday': quintas.push(d); break case 'Friday': sextas.push(d); break default: break } } let ListaDiasDatas = { segundas: segundas, tercas: tercas, quartas: quartas, quintas: quintas, sextas: sextas } return ListaDiasDatas } const handleClickAgendamento = (agendamento) => { if (agendamento.status !== 'vazio') return else setPageConsulta(true) }; useEffect(() => { console.log("mudou FiltredTodosMedicos:", FiltredTodosMedicos); if (MedicoFiltrado.id != "vazio") { const unicoMedico = MedicoFiltrado; console.log(unicoMedico) const idMedicoFiltrado = unicoMedico.idMedico; console.log(`Médico único encontrado: ${unicoMedico.nomeMedico}. ID: ${idMedicoFiltrado}`); const agendamentosDoMedico = filtrarAgendamentosPorMedico( DictAgendamentosOrganizados, idMedicoFiltrado ); console.log(`Total de agendamentos filtrados para este médico: ${agendamentosDoMedico.length}`); console.log("Lista completa de Agendamentos do Médico:", agendamentosDoMedico); //FiltrarAgendamentos(agendamentosDoMedico) setListaTodosAgendamentos(agendamentosDoMedico) } }, [FiltredTodosMedicos, MedicoFiltrado]); const filtrarAgendamentosPorMedico = (dictAgendamentos, idMedicoFiltrado) => { setCacheAgendamentos(DictAgendamentosOrganizados); const todasAsListasDeAgendamentos = Object.values(dictAgendamentos); const todosOsAgendamentos = todasAsListasDeAgendamentos.flat(); const agendamentosFiltrados = todosOsAgendamentos.filter(agendamento => agendamento.doctor_id === idMedicoFiltrado ); return agendamentosFiltrados; }; const handleSearchMedicos = (term) => { setSearchTermDoctor(term); if (term.trim() === '') { if (MedicoFiltrado.id !== "vazio") { console.log("Medico escolhido, mas vai ser apagado") console.log(cacheAgendamentos, "cache ") } setFiltredTodosMedicos([]); setMedicoFiltrado({ id: "vazio" }) //2 FiltrarAgendamentos() return; } if (FiltredTodosMedicos.length === 1) { setMedicoFiltrado({ ...FiltredTodosMedicos[0] }) } const filtered = ListaDeMedicos.filter(medico => medico.nomeMedico.toLowerCase().includes(term.toLowerCase()) ); setFiltredTodosMedicos(filtered); }; return (

Agendar nova consulta

{!PageNovaConsulta ? (
{/* Bloco de busca por médico */}
handleSearchMedicos(e.target.value)} />
{/* DROPDOWN (RENDERIZAÇÃO CONDICIONAL) */} {searchTermDoctor && FiltredTodosMedicos.length > 0 && (
{FiltredTodosMedicos.map((medico) => (
{ setSearchTermDoctor(medico.nomeMedico); setFiltredTodosMedicos([]); setMedicoFiltrado(medico) }} >

{medico.nomeMedico}

))}
)}
{FiladeEspera === false ? (
Realizado
Confirmado
Agendado
Cancelado
{/* Componentes de Tabela - Adicionado props de delete da main */} {tabela === "diario" && } {tabela === 'semanal' && } {tabela === 'mensal' && }
) : (

Fila de Espera

{/* Filtros */}
Filtros
setSearchTermFila(e.target.value)} /> Digite o nome completo ou número do CPF
setFiltroMedicoFila(e.target.value || 'Todos')} /> Digite o nome do médico para filtrar
{(() => { const filtrados = filaEsperaData.filter((item) => { const buscaNome = item.Infos?.paciente_nome?.toLowerCase().includes(searchTermFila.toLowerCase()); const buscaCPF = item.Infos?.paciente_cpf?.toLowerCase().includes(searchTermFila.toLowerCase()); const passaBusca = searchTermFila === "" || buscaNome || buscaCPF; const passaMedico = filtroMedicoFila === "Todos" || item.Infos?.nome_medico?.toLowerCase().includes(filtroMedicoFila.toLowerCase()); return passaBusca && passaMedico; }); return filtrados.length; })()} DE {filaEsperaData.length} SOLICITAÇÕES ENCONTRADAS
{/* Filtros Ativos */} {(searchTermFila || filtroMedicoFila !== "Todos") && (
Filtros ativos:
{searchTermFila && Busca: "{searchTermFila}"} {filtroMedicoFila !== "Todos" && Médico: {filtroMedicoFila}}
)} {/* Tabela */}
{(() => { // Filtrar dados const filaFiltrada = filaEsperaData.filter((item) => { const buscaNome = item.Infos?.paciente_nome?.toLowerCase().includes(searchTermFila.toLowerCase()); const buscaCPF = item.Infos?.paciente_cpf?.toLowerCase().includes(searchTermFila.toLowerCase()); const passaBusca = searchTermFila === "" || buscaNome || buscaCPF; const passaMedico = filtroMedicoFila === "Todos" || item.Infos?.nome_medico?.toLowerCase().includes(filtroMedicoFila.toLowerCase()); return passaBusca && passaMedico; }); // Paginação const totalPaginasFila = Math.ceil(filaFiltrada.length / itensPorPaginaFila); const indiceInicial = (paginaAtualFila - 1) * itensPorPaginaFila; const indiceFinal = indiceInicial + itensPorPaginaFila; const filaPaginada = filaFiltrada.slice(indiceInicial, indiceFinal); if (filaPaginada.length > 0) { return filaPaginada.map((item, index) => ( )); } else { return ( ); } })()}
Nome do Paciente CPF Médico Solicitado Data da Solicitação Ações
{item.Infos?.paciente_nome}
{item.Infos?.paciente_cpf} {item.Infos?.nome_medico || 'Não informado'} {dayjs(item.agendamento.created_at).format('DD/MM/YYYY HH:mm')}

Nenhuma solicitação encontrada com os filtros aplicados.

{(searchTermFila || filtroMedicoFila !== "Todos") && ( )}
{/* Paginação */} {(() => { const filaFiltrada = filaEsperaData.filter((item) => { const buscaNome = item.Infos?.paciente_nome?.toLowerCase().includes(searchTermFila.toLowerCase()); const buscaCPF = item.Infos?.paciente_cpf?.toLowerCase().includes(searchTermFila.toLowerCase()); const passaBusca = searchTermFila === "" || buscaNome || buscaCPF; const passaMedico = filtroMedicoFila === "Todos" || item.Infos?.nome_medico?.toLowerCase().includes(filtroMedicoFila.toLowerCase()); return passaBusca && passaMedico; }); const totalPaginasFila = Math.ceil(filaFiltrada.length / itensPorPaginaFila); const indiceInicial = (paginaAtualFila - 1) * itensPorPaginaFila; const indiceFinal = indiceInicial + itensPorPaginaFila; if (filaFiltrada.length > 0) { return (
Itens por página:
Página {paginaAtualFila} de {totalPaginasFila} • Mostrando {indiceInicial + 1}-{Math.min(indiceFinal, filaFiltrada.length)} de {filaFiltrada.length} solicitações
); } return null; })()}
) }
) : ( )} {/* Modal de Confirmação de Exclusão */} {showDeleteModal && (
e.target.classList.contains("modal") && setShowDeleteModal(false) } >
Confirmação de Cancelamento

Qual o motivo do cancelamento?