"use client"; import { BarChart3, Bell, Box, ChevronLeft, ChevronRight, ChevronsUpDown, ClipboardList, Download, Globe, HelpCircle, LayoutDashboard, LogOut, MessageSquare, Minus, MoreHorizontal, Package, RotateCcw, Settings, TrendingDown, TrendingUp, Truck, User, Users, Wallet, } from "lucide-react"; import * as React from "react"; import type { TooltipProps } from "recharts"; import { Bar, BarChart, CartesianGrid, Line, LineChart, Tooltip, XAxis, YAxis, } from "recharts"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card"; import { type ChartConfig, ChartContainer } from "@/components/ui/chart"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarTrigger, } from "@/components/ui/sidebar"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { TooltipProvider } from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; type NavItem = { label: string; icon: React.ComponentType>; href: string; isActive?: boolean; children?: NavItem[]; }; type NavGroup = { title: string; items: NavItem[]; defaultOpen?: boolean; }; type UserData = { name: string; email: string; avatar: string; }; type SidebarData = { logo: { src: string; alt: string; title: string; description: string; }; navGroups: NavGroup[]; footerGroup: NavGroup; user?: UserData; }; type RichMetricStatItem = { title: string; value: number; trendValue: number; footerDelta: number; footerSubtextCount: number; }; type OrderStatus = "Processing" | "Shipped" | "Delivered" | "Cancelled"; type Order = { id: string; orderNumber: string; customer: string; total: number; status: OrderStatus; }; type FulfillmentItem = { order: string; shipped: Date; progress: number; segments: number[]; }; const currencyFormatter = new Intl.NumberFormat("fa-IR", { style: "currency", currency: "IRR", }); const numberFormatter = new Intl.NumberFormat("fa-IR"); const trendPercentFormatter = new Intl.NumberFormat("fa-IR", { style: "percent", maximumFractionDigits: 1, signDisplay: "exceptZero", }); const compactCurrencyFormatter = new Intl.NumberFormat("fa-IR", { style: "currency", currency: "IRR", notation: "compact", maximumFractionDigits: 0, }); const monthFormatter = new Intl.DateTimeFormat("fa-IR", { month: "short" }); const dashboardRangeFormatter = new Intl.DateTimeFormat("fa-IR", { month: "short", day: "numeric", year: "numeric", }); const dashboardRangeStart = new Date(2025, 0, 1); const dashboardRangeEnd = new Date(2025, 0, 31); const dashboardDateRangeLabel = typeof dashboardRangeFormatter.formatRange === "function" ? dashboardRangeFormatter.formatRange( dashboardRangeStart, dashboardRangeEnd, ) : `${dashboardRangeFormatter.format( dashboardRangeStart, )} – ${dashboardRangeFormatter.format(dashboardRangeEnd)}`; const shippedDateFormatter = new Intl.DateTimeFormat("fa-IR", { month: "short", day: "numeric", year: "numeric", }); const orderStatusLabels: Record = { Processing: "در حال پردازش", Shipped: "ارسال‌شده", Delivered: "تحویل‌شده", Cancelled: "لغوشده", }; const formatTrendValue = (trendValue: number) => { return trendPercentFormatter.format(trendValue / 100); }; const mixBase = "var(--background)"; const palette = { primary: "var(--primary)", secondary: { light: `color-mix(in oklch, var(--primary) 75%, ${mixBase})`, dark: `color-mix(in oklch, var(--primary) 85%, ${mixBase})`, }, tertiary: { light: `color-mix(in oklch, var(--primary) 55%, ${mixBase})`, dark: `color-mix(in oklch, var(--primary) 65%, ${mixBase})`, }, quaternary: { light: `color-mix(in oklch, var(--primary) 40%, ${mixBase})`, dark: `color-mix(in oklch, var(--primary) 45%, ${mixBase})`, }, }; const sidebarData: SidebarData = { logo: { src: "/block-media/shadcnblocks/block/logos/NovaSales-logo.svg", alt: "فروشگاه آکمه", title: "ری یو آی Store", description: "فروشگاه آنلاین", }, navGroups: [ { title: "اصلی", defaultOpen: true, items: [ { label: "داشبورد", icon: LayoutDashboard, href: "#", isActive: true, }, { label: "سفارش‌ها", icon: ClipboardList, href: "#" }, { label: "مرجوعی‌ها", icon: RotateCcw, href: "#" }, ], }, { title: "کاتالوگ", defaultOpen: true, items: [ { label: "محصولات", icon: Box, href: "#", children: [ { label: "همه محصولات", icon: Package, href: "#" }, { label: "دسته‌بندی‌ها", icon: Package, href: "#" }, { label: "موجودی", icon: Package, href: "#" }, ], }, { label: "ارسال", icon: Truck, href: "#" }, ], }, { title: "مشتریان", defaultOpen: false, items: [ { label: "همه مشتریان", icon: Users, href: "#" }, { label: "پیام‌ها", icon: MessageSquare, href: "#" }, ], }, { title: "تحلیل فروش", defaultOpen: false, items: [ { label: "نمای کلی", icon: Globe, href: "#" }, { label: "گزارش‌ها", icon: BarChart3, href: "#" }, { label: "امور مالی", icon: Wallet, href: "#" }, ], }, ], footerGroup: { title: "تنظیمات", items: [{ label: "تنظیمات", icon: Settings, href: "#" }], }, user: { name: "علی رضایی", email: "john@acme.store", avatar: "/block-media/shadcnblocks/block/avatar-8.webp", }, }; const richMetricStats: RichMetricStatItem[] = [ { title: "فروش حضوری", value: 7820.75, trendValue: 4.3, footerDelta: 322.5, footerSubtextCount: 5000, }, { title: "فروش آنلاین", value: 985_937.45, trendValue: 12.5, footerDelta: 109_500, footerSubtextCount: 21_000, }, { title: "عمده‌فروشی", value: 124_650, trendValue: 6.8, footerDelta: 7_935, footerSubtextCount: 890, }, ]; const monthLabel = (monthIndex: number) => monthFormatter.format(new Date(2025, monthIndex, 1)); const salesPipelineData: Record< string, { week: string; month: string; orders: number; sales: number }[] > = { q1: [ { week: "W1", month: monthLabel(0), orders: 220, sales: 5100 }, { week: "W2", month: monthLabel(0), orders: 480, sales: 11200 }, { week: "W3", month: monthLabel(0), orders: 390, sales: 9400 }, { week: "W4", month: monthLabel(0), orders: 150, sales: 3600 }, { week: "W5", month: monthLabel(1), orders: 310, sales: 7400 }, { week: "W6", month: monthLabel(1), orders: 540, sales: 13100 }, { week: "W7", month: monthLabel(1), orders: 460, sales: 10800 }, { week: "W8", month: monthLabel(1), orders: 200, sales: 4700 }, { week: "W9", month: monthLabel(2), orders: 130, sales: 3100 }, { week: "W10", month: monthLabel(2), orders: 420, sales: 10200 }, { week: "W11", month: monthLabel(2), orders: 510, sales: 12400 }, { week: "W12", month: monthLabel(2), orders: 350, sales: 8500 }, ], q2: [ { week: "W1", month: monthLabel(3), orders: 410, sales: 9800 }, { week: "W2", month: monthLabel(3), orders: 280, sales: 6700 }, { week: "W3", month: monthLabel(3), orders: 120, sales: 2900 }, { week: "W4", month: monthLabel(3), orders: 350, sales: 8400 }, { week: "W5", month: monthLabel(4), orders: 520, sales: 12600 }, { week: "W6", month: monthLabel(4), orders: 470, sales: 11300 }, { week: "W7", month: monthLabel(4), orders: 190, sales: 4500 }, { week: "W8", month: monthLabel(4), orders: 100, sales: 2400 }, { week: "W9", month: monthLabel(5), orders: 330, sales: 7900 }, { week: "W10", month: monthLabel(5), orders: 490, sales: 11800 }, { week: "W11", month: monthLabel(5), orders: 540, sales: 13000 }, { week: "W12", month: monthLabel(5), orders: 260, sales: 6200 }, ], q3: [ { week: "W1", month: monthLabel(6), orders: 180, sales: 4200 }, { week: "W2", month: monthLabel(6), orders: 520, sales: 12800 }, { week: "W3", month: monthLabel(6), orders: 480, sales: 11500 }, { week: "W4", month: monthLabel(6), orders: 120, sales: 2800 }, { week: "W5", month: monthLabel(7), orders: 90, sales: 2100 }, { week: "W6", month: monthLabel(7), orders: 450, sales: 10500 }, { week: "W7", month: monthLabel(7), orders: 510, sales: 12200 }, { week: "W8", month: monthLabel(7), orders: 480, sales: 11000 }, { week: "W9", month: monthLabel(8), orders: 200, sales: 4800 }, { week: "W10", month: monthLabel(8), orders: 150, sales: 3500 }, { week: "W11", month: monthLabel(8), orders: 380, sales: 9200 }, { week: "W12", month: monthLabel(8), orders: 420, sales: 10100 }, ], q4: [ { week: "W1", month: monthLabel(9), orders: 300, sales: 7200 }, { week: "W2", month: monthLabel(9), orders: 160, sales: 3800 }, { week: "W3", month: monthLabel(9), orders: 440, sales: 10600 }, { week: "W4", month: monthLabel(9), orders: 530, sales: 12900 }, { week: "W5", month: monthLabel(10), orders: 380, sales: 9100 }, { week: "W6", month: monthLabel(10), orders: 140, sales: 3400 }, { week: "W7", month: monthLabel(10), orders: 250, sales: 6000 }, { week: "W8", month: monthLabel(10), orders: 500, sales: 12100 }, { week: "W9", month: monthLabel(11), orders: 550, sales: 13300 }, { week: "W10", month: monthLabel(11), orders: 470, sales: 11400 }, { week: "W11", month: monthLabel(11), orders: 210, sales: 5000 }, { week: "W12", month: monthLabel(11), orders: 340, sales: 8200 }, ], }; const fullYearData = [ { monthIndex: 0, thisYear: 42000, prevYear: 38000 }, { monthIndex: 1, thisYear: 38000, prevYear: 45000 }, { monthIndex: 2, thisYear: 52000, prevYear: 41000 }, { monthIndex: 3, thisYear: 45000, prevYear: 48000 }, { monthIndex: 4, thisYear: 58000, prevYear: 44000 }, { monthIndex: 5, thisYear: 41000, prevYear: 52000 }, { monthIndex: 6, thisYear: 55000, prevYear: 47000 }, { monthIndex: 7, thisYear: 48000, prevYear: 53000 }, { monthIndex: 8, thisYear: 62000, prevYear: 49000 }, { monthIndex: 9, thisYear: 54000, prevYear: 58000 }, { monthIndex: 10, thisYear: 67000, prevYear: 52000 }, { monthIndex: 11, thisYear: 71000, prevYear: 61000 }, ].map(({ monthIndex, ...entry }) => ({ month: monthLabel(monthIndex), ...entry, })); type TimePeriod = "6months" | "year"; const periodLabels: Record = { "6months": "۶ ماه اخیر", year: "سال گذشته", }; function getDataForPeriod(period: TimePeriod) { if (period === "6months") { return fullYearData.slice(0, 6); } return fullYearData; } const orderStatuses: OrderStatus[] = [ "Processing", "Shipped", "Delivered", "Cancelled", ]; const statusStyles: Record = { Processing: "bg-amber-50 text-amber-700 ring-1 ring-inset ring-amber-600/20 dark:bg-amber-900/30 dark:text-amber-400 dark:ring-amber-400/20", Shipped: "bg-blue-50 text-blue-700 ring-1 ring-inset ring-blue-700/10 dark:bg-blue-900/30 dark:text-blue-400 dark:ring-blue-400/20", Delivered: "bg-emerald-50 text-emerald-700 ring-1 ring-inset ring-emerald-600/20 dark:bg-emerald-900/30 dark:text-emerald-400 dark:ring-emerald-400/20", Cancelled: "bg-red-50 text-red-700 ring-1 ring-inset ring-red-600/10 dark:bg-red-900/30 dark:text-red-400 dark:ring-red-400/20", }; const orders: Order[] = [ { id: "1", orderNumber: "ORD-2024-001", customer: "Sarah Johnson", status: "Delivered", total: 2499.0, }, { id: "2", orderNumber: "ORD-2024-002", customer: "Michael Chen", status: "Shipped", total: 1348.0, }, { id: "3", orderNumber: "ORD-2024-003", customer: "Emma Wilson", status: "Processing", total: 1198.0, }, { id: "4", orderNumber: "ORD-2024-004", customer: "James Rodriguez", status: "Delivered", total: 799.0, }, { id: "5", orderNumber: "ORD-2024-005", customer: "Lisa Park", status: "Cancelled", total: 599.0, }, { id: "6", orderNumber: "ORD-2024-006", customer: "David Kim", status: "Shipped", total: 5498.0, }, { id: "7", orderNumber: "ORD-2024-007", customer: "Anna Martinez", status: "Delivered", total: 1199.0, }, { id: "8", orderNumber: "ORD-2024-008", customer: "Robert Taylor", status: "Processing", total: 1128.0, }, { id: "9", orderNumber: "ORD-2024-009", customer: "Jennifer Lee", status: "Shipped", total: 449.0, }, { id: "10", orderNumber: "ORD-2024-010", customer: "William Brown", status: "Delivered", total: 2199.0, }, { id: "11", orderNumber: "ORD-2024-011", customer: "Sophia Davis", status: "Cancelled", total: 349.0, }, { id: "12", orderNumber: "ORD-2024-012", customer: "Daniel Garcia", status: "Processing", total: 899.0, }, ]; const fulfillmentData: FulfillmentItem[] = [ { order: "ORD-4821", shipped: new Date(2025, 0, 27), progress: 92, segments: [ 0.9, 0.7, 1.0, 0.8, 0.6, 0.9, 1.0, 0.7, 0.5, 0.8, 0.9, 1.0, 0.6, 0.7, 0.8, 0.9, 1.0, 0.5, 0.7, 0.8, 0.9, 0.6, 1.0, 0.8, 0.7, 0.3, 0.2, 0.1, 0.1, 0.1, ], }, { order: "ORD-4819", shipped: new Date(2025, 0, 26), progress: 78, segments: [ 0.8, 0.6, 0.9, 0.7, 1.0, 0.5, 0.8, 0.9, 0.6, 0.7, 1.0, 0.8, 0.5, 0.9, 0.7, 0.6, 0.8, 1.0, 0.7, 0.5, 0.2, 0.1, 0.15, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, ], }, { order: "ORD-4815", shipped: new Date(2025, 0, 25), progress: 100, segments: [ 1.0, 0.9, 0.8, 1.0, 0.7, 0.9, 1.0, 0.8, 0.6, 0.9, 1.0, 0.7, 0.8, 0.9, 1.0, 0.6, 0.8, 0.9, 1.0, 0.7, 0.9, 0.8, 1.0, 0.6, 0.9, 0.7, 1.0, 0.8, 0.9, 1.0, ], }, { order: "ORD-4812", shipped: new Date(2025, 0, 24), progress: 65, segments: [ 0.9, 1.0, 0.7, 0.8, 0.6, 0.9, 0.5, 0.8, 1.0, 0.7, 0.9, 0.6, 0.8, 0.5, 0.7, 1.0, 0.6, 0.9, 0.8, 0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, ], }, { order: "ORD-4808", shipped: new Date(2025, 0, 23), progress: 43, segments: [ 0.8, 0.7, 1.0, 0.6, 0.9, 0.8, 0.5, 0.7, 1.0, 0.9, 0.6, 0.8, 0.7, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, ], }, { order: "ORD-4805", shipped: new Date(2025, 0, 22), progress: 100, segments: [ 0.9, 0.8, 1.0, 0.7, 0.9, 0.6, 1.0, 0.8, 0.7, 0.9, 1.0, 0.8, 0.6, 0.9, 0.7, 1.0, 0.8, 0.9, 0.7, 1.0, 0.8, 0.9, 0.6, 1.0, 0.7, 0.8, 0.9, 1.0, 0.8, 0.9, ], }, { order: "ORD-4801", shipped: new Date(2025, 0, 21), progress: 88, segments: [ 1.0, 0.8, 0.7, 0.9, 0.6, 1.0, 0.8, 0.5, 0.9, 0.7, 1.0, 0.8, 0.6, 0.9, 0.7, 0.8, 1.0, 0.6, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, ], }, { order: "ORD-4798", shipped: new Date(2025, 0, 20), progress: 55, segments: [ 0.7, 0.9, 1.0, 0.6, 0.8, 0.9, 0.7, 1.0, 0.5, 0.8, 0.6, 0.9, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, ], }, { order: "ORD-4794", shipped: new Date(2025, 0, 19), progress: 100, segments: [ 0.8, 1.0, 0.9, 0.7, 0.8, 1.0, 0.6, 0.9, 0.8, 1.0, 0.7, 0.9, 0.8, 1.0, 0.6, 0.9, 0.7, 1.0, 0.8, 0.9, 0.7, 1.0, 0.8, 0.6, 0.9, 1.0, 0.7, 0.8, 0.9, 1.0, ], }, { order: "ORD-4790", shipped: new Date(2025, 0, 18), progress: 71, segments: [ 0.9, 0.6, 0.8, 1.0, 0.7, 0.9, 0.5, 0.8, 1.0, 0.6, 0.9, 0.7, 0.8, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, ], }, { order: "ORD-4786", shipped: new Date(2025, 0, 17), progress: 35, segments: [ 1.0, 0.8, 0.9, 0.7, 0.6, 0.8, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, ], }, { order: "ORD-4782", shipped: new Date(2025, 0, 16), progress: 96, segments: [ 0.8, 0.9, 1.0, 0.7, 0.8, 0.9, 1.0, 0.6, 0.8, 0.9, 1.0, 0.7, 0.9, 0.8, 1.0, 0.6, 0.9, 0.7, 1.0, 0.8, 0.9, 0.6, 1.0, 0.8, 0.7, 0.9, 1.0, 0.8, 0.3, 0.1, ], }, ]; const ordersBarConfig = { orders: { label: "سفارش‌ها", color: palette.primary }, } satisfies ChartConfig; const salesBarConfig = { sales: { label: "فروش", theme: palette.secondary }, } satisfies ChartConfig; const createHighlightBarShape = (fill: string) => (props: unknown) => { const { x, y, width, height, index } = props as { x: number; y: number; width: number; height: number; index: number; }; const isHighlight = index === 5; return ( ); }; const revenueFlowChartConfig = { thisYear: { label: "امسال", color: palette.primary }, prevYear: { label: "سال قبل", theme: palette.secondary }, } satisfies ChartConfig; const tableHeadClass = "text-xs font-medium text-muted-foreground sm:text-sm"; const SidebarLogo = ({ logo }: { logo: SidebarData["logo"] }) => { return (
{logo.alt}
{logo.title} {logo.description}
); }; const NavMenuItem = ({ item }: { item: NavItem }) => { const Icon = item.icon; const hasChildren = item.children && item.children.length > 0; if (!hasChildren) { return ( ); } return ( {item.children!.map((child) => ( {child.label} ))} ); }; const NavUser = ({ user }: { user: UserData }) => { return ( {user.name .split(" ") .map((n) => n[0]) .join("")}
{user.name} {user.email}
{user.name .split(" ") .map((n) => n[0]) .join("")}
{user.name} {user.email}
); }; const AppSidebar = ({ ...props }: React.ComponentProps) => { return (
{sidebarData.navGroups.map((group) => ( {group.title} {group.items.map((item) => ( ))} ))} {sidebarData.user && }
); }; const DashboardHeader = () => { return (

نمای کلی داشبورد

خلاصه‌ای از خریدها، فروش‌ها و سایر شاخص‌ها

{dashboardDateRangeLabel}
); }; const AccountingStatsCards = () => { return (
{richMetricStats.map((stat) => { const isPositive = stat.trendValue > 0; const isNeutral = stat.trendValue === 0; const Icon = isNeutral ? Minus : isPositive ? TrendingUp : TrendingDown; const trendClass = isNeutral ? "text-foreground bg-muted" : isPositive ? "text-success border-success/20 bg-success/10" : "text-destructive border-destructive/20 bg-destructive/10"; const formattedTrend = formatTrendValue(stat.trendValue); const deltaPrefix = stat.footerDelta > 0 ? "+" : stat.footerDelta < 0 ? "-" : ""; const footerLabel = `${deltaPrefix}${currencyFormatter.format( Math.abs(stat.footerDelta), )} نسبت به ماه قبل`; const footerSubtext = `بر اساس ${numberFormatter.format( stat.footerSubtextCount, )} سفارش`; return (
{stat.title} {currencyFormatter.format(stat.value)}
{footerLabel}
{footerSubtext}
); })}
); }; function PipelineTooltip({ active, payload, label, valueFormatter, }: any & { valueFormatter: (v: number) => string; }) { if (!active || !payload?.length) return null; const entry = payload[0]; return (

{label}

{valueFormatter(Number(entry.value))}

); } const SalesPipelineChart = () => { const [searchParams, setSearchParams] = React.useState( () => new URLSearchParams( typeof window !== "undefined" ? window.location.search : "", ), ); const quarter = searchParams.get("quarter") ?? "q1"; const handleQuarterChange = (value: string) => { const next = new URLSearchParams(searchParams); next.set("quarter", value); setSearchParams(next); window.history.replaceState(null, "", `?${next.toString()}`); }; const data = salesPipelineData[quarter] ?? salesPipelineData.q1; const totalOrders = data.reduce((sum, d) => sum + d.orders, 0); const totalSales = data.reduce((sum, d) => sum + d.sales, 0); return (

قیف فروش

{numberFormatter.format(totalOrders)}

مجموع سفارش‌ها

numberFormatter.format(v)} /> } />

{compactCurrencyFormatter.format(totalSales)}

مجموع فروش

currencyFormatter.format(v)} /> } />
); }; function CustomTooltip({ active, payload, label, colors, }: any & { colors: { primary: string; secondary: string }; }) { if (!active || !payload?.length) return null; const thisYear = payload.find((p: any) => p.dataKey === "thisYear")?.value || 0; const prevYear = payload.find((p: any) => p.dataKey === "prevYear")?.value || 0; const diff = Number(thisYear) - Number(prevYear); const percentage = prevYear ? Math.round((diff / Number(prevYear)) * 100) : 0; const currentYear = new Date().getFullYear(); return (

{label}, {currentYear}

امسال: {currencyFormatter.format(Number(thisYear))}
سال قبل: {currencyFormatter.format(Number(prevYear))}
= 0 ? "text-emerald-500" : "text-red-500", )} > {diff >= 0 ? "+" : ""} {percentage.toLocaleString("fa-IR")}٪ نسبت به سال قبل
); } const RevenueFlowChart = () => { const [period, setPeriod] = React.useState("year"); React.useEffect(() => { if (typeof window === "undefined") return; const params = new URLSearchParams(window.location.search); const nextPeriod = params.get("period"); if (nextPeriod === "6months" || nextPeriod === "year") { setPeriod(nextPeriod); } }, []); React.useEffect(() => { if (typeof window === "undefined") return; const params = new URLSearchParams(window.location.search); if (period !== "year") { params.set("period", period); } else { params.delete("period"); } const nextQuery = params.toString(); const nextUrl = nextQuery ? `${window.location.pathname}?${nextQuery}` : window.location.pathname; window.history.replaceState(null, "", nextUrl); }, [period]); const chartData = getDataForPeriod(period); const totalRevenue = chartData.reduce((acc, item) => acc + item.thisYear, 0); return (

{currencyFormatter.format(totalRevenue)}

درآمد کل ({periodLabels[period]})

امسال
سال قبل
بازه زمانی {(Object.keys(periodLabels) as TimePeriod[]).map((key) => ( setPeriod(key)} > {periodLabels[key]} ))}
compactCurrencyFormatter.format(value)} width={40} /> } cursor={{ strokeOpacity: 0.2 }} />
); }; const RecentOrdersTable = () => { const [statusFilter, setStatusFilter] = React.useState( "all", ); const [currentPage, setCurrentPage] = React.useState(1); const [isHydrated, setIsHydrated] = React.useState(false); const pageSize = 6; React.useEffect(() => { if (typeof window === "undefined") return; const params = new URLSearchParams(window.location.search); const nextStatus = params.get("status"); if ( nextStatus && (nextStatus === "all" || orderStatuses.includes(nextStatus as OrderStatus)) ) { setStatusFilter(nextStatus as OrderStatus | "all"); } const nextPage = Number(params.get("page")); if (!Number.isNaN(nextPage) && nextPage > 0) { setCurrentPage(nextPage); } setIsHydrated(true); }, []); const filteredOrders = React.useMemo(() => { if (statusFilter === "all") return orders; return orders.filter((order) => order.status === statusFilter); }, [statusFilter]); const totalPages = Math.max(1, Math.ceil(filteredOrders.length / pageSize)); const paginatedOrders = React.useMemo(() => { const startIndex = (currentPage - 1) * pageSize; return filteredOrders.slice(startIndex, startIndex + pageSize); }, [filteredOrders, currentPage, pageSize]); React.useEffect(() => { setCurrentPage(1); }, [statusFilter]); React.useEffect(() => { if (!isHydrated || typeof window === "undefined") return; const params = new URLSearchParams(window.location.search); if (statusFilter !== "all") { params.set("status", statusFilter); } else { params.delete("status"); } if (currentPage > 1) { params.set("page", String(currentPage)); } else { params.delete("page"); } const nextQuery = params.toString(); const nextUrl = nextQuery ? `${window.location.pathname}?${nextQuery}` : window.location.pathname; window.history.replaceState(null, "", nextUrl); }, [statusFilter, currentPage, isHydrated]); const goToPage = (page: number) => { setCurrentPage(Math.max(1, Math.min(page, totalPages))); }; const startRow = filteredOrders.length ? (currentPage - 1) * pageSize + 1 : 0; const endRow = Math.min(currentPage * pageSize, filteredOrders.length); return (

سفارش‌های اخیر

{filteredOrders.length.toLocaleString("fa-IR")}
فیلتر بر اساس وضعیت setStatusFilter("all")} > همه وضعیت‌ها {orderStatuses.map((status) => ( setStatusFilter(status)} > {orderStatusLabels[status]} ))}
مرجع سفارش خریدار مجموع وضعیت {paginatedOrders.length === 0 ? ( سفارشی یافت نشد. ) : ( paginatedOrders.map((order) => ( {order.orderNumber} {order.customer} {currencyFormatter.format(order.total)} {orderStatusLabels[order.status]} )) )}
{filteredOrders.length === 0 ? "۰" : `${startRow.toLocaleString("fa-IR")}-${endRow.toLocaleString("fa-IR")}`}{" "} از {filteredOrders.length.toLocaleString("fa-IR")}
); }; const FulfillmentPanel = () => { return (

تکمیل سفارش

خروجی جدول مشاهده همه سفارش‌ها
سفارش وضعیت تحویل٪
{fulfillmentData.map((row) => (
{row.order}
{row.segments.slice(0, 15).map((opacity, i) => { const filled = i < Math.round((row.progress / 100) * 15); return (
); })}
{row.progress.toLocaleString("fa-IR")}
))}
); }; const DashboardContent = () => { return (
); }; const Dashboard9 = ({ className }: { className?: string }) => { return ( رفتن به محتوای اصلی ); }; export { Dashboard9 };