mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 16:35:23 +02:00
Optimize Weekly Sales performance and fix UI hang
This commit is contained in:
+40
-40
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useState, useEffect, useCallback } from 'react';
|
||||
import React, { useMemo, useState, useEffect, useCallback, useRef } from 'react';
|
||||
import * as XLSX from 'xlsx';
|
||||
import { CombinedKPIs } from '../types';
|
||||
import { pivotWeeklySalesData, WeeklyPivotRow } from '../services/dataProcessor';
|
||||
@@ -196,21 +196,26 @@ const WeeklyGrid: React.FC<WeeklyGridProps> = ({ data, top50Ranking, onDrillDown
|
||||
});
|
||||
}, []);
|
||||
|
||||
// Calculate totals in a SINGLE PASS (O(rows) instead of O(weeks × rows))
|
||||
// Calculate totals in a SINGLE PASS
|
||||
const weekTotals = useMemo(() => {
|
||||
const totals: { [weekKey: string]: { units: number, spend: number, gv: number } } = {};
|
||||
// Initialize all weeks
|
||||
weeks.forEach(week => {
|
||||
totals[week] = { units: 0, spend: 0, gv: 0 };
|
||||
});
|
||||
const visibleWeeks = weeks;
|
||||
|
||||
// Initialize visible weeks
|
||||
for (let i = 0; i < visibleWeeks.length; i++) {
|
||||
totals[visibleWeeks[i]] = { units: 0, spend: 0, gv: 0 };
|
||||
}
|
||||
|
||||
// Single pass through rows
|
||||
rows.forEach(row => {
|
||||
weeks.forEach(week => {
|
||||
totals[week].units += (row.unitsByWeek[week] || 0);
|
||||
totals[week].spend += (row.spendByWeek[week] || 0);
|
||||
totals[week].gv += (row.gvByWeek?.[week] || 0);
|
||||
});
|
||||
});
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
const row = rows[i];
|
||||
for (let j = 0; j < visibleWeeks.length; j++) {
|
||||
const w = visibleWeeks[j];
|
||||
totals[w].units += (row.unitsByWeek[w] || 0);
|
||||
totals[w].spend += (row.spendByWeek[w] || 0);
|
||||
totals[w].gv += (row.gvByWeek?.[w] || 0);
|
||||
}
|
||||
}
|
||||
return totals;
|
||||
}, [rows, weeks]);
|
||||
|
||||
@@ -274,41 +279,36 @@ const WeeklyGrid: React.FC<WeeklyGridProps> = ({ data, top50Ranking, onDrillDown
|
||||
|
||||
// 2. Sort results
|
||||
const sortedRows = useMemo(() => {
|
||||
if (!sortConfig) return filteredRows;
|
||||
if (!sortConfig || filteredRows.length === 0) return filteredRows;
|
||||
|
||||
const result = [...filteredRows];
|
||||
const metricKey = sortConfig.metric === 'units' ? 'unitsByWeek' :
|
||||
sortConfig.metric === 'spend' ? 'spendByWeek' : 'gvByWeek';
|
||||
const weekKey = sortConfig.key;
|
||||
const direction = sortConfig.direction;
|
||||
const { key: weekKey, direction, metric } = sortConfig;
|
||||
|
||||
result.sort((a, b) => {
|
||||
if (sortConfig.metric === 'rank') {
|
||||
if (metric === 'rank') {
|
||||
if (!top50Ranking) return result;
|
||||
const rankMap = top50Mode === 'eu' ? top50Ranking.eu : top50Ranking.uk;
|
||||
|
||||
result.sort((a, b) => {
|
||||
const asinA = a.asin.trim().toUpperCase();
|
||||
const asinB = b.asin.trim().toUpperCase();
|
||||
|
||||
let rankA = 999;
|
||||
let rankB = 999;
|
||||
|
||||
if (top50Ranking) {
|
||||
if (top50Mode === 'eu') {
|
||||
rankA = top50Ranking.eu.get(asinA) || 999;
|
||||
rankB = top50Ranking.eu.get(asinB) || 999;
|
||||
} else {
|
||||
rankA = top50Ranking.uk.get(asinA) || 999;
|
||||
rankB = top50Ranking.uk.get(asinB) || 999;
|
||||
}
|
||||
}
|
||||
|
||||
const rankA = rankMap.get(asinA) || 999;
|
||||
const rankB = rankMap.get(asinB) || 999;
|
||||
return direction === 'asc' ? rankA - rankB : rankB - rankA;
|
||||
}
|
||||
const valA = a[metricKey][weekKey] || 0;
|
||||
const valB = b[metricKey][weekKey] || 0;
|
||||
return direction === 'asc' ? valA - valB : valB - valA;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
const metricKey = metric === 'units' ? 'unitsByWeek' :
|
||||
metric === 'spend' ? 'spendByWeek' : 'gvByWeek';
|
||||
|
||||
result.sort((a, b) => {
|
||||
const valA = a[metricKey][weekKey] || 0;
|
||||
const valB = b[metricKey][weekKey] || 0;
|
||||
if (valA === valB) return 0;
|
||||
return direction === 'asc' ? valA - valB : valB - valA;
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [filteredRows, sortConfig]);
|
||||
}, [filteredRows, sortConfig, top50Ranking, top50Mode]);
|
||||
|
||||
// 3. Paginate
|
||||
const paginatedRows = useMemo(() => {
|
||||
|
||||
Reference in New Issue
Block a user