mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 13:15:24 +02:00
feat: add YoY growth percentages to filtered totals summary
This commit is contained in:
+57
-14
@@ -637,7 +637,7 @@ const DataGrid: React.FC<DataGridProps> = ({ data }) => {
|
|||||||
<svg className="w-5 h-5 text-indigo-400" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z" /></svg>
|
<svg className="w-5 h-5 text-indigo-400" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z" /></svg>
|
||||||
<span className="text-xs font-bold text-indigo-300 uppercase tracking-wide">Filtered Totals:</span>
|
<span className="text-xs font-bold text-indigo-300 uppercase tracking-wide">Filtered Totals:</span>
|
||||||
</div>
|
</div>
|
||||||
{years.map((year) => {
|
{years.map((year, index) => {
|
||||||
const yearTotals = processedRows.reduce(
|
const yearTotals = processedRows.reduce(
|
||||||
(acc, row) => {
|
(acc, row) => {
|
||||||
const data = row.totalsByYear[year];
|
const data = row.totalsByYear[year];
|
||||||
@@ -649,21 +649,64 @@ const DataGrid: React.FC<DataGridProps> = ({ data }) => {
|
|||||||
},
|
},
|
||||||
{ sellOut: 0, units: 0 }
|
{ sellOut: 0, units: 0 }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Calculate YoY growth if previous year exists
|
||||||
|
const prevYear = years[index + 1];
|
||||||
|
let sellOutGrowth = null;
|
||||||
|
let unitsGrowth = null;
|
||||||
|
|
||||||
|
if (prevYear) {
|
||||||
|
const prevYearTotals = processedRows.reduce(
|
||||||
|
(acc, row) => {
|
||||||
|
const data = row.totalsByYear[prevYear];
|
||||||
|
if (data) {
|
||||||
|
acc.sellOut += data.sellOut;
|
||||||
|
acc.units += data.units;
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{ sellOut: 0, units: 0 }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (prevYearTotals.sellOut > 0) {
|
||||||
|
sellOutGrowth = ((yearTotals.sellOut - prevYearTotals.sellOut) / prevYearTotals.sellOut) * 100;
|
||||||
|
} else if (yearTotals.sellOut > 0) {
|
||||||
|
sellOutGrowth = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevYearTotals.units > 0) {
|
||||||
|
unitsGrowth = ((yearTotals.units - prevYearTotals.units) / prevYearTotals.units) * 100;
|
||||||
|
} else if (yearTotals.units > 0) {
|
||||||
|
unitsGrowth = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={year} className="flex items-center gap-4 px-4 py-1 bg-slate-900/50 border border-slate-700/50 rounded-lg">
|
<div key={year} className="flex items-center gap-4 px-4 py-2 bg-slate-900/50 border border-slate-700/50 rounded-lg">
|
||||||
<span className="text-xs font-bold text-slate-400">{year}</span>
|
<span className="text-xs font-bold text-slate-400">{year}</span>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<span className="text-xs text-slate-500">S.O:</span>
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-sm font-bold text-emerald-400">
|
<span className="text-xs text-slate-500">S.O:</span>
|
||||||
€{yearTotals.sellOut.toLocaleString(undefined, { maximumFractionDigits: 0 })}
|
<span className="text-sm font-bold text-emerald-400">
|
||||||
</span>
|
€{yearTotals.sellOut.toLocaleString(undefined, { maximumFractionDigits: 0 })}
|
||||||
</div>
|
</span>
|
||||||
<div className="h-3 w-px bg-slate-700"></div>
|
{sellOutGrowth !== null && (
|
||||||
<div className="flex items-center gap-1">
|
<span className={`text-xs font-bold ${sellOutGrowth >= 0 ? 'text-emerald-400' : 'text-red-400'}`}>
|
||||||
<span className="text-xs text-slate-500">Units:</span>
|
{sellOutGrowth >= 0 ? '↑' : '↓'} {Math.abs(sellOutGrowth).toFixed(1)}%
|
||||||
<span className="text-sm font-bold text-blue-400">
|
</span>
|
||||||
{yearTotals.units.toLocaleString()}
|
)}
|
||||||
</span>
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="text-xs text-slate-500">Units:</span>
|
||||||
|
<span className="text-sm font-bold text-blue-400">
|
||||||
|
{yearTotals.units.toLocaleString()}
|
||||||
|
</span>
|
||||||
|
{unitsGrowth !== null && (
|
||||||
|
<span className={`text-xs font-bold ${unitsGrowth >= 0 ? 'text-emerald-400' : 'text-red-400'}`}>
|
||||||
|
{unitsGrowth >= 0 ? '↑' : '↓'} {Math.abs(unitsGrowth).toFixed(1)}%
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user