feat: adicionada a coluna de totalizador por período

This commit is contained in:
Alessandro Gonçaalves 2025-12-10 09:00:06 -03:00
parent 021de27ab9
commit 5ab2e45966
1 changed files with 127 additions and 60 deletions

View File

@ -102,42 +102,97 @@ const TableRow = memo(({
</td> </td>
{/* Colunas de valores por mês e por filial - cada filial tem suas próprias colunas */} {/* Colunas de valores por mês e por filial - cada filial tem suas próprias colunas */}
{mesesDisponiveis.map((mes) => {mesesDisponiveis.map((mes) => {
((filtrosAplicados && filiaisSelecionadas.length > 0) ? filiaisSelecionadas : (opcoesFiliais.length > 0 ? opcoesFiliais : [''])).map((filial: string) => { const filiaisParaMes = (filtrosAplicados && filiaisSelecionadas.length > 0)
// Só exibir se a filial estiver selecionada ou se não houver filtros aplicados ? filiaisSelecionadas
if (filtrosAplicados && filiaisSelecionadas.length > 0 && !filiaisSelecionadas.includes(filial)) { : (opcoesFiliais.length > 0 ? opcoesFiliais : ['']);
return null;
} return (
return ( <React.Fragment key={mes}>
<React.Fragment key={`${mes}-${filial || 'default'}`}> {/* Colunas de filiais para este mês */}
<td {filiaisParaMes.map((filial: string) => {
className="px-2 py-1 text-right font-semibold cursor-pointer hover:bg-blue-50/50 transition-colors duration-200 whitespace-nowrap overflow-hidden w-[120px] min-w-[120px]" // Só exibir se a filial estiver selecionada ou se não houver filtros aplicados
onClick={() => handleRowClick(row, mes, filial)} if (filtrosAplicados && filiaisSelecionadas.length > 0 && !filiaisSelecionadas.includes(filial)) {
title={ return null;
filial && row.valoresPorMesPorFilial?.[mes]?.[filial] !== undefined
? formatCurrency(row.valoresPorMesPorFilial[mes][filial])
: row.valoresPorMes?.[mes] !== undefined
? formatCurrency(row.valoresPorMes[mes])
: "-"
} }
return (
<React.Fragment key={`${mes}-${filial || 'default'}`}>
<td
className="px-2 py-1 text-right font-semibold cursor-pointer hover:bg-blue-50/50 transition-colors duration-200 whitespace-nowrap overflow-hidden w-[120px] min-w-[120px]"
onClick={() => handleRowClick(row, mes, filial)}
title={
filial && row.valoresPorMesPorFilial?.[mes]?.[filial] !== undefined
? formatCurrency(row.valoresPorMesPorFilial[mes][filial])
: row.valoresPorMes?.[mes] !== undefined
? formatCurrency(row.valoresPorMes[mes])
: "-"
}
>
{filial && row.valoresPorMesPorFilial?.[mes]?.[filial] !== undefined && row.valoresPorMesPorFilial[mes][filial] !== 0 ? (
(() => {
const valor = row.valoresPorMesPorFilial[mes][filial];
const { formatted, isNegative } = formatCurrencyWithColor(valor);
return (
<span
className={
isNegative
? "text-red-600 font-bold"
: "text-gray-900"
}
>
{formatted}
</span>
);
})()
) : !filial && row.valoresPorMes?.[mes] !== undefined ? (
(() => {
const { formatted, isNegative } = formatCurrencyWithColor(row.valoresPorMes[mes]);
return (
<span
className={
isNegative
? "text-red-600 font-bold"
: "text-gray-900"
}
>
{formatted}
</span>
);
})()
) : (
<span className="text-gray-400">-</span>
)}
</td>
<td
className="px-2 py-1 text-center font-medium cursor-pointer hover:bg-blue-50/50 transition-colors duration-200 whitespace-nowrap overflow-hidden w-[100px] min-w-[100px]"
onClick={() => handleRowClick(row, mes, filial)}
title={
filial && row.percentuaisPorMesPorFilial?.[mes]?.[filial] !== undefined
? `${row.percentuaisPorMesPorFilial[mes][filial].toFixed(1)}%`
: row.percentuaisPorMes?.[mes] !== undefined
? `${row.percentuaisPorMes[mes].toFixed(1)}%`
: "-"
}
>
{filial && row.percentuaisPorMesPorFilial?.[mes]?.[filial] !== undefined && row.percentuaisPorMesPorFilial[mes][filial] !== 0 ? (
`${row.percentuaisPorMesPorFilial[mes][filial].toFixed(1)}%`
) : !filial && row.percentuaisPorMes?.[mes] !== undefined ? (
`${row.percentuaisPorMes[mes].toFixed(1)}%`
) : (
<span className="text-gray-400">-</span>
)}
</td>
</React.Fragment>
);
})}
{/* Colunas de totalizador para este mês */}
<td
className="px-2 py-1 text-right font-bold cursor-pointer hover:bg-green-50/50 transition-colors duration-200 whitespace-nowrap overflow-hidden w-[120px] min-w-[120px] bg-green-50/30"
onClick={() => handleRowClick(row, mes)}
title={row.valoresPorMes?.[mes] !== undefined ? formatCurrency(row.valoresPorMes[mes]) : "-"}
> >
{filial && row.valoresPorMesPorFilial?.[mes]?.[filial] !== undefined && row.valoresPorMesPorFilial[mes][filial] !== 0 ? ( {row.valoresPorMes?.[mes] !== undefined ? (
(() => {
const valor = row.valoresPorMesPorFilial[mes][filial];
const { formatted, isNegative } = formatCurrencyWithColor(valor);
return (
<span
className={
isNegative
? "text-red-600 font-bold"
: "text-gray-900"
}
>
{formatted}
</span>
);
})()
) : !filial && row.valoresPorMes?.[mes] !== undefined ? (
(() => { (() => {
const { formatted, isNegative } = formatCurrencyWithColor(row.valoresPorMes[mes]); const { formatted, isNegative } = formatCurrencyWithColor(row.valoresPorMes[mes]);
return ( return (
@ -145,7 +200,7 @@ const TableRow = memo(({
className={ className={
isNegative isNegative
? "text-red-600 font-bold" ? "text-red-600 font-bold"
: "text-gray-900" : "text-green-700 font-bold"
} }
> >
{formatted} {formatted}
@ -157,28 +212,21 @@ const TableRow = memo(({
)} )}
</td> </td>
<td <td
className="px-2 py-1 text-center font-medium cursor-pointer hover:bg-blue-50/50 transition-colors duration-200 whitespace-nowrap overflow-hidden w-[100px] min-w-[100px]" className="px-2 py-1 text-center font-bold cursor-pointer hover:bg-green-50/50 transition-colors duration-200 whitespace-nowrap overflow-hidden w-[100px] min-w-[100px] bg-green-50/30"
onClick={() => handleRowClick(row, mes, filial)} onClick={() => handleRowClick(row, mes)}
title={ title={
filial && row.percentuaisPorMesPorFilial?.[mes]?.[filial] !== undefined row.percentuaisPorMes?.[mes] !== undefined
? `${row.percentuaisPorMesPorFilial[mes][filial].toFixed(1)}%`
: row.percentuaisPorMes?.[mes] !== undefined
? `${row.percentuaisPorMes[mes].toFixed(1)}%` ? `${row.percentuaisPorMes[mes].toFixed(1)}%`
: "-" : "-"
} }
> >
{filial && row.percentuaisPorMesPorFilial?.[mes]?.[filial] !== undefined && row.percentuaisPorMesPorFilial[mes][filial] !== 0 ? ( {row.percentuaisPorMes?.[mes] !== undefined
`${row.percentuaisPorMesPorFilial[mes][filial].toFixed(1)}%` ? `${row.percentuaisPorMes[mes].toFixed(1)}%`
) : !filial && row.percentuaisPorMes?.[mes] !== undefined ? ( : <span className="text-gray-400">-</span>}
`${row.percentuaisPorMes[mes].toFixed(1)}%`
) : (
<span className="text-gray-400">-</span>
)}
</td> </td>
</React.Fragment> </React.Fragment>
); );
}) })}
)}
{/* Coluna Total */} {/* Coluna Total */}
<td <td
@ -1431,20 +1479,39 @@ export default function Teste() {
<th className="px-4 py-2 text-left text-xs font-semibold text-gray-700 uppercase tracking-wide w-[300px] min-w-[300px] bg-gradient-to-r from-blue-50 to-indigo-50 sticky left-0 z-20 shadow-[2px_0_4px_rgba(0,0,0,0.1)]"> <th className="px-4 py-2 text-left text-xs font-semibold text-gray-700 uppercase tracking-wide w-[300px] min-w-[300px] bg-gradient-to-r from-blue-50 to-indigo-50 sticky left-0 z-20 shadow-[2px_0_4px_rgba(0,0,0,0.1)]">
Descrição Descrição
</th> </th>
{mesesDisponiveis.map((mes) => {mesesDisponiveis.map((mes) => {
((filtrosAplicados && filiaisSelecionadas.length > 0) ? filiaisSelecionadas : (opcoesFiliais.length > 0 ? opcoesFiliais : [''])).map((filial: string) => ( const filiaisParaMes = (filtrosAplicados && filiaisSelecionadas.length > 0)
<React.Fragment key={`${mes}-${filial || 'default'}`}> ? filiaisSelecionadas
<th className="px-2 py-2 text-right text-xs font-semibold text-gray-700 uppercase tracking-wide w-[120px] min-w-[120px] bg-gradient-to-r from-blue-50 to-indigo-50"> : (opcoesFiliais.length > 0 ? opcoesFiliais : ['']);
{mes}{filial && <><br/>
<span className="text-[10px] font-normal text-gray-600">Filial - {filial}</span></>} return (
<React.Fragment key={mes}>
{/* Cabeçalhos de filiais para este mês */}
{filiaisParaMes.map((filial: string) => (
<React.Fragment key={`${mes}-${filial || 'default'}`}>
<th className="px-2 py-2 text-right text-xs font-semibold text-gray-700 uppercase tracking-wide w-[120px] min-w-[120px] bg-gradient-to-r from-blue-50 to-indigo-50">
{mes}{filial && <><br/>
<span className="text-[10px] font-normal text-gray-600">Filial - {filial}</span></>}
</th>
<th className="px-2 py-2 text-center text-xs font-semibold text-gray-500 uppercase tracking-wide w-[100px] min-w-[100px] bg-gradient-to-r from-blue-50 to-indigo-50">
%{filial && <><br/>
<span className="text-[10px] font-normal text-gray-600">Filial - {filial}</span></>}
</th>
</React.Fragment>
))}
{/* Cabeçalhos de totalizador para este mês */}
<th className="px-2 py-2 text-right text-xs font-bold text-green-700 uppercase tracking-wide w-[120px] min-w-[120px] bg-gradient-to-r from-green-50 to-emerald-50">
{mes}<br/>
<span className="text-[10px] font-normal text-green-600">Total</span>
</th> </th>
<th className="px-2 py-2 text-center text-xs font-semibold text-gray-500 uppercase tracking-wide w-[100px] min-w-[100px] bg-gradient-to-r from-blue-50 to-indigo-50"> <th className="px-2 py-2 text-center text-xs font-bold text-green-700 uppercase tracking-wide w-[100px] min-w-[100px] bg-gradient-to-r from-green-50 to-emerald-50">
%{filial && <><br/> %<br/>
<span className="text-[10px] font-normal text-gray-600">Filial - {filial}</span></>} <span className="text-[10px] font-normal text-green-600">Total</span>
</th> </th>
</React.Fragment> </React.Fragment>
)) );
)} })}
<th className="px-4 py-2 text-right text-xs font-semibold text-gray-700 uppercase tracking-wide w-[120px] min-w-[120px] bg-gradient-to-r from-blue-50 to-indigo-50"> <th className="px-4 py-2 text-right text-xs font-semibold text-gray-700 uppercase tracking-wide w-[120px] min-w-[120px] bg-gradient-to-r from-blue-50 to-indigo-50">
Total Total
</th> </th>