function buildChartGeometry(points, width, height, padding) { if (!points.length) return null; const amounts = points.map((point) => point.amount); const min = Math.min(...amounts); const max = Math.max(...amounts); const range = max - min || 1; const innerWidth = width - padding * 2; const innerHeight = height - padding * 2; const coordinates = points.map((point, index) => { const x = padding + (index / Math.max(points.length - 1, 1)) * innerWidth; const y = padding + innerHeight - ((point.amount - min) / range) * innerHeight; return { x, y }; }); const polyline = coordinates.map(({ x, y }) => `${x},${y}`).join(' '); const area = [ `${coordinates[0].x},${height - padding}`, ...coordinates.map(({ x, y }) => `${x},${y}`), `${coordinates[coordinates.length - 1].x},${height - padding}`, ].join(' '); return { polyline, area, min, max }; } export default function CardDetailPriceHistoryTab({ points = [], priceHistoryLoading, formatCurrency, }) { const chart = buildChartGeometry(points, 640, 220, 24); return (

Price History

Price Trend

{priceHistoryLoading ? (

Loading price history…

) : points.length === 0 ? (

No price history yet. Snapshots are recorded during catalog sync — check back after the next update.

) : (
{points[0]?.date} Low {formatCurrency(chart.min)} · High {formatCurrency(chart.max)} {points[points.length - 1]?.date}
)}
{points.length > 0 && (
Latest Price
{formatCurrency(points[points.length - 1].amount)}
)}
); }