← back to Omega Watches 2
src/components/charts/PriceTimeSeries.tsx
98 lines
'use client';
import { ResponsiveContainer, ComposedChart, Line, Area, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ReferenceLine } from 'recharts';
import { formatCurrency, formatDate } from '@/lib/utils';
interface TimeSeriesPoint {
date: string;
price?: number;
msrp?: number;
event_type?: string;
source?: string;
label?: string;
}
interface PriceTimeSeriesProps {
data: TimeSeriesPoint[];
title?: string;
showMSRP?: boolean;
currency?: string;
}
const EVENT_COLORS: Record<string, string> = {
auction_result: '#c89b3c',
dealer_ask: '#6366f1',
marketplace_sold: '#22c55e',
forum_listing: '#f59e0b',
msrp: '#ef4444',
};
const CustomTooltip = ({ active, payload, label }: any) => {
if (!active || !payload?.length) return null;
return (
<div className="bg-navy-800 border border-navy-600 rounded-lg p-3 shadow-xl">
<p className="text-xs text-navy-300 mb-1">{formatDate(label)}</p>
{payload.map((entry: any, i: number) => (
<p key={i} className="text-sm" style={{ color: entry.color }}>
{entry.name}: {formatCurrency(entry.value)}
</p>
))}
</div>
);
};
export default function PriceTimeSeries({ data, title, showMSRP = true, currency = 'USD' }: PriceTimeSeriesProps) {
if (!data?.length) {
return (
<div className="bg-navy-800/50 rounded-xl border border-navy-700 p-8 text-center">
<p className="text-navy-400">No time series data available</p>
</div>
);
}
return (
<div className="bg-navy-800/50 rounded-xl border border-navy-700 p-4">
{title && <h3 className="text-lg font-semibold text-white mb-4">{title}</h3>}
<ResponsiveContainer width="100%" height={400}>
<ComposedChart data={data} margin={{ top: 5, right: 20, bottom: 5, left: 20 }}>
<CartesianGrid strokeDasharray="3 3" stroke="#1e293b" />
<XAxis
dataKey="date"
tickFormatter={(v) => formatDate(v)}
stroke="#64748b"
fontSize={11}
/>
<YAxis
tickFormatter={(v) => `$${(v / 1000).toFixed(0)}k`}
stroke="#64748b"
fontSize={11}
/>
<Tooltip content={<CustomTooltip />} />
<Legend />
{showMSRP && (
<Area
type="monotone"
dataKey="msrp"
name="MSRP"
fill="#ef444420"
stroke="#ef4444"
strokeWidth={2}
strokeDasharray="5 5"
dot={false}
/>
)}
<Line
type="monotone"
dataKey="price"
name="Market Price"
stroke="#c89b3c"
strokeWidth={2}
dot={{ fill: '#c89b3c', r: 3 }}
activeDot={{ r: 6 }}
/>
</ComposedChart>
</ResponsiveContainer>
</div>
);
}