"use client" import { useEffect, useState } from "react" import { useRouter } from "next/navigation" import { FolderOpen, FileText, AlertCircle, DollarSign, TrendingUp, AlertTriangle, Calendar } from "lucide-react" interface Deadline { type: string id: string name: string date: string status_name: string } export default function ClientDashboard() { const router = useRouter() const [counts, setCounts] = useState({ projects: 0, invoices: 0, tickets: 0 }) const [stats, setStats] = useState({ totalBilled: 0, totalPaid: 0, totalOverdue: 0, upcomingDeadlines: [] as Deadline[] }) const [name, setName] = useState("") const safeJson = (r: Response) => r.ok ? r.json() : Promise.reject() useEffect(() => { fetch("/client-portal/api/projects", { credentials: "include" }) .then(safeJson) .then((d) => setCounts((prev) => ({ ...prev, projects: d.projects?.length || 0 }))) .catch(() => {}) fetch("/client-portal/api/invoices", { credentials: "include" }) .then(safeJson) .then((d) => setCounts((prev) => ({ ...prev, invoices: d.invoices?.length || 0 }))) .catch(() => {}) fetch("/client-portal/api/support", { credentials: "include" }) .then(safeJson) .then((d) => setCounts((prev) => ({ ...prev, tickets: d.tickets?.length || 0 }))) .catch(() => {}) fetch("/client-portal/api/dashboard/stats", { credentials: "include" }) .then(safeJson) .then((d) => setStats(d)) .catch(() => {}) fetch("/api/auth/me", { credentials: "include" }) .then(safeJson) .then((d) => setName(d.user?.firstName || d.user?.email || "Client")) .catch(() => {}) }, []) const cards = [ { label: "Active Projects", value: counts.projects, icon: FolderOpen, color: "#1BB0CE", href: "/client-portal/projects" }, { label: "Invoices", value: counts.invoices, icon: FileText, color: "#a855f7", href: "/client-portal/invoices" }, { label: "Support Tickets", value: counts.tickets, icon: AlertCircle, color: "#f59e0b", href: "/client-portal/support" }, ] const formatCurrency = (amount: number) => { const num = Number(amount) || 0 return `$${num.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` } return (

Welcome, {name}

Your project overview at a glance

{/* Count cards */}
{cards.map((card) => { const Icon = card.icon return ( ) })}
{/* Financial stats */}
Total Billed

{formatCurrency(stats.totalBilled)}

Total Paid

{formatCurrency(stats.totalPaid)}

Overdue

{formatCurrency(stats.totalOverdue)}

{/* Upcoming Deadlines */} {stats.upcomingDeadlines.length > 0 && (
Upcoming Deadlines
{(stats.upcomingDeadlines || []).map((d, i) => (

{d.name}

{d.type} · {d.status_name?.replace("_", " ")}

{new Date(d.date).toLocaleDateString()}
))}
)}
) }