"use client"; import Link from "next/link"; import { Card, CardContent } from "@/components/ui/card"; import { BarChart2, Activity } from "lucide-react"; import { ReactNode } from "react"; type StatCard = { label: string; icon: ReactNode; count: number; href: string; }; type RecentEvent = { summary: string; createdAt: string; }; type TrafficSummary = { totalRequests: number; blockedPercent: number; } | null; // Per-position accent colors for stat cards (proxy hosts, certs, access lists, traffic) const CARD_ACCENTS = [ { border: "border-l-violet-500", icon: "border-violet-500/30 bg-violet-500/10 text-violet-500", count: "text-violet-600 dark:text-violet-400" }, { border: "border-l-emerald-500", icon: "border-emerald-500/30 bg-emerald-500/10 text-emerald-500", count: "text-emerald-600 dark:text-emerald-400" }, { border: "border-l-amber-500", icon: "border-amber-500/30 bg-amber-500/10 text-amber-500", count: "text-amber-600 dark:text-amber-400" }, ]; const TRAFFIC_ACCENT = { border: "border-l-cyan-500", icon: "border-cyan-500/30 bg-cyan-500/10 text-cyan-500", count: "text-cyan-600 dark:text-cyan-400", }; function getEventDotColor(summary: string): string { const lower = summary.toLowerCase(); if (lower.startsWith("delete") || lower.startsWith("remove")) return "bg-rose-500 shadow-[0_0_6px_rgba(244,63,94,0.5)]"; if (lower.startsWith("create") || lower.startsWith("add")) return "bg-emerald-500 shadow-[0_0_6px_rgba(16,185,129,0.5)]"; return "bg-primary shadow-[0_0_6px_var(--primary)]"; } function formatRelativeTime(iso: string): string { const diff = Date.now() - new Date(iso).getTime(); const mins = Math.floor(diff / 60000); if (mins < 1) return "just now"; if (mins < 60) return `${mins}m ago`; const hrs = Math.floor(mins / 60); if (hrs < 24) return `${hrs}h ago`; return new Date(iso).toLocaleDateString(); } export default function OverviewClient({ userName, stats, trafficSummary, recentEvents, isAdmin = true }: { userName: string; stats: StatCard[]; trafficSummary: TrafficSummary; recentEvents: RecentEvent[]; isAdmin?: boolean; }) { return (
{/* Welcome header */}

Welcome back, {userName}

Everything you need to orchestrate Caddy proxies, certificates, and secure edge services.

{/* Stat grid */}
{stats.map((stat, i) => { const accent = CARD_ACCENTS[i % CARD_ACCENTS.length]; return (
{stat.icon}
{stat.count}

{stat.label}

); })} {/* Traffic (24h) card — admin only */} {isAdmin && (
{trafficSummary ? trafficSummary.totalRequests.toLocaleString() : "—"}

Traffic (24h)

{trafficSummary && trafficSummary.totalRequests > 0 && (
Blocked 0 ? "text-rose-500" : "text-muted-foreground"}`}> {trafficSummary.blockedPercent}%
)} )}
{/* Recent Activity — admin only */} {isAdmin && (

Recent Activity

{recentEvents.length === 0 ? (

No activity recorded yet.

) : (
{/* Vertical timeline line */}
{recentEvents.map((event, index) => (
{/* Dot */}
{event.summary} {formatRelativeTime(event.createdAt)}
))}
)}
)}
); }