diff --git a/src/PagesMedico/DoctorAgendamentoManager.jsx b/src/PagesMedico/DoctorAgendamentoManager.jsx new file mode 100644 index 0000000..518f5c8 --- /dev/null +++ b/src/PagesMedico/DoctorAgendamentoManager.jsx @@ -0,0 +1,520 @@ +import React, { useState, useMemo, useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import API_KEY from '../components/utils/apiKeys.js'; +import AgendamentoCadastroManager from '../pages/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'; +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 "../pages/style/Agendamento.css"; +import '../pages/style/FilaEspera.css'; +import { Search } from 'lucide-react'; + + + +const Agendamento = ({setDictInfo}) => { + const navigate = useNavigate(); + + 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(''); + + + let authHeader = getAuthorizationHeader() + + const FiltrarAgendamentos = async (listaTodosAgendamentos) => { + const ConfigurarFiladeEspera = async (patient_id, doctor_id, agendamento) => { + // Assumindo que GetDoctorByID e GetPatientByID estão definidos no seu escopo + let medico = await GetDoctorByID(doctor_id, authHeader); + let paciente = await GetPatientByID(patient_id, authHeader); + + let dicionario = { + agendamento: agendamento, + Infos: { + nome_nedico: medico.full_name, + doctor_id: medico.id, + patient_id: paciente[0].id, + paciente_nome: paciente[0].full_name, + paciente_cpf: paciente[0].cpf + } + }; + return dicionario; + }; + + let DictAgendamentosOrganizados = {}; + let ListaFilaDeEspera = []; + + // 1. Agrupamento (igual ao seu código original) + for (const agendamento of listaTodosAgendamentos) { + if (agendamento.status === 'requested') { + // Recomenda-se usar Promise.all para melhorar a performance + // mas, para manter a estrutura, mantemos o await no loop. + let v = await ConfigurarFiladeEspera(agendamento.patient_id, agendamento.doctor_id, agendamento); + ListaFilaDeEspera.push(v); + } else { + const DiaAgendamento = agendamento.scheduled_at.split("T")[0]; + + if (DiaAgendamento in DictAgendamentosOrganizados) { + DictAgendamentosOrganizados[DiaAgendamento].push(agendamento); + } else { + DictAgendamentosOrganizados[DiaAgendamento] = [agendamento]; + } + } + } + +// ---------------------------------------------------------------------- + // 2. Ordenação Interna: Ordenar os agendamentos por HORÁRIO (do menor para o maior) + for (const DiaAgendamento in DictAgendamentosOrganizados) { + DictAgendamentosOrganizados[DiaAgendamento].sort((a, b) => { + // Compara as strings de data/hora (ISO 8601) diretamente, + // que funcionam para ordenação cronológica. + if (a.scheduled_at < b.scheduled_at) return -1; + if (a.scheduled_at > b.scheduled_at) return 1; + return 0; + }); + } + +// ---------------------------------------------------------------------- + // 3. Ordenação Externa: Ordenar os DIAS (as chaves do objeto) + // Para garantir que as chaves fiquem na sequência cronológica correta. + + // Pega as chaves (datas) + const chavesOrdenadas = Object.keys(DictAgendamentosOrganizados).sort((a, b) => { + // Compara as chaves de data (strings 'YYYY-MM-DD') + if (a < b) return -1; + if (a > b) return 1; + return 0; + }); + + // Cria um novo objeto no formato desejado, garantindo a ordem das chaves + let DictAgendamentosFinal = {}; + for (const data of chavesOrdenadas) { + DictAgendamentosFinal[data] = DictAgendamentosOrganizados[data]; + } + setAgendamentosOrganizados(DictAgendamentosFinal); // Use o objeto final ordenado + setfilaEsperaData(ListaFilaDeEspera); +}; + + // Requisição inicial para mostrar os agendamentos do banco de dados + 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 => {FiltrarAgendamentos(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() + + }, []) + + useEffect(() => { + console.log("mudou FiltredTodosMedicos:", FiltredTodosMedicos); + if (FiltredTodosMedicos.length === 1) { + const unicoMedico = FiltredTodosMedicos[0]; + 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) + + } + }, [FiltredTodosMedicos]); + +const deleteConsulta = (selectedPatientId) => { + console.log("tentando apagar") + var myHeaders = new Headers(); + myHeaders.append("Authorization", authHeader); + myHeaders.append("apikey", API_KEY) + +var requestOptions = { + method: 'DELETE', + redirect: 'follow', + headers: myHeaders +}; + +fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?id=eq.${selectedPatientId}`, requestOptions) + .then(response => response.json()) + .then(result => console.log(result)) + .catch(error => console.log('error', error)); + +} + + +/** + * Filtra todos os agendamentos em um objeto aninhado (data -> [agendamentos]) + * com base no ID do médico. + * + * @param {Object} dictAgendamentos - O dicionário de agendamentos. + * @param {string} idMedicoFiltrado - O ID do médico (doctor_id) para ser usado como filtro. + * @returns {Array} Um array contendo todos os agendamentos que correspondem ao idMedicoFiltrado. + */ +const filtrarAgendamentosPorMedico = (dictAgendamentos, idMedicoFiltrado) => { + + // O corpo da função deve usar esses nomes de variáveis: + const todasAsListasDeAgendamentos = Object.values(dictAgendamentos); + + const todosOsAgendamentos = todasAsListasDeAgendamentos.flat(); + + const agendamentosFiltrados = todosOsAgendamentos.filter(agendamento => + agendamento.doctor_id === idMedicoFiltrado + ); + + return agendamentosFiltrados; +}; + + + + // Lógica para filtrar os dados da AGENDA (AgendamentosMes) + 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) +}; + + +const handleSearchMedicos = (term) => { + setSearchTermDoctor(term); + if (term.trim() === '') { + setFiltredTodosMedicos([]); + return; + } + + // Lógica simples de filtragem: + const filtered = ListaDeMedicos.filter(medico => + medico.nomeMedico.toLowerCase().includes(term.toLowerCase()) + ); + setFiltredTodosMedicos(filtered); +}; + + + const handleClickCancel = () => setPageConsulta(false) + + return ( +
+

Agendar nova consulta

+ + + + + + {!PageNovaConsulta ? ( +
+ +
+ +
+ +
+
+ + handleSearchMedicos(e.target.value)} // Chama a nova função de filtro + /> +
+
+ + {/* DROPDOWN (RENDERIZAÇÃO CONDICIONAL) */} + {searchTermDoctor && FiltredTodosMedicos.length > 0 && ( +
+ {FiltredTodosMedicos.map((medico) => ( +
{ + // Ação ao selecionar o médico + setSearchTermDoctor(medico.nomeMedico); // Preenche o input + //setFiltredTodosMedicos([]); // Fecha o dropdown + // Lógica adicional, como selecionar o ID do médico... + }} + > +

{medico.nomeMedico}

+
+ ))} +
+ )} +
+
+ + +
+ + +
+ +
+ + +
+ +
+ {FiladeEspera === false ? + ( +
+
+
+
+ + + +
+
+
Realizado
+
Confirmado
+
Agendado
+
Cancelado
+
+
+ + {tabela === "diario" && } + {tabela === 'semanal' && } + {tabela === 'mensal' && } +
+
+ ) + : + ( +
+
+ setSearchTerm(e.target.value)} + /> +

Fila de Espera

+
+ + + + + + + + + + + + + {filaEsperaData.map((item, index) => ( + + + + + + + + ))} + +
NomeTelefoneTelefoneEntrou na fila de esperaAções

{item.Infos?.paciente_nome}

{}

{}{}
+ + + + + +
+
+ ) + } +
+
+ ) : ( + + )} + + {showDeleteModal && ( +
+ e.target.classList.contains("modal") && setShowDeleteModal(false) + } + > +
+
+ +
+
+ Confirmação de Exclusão +
+ +
+ +
+

+ Tem certeza que deseja excluir este agendamento? +

+
+ +
+ + + + + +
+
+
+
)} + + +
+ ) +} + +export default Agendamento; \ No newline at end of file