From 29be7aec71d51b28a52ad8a6cc828299c27929e4 Mon Sep 17 00:00:00 2001 From: Pedro Araujo da Silveira Date: Wed, 29 Oct 2025 18:10:33 -0300 Subject: [PATCH] fix: status de consultas --- .../components/consultas/ConsultaModal.tsx | 28 +++++++--- MEDICONNECT 2/src/pages/PainelMedico.tsx | 56 +++++++++++++++---- MEDICONNECT 2/src/services/api/client.ts | 9 ++- .../appointments/appointmentService.ts | 30 ++++++++-- 4 files changed, 98 insertions(+), 25 deletions(-) diff --git a/MEDICONNECT 2/src/components/consultas/ConsultaModal.tsx b/MEDICONNECT 2/src/components/consultas/ConsultaModal.tsx index b9e3aeae3..572127ce8 100644 --- a/MEDICONNECT 2/src/components/consultas/ConsultaModal.tsx +++ b/MEDICONNECT 2/src/components/consultas/ConsultaModal.tsx @@ -63,7 +63,7 @@ const ConsultaModal: React.FC = ({ const [tipo, setTipo] = useState(""); const [motivo, setMotivo] = useState(""); const [observacoes, setObservacoes] = useState(""); - const [status, setStatus] = useState("agendada"); + const [status, setStatus] = useState("requested"); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); @@ -118,7 +118,7 @@ const ConsultaModal: React.FC = ({ setTipo(""); setMotivo(""); setObservacoes(""); - setStatus("agendada"); + setStatus("requested"); } setError(null); setSaving(false); @@ -166,13 +166,23 @@ const ConsultaModal: React.FC = ({ if (editing) { // Atualizar consulta existente + // Validar se o status é válido + const validStatuses: AppointmentStatus[] = [ + 'requested', 'confirmed', 'checked_in', 'in_progress', 'completed', 'cancelled', 'no_show' + ]; + const finalStatus = validStatuses.includes(status as AppointmentStatus) + ? (status as AppointmentStatus) + : 'confirmed'; + const payload = { scheduled_at: iso, chief_complaint: motivo || undefined, notes: observacoes || undefined, - status: status as AppointmentStatus, + status: finalStatus, }; + console.log('[ConsultaModal] Enviando atualização:', payload); + const updated = await appointmentService.update(editing.id, payload); // Converter para formato esperado @@ -342,11 +352,13 @@ const ConsultaModal: React.FC = ({ value={status} onChange={(e) => setStatus(e.target.value)} > - - - - - + + + + + + + )} diff --git a/MEDICONNECT 2/src/pages/PainelMedico.tsx b/MEDICONNECT 2/src/pages/PainelMedico.tsx index 9b173156f..535e4869f 100644 --- a/MEDICONNECT 2/src/pages/PainelMedico.tsx +++ b/MEDICONNECT 2/src/pages/PainelMedico.tsx @@ -74,7 +74,7 @@ const PainelMedico: React.FC = () => { const [filtroData, setFiltroData] = useState("hoje"); const [loading, setLoading] = useState(true); const [modalOpen, setModalOpen] = useState(false); - const [editing, setEditing] = useState(null); + const [editing, setEditing] = useState(null); const [relatorioModalOpen, setRelatorioModalOpen] = useState(false); const [loadingRelatorio, setLoadingRelatorio] = useState(false); const [laudos, setLaudos] = useState([]); @@ -291,27 +291,63 @@ const PainelMedico: React.FC = () => { }; const handleEditConsulta = (consulta: ConsultaUI) => { - setEditing(consulta); + // Converter ConsultaUI para Appointment compatível com o modal + const appointmentData: any = { + id: consulta.id, + patient_id: consulta.pacienteId, + doctor_id: consulta.medicoId, + scheduled_at: consulta.dataHora, + status: consulta.status, + appointment_type: consulta.tipo, + notes: consulta.observacoes, + pacienteId: consulta.pacienteId, + medicoId: consulta.medicoId, + dataHora: consulta.dataHora, + }; + setEditing(appointmentData); setModalOpen(true); }; const handleDeleteConsulta = async (id: string) => { if (!window.confirm("Deseja realmente excluir esta consulta?")) return; try { - const raw = localStorage.getItem("consultas_local"); - if (raw) { - const lista: ServiceConsulta[] = JSON.parse(raw); - const nova = lista.filter((c) => c.id !== id); - localStorage.setItem("consultas_local", JSON.stringify(nova)); - toast.success("Consulta excluída"); - fetchConsultas(); - } + await appointmentService.delete(id); + toast.success("Consulta excluída"); + fetchConsultas(); } catch (error) { console.error("Erro ao excluir consulta:", error); toast.error("Erro ao excluir consulta"); } }; + const handleUpdateStatus = async (id: string, newStatus: string) => { + try { + console.log(`[PainelMedico] Atualizando status da consulta ${id} para ${newStatus}`); + + // Mapear status em português para inglês + const statusMap: Record = { + 'agendada': 'requested', + 'confirmada': 'confirmed', + 'em_andamento': 'in_progress', + 'concluida': 'completed', + 'cancelada': 'cancelled', + 'falta': 'no_show', + }; + + const mappedStatus = statusMap[newStatus.toLowerCase()] || newStatus; + + await appointmentService.update(id, { + status: mappedStatus as any + }); + + toast.success("Status atualizado com sucesso!"); + fetchConsultas(); + } catch (error) { + console.error("Erro ao atualizar status:", error); + toast.error("Erro ao atualizar status da consulta"); + } + }; + const handleSaveConsulta = () => { setModalOpen(false); setEditing(null); diff --git a/MEDICONNECT 2/src/services/api/client.ts b/MEDICONNECT 2/src/services/api/client.ts index 550033bf6..451a330d2 100644 --- a/MEDICONNECT 2/src/services/api/client.ts +++ b/MEDICONNECT 2/src/services/api/client.ts @@ -38,8 +38,15 @@ class ApiClient { if (token && config.headers) { config.headers.Authorization = `Bearer ${token}`; + + // Adicionar Prefer header para operações de escrita retornarem dados + const method = config.method?.toUpperCase(); + if (method === 'POST' || method === 'PATCH' || method === 'PUT') { + config.headers['Prefer'] = 'return=representation'; + } + console.log( - `[ApiClient] Request: ${config.method?.toUpperCase()} ${ + `[ApiClient] Request: ${method} ${ config.url } - Token presente: ${token.substring(0, 20)}...` ); diff --git a/MEDICONNECT 2/src/services/appointments/appointmentService.ts b/MEDICONNECT 2/src/services/appointments/appointmentService.ts index 486611e65..6120287bc 100644 --- a/MEDICONNECT 2/src/services/appointments/appointmentService.ts +++ b/MEDICONNECT 2/src/services/appointments/appointmentService.ts @@ -94,14 +94,32 @@ class AppointmentService { * Atualiza agendamento existente */ async update(id: string, data: UpdateAppointmentInput): Promise { - const response = await apiClient.patch( - `${this.basePath}?id=eq.${id}`, - data - ); - if (response.data && response.data.length > 0) { + console.log('[appointmentService] Atualizando consulta:', id, data); + + try { + const response = await apiClient.patch( + `${this.basePath}?id=eq.${id}`, + data + ); + + console.log('[appointmentService] Resposta da atualização:', response.status, response.data); + + // Se retornou 204 (No Content), buscar o registro atualizado + if (response.status === 204 || !response.data || response.data.length === 0) { + console.log('[appointmentService] Buscando registro atualizado...'); + const getResponse = await apiClient.get(`${this.basePath}?id=eq.${id}`); + if (getResponse.data && getResponse.data.length > 0) { + return getResponse.data[0]; + } + throw new Error("Agendamento não encontrado após atualização"); + } + return response.data[0]; + } catch (error: any) { + console.error('[appointmentService] Erro ao atualizar:', error); + console.error('[appointmentService] Error response:', error?.response?.data); + throw error; } - throw new Error("Agendamento não encontrado"); } /**