import { ResponsiveContainer, AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, } from 'recharts' import type { InterfaceMetricPoint } from '@/lib/api' interface TrafficChartProps { data: InterfaceMetricPoint[] interfaceName: string } function formatBps(bps: number): string { if (bps >= 1_000_000_000) return `${(bps / 1_000_000_000).toFixed(1)} Gbps` if (bps >= 1_000_000) return `${(bps / 1_000_000).toFixed(1)} Mbps` if (bps >= 1_000) return `${(bps / 1_000).toFixed(1)} Kbps` return `${bps} bps` } function formatBucket(bucket: string, useDate: boolean): string { const d = new Date(bucket) if (useDate) { const mm = String(d.getMonth() + 1).padStart(2, '0') const dd = String(d.getDate()).padStart(2, '0') return `${mm}/${dd}` } const hh = String(d.getHours()).padStart(2, '0') const min = String(d.getMinutes()).padStart(2, '0') return `${hh}:${min}` } function CustomTooltip({ active, payload, label }: { active?: boolean; payload?: Array<{ value?: number; dataKey?: string; name?: string; color?: string }>; label?: string }) { if (!active || !payload?.length) return null return (
{label}
{payload.map((entry) => (
{entry.name === 'avg_rx_bps' ? 'RX' : 'TX'} {formatBps(entry.value ?? 0)}
))}
) } export function TrafficChart({ data, interfaceName }: TrafficChartProps) { // Determine if we should show dates vs times based on data span const useDate = data.length >= 2 ? new Date(data[data.length - 1].bucket).getTime() - new Date(data[0].bucket).getTime() > 2 * 24 * 60 * 60 * 1000 : false const chartData = data.map((point) => ({ bucket: formatBucket(point.bucket, useDate), avg_rx_bps: point.avg_rx_bps ?? 0, avg_tx_bps: point.avg_tx_bps ?? 0, })) return (
{interfaceName}
} />
RX TX
) }