diff --git a/src/app/dre-filial/teste.tsx b/src/app/dre-filial/teste.tsx index acbfa33..0c80d28 100644 --- a/src/app/dre-filial/teste.tsx +++ b/src/app/dre-filial/teste.tsx @@ -66,6 +66,8 @@ const TableRow = memo(({ renderCellContent, mesesDisponiveis, opcoesFiliais, + filiaisSelecionadas, + filtrosAplicados, formatCurrency, formatCurrencyWithColor, getFixedCellBackground @@ -78,6 +80,8 @@ const TableRow = memo(({ renderCellContent: (row: HierarchicalRow) => React.ReactNode; mesesDisponiveis: string[]; opcoesFiliais: string[]; + filiaisSelecionadas: string[]; + filtrosAplicados: boolean; formatCurrency: (value: number) => string; formatCurrencyWithColor: (value: number) => { formatted: string; isNegative: boolean }; getFixedCellBackground: (row: HierarchicalRow) => string; @@ -99,7 +103,12 @@ const TableRow = memo(({ {/* Colunas de valores por mês e por filial - cada filial tem suas próprias colunas */} {mesesDisponiveis.map((mes) => - (opcoesFiliais.length > 0 ? opcoesFiliais : ['']).map((filial: string) => ( + ((filtrosAplicados && filiaisSelecionadas.length > 0) ? filiaisSelecionadas : (opcoesFiliais.length > 0 ? opcoesFiliais : [''])).map((filial: string) => { + // Só exibir se a filial estiver selecionada ou se não houver filtros aplicados + if (filtrosAplicados && filiaisSelecionadas.length > 0 && !filiaisSelecionadas.includes(filial)) { + return null; + } + return ( - )) + ); + }) )} {/* Coluna Total */} @@ -339,23 +349,23 @@ export default function Teste() { } }; - const formatCurrency = (value: string | number) => { + const formatCurrency = React.useCallback((value: string | number) => { const numValue = typeof value === "string" ? parseFloat(value) : value; return numValue.toLocaleString("pt-BR", { style: "currency", currency: "BRL", }); - }; + }, []); - const formatCurrencyWithColor = (value: string | number) => { + const formatCurrencyWithColor = React.useCallback((value: string | number) => { const numValue = typeof value === "string" ? parseFloat(value) : value; const formatted = formatCurrency(value); const isNegative = numValue < 0; return { formatted, isNegative }; - }; + }, [formatCurrency]); // Função para lidar com clique nas linhas - const handleRowClick = (row: HierarchicalRow, mesSelecionado?: string) => { + const handleRowClick = React.useCallback((row: HierarchicalRow, mesSelecionado?: string) => { console.log('🖱️ Clique na linha:', row); console.log('📅 Mês selecionado:', mesSelecionado); @@ -431,7 +441,7 @@ export default function Teste() { console.log('🎯 Novos filtros para analítico:', novosFiltros); setAnaliticoFiltros(novosFiltros); - }; + }, [data]); const toggleGrupo = useCallback((codigoGrupo: string) => { setExpandedGrupos(prev => { @@ -464,7 +474,7 @@ export default function Teste() { }; // Função auxiliar para calcular valores por mês - const calcularValoresPorMes = (items: DREItem[]): Record => { + const calcularValoresPorMes = React.useCallback((items: DREItem[]): Record => { const valoresPorMes: Record = {}; mesesDisponiveis.forEach(mes => { @@ -479,16 +489,18 @@ export default function Teste() { }); return valoresPorMes; - }; + }, [mesesDisponiveis]); // Função auxiliar para calcular valores por mês e por filial - const calcularValoresPorMesPorFilial = (items: DREItem[]): Record> => { + const calcularValoresPorMesPorFilial = React.useCallback((items: DREItem[]): Record> => { const valoresPorMesPorFilial: Record> = {}; - // Extrair filiais únicas dos items se opcoesFiliais ainda não estiver disponível - const filiaisDisponiveis = opcoesFiliais.length > 0 - ? opcoesFiliais - : [...new Set(items.map(item => item.filial || item.codfilial).filter(Boolean))] as string[]; + // Usar filiais selecionadas se houver filtros aplicados, senão usar todas as opções disponíveis + const filiaisDisponiveis = (filtrosAplicados && filiaisSelecionadas.length > 0) + ? filiaisSelecionadas + : (opcoesFiliais.length > 0 + ? opcoesFiliais + : [...new Set(items.map(item => item.filial || item.codfilial).filter(Boolean))] as string[]); mesesDisponiveis.forEach(mes => { valoresPorMesPorFilial[mes] = {}; @@ -500,7 +512,7 @@ export default function Teste() { items.forEach((item) => { const anoMes = item.data_competencia; const filial = item.filial || item.codfilial || ""; - if (anoMes && valoresPorMesPorFilial[anoMes] && filial) { + if (anoMes && valoresPorMesPorFilial[anoMes] && filial && filiaisDisponiveis.includes(filial)) { if (!valoresPorMesPorFilial[anoMes][filial]) { valoresPorMesPorFilial[anoMes][filial] = 0; } @@ -509,10 +521,49 @@ export default function Teste() { }); return valoresPorMesPorFilial; - }; + }, [mesesDisponiveis, opcoesFiliais, filtrosAplicados, filiaisSelecionadas]); + + // Memoizar valores do grupo 01 por mês para evitar recálculos repetidos + const valoresGrupo01PorMesMemo = React.useMemo(() => { + const valores: Record = {}; + mesesDisponiveis.forEach(mes => { + valores[mes] = data + .filter(item => { + const codgrupo = item.codgrupo || item.codigo_grupo || ""; + return codgrupo === "01" && item.data_competencia === mes; + }) + .reduce((sum, item) => sum + parseFloat(item.valor), 0); + }); + return valores; + }, [data, mesesDisponiveis]); + + // Memoizar valores do grupo 01 por mês e por filial + const valoresGrupo01PorMesPorFilialMemo = React.useMemo(() => { + const valores: Record> = {}; + // Usar filiais selecionadas se houver filtros aplicados, senão usar todas as opções disponíveis + const filiaisDisponiveis = (filtrosAplicados && filiaisSelecionadas.length > 0) + ? filiaisSelecionadas + : (opcoesFiliais.length > 0 + ? opcoesFiliais + : [...new Set(data.map(item => item.filial || item.codfilial).filter(Boolean))] as string[]); + + mesesDisponiveis.forEach(mes => { + valores[mes] = {}; + filiaisDisponiveis.forEach(filial => { + valores[mes][filial] = data + .filter(item => { + const codgrupo = item.codgrupo || item.codigo_grupo || ""; + const itemFilial = item.filial || item.codfilial || ""; + return codgrupo === "01" && item.data_competencia === mes && itemFilial === filial; + }) + .reduce((sum, item) => sum + parseFloat(item.valor), 0); + }); + }); + return valores; + }, [data, mesesDisponiveis, opcoesFiliais, filtrosAplicados, filiaisSelecionadas]); // Função para calcular percentuais baseado no CODGRUPO 01 (FATURAMENTO LÍQUIDO) - const calcularPercentuaisPorMes = ( + const calcularPercentuaisPorMes = React.useCallback(( valoresPorMes: Record, codigoGrupo?: string ): Record => { @@ -525,22 +576,11 @@ export default function Teste() { }); return percentuais; } - - // Calcular valores do grupo 01 por mês (base para cálculo) - const valoresGrupo01PorMes: Record = {}; - mesesDisponiveis.forEach(mes => { - valoresGrupo01PorMes[mes] = data - .filter(item => { - const codgrupo = item.codgrupo || item.codigo_grupo || ""; - return codgrupo === "01" && item.data_competencia === mes; - }) - .reduce((sum, item) => sum + parseFloat(item.valor), 0); - }); - // Calcular percentuais baseado no grupo 01 + // Usar valores memoizados do grupo 01 Object.keys(valoresPorMes).forEach((mes) => { const valorAtual = valoresPorMes[mes]; - const valorGrupo01 = valoresGrupo01PorMes[mes] || 0; + const valorGrupo01 = valoresGrupo01PorMesMemo[mes] || 0; if (valorGrupo01 !== 0) { percentuais[mes] = (valorAtual / valorGrupo01) * 100; @@ -550,19 +590,21 @@ export default function Teste() { }); return percentuais; - }; + }, [mesesDisponiveis, valoresGrupo01PorMesMemo]); // Função para calcular percentuais por mês e por filial baseado no CODGRUPO 01 - const calcularPercentuaisPorMesPorFilial = ( + const calcularPercentuaisPorMesPorFilial = React.useCallback(( valoresPorMesPorFilial: Record>, codigoGrupo?: string ): Record> => { const percentuaisPorMesPorFilial: Record> = {}; - // Extrair filiais únicas dos valores se opcoesFiliais ainda não estiver disponível - const filiaisDisponiveis = opcoesFiliais.length > 0 - ? opcoesFiliais - : Object.keys(valoresPorMesPorFilial[mesesDisponiveis[0] || ""] || {}); + // Usar filiais selecionadas se houver filtros aplicados, senão usar todas as opções disponíveis + const filiaisDisponiveis = (filtrosAplicados && filiaisSelecionadas.length > 0) + ? filiaisSelecionadas + : (opcoesFiliais.length > 0 + ? opcoesFiliais + : Object.keys(valoresPorMesPorFilial[mesesDisponiveis[0] || ""] || {})); // Se for CODGRUPO 01, sempre retornar 100% para todas as filiais if (codigoGrupo === "01") { @@ -574,28 +616,13 @@ export default function Teste() { }); return percentuaisPorMesPorFilial; } - - // Calcular valores do grupo 01 por mês e por filial (base para cálculo) - const valoresGrupo01PorMesPorFilial: Record> = {}; - mesesDisponiveis.forEach(mes => { - valoresGrupo01PorMesPorFilial[mes] = {}; - filiaisDisponiveis.forEach(filial => { - valoresGrupo01PorMesPorFilial[mes][filial] = data - .filter(item => { - const codgrupo = item.codgrupo || item.codigo_grupo || ""; - const itemFilial = item.filial || item.codfilial || ""; - return codgrupo === "01" && item.data_competencia === mes && itemFilial === filial; - }) - .reduce((sum, item) => sum + parseFloat(item.valor), 0); - }); - }); - // Calcular percentuais baseado no grupo 01 por filial + // Usar valores memoizados do grupo 01 mesesDisponiveis.forEach(mes => { percentuaisPorMesPorFilial[mes] = {}; filiaisDisponiveis.forEach(filial => { const valorAtual = valoresPorMesPorFilial[mes]?.[filial] || 0; - const valorGrupo01 = valoresGrupo01PorMesPorFilial[mes]?.[filial] || 0; + const valorGrupo01 = valoresGrupo01PorMesPorFilialMemo[mes]?.[filial] || 0; if (valorGrupo01 !== 0) { percentuaisPorMesPorFilial[mes][filial] = (valorAtual / valorGrupo01) * 100; @@ -606,31 +633,34 @@ export default function Teste() { }); return percentuaisPorMesPorFilial; - }; + }, [mesesDisponiveis, opcoesFiliais, valoresGrupo01PorMesPorFilialMemo, filtrosAplicados, filiaisSelecionadas]); - // Função para calcular percentual do total baseado no CODGRUPO 01 - const calcularPercentualTotal = (total: number, codigoGrupo?: string): number => { - // Se for CODGRUPO 01, sempre retornar 100% - if (codigoGrupo === "01") { - return 100; - } - - // Calcular total do grupo 01 (base para cálculo) - const totalGrupo01 = data + // Memoizar total do grupo 01 + const totalGrupo01Memo = React.useMemo(() => { + return data .filter(item => { const codgrupo = item.codgrupo || item.codigo_grupo || ""; return codgrupo === "01"; }) .reduce((sum, item) => sum + parseFloat(item.valor), 0); + }, [data]); + + // Função para calcular percentual do total baseado no CODGRUPO 01 + const calcularPercentualTotal = React.useCallback((total: number, codigoGrupo?: string): number => { + // Se for CODGRUPO 01, sempre retornar 100% + if (codigoGrupo === "01") { + return 100; + } - if (totalGrupo01 !== 0) { - return (total / totalGrupo01) * 100; + // Usar total memoizado do grupo 01 + if (totalGrupo01Memo !== 0) { + return (total / totalGrupo01Memo) * 100; } else { return 0; } - }; + }, [totalGrupo01Memo]); - const buildHierarchicalData = (): HierarchicalRow[] => { + const buildHierarchicalData = React.useCallback((): HierarchicalRow[] => { const rows: HierarchicalRow[] = []; // Hierarquia simplificada: [grupo, conta] @@ -790,9 +820,9 @@ export default function Teste() { }); return rows; - }; + }, [data, mesesDisponiveis, expandedGrupos, opcoesFiliais, filtrosAplicados, filiaisSelecionadas, calcularValoresPorMes, calcularValoresPorMesPorFilial, calcularPercentuaisPorMes, calcularPercentuaisPorMesPorFilial, calcularPercentualTotal]); - const getRowStyle = (row: HierarchicalRow) => { + const getRowStyle = React.useCallback((row: HierarchicalRow) => { const baseStyle = "transition-all duration-200 hover:bg-gradient-to-r hover:from-blue-50/30 hover:to-indigo-50/30"; @@ -816,9 +846,9 @@ export default function Teste() { default: return style; } - }; + }, [linhaSelecionada]); - const getFixedCellBackground = (row: HierarchicalRow): string => { + const getFixedCellBackground = React.useCallback((row: HierarchicalRow): string => { const linhaId = `${row.type}-${row.codigo_grupo || ""}-${row.codigo_conta || ""}`; const isSelected = linhaSelecionada === linhaId; @@ -836,13 +866,13 @@ export default function Teste() { default: return "bg-white"; } - }; + }, [linhaSelecionada]); - const getIndentStyle = (level: number) => { + const getIndentStyle = React.useCallback((level: number) => { return { paddingLeft: `${level * 20}px` }; - }; + }, []); - const renderCellContent = (row: HierarchicalRow) => { + const renderCellContent = React.useCallback((row: HierarchicalRow) => { switch (row.type) { case "grupo": return ( @@ -917,7 +947,7 @@ export default function Teste() { default: return null; } - }; + }, [toggleGrupo, handleRowClick]); const toggleExpandAll = () => { if (isAllExpanded) { @@ -1109,7 +1139,13 @@ export default function Teste() { console.log('✅ Arquivo XLSX completo exportado:', nomeArquivo); }; - const hierarchicalData = buildHierarchicalData(); + // Memoizar dados hierárquicos para evitar recálculos desnecessários + const hierarchicalData = React.useMemo(() => { + if (!data.length || !mesesDisponiveis.length) { + return []; + } + return buildHierarchicalData(); + }, [buildHierarchicalData]); return (
@@ -1370,7 +1406,7 @@ export default function Teste() { Descrição {mesesDisponiveis.map((mes) => - (opcoesFiliais.length > 0 ? opcoesFiliais : ['']).map((filial: string) => ( + ((filtrosAplicados && filiaisSelecionadas.length > 0) ? filiaisSelecionadas : (opcoesFiliais.length > 0 ? opcoesFiliais : [''])).map((filial: string) => ( {mes}{filial && <>
@@ -1408,6 +1444,8 @@ export default function Teste() { renderCellContent={renderCellContent} mesesDisponiveis={mesesDisponiveis} opcoesFiliais={opcoesFiliais} + filiaisSelecionadas={filiaisSelecionadas} + filtrosAplicados={filtrosAplicados} formatCurrency={formatCurrency} formatCurrencyWithColor={formatCurrencyWithColor} getFixedCellBackground={getFixedCellBackground}