import { useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { analyticsApi } from '../api/client'; import { AlertCircle, Database } from 'lucide-react'; import { PieChart, Pie, Cell, BarChart, Bar, LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, Legend } from 'recharts'; import { useChartTheme } from '../context/useChartTheme'; const COLORS = ['#6366f1', '#0ea5e9', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899', '#14b8a6']; export function AnalyticsPage() { const [days, setDays] = useState(30); const chartTheme = useChartTheme(); const { data, isLoading, isError, refetch } = useQuery({ queryKey: ['analytics', days], queryFn: () => analyticsApi.getAnalytics(days), }); const trendsQuery = useQuery({ queryKey: ['analytics-trends', days], queryFn: () => analyticsApi.getTrends(days), }); if (isLoading) { return (

Analytics Dashboard

Loading analytics data...

{/* Skeleton cards */}
{[1, 2, 3].map((i) => (
))}
{/* Skeleton charts */}
{[1, 2].map((i) => (
))}
); } if (isError) { return (

Analytics Dashboard

Unable to Load Analytics

Could not connect to the analytics database. Ensure PostgreSQL is running and DATABASE_URL is configured correctly.

); } if (!data || (data.total_messages === 0 && data.by_company.length === 0)) { return (

Analytics Dashboard

Track historical analysis data and view insights.

No analytics data available yet. Run some analyses first!
); } const companyData = data.by_company.map((c) => ({ name: (c.company_name || 'Unknown').toUpperCase(), value: c.count, })); const typeData = data.by_type.map((t) => ({ name: t.analysis_type || 'Unknown', count: t.count, })); return (
{/* Header */}

Analytics Dashboard

Track historical analysis data and view insights.

{/* Time Range Selector */}
{/* Summary Metrics */}
{/* Charts */}
{/* Pie Chart - Distribution by Company */} {companyData.length > 0 && (

Distribution by Company

`${name} ${(percent * 100).toFixed(0)}%`} labelLine={false} > {companyData.map((_, index) => ( ))}
)} {/* Bar Chart - Analysis Types */} {typeData.length > 0 && (

Analysis Types

)}
{/* Trend Charts */} {trendsQuery.data && (

Trends Over Time

{/* Patent count over time per company (line chart) */} {trendsQuery.data.by_month.length > 0 && (() => { // Pivot data: each month as a row, companies as columns const companies = [...new Set(trendsQuery.data!.by_month.map(d => d.company_name))]; const months = [...new Set(trendsQuery.data!.by_month.map(d => d.month))].sort(); const pivoted = months.map(month => { const row: Record = { month }; for (const c of companies) { const entry = trendsQuery.data!.by_month.find(d => d.month === month && d.company_name === c); row[c] = entry?.count || 0; } return row; }); return (

Analyses per Company Over Time

{companies.map((company, idx) => ( ))}
); })()} {/* Analysis type distribution over time (stacked bar) */} {trendsQuery.data.by_type_over_time.length > 0 && (() => { const types = [...new Set(trendsQuery.data!.by_type_over_time.map(d => d.analysis_type))]; const months = [...new Set(trendsQuery.data!.by_type_over_time.map(d => d.month))].sort(); const pivoted = months.map(month => { const row: Record = { month }; for (const t of types) { const entry = trendsQuery.data!.by_type_over_time.find(d => d.month === month && d.analysis_type === t); row[t] = entry?.count || 0; } return row; }); return (

Analysis Types Over Time

{types.map((type, idx) => ( ))}
); })()}
{trendsQuery.data.by_month.length === 0 && (
No trend data available yet. Run analyses over multiple days to see trends.
)}
)}
); } function MetricCard({ label, value }: { label: string; value: number }) { return (
{value}
{label}
); }