import {
Activity,
ArrowUpRight,
BarChart3,
Calendar,
Edit,
Eye,
FileText,
Plus,
Users,
} from "lucide-react";
import Link from "next/link";
import { Suspense } from "react";
import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import { Skeleton } from "~/components/ui/skeleton";
import { getEffectiveInvoiceStatus } from "~/lib/invoice-status";
import { auth } from "~/lib/auth";
import { headers } from "next/headers";
import { HydrateClient, api } from "~/trpc/server";
import type { StoredInvoiceStatus } from "~/types/invoice";
import { RevenueChart } from "~/app/dashboard/_components/revenue-chart";
import { InvoiceStatusChart } from "~/app/dashboard/_components/invoice-status-chart";
import { MonthlyMetricsChart } from "~/app/dashboard/_components/monthly-metrics-chart";
import { AnimatedStatsCard } from "~/app/dashboard/_components/animated-stats-card";
import type { DashboardStats, RecentInvoice } from "./types";
// Hero section with clean mono design
// Enhanced stats cards with better visuals
function DashboardStats({ stats }: { stats: DashboardStats }) { // TODO: Import RouterOutput type
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: "Total collected revenue",
},
{
title: "Pending Amount",
value: `$${stats.pendingAmount.toLocaleString("en-US", { minimumFractionDigits: 2 })}`,
numericValue: stats.pendingAmount,
isCurrency: true,
change: "0%", // TODO: Calculate pending change if needed
trend: "neutral" as const,
iconName: "Clock" as const,
description: "Invoices awaiting payment",
},
{
title: "Active Clients",
value: stats.totalClients.toString(),
numericValue: stats.totalClients,
isCurrency: false,
change: "0", // TODO: Calculate client change if needed
trend: "neutral" as const,
iconName: "Users" as const,
description: "Total registered clients",
},
{
title: "Overdue Invoices",
value: stats.overdueCount.toString(),
numericValue: stats.overdueCount,
isCurrency: false,
change: "0", // TODO: Calculate overdue change if needed
trend: "neutral" as const,
iconName: "TrendingDown" as const,
description: "Invoices past due date",
},
];
return (
{statCards.map((stat, index) => (
))}
);
}
// Charts section
async function ChartsSection({ stats }: { stats: DashboardStats }) {
// We still fetch all invoices for the status chart for now, or we could aggregate that too.
// For now, let's keep status chart as is (fetching all) but use aggregated for revenue.
// Actually, let's fetch invoices here for the status chart to keep it working.
const invoices = await api.invoices.getAll();
return (
{/* Revenue Trend Chart */}
Revenue Over Time
{/* Invoice Status Breakdown */}
Invoice Status
{/* Monthly Metrics */}
Monthly Metrics
);
}
// Enhanced Quick Actions
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 a new client",
href: "/dashboard/clients/new",
icon: Users,
featured: false,
},
{
title: "View All Invoices",
description: "Manage your invoice pipeline",
href: "/dashboard/invoices",
icon: BarChart3,
featured: false,
},
];
return (
Quick Actions
{actions.map((action) => {
const Icon = action.icon;
return (
{action.title}
{action.description}
);
})}
);
}
// Current work section with enhanced design
async function CurrentWork() {
const invoices = await api.invoices.getAll();
const draftInvoices = invoices.filter(
(invoice) =>
getEffectiveInvoiceStatus(
invoice.status as StoredInvoiceStatus,
invoice.dueDate,
) === "draft",
);
const currentInvoice = draftInvoices[0];
if (!currentInvoice) {
return (
Current Work
No active drafts
Create a new invoice to get started
);
}
const totalHours =
currentInvoice.items?.reduce((sum, item) => sum + item.hours, 0) ?? 0;
return (
Current Work
In Progress