import React, { useMemo, useState } from 'react'; import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, Cell } from 'recharts'; import { BSRRecord } from '../types'; import { BuyBoxWarningBadge } from './BuyBoxWarningBadge'; const MARKET_COLORS: Record = { DE: '#3b82f6', UK: '#ef4444', IT: '#22c55e', FR: '#a855f7', ES: '#f59e0b', }; interface VendorDataViewProps { bsrData: BSRRecord[]; asinMetadata?: Map; buyBoxLostMap?: Map }>; } interface ChartPoint { label: string; sortKey: string; [key: string]: number | string | null; } 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 (>= half the records have a date) 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]; const metadata = asinMetadata?.get(asin); if (!metadata) return null; return { asin, sku: metadata.sku, title: metadata.title, line: metadata.line, }; }, [uniqueAsins, asinMetadata]); // Aggregate Data for Charts — daily if dates available, else weekly const { topBsrChartData, detailBsrChartData, ratingChartData } = useMemo(() => { // Group by date string (YYYY-MM-DD) or by week number const byBucket = new Map(); bsrData.forEach(r => { const key = useDailyResolution && r.date ? r.date : `W${String(r.week).padStart(2, '0')}`; if (!byBucket.has(key)) byBucket.set(key, []); byBucket.get(key)!.push(r); }); const sortedKeys = Array.from(byBucket.keys()).sort(); const topBsrChartData: ChartPoint[] = []; const detailBsrChartData: ChartPoint[] = []; const ratingChartData: ChartPoint[] = []; sortedKeys.forEach(key => { const rows = byBucket.get(key)!; // Human-readable label let label: string; if (useDailyResolution && key.includes('-')) { // YYYY-MM-DD → "DD MMM" const d = new Date(key + 'T12:00:00Z'); label = d.toLocaleDateString('en-GB', { day: '2-digit', month: 'short' }); } else { label = key; // e.g. "W08" } const topPoint: ChartPoint = { label, sortKey: key }; const detailPoint: ChartPoint = { label, sortKey: key }; const ratingPoint: ChartPoint = { label, sortKey: key }; 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 : null; }); topBsrChartData.push(topPoint); detailBsrChartData.push(detailPoint); ratingChartData.push(ratingPoint); }); return { topBsrChartData, detailBsrChartData, ratingChartData }; }, [bsrData, activeMarkets, useDailyResolution]); if (bsrData.length === 0) { return (

No BSR Data Yet

Ensure BSR.xlsx is present and loading to see Top Level BSR, Detail Level BSR, and Average Rating trends.

); } const resolutionLabel = useDailyResolution ? 'Daily Avg' : 'Weekly Avg'; return (
{bsrData.length.toLocaleString()} records filtered
{/* Product Info Card - Only shown when single ASIN is selected */} {productInfo && (
Product Details
SKU: {productInfo.sku}
ASIN: {productInfo.asin}
Title: {productInfo.title}
)} {/* Top Level BSR Trend Chart */}

Top Level BSR Trend ({resolutionLabel})

Lower rank = better position. Averaged across filtered ASINs per market.

{activeMarkets.map(m => ( ))}
{/* Detail Level BSR Trend Chart */}

Detail Level BSR Trend ({resolutionLabel})

Lower rank = better position. Averaged across filtered ASINs per market.

{activeMarkets.map(m => ( ))}
{/* Average Rating Chart */}

Average Rating ({resolutionLabel})

Averaged across filtered ASINs per market.

{activeMarkets.map(m => ( ))}
); }; export default VendorDataView;