feat(ranking): adicionar badges de tipos de atuação nos cards

- Adiciona campo tipos_atuacao ao schema e extração no mapper
- Exibe tipos de atuação (Coordenador, Consultor, Avaliador, etc.)
  na seção expandida do card, acima de Selos e Reconhecimentos
- Inclui estilos visuais distintos para cada tipo de atuação
- Melhorias no Header e SugerirConsultores
This commit is contained in:
Frederico Castro
2025-12-21 05:36:26 -03:00
parent bb36961b4c
commit d4aa75ca0b
10 changed files with 424 additions and 40 deletions

View File

@@ -1,14 +1,47 @@
import json
import logging
from typing import Any, Dict, Optional
from typing import Any, Dict, List, Optional
from ...domain.entities.consultor_ranking import ConsultorRanking
from ...interface.schemas.ranking_schema import ConsultorRankingResumoSchema
logger = logging.getLogger(__name__)
TIPOS_ATUACAO_ORDEM = [
("Coordenador", "coordenacoes_capes"),
("Consultor", "consultoria"),
("Avaliador", "avaliacoes_comissao"),
("Premiado", "premiacoes"),
("Orientador", "orientacoes"),
("Bolsista CNPq", "bolsas_cnpq"),
("Inscrito Premio", "inscricoes"),
("Projeto", "participacoes_projeto"),
("Evento", "participacoes_evento"),
]
class RankingMapper:
@staticmethod
def _extrair_tipos_atuacao(jd: Dict[str, Any]) -> List[str]:
tipos = []
for label, campo in TIPOS_ATUACAO_ORDEM:
if campo == "consultoria":
if jd.get("consultoria"):
tipos.append(label)
elif campo == "participacoes_projeto":
participacoes = jd.get("participacoes") or []
if any(p.get("codigo") == "PROJ" for p in participacoes):
tipos.append(label)
elif campo == "participacoes_evento":
participacoes = jd.get("participacoes") or []
if any(p.get("codigo") == "EVENTO" for p in participacoes):
tipos.append(label)
else:
dados = jd.get(campo)
if dados and (isinstance(dados, list) and len(dados) > 0):
tipos.append(label)
return tipos
@staticmethod
def consultor_ranking_to_schema(c: ConsultorRanking) -> ConsultorRankingResumoSchema:
consultoria = None
@@ -21,6 +54,7 @@ class RankingMapper:
orientacoes = None
membros_banca = None
pontuacao = None
tipos_atuacao = []
try:
jd = json.loads(c.json_detalhes) if c.json_detalhes else {}
@@ -35,6 +69,7 @@ class RankingMapper:
orientacoes = jd.get("orientacoes")
membros_banca = jd.get("membros_banca")
pontuacao = jd.get("pontuacao")
tipos_atuacao = RankingMapper._extrair_tipos_atuacao(jd)
except (json.JSONDecodeError, TypeError) as e:
logger.warning(f"Erro ao parsear json_detalhes do consultor {c.id_pessoa}: {e}")
@@ -59,6 +94,7 @@ class RankingMapper:
bloco_d=bloco_d,
ativo=c.ativo,
anos_atuacao=c.anos_atuacao,
tipos_atuacao=tipos_atuacao,
consultoria=consultoria,
coordenacoes_capes=coordenacoes_capes,
inscricoes=inscricoes,

View File

@@ -21,6 +21,7 @@ def normalizar_texto(texto: str) -> str:
from ...application.use_cases.obter_ranking import ObterRankingUseCase
from ...application.use_cases.obter_consultor import ObterConsultorUseCase
from ...infrastructure.repositories.consultor_repository_impl import ConsultorRepositoryImpl
from ...application.mappers.ranking_mapper import RankingMapper
from ..schemas.consultor_schema import (
RankingResponseSchema,
RankingDetalhadoResponseSchema,
@@ -183,6 +184,7 @@ async def ranking_paginado(
consultores_schema = []
for e in entries:
d = e.detalhes
tipos_atuacao = RankingMapper._extrair_tipos_atuacao(d)
consultores_schema.append(
ConsultorRankingResumoSchema(
id_pessoa=e.id_pessoa,
@@ -195,6 +197,7 @@ async def ranking_paginado(
bloco_d=float(e.bloco_d),
ativo=e.ativo,
anos_atuacao=float(e.anos_atuacao),
tipos_atuacao=tipos_atuacao,
coordenador_ppg=bool(d.get("coordenador_ppg", False)),
consultoria=d.get("consultoria"),
coordenacoes_capes=d.get("coordenacoes_capes"),

View File

@@ -14,6 +14,7 @@ class ConsultorRankingResumoSchema(BaseModel):
bloco_d: float
ativo: bool
anos_atuacao: float
tipos_atuacao: List[str] = []
coordenador_ppg: Optional[bool] = None
consultoria: Optional[dict] = None
coordenacoes_capes: Optional[list] = None