import { Activity, ArrowUpRight, BarChart3, Calendar, Edit, Eye, FileText, Plus, Users, } from "lucide-react"; import Link from "next/link"; import { AnimatedStatsCard } from "~/app/dashboard/_components/animated-stats-card"; import { InvoiceStatusChart, MonthlyMetricsChart, RevenueChart, } from "~/app/dashboard/_components/charts-client"; import { DashboardPageHeader } from "~/components/layout/page-header"; import { DashboardCardTitle, DashboardGrid, DashboardPage as DashboardPageLayout, dashboardGridClass, } from "~/components/layout/dashboard-page"; import { Badge } from "~/components/ui/badge"; import { Button } from "~/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "~/components/ui/card"; import { getOptionalServerSessionFromHeaders } from "~/lib/auth-server"; import { cn } from "~/lib/utils"; import { api } from "~/trpc/server"; import type { DashboardStats, RecentInvoice } from "./types"; function DashboardStats({ stats }: { stats: DashboardStats }) { const formatTrend = (value: number, isCount = false) => { if (isCount) { return value > 0 ? `+${value}` : value.toString(); } return value > 0 ? `+${value.toFixed(1)}%` : `${value.toFixed(1)}%`; }; const statCards = [ { title: "Total Revenue", value: `$${stats.totalRevenue.toLocaleString("en-US", { minimumFractionDigits: 2 })}`, numericValue: stats.totalRevenue, isCurrency: true, change: formatTrend(stats.revenueChange), trend: stats.revenueChange >= 0 ? ("up" as const) : ("down" as const), iconName: "DollarSign" as const, description: "Collected to date", }, { title: "Pending", value: `$${stats.pendingAmount.toLocaleString("en-US", { minimumFractionDigits: 2 })}`, numericValue: stats.pendingAmount, isCurrency: true, change: "0%", trend: "neutral" as const, iconName: "Clock" as const, description: "Awaiting payment", }, { title: "Clients", value: stats.totalClients.toString(), numericValue: stats.totalClients, isCurrency: false, change: "0", trend: "neutral" as const, iconName: "Users" as const, description: "Active clients", }, { title: "Overdue", value: stats.overdueCount.toString(), numericValue: stats.overdueCount, isCurrency: false, change: "0", trend: "neutral" as const, iconName: "TrendingDown" as const, description: "Past due date", }, ]; return (
{statCards.map((stat, index) => ( ))}
); } function ChartsSection({ stats }: { stats: DashboardStats }) { return ( Revenue over time Invoice status Monthly metrics ); } function QuickActions() { const actions = [ { title: "Create invoice", description: "Start a new invoice for a client", href: "/dashboard/invoices/new", icon: FileText, featured: true, }, { title: "Add client", description: "Register someone you bill", href: "/dashboard/clients/new", icon: Users, featured: false, }, { title: "View invoices", description: "Browse your full pipeline", href: "/dashboard/invoices", icon: BarChart3, featured: false, }, ]; return ( Quick actions {actions.map((action) => { const Icon = action.icon; return (

{action.title}

{action.description}

); })}
); } function CurrentWork({ currentDraft, }: { currentDraft: DashboardStats["currentDraft"]; }) { if (!currentDraft) { return ( Current work

No draft in progress

Start an invoice when you're ready to bill your next piece of work.
); } const totalHours = currentDraft.totalHours; return ( Current work Draft

#{currentDraft.invoiceNumber}

{currentDraft.client?.name}

${currentDraft.totalAmount.toFixed(2)}

{totalHours.toFixed(1)} hours logged

); } function RecentActivity({ recentInvoices, }: { recentInvoices: RecentInvoice[]; }) { const getStatusVariant = (status: string) => { switch (status) { case "paid": return "default" as const; case "sent": return "secondary" as const; case "overdue": return "destructive" as const; default: return "outline" as const; } }; return ( Recent activity {recentInvoices.length === 0 ? (

No invoices yet

Your latest invoices will show up here.
) : (
{recentInvoices.map((invoice) => (

#{invoice.invoiceNumber}

${invoice.totalAmount.toFixed(2)}

{invoice.client?.name}

{invoice.status}
))}
)}
); } export default async function DashboardPage() { const session = await getOptionalServerSessionFromHeaders(); const firstName = session?.user?.name?.split(" ")[0] ?? "User"; const stats = await api.dashboard.getStats(); return (
); }