agendamento de consulta do medico e paciente

This commit is contained in:
GilenoNeto901 2025-12-03 21:55:15 -03:00
parent 6f3a49575c
commit 94c0dd13dc
5 changed files with 325 additions and 167 deletions

View File

@ -29,7 +29,7 @@ const Agendamento = () => {
const { getAuthorizationHeader, user } = useAuth(); const { getAuthorizationHeader, user } = useAuth();
const authHeader = getAuthorizationHeader(); 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([]); const [listaTodosAgendamentos, setListaTodosAgendamentos] = useState([]);
@ -580,7 +580,7 @@ const filtrarPorPaciente = (appointments) => {
data-status={app.status} data-status={app.status}
> >
<div className="item-time"> <div className="item-time">
{dayjs(app.scheduled_at).format("HH:mm")} {dayjs(app.scheduled_at).add(3, "hour").format("HH:mm")}
</div> </div>
<div className="item-details"> <div className="item-details">
<span>{app.paciente_nome}</span> <span>{app.paciente_nome}</span>

View File

@ -1,83 +1,110 @@
import React from 'react' import React, { useState, useEffect } from 'react';
import FormConsultaPaciente from './FormConsultaPaciente' import { useNavigate } from 'react-router-dom';
import { useState, useEffect } from 'react' import dayjs from 'dayjs';
import { useNavigate } from 'react-router-dom'
import { useAuth } from '../components/utils/AuthProvider' import FormConsultaPaciente from './FormConsultaPaciente';
import API_KEY from '../components/utils/apiKeys' 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 ConsultaCadastroManager = () => {
const { getAuthorizationHeader, user } = useAuth();
const navigate = useNavigate();
const {getAuthorizationHeader} = useAuth() const [Dict, setDict] = useState({});
const [Dict, setDict] = useState({}) // patient_id fixo do Pedro Abravanel
const navigate = useNavigate() const [patientId, setPatientId] = useState('bf7d8323-05e1-437a-817c-f08eb5f174ef');
const [idUsuario, setIDusuario] = useState("") const [idUsuario, setIDusuario] = useState('');
let authHeader = getAuthorizationHeader()
const authHeader = getAuthorizationHeader();
// Opcional: ainda tenta buscar infos do usuário, mas NÃO mostra mais alerta
useEffect(() => { useEffect(() => {
const ColherInfoUsuario =async () => { const ColherInfoUsuario = async () => {
const result = await UserInfos(authHeader) try {
if (!authHeader) return;
setIDusuario(result?.profile?.id) const result = await UserInfos(authHeader);
} const pid =
ColherInfoUsuario() result?.patient_id ||
result?.profile?.id ||
user?.patient_id ||
user?.profile?.id ||
user?.user?.id;
if (pid) {
setPatientId(pid);
}
}, []) setIDusuario(result?.profile?.id || pid || '');
} catch (e) {
const handleSave = (Dict) => { console.error('Erro ao colher infos do usuário:', e);
}
let DataAtual = dayjs()
var myHeaders = new Headers();
myHeaders.append("apikey", API_KEY);
myHeaders.append("Authorization", authHeader);
myHeaders.append("Content-Type", "application/json");
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) ColherInfoUsuario();
.then(response => response.text()) }, [authHeader, user]);
.then(result => console.log(result))
.catch(error => console.log('error', error));
} 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 (
return (
<div> <div>
<FormConsultaPaciente agendamento={Dict} setAgendamento={setDict} onSave={handleSave} onCancel={() => navigate("/paciente/agendamento/")}/> <FormConsultaPaciente
agendamento={Dict}
setAgendamento={setDict}
onSave={handleSave}
onCancel={() => navigate('/paciente/agendamento/')}
/>
</div> </div>
) );
} };
export default ConsultaCadastroManager export default ConsultaCadastroManager;

View File

@ -7,8 +7,8 @@ import dayjs from 'dayjs';
import 'dayjs/locale/pt-br'; import 'dayjs/locale/pt-br';
import isBetween from 'dayjs/plugin/isBetween'; import isBetween from 'dayjs/plugin/isBetween';
import localeData from 'dayjs/plugin/localeData'; import localeData from 'dayjs/plugin/localeData';
import { ChevronLeft, ChevronRight, Edit, Trash2 } from 'lucide-react'; import { ChevronLeft, ChevronRight, Trash2 } from 'lucide-react';
import "../pages/style/Agendamento.css"; import '../pages/style/Agendamento.css';
import '../pages/style/FilaEspera.css'; import '../pages/style/FilaEspera.css';
import Spinner from '../components/Spinner.jsx'; import Spinner from '../components/Spinner.jsx';
@ -20,8 +20,12 @@ const Agendamento = ({ setDictInfo }) => {
const navigate = useNavigate(); const navigate = useNavigate();
const { getAuthorizationHeader, user } = useAuth(); const { getAuthorizationHeader, user } = useAuth();
const [isLoading, setIsLoading] = useState(true); console.log('USER NO AGENDAMENTO:', user);
const [DictAgendamentosOrganizados, setDictAgendamentosOrganizados] = useState({});
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 [filaEsperaData, setFilaDeEsperaData] = useState([]);
const [FiladeEspera, setFiladeEspera] = useState(false); const [FiladeEspera, setFiladeEspera] = useState(false);
const [PageNovaConsulta, setPageConsulta] = useState(false); const [PageNovaConsulta, setPageConsulta] = useState(false);
@ -30,37 +34,49 @@ const Agendamento = ({ setDictInfo }) => {
const [selectedDay, setSelectedDay] = useState(dayjs()); const [selectedDay, setSelectedDay] = useState(dayjs());
const [quickJump, setQuickJump] = useState({ const [quickJump, setQuickJump] = useState({
month: currentDate.month(), month: currentDate.month(),
year: currentDate.year() year: currentDate.year(),
}); });
const [isCancelModalOpen, setIsCancelModalOpen] = useState(false); const [isCancelModalOpen, setIsCancelModalOpen] = useState(false);
const [appointmentToCancel, setAppointmentToCancel] = useState(null); const [appointmentToCancel, setAppointmentToCancel] = useState(null);
const [cancellationReason, setCancellationReason] = useState(''); 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 carregarDados = async () => {
const patientId = user?.patient_id || "6e7f8829-0574-42df-9290-8dbb70f75ada"; // só tenta buscar quando tiver header e patientId
if (!authHeader) { if (!authHeader) {
console.warn("Header de autorização não disponível."); console.warn('Header de autorização não disponível.');
setIsLoading(false); return;
}
if (!patientId) {
console.warn('patientId ainda não carregado, aguardando contexto.');
return; return;
} }
setIsLoading(true); setIsLoading(true);
try { 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 requestOptions = { method: 'GET', headers: myHeaders };
const response = await fetch( const response = await fetch(
`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?select=*,doctors(full_name)&patient_id=eq.${patientId}`, `https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?select=*,doctors(full_name)&patient_id=eq.${patientId}`,
requestOptions 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 newDict = {};
const newFila = []; const newFila = [];
@ -68,13 +84,18 @@ const Agendamento = ({ setDictInfo }) => {
for (const agendamento of consultasBrutas) { for (const agendamento of consultasBrutas) {
const agendamentoMelhorado = { const agendamentoMelhorado = {
...agendamento, ...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") { if (agendamento.status === 'requested') {
newFila.push({ agendamento: agendamentoMelhorado, Infos: agendamentoMelhorado }); newFila.push({
agendamento: agendamentoMelhorado,
Infos: agendamentoMelhorado,
});
} else { } else {
const diaAgendamento = dayjs(agendamento.scheduled_at).format("YYYY-MM-DD"); const diaAgendamento = dayjs(
agendamento.scheduled_at
).format('YYYY-MM-DD');
if (newDict[diaAgendamento]) { if (newDict[diaAgendamento]) {
newDict[diaAgendamento].push(agendamentoMelhorado); newDict[diaAgendamento].push(agendamentoMelhorado);
} else { } else {
@ -84,7 +105,9 @@ const Agendamento = ({ setDictInfo }) => {
} }
for (const key in newDict) { 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); setDictAgendamentosOrganizados(newDict);
@ -98,15 +121,22 @@ const Agendamento = ({ setDictInfo }) => {
} }
}; };
// roda quando authHeader ou patientId mudarem
useEffect(() => { useEffect(() => {
carregarDados(); carregarDados();
}, [authHeader, user]); }, [authHeader, patientId]); // padrão recomendado para fetch com useEffect [web:46][web:82]
const updateAppointmentStatus = async (id, updates) => { const updateAppointmentStatus = async (id, updates) => {
const myHeaders = new Headers({ 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 { try {
const response = await fetch( const response = await fetch(
@ -130,11 +160,13 @@ const Agendamento = ({ setDictInfo }) => {
const executeCancellation = async () => { const executeCancellation = async () => {
if (!appointmentToCancel) return; if (!appointmentToCancel) return;
setIsLoading(true); 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, { const success = await updateAppointmentStatus(appointmentToCancel, {
status: "cancelled", status: 'cancelled',
cancellation_reason: motivo, cancellation_reason: motivo,
updated_at: new Date().toISOString() updated_at: new Date().toISOString(),
}); });
setIsCancelModalOpen(false); setIsCancelModalOpen(false);
@ -142,27 +174,34 @@ const Agendamento = ({ setDictInfo }) => {
setCancellationReason(''); setCancellationReason('');
if (success) { if (success) {
alert("Solicitação cancelada com sucesso!"); alert('Solicitação cancelada com sucesso!');
setDictAgendamentosOrganizados(prev => { setDictAgendamentosOrganizados((prev) => {
const newDict = { ...prev }; const newDict = { ...prev };
for (const date in newDict) { 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; return newDict;
}); });
setFilaDeEsperaData(prev => prev.filter(item => item.agendamento.id !== appointmentToCancel)); setFilaDeEsperaData((prev) =>
prev.filter((item) => item.agendamento.id !== appointmentToCancel)
);
} else { } else {
alert("Falha ao cancelar a solicitação."); alert('Falha ao cancelar a solicitação.');
} }
setIsLoading(false); setIsLoading(false);
}; };
const handleQuickJumpChange = (type, value) => const handleQuickJumpChange = (type, value) =>
setQuickJump(prev => ({ ...prev, [type]: Number(value) })); setQuickJump((prev) => ({ ...prev, [type]: Number(value) }));
const applyQuickJump = () => { 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); setCurrentDate(newDate);
setSelectedDay(newDate); setSelectedDay(newDate);
}; };
@ -183,18 +222,24 @@ const Agendamento = ({ setDictInfo }) => {
if (isLoading) { if (isLoading) {
return ( return (
<div className="form-container" <div
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '50vh' }} className="form-container"
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '50vh',
}}
> >
<Spinner /> <Spinner />
</div> </div>
); );
} }
return ( return (
<div> <div>
<h1>Minhas consultas</h1> <h1>Minhas consultas</h1>
<div className="btns-gerenciamento-e-consulta" <div
className="btns-gerenciamento-e-consulta"
style={{ display: 'flex', gap: '10px', marginBottom: '20px' }} style={{ display: 'flex', gap: '10px', marginBottom: '20px' }}
> >
<button <button
@ -213,15 +258,19 @@ const Agendamento = ({ setDictInfo }) => {
setFiladeEspera(!FiladeEspera); setFiladeEspera(!FiladeEspera);
setPageConsulta(false); setPageConsulta(false);
}} }}
style={{ backgroundColor: FiladeEspera && !PageNovaConsulta ? '#1d4ed8' : undefined }} style={{
backgroundColor:
FiladeEspera && !PageNovaConsulta ? '#1d4ed8' : undefined,
}}
> >
<i className="bi bi-list-task me-1"></i> Fila de Espera ({filaEsperaData.length}) <i className="bi bi-list-task me-1"></i> Fila de Espera (
{filaEsperaData.length})
</button> </button>
</div> </div>
{!PageNovaConsulta ? ( {!PageNovaConsulta ? (
<div className='atendimento-eprocura'> <div className="atendimento-eprocura">
<section className='calendario-ou-filaespera'> <section className="calendario-ou-filaespera">
{!FiladeEspera ? ( {!FiladeEspera ? (
<div className="calendar-wrapper"> <div className="calendar-wrapper">
<div className="calendar-info-panel"> <div className="calendar-info-panel">
@ -236,42 +285,73 @@ const Agendamento = ({ setDictInfo }) => {
<div className="appointments-list"> <div className="appointments-list">
<div <div
className="calendar-legend compact-legend" className="calendar-legend compact-legend"
style={{ marginTop: 4, gap: 3, fontSize: 8, lineHeight: 1.1 }} style={{
marginTop: 4,
gap: 3,
fontSize: 8,
lineHeight: 1.1,
}}
> >
<div className="legend-item" data-status="completed" style={{ padding: '0px 5px' }}> <div
className="legend-item"
data-status="completed"
style={{ padding: '0px 5px' }}
>
Realizado Realizado
</div> </div>
<div className="legend-item" data-status="confirmed" style={{ padding: '0px 5px' }}> <div
className="legend-item"
data-status="confirmed"
style={{ padding: '0px 5px' }}
>
Confirmado Confirmado
</div> </div>
<div className="legend-item" data-status="agendado" style={{ padding: '0px 5px' }}> <div
className="legend-item"
data-status="agendado"
style={{ padding: '0px 5px' }}
>
Agendado Agendado
</div> </div>
<div className="legend-item" data-status="cancelled" style={{ padding: '0px 5px' }}> <div
className="legend-item"
data-status="cancelled"
style={{ padding: '0px 5px' }}
>
Cancelado Cancelado
</div> </div>
</div> </div>
<h4>Consultas para {selectedDay.format('DD/MM')}</h4> <h4>Consultas para {selectedDay.format('DD/MM')}</h4>
{(DictAgendamentosOrganizados[selectedDay.format('YYYY-MM-DD')]?.length > 0) ? ( {DictAgendamentosOrganizados[
DictAgendamentosOrganizados[selectedDay.format('YYYY-MM-DD')].map(app => ( selectedDay.format('YYYY-MM-DD')
<div key={app.id} className="appointment-item" data-status={app.status}> ]?.length > 0 ? (
DictAgendamentosOrganizados[
selectedDay.format('YYYY-MM-DD')
].map((app) => (
<div
key={app.id}
className="appointment-item"
data-status={app.status}
>
<div className="item-time"> <div className="item-time">
{dayjs(app.scheduled_at).format('HH:mm')} {dayjs(app.scheduled_at).add(3, 'hour').format('HH:mm')}
</div> </div>
<div className="item-details"> <div className="item-details">
<span>Consulta com Dr(a). {app.medico_nome}</span> <span>Consulta com Dr(a). {app.medico_nome}</span>
</div> </div>
<div className='item-actions'> <div className="item-actions">
{app.status !== 'cancelled' && dayjs(app.scheduled_at).isAfter(dayjs()) && ( {app.status !== 'cancelled' &&
<button dayjs(app.scheduled_at).isAfter(dayjs()) && (
className="btn btn-sm btn-outline-danger" <button
onClick={() => handleCancelClick(app.id)} className="btn btn-sm btn-outline-danger"
title="Cancelar Consulta" onClick={() => handleCancelClick(app.id)}
> title="Cancelar Consulta"
<Trash2 size={16} /> >
</button> <Trash2 size={16} />
)} </button>
)}
</div> </div>
</div> </div>
)) ))
@ -288,12 +368,19 @@ const Agendamento = ({ setDictInfo }) => {
<div className="calendar-controls"> <div className="calendar-controls">
<div className="date-indicator"> <div className="date-indicator">
<h2>{currentDate.format('MMMM [de] YYYY')}</h2> <h2>{currentDate.format('MMMM [de] YYYY')}</h2>
<div className="quick-jump-controls" <div
style={{ display: 'flex', gap: '5px', marginTop: '10px' }} className="quick-jump-controls"
style={{
display: 'flex',
gap: '5px',
marginTop: '10px',
}}
> >
<select <select
value={quickJump.month} value={quickJump.month}
onChange={(e) => handleQuickJumpChange('month', e.target.value)} onChange={(e) =>
handleQuickJumpChange('month', e.target.value)
}
className="form-select form-select-sm w-auto" className="form-select form-select-sm w-auto"
> >
{dayjs.months().map((month, index) => ( {dayjs.months().map((month, index) => (
@ -304,11 +391,17 @@ const Agendamento = ({ setDictInfo }) => {
</select> </select>
<select <select
value={quickJump.year} value={quickJump.year}
onChange={(e) => handleQuickJumpChange('year', e.target.value)} onChange={(e) =>
handleQuickJumpChange('year', e.target.value)
}
className="form-select form-select-sm w-auto" className="form-select form-select-sm w-auto"
> >
{Array.from({ length: 11 }, (_, i) => dayjs().year() - 5 + i).map(year => ( {Array.from({ length: 11 }, (_, i) =>
<option key={year} value={year}>{year}</option> dayjs().year() - 5 + i
).map((year) => (
<option key={year} value={year}>
{year}
</option>
))} ))}
</select> </select>
<button <button
@ -324,24 +417,36 @@ const Agendamento = ({ setDictInfo }) => {
</div> </div>
</div> </div>
<div className="nav-buttons"> <div className="nav-buttons">
<button onClick={() => setCurrentDate(c => c.subtract(1, 'month'))}> <button
onClick={() => setCurrentDate((c) => c.subtract(1, 'month'))}
>
<ChevronLeft size={20} /> <ChevronLeft size={20} />
</button> </button>
<button onClick={() => setCurrentDate(dayjs())}> <button onClick={() => setCurrentDate(dayjs())}>
Hoje Hoje
</button> </button>
<button onClick={() => setCurrentDate(c => c.add(1, 'month'))}> <button
onClick={() => setCurrentDate((c) => c.add(1, 'month'))}
>
<ChevronRight size={20} /> <ChevronRight size={20} />
</button> </button>
</div> </div>
</div> </div>
<div className="calendar-grid"> <div className="calendar-grid">
{weekDays.map(day => <div key={day} className="day-header">{day}</div>)} {weekDays.map((day) => (
<div key={day} className="day-header">
{day}
</div>
))}
{dateGrid.map((day, index) => { {dateGrid.map((day, index) => {
const appointmentsOnDay = const appointmentsOnDay =
DictAgendamentosOrganizados[day.format('YYYY-MM-DD')] || []; DictAgendamentosOrganizados[
day.format('YYYY-MM-DD')
] || [];
const cellClasses = `day-cell ${ 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(dayjs(), 'day') ? 'today' : ''} ${
day.isSame(selectedDay, 'day') ? 'selected' : '' day.isSame(selectedDay, 'day') ? 'selected' : ''
}`; }`;
@ -369,7 +474,9 @@ const Agendamento = ({ setDictInfo }) => {
<div className="col-12"> <div className="col-12">
<div className="card table-paciente-card"> <div className="card table-paciente-card">
<div className="card-header"> <div className="card-header">
<h4 className="card-title mb-0">Minhas Solicitações em Fila de Espera</h4> <h4 className="card-title mb-0">
Minhas Solicitações em Fila de Espera
</h4>
</div> </div>
<div className="card-body"> <div className="card-body">
<div className="table-responsive"> <div className="table-responsive">
@ -387,21 +494,29 @@ const Agendamento = ({ setDictInfo }) => {
<tr key={item.agendamento.id}> <tr key={item.agendamento.id}>
<td>Dr(a). {item.Infos?.medico_nome}</td> <td>Dr(a). {item.Infos?.medico_nome}</td>
<td> <td>
{dayjs(item.agendamento.created_at).format('DD/MM/YYYY HH:mm')} {dayjs(
item.agendamento.created_at
).format('DD/MM/YYYY HH:mm')}
</td> </td>
<td> <td>
<button <button
className="btn btn-sm btn-danger" className="btn btn-sm btn-danger"
onClick={() => handleCancelClick(item.agendamento.id)} onClick={() =>
handleCancelClick(item.agendamento.id)
}
> >
<i className="bi bi-trash me-1"></i> Cancelar <i className="bi bi-trash me-1"></i>{' '}
Cancelar
</button> </button>
</td> </td>
</tr> </tr>
)) ))
) : ( ) : (
<tr> <tr>
<td colSpan="3" className="text-center py-4"> <td
colSpan="3"
className="text-center py-4"
>
<div className="text-muted"> <div className="text-muted">
Nenhuma solicitação na fila de espera. Nenhuma solicitação na fila de espera.
</div> </div>
@ -423,7 +538,7 @@ const Agendamento = ({ setDictInfo }) => {
<AgendamentoCadastroManager <AgendamentoCadastroManager
setPageConsulta={setPageConsulta} setPageConsulta={setPageConsulta}
onSaved={() => { onSaved={() => {
carregarDados(); // recarrega consultas do paciente carregarDados(); // recarrega consultas do paciente
setPageConsulta(false); setPageConsulta(false);
}} }}
/> />
@ -438,7 +553,7 @@ const Agendamento = ({ setDictInfo }) => {
backgroundColor: '#fee2e2', backgroundColor: '#fee2e2',
borderBottom: '1px solid #fca5a5', borderBottom: '1px solid #fca5a5',
padding: '15px', padding: '15px',
borderRadius: '8px 8px 0 0' borderRadius: '8px 8px 0 0',
}} }}
> >
<h4 style={{ margin: 0, color: '#dc2626' }}> <h4 style={{ margin: 0, color: '#dc2626' }}>
@ -451,7 +566,7 @@ const Agendamento = ({ setDictInfo }) => {
background: 'none', background: 'none',
border: 'none', border: 'none',
fontSize: '1.5rem', fontSize: '1.5rem',
cursor: 'pointer' cursor: 'pointer',
}} }}
> >
&times; &times;
@ -469,7 +584,7 @@ const Agendamento = ({ setDictInfo }) => {
padding: '10px', padding: '10px',
resize: 'none', resize: 'none',
border: '1px solid #ccc', border: '1px solid #ccc',
borderRadius: '4px' borderRadius: '4px',
}} }}
></textarea> ></textarea>
</div> </div>
@ -480,7 +595,7 @@ const Agendamento = ({ setDictInfo }) => {
justifyContent: 'flex-end', justifyContent: 'flex-end',
gap: '10px', gap: '10px',
padding: '15px', padding: '15px',
borderTop: '1px solid #eee' borderTop: '1px solid #eee',
}} }}
> >
<button <button
@ -491,7 +606,7 @@ const Agendamento = ({ setDictInfo }) => {
color: 'white', color: 'white',
border: 'none', border: 'none',
padding: '8px 15px', padding: '8px 15px',
borderRadius: '4px' borderRadius: '4px',
}} }}
> >
Cancelar Cancelar
@ -504,7 +619,7 @@ const Agendamento = ({ setDictInfo }) => {
color: 'white', color: 'white',
border: 'none', border: 'none',
padding: '8px 15px', padding: '8px 15px',
borderRadius: '4px' borderRadius: '4px',
}} }}
> >
<Trash2 size={16} style={{ marginRight: '5px' }} /> Excluir <Trash2 size={16} style={{ marginRight: '5px' }} /> Excluir
@ -514,7 +629,7 @@ const Agendamento = ({ setDictInfo }) => {
</div> </div>
)} )}
</div> </div>
) );
} };
export default Agendamento; export default Agendamento;

View File

@ -442,7 +442,7 @@ const filtered = allApps.filter(app =>
filtered.map(app => ( filtered.map(app => (
<div key={app.id} className="appointment-item" data-status={app.status}> <div key={app.id} className="appointment-item" data-status={app.status}>
<div className="item-time"> <div className="item-time">
{dayjs(app.scheduled_at).format('HH:mm')} {dayjs(app.scheduled_at).add(3, 'hour').format('HH:mm')}
</div> </div>
<div className="item-details"> <div className="item-details">
<span>{app.paciente_nome}</span> <span>{app.paciente_nome}</span>

View File

@ -6,11 +6,15 @@ import dayjs from 'dayjs';
import { UserInfos } from '../components/utils/Functions-Endpoints/General'; import { UserInfos } from '../components/utils/Functions-Endpoints/General';
const AgendamentoCadastroManager = ({ setPageConsulta, Dict, onSaved }) => { const AgendamentoCadastroManager = ({ setPageConsulta, Dict, onSaved }) => {
const { getAuthorizationHeader } = useAuth(); const { getAuthorizationHeader, user } = useAuth();
const [agendamento, setAgendamento] = useState({ status: 'confirmed' }); const [agendamento, setAgendamento] = useState({ status: 'confirmed' });
const [idUsuario, setIDusuario] = useState('0'); 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(() => { useEffect(() => {
if (!Dict) { if (!Dict) {
@ -20,27 +24,39 @@ const AgendamentoCadastroManager = ({ setPageConsulta, Dict, onSaved }) => {
} }
const ColherInfoUsuario = async () => { const ColherInfoUsuario = async () => {
const result = await UserInfos(authHeader); try {
setIDusuario(result?.profile?.id); 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]); }, [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(); const myHeaders = new Headers();
myHeaders.append('apikey', API_KEY); myHeaders.append('apikey', API_KEY);
myHeaders.append('Authorization', authHeader); myHeaders.append('Authorization', authHeader);
myHeaders.append('Content-Type', 'application/json'); myHeaders.append('Content-Type', 'application/json');
const raw = JSON.stringify({ const raw = JSON.stringify({
patient_id: Dict.patient_id, patient_id: patientId, // paciente logado
doctor_id: Dict.doctor_id, doctor_id: DictForm.doctor_id,
scheduled_at: `${Dict.dataAtendimento}T${Dict.horarioInicio}:00.000Z`, scheduled_at: `${DictForm.dataAtendimento}T${DictForm.horarioInicio}:00`,
duration_minutes: 30, duration_minutes: 30,
appointment_type: Dict.tipo_consulta, appointment_type: DictForm.tipo_consulta,
patient_notes: '', patient_notes: '',
insurance_provider: Dict.convenio, insurance_provider: DictForm.convenio,
status: Dict.status || 'confirmed', status: 'confirmed', // ou 'confirmed'
created_by: idUsuario, created_by: idUsuario,
created_at: dayjs().toISOString(), created_at: dayjs().toISOString(),
}); });
@ -58,7 +74,7 @@ const AgendamentoCadastroManager = ({ setPageConsulta, Dict, onSaved }) => {
requestOptions requestOptions
); );
if (response.ok) { if (response.ok) {
if (onSaved) onSaved(); // avisa o pai para recarregar e fechar if (onSaved) onSaved(); // pai recarrega e fecha
else setPageConsulta(false); else setPageConsulta(false);
} else { } else {
console.error('Erro ao criar agendamento:', await response.text()); console.error('Erro ao criar agendamento:', await response.text());