mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 13:45:23 +02:00
feat: add Top 50 Best Sellers badge in Weekly Sales
- Calculate static Top 50 ranking based on 2025 Sell Out (independent of filters)
- Display trophy badge with position number for Top 50 ASINs
- Badge shows 🏆 followed by rank (1-50)
- Ranking stays static regardless of date/country filters applied
- Pre-computed ranking based on cumulative 2025 data
This commit is contained in:
@@ -254,6 +254,32 @@ 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)
|
||||
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);
|
||||
});
|
||||
|
||||
// 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);
|
||||
|
||||
// Create a Map of ASIN -> rank (1-50)
|
||||
const rankMap = new Map<string, number>();
|
||||
sorted.forEach(([asin], index) => {
|
||||
rankMap.set(asin, index + 1);
|
||||
});
|
||||
|
||||
return rankMap;
|
||||
}, [rawData]);
|
||||
|
||||
// Combine Sales & Ads Data dynamically based on current filters
|
||||
const combinedAdsData = useMemo(() => {
|
||||
return mergeSalesAndAdsData(filteredData, filteredAdsData);
|
||||
@@ -427,7 +453,7 @@ const App: React.FC = () => {
|
||||
)}
|
||||
<Suspense fallback={<LoadingSpinner />}>
|
||||
{view === 'table' && <DataGrid data={combinedAdsData} hasCustomerFilter={filters.customer.length > 0} adsData={filteredAdsData} />}
|
||||
{view === 'weekly' && <WeeklyGrid data={combinedAdsData} />}
|
||||
{view === 'weekly' && <WeeklyGrid data={combinedAdsData} top50Ranking={top50Ranking2025} />}
|
||||
{view === 'movers' && <TopMovers data={filteredData} />}
|
||||
</Suspense>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user