fix: resolver problemas identificados no code review
Correções de segurança: - SQL Injection: usar prepared statements em ranking_repository.py - Validação de entrada para parâmetros page/size Correções de bugs: - Bônus de continuidade: 15→20 pts para 8+ anos (conforme especificação) - Memory leak: limpar _consultores após processamento do ranking Melhorias de robustez: - Substituir bare except por exceções específicas - Threading.Lock para padrão singleton thread-safe - Pool Oracle com configuração otimizada (timeout/getmode) - ES client com timeouts diferenciados e verificação is_closed - Logging para tipos de coordenação desconhecidos Correções frontend: - Polling com timeout máximo de 5 minutos - useEffect cleanup para setTimeout - React.memo e useMemo para otimização de performance
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import React, { useState, useRef, useEffect, useMemo, memo } from 'react';
|
||||
import './ConsultorCard.css';
|
||||
|
||||
const SELOS = {
|
||||
@@ -123,7 +123,7 @@ const FORMULAS = {
|
||||
},
|
||||
bloco_c: {
|
||||
titulo: 'Consultoria',
|
||||
descricao: 'CONS_ATIVO=150 | CONS_HIST=100 | CONS_FALECIDO=100\nTempo: 5 pts/ano (max 50)\nContinuidade 8a+=+20 (escalonado)\nRetorno (reativação): +15 (uma vez)',
|
||||
descricao: 'CONS_ATIVO=150 | CONS_HIST=100 | CONS_FALECIDO=100\nTempo: 5 pts/ano (max 50)\nContinuidade: 3a=+5, 5a=+10, 8a+=+20 (escalonado)\nRetorno (reativação): +15 (uma vez)',
|
||||
},
|
||||
bloco_d: {
|
||||
titulo: 'Premiacoes/Avaliacoes',
|
||||
@@ -183,15 +183,16 @@ const ScoreItemWithTooltip = ({ value, label, formula, style }) => (
|
||||
</div>
|
||||
);
|
||||
|
||||
const ConsultorCard = ({ consultor, highlight, selecionado, onToggleSelecionado }) => {
|
||||
const ConsultorCard = memo(({ consultor, highlight, selecionado, onToggleSelecionado }) => {
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
const cardRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (highlight && cardRef.current) {
|
||||
setTimeout(() => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
cardRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}, 100);
|
||||
return () => clearTimeout(timeoutId);
|
||||
}
|
||||
}, [highlight]);
|
||||
|
||||
@@ -219,7 +220,7 @@ const ConsultorCard = ({ consultor, highlight, selecionado, onToggleSelecionado
|
||||
const blocoD = pontuacao?.bloco_d || { total: consultor.bloco_d || 0 };
|
||||
const pontuacaoTotal = (blocoA.total || 0) + (blocoB.total || 0) + (blocoC.total || 0) + (blocoD.total || 0);
|
||||
|
||||
const selos = gerarSelos(consultor);
|
||||
const selos = useMemo(() => gerarSelos(consultor), [consultor]);
|
||||
|
||||
return (
|
||||
<div ref={cardRef} className={`ranking-card ${expanded ? 'expanded' : ''} ${highlight ? 'highlight' : ''} ${selecionado ? 'selecionado' : ''}`} onClick={() => setExpanded(!expanded)}>
|
||||
@@ -421,9 +422,11 @@ const ConsultorCard = ({ consultor, highlight, selecionado, onToggleSelecionado
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
const BlocoDetalhes = ({ titulo, bloco, cor }) => (
|
||||
ConsultorCard.displayName = 'ConsultorCard';
|
||||
|
||||
const BlocoDetalhes = memo(({ titulo, bloco, cor }) => (
|
||||
<div className="detail-section">
|
||||
<h4 style={{ color: cor }}>{titulo}</h4>
|
||||
<div className="score-breakdown">
|
||||
@@ -468,6 +471,8 @@ const BlocoDetalhes = ({ titulo, bloco, cor }) => (
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
));
|
||||
|
||||
BlocoDetalhes.displayName = 'BlocoDetalhes';
|
||||
|
||||
export default ConsultorCard;
|
||||
|
||||
Reference in New Issue
Block a user