diff --git a/susconecta/app/(main-routes)/dashboard/relatorios/page.tsx b/susconecta/app/(main-routes)/dashboard/relatorios/page.tsx index c70081a..a15da37 100644 --- a/susconecta/app/(main-routes)/dashboard/relatorios/page.tsx +++ b/susconecta/app/(main-routes)/dashboard/relatorios/page.tsx @@ -520,28 +520,30 @@ export default function RelatoriosPage() { {/* Performance por médico */}
-
+

Performance por Médico

- +
- - - - - - - - - - {(loading ? performancePorMedico : medicosPerformance).map((m) => ( - - - - +
+
MédicoConsultasAbsenteísmo (%)
{m.nome}{m.consultas}{m.absenteismo}
+ + + + + - ))} - -
MédicoConsultasAbsenteísmo (%)
+ + + {(loading ? performancePorMedico : medicosPerformance).map((m) => ( + + {m.nome} + {m.consultas} + {m.absenteismo} + + ))} + + +
diff --git a/susconecta/app/profissional/page.tsx b/susconecta/app/profissional/page.tsx index adb9607..e96065b 100644 --- a/susconecta/app/profissional/page.tsx +++ b/susconecta/app/profissional/page.tsx @@ -7,6 +7,7 @@ import ProtectedRoute from "@/components/shared/ProtectedRoute"; import { useAuth } from "@/hooks/useAuth"; import { useToast } from "@/hooks/use-toast"; import { buscarPacientes, listarPacientes, buscarPacientePorId, buscarPacientesPorIds, buscarMedicoPorId, buscarMedicosPorIds, buscarMedicos, listarAgendamentos, type Paciente, buscarRelatorioPorId, atualizarMedico } from "@/lib/api"; +import { ENV_CONFIG } from '@/lib/env-config'; import { useReports } from "@/hooks/useReports"; import { CreateReportData } from "@/types/report-types"; import { Button } from "@/components/ui/button"; @@ -36,7 +37,6 @@ import { import dynamic from "next/dynamic"; -import { ENV_CONFIG } from '@/lib/env-config'; import dayGridPlugin from "@fullcalendar/daygrid"; import timeGridPlugin from "@fullcalendar/timegrid"; import interactionPlugin from "@fullcalendar/interaction"; @@ -182,7 +182,7 @@ const ProfissionalPage = () => { const q = `doctor_id=eq.${encodeURIComponent(String(resolvedDoctorId))}&select=patient_id&limit=200`; const appts = await listarAgendamentos(q).catch(() => []); for (const a of (appts || [])) { - const pid = a.patient_id ?? a.patient ?? a.patient_id_raw ?? null; + const pid = (a as any).patient_id ?? null; if (pid) patientIdSet.add(String(pid)); } } catch (e) { @@ -211,6 +211,7 @@ const ProfissionalPage = () => { })(); return () => { mounted = false; }; // Re-run when user id becomes available so patients assigned to the logged-in doctor are loaded + // eslint-disable-next-line react-hooks/exhaustive-deps }, [user?.id]); // Carregar perfil do médico correspondente ao usuário logado @@ -429,6 +430,9 @@ const ProfissionalPage = () => { const [commPhoneNumber, setCommPhoneNumber] = useState(''); const [commMessage, setCommMessage] = useState(''); const [commPatientId, setCommPatientId] = useState(null); + const [commResponses, setCommResponses] = useState([]); + const [commResponsesLoading, setCommResponsesLoading] = useState(false); + const [commResponsesError, setCommResponsesError] = useState(null); const [smsSending, setSmsSending] = useState(false); const handleSave = async (event: React.MouseEvent) => { @@ -520,6 +524,68 @@ const ProfissionalPage = () => { } }; + const loadCommResponses = async (patientId?: string) => { + const pid = patientId ?? commPatientId; + if (!pid) { + setCommResponses([]); + setCommResponsesError('Selecione um paciente para ver respostas'); + return; + } + setCommResponsesLoading(true); + setCommResponsesError(null); + try { + // 1) tentar buscar por patient_id (o comportamento ideal) + const qs = new URLSearchParams(); + qs.set('patient_id', `eq.${String(pid)}`); + qs.set('order', 'created_at.desc'); + const url = `${(ENV_CONFIG as any).REST}/messages?${qs.toString()}`; + const headers: Record = { 'Accept': 'application/json' }; + if (token) headers['Authorization'] = `Bearer ${token}`; + if ((ENV_CONFIG as any)?.SUPABASE_ANON_KEY) headers['apikey'] = (ENV_CONFIG as any).SUPABASE_ANON_KEY; + const r = await fetch(url, { method: 'GET', headers }); + let data = await r.json().catch(() => []); + data = Array.isArray(data) ? data : []; + + // 2) Se não houver mensagens por patient_id, tentar buscar por número (from/to) + if ((!data || data.length === 0) && commPhoneNumber) { + try { + const norm = normalizePhoneNumber(commPhoneNumber); + if (norm) { + // Primeiro tenta buscar mensagens onde `from` é o número + const qsFrom = new URLSearchParams(); + qsFrom.set('from', `eq.${String(norm)}`); + qsFrom.set('order', 'created_at.desc'); + const urlFrom = `${(ENV_CONFIG as any).REST}/messages?${qsFrom.toString()}`; + const rf = await fetch(urlFrom, { method: 'GET', headers }); + const dataFrom = await rf.json().catch(() => []); + if (Array.isArray(dataFrom) && dataFrom.length) { + data = dataFrom; + } else { + // se nada, tenta `to` (caso o provedor grave a direção inversa) + const qsTo = new URLSearchParams(); + qsTo.set('to', `eq.${String(norm)}`); + qsTo.set('order', 'created_at.desc'); + const urlTo = `${(ENV_CONFIG as any).REST}/messages?${qsTo.toString()}`; + const rt = await fetch(urlTo, { method: 'GET', headers }); + const dataTo = await rt.json().catch(() => []); + if (Array.isArray(dataTo) && dataTo.length) data = dataTo; + } + } + } catch (phoneErr) { + // não bloqueara o fluxo principal; apenas log + console.warn('[ProfissionalPage] fallback por telefone falhou', phoneErr); + } + } + + setCommResponses(Array.isArray(data) ? data : []); + } catch (e: any) { + setCommResponsesError(String(e?.message || e || 'Falha ao buscar respostas')); + setCommResponses([]); + } finally { + setCommResponsesLoading(false); + } + }; + const handleEditarLaudo = (paciente: any) => { @@ -2638,6 +2704,9 @@ const ProfissionalPage = () => { // Use a sentinel value "__none" for the "-- nenhum --" choice and map it to null here. const v = val === "__none" ? null : (val || null); setCommPatientId(v); + // clear previous responses when changing selection + setCommResponses([]); + setCommResponsesError(null); if (!v) { setCommPhoneNumber(''); return; @@ -2655,6 +2724,8 @@ const ProfissionalPage = () => { console.warn('[ProfissionalPage] erro ao preencher telefone do paciente selecionado', e); setCommPhoneNumber(''); } + // carregar respostas do paciente selecionado + void loadCommResponses(String(v)); }} > @@ -2686,6 +2757,35 @@ const ProfissionalPage = () => { {smsSending ? 'Enviando...' : 'Enviar SMS'} + + {/* Respostas do paciente */} +
+
+

Últimas respostas do paciente

+
+ +
+
+ + {commResponsesLoading ? ( +
Carregando respostas...
+ ) : commResponsesError ? ( +
{commResponsesError}
+ ) : (commResponses && commResponses.length) ? ( +
+ {commResponses.map((m:any) => ( +
+
{m.created_at ? new Date(m.created_at).toLocaleString() : ''}
+
{m.body ?? m.content ?? m.message ?? '-'}
+
+ ))} +
+ ) : ( +
Nenhuma resposta encontrada para o paciente selecionado.
+ )} +