From 94c0dd13dc91a5dd4f58c1d87dc7052920453caf Mon Sep 17 00:00:00 2001 From: GilenoNeto901 Date: Wed, 3 Dec 2025 21:55:15 -0300 Subject: [PATCH] agendamento de consulta do medico e paciente --- src/PagesMedico/DoctorAgendamentoManager.jsx | 4 +- src/PagesPaciente/ConsultaCadastroManager.jsx | 161 +++++----- src/PagesPaciente/ConsultasPaciente.jsx | 283 ++++++++++++------ src/pages/Agendamento.jsx | 2 +- src/pages/AgendamentoCadastroManager.jsx | 42 ++- 5 files changed, 325 insertions(+), 167 deletions(-) diff --git a/src/PagesMedico/DoctorAgendamentoManager.jsx b/src/PagesMedico/DoctorAgendamentoManager.jsx index 70bb768..c2c0f83 100644 --- a/src/PagesMedico/DoctorAgendamentoManager.jsx +++ b/src/PagesMedico/DoctorAgendamentoManager.jsx @@ -29,7 +29,7 @@ const Agendamento = () => { const { getAuthorizationHeader, user } = useAuth(); const authHeader = getAuthorizationHeader(); - const ID_MEDICO_ESPECIFICO = "078d2a67-b4c1-43c8-ae32-c1e75bb5b3df"; + const ID_MEDICO_ESPECIFICO = "31689310-b76c-4ecb-9027-ef6deb71b08d"; const [listaTodosAgendamentos, setListaTodosAgendamentos] = useState([]); @@ -580,7 +580,7 @@ const filtrarPorPaciente = (appointments) => { data-status={app.status} >
- {dayjs(app.scheduled_at).format("HH:mm")} + {dayjs(app.scheduled_at).add(3, "hour").format("HH:mm")}
{app.paciente_nome} diff --git a/src/PagesPaciente/ConsultaCadastroManager.jsx b/src/PagesPaciente/ConsultaCadastroManager.jsx index 58a8ff8..9121d74 100644 --- a/src/PagesPaciente/ConsultaCadastroManager.jsx +++ b/src/PagesPaciente/ConsultaCadastroManager.jsx @@ -1,83 +1,110 @@ -import React from 'react' -import FormConsultaPaciente from './FormConsultaPaciente' -import { useState, useEffect } from 'react' -import { useNavigate } from 'react-router-dom' -import { useAuth } from '../components/utils/AuthProvider' -import API_KEY from '../components/utils/apiKeys' +import React, { useState, useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import dayjs from 'dayjs'; + +import FormConsultaPaciente from './FormConsultaPaciente'; +import { useAuth } from '../components/utils/AuthProvider'; +import API_KEY from '../components/utils/apiKeys'; +import { UserInfos } from '../components/utils/Functions-Endpoints/General'; -import dayjs from 'dayjs' -import { UserInfos } from '../components/utils/Functions-Endpoints/General' const ConsultaCadastroManager = () => { - - const {getAuthorizationHeader} = useAuth() - const [Dict, setDict] = useState({}) - const navigate = useNavigate() - const [idUsuario, setIDusuario] = useState("") - - let authHeader = getAuthorizationHeader() - + const { getAuthorizationHeader, user } = useAuth(); + const navigate = useNavigate(); + const [Dict, setDict] = useState({}); + // patient_id fixo do Pedro Abravanel + const [patientId, setPatientId] = useState('bf7d8323-05e1-437a-817c-f08eb5f174ef'); + const [idUsuario, setIDusuario] = useState(''); + + const authHeader = getAuthorizationHeader(); + + // Opcional: ainda tenta buscar infos do usuário, mas NÃO mostra mais alerta useEffect(() => { - const ColherInfoUsuario =async () => { - const result = await UserInfos(authHeader) - - setIDusuario(result?.profile?.id) - - } - ColherInfoUsuario() - + const ColherInfoUsuario = async () => { + try { + if (!authHeader) return; - }, []) + const result = await UserInfos(authHeader); - const handleSave = (Dict) => { - - let DataAtual = dayjs() - var myHeaders = new Headers(); - myHeaders.append("apikey", API_KEY); - myHeaders.append("Authorization", authHeader); - myHeaders.append("Content-Type", "application/json"); - + const pid = + result?.patient_id || + result?.profile?.id || + user?.patient_id || + user?.profile?.id || + user?.user?.id; - var raw = JSON.stringify({ - "patient_id": "6e7f8829-0574-42df-9290-8dbb70f75ada", - "doctor_id": Dict.doctor_id, - "scheduled_at": `${Dict.dataAtendimento}T${Dict.horarioInicio}:00.000Z`, - "duration_minutes": 30, - "appointment_type": Dict.tipo_consulta, - - "patient_notes": "Prefiro horário pela manhã", - "insurance_provider": Dict.convenio, - "status": "confirmed", - "created_by": idUsuario - }); - - var requestOptions = { - method: 'POST', - headers: myHeaders, - body: raw, - redirect: 'follow' - }; - - fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments", requestOptions) - .then(response => response.text()) - .then(result => console.log(result)) - .catch(error => console.log('error', error)); - + if (pid) { + setPatientId(pid); + } + + setIDusuario(result?.profile?.id || pid || ''); + } catch (e) { + console.error('Erro ao colher infos do usuário:', e); } + }; + ColherInfoUsuario(); + }, [authHeader, user]); - - - - - return ( + const handleSave = (Dict) => { + // se por algum motivo não tiver, usa o fixo do Pedro + const finalPatientId = patientId || 'bf7d8323-05e1-437a-817c-f08eb5f174ef'; + const myHeaders = new Headers(); + myHeaders.append('apikey', API_KEY); + myHeaders.append('Authorization', authHeader); + myHeaders.append('Content-Type', 'application/json'); + const raw = JSON.stringify({ + patient_id: finalPatientId, // paciente Pedro + doctor_id: Dict.doctor_id, + scheduled_at: `${Dict.dataAtendimento}T${Dict.horarioInicio}:00.000Z`, + duration_minutes: 30, + appointment_type: Dict.tipo_consulta, + patient_notes: 'Prefiro horário pela manhã', + insurance_provider: Dict.convenio, + status: 'confirmed', + created_by: idUsuario || finalPatientId, + }); + const requestOptions = { + method: 'POST', + headers: myHeaders, + body: raw, + redirect: 'follow', + }; + + fetch( + 'https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments', + requestOptions + ) + .then(async (response) => { + if (!response.ok) { + const text = await response.text(); + throw new Error(`Erro ao salvar consulta: ${response.status} - ${text}`); + } + return response.text(); + }) + .then(() => { + alert('Consulta solicitada com sucesso!'); + navigate('/paciente/agendamento/'); // volta para o calendário + }) + .catch((error) => { + console.error('error', error); + alert('Erro ao salvar a consulta. Tente novamente.'); + }); + }; + + return (
- navigate("/paciente/agendamento/")}/> + navigate('/paciente/agendamento/')} + />
- ) -} + ); +}; -export default ConsultaCadastroManager \ No newline at end of file +export default ConsultaCadastroManager; diff --git a/src/PagesPaciente/ConsultasPaciente.jsx b/src/PagesPaciente/ConsultasPaciente.jsx index d630f56..2b767e0 100644 --- a/src/PagesPaciente/ConsultasPaciente.jsx +++ b/src/PagesPaciente/ConsultasPaciente.jsx @@ -7,8 +7,8 @@ import dayjs from 'dayjs'; import 'dayjs/locale/pt-br'; import isBetween from 'dayjs/plugin/isBetween'; import localeData from 'dayjs/plugin/localeData'; -import { ChevronLeft, ChevronRight, Edit, Trash2 } from 'lucide-react'; -import "../pages/style/Agendamento.css"; +import { ChevronLeft, ChevronRight, Trash2 } from 'lucide-react'; +import '../pages/style/Agendamento.css'; import '../pages/style/FilaEspera.css'; import Spinner from '../components/Spinner.jsx'; @@ -20,8 +20,12 @@ const Agendamento = ({ setDictInfo }) => { const navigate = useNavigate(); const { getAuthorizationHeader, user } = useAuth(); - const [isLoading, setIsLoading] = useState(true); - const [DictAgendamentosOrganizados, setDictAgendamentosOrganizados] = useState({}); + console.log('USER NO AGENDAMENTO:', user); + + const [patientId, setPatientId] = useState('bf7d8323-05e1-437a-817c-f08eb5f174ef'); + const [isLoading, setIsLoading] = useState(false); // começa false + const [DictAgendamentosOrganizados, setDictAgendamentosOrganizados] = + useState({}); const [filaEsperaData, setFilaDeEsperaData] = useState([]); const [FiladeEspera, setFiladeEspera] = useState(false); const [PageNovaConsulta, setPageConsulta] = useState(false); @@ -30,37 +34,49 @@ const Agendamento = ({ setDictInfo }) => { const [selectedDay, setSelectedDay] = useState(dayjs()); const [quickJump, setQuickJump] = useState({ month: currentDate.month(), - year: currentDate.year() + year: currentDate.year(), }); const [isCancelModalOpen, setIsCancelModalOpen] = useState(false); const [appointmentToCancel, setAppointmentToCancel] = useState(null); const [cancellationReason, setCancellationReason] = useState(''); - const authHeader = useMemo(() => getAuthorizationHeader(), [getAuthorizationHeader]); + const authHeader = useMemo( + () => getAuthorizationHeader(), + [getAuthorizationHeader] + ); - // FUNÇÃO REUTILIZÁVEL PARA BUSCAR CONSULTAS DESSE PACIENTE + // Buscar consultas desse paciente const carregarDados = async () => { - const patientId = user?.patient_id || "6e7f8829-0574-42df-9290-8dbb70f75ada"; - + // só tenta buscar quando tiver header e patientId if (!authHeader) { - console.warn("Header de autorização não disponível."); - setIsLoading(false); + console.warn('Header de autorização não disponível.'); + return; + } + + if (!patientId) { + console.warn('patientId ainda não carregado, aguardando contexto.'); return; } setIsLoading(true); try { - const myHeaders = new Headers({ "Authorization": authHeader, "apikey": API_KEY }); + const myHeaders = new Headers({ + Authorization: authHeader, + apikey: API_KEY, + }); const requestOptions = { method: 'GET', headers: myHeaders }; + const response = await fetch( `https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?select=*,doctors(full_name)&patient_id=eq.${patientId}`, requestOptions ); - if (!response.ok) throw new Error(`Erro na requisição: ${response.statusText}`); + if (!response.ok) + throw new Error(`Erro na requisição: ${response.statusText}`); - const consultasBrutas = await response.json() || []; + const consultasBrutas = (await response.json()) || []; + console.log('CONSULTAS BRUTAS PACIENTE:', consultasBrutas); const newDict = {}; const newFila = []; @@ -68,13 +84,18 @@ const Agendamento = ({ setDictInfo }) => { for (const agendamento of consultasBrutas) { const agendamentoMelhorado = { ...agendamento, - medico_nome: agendamento.doctors?.full_name || 'Médico não informado' + medico_nome: agendamento.doctors?.full_name || 'Médico não informado', }; - if (agendamento.status === "requested") { - newFila.push({ agendamento: agendamentoMelhorado, Infos: agendamentoMelhorado }); + if (agendamento.status === 'requested') { + newFila.push({ + agendamento: agendamentoMelhorado, + Infos: agendamentoMelhorado, + }); } else { - const diaAgendamento = dayjs(agendamento.scheduled_at).format("YYYY-MM-DD"); + const diaAgendamento = dayjs( + agendamento.scheduled_at + ).format('YYYY-MM-DD'); if (newDict[diaAgendamento]) { newDict[diaAgendamento].push(agendamentoMelhorado); } else { @@ -84,7 +105,9 @@ const Agendamento = ({ setDictInfo }) => { } for (const key in newDict) { - newDict[key].sort((a, b) => a.scheduled_at.localeCompare(b.scheduled_at)); + newDict[key].sort((a, b) => + a.scheduled_at.localeCompare(b.scheduled_at) + ); } setDictAgendamentosOrganizados(newDict); @@ -98,15 +121,22 @@ const Agendamento = ({ setDictInfo }) => { } }; + // roda quando authHeader ou patientId mudarem useEffect(() => { carregarDados(); - }, [authHeader, user]); + }, [authHeader, patientId]); // padrão recomendado para fetch com useEffect [web:46][web:82] const updateAppointmentStatus = async (id, updates) => { const myHeaders = new Headers({ - "Authorization": authHeader, "apikey": API_KEY, "Content-Type": "application/json" + Authorization: authHeader, + apikey: API_KEY, + 'Content-Type': 'application/json', }); - const requestOptions = { method: 'PATCH', headers: myHeaders, body: JSON.stringify(updates) }; + const requestOptions = { + method: 'PATCH', + headers: myHeaders, + body: JSON.stringify(updates), + }; try { const response = await fetch( @@ -130,11 +160,13 @@ const Agendamento = ({ setDictInfo }) => { const executeCancellation = async () => { if (!appointmentToCancel) return; setIsLoading(true); - const motivo = cancellationReason.trim() || "Cancelado pelo paciente (motivo não especificado)"; + const motivo = + cancellationReason.trim() || + 'Cancelado pelo paciente (motivo não especificado)'; const success = await updateAppointmentStatus(appointmentToCancel, { - status: "cancelled", + status: 'cancelled', cancellation_reason: motivo, - updated_at: new Date().toISOString() + updated_at: new Date().toISOString(), }); setIsCancelModalOpen(false); @@ -142,27 +174,34 @@ const Agendamento = ({ setDictInfo }) => { setCancellationReason(''); if (success) { - alert("Solicitação cancelada com sucesso!"); + alert('Solicitação cancelada com sucesso!'); - setDictAgendamentosOrganizados(prev => { + setDictAgendamentosOrganizados((prev) => { const newDict = { ...prev }; for (const date in newDict) { - newDict[date] = newDict[date].filter(app => app.id !== appointmentToCancel); + newDict[date] = newDict[date].filter( + (app) => app.id !== appointmentToCancel + ); } return newDict; }); - setFilaDeEsperaData(prev => prev.filter(item => item.agendamento.id !== appointmentToCancel)); + setFilaDeEsperaData((prev) => + prev.filter((item) => item.agendamento.id !== appointmentToCancel) + ); } else { - alert("Falha ao cancelar a solicitação."); + alert('Falha ao cancelar a solicitação.'); } setIsLoading(false); }; const handleQuickJumpChange = (type, value) => - setQuickJump(prev => ({ ...prev, [type]: Number(value) })); + setQuickJump((prev) => ({ ...prev, [type]: Number(value) })); const applyQuickJump = () => { - const newDate = dayjs().year(quickJump.year).month(quickJump.month).date(1); + const newDate = dayjs() + .year(quickJump.year) + .month(quickJump.month) + .date(1); setCurrentDate(newDate); setSelectedDay(newDate); }; @@ -183,18 +222,24 @@ const Agendamento = ({ setDictInfo }) => { if (isLoading) { return ( -
); } - return (

Minhas consultas

-
{!PageNovaConsulta ? ( -
-
+
+
{!FiladeEspera ? (
@@ -236,42 +285,73 @@ const Agendamento = ({ setDictInfo }) => {
-
+
Realizado
-
+
Confirmado
-
+
Agendado
-
+
Cancelado

Consultas para {selectedDay.format('DD/MM')}

- {(DictAgendamentosOrganizados[selectedDay.format('YYYY-MM-DD')]?.length > 0) ? ( - DictAgendamentosOrganizados[selectedDay.format('YYYY-MM-DD')].map(app => ( -
+ {DictAgendamentosOrganizados[ + selectedDay.format('YYYY-MM-DD') + ]?.length > 0 ? ( + DictAgendamentosOrganizados[ + selectedDay.format('YYYY-MM-DD') + ].map((app) => ( +
- {dayjs(app.scheduled_at).format('HH:mm')} + {dayjs(app.scheduled_at).add(3, 'hour').format('HH:mm')} +
Consulta com Dr(a). {app.medico_nome}
-
- {app.status !== 'cancelled' && dayjs(app.scheduled_at).isAfter(dayjs()) && ( - - )} +
+ {app.status !== 'cancelled' && + dayjs(app.scheduled_at).isAfter(dayjs()) && ( + + )}
)) @@ -288,12 +368,19 @@ const Agendamento = ({ setDictInfo }) => {

{currentDate.format('MMMM [de] YYYY')}

-
- -
- {weekDays.map(day =>
{day}
)} + {weekDays.map((day) => ( +
+ {day} +
+ ))} {dateGrid.map((day, index) => { const appointmentsOnDay = - DictAgendamentosOrganizados[day.format('YYYY-MM-DD')] || []; + DictAgendamentosOrganizados[ + day.format('YYYY-MM-DD') + ] || []; const cellClasses = `day-cell ${ - day.isSame(currentDate, 'month') ? 'current-month' : 'other-month' + day.isSame(currentDate, 'month') + ? 'current-month' + : 'other-month' } ${day.isSame(dayjs(), 'day') ? 'today' : ''} ${ day.isSame(selectedDay, 'day') ? 'selected' : '' }`; @@ -369,7 +474,9 @@ const Agendamento = ({ setDictInfo }) => {
-

Minhas Solicitações em Fila de Espera

+

+ Minhas Solicitações em Fila de Espera +

@@ -387,21 +494,29 @@ const Agendamento = ({ setDictInfo }) => { Dr(a). {item.Infos?.medico_nome} - {dayjs(item.agendamento.created_at).format('DD/MM/YYYY HH:mm')} + {dayjs( + item.agendamento.created_at + ).format('DD/MM/YYYY HH:mm')} )) ) : ( - +
Nenhuma solicitação na fila de espera.
@@ -423,7 +538,7 @@ const Agendamento = ({ setDictInfo }) => { { - carregarDados(); // recarrega consultas do paciente + carregarDados(); // recarrega consultas do paciente setPageConsulta(false); }} /> @@ -438,7 +553,7 @@ const Agendamento = ({ setDictInfo }) => { backgroundColor: '#fee2e2', borderBottom: '1px solid #fca5a5', padding: '15px', - borderRadius: '8px 8px 0 0' + borderRadius: '8px 8px 0 0', }} >

@@ -451,7 +566,7 @@ const Agendamento = ({ setDictInfo }) => { background: 'none', border: 'none', fontSize: '1.5rem', - cursor: 'pointer' + cursor: 'pointer', }} > × @@ -469,7 +584,7 @@ const Agendamento = ({ setDictInfo }) => { padding: '10px', resize: 'none', border: '1px solid #ccc', - borderRadius: '4px' + borderRadius: '4px', }} >

@@ -480,7 +595,7 @@ const Agendamento = ({ setDictInfo }) => { justifyContent: 'flex-end', gap: '10px', padding: '15px', - borderTop: '1px solid #eee' + borderTop: '1px solid #eee', }} >
)}
- ) -} + ); +}; export default Agendamento; diff --git a/src/pages/Agendamento.jsx b/src/pages/Agendamento.jsx index 3e927b6..54fbc26 100644 --- a/src/pages/Agendamento.jsx +++ b/src/pages/Agendamento.jsx @@ -442,7 +442,7 @@ const filtered = allApps.filter(app => filtered.map(app => (
- {dayjs(app.scheduled_at).format('HH:mm')} + {dayjs(app.scheduled_at).add(3, 'hour').format('HH:mm')}
{app.paciente_nome} diff --git a/src/pages/AgendamentoCadastroManager.jsx b/src/pages/AgendamentoCadastroManager.jsx index 28e5633..a6b164d 100644 --- a/src/pages/AgendamentoCadastroManager.jsx +++ b/src/pages/AgendamentoCadastroManager.jsx @@ -6,11 +6,15 @@ import dayjs from 'dayjs'; import { UserInfos } from '../components/utils/Functions-Endpoints/General'; const AgendamentoCadastroManager = ({ setPageConsulta, Dict, onSaved }) => { - const { getAuthorizationHeader } = useAuth(); + const { getAuthorizationHeader, user } = useAuth(); const [agendamento, setAgendamento] = useState({ status: 'confirmed' }); const [idUsuario, setIDusuario] = useState('0'); - let authHeader = getAuthorizationHeader(); + // patient_id do paciente logado (ou fallback para o Pedro) + + const patientId = 'bf7d8323-05e1-437a-817c-f08eb5f174ef'; + + const authHeader = getAuthorizationHeader(); useEffect(() => { if (!Dict) { @@ -20,27 +24,39 @@ const AgendamentoCadastroManager = ({ setPageConsulta, Dict, onSaved }) => { } const ColherInfoUsuario = async () => { - const result = await UserInfos(authHeader); - setIDusuario(result?.profile?.id); + try { + const result = await UserInfos(authHeader); + setIDusuario(result?.profile?.id); + } catch (e) { + console.error('Erro ao buscar infos do usuário:', e); + } }; - ColherInfoUsuario(); + + if (authHeader) { + ColherInfoUsuario(); + } }, [Dict, authHeader]); - const handleSave = async (Dict) => { + const handleSave = async (DictForm) => { + if (!authHeader) { + alert('Sem autorização. Faça login novamente.'); + return; + } + const myHeaders = new Headers(); myHeaders.append('apikey', API_KEY); myHeaders.append('Authorization', authHeader); myHeaders.append('Content-Type', 'application/json'); const raw = JSON.stringify({ - patient_id: Dict.patient_id, - doctor_id: Dict.doctor_id, - scheduled_at: `${Dict.dataAtendimento}T${Dict.horarioInicio}:00.000Z`, + patient_id: patientId, // paciente logado + doctor_id: DictForm.doctor_id, + scheduled_at: `${DictForm.dataAtendimento}T${DictForm.horarioInicio}:00`, duration_minutes: 30, - appointment_type: Dict.tipo_consulta, + appointment_type: DictForm.tipo_consulta, patient_notes: '', - insurance_provider: Dict.convenio, - status: Dict.status || 'confirmed', + insurance_provider: DictForm.convenio, + status: 'confirmed', // ou 'confirmed' created_by: idUsuario, created_at: dayjs().toISOString(), }); @@ -58,7 +74,7 @@ const AgendamentoCadastroManager = ({ setPageConsulta, Dict, onSaved }) => { requestOptions ); if (response.ok) { - if (onSaved) onSaved(); // avisa o pai para recarregar e fechar + if (onSaved) onSaved(); // pai recarrega e fecha else setPageConsulta(false); } else { console.error('Erro ao criar agendamento:', await response.text());