feat(filtros): adicionar filtro multi-select por selos no ranking
- Backend: extrair selos de detalhes e filtrar por eles - API: endpoint /ranking/selos e parâmetro selos em /ranking/paginado - Frontend: componente FiltroSelos com dropdown e seleção múltipla - Selos disponíveis: funções, premiações, orientações
This commit is contained in:
@@ -110,11 +110,43 @@ async def health_check():
|
||||
return {"status": "ok", "message": "API Ranking CAPES funcionando"}
|
||||
|
||||
|
||||
@router.get("/ranking/selos")
|
||||
async def listar_selos():
|
||||
from ...infrastructure.ranking_store import SELOS_DISPONIVEIS
|
||||
selos_info = {
|
||||
"PRESID_CAMARA": {"label": "Presidente Câmara", "icone": "👑", "grupo": "funcoes"},
|
||||
"COORD_PPG": {"label": "Coord. PPG", "icone": "🎓", "grupo": "funcoes"},
|
||||
"BPQ": {"label": "Bolsista PQ", "icone": "🏅", "grupo": "funcoes"},
|
||||
"AUTOR_GP": {"label": "Autor Grande Prêmio", "icone": "🏆", "grupo": "premiacoes"},
|
||||
"AUTOR_PREMIO": {"label": "Autor Prêmio", "icone": "🥇", "grupo": "premiacoes"},
|
||||
"AUTOR_MENCAO": {"label": "Autor Menção", "icone": "🥈", "grupo": "premiacoes"},
|
||||
"ORIENT_GP": {"label": "Orientador GP", "icone": "🏆", "grupo": "premiacoes"},
|
||||
"ORIENT_PREMIO": {"label": "Orientador Prêmio", "icone": "🎖️", "grupo": "premiacoes"},
|
||||
"ORIENT_MENCAO": {"label": "Orientador Menção", "icone": "📜", "grupo": "premiacoes"},
|
||||
"COORIENT_GP": {"label": "Coorientador GP", "icone": "🏆", "grupo": "premiacoes"},
|
||||
"COORIENT_PREMIO": {"label": "Coorientador Prêmio", "icone": "🎖️", "grupo": "premiacoes"},
|
||||
"COORIENT_MENCAO": {"label": "Coorientador Menção", "icone": "📜", "grupo": "premiacoes"},
|
||||
"ORIENT_POS_DOC": {"label": "Orient. Pós-Doc", "icone": "🔬", "grupo": "orientacoes"},
|
||||
"ORIENT_TESE": {"label": "Orient. Tese", "icone": "📚", "grupo": "orientacoes"},
|
||||
"ORIENT_DISS": {"label": "Orient. Dissertação", "icone": "📄", "grupo": "orientacoes"},
|
||||
"CO_ORIENT_POS_DOC": {"label": "Coorient. Pós-Doc", "icone": "🔬", "grupo": "coorientacoes"},
|
||||
"CO_ORIENT_TESE": {"label": "Coorient. Tese", "icone": "📚", "grupo": "coorientacoes"},
|
||||
"CO_ORIENT_DISS": {"label": "Coorient. Dissertação", "icone": "📄", "grupo": "coorientacoes"},
|
||||
}
|
||||
return {
|
||||
"selos": [
|
||||
{"codigo": s, **selos_info.get(s, {"label": s, "icone": "🏷️", "grupo": "outros"})}
|
||||
for s in SELOS_DISPONIVEIS
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@router.get("/ranking/paginado", response_model=RankingPaginadoResponseSchema)
|
||||
async def ranking_paginado(
|
||||
page: int = Query(default=1, ge=1, description="Número da página"),
|
||||
size: int = Query(default=50, ge=1, le=1000, description="Tamanho da página (máx 1000)"),
|
||||
ativo: Optional[bool] = Query(default=None, description="Filtrar por status ativo"),
|
||||
selos: Optional[str] = Query(default=None, description="Filtrar por selos (separados por vírgula)"),
|
||||
store = Depends(get_ranking_store),
|
||||
):
|
||||
if not store.is_ready():
|
||||
@@ -123,7 +155,8 @@ async def ranking_paginado(
|
||||
detail="Ranking ainda não foi processado. Execute POST /api/v1/ranking/processar.",
|
||||
)
|
||||
|
||||
total, entries = store.get_page(page=page, size=size, filtro_ativo=ativo)
|
||||
filtro_selos = [s.strip() for s in selos.split(",") if s.strip()] if selos else None
|
||||
total, entries = store.get_page(page=page, size=size, filtro_ativo=ativo, filtro_selos=filtro_selos)
|
||||
|
||||
total_pages = (total + size - 1) // size
|
||||
|
||||
|
||||
Reference in New Issue
Block a user