All Taste components
Dashboards
Invoicing dashboard
A small-business money overview: what’s owed, what’s overdue, monthly collections and the latest invoices.
sidebar · header · 4 KPIs · bar chart · due list · invoice table · 4 statuses
Overview
Search invoices, customers⌘K
Good morning, Asha
Here’s where your money stands for October.
Outstanding
₹4,82,300
23 open invoices
Overdue
₹96,400
6 invoices · oldest 21 days
Collected in October
₹7,14,950
↑ 12.4% vs September
Average days to pay
18 days
↓ 3 days faster
Invoiced vs collected
InvoicedCollected
Due in 7 days
₹1,37,500Nilgiri Traders
Fri 16
Sharma Hardware
Sat 17
Coastal Spice Co.
Mon 19
Bluefern Studio
Tue 20
Recent invoices
| Invoice | Customer | Issued | Due | Amount | Status |
|---|---|---|---|---|---|
| INV-1048 | Nilgiri Traders | 12 Oct | 26 Oct | ₹38,500 | Sent |
| INV-1047 | Coastal Spice Co. | 10 Oct | 24 Oct | ₹64,200 | Viewed |
| INV-1046 | Sharma Hardware | 02 Oct | 09 Oct | ₹12,800 | Overdue |
| INV-1045 | Bluefern Studio | 28 Sep | 12 Oct | ₹22,000 | Paid |
import { Bell, ChevronDown, CreditCard, Download, FileText, Home, LineChart, Plus, Search, Tag, Users } from "lucide-react";
import { cn } from "@/lib/utils";
const nav = [
{ label: "Overview", icon: Home, href: "/", current: true },
{ label: "Invoices", icon: FileText, href: "/invoices", count: 12 },
{ label: "Customers", icon: Users, href: "/customers" },
{ label: "Payments", icon: CreditCard, href: "/payments" },
{ label: "Expenses", icon: Tag, href: "/expenses" },
{ label: "Reports", icon: LineChart, href: "/reports" },
];
const kpis = [
{ label: "Outstanding", value: "₹4,82,300", note: "23 open invoices", tone: "flat" },
{ label: "Overdue", value: "₹96,400", note: "6 invoices · oldest 21 days", tone: "down" },
{ label: "Collected in October", value: "₹7,14,950", note: "↑ 12.4% vs September", tone: "up" },
{ label: "Average days to pay", value: "18 days", note: "↓ 3 days faster", tone: "up" },
] as const;
// Lakh rupees per month, November → October.
const months = ["Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct"];
const invoiced = [6.2, 5.8, 7.1, 6.6, 7.9, 8.4, 7.2, 8.8, 9.6, 9.1, 10.4, 9.8];
const collected = [5.6, 5.5, 6.4, 6.1, 7.0, 7.9, 6.8, 8.0, 8.7, 8.6, 9.2, 7.1];
const max = 12;
const dueThisWeek = [
{ customer: "Nilgiri Traders", day: "Fri 16", amount: "₹38,500" },
{ customer: "Sharma Hardware", day: "Sat 17", amount: "₹12,800" },
{ customer: "Coastal Spice Co.", day: "Mon 19", amount: "₹64,200" },
{ customer: "Bluefern Studio", day: "Tue 20", amount: "₹22,000" },
];
const invoices = [
{ id: "INV-1048", customer: "Nilgiri Traders", issued: "12 Oct", due: "26 Oct", amount: "₹38,500", status: "Sent" },
{ id: "INV-1047", customer: "Coastal Spice Co.", issued: "10 Oct", due: "24 Oct", amount: "₹64,200", status: "Viewed" },
{ id: "INV-1046", customer: "Sharma Hardware", issued: "02 Oct", due: "09 Oct", amount: "₹12,800", status: "Overdue" },
{ id: "INV-1045", customer: "Bluefern Studio", issued: "28 Sep", due: "12 Oct", amount: "₹22,000", status: "Paid" },
] as const;
const statusTone = {
Sent: "bg-surface-2 text-fg-muted",
Viewed: "bg-info-soft text-info-fg",
Overdue: "bg-danger-soft text-danger-fg",
Paid: "bg-success-soft text-success-fg",
};
export default function DashboardPage() {
return (
<div className="flex min-h-screen bg-bg font-sans text-sm text-fg">
<aside aria-label="Main" className="hidden w-56 shrink-0 flex-col gap-0.5 border-r border-border bg-surface p-3 lg:flex">
<button type="button" className="mb-2 flex h-8 items-center gap-2 rounded px-1.5 font-medium hover:bg-surface-2">
<span className="grid size-6 place-items-center rounded-sm bg-primary text-xs font-semibold text-primary-fg">K</span>
Kaveri Foods
<ChevronDown className="ml-auto size-3.5 text-fg-subtle" aria-hidden />
</button>
<nav className="grid gap-0.5">
{nav.map(({ label, icon: Icon, href, current, count }) => (
<a
key={label}
href={href}
aria-current={current ? "page" : undefined}
className={cn(
"flex h-8 items-center gap-2.5 rounded px-2 font-medium text-fg-muted transition hover:bg-surface-2 hover:text-fg",
current && "bg-bg text-fg shadow-sm ring-1 ring-border",
)}
>
<Icon className="size-4" aria-hidden />
{label}
{count && <span className="ml-auto text-xs tabular-nums text-fg-subtle">{count}</span>}
</a>
))}
</nav>
<div className="mt-auto flex items-center gap-2 border-t border-border px-1 pt-3">
<span className="grid size-7 place-items-center rounded-full bg-primary-soft text-[11px] font-medium text-primary-soft-fg">AR</span>
<div className="leading-tight"><p className="font-medium">Asha Rao</p><p className="text-xs text-fg-subtle">Owner</p></div>
</div>
</aside>
<div className="flex min-w-0 flex-1 flex-col">
<header className="flex h-14 items-center gap-3 border-b border-border px-4 sm:px-6">
<p className="font-medium">Overview</p>
<label className="ml-auto hidden h-9 w-64 items-center gap-2 rounded border border-border bg-surface px-2.5 text-fg-subtle md:flex">
<Search className="size-4" aria-hidden />
<input placeholder="Search invoices, customers" className="w-full bg-transparent text-[13px] text-fg outline-none placeholder:text-fg-subtle" />
</label>
<button type="button" aria-label="Notifications" className="relative grid size-9 place-items-center rounded text-fg-muted hover:bg-surface-2 hover:text-fg">
<Bell className="size-4" aria-hidden />
<span className="absolute right-2 top-2 size-1.5 rounded-full bg-danger ring-2 ring-bg" />
</button>
<button type="button" className="inline-flex h-9 items-center gap-1.5 rounded bg-primary px-3 font-medium text-primary-fg hover:bg-primary-hover">
<Plus className="size-4" aria-hidden /> New invoice
</button>
</header>
<main className="grid gap-4 p-4 sm:p-6">
<div className="flex flex-wrap items-end justify-between gap-3">
<div>
<h1 className="text-xl font-medium tracking-tight">Good morning, Asha</h1>
<p className="text-fg-muted">Here’s where your money stands for October.</p>
</div>
<button type="button" className="inline-flex h-9 items-center gap-1.5 rounded border border-border-strong bg-bg px-3 font-medium hover:bg-surface">
<Download className="size-4" aria-hidden /> Export
</button>
</div>
<section aria-label="Key figures" className="grid grid-cols-2 gap-3 xl:grid-cols-4">
{kpis.map((k) => (
<div key={k.label} className="rounded-lg border border-border p-4">
<p className="text-xs text-fg-muted">{k.label}</p>
<p className="mt-1 text-2xl font-medium tracking-tight tabular-nums">{k.value}</p>
<p className={cn("mt-1 text-xs font-medium tabular-nums",
k.tone === "up" ? "text-success-fg" : k.tone === "down" ? "text-danger-fg" : "text-fg-subtle")}>{k.note}</p>
</div>
))}
</section>
<div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_288px]">
<section aria-labelledby="chart-title" className="rounded-lg border border-border">
<div className="flex items-center gap-3 border-b border-border px-4 py-3">
<h2 id="chart-title" className="font-medium">Invoiced vs collected</h2>
<div className="ml-auto flex gap-3 text-xs text-fg-muted">
<span className="flex items-center gap-1.5"><i className="size-2 rounded-sm bg-primary/30" />Invoiced</span>
<span className="flex items-center gap-1.5"><i className="size-2 rounded-sm bg-primary" />Collected</span>
</div>
</div>
<div className="flex h-48 items-end gap-2 px-4 pb-3 pt-4" role="img" aria-label="Monthly invoiced and collected amounts">
{months.map((m, i) => (
<div key={m} className="flex flex-1 flex-col items-center gap-1.5">
<div className="flex h-36 w-full items-end justify-center gap-0.5">
<span className="w-2.5 rounded-sm bg-primary/30" style={{ height: (invoiced[i] / max) * 100 + "%" }} />
<span className="w-2.5 rounded-sm bg-primary" style={{ height: (collected[i] / max) * 100 + "%" }} />
</div>
<span className="text-[11px] text-fg-subtle">{m}</span>
</div>
))}
</div>
</section>
<section aria-labelledby="due-title" className="rounded-lg border border-border">
<div className="flex items-center justify-between border-b border-border px-4 py-3">
<h2 id="due-title" className="font-medium">Due in 7 days</h2>
<span className="rounded-full bg-surface-2 px-2 py-0.5 text-xs font-medium tabular-nums text-fg-muted">₹1,37,500</span>
</div>
<ul className="divide-y divide-border">
{dueThisWeek.map((d) => (
<li key={d.customer} className="flex items-center gap-3 px-4 py-2.5">
<div className="min-w-0"><p className="truncate font-medium">{d.customer}</p><p className="text-xs text-fg-subtle">{d.day}</p></div>
<span className="ml-auto font-medium tabular-nums">{d.amount}</span>
</li>
))}
</ul>
</section>
</div>
<section aria-labelledby="recent-title" className="overflow-hidden rounded-lg border border-border">
<div className="flex items-center justify-between border-b border-border px-4 py-3">
<h2 id="recent-title" className="font-medium">Recent invoices</h2>
<a href="/invoices" className="text-[13px] font-medium text-primary hover:underline">View all</a>
</div>
<div className="overflow-x-auto">
<table className="w-full text-[13px]">
<thead className="bg-surface text-left text-xs text-fg-subtle">
<tr>
<th className="px-4 py-2 font-medium">Invoice</th><th className="px-4 py-2 font-medium">Customer</th>
<th className="px-4 py-2 font-medium">Issued</th><th className="px-4 py-2 font-medium">Due</th>
<th className="px-4 py-2 text-right font-medium">Amount</th><th className="px-4 py-2 font-medium">Status</th>
</tr>
</thead>
<tbody className="divide-y divide-border">
{invoices.map((inv) => (
<tr key={inv.id} className="whitespace-nowrap hover:bg-surface">
<td className="px-4 py-2.5 tabular-nums text-fg-muted">{inv.id}</td>
<td className="px-4 py-2.5 font-medium">{inv.customer}</td>
<td className="px-4 py-2.5 text-fg-muted">{inv.issued}</td>
<td className="px-4 py-2.5 text-fg-muted">{inv.due}</td>
<td className="px-4 py-2.5 text-right font-medium tabular-nums">{inv.amount}</td>
<td className="px-4 py-2.5">
<span className={cn("inline-flex h-5 items-center gap-1.5 rounded-full px-2 text-xs font-medium", statusTone[inv.status])}>
<span className="size-1.5 rounded-full bg-current" />{inv.status}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
</main>
</div>
</div>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.