import { Loader2 } from 'lucide-react' import { useTheme } from 'next-themes' import { useMemo, useState } from 'react' import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts' import { cn, Tabs_Shadcn_, TabsContent_Shadcn_, TabsList_Shadcn_, TabsTrigger_Shadcn_ } from 'ui' import type { ChartDataPoint } from '../QueryInsights.types' import { CHART_TABS, CHART_TYPE, LEGEND_ITEMS, SEL_COLOR } from './QueryInsightsChart.constants' import { formatTime } from './QueryInsightsChart.utils' import { QueryInsightsChartTooltip } from './QueryInsightsChartTooltip' interface QueryInsightsChartProps { chartData: ChartDataPoint[] selectedChartData?: ChartDataPoint[] isLoading: boolean } export const QueryInsightsChart = ({ chartData, selectedChartData, isLoading, }: QueryInsightsChartProps) => { const [selectedMetric, setSelectedMetric] = useState('query_latency') const [hiddenSeries, setHiddenSeries] = useState>(new Set()) const { resolvedTheme } = useTheme() const isDarkMode = resolvedTheme?.includes('dark') const data = useMemo(() => { const normalize = (ts: number) => (ts > 1e13 ? Math.floor(ts / 1000) : ts) const selByTime = new Map((selectedChartData ?? []).map((d) => [normalize(d.period_start), d])) return chartData.map((d) => { const t = normalize(d.period_start) const sel = selByTime.get(t) return { time: t, p50: d.p50_time, p95: d.p95_time, rows_read: d.rows_read, calls: d.calls, cache_hits: d.cache_hits, sel_p50: sel?.p50_time, sel_rows_read: sel?.rows_read, sel_calls: sel?.calls, sel_cache_hits: sel?.cache_hits, } }) }, [chartData, selectedChartData]) const filteredData = useMemo(() => { if (hiddenSeries.size === 0) return data return data.map((point) => { const filtered = { ...point } as Record hiddenSeries.forEach((key) => { filtered[key] = undefined }) return filtered }) }, [data, hiddenSeries]) const toggleSeries = (dataKey: string) => { setHiddenSeries((prev) => { const next = new Set(prev) if (next.has(dataKey)) { next.delete(dataKey) } else { next.add(dataKey) } return next }) } const hasSelection = !!selectedChartData && selectedChartData.length > 0 const selDataKey = selectedMetric === 'query_latency' ? 'sel_p50' : `sel_${selectedMetric}` const legendItems = LEGEND_ITEMS[selectedMetric] ?? [] return (
{CHART_TABS.map((tab) => ( {tab.label} ))}
{legendItems.map((item: { dataKey: string; label: string; color: string }) => ( ))} {hasSelection && ( )}
{isLoading ? (
) : data.length === 0 ? (

No data available

) : ( {legendItems.map((item) => ( ))} {hasSelection && ( )} selectedMetric === 'query_latency' ? `${Math.round(v)}ms` : `${Math.round(v)}` } mirror={true} /> } cursor={{ stroke: isDarkMode ? 'rgba(255, 255, 255, 0.5)' : 'rgba(0, 0, 0, 0.5)', strokeWidth: 1, }} /> {legendItems.map((item) => ( ))} {hasSelection && ( )} )}
{data.length > 0 && (
{formatTime(data[0].time)} {formatTime(data[data.length - 1].time)}
)}
) }