"use client"; import { usePoll } from "@/lib/use-poll"; import type { OverviewStats } from "@/lib/types"; import { StatCard } from "@/components/stat-card"; import { ActivityFeed } from "@/components/activity-feed"; import { JellyfinCard } from "@/components/jellyfin-card"; import { OllamaCard } from "@/components/ollama-card"; import { HostCard } from "@/components/host-card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; function SectionHeading({ children }: { children: React.ReactNode }) { return (

{children}

); } export default function DashboardPage() { const { data } = usePoll("/api/stats/overview", 60000); // Handle both API field name variants const endpoints = data?.containers?.endpoints || data?.containers?.by_endpoint || {}; const rawEmail = data?.emails_today ?? data?.email_today ?? 0; const emailCount = typeof rawEmail === "object" && rawEmail !== null ? (rawEmail as Record).total ?? 0 : rawEmail; const alertCount = data?.alerts ?? data?.unhealthy_count ?? 0; const running = data?.containers?.running ?? Object.values(endpoints).reduce((s, e) => s + (e.running || 0), 0); const hostsOnline = data?.hosts_online ?? Object.values(endpoints).filter(e => !e.error).length; const gpuPct = data?.gpu?.utilization_pct; return (
{/* Row 1: Stat Cards */} Overview
{/* Row 2: Activity + Jellyfin + Ollama */} Live
{/* Row 3: Hosts */} Infrastructure Hosts
{data ? Object.entries(endpoints).map( ([name, info]) => ( ) ) : Array.from({ length: 5 }).map((_, i) => (

Loading...

))}
); }