From 4876d4d9f500bda28faa9ad8ab3915454f163b7f Mon Sep 17 00:00:00 2001 From: Frederico Castro Date: Mon, 15 Dec 2025 11:14:10 -0300 Subject: [PATCH] feat(frontend): adicionar link para perfil no ATUACAPES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adiciona ícone de link externo antes do nome do consultor - Link abre perfil no ATUACAPES em nova aba (/perfil/{id_pessoa}) - Variável de ambiente HOST_ATUACAPES configurável - Adiciona retry automático (10 tentativas) ao carregar ranking - Corrige espaçamento da seção de selos - Atualiza arquivos .env.example --- .env.example | 2 ++ backend/.env.example | 23 ++++++++++---------- docker-compose.yml | 2 ++ frontend/.env.example | 2 ++ frontend/src/App.jsx | 15 +++++++++++-- frontend/src/components/ConsultorCard.css | 24 +++++++++++++++++++++ frontend/src/components/ConsultorCard.jsx | 26 +++++++++++++++++------ 7 files changed, 73 insertions(+), 21 deletions(-) create mode 100644 frontend/.env.example diff --git a/.env.example b/.env.example index cc910f5..dbbe65a 100644 --- a/.env.example +++ b/.env.example @@ -6,3 +6,5 @@ ES_VERIFY_SSL=true SCHEDULER_ENABLED=false SCHEDULER_HOUR=3 + +HOST_ATUACAPES=https://atuacapes.capes.gov.br \ No newline at end of file diff --git a/backend/.env.example b/backend/.env.example index c135381..ce549fd 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -1,18 +1,17 @@ ES_URL=http://localhost:9200 -ES_INDEX=atuacapes__1763197236 +ES_INDEX=atuacapes ES_USER=seu_usuario_elastic ES_PASSWORD=sua_senha_elastic -ES_VERIFY_SSL=true +ES_PASS=sua_senha_elastic -ORACLE_LOCAL_USER=ranking -ORACLE_LOCAL_PASSWORD=senha_oracle -ORACLE_LOCAL_DSN=localhost:1521/XEPDB1 +ORACLE_USER=seu_usuario_oracle +ORACLE_PASSWORD=sua_senha_oracle +ORACLE_DSN=oracle:1521/XEPDB1 -API_HOST=0.0.0.0 -API_PORT=8000 -API_RELOAD=true -CORS_ORIGINS=http://localhost:3000,http://localhost:5173 +ORACLE_LOCAL_USER=seu_usuario_local +ORACLE_LOCAL_PASSWORD=sua_senha_local +ORACLE_LOCAL_DSN=XEPDB1 -LOG_LEVEL=INFO -SCHEDULER_ENABLED=false -SCHEDULER_HOUR=3 +ORACLE_CLIENT=oracle-local + +HOST_ATUACAPES=https://atuacapes.capes.gov.br diff --git a/docker-compose.yml b/docker-compose.yml index 7b8977e..f337d65 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,6 +36,8 @@ services: - backend ports: - "5173:5173" + environment: + - VITE_HOST_ATUACAPES=${HOST_ATUACAPES:-https://atuacapes.capes.gov.br} volumes: - ./frontend/src:/app/src - ./frontend/index.html:/app/index.html diff --git a/frontend/.env.example b/frontend/.env.example new file mode 100644 index 0000000..d8b61f6 --- /dev/null +++ b/frontend/.env.example @@ -0,0 +1,2 @@ +VITE_API_URL=http://localhost:8010/api/v1 +VITE_HOST_ATUACAPES=https://atuacapes.capes.gov.br diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index b5deae9..d7259e5 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -44,7 +44,10 @@ function App() { loadRanking(); }, [page, pageSize]); - const loadRanking = async () => { + const loadRanking = async (retryCount = 0) => { + const MAX_RETRIES = 10; + const RETRY_DELAY = 2000; + try { setLoading(true); setError(null); @@ -56,6 +59,14 @@ function App() { setPage(response.page || page); } catch (err) { const status = err?.response?.status; + const isNetworkError = !err?.response || err?.code === 'ERR_NETWORK'; + + if (isNetworkError && retryCount < MAX_RETRIES) { + setProcessMessage(`Aguardando API... (tentativa ${retryCount + 1}/${MAX_RETRIES})`); + await new Promise((r) => setTimeout(r, RETRY_DELAY)); + return loadRanking(retryCount + 1); + } + if (status === 503) { try { setProcessing(true); @@ -146,7 +157,7 @@ function App() { return (
- {processing ? (processMessage || 'Processando ranking...') : 'Carregando ranking...'} + {processMessage || (processing ? 'Processando ranking...' : 'Carregando ranking...')}
); diff --git a/frontend/src/components/ConsultorCard.css b/frontend/src/components/ConsultorCard.css index f5c617f..532c0cd 100644 --- a/frontend/src/components/ConsultorCard.css +++ b/frontend/src/components/ConsultorCard.css @@ -628,6 +628,7 @@ .selos-section { grid-column: 1 / -1; + margin-top: 1rem; } .selos-section .selos-container { @@ -651,3 +652,26 @@ display: none; } } + +.link-atuacapes { + display: inline-flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + font-size: 0.9rem; + color: var(--muted); + background: rgba(255, 255, 255, 0.06); + border: 1px solid var(--stroke); + border-radius: 6px; + text-decoration: none; + transition: all 200ms ease; + cursor: pointer; +} + +.link-atuacapes:hover { + color: var(--accent-2); + background: rgba(79, 70, 229, 0.15); + border-color: rgba(79, 70, 229, 0.4); + transform: scale(1.1); +} diff --git a/frontend/src/components/ConsultorCard.jsx b/frontend/src/components/ConsultorCard.jsx index 605ff09..9902dce 100644 --- a/frontend/src/components/ConsultorCard.jsx +++ b/frontend/src/components/ConsultorCard.jsx @@ -237,6 +237,18 @@ const ConsultorCard = memo(({ consultor, highlight, selecionado, onToggleSelecio
+ {import.meta.env.VITE_HOST_ATUACAPES && consultor.id_pessoa && ( + e.stopPropagation()} + title="Ver perfil no ATUACAPES" + > + ↗ + + )} {consultor.nome} {consultor.ativo && ATIVO} {!consultor.ativo && HISTORICO} @@ -325,15 +337,15 @@ const ConsultorCard = memo(({ consultor, highlight, selecionado, onToggleSelecio {blocoD.atuacoes && blocoD.atuacoes.length > 0 && ( )} - - {selos.length > 0 && ( -
-

Selos e Reconhecimentos

- -
- )}
+ {selos.length > 0 && ( +
+

Selos e Reconhecimentos

+ +
+ )} + {consultor.coordenacoes_capes?.length > 0 && (

Coordenacoes CAPES