diff --git a/susconecta/app/(main-routes)/pacientes/page.tsx b/susconecta/app/(main-routes)/pacientes/page.tsx index 76b8682..c331bf9 100644 --- a/susconecta/app/(main-routes)/pacientes/page.tsx +++ b/susconecta/app/(main-routes)/pacientes/page.tsx @@ -317,6 +317,16 @@ export default function PacientesPage() { )} + {/* Assignment dialog */} + {assignDialogOpen && assignPatientId && ( + { setAssignDialogOpen(false); setAssignPatientId(null); }} + onSaved={() => { setAssignDialogOpen(false); setAssignPatientId(null); loadAll(); }} + /> + )} +
Mostrando {filtered.length} de {patients.length}
); diff --git a/susconecta/app/profissional/page.tsx b/susconecta/app/profissional/page.tsx index a1fc978..25ec79d 100644 --- a/susconecta/app/profissional/page.tsx +++ b/susconecta/app/profissional/page.tsx @@ -737,23 +737,45 @@ const ProfissionalPage = () => { ); } - // carregar laudos ao montar + // carregar laudos ao montar - somente dos pacientes atribuídos ao médico logado useEffect(() => { let mounted = true; (async () => { try { - await loadReports(); + // obter assignments para o usuário logado + const assignments = await import('@/lib/assignment').then(m => m.listAssignmentsForUser(user?.id || '')); + const patientIds = Array.isArray(assignments) ? assignments.map(a => String(a.patient_id)).filter(Boolean) : []; + + if (patientIds.length === 0) { + if (mounted) setLaudos([]); + return; + } + + // carregar relatórios para cada paciente encontrado (useReports não tem batch by multiple ids, então carregamos por paciente) + const allReports: any[] = []; + for (const pid of patientIds) { + try { + const rels = await import('@/lib/reports').then(m => m.listarRelatoriosPorPaciente(pid)); + if (Array.isArray(rels)) allReports.push(...rels); + } catch (err) { + console.warn('[LaudoManager] falha ao carregar relatórios para paciente', pid, err); + } + } + + if (mounted) { + setLaudos(allReports); + } } catch (e) { - // erro tratado no hook + console.warn('[LaudoManager] erro ao carregar laudos para pacientes atribuídos:', e); + if (mounted) setLaudos(reports || []); } - if (mounted) setLaudos(reports || []); })(); return () => { mounted = false; }; - }, [loadReports]); + }, [user?.id]); - // sincroniza quando reports mudarem no hook + // sincroniza quando reports mudarem no hook (fallback) useEffect(() => { - setLaudos(reports || []); + if (!laudos || laudos.length === 0) setLaudos(reports || []); }, [reports]); const [activeTab, setActiveTab] = useState("descobrir"); diff --git a/susconecta/components/admin/AssignmentForm.tsx b/susconecta/components/admin/AssignmentForm.tsx index 66e0d2c..4045c92 100644 --- a/susconecta/components/admin/AssignmentForm.tsx +++ b/susconecta/components/admin/AssignmentForm.tsx @@ -8,7 +8,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@ import { Input } from "@/components/ui/input"; import { useToast } from "@/hooks/use-toast"; -import { assignRoleToUser, listAssignmentsForPatient } from "@/lib/assignment"; +import { assignRoleToUser, listAssignmentsForPatient, PatientAssignmentRole } from "@/lib/assignment"; import { listarProfissionais } from "@/lib/api"; type Props = { @@ -22,7 +22,8 @@ export default function AssignmentForm({ patientId, open, onClose, onSaved }: Pr const { toast } = useToast(); const [professionals, setProfessionals] = useState([]); const [selectedProfessional, setSelectedProfessional] = useState(null); - const [role, setRole] = useState("doctor"); + // default to Portuguese role values expected by the backend + const [role, setRole] = useState("medico"); const [loading, setLoading] = useState(false); const [existing, setExisting] = useState([]); @@ -48,11 +49,11 @@ export default function AssignmentForm({ patientId, open, onClose, onSaved }: Pr }, [open, patientId]); async function handleSave() { - if (!selectedProfessional) return toast({ title: 'Selecione um profissional', variant: 'warning' }); + if (!selectedProfessional) return toast({ title: 'Selecione um profissional', variant: 'default' }); setLoading(true); try { await assignRoleToUser({ patient_id: patientId, user_id: selectedProfessional, role }); - toast({ title: 'Atribuição criada', variant: 'success' }); + toast({ title: 'Atribuição criada', variant: 'default' }); onSaved && onSaved(); onClose(); } catch (err: any) { @@ -87,8 +88,19 @@ export default function AssignmentForm({ patientId, open, onClose, onSaved }: Pr
- setRole(e.target.value)} /> -
Ex: doctor, nurse
+ { + const v = String(e.target.value || '').toLowerCase().trim(); + // Map common english values to portuguese expected by backend + if (v === 'doctor') return setRole('medico'); + if (v === 'nurse') return setRole('enfermeiro'); + if (v === 'medico' || v === 'enfermeiro') return setRole(v as PatientAssignmentRole); + // fallback: keep current role (ignore unknown input) + return setRole(role); + }} + /> +
Ex: medico, enfermeiro (inglês: doctor → medico)
{existing && existing.length > 0 && ( diff --git a/susconecta/lib/api.ts b/susconecta/lib/api.ts index 2554f2f..ed8c5c5 100644 --- a/susconecta/lib/api.ts +++ b/susconecta/lib/api.ts @@ -838,6 +838,12 @@ export async function buscarMedicosPorIds(ids: Array): Promise< return unique; } +// Alias/backwards-compat: listarProfissionais usado por components +export async function listarProfissionais(params?: { page?: number; limit?: number; q?: string; }): Promise { + // Reuse listarMedicos implementation to avoid duplication + return await listarMedicos(params); +} + // Dentro de lib/api.ts export async function criarMedico(input: MedicoInput): Promise { console.log("Enviando os dados para a API:", input); // Log para depuração diff --git a/susconecta/lib/assignment.ts b/susconecta/lib/assignment.ts index ddd5cd2..6a11d44 100644 --- a/susconecta/lib/assignment.ts +++ b/susconecta/lib/assignment.ts @@ -78,7 +78,9 @@ export async function assignRoleToUser(input: CreateAssignmentInput): Promise { + console.log(`🔍 [ASSIGNMENT] Listando atribuições para o usuário: ${userId}`); + const url = `${ASSIGNMENTS_URL}?user_id=eq.${userId}`; + + try { + const headers = getHeaders(); + console.debug('[ASSIGNMENT] GET', url, 'headers(masked)=', { + ...headers, + Authorization: headers.Authorization ? '<>' : undefined, + }); + const response = await fetch(url, { + method: 'GET', + headers, + }); + + // dump raw text for debugging when content-type isn't JSON or when empty + const contentType = response.headers.get('content-type') || ''; + const txt = await response.clone().text().catch(() => ''); + console.debug('[ASSIGNMENT] response status=', response.status, response.statusText, 'content-type=', contentType, 'bodyPreview=', txt ? (txt.length > 1000 ? txt.slice(0,1000) + '...[truncated]' : txt) : ''); + + if (!response.ok) { + const errorBody = txt || ''; + console.error("❌ [ASSIGNMENT] Erro ao listar atribuições por usuário:", { + status: response.status, + statusText: response.statusText, + body: errorBody, + }); + throw new Error(`Erro ao listar atribuições por usuário: ${response.status} ${response.statusText} - body: ${errorBody}`); + } + + let assignments: any = []; + try { + assignments = await response.json(); + } catch (e) { + console.warn('[ASSIGNMENT] não foi possível parsear JSON, usando texto cru como fallback'); + assignments = txt ? JSON.parse(txt) : []; + } + console.log(`✅ [ASSIGNMENT] ${Array.isArray(assignments) ? assignments.length : 0} atribuições encontradas para o usuário.`); + return Array.isArray(assignments) ? assignments : []; + } catch (error) { + console.error("❌ [ASSIGNMENT] Erro inesperado ao listar atribuições por usuário:", error); + throw error; + } +}