feat(avaliacao): adicionar nome da comissão nas avaliações
- Adiciona campo nome_comissao em AvaliacaoComissao (entity, DTO, schema) - Extrai nome da comissão do Elasticsearch no repository - Propaga campo pelo job de processamento e use case - Exibe nome da comissão no ConsultorCard (frontend) - Remove link do manual PDF do footer
This commit is contained in:
@@ -47,6 +47,7 @@ class AvaliacaoComissaoDTO:
|
|||||||
premio: str
|
premio: str
|
||||||
ano: int
|
ano: int
|
||||||
comissao_tipo: str
|
comissao_tipo: str
|
||||||
|
nome_comissao: str
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -149,7 +149,8 @@ class ProcessarRankingJob:
|
|||||||
"tipo": a.tipo,
|
"tipo": a.tipo,
|
||||||
"premio": a.premio,
|
"premio": a.premio,
|
||||||
"ano": a.ano,
|
"ano": a.ano,
|
||||||
"comissao_tipo": a.comissao_tipo
|
"comissao_tipo": a.comissao_tipo,
|
||||||
|
"nome_comissao": a.nome_comissao,
|
||||||
}
|
}
|
||||||
for a in consultor.avaliacoes_comissao
|
for a in consultor.avaliacoes_comissao
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ class ObterRankingUseCase:
|
|||||||
premio=a.premio,
|
premio=a.premio,
|
||||||
ano=a.ano,
|
ano=a.ano,
|
||||||
comissao_tipo=a.comissao_tipo,
|
comissao_tipo=a.comissao_tipo,
|
||||||
|
nome_comissao=a.nome_comissao,
|
||||||
)
|
)
|
||||||
for a in consultor.avaliacoes_comissao
|
for a in consultor.avaliacoes_comissao
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class AvaliacaoComissao:
|
|||||||
premio: str
|
premio: str
|
||||||
ano: int
|
ano: int
|
||||||
comissao_tipo: str = ""
|
comissao_tipo: str = ""
|
||||||
|
nome_comissao: str = ""
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -253,6 +253,7 @@ class ConsultorRepositoryImpl(ConsultorRepository):
|
|||||||
|
|
||||||
comissao = dados.get("comissao", {}) or {}
|
comissao = dados.get("comissao", {}) or {}
|
||||||
comissao_tipo = comissao.get("tipo", "") if isinstance(comissao, dict) else ""
|
comissao_tipo = comissao.get("tipo", "") if isinstance(comissao, dict) else ""
|
||||||
|
nome_comissao = comissao.get("nome", "") if isinstance(comissao, dict) else ""
|
||||||
|
|
||||||
is_grande_premio = "grande" in nome_premio.lower()
|
is_grande_premio = "grande" in nome_premio.lower()
|
||||||
is_coordenador = "coordenador" in tipo_part.lower() or "presidente" in tipo_part.lower()
|
is_coordenador = "coordenador" in tipo_part.lower() or "presidente" in tipo_part.lower()
|
||||||
@@ -268,6 +269,7 @@ class ConsultorRepositoryImpl(ConsultorRepository):
|
|||||||
premio=nome_premio,
|
premio=nome_premio,
|
||||||
ano=ano,
|
ano=ano,
|
||||||
comissao_tipo=comissao_tipo,
|
comissao_tipo=comissao_tipo,
|
||||||
|
nome_comissao=nome_comissao,
|
||||||
))
|
))
|
||||||
|
|
||||||
return avaliacoes
|
return avaliacoes
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
from fastapi.staticfiles import StaticFiles
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
|
||||||
from .routes import router
|
from .routes import router
|
||||||
@@ -147,6 +149,10 @@ app.add_middleware(
|
|||||||
|
|
||||||
app.include_router(router)
|
app.include_router(router)
|
||||||
|
|
||||||
|
static_dir = Path(__file__).parent.parent.parent.parent / "static"
|
||||||
|
if static_dir.exists():
|
||||||
|
app.mount("/api/static", StaticFiles(directory=str(static_dir)), name="static")
|
||||||
|
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
async def root():
|
async def root():
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class AvaliacaoComissaoSchema(BaseModel):
|
|||||||
premio: str
|
premio: str
|
||||||
ano: int
|
ano: int
|
||||||
comissao_tipo: str
|
comissao_tipo: str
|
||||||
|
nome_comissao: str = ""
|
||||||
|
|
||||||
|
|
||||||
class PremiacaoSchema(BaseModel):
|
class PremiacaoSchema(BaseModel):
|
||||||
|
|||||||
BIN
backend/static/Manual_Ranking_Consultores_CAPES.pdf
Normal file
BIN
backend/static/Manual_Ranking_Consultores_CAPES.pdf
Normal file
Binary file not shown.
@@ -22,6 +22,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./backend/src:/app/src
|
- ./backend/src:/app/src
|
||||||
- ./backend/scripts:/app/scripts
|
- ./backend/scripts:/app/scripts
|
||||||
|
- ./backend/static:/app/static
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
networks:
|
networks:
|
||||||
- shared_network
|
- shared_network
|
||||||
|
|||||||
@@ -194,6 +194,28 @@ footer p + p {
|
|||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.manual-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
padding: 0.6rem 1.2rem;
|
||||||
|
background: linear-gradient(145deg, var(--accent), var(--accent-2));
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
transition: all 200ms ease;
|
||||||
|
box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-link:hover {
|
||||||
|
filter: brightness(1.1);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 20px rgba(79, 70, 229, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
.selecao-flutuante {
|
.selecao-flutuante {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 2rem;
|
bottom: 2rem;
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ function App() {
|
|||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<p>Dados: ATUACAPES (Elasticsearch) + Oracle</p>
|
<p>Dados: ATUACAPES (Elasticsearch) + Oracle</p>
|
||||||
<p>Critérios: Minuta Técnica - Ranking AtuaCAPES | Clique em qualquer consultor para ver detalhes</p>
|
<p>Clique em qualquer consultor para ver detalhes</p>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -388,7 +388,7 @@ const ConsultorCard = memo(({ consultor, highlight, selecionado, onToggleSelecio
|
|||||||
<div key={idx} className="list-item">
|
<div key={idx} className="list-item">
|
||||||
<span className="badge">{aval.codigo}</span>
|
<span className="badge">{aval.codigo}</span>
|
||||||
<span className="pontos">{PONTOS_BASE[aval.codigo] || 0} pts</span>
|
<span className="pontos">{PONTOS_BASE[aval.codigo] || 0} pts</span>
|
||||||
<span>{aval.premio}</span>
|
<span>{aval.nome_comissao || aval.premio}</span>
|
||||||
<span className="muted">{aval.ano}</span>
|
<span className="muted">{aval.ano}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
Reference in New Issue
Block a user