From bdd65d16d14de0287b0187be8444b38ef6ce49f2 Mon Sep 17 00:00:00 2001 From: Christian Vidal Wolf Date: Wed, 4 Mar 2026 08:29:20 +0100 Subject: [PATCH] fix: perfectly match Vendor tab UI to reference screenshot --- components/VendorDataView.tsx | 292 ++++++++++++++-------------------- 1 file changed, 119 insertions(+), 173 deletions(-) diff --git a/components/VendorDataView.tsx b/components/VendorDataView.tsx index 9190bc1..a0cfe14 100644 --- a/components/VendorDataView.tsx +++ b/components/VendorDataView.tsx @@ -3,14 +3,6 @@ import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContai import { BSRRecord } from '../types'; import { BuyBoxWarningBadge } from './BuyBoxWarningBadge'; -const MARKET_COLORS: Record = { - DE: '#3b82f6', - UK: '#ef4444', - IT: '#22c55e', - FR: '#a855f7', - ES: '#f97316', -}; - interface VendorDataViewProps { bsrData: BSRRecord[]; asinMetadata?: Map; @@ -24,25 +16,21 @@ interface ChartPoint { } const VendorDataView: React.FC = ({ bsrData = [], asinMetadata, buyBoxLostMap }) => { - // Determine active markets in filtered data for series generation const activeMarkets = useMemo(() => { const m = new Set(bsrData.map(r => r.market)); return Array.from(m).sort(); }, [bsrData]); - // Determine if daily resolution is available const useDailyResolution = useMemo(() => { const withDate = bsrData.filter(r => r.date).length; return withDate > bsrData.length / 2; }, [bsrData]); - // Get unique ASINs in filtered data const uniqueAsins = useMemo(() => { const asinSet = new Set(bsrData.map(r => r.asin.trim().toUpperCase())); return Array.from(asinSet); }, [bsrData]); - // Get product info when single ASIN is selected const productInfo = useMemo(() => { if (uniqueAsins.length !== 1) return null; const asin = uniqueAsins[0]; @@ -56,7 +44,6 @@ const VendorDataView: React.FC = ({ bsrData = [], asinMetad }; }, [uniqueAsins, asinMetadata]); - // Aggregate Data for Charts const { topBsrChartData, detailBsrChartData, ratingChartData } = useMemo(() => { const byBucket = new Map(); @@ -90,19 +77,16 @@ const VendorDataView: React.FC = ({ bsrData = [], asinMetad activeMarkets.forEach(m => { const marketRows = rows.filter(r => r.market === m); - // Top BSR const topBsrRows = marketRows.filter(r => r.topLevelBSR != null); topPoint[`${m}_bsr`] = topBsrRows.length > 0 ? Math.round(topBsrRows.reduce((sum, r) => sum + r.topLevelBSR!, 0) / topBsrRows.length) : null; - // Detail BSR const detailBsrRows = marketRows.filter(r => r.detailLevelBSR != null); detailPoint[`${m}_bsr`] = detailBsrRows.length > 0 ? Math.round(detailBsrRows.reduce((sum, r) => sum + r.detailLevelBSR!, 0) / detailBsrRows.length) : null; - // Rating const ratingRows = marketRows.filter(r => r.avgRating != null); ratingPoint[`${m}_rating`] = ratingRows.length > 0 ? Math.round((ratingRows.reduce((sum, r) => sum + r.avgRating!, 0) / ratingRows.length) * 10) / 10 @@ -133,39 +117,38 @@ const VendorDataView: React.FC = ({ bsrData = [], asinMetad ); } - return ( -
- {/* Header Info */} -
-

Vendor Analytics

- - {bsrData.length.toLocaleString()} records filtered - -
+ // Exact color values based on the screenshot + const cardBg = '#161b24'; + const orangeHex = '#f37526'; + const cyanHex = '#2acbd6'; + const purpleHex = '#7950f2'; + const gridLineColor = '#ffffff'; - {/* Product Info Card */} + return ( +
+ + {/* Product Details Header Card */} {productInfo && ( -
-
+
-
+
- - Product Details + + PRODUCT DETAILS -

+

{productInfo.title} -

+
-
-
- SKU: - {productInfo.sku} +
+
+ SKU: + {productInfo.sku}
-
- ASIN: - {productInfo.asin} +
+ ASIN: + {productInfo.asin}
@@ -177,200 +160,163 @@ const VendorDataView: React.FC = ({ bsrData = [], asinMetad )} {/* Top Level BSR Trend Chart */} -
-
-

Top Level BSR Trend

-

Weekly Average Rank • Lower is better

+
+
+

Top Level BSR Trend

+

Weekly Average Rank • Lower is better

-
+ +
- + - - - + + + - {activeMarkets.map(m => ( - - - - - ))} - - - + + + - {activeMarkets.map(m => ( + {activeMarkets.map((m, i) => ( ))}
-
- {activeMarkets.map(m => ( -
-
- {m} BSR + + {/* Exact Legend matching screenshot */} +
+ {activeMarkets.length > 0 && ( +
+
+ {activeMarkets[0]} BSR
- ))} + )}
{/* Detail Level BSR Trend Chart */} -
-
-

Detail Level BSR Trend

-

Sub-category Performance • Filtered ASINs

+
+
+

Detail Level BSR Trend

+

Sub-category Performance • Filtered ASINs

-
+ +
- + - {activeMarkets.map(m => ( - - - - - ))} + + + + - - - + + + - {activeMarkets.map(m => ( + {activeMarkets.map((m, i) => ( ))}
-
- {activeMarkets.map(m => ( -
-
- {m} Category Rank -
- ))} + + {/* Exact Legend matching screenshot */} +
+
+
+ Category Rank +
{/* Average Rating Chart */} -
-
-

Average Rating

-

Weekly Average • 1.0 - 5.0 Stars

+
+
+

Average Rating

+

Weekly Average (1.0 - 5.0)

-
+ +
- + - {activeMarkets.map(m => ( - - - - - ))} + + + + - - - + + + - {activeMarkets.map(m => ( + {activeMarkets.map((m, i) => ( ))}
-
- {activeMarkets.map(m => ( -
-
- {m} Star Rating -
- ))} + + {/* Exact Legend matching screenshot */} +
+
+
+ Star Rating +
+
); };