riseup-squad23/src/PagesMedico/DoctorAgendamentoManager.jsx
2025-11-04 11:53:45 -03:00

477 lines
17 KiB
JavaScript

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 { UserInfos } from '../components/utils/Functions-Endpoints/General.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 [showConfirmModal, setShowConfirmModal] = useState(false)
const [coresConsultas, setCoresConsultas] = useState([])
const [listaConsultasID, setListaConsultaID] = useState([])
const [motivoCancelamento, setMotivoCancelamento] = useState("")
const [user, setUser] = 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,
nome_medico: medico[0].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') {
let v = await ConfigurarFiladeEspera(agendamento.patient_id, agendamento.doctor_id, agendamento);
ListaFilaDeEspera.push(v);
} else {
const DiaAgendamento = agendamento.scheduled_at?.split("T")[0];
let novoAgendamento = await ConfigurarFiladeEspera(agendamento.patient_id, agendamento.doctor_id, agendamento);
if (DiaAgendamento in DictAgendamentosOrganizados) {
DictAgendamentosOrganizados[DiaAgendamento].push(novoAgendamento);
} else {
DictAgendamentosOrganizados[DiaAgendamento] = [novoAgendamento];
}
}
}
// ----------------------------------------------------------------------
// 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);
};
useEffect(() => {
console.log(user, "usuario")
}, [user])
// Requisição inicial para mostrar os agendamentos do banco de dados
useEffect(() => {
async function fetchDadosUser (){
let dado = await UserInfos(authHeader)
setUser(dado)
}
fetchDadosUser()
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?doctor_id=eq.${"078d2a67-b4c1-43c8-ae32-c1e75bb5b3df"}`, requestOptions)
.then(response => response.json())
.then(result => {FiltrarAgendamentos(result); console.log(result, "RESULTRADO DA API")})
.catch(error => console.log('error', error));
}, [])
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));
}
// 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 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 handleClickCancel = () => setPageConsulta(false)
return (
<div>
<h1>Agendar nova consulta</h1>
<button className='manage-button btn' onClick={() => navigate('/secretaria/excecoes-disponibilidade')}>
<i className="bi bi-gear-fill me-1"></i>
Mudar Disponibilidade
</button>
<button className="btn btn-primary" onClick={() => setPageConsulta(true)}>
<i className="bi bi-plus-circle"></i> Adicionar Paciente
</button>
{!PageNovaConsulta ? (
<div className='atendimento-eprocura'>
<div className='busca-atendimento-container'>
</div>
<section className='calendario-ou-filaespera'>
<div className='calendario'>
<div>
<section className='btns-e-legenda-container'>
<div>
<button className={`btn-selecionar-tabeladia ${tabela === "diario" ? "ativo" : ""}`} onClick={() => setTabela("diario")}>
<i className="fa-solid fa-calendar-day"></i> Dia
</button>
<button className={`btn-selecionar-tabelasemana ${tabela === 'semanal' ? 'ativo' : ""}`} onClick={() => setTabela("semanal")}>
<i className="fa-solid fa-calendar-day"></i> Semana
</button>
<button className={`btn-selecionar-tabelames ${tabela === 'mensal' ? 'ativo' : ''}`} onClick={() => setTabela("mensal")}>
<i className="fa-solid fa-calendar-day"></i> Mês
</button>
</div>
<div className='legenda-tabela'>
<div className='legenda-item-realizado'><span>Realizado</span></div>
<div className='legenda-item-confirmado'><span>Confirmado</span></div>
<div className='legenda-item-agendado'><span>Agendado</span></div>
<div className='legenda-item-cancelado'><span>Cancelado</span></div>
</div>
</section>
{tabela === "diario" && <TabelaAgendamentoDia agendamentos={DictAgendamentosOrganizados}
setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo}
listaConsultasID={listaConsultasID}
setListaConsultaID={setListaConsultaID} coresConsultas={coresConsultas} setShowConfirmModal={setShowConfirmModal}
/>}
{tabela === 'semanal' && <TabelaAgendamentoSemana agendamentos={DictAgendamentosOrganizados} ListarDiasdoMes={ListarDiasdoMes}
setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo}
listaConsultasID={listaConsultasID} setListaConsultaID={setListaConsultaID} coresConsultas={coresConsultas} setShowConfirmModal={setShowConfirmModal} />}
{tabela === 'mensal' && <TabelaAgendamentoMes ListarDiasdoMes={ListarDiasdoMes} aplicarCores={true} agendamentos={DictAgendamentosOrganizados}
setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} listaConsultasID={listaConsultasID}
setListaConsultaID={setListaConsultaID} coresConsultas={coresConsultas} setShowConfirmModal={setShowConfirmModal} />}
</div>
</div>
</section>
</div>
) : (
<AgendamentoCadastroManager setPageConsulta={setPageConsulta} Dict={{nome_medico:user?.profile?.full_name}}
/>
)}
{showConfirmModal &&(
<div
className="modal fade show"
style={{
display: "block",
backgroundColor: "rgba(0, 0, 0, 0.5)",
}}
tabIndex="-1"
onClick={(e) =>
e.target.classList.contains("modal") && setShowDeleteModal(false)
}
>
<div className="modal-dialog modal-dialog-centered">
<div className="modal-content">
<div className="modal-header bg-success">
<h5 className="modal-title">
Confirmação de edição
</h5>
</div>
<div className="modal-body">
<p className="mb-0 fs-5">
Tem certeza que deseja retirar o cancelamento ?
</p>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-primary"
onClick={() => {setShowConfirmModal(false); setSelectedId("")}}
>
Cancelar
</button>
<button
type="button"
className="btn btn-success"
onClick={() => {confirmConsulta(selectedID);setShowConfirmModal(false)
let lista_cores = coresConsultas
let lista = listaConsultasID
lista.push(selectedID)
lista_cores.push("confirmed")
setCoresConsultas(lista_cores)
setListaConsultaID(lista)
}}
>
<i className="bi bi-trash me-1"></i> Confirmar
</button>
</div>
</div>
</div>
</div>)}
{showDeleteModal && (
<div
className="modal fade show"
style={{
display: "block",
backgroundColor: "rgba(0, 0, 0, 0.5)",
}}
tabIndex="-1"
onClick={(e) =>
e.target.classList.contains("modal") && setShowDeleteModal(false)
}
>
<div className="modal-dialog modal-dialog-centered">
<div className="modal-content">
<div className="modal-header bg-danger bg-opacity-25">
<h5 className="modal-title text-danger">
Confirmação de Cancelamento
</h5>
<button
type="button"
className="btn-close"
onClick={() => setShowDeleteModal(false)}
></button>
</div>
<div className="modal-body">
<p className="mb-0 fs-5">
Qual o motivo do cancelamento?
</p>
<div className='campo-de-input'>
<textarea className='input-modal' value={motivoCancelamento} onChange={(e) => setMotivoCancelamento(e.target.value)} />
</div>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-primary"
onClick={() => {
setShowDeleteModal(false);
}}
>
Cancelar
</button>
<button
type="button"
className="btn btn-danger"
onClick={() => {
deleteConsulta(selectedID)
setShowDeleteModal(false)
let lista_cores = coresConsultas
let lista = listaConsultasID
lista.push(selectedID)
lista_cores.push("cancelled")
setCoresConsultas(lista_cores)
setListaConsultaID(lista)
console.log("lista", lista)
}}
>
<i className="bi bi-trash me-1"></i> Excluir
</button>
</div>
</div>
</div>
</div>)}
</div>
)
}
export default Agendamento;