mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 15:25:23 +02:00
fix: correct revenue metric mapping in Weekly Sales grid (pivot revenue vs ads cost)
This commit is contained in:
+256326
File diff suppressed because it is too large
Load Diff
+30
-26
@@ -207,6 +207,8 @@ const WeeklyRow: React.FC<{
|
|||||||
const prevVal = row.unitsByWeek[weeks[idx + 1]] || 0;
|
const prevVal = row.unitsByWeek[weeks[idx + 1]] || 0;
|
||||||
const spend = row.spendByWeek[week] || 0;
|
const spend = row.spendByWeek[week] || 0;
|
||||||
const prevSpend = row.spendByWeek[weeks[idx + 1]] || 0;
|
const prevSpend = row.spendByWeek[weeks[idx + 1]] || 0;
|
||||||
|
const revenue = row.revenueByWeek[week] || 0;
|
||||||
|
const prevRevenue = row.revenueByWeek[weeks[idx + 1]] || 0;
|
||||||
const gv = row.gvByWeek?.[week] || 0;
|
const gv = row.gvByWeek?.[week] || 0;
|
||||||
const prevGv = row.gvByWeek?.[weeks[idx + 1]] || 0;
|
const prevGv = row.gvByWeek?.[weeks[idx + 1]] || 0;
|
||||||
|
|
||||||
@@ -218,6 +220,7 @@ const WeeklyRow: React.FC<{
|
|||||||
const lastYearWeek = `${parseInt(year) - 1}-${weekNum}`;
|
const lastYearWeek = `${parseInt(year) - 1}-${weekNum}`;
|
||||||
const yoyUnits = row.unitsByWeek[lastYearWeek] || 0;
|
const yoyUnits = row.unitsByWeek[lastYearWeek] || 0;
|
||||||
const yoySpend = row.spendByWeek[lastYearWeek] || 0;
|
const yoySpend = row.spendByWeek[lastYearWeek] || 0;
|
||||||
|
const yoyRevenue = row.revenueByWeek[lastYearWeek] || 0;
|
||||||
const yoyGv = row.gvByWeek?.[lastYearWeek] || 0;
|
const yoyGv = row.gvByWeek?.[lastYearWeek] || 0;
|
||||||
|
|
||||||
|
|
||||||
@@ -244,9 +247,9 @@ const WeeklyRow: React.FC<{
|
|||||||
</MetricDetailTooltip>
|
</MetricDetailTooltip>
|
||||||
) : (
|
) : (
|
||||||
<MetricDetailTooltip
|
<MetricDetailTooltip
|
||||||
currentValue={spend}
|
currentValue={revenue}
|
||||||
previousValue={prevSpend}
|
previousValue={prevRevenue}
|
||||||
yoyValue={yoySpend}
|
yoyValue={yoyRevenue}
|
||||||
currentWeekLabel={`Week ${weekNum} (${year})`}
|
currentWeekLabel={`Week ${weekNum} (${year})`}
|
||||||
previousWeekLabel={`Week ${prevWeekNum} (${year})`}
|
previousWeekLabel={`Week ${prevWeekNum} (${year})`}
|
||||||
yoyWeekLabel={`Week ${weekNum} (${parseInt(year) - 1})`}
|
yoyWeekLabel={`Week ${weekNum} (${parseInt(year) - 1})`}
|
||||||
@@ -255,10 +258,10 @@ const WeeklyRow: React.FC<{
|
|||||||
formatValue={(v) => `€${v.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}`}
|
formatValue={(v) => `€${v.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}`}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<span className={`text-sm font-bold ${spend > 0 ? (sortConfig?.key === week && sortConfig.metric === 'spend' ? 'text-amber-400' : 'text-white') : 'text-slate-700'}`}>
|
<span className={`text-sm font-bold ${revenue > 0 ? (sortConfig?.key === week && sortConfig.metric === 'spend' ? 'text-amber-400' : 'text-white') : 'text-slate-700'}`}>
|
||||||
{spend > 0 ? `€${spend.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}` : '-'}
|
{revenue > 0 ? `€${revenue.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}` : '-'}
|
||||||
</span>
|
</span>
|
||||||
{spend > 0 && renderGrowth(spend, prevSpend)}
|
{revenue > 0 && renderGrowth(revenue, prevRevenue)}
|
||||||
</div>
|
</div>
|
||||||
</MetricDetailTooltip>
|
</MetricDetailTooltip>
|
||||||
)}
|
)}
|
||||||
@@ -266,23 +269,23 @@ const WeeklyRow: React.FC<{
|
|||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
{/* Secondary Metric (the one not selected) */}
|
{/* Secondary Metric (the one not selected) */}
|
||||||
{primaryMetric === 'units' ? (
|
{primaryMetric === 'units' ? (
|
||||||
spend > 0 && (
|
revenue > 0 && (
|
||||||
<MetricDetailTooltip
|
<MetricDetailTooltip
|
||||||
currentValue={spend}
|
currentValue={revenue}
|
||||||
previousValue={prevSpend}
|
previousValue={prevRevenue}
|
||||||
yoyValue={yoySpend}
|
yoyValue={yoyRevenue}
|
||||||
currentWeekLabel={`Week ${weekNum} (${year})`}
|
currentWeekLabel={`Week ${weekNum} (${year})`}
|
||||||
previousWeekLabel={`Week ${prevWeekNum} (${year})`}
|
previousWeekLabel={`Week ${prevWeekNum} (${year})`}
|
||||||
yoyWeekLabel={`Week ${weekNum} (${parseInt(year) - 1})`}
|
yoyWeekLabel={`Week ${weekNum} (${parseInt(year) - 1})`}
|
||||||
metricName="Spend"
|
metricName="Revenue"
|
||||||
metricColor="text-indigo-400"
|
metricColor="text-indigo-400/80"
|
||||||
formatValue={(v) => `€${v.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}`}
|
formatValue={(v) => `€${v.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}`}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1 text-[10px]">
|
||||||
<span className={`text-[11px] font-medium ${sortConfig?.key === week && sortConfig.metric === 'spend' ? 'text-amber-300' : 'text-indigo-400/80'}`}>
|
<span className={`font-medium ${sortConfig?.key === week && sortConfig.metric === 'spend' ? 'text-amber-300' : 'text-indigo-400/80'}`}>
|
||||||
€{spend.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}
|
€{revenue.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}
|
||||||
</span>
|
</span>
|
||||||
{renderGrowth(spend, prevSpend)}
|
{renderGrowth(revenue, prevRevenue)}
|
||||||
</div>
|
</div>
|
||||||
</MetricDetailTooltip>
|
</MetricDetailTooltip>
|
||||||
)
|
)
|
||||||
@@ -296,11 +299,11 @@ const WeeklyRow: React.FC<{
|
|||||||
previousWeekLabel={`Week ${prevWeekNum} (${year})`}
|
previousWeekLabel={`Week ${prevWeekNum} (${year})`}
|
||||||
yoyWeekLabel={`Week ${weekNum} (${parseInt(year) - 1})`}
|
yoyWeekLabel={`Week ${weekNum} (${parseInt(year) - 1})`}
|
||||||
metricName="Units"
|
metricName="Units"
|
||||||
metricColor="text-indigo-400"
|
metricColor="text-indigo-400/80"
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1 text-[10px]">
|
||||||
<span className={`text-[11px] font-medium ${sortConfig?.key === week && sortConfig.metric === 'units' ? 'text-amber-300' : 'text-indigo-400/80'}`}>
|
<span className={`font-medium ${sortConfig?.key === week && sortConfig.metric === 'units' ? 'text-indigo-300' : 'text-indigo-400/80'}`}>
|
||||||
{val.toLocaleString('de-DE')} Units
|
{val.toLocaleString('de-DE')}
|
||||||
</span>
|
</span>
|
||||||
{renderGrowth(val, prevVal)}
|
{renderGrowth(val, prevVal)}
|
||||||
</div>
|
</div>
|
||||||
@@ -427,12 +430,12 @@ const WeeklyGrid: React.FC<WeeklyGridProps & { top50Mode: 'eu' | 'uk' }> = ({
|
|||||||
|
|
||||||
// Calculate totals in a SINGLE PASS
|
// Calculate totals in a SINGLE PASS
|
||||||
const weekTotals = useMemo(() => {
|
const weekTotals = useMemo(() => {
|
||||||
const totals: { [weekKey: string]: { units: number, spend: number, gv: number } } = {};
|
const totals: { [weekKey: string]: { units: number, spend: number, revenue: number, gv: number } } = {};
|
||||||
const visibleWeeks = weeks;
|
const visibleWeeks = weeks;
|
||||||
|
|
||||||
// Initialize visible weeks
|
// Initialize visible weeks
|
||||||
for (let i = 0; i < visibleWeeks.length; i++) {
|
for (let i = 0; i < visibleWeeks.length; i++) {
|
||||||
totals[visibleWeeks[i]] = { units: 0, spend: 0, gv: 0 };
|
totals[visibleWeeks[i]] = { units: 0, spend: 0, revenue: 0, gv: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single pass through rows
|
// Single pass through rows
|
||||||
@@ -442,6 +445,7 @@ const WeeklyGrid: React.FC<WeeklyGridProps & { top50Mode: 'eu' | 'uk' }> = ({
|
|||||||
const w = visibleWeeks[j];
|
const w = visibleWeeks[j];
|
||||||
totals[w].units += (row.unitsByWeek[w] || 0);
|
totals[w].units += (row.unitsByWeek[w] || 0);
|
||||||
totals[w].spend += (row.spendByWeek[w] || 0);
|
totals[w].spend += (row.spendByWeek[w] || 0);
|
||||||
|
totals[w].revenue += (row.revenueByWeek[w] || 0);
|
||||||
totals[w].gv += (row.gvByWeek?.[w] || 0);
|
totals[w].gv += (row.gvByWeek?.[w] || 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -981,15 +985,15 @@ const WeeklyGrid: React.FC<WeeklyGridProps & { top50Mode: 'eu' | 'uk' }> = ({
|
|||||||
{renderGrowth(weekTotals[week]?.units || 0, weekTotals[weeks[idx + 1]]?.units || 0)}
|
{renderGrowth(weekTotals[week]?.units || 0, weekTotals[weeks[idx + 1]]?.units || 0)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-center gap-1 text-[10px] text-indigo-400 font-bold">
|
<div className="flex items-center justify-center gap-1 text-[10px] text-indigo-400 font-bold">
|
||||||
<span>€{(weekTotals[week]?.spend || 0).toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}</span>
|
<span>€{(weekTotals[week]?.revenue || 0).toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}</span>
|
||||||
{renderGrowth(weekTotals[week]?.spend || 0, weekTotals[weeks[idx + 1]]?.spend || 0)}
|
{renderGrowth(weekTotals[week]?.revenue || 0, weekTotals[weeks[idx + 1]]?.revenue || 0)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<span>€{(weekTotals[week]?.spend || 0).toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}</span>
|
<span>€{(weekTotals[week]?.revenue || 0).toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}</span>
|
||||||
{renderGrowth(weekTotals[week]?.spend || 0, weekTotals[weeks[idx + 1]]?.spend || 0)}
|
{renderGrowth(weekTotals[week]?.revenue || 0, weekTotals[weeks[idx + 1]]?.revenue || 0)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-center gap-1 text-[10px] text-indigo-400 font-bold">
|
<div className="flex items-center justify-center gap-1 text-[10px] text-indigo-400 font-bold">
|
||||||
<span>{(weekTotals[week]?.units || 0).toLocaleString('de-DE')} Units</span>
|
<span>{(weekTotals[week]?.units || 0).toLocaleString('de-DE')} Units</span>
|
||||||
|
|||||||
@@ -1642,7 +1642,8 @@ export interface WeeklyPivotRow {
|
|||||||
line: string;
|
line: string;
|
||||||
customer: string;
|
customer: string;
|
||||||
unitsByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW"
|
unitsByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW"
|
||||||
spendByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW"
|
spendByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW" (Ads Cost)
|
||||||
|
revenueByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW" (Sell-out)
|
||||||
gvByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW"
|
gvByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1691,6 +1692,7 @@ export const pivotWeeklySalesData = (data: CombinedKPIs[]): {
|
|||||||
customer: record.customer || record.marketplace || '',
|
customer: record.customer || record.marketplace || '',
|
||||||
unitsByWeek: {},
|
unitsByWeek: {},
|
||||||
spendByWeek: {},
|
spendByWeek: {},
|
||||||
|
revenueByWeek: {},
|
||||||
gvByWeek: {}
|
gvByWeek: {}
|
||||||
};
|
};
|
||||||
map.set(key, row);
|
map.set(key, row);
|
||||||
@@ -1698,6 +1700,7 @@ export const pivotWeeklySalesData = (data: CombinedKPIs[]): {
|
|||||||
|
|
||||||
row.unitsByWeek[weekKey] = (row.unitsByWeek[weekKey] || 0) + (record.unitsTotal || 0);
|
row.unitsByWeek[weekKey] = (row.unitsByWeek[weekKey] || 0) + (record.unitsTotal || 0);
|
||||||
row.spendByWeek[weekKey] = (row.spendByWeek[weekKey] || 0) + (record.cost || 0);
|
row.spendByWeek[weekKey] = (row.spendByWeek[weekKey] || 0) + (record.cost || 0);
|
||||||
|
row.revenueByWeek[weekKey] = (row.revenueByWeek[weekKey] || 0) + (record.salesTotal || 0);
|
||||||
row.gvByWeek[weekKey] = (row.gvByWeek[weekKey] || 0) + (record.glanceViews || 0);
|
row.gvByWeek[weekKey] = (row.gvByWeek[weekKey] || 0) + (record.glanceViews || 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user