import { useState } from 'react'; import { useIngestionThroughput, useIngestionSummary } from '../api/hooks'; import { LoadingSpinner, DateRangeSelector, Card } from '../components/ui'; import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, Legend } from 'recharts'; export function OpsIngestionPage() { const [hours, setHours] = useState(24); const [bucket, setBucket] = useState('1h'); const { data: throughput, isLoading: tpLoading } = useIngestionThroughput(hours, bucket); const { data: summary } = useIngestionSummary(hours); if (tpLoading) return ; const chartData = (() => { const buckets = new Map(); for (const row of throughput ?? []) { const r = row as Record; const time = r.bucket_start ? new Date(r.bucket_start as string).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : ''; if (!time) continue; const existing = buckets.get(time) ?? { time, completed: 0, failed: 0, items: 0 }; existing.completed += Number(r.completed ?? 0); existing.failed += Number(r.failed ?? 0); existing.items += Number(r.items_fetched ?? 0); buckets.set(time, existing); } return Array.from(buckets.values()); })(); const s = (summary ?? {}) as Record; return ( Ingestion Monitor {['15m', '1h', '6h', '1d'].map((b) => ( setBucket(b)} className={`px-2 py-1 text-xs font-medium first:rounded-l-md last:rounded-r-md ${bucket === b ? 'bg-brand-600 text-white' : 'bg-surface-900 text-gray-400 hover:bg-surface-800'}`} > {b} ))} {/* Summary stats */} {/* Throughput chart */} Throughput {/* By source type */} {s.by_source_type ? ( By Source Type Type Runs Completed Failed Items {(s.by_source_type as Array>).map((row, i) => ( {String(row.source_type)} {String(row.runs)} {String(row.completed)} {String(row.failed)} {String(row.items_fetched)} ))} ) : null} ); } function StatCard({ label, value, color = 'text-gray-100' }: { label: string; value: string; color?: string }) { return ( {value} {label} ); }