mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 17:25:23 +02:00
feat: implement country-aware Top 50 ranking
- App.tsx: Update top50Ranking2025 to calculate ranks based on active country filters - App.tsx: Add split Pan-EU vs UK ranking when no filters are active - WeeklyGrid.tsx: Add support for multiple ranking badges (EU/UK) - WeeklyGrid.tsx: Enhance Top50Badge with labels and color themes - WeeklyGrid.tsx: Update sorting and filtering logic for new ranking structure
This commit is contained in:
@@ -254,31 +254,48 @@ const App: React.FC = () => {
|
||||
const filteredAdsData = useMemo(() => filterAdsData(adsData, filters), [adsData, filters]);
|
||||
const aggregatedData = useMemo(() => aggregateData(filteredData), [filteredData]);
|
||||
|
||||
// Calculate static Top 50 Best Sellers for 2025 (independent of current filters)
|
||||
// Calculate country-aware Top 50 Best Sellers for 2025
|
||||
const top50Ranking2025 = useMemo(() => {
|
||||
// Filter only 2025 data
|
||||
const data2025 = rawData.filter(r => r.year === 2025);
|
||||
|
||||
// Aggregate Sell Out by ASIN
|
||||
const asinTotals = new Map<string, number>();
|
||||
data2025.forEach(r => {
|
||||
const asin = r.asin.trim().toUpperCase();
|
||||
asinTotals.set(asin, (asinTotals.get(asin) || 0) + r.sellOut);
|
||||
});
|
||||
const calculateTop50 = (entries: SalesRecord[]) => {
|
||||
const asinTotals = new Map<string, number>();
|
||||
entries.forEach(r => {
|
||||
const asin = r.asin.trim().toUpperCase();
|
||||
asinTotals.set(asin, (asinTotals.get(asin) || 0) + r.sellOut);
|
||||
});
|
||||
|
||||
// Sort by total Sell Out descending and take top 50
|
||||
const sorted = Array.from(asinTotals.entries())
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.slice(0, 50);
|
||||
const sorted = Array.from(asinTotals.entries())
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.slice(0, 50);
|
||||
|
||||
// Create a Map of ASIN -> rank (1-50)
|
||||
const rankMap = new Map<string, number>();
|
||||
sorted.forEach(([asin], index) => {
|
||||
rankMap.set(asin, index + 1);
|
||||
});
|
||||
const rankMap = new Map<string, number>();
|
||||
sorted.forEach(([asin], index) => {
|
||||
rankMap.set(asin, index + 1);
|
||||
});
|
||||
return rankMap;
|
||||
};
|
||||
|
||||
return rankMap;
|
||||
}, [rawData]);
|
||||
if (filters.customer.length > 0) {
|
||||
// Filtered mode: Rank products based on currently selected countries
|
||||
const filtered2025 = data2025.filter(r => filters.customer.includes(r.customer));
|
||||
return {
|
||||
type: 'filtered' as const,
|
||||
overall: calculateTop50(filtered2025)
|
||||
};
|
||||
} else {
|
||||
// Dual mode: Separate Pan-EU and UK rankings when no countries are selected
|
||||
const euData = data2025.filter(r => !r.customer.toLowerCase().includes('uk'));
|
||||
const ukData = data2025.filter(r => r.customer.toLowerCase().includes('uk'));
|
||||
|
||||
return {
|
||||
type: 'dual' as const,
|
||||
eu: calculateTop50(euData),
|
||||
uk: calculateTop50(ukData)
|
||||
};
|
||||
}
|
||||
}, [rawData, filters.customer]);
|
||||
|
||||
// Combine Sales & Ads Data dynamically based on current filters
|
||||
const combinedAdsData = useMemo(() => {
|
||||
|
||||
Reference in New Issue
Block a user