feat: add SVG icons for navigation and branding, configure Tailwind CSS, and set up TypeScript
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
"use client"
|
||||
|
||||
import { Eye, Pencil, Trash2 } from "lucide-react"
|
||||
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { DataTable, type DataTableColumn } from "@/components/ui/data-table"
|
||||
|
||||
const orders = [
|
||||
{ id: "#3210", customer: "John Martinez", date: "Jul 4, 2026", status: "Paid", items: 3, amount: 245.0 },
|
||||
{ id: "#3209", customer: "Aisha Khan", date: "Jul 3, 2026", status: "Pending", items: 1, amount: 89.5 },
|
||||
{ id: "#3208", customer: "Liam Chen", date: "Jul 3, 2026", status: "Paid", items: 5, amount: 512.2 },
|
||||
{ id: "#3207", customer: "Sofia Rossi", date: "Jul 2, 2026", status: "Cancelled", items: 2, amount: 64.0 },
|
||||
{ id: "#3206", customer: "Noah Williams", date: "Jul 1, 2026", status: "Paid", items: 4, amount: 178.9 },
|
||||
{ id: "#3205", customer: "Emma Garcia", date: "Jun 30, 2026", status: "Paid", items: 2, amount: 132.4 },
|
||||
{ id: "#3204", customer: "Yuki Tanaka", date: "Jun 30, 2026", status: "Pending", items: 6, amount: 340.75 },
|
||||
{ id: "#3203", customer: "Priya Patel", date: "Jun 29, 2026", status: "Paid", items: 1, amount: 42.0 },
|
||||
{ id: "#3202", customer: "Lucas Silva", date: "Jun 28, 2026", status: "Cancelled", items: 3, amount: 97.6 },
|
||||
{ id: "#3201", customer: "Olivia Brown", date: "Jun 27, 2026", status: "Paid", items: 4, amount: 210.3 },
|
||||
{ id: "#3200", customer: "Mateo Alvarez", date: "Jun 26, 2026", status: "Paid", items: 2, amount: 88.0 },
|
||||
{ id: "#3199", customer: "Grace Kim", date: "Jun 25, 2026", status: "Pending", items: 5, amount: 265.5 },
|
||||
] as const
|
||||
|
||||
type Order = (typeof orders)[number]
|
||||
|
||||
const statusStyles: Record<Order["status"], string> = {
|
||||
Paid: "bg-emerald-50 text-emerald-700",
|
||||
Pending: "bg-amber-50 text-amber-700",
|
||||
Cancelled: "bg-rose-50 text-rose-700",
|
||||
}
|
||||
|
||||
// Use a fixed locale to avoid hydration mismatches between server and client
|
||||
const currency = new Intl.NumberFormat("en-US", {
|
||||
style: "currency",
|
||||
currency: "USD",
|
||||
})
|
||||
|
||||
const columns: DataTableColumn<Order>[] = [
|
||||
{
|
||||
key: "id",
|
||||
header: "Order",
|
||||
cell: (order) => <span className="font-medium text-slate-900">{order.id}</span>,
|
||||
},
|
||||
{
|
||||
key: "customer",
|
||||
header: "Customer",
|
||||
cell: (order) => order.customer,
|
||||
},
|
||||
{
|
||||
key: "date",
|
||||
header: "Date",
|
||||
cell: (order) => order.date,
|
||||
headerClassName: "hidden sm:table-cell",
|
||||
cellClassName: "hidden text-muted-foreground sm:table-cell",
|
||||
},
|
||||
{
|
||||
key: "items",
|
||||
header: "Items",
|
||||
cell: (order) => order.items,
|
||||
headerClassName: "hidden md:table-cell",
|
||||
cellClassName: "hidden text-muted-foreground md:table-cell",
|
||||
},
|
||||
{
|
||||
key: "status",
|
||||
header: "Status",
|
||||
cell: (order) => <Badge className={statusStyles[order.status]}>{order.status}</Badge>,
|
||||
},
|
||||
{
|
||||
key: "amount",
|
||||
header: "Amount",
|
||||
cell: (order) => currency.format(order.amount),
|
||||
headerClassName: "text-right",
|
||||
cellClassName: "text-right font-medium text-slate-900",
|
||||
},
|
||||
]
|
||||
|
||||
export function RecentOrdersTable() {
|
||||
return (
|
||||
<div className="rounded-2xl bg-white p-5 shadow-sm ring-1 ring-black/5">
|
||||
<h2 className="mb-4 text-lg font-bold tracking-tight text-slate-900">Recent Orders</h2>
|
||||
|
||||
<DataTable
|
||||
data={orders}
|
||||
columns={columns}
|
||||
getRowId={(order) => order.id}
|
||||
searchAccessor={(order) => `${order.id} ${order.customer}`}
|
||||
searchPlaceholder="Search orders..."
|
||||
filters={[
|
||||
{
|
||||
key: "status",
|
||||
label: "Status",
|
||||
options: ["Paid", "Pending", "Cancelled"],
|
||||
accessor: (order) => order.status,
|
||||
},
|
||||
]}
|
||||
pageSize={5}
|
||||
actions={(order) => (
|
||||
<div className="flex items-center justify-end gap-1">
|
||||
<button
|
||||
type="button"
|
||||
aria-label={`View ${order.id}`}
|
||||
className="flex size-8 items-center justify-center rounded-full text-slate-500 hover:bg-slate-50 hover:text-slate-700"
|
||||
>
|
||||
<Eye className="size-4" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={`Edit ${order.id}`}
|
||||
className="flex size-8 items-center justify-center rounded-full text-slate-500 hover:bg-slate-50 hover:text-slate-700"
|
||||
>
|
||||
<Pencil className="size-4" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={`Delete ${order.id}`}
|
||||
className="flex size-8 items-center justify-center rounded-full text-rose-500 hover:bg-rose-50"
|
||||
>
|
||||
<Trash2 className="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user