Files
ERP_Frontend/app/dashboard/page.tsx
T
2026-07-08 11:08:24 +05:30

327 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client"
import * as React from "react"
import { CheckCircle2, DollarSign, Package, Plus, ShoppingCart, Users } from "lucide-react"
import { cn } from "@/lib/utils"
import { RecentOrdersTable } from "@/components/dashboard/recent-orders-table"
import { Button } from "@/components/ui/button"
import { DatePicker, DateRangePicker } from "@/components/ui/date-picker"
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import {
AlertDialog,
AlertDialogContent,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import { StatCard } from "@/components/ui/stat-card"
import { toast } from "@/components/ui/toast"
import LineChart from "@/components/ui/line-chart"
import BarChart from "@/components/ui/bar-chart"
import PieChart from "@/components/ui/pie-chart"
const indigoButton =
"rounded-full bg-indigo-50 text-indigo-700 hover:bg-indigo-100 focus-visible:ring-indigo-300/40"
export default function DashboardPage() {
const [date, setDate] = React.useState<Date>()
const [range, setRange] = React.useState<{ from: Date | undefined; to?: Date | undefined }>()
return (
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-5 rounded-2xl bg-white p-4 shadow-sm ring-1 ring-black/5 sm:p-5">
<div>
<p className="mb-2 text-sm font-semibold text-slate-500">Breadcrumb</p>
<div className="flex flex-col gap-3">
{/* Basic */}
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/dashboard">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/dashboard/products">Products</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Product Detail</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
{/* With ellipsis */}
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/dashboard">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbEllipsis />
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/dashboard/products">Products</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Edit</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
</div>
<div>
<p className="mb-2 text-sm font-semibold text-slate-500">Variants</p>
<div className="flex flex-wrap gap-2">
<Button variant="default">Default</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="success">Success</Button>
<Button variant="warning">Warning</Button>
<Button variant="info">Info</Button>
<Button variant="link">Link</Button>
</div>
</div>
<div>
<p className="mb-2 text-sm font-semibold text-slate-500">Sizes</p>
<div className="flex flex-wrap items-center gap-3">
<Button size="xs" className={indigoButton}>
Extra Small
</Button>
<Button size="sm" className={indigoButton}>
Small
</Button>
<Button size="default" className={indigoButton}>
Default
</Button>
<Button size="lg" className={indigoButton}>
Large
</Button>
<Button size="lg" className={cn(indigoButton, "h-13 px-8 text-base")}>
Extra Large
</Button>
<Button size="icon-sm" className={indigoButton} aria-label="Add (small)">
<Plus />
</Button>
<Button size="icon" className={indigoButton} aria-label="Add">
<Plus />
</Button>
<Button size="icon-lg" className={indigoButton} aria-label="Add (large)">
<Plus />
</Button>
<Button
size="icon-lg"
className={cn(indigoButton, "size-13")}
aria-label="Add (extra large)"
>
<Plus className="size-6" />
</Button>
</div>
</div>
<div>
<p className="mb-2 text-sm font-semibold text-slate-500">Date Picker</p>
<div className="flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center">
<div className="flex flex-col gap-1">
<span className="text-xs text-slate-400">Single date</span>
<DatePicker
value={date}
onChange={setDate}
placeholder="Select a date"
/>
</div>
<div className="flex flex-col gap-1">
<span className="text-xs text-slate-400">Date range</span>
<DateRangePicker
value={range}
onChange={setRange}
placeholder="Select date range"
/>
</div>
</div>
{(date || range?.from) && (
<p className="mt-2 text-xs text-slate-500">
{date && <>Selected: <span className="font-medium text-slate-700">{date.toLocaleDateString()}</span></>}
{range?.from && (
<>
{date && " · "}
Range: <span className="font-medium text-slate-700">{range.from.toLocaleDateString()}</span>
{range.to && <> <span className="font-medium text-slate-700">{range.to.toLocaleDateString()}</span></>}
</>
)}
</p>
)}
</div>
<div>
<p className="mb-2 text-sm font-semibold text-slate-500">Modal</p>
<Dialog>
<DialogTrigger render={<Button variant="outline">Open Modal</Button>} />
<DialogContent className="w-[calc(100%-2rem)] sm:max-w-md">
<DialogHeader className="items-center gap-3 px-2 pt-4 text-center sm:px-4">
<div className="flex size-14 items-center justify-center rounded-full bg-emerald-50">
<CheckCircle2 className="size-7 text-emerald-600" />
</div>
<DialogTitle className="text-lg font-bold">Order confirmed</DialogTitle>
<DialogDescription>
Your order has been placed successfully and is now being processed.
</DialogDescription>
</DialogHeader>
<div className="flex justify-center px-2 pb-2 sm:px-4">
<Button size="lg" className="w-full rounded-full sm:w-auto sm:px-10">
Continue
</Button>
</div>
</DialogContent>
</Dialog>
</div>
<div>
<p className="mb-2 text-sm font-semibold text-slate-500">Toast</p>
<div className="flex flex-wrap gap-2">
<Button variant="outline" onClick={() => toast({ title: "Default toast message" })}>
Default
</Button>
<Button variant="success" onClick={() => toast.success("Success!", "Your changes have been saved.")}>
Success
</Button>
<Button variant="destructive" onClick={() => toast.error("Error", "Something went wrong. Please try again.")}>
Error
</Button>
<Button variant="warning" onClick={() => toast.warning("Warning", "This action cannot be undone.")}>
Warning
</Button>
<Button variant="info" onClick={() => toast.info("Info", "Your session will expire in 5 minutes.")}>
Info
</Button>
<Button
variant="secondary"
onClick={() =>
toast({
title: "With Action",
description: "Do you want to undo this change?",
actionLabel: "Undo",
onAction: () => toast.success("Undone!", "Change has been reverted."),
})
}
>
With Action
</Button>
</div>
</div>
</div>
<div className="flex flex-col gap-5 rounded-2xl bg-white p-4 shadow-sm ring-1 ring-black/5 sm:p-5">
<div>
<p className="mb-2 text-sm font-semibold text-slate-500">Alert Dialogs</p>
<div className="flex flex-wrap gap-2">
<AlertDialog>
<AlertDialogTrigger render={<Button variant="info">Info</Button>} />
<AlertDialogContent
variant="info"
title="Update available"
description="A new version is ready. Reload the page to apply the latest changes."
confirmLabel="Reload"
onConfirm={() => toast.info("Reloading...", "Applying the latest update.")}
/>
</AlertDialog>
<AlertDialog>
<AlertDialogTrigger render={<Button variant="success">Success</Button>} />
<AlertDialogContent
variant="success"
title="Order confirmed"
description="Your order has been placed successfully and is now being processed."
confirmLabel="Continue"
cancelLabel="View order"
onConfirm={() => toast.success("Done!", "Redirecting to dashboard.")}
/>
</AlertDialog>
<AlertDialog>
<AlertDialogTrigger render={<Button variant="warning">Warning</Button>} />
<AlertDialogContent
variant="warning"
title="Unsaved changes"
description="You have unsaved changes. Leaving this page will discard them."
confirmLabel="Leave anyway"
onConfirm={() => toast.warning("Changes discarded")}
/>
</AlertDialog>
<AlertDialog>
<AlertDialogTrigger render={<Button variant="destructive">Delete</Button>} />
<AlertDialogContent
variant="destructive"
title="Delete record?"
description="This action is permanent and cannot be undone. All associated data will be removed."
confirmLabel="Delete"
onConfirm={() => toast.error("Deleted", "The record has been permanently removed.")}
/>
</AlertDialog>
</div>
</div>
</div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
<StatCard label="Total Revenue" value={45231.89} icon={DollarSign} />
<StatCard label="Orders" value={1284} icon={ShoppingCart} />
<StatCard label="Customers" value={892} icon={Users} />
<StatCard label="Low Stock Items" value={16} icon={Package} />
</div>
<RecentOrdersTable />
<div className="mt-6 grid grid-cols-1 gap-4 lg:grid-cols-3">
<div className="rounded-2xl bg-white p-4 shadow-sm ring-1 ring-black/5">
<h3 className="mb-2 text-sm font-semibold text-slate-600">Sales (Line)</h3>
<div className="h-56">
<LineChart
labels={["Jan", "Feb", "Mar", "Apr", "May", "Jun"]}
datasets={[{ label: "Sales", data: [120, 200, 150, 220, 180, 260] }]}
/>
</div>
</div>
<div className="rounded-2xl bg-white p-4 shadow-sm ring-1 ring-black/5">
<h3 className="mb-2 text-sm font-semibold text-slate-600">Revenue (Bar)</h3>
<div className="h-56">
<BarChart
labels={["Q1", "Q2", "Q3", "Q4"]}
datasets={[{ label: "Revenue", data: [30000, 42000, 36000, 48000], backgroundColor: "#60a5fa" }]}
/>
</div>
</div>
<div className="rounded-2xl bg-white p-4 shadow-sm ring-1 ring-black/5">
<h3 className="mb-2 text-sm font-semibold text-slate-600">Product Mix (Pie)</h3>
<div className="h-56">
<PieChart labels={["A","B","C"]} data={[45, 30, 25]} />
</div>
</div>
</div>
</div>
)
}