diff --git a/App.tsx b/App.tsx
index 1346f70..ae93ec7 100644
--- a/App.tsx
+++ b/App.tsx
@@ -836,7 +836,16 @@ const App: React.FC = () => {
-
+
}>
diff --git a/components/Dashboard.tsx b/components/Dashboard.tsx
index c32079d..0ce81d7 100644
--- a/components/Dashboard.tsx
+++ b/components/Dashboard.tsx
@@ -12,6 +12,10 @@ interface DashboardProps {
contextData?: AggregatedData | null;
adsData?: AdsRecord[];
rawData?: SalesRecord[];
+ stockMap?: Map
;
+ vendorStockMap?: Map;
+ buyBoxLostMap?: Map }>;
+ top50Mode?: 'eu' | 'uk';
}
const COLORS = ['#6366f1', '#ec4899', '#10b981', '#f59e0b', '#8b5cf6', '#0ea5e9'];
@@ -814,7 +818,13 @@ const Dashboard: React.FC = ({ data, contextData, adsData = [],
{/* Top Movers Table - Full Width */}
{rawData && rawData.length > 0 && (
-
+
)}
diff --git a/components/TopMovers.tsx b/components/TopMovers.tsx
index 8d5d852..7753487 100644
--- a/components/TopMovers.tsx
+++ b/components/TopMovers.tsx
@@ -2,15 +2,23 @@ import React, { useState, useMemo, useCallback } from 'react';
import * as XLSX from 'xlsx';
import { SalesRecord } from '../types';
import { DownloadIcon } from './Icons';
+import { StockBadge } from './StockBadge';
+import { VendorStockBadge } from './VendorStockBadge';
+import { BuyBoxWarningBadge } from './BuyBoxWarningBadge';
interface TopMoversProps {
data: SalesRecord[];
+ stockMap?: Map;
+ vendorStockMap?: Map;
+ buyBoxLostMap?: Map }>;
+ top50Mode?: 'eu' | 'uk';
}
type Metric = 'sellOut' | 'units';
interface SkuAggr {
sku: string;
+ asin: string;
title: string;
line: string;
previousValue: number;
@@ -27,7 +35,11 @@ const MoversTable: React.FC<{
previousYear: number;
currentYear: number;
type: 'growth' | 'decline';
-}> = ({ title, data, metric, previousYear, currentYear, type }) => {
+ stockMap?: Map;
+ vendorStockMap?: Map;
+ buyBoxLostMap?: Map }>;
+ top50Mode?: 'eu' | 'uk';
+}> = ({ title, data, metric, previousYear, currentYear, type, stockMap, vendorStockMap, buyBoxLostMap, top50Mode = 'eu' }) => {
const formatValue = (val: number) => {
if (metric === 'sellOut') return `€${val.toLocaleString('de-DE', { maximumFractionDigits: 0 })}`;
@@ -84,6 +96,9 @@ const MoversTable: React.FC<{
Rank |
SKU Details |
Product Line |
+ Stock |
+ Vendor |
+ Buy Box |
{previousYear} |
{currentYear} |
Diff |
@@ -113,6 +128,25 @@ const MoversTable: React.FC<{
+ {/* Stock Badge */}
+
+
+ |
+
+ {/* Vendor Stock Badge */}
+
+
+ |
+
+ {/* Buy Box Warning Badge */}
+
+
+ |
+
{formatValue(item.previousValue)}
|
@@ -148,7 +182,7 @@ const MoversTable: React.FC<{
);
};
-const TopMovers: React.FC = ({ data }) => {
+const TopMovers: React.FC = ({ data, stockMap, vendorStockMap, buyBoxLostMap, top50Mode = 'eu' }) => {
const [metric, setMetric] = useState('sellOut');
const [viewMode, setViewMode] = useState<'growth' | 'decline'>('growth');
@@ -167,14 +201,14 @@ const TopMovers: React.FC = ({ data }) => {
if (!currentYear || !previousYear) return { growers: [], decliners: [] };
// Map: SKU -> { currentVal, previousVal, metadata }
- const map = new Map();
+ const map = new Map();
data.forEach(row => {
// Only care about the two comparison years
if (row.year !== currentYear && row.year !== previousYear) return;
if (!map.has(row.sku)) {
- map.set(row.sku, { current: 0, previous: 0, title: row.title, line: row.line });
+ map.set(row.sku, { current: 0, previous: 0, title: row.title, line: row.line, asin: row.asin });
}
const entry = map.get(row.sku)!;
@@ -204,6 +238,7 @@ const TopMovers: React.FC = ({ data }) => {
list.push({
sku,
+ asin: val.asin,
title: val.title,
line: val.line,
previousValue: val.previous,
@@ -297,6 +332,10 @@ const TopMovers: React.FC = ({ data }) => {
previousYear={previousYear}
currentYear={currentYear}
type={viewMode}
+ stockMap={stockMap}
+ vendorStockMap={vendorStockMap}
+ buyBoxLostMap={buyBoxLostMap}
+ top50Mode={top50Mode}
/>