Mergin com melhoriasAgendamentos

This commit is contained in:
joao_pedro 2025-10-29 20:30:13 -03:00
commit 274bbef699
18 changed files with 469 additions and 211 deletions

View File

@ -1,56 +0,0 @@
3993097 (HEAD -> main) Merge branch 'main' of https://git.popcode.com.br/RiseUP/riseup-squad23
63659b6 Verificação do cpf e colocar o erro 404
ecae83c (riseup/main, riseup/HEAD, origin/main, origin/HEAD) Merge pull request 'Conectando-o-resto-das-API' (#2) from Conectando-o-resto-das-API into main
908d545 (riseup/Conectando-o-resto-das-API, origin/Conectando-o-resto-das-API) feat: adicionar upload e delete de anexos do paciente
4b404c0 Merge branch 'main' of https://git.popcode.com.br/RiseUP/riseup-squad23
bd20c2d Merge remote-tracking branch 'origin/main'
8aeabd1 (riseup/Fix-dos-erros-do-projeto, origin/Fix-dos-erros-do-projeto) FIx: todos os erros que aparecia no console foram resolvidos
0e29e7d melhorias na organização de pastas
98f076a Mergin com TableMelhorias
589d590 Mergin com novas alterações de laudo
7b28e2a Details melhorias
9480edc (riseup/PaginaDetalhes, origin/PaginaDetalhes) Pàgina detalhes
e4515cf Adição das cores nos cards de consulta
d3dd2fd (riseup/TableMelhorias, origin/TableMelhorias) Detalhe nas tabelas
a54b119 Delete Anexos apos pacientes forem excluidos
6e93cb5 atualizar paciente
b9a35be começo do concerto do editar
82469bc Details funcional
cdfe4ea Validação de CPF
57c8f67 (riseup/DetalhesMedico, origin/DetalhesMedico) Detalhes do medico
b021444 Mudanças formularios e detalhes
d5d03b0 (riseup/mudanças-de-laudo, origin/mudanças-de-laudo) atualização do laudo
a502bbd agendamentos no incio
8e1fcd9 Merge branch 'feature/novo-cadastro-paciente'
bea9076 Merge remote-tracking branch 'origin/PaginaDetalhes'
e35f217 mergin branch inicio com main
1af8268 Atualizacão do laudo
725d60d feat: ajeitei o nome
bab85ff (riseup/AgendamentoSidebar, origin/AgendamentoSidebar) Concertar Agendamento
b2707e3 Refatora o estilo do formulário do paciente para uma aparência de cartão com tipografia maior
37e8959 Refatora o estilo do formulário do paciente para uma aparência de cartão com tipografia maior
0930385 feat: uma piquena mudança
f6a19c4 feat: Adiciona formulário de cadastro de paciente
d91b5cf form de agendar consulta melhorado
0a60dd7 Tabela semana e mes
7f07950 (riseup/feature-Melhoria-no-Dashboard, origin/feature-Melhoria-no-Dashboard) feat: Criação da página início e melhoria na navegação
39e25ad Pagina de detalhes atualizada
4f84791 pequenas mudanaças na tabela de semana e mes
6737955 form para nova consulta e tabelas de horario
26ded17 Nova pagina de detalhes
874de84 Inicio do agendamento
f3e7470 (riseup/gerenciamento-de-laudo, origin/gerenciamento-de-laudo) Laudo do Paciente
709cd4e Merge finalizado
d6b3e86 Merge detalhes-do-pacientes para main
08ffa55 Merge remote-tracking branch 'origin/CrudMedico'
70c4d5f Termino da organização
edd567d Inicio da organização
9c09113 Mudanças pos feedback de davi
aa3a5fa Criação da página dos detalhes dos pacientes
5534568 Inicio de detalhes e atualização do paciente
06ff7d5 Funcionalidade de delete e botão de opções
5b63fa2 Mascara telefones
fb9d783 adição da mascara do CPF
a489d84 metodo GET e POST
4eaabbd first commit
a244691 Initial commit

View File

@ -4,14 +4,20 @@ import { useAuth } from '../utils/AuthProvider';
import { useNavigate } from 'react-router-dom';
import { useMemo } from 'react';
import "./style/card-consulta.css"
const CardConsulta = ( {DadosConsulta, TabelaAgendamento, setShowDeleteModal, setDictInfo, setSelectedId} ) => {
const CardConsulta = ( {DadosConsulta, TabelaAgendamento, setShowDeleteModal, setDictInfo, setSelectedId, setShowConfirmModal, corModal, selectedID, coresConsultas, setListaConsultaID, listaConsultasID} ) => {
const navigate = useNavigate();
const {getAuthorizationHeader} = useAuth()
const authHeader = getAuthorizationHeader()
const [Paciente, setPaciente] = useState()
const [Medico, setMedico] = useState()
const [decidirBotton, setDecidirBotton] = useState("")
const ids = useMemo(() => {
return {
doctor_id: DadosConsulta?.doctor_id,
@ -45,23 +51,35 @@ const CardConsulta = ( {DadosConsulta, TabelaAgendamento, setShowDeleteModal, se
let nameArrayMedico = Medico?.full_name.split(' ')
console.log(DadosConsulta.status)
let indice_cor = listaConsultasID.indexOf(DadosConsulta.id)
// console.log(coresConsultas)
//console.log(indice_cor,"indice no cores")
return (
<div className={`container-cardconsulta container-cardconsulta-${TabelaAgendamento}`}>
{DadosConsulta.id?
<div className={`container-cardconsulta container-cardconsulta-${TabelaAgendamento} ` }>
<div className='cardconsulta' id={`status-card-consulta-${DadosConsulta.status}`}>
{DadosConsulta.id?
<div className={`cardconsulta`} id={indice_cor !== -1 ? `status-card-consulta-${coresConsultas[indice_cor]}` : `status-card-consulta-${DadosConsulta.status}`}>
<div>
<section className='cardconsulta-infosecundaria'>
<p>{DadosConsulta.horario} {nameArrayMedico && nameArrayMedico.length > 0 ? nameArrayMedico[0] : ''} {nameArrayMedico && nameArrayMedico.length > 1 ? ` ${nameArrayMedico[1]}` : ''} </p>
<p>Medico:{DadosConsulta.horario} {nameArrayMedico && nameArrayMedico.length > 0 ? nameArrayMedico[0] : ''} {nameArrayMedico && nameArrayMedico.length > 1 ? ` ${nameArrayMedico[1]}` : ''} </p>
</section>
<section className='cardconsulta-infoprimaria'>
<p>{nameArrayPaciente && nameArrayPaciente.length > 0 ? nameArrayPaciente[0] : ''} {nameArrayPaciente && nameArrayPaciente.length > 1 ? ` ${nameArrayPaciente[1]}` : ''}- {}</p>
<p>Paciente: {nameArrayPaciente && nameArrayPaciente.length > 0 ? nameArrayPaciente[0] : ''} {nameArrayPaciente && nameArrayPaciente.length > 1 ? ` ${nameArrayPaciente[1]}` : ''}- {}
{DadosConsulta.chief_complaint && `Reclamação: ${DadosConsulta.chief_complaint}`}
</p>
</section>
</div>
@ -75,16 +93,38 @@ const CardConsulta = ( {DadosConsulta, TabelaAgendamento, setShowDeleteModal, se
>
<i className="bi bi-pencil me-1"></i>
</button>
{DadosConsulta.status === "cancelled" ?
<button
className="btn btn-sm btn-confirm-style"
onClick={() => {
console.log(DadosConsulta.id)
setShowConfirmModal(true)
setSelectedId(DadosConsulta.id);
}}
>
<i class="bi bi-check-lg"></i>
</button>
:
<button
className="btn btn-sm btn-delete-custom-style "
onClick={() => {
console.log(DadosConsulta.id)
setSelectedId(DadosConsulta.id);
setShowDeleteModal(true);
}}
>
<i className="bi bi-trash me-1"></i>
</button>
}
</div>
</div>
@ -93,6 +133,8 @@ const CardConsulta = ( {DadosConsulta, TabelaAgendamento, setShowDeleteModal, se
}
</div>
)

View File

@ -87,7 +87,11 @@ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
}
}
// Se estiver na página de edição esse useEffect pega o horario de inicio para coloca-lo no horarioInicio
useEffect(() => {
console.log("Horario", )
setHorarioInicio(formatarHora(agendamento.scheduled_at))
}, [])
useEffect(() => {
@ -287,7 +291,7 @@ const handleSubmit = (e) => {
<div className="campo-de-input">
<label>Data *</label>
<input type="date" name="dataAtendimento" onChange={handleChange} required />
<input type="date" name="dataAtendimento" onChange={handleChange} value={agendamento.dataAtendimento} required />
</div>
</div>
<div className="linha">

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import CardConsulta from './CardConsulta';
import "./style/styleTabelas/tabeladia.css";
const TabelaAgendamentoDia = ({ handleClickAgendamento, agendamentos, setShowDeleteModal, setDictInfo, setSelectedId }) => {
const TabelaAgendamentoDia = ({ handleClickAgendamento, agendamentos, setShowDeleteModal, setDictInfo,selectedID, setSelectedId, setShowConfirmModal, coresConsultas, setListaConsultaID, listaConsultasID }) => {
const [indiceAcesso, setIndiceAcesso] = useState(0)
const [Dia, setDia] = useState()
const agendamentosDoDia = agendamentos?.semana1?.segunda || [];
@ -10,8 +10,7 @@ const TabelaAgendamentoDia = ({ handleClickAgendamento, agendamentos, setShowDel
let ListaDiasComAgendamentos = Object.keys(agendamentos)
console.log(agendamentos)
//console.log(Dia, "hshdhshhsdhs")
@ -19,6 +18,28 @@ const TabelaAgendamentoDia = ({ handleClickAgendamento, agendamentos, setShowDel
setDia(ListaDiasComAgendamentos[indiceAcesso])
}, [indiceAcesso])
const formatarDataComDia = (dataISO) => {
if (!dataISO) return '';
const data = new Date(dataISO); // converte para objeto Date
// nomes dos dias da semana
const dias = [
'Segunda-feira',
'Terça-feira',
'Quarta-feira',
'Quinta-feira',
'Sexta-feira',
'Sábado'
];
const diaSemana = dias[data.getDay()]; // 0 = Domingo, 1 = Segunda, etc.
const dia = dataISO.split('-')[2];
const mes = dataISO.split('-')[1];
const ano = dataISO.split('-')[0];
return `${diaSemana}, ${dia}/${mes}/${ano}`;
};
return (
<div>
@ -27,7 +48,7 @@ const TabelaAgendamentoDia = ({ handleClickAgendamento, agendamentos, setShowDel
<button onClick={() => {if(indiceAcesso === 0)return; else(setIndiceAcesso(indiceAcesso - 1))}}> <i className="bi bi-chevron-compact-left"></i></button>
<p>{Dia ? `${Dia?.split('-')[2]}/${Dia?.split('-')[1]}/${Dia?.split('-')[0]}`: ''}</p>
<p>{Dia ? formatarDataComDia(Dia) : ''}</p>
<button onClick={() => {if(ListaDiasComAgendamentos.length - 1 === indiceAcesso)return; else(setIndiceAcesso(indiceAcesso + 1))}}> <i className="bi bi-chevron-compact-right"></i></button>
</div>
@ -51,7 +72,7 @@ const TabelaAgendamentoDia = ({ handleClickAgendamento, agendamentos, setShowDel
<td className='coluna-horario'><p className='horario-texto'>{`${horario[0]}:${horario[1]}`}</p></td>
<td className='mostrar-horario'>
<div onClick={() => handleClickAgendamento(agendamento)}>
<CardConsulta DadosConsulta={agendamento} TabelaAgendamento={'dia'} setShowDeleteModal={setShowDeleteModal} setDictInfo={setDictInfo} setSelectedId={setSelectedId}/>
<CardConsulta DadosConsulta={agendamento} TabelaAgendamento={'dia'} setShowDeleteModal={setShowDeleteModal} setDictInfo={setDictInfo} setSelectedId={setSelectedId} selectedID={selectedID} setShowConfirmModal={setShowConfirmModal} coresConsultas={coresConsultas} setListaConsultaID={setListaConsultaID} listaConsultasID={listaConsultasID}/>
</div>
</td>
</tr>

View File

@ -6,7 +6,7 @@ import "./style/styleTabelas/tabelames.css";
import { useEffect, useState } from 'react';
import { useMemo } from 'react';
const TabelaAgendamentoMes = ({ ListarDiasdoMes, agendamentos, setShowDeleteModal, setSelectedId ,setDictInfo }) => {
const TabelaAgendamentoMes = ({ ListarDiasdoMes, agendamentos, setShowDeleteModal, setSelectedId ,setDictInfo, setShowConfirmModal }) => {
const dataHoje = dayjs();
const AnoAtual = dataHoje.year();
@ -202,9 +202,9 @@ const TabelaAgendamentoMes = ({ ListarDiasdoMes, agendamentos, setShowDeleteModa
{
semana && typeof semana === "object" && Object.keys(semana).map((dia) => (
<td key={dia} >
<CardConsulta DadosConsulta={((semana[dia]|| [])[0]) || {status:'vazio'}} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo}/>
<CardConsulta DadosConsulta={((semana[dia]|| [])[1]) || {status:'vazio'}} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo}/>
<CardConsulta DadosConsulta={((semana[dia]|| [])[2]) || {status:'vazio'}} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo}/>
<CardConsulta TabelaAgendamento={'mes'} DadosConsulta={((semana[dia]|| [])[0]) || {status:'vazio'}} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} setShowConfirmModal={setShowConfirmModal}/>
<CardConsulta TabelaAgendamento={'mes'} DadosConsulta={((semana[dia]|| [])[1]) || {status:'vazio'}} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} setShowConfirmModal={setShowConfirmModal}/>
<CardConsulta TabelaAgendamento={'mes'} DadosConsulta={((semana[dia]|| [])[2]) || {status:'vazio'}} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} setShowConfirmModal={setShowConfirmModal} />
{semana[dia].length > 3 ? (
<div>
<p>{` +${semana[dia].length - 2}`}</p>

View File

@ -6,7 +6,7 @@ import { useEffect, useState, useMemo } from 'react';
import weekOfYear from 'dayjs/plugin/weekOfYear'
dayjs.extend(weekOfYear)
const TabelaAgendamentoSemana = ({ agendamentos, ListarDiasdoMes, setShowDeleteModal ,setSelectedId ,setDictInfo}) => {
const TabelaAgendamentoSemana = ({ agendamentos, ListarDiasdoMes, setShowDeleteModal ,setSelectedId ,setDictInfo, setShowConfirmModal}) => {
// Armazena o objeto COMPLETO das semanas organizadas
const [semanasOrganizadas, setSemanasOrganizadas] = useState({});
@ -67,9 +67,9 @@ const TabelaAgendamentoSemana = ({ agendamentos, ListarDiasdoMes, setShowDeleteM
break
}
}
console.log(semanas)
return semanas
}, [agendamentos, AnoAtual]) // Adicionei AnoAtual como dependência por segurança
}, [agendamentos, AnoAtual])
// --- EFEITO PARA POPULAR O ESTADO ---
@ -159,49 +159,50 @@ const TabelaAgendamentoSemana = ({ agendamentos, ListarDiasdoMes, setShowDeleteM
<tbody>
{indicesDeLinha.map((indiceLinha) => {
let schedulet_at = semanaParaRenderizar.segunda[indiceLinha].scheduled_at.split("T")
//let schedulet_at = semanaParaRenderizar.segunda[indiceLinha].scheduled_at.split("T")
let horario = schedulet_at[1].split(":")
// let horario = schedulet_at[1].split(":")
console.log(horario)
console.log(semanaParaRenderizar, "aqui")
return(
<tr key={indiceLinha}>
{/* Célula para Horário (Pode ser ajustado para mostrar o horário real) */}
<td>
<p className='horario-texto'> {`${horario[0]}:${horario[1]}`} </p>
{/* <p className='horario-texto'> {`${horario[0]}:${horario[1]}`} </p>*/}
</td>
{/* Mapeamento de COLUNAS (dias) */}
<td>
{semanaParaRenderizar.segunda[indiceLinha]
? <CardConsulta DadosConsulta={semanaParaRenderizar.segunda[indiceLinha]} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} />
{semanaParaRenderizar?.segunda[indiceLinha]
? <CardConsulta TabelaAgendamento={'semana'} DadosConsulta={semanaParaRenderizar?.segunda[indiceLinha]} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} setShowConfirmModal={setShowConfirmModal}/>
: null
}
</td>
<td>
{semanaParaRenderizar.terça[indiceLinha]
? <CardConsulta DadosConsulta={semanaParaRenderizar.terça[indiceLinha]} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo}/>
? <CardConsulta TabelaAgendamento={'semana'} DadosConsulta={semanaParaRenderizar.terça[indiceLinha]} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} setShowConfirmModal={setShowConfirmModal}/>
: null
}
</td>
<td>
{semanaParaRenderizar.quarta[indiceLinha]
? <CardConsulta DadosConsulta={semanaParaRenderizar.quarta[indiceLinha]} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo}/>
? <CardConsulta TabelaAgendamento={'semana'} DadosConsulta={semanaParaRenderizar.quarta[indiceLinha]} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} setShowConfirmModal={setShowConfirmModal}/>
: null
}
</td>
<td>
{semanaParaRenderizar.quinta[indiceLinha]
? <CardConsulta DadosConsulta={semanaParaRenderizar.quinta[indiceLinha]} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} />
? <CardConsulta TabelaAgendamento={'semana'} DadosConsulta={semanaParaRenderizar.quinta[indiceLinha]} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} setShowConfirmModal={setShowConfirmModal}/>
: null
}
</td>
<td>
{semanaParaRenderizar.sexta[indiceLinha]
? <CardConsulta DadosConsulta={semanaParaRenderizar.sexta[indiceLinha]} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} />
? <CardConsulta TabelaAgendamento={'semana'} DadosConsulta={semanaParaRenderizar.sexta[indiceLinha]} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} setShowConfirmModal={setShowConfirmModal} />
: null
}
</td>

View File

@ -50,7 +50,7 @@
/* 6. Estilo de hover para o botão de exclusão */
.btn-delete-custom-style:hover {
background-color: #c82333; /* Um vermelho um pouco mais escuro para o hover */
filter: brightness(90%); /* Alternativa: escurecer um pouco mais */
}
/* 7. Estilos para os ícones dentro dos botões (já está no JSX com fs-4) */
@ -58,4 +58,19 @@
.action-button .bi {
/* Exemplo: se precisar de um ajuste fino além do fs-4 */
/* font-size: 1.5rem; */
}
}
.btn-confirm-style{
background-color: #5ce687;
}
.container-cardconsulta{
width: 40rem;
}
.card-verde{
background-color: #b7ffbd;
border: #91d392;
}

View File

@ -6,6 +6,8 @@
overflow: hidden; /* mantém o arredondado */
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
border: 4px solid #4a90e2; /* borda azul, altere para a cor desejada */
}
/* 1. Estilização do TD (Container) */
.coluna-horario {

View File

@ -6,6 +6,7 @@
overflow: hidden; /* mantém o arredondado */
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
border: 4px solid #4a90e2; /* borda azul, altere para a cor desejada */
}
/* Células da tabela */
@ -67,10 +68,10 @@
.tabelasemanal tr:hover {
background-color: #f1f1f1 !important;
}
/*
tr{
width: 1000px;
}
}*/
html[data-bs-theme="dark"] .tabelasemanal {
border: 4px solid #333;
@ -110,4 +111,10 @@ html[data-bs-theme="dark"] .tabelasemanal .cardconsulta {
color: #e0e0e0;
box-shadow: 0 1px 3px rgba(0,0,0,0.3);
border-left: 5px solid #333;
}
.tabelasemanal td{
width: 50rem;
}

View File

@ -0,0 +1,17 @@
import React from 'react';
import './style.css';
const CabecalhoError = ({ showCabecalho, message, errorCode }) => {
if (!showCabecalho) return null;
return (
<div className="cabecalho-error-wrapper">
<div className="cabecalho-error">
<p className='cabecalho-error-text'>{message}</p>
</div>
</div>
);
};
export default CabecalhoError;

View File

@ -0,0 +1,15 @@
function manager (setShowModal, RefreshingToken, setErrorInfo,errorData) {
console.log((errorData, "MANAGER"))
if(errorData.httpStatus === 401){
RefreshingToken()
}else{
// setErrorInfo(errorData)
setShowModal("modal");
}
}
export default manager

View File

@ -24,7 +24,7 @@ return(
<div>
{showModal ?
{showModal === "modal"?
<div className="modal-overlay">

View File

@ -0,0 +1,26 @@
.cabecalho-error {
background-color: #f3616d; /* vermelho forte */
color: white;
display: flex;
align-items: center; /* centraliza verticalmente */
justify-content: center; /* centraliza horizontalmente */
padding: 12px 20px;
margin: 10px;
border-radius: 8px;
font-weight: bold;
font-size: 16px;
width: calc(100% - 20px); /* ocupa quase toda a largura da div pai */
box-sizing: border-box;
}
.cabecalho-error-text {
margin: 0;
padding-left: 30px; /* espaço para "Erro 404" */
position: relative;
}
.cabecalho-error-code {
position: absolute;
left: 0;
font-weight: 700;
}

View File

@ -23,10 +23,11 @@ import { Search } from 'lucide-react';
const Agendamento = ({setDictInfo}) => {
const navigate = useNavigate();
const [listaTodosAgendamentos, setListaTodosAgendamentos] = useState([])
const [selectedID, setSelectedId] = useState('0')
const [filaEsperaData, setfilaEsperaData] = useState([])
const [filaEsperaData, setFilaEsperaData] = useState([])
const [FiladeEspera, setFiladeEspera] = useState(false);
const [tabela, setTabela] = useState('diario');
const [PageNovaConsulta, setPageConsulta] = useState(false);
@ -42,72 +43,92 @@ const Agendamento = ({setDictInfo}) => {
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([])
let authHeader = getAuthorizationHeader()
const cacheMedicos = {};
const cachePacientes = {};
const FiltrarAgendamentos = async (listaTodosAgendamentos) => {
const ConfigurarFiladeEspera = async (patient_id, doctor_id, agendamento) => {
let medico = await GetDoctorByID(doctor_id, authHeader);
let paciente = await GetPatientByID(patient_id, authHeader);
console.log(medico)
let dicionario = {
agendamento: 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
}
};
return dicionario;
};
let DictAgendamentosOrganizados = {};
let ListaFilaDeEspera = [];
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') {
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];
}
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);
}
}
for (const DiaAgendamento in DictAgendamentosOrganizados) {
DictAgendamentosOrganizados[DiaAgendamento].sort((a, b) => {
if (a.scheduled_at < b.scheduled_at) return -1;
if (a.scheduled_at > b.scheduled_at) return 1;
return 0;
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((a, b) => {
if (a < b) return -1;
if (a > b) return 1;
return 0;
});
const chavesOrdenadas = Object.keys(DictAgendamentosOrganizados).sort();
let DictAgendamentosFinal = {};
const DictAgendamentosFinal = {};
for (const data of chavesOrdenadas) {
DictAgendamentosFinal[data] = DictAgendamentosOrganizados[data];
DictAgendamentosFinal[data] = DictAgendamentosOrganizados[data];
}
setAgendamentosOrganizados(DictAgendamentosFinal);
setfilaEsperaData(ListaFilaDeEspera);
};
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);
@ -121,7 +142,7 @@ const Agendamento = ({setDictInfo}) => {
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);console.log(result)})
.then(result => {setListaTodosAgendamentos(result);console.log(result)})
.catch(error => console.log('error', error));
const PegarTodosOsMedicos = async () => {
@ -135,24 +156,7 @@ const Agendamento = ({setDictInfo}) => {
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) => {
var myHeaders = new Headers();
@ -161,7 +165,32 @@ const deleteConsulta = (selectedPatientId) => {
myHeaders.append("authorization", authHeader)
var raw = JSON.stringify({ "status":"cancelled"
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"
});
@ -179,17 +208,6 @@ const deleteConsulta = (selectedPatientId) => {
}
const filtrarAgendamentosPorMedico = (dictAgendamentos, idMedicoFiltrado) => {
const todasAsListasDeAgendamentos = Object.values(dictAgendamentos);
const todosOsAgendamentos = todasAsListasDeAgendamentos.flat();
const agendamentosFiltrados = todosOsAgendamentos.filter(agendamento =>
agendamento.doctor_id === idMedicoFiltrado
);
return agendamentosFiltrados;
};
const filteredAgendamentos = useMemo(() => {
@ -238,12 +256,60 @@ const filtrarAgendamentosPorMedico = (dictAgendamentos, idMedicoFiltrado) => {
};
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() === '') {
setFiltredTodosMedicos([]);
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())
@ -252,10 +318,9 @@ const handleSearchMedicos = (term) => {
};
const handleClickCancel = () => setPageConsulta(false)
return (
<div>
<div className='spinner'></div>
<h1>Agendar nova consulta</h1>
@ -306,6 +371,9 @@ const handleSearchMedicos = (term) => {
className='dropdown-item'
onClick={() => {
setSearchTermDoctor(medico.nomeMedico);
setFiltredTodosMedicos([]);
setMedicoFiltrado(medico)
}}
>
<p>{medico.nomeMedico} </p>
@ -336,6 +404,7 @@ const handleSearchMedicos = (term) => {
}}
>
Fila de espera
</button>
</div>
@ -364,10 +433,10 @@ const handleSearchMedicos = (term) => {
</div>
</section>
{/* Componentes de Tabela - Adicionado props de delete da main */}
{tabela === "diario" && <TabelaAgendamentoDia handleClickAgendamento={handleClickAgendamento} agendamentos={DictAgendamentosOrganizados} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} />}
{tabela === 'semanal' && <TabelaAgendamentoSemana agendamentos={DictAgendamentosOrganizados} ListarDiasdoMes={ListarDiasdoMes} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo}/>}
{tabela === 'mensal' && <TabelaAgendamentoMes ListarDiasdoMes={ListarDiasdoMes} aplicarCores={true} agendamentos={DictAgendamentosOrganizados} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} setDictInfo={setDictInfo} />}
{/* Componentes de Tabela - Adicionado props de delete da main */}
{tabela === "diario" && <TabelaAgendamentoDia handleClickAgendamento={handleClickAgendamento} agendamentos={DictAgendamentosOrganizados} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} selectedID={selectedID} setDictInfo={setDictInfo} setShowConfirmModal={setShowConfirmModal} coresConsultas={coresConsultas} setListaConsultaID={setListaConsultaID} listaConsultasID={listaConsultasID} />}
{tabela === 'semanal' && <TabelaAgendamentoSemana agendamentos={DictAgendamentosOrganizados} ListarDiasdoMes={ListarDiasdoMes} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} selectedID={selectedID} setDictInfo={setDictInfo} setShowConfirmModal={setShowConfirmModal} corModal={corModal}/>}
{tabela === 'mensal' && <TabelaAgendamentoMes ListarDiasdoMes={ListarDiasdoMes} aplicarCores={true} agendamentos={DictAgendamentosOrganizados} setShowDeleteModal={setShowDeleteModal} setSelectedId={setSelectedId} selectedID={selectedID} setDictInfo={setDictInfo} setShowConfirmModal={setShowConfirmModal} corModal={corModal}/>}
</div>
</div>
)
@ -455,7 +524,7 @@ const handleSearchMedicos = (term) => {
<div className="modal-header bg-danger bg-opacity-25">
<h5 className="modal-title text-danger">
Confirmação de Exclusão
Confirmação de Cancelamento
</h5>
<button
type="button"
@ -466,8 +535,12 @@ const handleSearchMedicos = (term) => {
<div className="modal-body">
<p className="mb-0 fs-5">
Tem certeza que deseja excluir este agendamento?
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">
@ -475,7 +548,9 @@ const handleSearchMedicos = (term) => {
<button
type="button"
className="btn btn-primary"
onClick={() => setShowDeleteModal(false)}
onClick={() => {setShowDeleteModal(false);
}}
>
Cancelar
</button>
@ -484,7 +559,22 @@ const handleSearchMedicos = (term) => {
<button
type="button"
className="btn btn-danger"
onClick={() => {deleteConsulta(selectedID);setShowDeleteModal(false)}}
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
@ -494,6 +584,79 @@ const handleSearchMedicos = (term) => {
</div>
</div>)}
{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>)
}
</div>
)

View File

@ -13,8 +13,7 @@ const AgendamentoEditPage = ({setDictInfo, DictInfo}) => {
//let DataAtual = dayjs()
const {getAuthorizationHeader} = useAuth()
const params = useParams()
const [PatientToPatch, setPatientToPatch] = useState({})
let id = params.id
console.log(DictInfo, "DENTRO DO EDITAR")
@ -22,8 +21,7 @@ const AgendamentoEditPage = ({setDictInfo, DictInfo}) => {
//console.log(DictInfo, 'aqui')
useEffect(() => {
setDictInfo({...DictInfo?.Infos,...DictInfo?.agendamento})
setDictInfo({...DictInfo, dataAtendimento:DictInfo.scheduled_at.split("T")[0]})
const ColherInfoUsuario =async () => {
const result = await UserInfos(authHeader)

View File

@ -1,11 +1,13 @@
import React, { useState, useEffect, use } from "react";
import React, { useState, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";
import { useAuth } from "../components/utils/AuthProvider";
import API_KEY from "../components/utils/apiKeys";
import { UserInfos } from "../components/utils/Functions-Endpoints/General";
import CabecalhoError from "../components/utils/fetchErros/CabecalhoError";
function Login({ onEnterSystem }) {
const { setAuthTokens } = useAuth();
const [showCabecalho, setShowCabecalho ] = useState(false)
const navigate = useNavigate();
const [form, setForm] = useState({
username: "",
@ -126,6 +128,9 @@ function Login({ onEnterSystem }) {
} else if (UserData?.roles?.includes("financeiro")) {
navigate(`/financeiro/`);
}
}else{
console.log("ERROROROROROOR")
setShowCabecalho(true)
}
} else {
setAlert("Preencha todos os campos!");
@ -148,11 +153,7 @@ function Login({ onEnterSystem }) {
<p className="auth-subtitle mb-5">
Entre com os dados que você inseriu durante o registro.
</p>
{alert && (
<div className="alert alert-info" role="alert">
{alert}
</div>
)}
<CabecalhoError showCabecalho={showCabecalho} message={"E-mail ou senha incorretos."}/>
<form onSubmit={handleLogin}>
<div className="form-group position-relative has-icon-left mb-4">
<input

View File

@ -4,6 +4,8 @@ import API_KEY from "../components/utils/apiKeys";
import { useAuth } from "../components/utils/AuthProvider";
import "./style/TablePaciente.css";
import ModalErro from "../components/utils/fetchErros/ModalErro";
import manager from "../components/utils/fetchErros/ManagerFunction";
function TablePaciente({ setCurrentPage, setPatientID }) {
const { getAuthorizationHeader, isAuthenticated, RefreshingToken } = useAuth();
@ -24,7 +26,7 @@ function TablePaciente({ setCurrentPage, setPatientID }) {
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [selectedPatientId, setSelectedPatientId] = useState(null);
const [showModalError, setShowModalError] = useState(false);
const [showModalError, setShowModalError] = useState("");
const [ ErrorInfo, setErrorInfo] = useState({})
@ -117,7 +119,7 @@ function TablePaciente({ setCurrentPage, setPatientID }) {
redirect: 'follow'
};
fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patients", requestOptions)
fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patient", requestOptions)
.then(response => {
// 1. VERIFICAÇÃO DO STATUS HTTP (Se não for 2xx)
@ -142,21 +144,15 @@ function TablePaciente({ setCurrentPage, setPatientID }) {
return response.json();
})
.then(result => {
// 4. Bloco de SUCESSO
setPacientes(result);
console.log("Sucesso:", result);
// IMPORTANTE: Se o modal estava aberto, feche-o no sucesso
setShowModalError(false);
})
.catch(error => {
// 5. Bloco de ERRO (Captura erros de rede ou o erro lançado pelo 'throw')
//console.error('Falha na requisição:', error.message);
if(error.httpStatus === 401){
RefreshingToken()
}
setErrorInfo(error)
setShowModalError(true);
manager(setShowModalError, RefreshingToken, setErrorInfo, error)
});
}, [isAuthenticated, getAuthorizationHeader]);

View File

@ -426,4 +426,10 @@ html[data-bs-theme="dark"] {
.dropdown-item:hover {
background-color: #f0f0f0; /* Cor ao passar o mouse */
color: #007bff;
}
}
.input-modal{
width: 80%;
}