From 7010e8e7d9bbf65372475e72fbce50e73effd64d Mon Sep 17 00:00:00 2001 From: NANDO9322 Date: Mon, 12 Jan 2026 12:20:08 -0300 Subject: [PATCH] =?UTF-8?q?fix:=20corre=C3=A7=C3=B5es=20de=20email,=20avat?= =?UTF-8?q?ar=20e=20filtro=20de=20equipe=20no=20agendador?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend: - Corrigido mapeamento de email na listagem e busca por ID de profissionais. Agora o sistema utiliza o email do usuário vinculado (`usuario_email`) como fallback caso o email do perfil profissional esteja vazio. Frontend: - EventScheduler: Implementado filtro estrito para exibir apenas profissionais que foram explicitamente adicionados à equipe do evento ("Gerenciar Equipe"), prevenindo escalações indevidas. - EventScheduler: Adicionada validação para ocultar cargos administrativos sem função operacional definida. - ProfessionalDetailsModal: Corrigida a lógica de exibição do avatar para suportar a propriedade `avatar_url` (padrão atual do backend), resolvendo o problema de imagens quebradas ou ícones genéricos. --- backend/internal/profissionais/handler.go | 7 ++++++- frontend/components/EventScheduler.tsx | 11 ++++++++--- frontend/components/ProfessionalDetailsModal.tsx | 2 +- frontend/components/ProfessionalForm.tsx | 2 +- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/backend/internal/profissionais/handler.go b/backend/internal/profissionais/handler.go index fd169e8..dc07122 100644 --- a/backend/internal/profissionais/handler.go +++ b/backend/internal/profissionais/handler.go @@ -89,6 +89,10 @@ func toResponse(p interface{}) ProfissionalResponse { AvatarURL: fromPgText(v.AvatarUrl), } case generated.ListProfissionaisRow: + email := fromPgText(v.Email) + if email == nil { + email = fromPgText(v.UsuarioEmail) + } return ProfissionalResponse{ ID: uuid.UUID(v.ID.Bytes).String(), UsuarioID: uuid.UUID(v.UsuarioID.Bytes).String(), @@ -116,7 +120,7 @@ func toResponse(p interface{}) ProfissionalResponse { TabelaFree: fromPgText(v.TabelaFree), ExtraPorEquipamento: fromPgBool(v.ExtraPorEquipamento), Equipamentos: fromPgText(v.Equipamentos), - Email: fromPgText(v.Email), + Email: email, AvatarURL: fromPgText(v.AvatarUrl), } case generated.GetProfissionalByIDRow: @@ -147,6 +151,7 @@ func toResponse(p interface{}) ProfissionalResponse { TabelaFree: fromPgText(v.TabelaFree), ExtraPorEquipamento: fromPgBool(v.ExtraPorEquipamento), Equipamentos: fromPgText(v.Equipamentos), + Email: fromPgText(v.Email), AvatarURL: fromPgText(v.AvatarUrl), } default: diff --git a/frontend/components/EventScheduler.tsx b/frontend/components/EventScheduler.tsx index 92c1fd6..cc1ff54 100644 --- a/frontend/components/EventScheduler.tsx +++ b/frontend/components/EventScheduler.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; import { Plus, Trash, User, Truck, MapPin } from "lucide-react"; import { useAuth } from "../contexts/AuthContext"; -import { listEscalas, createEscala, deleteEscala, EscalaInput } from "../services/apiService"; +import { listEscalas, createEscala, deleteEscala, EscalaInput, getFunctions } from "../services/apiService"; import { useData } from "../contexts/DataContext"; import { UserRole } from "../types"; @@ -23,6 +23,7 @@ const EventScheduler: React.FC = ({ agendaId, dataEvento, a const { token, user } = useAuth(); const { professionals, events } = useData(); const [escalas, setEscalas] = useState([]); + const [roles, setRoles] = useState<{ id: string; nome: string }[]>([]); const [loading, setLoading] = useState(false); // New entry state @@ -78,6 +79,9 @@ const EventScheduler: React.FC = ({ agendaId, dataEvento, a useEffect(() => { if (agendaId && token) { fetchEscalas(); + getFunctions().then(res => { + if (res.data) setRoles(res.data); + }); } }, [agendaId, token]); @@ -143,10 +147,11 @@ const EventScheduler: React.FC = ({ agendaId, dataEvento, a }; // 1. Start with all professionals or just the allowed ones - let availableProfs = professionals; + // FILTER: Only show professionals with a valid role (Function), matching "Equipe" page logic. + let availableProfs = professionals.filter(p => roles.some(r => r.id === p.funcao_profissional_id)); const allowedMap = new Map(); // ID -> Status - if (allowedProfessionals && allowedProfessionals.length > 0) { + if (allowedProfessionals) { // Normalize allowed list const ids: string[] = []; allowedProfessionals.forEach((p: any) => { diff --git a/frontend/components/ProfessionalDetailsModal.tsx b/frontend/components/ProfessionalDetailsModal.tsx index 496a5bc..d8ceecd 100644 --- a/frontend/components/ProfessionalDetailsModal.tsx +++ b/frontend/components/ProfessionalDetailsModal.tsx @@ -80,7 +80,7 @@ export const ProfessionalDetailsModal: React.FC =
= ({