fix(lattes): correcoes finais na integracao Lattes

This commit is contained in:
Frederico Castro
2025-12-27 01:06:43 -03:00
parent 1e15ab64ca
commit c78f48c988
3 changed files with 632 additions and 25 deletions

View File

@@ -236,7 +236,17 @@ async def ranking_paginado(
if not d.get("idiomas"): if not d.get("idiomas"):
faltando_idiomas.append((c.id_pessoa, d)) faltando_idiomas.append((c.id_pessoa, d))
faltando_lattes = [(c.id_pessoa, d) for c, d in consultores_dados if not d.get("lattes")] def lattes_incompleto(d):
lattes = d.get("lattes")
if not lattes:
return True
titulacoes = lattes.get("titulacoes", [])
if not titulacoes:
return False
primeira = titulacoes[0] if titulacoes else {}
return "programa" not in primeira or "area_avaliacao" not in primeira
faltando_lattes = [(c.id_pessoa, d) for c, d in consultores_dados if lattes_incompleto(d)]
ids_buscar = list(set([item[0] for item in faltando_idiomas] + [item[0] for item in faltando_lattes])) ids_buscar = list(set([item[0] for item in faltando_idiomas] + [item[0] for item in faltando_lattes]))
if ids_buscar: if ids_buscar:
@@ -279,14 +289,26 @@ async def ranking_paginado(
for t in titulacoes_raw: for t in titulacoes_raw:
grau_obj = t.get("grauAcademico", {}) grau_obj = t.get("grauAcademico", {})
ies_obj = t.get("ies", {}) ies_obj = t.get("ies", {})
area_obj = t.get("areaConhecimento", {})
programa_obj = t.get("programa", {})
titulacoes_formatadas.append({ titulacoes_formatadas.append({
"grau": grau_obj.get("nome", ""), "grau": grau_obj.get("nome", ""),
"hierarquia": grau_obj.get("hierarquia"),
"ano": t.get("ano"), "ano": t.get("ano"),
"inicio": t.get("inicio"),
"fim": t.get("fim"),
"ies_nome": ies_obj.get("nome"), "ies_nome": ies_obj.get("nome"),
"ies_sigla": ies_obj.get("sigla"), "ies_sigla": ies_obj.get("sigla"),
"area": t.get("areaConhecimento", {}).get("nome"), "ies_status": ies_obj.get("statusJuridico"),
"pais": "Brasil", "area": area_obj.get("nome"),
"area_avaliacao": area_obj.get("areaAvaliacao", {}).get("nome") if area_obj.get("areaAvaliacao") else None,
"programa": programa_obj.get("nome") if programa_obj else None,
"codigo_programa": programa_obj.get("codigo") if programa_obj else None,
"programa_modalidade": programa_obj.get("modalidade") if programa_obj else None,
"programa_situacao": programa_obj.get("situacao") if programa_obj else None,
"pais": t.get("pais") or "Brasil",
}) })
titulacoes_formatadas.sort(key=lambda x: (x.get("hierarquia") or 99, -(x.get("ano") or 0)))
detalhes["lattes"] = { detalhes["lattes"] = {
"id_lattes": id_lattes, "id_lattes": id_lattes,
"url": f"http://lattes.cnpq.br/{id_lattes}", "url": f"http://lattes.cnpq.br/{id_lattes}",
@@ -514,6 +536,9 @@ async def obter_lattes(
"area_avaliacao": area_obj.get("areaAvaliacao", {}).get("nome") if area_obj.get("areaAvaliacao") else None, "area_avaliacao": area_obj.get("areaAvaliacao", {}).get("nome") if area_obj.get("areaAvaliacao") else None,
"programa": programa_obj.get("nome") if programa_obj else None, "programa": programa_obj.get("nome") if programa_obj else None,
"codigo_programa": programa_obj.get("codigo") if programa_obj else None, "codigo_programa": programa_obj.get("codigo") if programa_obj else None,
"programa_modalidade": programa_obj.get("modalidade") if programa_obj else None,
"programa_situacao": programa_obj.get("situacao") if programa_obj else None,
"pais": t.get("pais") or "Brasil",
}) })
titulacoes.sort(key=lambda x: (x.get("hierarquia") or 99, -(x.get("ano") or 0))) titulacoes.sort(key=lambda x: (x.get("hierarquia") or 99, -(x.get("ano") or 0)))
@@ -562,6 +587,111 @@ async def obter_lattes(
"ies": dados.get("ies", {}).get("sigla") if dados.get("ies") else None, "ies": dados.get("ies", {}).get("sigla") if dados.get("ies") else None,
}) })
docencias = []
for a in atuacoes_raw:
if a.get("tipo") == "Docência":
dados = a.get("dadosDocencia", {})
if dados:
programa_obj = dados.get("programa", {})
ies_obj = dados.get("ies", {})
area_obj = dados.get("areaConhecimento", {})
linhas = dados.get("linhaPesquisa", [])
linhas_ativas = [l.get("nome") for l in linhas if l.get("fim") is None][:5]
docencias.append({
"programa": programa_obj.get("nome") if programa_obj else None,
"codigo_programa": programa_obj.get("codigo") if programa_obj else None,
"modalidade": programa_obj.get("modalidade") if programa_obj else None,
"situacao_programa": programa_obj.get("situacao") if programa_obj else None,
"ies_nome": ies_obj.get("nome") if ies_obj else None,
"ies_sigla": ies_obj.get("sigla") if ies_obj else None,
"area": area_obj.get("nome") if area_obj else None,
"area_avaliacao": area_obj.get("areaAvaliacao", {}).get("nome") if area_obj.get("areaAvaliacao") else None,
"categoria": dados.get("categoria"),
"tipo_vinculo": dados.get("tipoVinculo"),
"regime_trabalho": dados.get("regimeTrabalho"),
"carga_horaria": dados.get("cargaHoraria"),
"linhas_pesquisa_ativas": linhas_ativas,
"total_linhas_pesquisa": len(linhas),
})
empregos = []
for a in atuacoes_raw:
if a.get("tipo") == "Emprego":
dados = a.get("dadosEmprego", {})
if dados:
historico = dados.get("historico", [])
periodos = []
for h in historico:
periodos.append({
"inicio": h.get("inicioRelacionamento"),
"fim": h.get("fimRelacionamento"),
})
empregos.append({
"empregador": dados.get("nomeEmpregador"),
"cnpj": dados.get("cnpjEmpregador"),
"tipo_emprego": dados.get("emprego"),
"atividade": dados.get("atividade"),
"vinculo": dados.get("vinculo"),
"profissao": dados.get("profissao"),
"periodos": periodos,
})
projetos = []
for a in atuacoes_raw:
if a.get("tipo") == "Projeto":
dados = a.get("dadosProjeto", {})
if dados and dados.get("nome"):
programa_obj = dados.get("programa", {})
ies_obj = dados.get("ies", {})
area_obj = dados.get("areaConhecimento", {})
projetos.append({
"nome": dados.get("nome"),
"situacao": dados.get("situacao"),
"ano_inicio": dados.get("anoInicio"),
"linha_pesquisa": dados.get("linhaPesquisa"),
"programa": programa_obj.get("nome") if programa_obj else None,
"ies_sigla": ies_obj.get("sigla") if ies_obj else None,
"area": area_obj.get("nome") if area_obj else None,
})
premiacoes_detalhadas = []
for a in atuacoes_raw:
if a.get("tipo") == "Premiação Prêmio":
dados = a.get("dadosPremiacaoPremio", {})
if dados:
produto = dados.get("produto", {})
ies_obj = dados.get("ies", {})
programa_obj = dados.get("programa", {})
area_obj = dados.get("areaConhecimento", {})
premiacoes_detalhadas.append({
"premio": dados.get("premio"),
"evento": dados.get("evento"),
"premiacao": dados.get("premiacao"),
"ano": dados.get("ano"),
"papel": dados.get("papelPessoa"),
"situacao": dados.get("situacao"),
"produto_nome": produto.get("nome") if produto else None,
"produto_tipo": produto.get("tipoProduto", {}).get("nome") if produto.get("tipoProduto") else None,
"produto_autor": produto.get("autor") if produto else None,
"ies_sigla": ies_obj.get("sigla") if ies_obj else None,
"programa": programa_obj.get("nome") if programa_obj else None,
"area": area_obj.get("nome") if area_obj else None,
})
estatisticas_orientacoes = None
for a in atuacoes_raw:
if a.get("tipo") == "Orientação de Discentes":
dados = a.get("dadosOrientacaoDiscente", {})
if dados:
estatisticas_orientacoes = {
"mestrado_finalizado": dados.get("totalOrientacaoFinalizadaMestrado"),
"doutorado_finalizado": dados.get("totalOrientacaoFinalizadaDoutorado"),
"mestrado_andamento": dados.get("totalOrientacaoAndamentoMestrado"),
"doutorado_andamento": dados.get("totalOrientacaoAndamentoDoutorado"),
"pos_doutorado": dados.get("totalAcompanhamentoPosDoutorado"),
}
break
return { return {
"encontrado": True, "encontrado": True,
"id_lattes": id_lattes, "id_lattes": id_lattes,
@@ -575,6 +705,12 @@ async def obter_lattes(
"endereco_profissional": endereco_profissional, "endereco_profissional": endereco_profissional,
"orientacoes_concluidas": orientacoes_concluidas[:20], "orientacoes_concluidas": orientacoes_concluidas[:20],
"total_orientacoes": len(orientacoes_concluidas), "total_orientacoes": len(orientacoes_concluidas),
"estatisticas_orientacoes": estatisticas_orientacoes,
"docencias": docencias,
"empregos": empregos,
"projetos": projetos[:30],
"total_projetos": len(projetos),
"premiacoes_detalhadas": premiacoes_detalhadas,
"data_atualizacao_lattes": None, "data_atualizacao_lattes": None,
} }

View File

@@ -1607,3 +1607,34 @@
opacity: 1; opacity: 1;
transform: translateY(-50%) translateX(3px); transform: translateY(-50%) translateX(3px);
} }
.modal-stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 0.75rem;
margin-bottom: 1rem;
}
.modal-stat-card {
background: rgba(99, 102, 241, 0.1);
border: 1px solid rgba(99, 102, 241, 0.2);
border-radius: 8px;
padding: 0.75rem;
text-align: center;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.modal-stat-card .stat-number {
font-size: 1.5rem;
font-weight: 700;
color: var(--accent);
}
.modal-stat-card .stat-label {
font-size: 0.7rem;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.03em;
}

View File

@@ -719,6 +719,10 @@ const ItemDetalheModal = ({ item, tipo, onClose }) => {
case 'orientacao': return 'Orientação'; case 'orientacao': return 'Orientação';
case 'orientacao_lattes': return 'Orientação Concluída'; case 'orientacao_lattes': return 'Orientação Concluída';
case 'idioma': return 'Idioma'; case 'idioma': return 'Idioma';
case 'docencia': return 'Docência em PPG';
case 'emprego': return 'Vínculo Empregatício';
case 'projeto': return 'Projeto de Pesquisa';
case 'premiacao_lattes': return 'Premiação';
default: return 'Detalhes'; default: return 'Detalhes';
} }
}; };
@@ -736,6 +740,10 @@ const ItemDetalheModal = ({ item, tipo, onClose }) => {
case 'orientacao': return '🎓'; case 'orientacao': return '🎓';
case 'orientacao_lattes': return '👨‍🏫'; case 'orientacao_lattes': return '👨‍🏫';
case 'idioma': return '🌐'; case 'idioma': return '🌐';
case 'docencia': return '👨‍🏫';
case 'emprego': return '🏢';
case 'projeto': return '📊';
case 'premiacao_lattes': return '🏆';
default: return '📄'; default: return '📄';
} }
}; };
@@ -792,6 +800,18 @@ const ItemDetalheModal = ({ item, tipo, onClose }) => {
<span className="modal-detalhe-value">{it.codigo_programa}</span> <span className="modal-detalhe-value">{it.codigo_programa}</span>
</div> </div>
)} )}
{it.programa_modalidade && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Modalidade</span>
<span className="modal-detalhe-value">{it.programa_modalidade}</span>
</div>
)}
{it.programa_situacao && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Situação Programa</span>
<span className="modal-detalhe-value">{it.programa_situacao}</span>
</div>
)}
{it.pais && ( {it.pais && (
<div className="modal-detalhe-row"> <div className="modal-detalhe-row">
<span className="modal-detalhe-label">País</span> <span className="modal-detalhe-label">País</span>
@@ -900,6 +920,269 @@ const ItemDetalheModal = ({ item, tipo, onClose }) => {
); );
} }
case 'docencia': {
const d = currentItem;
return (
<div className="modal-detalhe-content">
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Programa</span>
<span className="modal-detalhe-value">{d.programa || 'N/A'}</span>
</div>
{d.codigo_programa && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Código</span>
<span className="modal-detalhe-value">{d.codigo_programa}</span>
</div>
)}
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Instituição</span>
<span className="modal-detalhe-value">{d.ies_nome} ({d.ies_sigla})</span>
</div>
{d.modalidade && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Modalidade</span>
<span className="modal-detalhe-value">{d.modalidade}</span>
</div>
)}
{d.situacao_programa && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Situação</span>
<span className="modal-detalhe-value">{d.situacao_programa}</span>
</div>
)}
{d.area && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Área</span>
<span className="modal-detalhe-value">{d.area}</span>
</div>
)}
{d.area_avaliacao && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Área de Avaliação</span>
<span className="modal-detalhe-value">{d.area_avaliacao}</span>
</div>
)}
{d.categoria && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Categoria</span>
<span className="modal-detalhe-value">{d.categoria}</span>
</div>
)}
{d.tipo_vinculo && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Tipo de Vínculo</span>
<span className="modal-detalhe-value">{d.tipo_vinculo}</span>
</div>
)}
{d.regime_trabalho && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Regime de Trabalho</span>
<span className="modal-detalhe-value">{d.regime_trabalho}</span>
</div>
)}
{d.carga_horaria && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Carga Horária</span>
<span className="modal-detalhe-value">{d.carga_horaria}h</span>
</div>
)}
{d.linhas_pesquisa_ativas?.length > 0 && (
<>
<h5 className="modal-section-title">Linhas de Pesquisa Ativas ({d.linhas_pesquisa_ativas.length} de {d.total_linhas_pesquisa})</h5>
<ul className="modal-list">
{d.linhas_pesquisa_ativas.map((linha, idx) => (
<li key={idx} className="modal-item">
<span className="modal-item-main">{linha}</span>
</li>
))}
</ul>
</>
)}
</div>
);
}
case 'emprego': {
const e = currentItem;
return (
<div className="modal-detalhe-content">
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Empregador</span>
<span className="modal-detalhe-value">{e.empregador || 'N/A'}</span>
</div>
{e.cnpj && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">CNPJ</span>
<span className="modal-detalhe-value">{e.cnpj}</span>
</div>
)}
{e.tipo_emprego && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Tipo</span>
<span className="modal-detalhe-value">{e.tipo_emprego}</span>
</div>
)}
{e.atividade && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Atividade</span>
<span className="modal-detalhe-value">{e.atividade}</span>
</div>
)}
{e.vinculo && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Vínculo</span>
<span className="modal-detalhe-value">{e.vinculo}</span>
</div>
)}
{e.profissao && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Profissão</span>
<span className="modal-detalhe-value">{e.profissao}</span>
</div>
)}
{e.periodos?.length > 0 && (
<>
<h5 className="modal-section-title">Períodos ({e.periodos.length})</h5>
<ul className="modal-list">
{e.periodos.map((p, idx) => (
<li key={idx} className="modal-item">
<span className="modal-item-main">
{p.inicio ? formatDate(p.inicio) : 'Sem data'} a {p.fim ? formatDate(p.fim) : 'Atual'}
</span>
</li>
))}
</ul>
</>
)}
</div>
);
}
case 'projeto': {
const p = currentItem;
return (
<div className="modal-detalhe-content">
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Nome</span>
<span className="modal-detalhe-value">{p.nome || 'N/A'}</span>
</div>
{p.situacao && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Situação</span>
<span className={`badge ${p.situacao === 'EM ANDAMENTO' ? 'badge-ativo' : 'badge-historico'}`}>
{p.situacao}
</span>
</div>
)}
{p.ano_inicio && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Ano de Início</span>
<span className="modal-detalhe-value">{p.ano_inicio}</span>
</div>
)}
{p.ies_sigla && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Instituição</span>
<span className="modal-detalhe-value">{p.ies_sigla}</span>
</div>
)}
{p.programa && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Programa</span>
<span className="modal-detalhe-value">{p.programa}</span>
</div>
)}
{p.area && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Área</span>
<span className="modal-detalhe-value">{p.area}</span>
</div>
)}
{p.linha_pesquisa && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Linha de Pesquisa</span>
<span className="modal-detalhe-value">{p.linha_pesquisa}</span>
</div>
)}
</div>
);
}
case 'premiacao_lattes': {
const pr = currentItem;
return (
<div className="modal-detalhe-content">
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Evento</span>
<span className="modal-detalhe-value">{pr.evento || pr.premio || 'N/A'}</span>
</div>
{pr.premiacao && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Tipo</span>
<span className="modal-detalhe-value">{pr.premiacao}</span>
</div>
)}
{pr.ano && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Ano</span>
<span className="modal-detalhe-value">{pr.ano}</span>
</div>
)}
{pr.papel && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Papel</span>
<span className="modal-detalhe-value">{pr.papel}</span>
</div>
)}
{pr.situacao && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Situação</span>
<span className="modal-detalhe-value">{pr.situacao}</span>
</div>
)}
{pr.ies_sigla && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Instituição</span>
<span className="modal-detalhe-value">{pr.ies_sigla}</span>
</div>
)}
{pr.programa && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Programa</span>
<span className="modal-detalhe-value">{pr.programa}</span>
</div>
)}
{pr.area && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Área</span>
<span className="modal-detalhe-value">{pr.area}</span>
</div>
)}
{pr.produto_nome && (
<>
<h5 className="modal-section-title">Produto</h5>
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Título</span>
<span className="modal-detalhe-value">{pr.produto_nome}</span>
</div>
{pr.produto_tipo && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Tipo</span>
<span className="modal-detalhe-value">{pr.produto_tipo}</span>
</div>
)}
{pr.produto_autor && (
<div className="modal-detalhe-row">
<span className="modal-detalhe-label">Autor</span>
<span className="modal-detalhe-value">{pr.produto_autor}</span>
</div>
)}
</>
)}
</div>
);
}
case 'producoes_lattes': { case 'producoes_lattes': {
const titulacoes = item.titulacoes || []; const titulacoes = item.titulacoes || [];
const idiomas = item.idiomas || []; const idiomas = item.idiomas || [];
@@ -1013,6 +1296,162 @@ const ItemDetalheModal = ({ item, tipo, onClose }) => {
</> </>
)} )}
{item.estatisticas_orientacoes && (
<>
<h5 className="modal-section-title">Estatísticas de Orientações</h5>
<div className="modal-stats-grid">
{item.estatisticas_orientacoes.doutorado_finalizado > 0 && (
<div className="modal-stat-card">
<span className="stat-number">{item.estatisticas_orientacoes.doutorado_finalizado}</span>
<span className="stat-label">Doutorados Concluídos</span>
</div>
)}
{item.estatisticas_orientacoes.mestrado_finalizado > 0 && (
<div className="modal-stat-card">
<span className="stat-number">{item.estatisticas_orientacoes.mestrado_finalizado}</span>
<span className="stat-label">Mestrados Concluídos</span>
</div>
)}
{item.estatisticas_orientacoes.doutorado_andamento > 0 && (
<div className="modal-stat-card">
<span className="stat-number">{item.estatisticas_orientacoes.doutorado_andamento}</span>
<span className="stat-label">Doutorados em Andamento</span>
</div>
)}
{item.estatisticas_orientacoes.mestrado_andamento > 0 && (
<div className="modal-stat-card">
<span className="stat-number">{item.estatisticas_orientacoes.mestrado_andamento}</span>
<span className="stat-label">Mestrados em Andamento</span>
</div>
)}
{item.estatisticas_orientacoes.pos_doutorado > 0 && (
<div className="modal-stat-card">
<span className="stat-number">{item.estatisticas_orientacoes.pos_doutorado}</span>
<span className="stat-label">Pós-Doutorados</span>
</div>
)}
</div>
</>
)}
{item.docencias?.length > 0 && (
<>
<h5 className="modal-section-title">Docência em PPG ({item.docencias.length})</h5>
<ul className="modal-list">
{item.docencias.map((d, idx) => (
<li
key={idx}
className="modal-item modal-item-clicavel"
onClick={() => setSubDetalhe({ item: d, tipo: 'docencia' })}
>
<span className="modal-item-main">
<strong>{d.programa || 'Programa não informado'}</strong>
</span>
<span className="modal-item-detail">
{d.ies_sigla} | {d.modalidade} | {d.categoria}
</span>
{d.linhas_pesquisa_ativas?.length > 0 && (
<span className="modal-item-sub muted">
{d.linhas_pesquisa_ativas.length} linhas de pesquisa ativas
</span>
)}
<span className="modal-item-arrow"></span>
</li>
))}
</ul>
</>
)}
{item.empregos?.length > 0 && (
<>
<h5 className="modal-section-title">Vínculos Empregatícios ({item.empregos.length})</h5>
<ul className="modal-list">
{item.empregos.map((e, idx) => (
<li
key={idx}
className="modal-item modal-item-clicavel"
onClick={() => setSubDetalhe({ item: e, tipo: 'emprego' })}
>
<span className="modal-item-main">{e.empregador || 'Empregador não informado'}</span>
<span className="modal-item-detail">
{e.tipo_emprego}
{e.atividade && ` | ${e.atividade}`}
</span>
{e.periodos?.length > 0 && (
<span className="modal-item-sub muted">
{e.periodos.length} período(s) registrado(s)
</span>
)}
<span className="modal-item-arrow"></span>
</li>
))}
</ul>
</>
)}
{item.projetos?.length > 0 && (
<>
<h5 className="modal-section-title">
Projetos de Pesquisa ({item.total_projetos})
</h5>
<ul className="modal-list">
{item.projetos.slice(0, 10).map((p, idx) => (
<li
key={idx}
className="modal-item modal-item-clicavel"
onClick={() => setSubDetalhe({ item: p, tipo: 'projeto' })}
>
<span className="modal-item-main">
{p.nome?.length > 60 ? p.nome.substring(0, 60) + '...' : p.nome}
</span>
<span className="modal-item-detail">
{p.situacao}
{p.ano_inicio && ` | Início: ${p.ano_inicio}`}
{p.ies_sigla && ` | ${p.ies_sigla}`}
</span>
<span className="modal-item-arrow"></span>
</li>
))}
{item.total_projetos > 10 && (
<li className="modal-item muted">
... e mais {item.total_projetos - 10} projetos
</li>
)}
</ul>
</>
)}
{item.premiacoes_detalhadas?.length > 0 && (
<>
<h5 className="modal-section-title">Premiações Detalhadas ({item.premiacoes_detalhadas.length})</h5>
<ul className="modal-list">
{item.premiacoes_detalhadas.map((pr, idx) => (
<li
key={idx}
className="modal-item modal-item-clicavel"
onClick={() => setSubDetalhe({ item: pr, tipo: 'premiacao_lattes' })}
>
<span className="modal-item-main">
<strong>{pr.evento || pr.premio}</strong>
{pr.premiacao && ` - ${pr.premiacao}`}
</span>
<span className="modal-item-detail">
{pr.papel && `${pr.papel} | `}
{pr.ano}
{pr.ies_sigla && ` | ${pr.ies_sigla}`}
</span>
{pr.produto_nome && (
<span className="modal-item-sub muted" style={{ fontSize: '0.75rem' }}>
{pr.produto_nome.length > 60 ? pr.produto_nome.substring(0, 60) + '...' : pr.produto_nome}
</span>
)}
<span className="modal-item-arrow"></span>
</li>
))}
</ul>
</>
)}
{endereco && ( {endereco && (
<> <>
<h5 className="modal-section-title">Endereço Profissional</h5> <h5 className="modal-section-title">Endereço Profissional</h5>
@@ -1030,7 +1469,8 @@ const ItemDetalheModal = ({ item, tipo, onClose }) => {
</> </>
)} )}
{titulacoes.length === 0 && idiomas.length === 0 && orientacoes.length === 0 && ( {titulacoes.length === 0 && idiomas.length === 0 && orientacoes.length === 0 &&
!item.docencias?.length && !item.projetos?.length && !item.premiacoes_detalhadas?.length && (
<p className="modal-empty">Dados detalhados não disponíveis no ATUACAPES.</p> <p className="modal-empty">Dados detalhados não disponíveis no ATUACAPES.</p>
)} )}
</div> </div>
@@ -1953,27 +2393,6 @@ const ConsultorCard = memo(({ consultor, highlight, selecionado, onToggleSelecio
<span className="lattes-external"></span> <span className="lattes-external"></span>
</a> </a>
<div className="titulacoes-resumo"> <div className="titulacoes-resumo">
{consultor.lattes.titulacoes
?.sort((a, b) => {
const ordem = { 'Pos-Doutorado': 1, 'Doutorado': 2, 'Mestrado': 3, 'Graduacao': 4 };
return (ordem[a.grau] || 99) - (ordem[b.grau] || 99);
})
.map((t, idx) => (
<span
key={idx}
className="titulacao-badge titulacao-clicavel"
onClick={(e) => {
e.stopPropagation();
setItemDetalhe({
item: t,
tipo: 'titulacao'
});
}}
title={`${t.grau}${t.area ? ` em ${t.area}` : ''}${t.ies_nome ? ` - ${t.ies_nome}` : ''}${t.pais ? ` (${t.pais})` : ''}`}
>
{t.grau}{t.ies_sigla ? ` (${t.ies_sigla})` : ''}{t.ano ? ` - ${t.ano}` : ''}
</span>
))}
<span <span
className="titulacao-badge titulacao-clicavel lattes-producoes" className="titulacao-badge titulacao-clicavel lattes-producoes"
title="Ver producoes do Lattes" title="Ver producoes do Lattes"
@@ -1998,6 +2417,27 @@ const ConsultorCard = memo(({ consultor, highlight, selecionado, onToggleSelecio
> >
📚 Producoes 📚 Producoes
</span> </span>
{consultor.lattes.titulacoes
?.sort((a, b) => {
const ordem = { 'Pos-Doutorado': 1, 'Doutorado': 2, 'Mestrado': 3, 'Graduacao': 4, 'Bacharelado': 5 };
return (ordem[a.grau] || 99) - (ordem[b.grau] || 99);
})
.map((t, idx) => (
<span
key={idx}
className="titulacao-badge titulacao-clicavel"
onClick={(e) => {
e.stopPropagation();
setItemDetalhe({
item: t,
tipo: 'titulacao'
});
}}
title={`Clique para detalhes: ${t.grau}${t.area ? ` em ${t.area}` : ''}${t.programa ? ` (${t.programa})` : ''}${t.ies_nome ? ` - ${t.ies_nome}` : ''}`}
>
{t.grau}{t.ies_sigla ? ` (${t.ies_sigla})` : ''}{t.ano ? ` - ${t.ano}` : ''}
</span>
))}
</div> </div>
</div> </div>
</div> </div>