"use client"; import { Activity, ArrowDownRight, ArrowUpRight, BarChart3, Bell, Building2, ChevronRight, ChevronsUpDown, CircleDollarSign, CreditCard, Download, FileText, Layers, LayoutDashboard, LineChart as LineChartIcon, LogOut, MoreHorizontal, Receipt, Search, Settings, TrendingDown, User, UserPlus, Users, Zap, } from "lucide-react"; import * as React from "react"; import type { TooltipContentProps } from "recharts"; import { Area, Bar, BarChart, CartesianGrid, Cell, ComposedChart, Line, LineChart, Pie, PieChart, ReferenceLine, Sector, Tooltip, XAxis, YAxis, } from "recharts"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; import { type ChartConfig, ChartContainer } from "@/components/ui/chart"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; 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 { TooltipProvider } from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; // ============================================================================ // Types // ============================================================================ 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; href: string; }; navGroups: NavGroup[]; footerGroup: NavGroup; user?: UserData; }; type StatItem = { title: string; previousValue: number; value: number; changePercent: number; isPositive: boolean; icon: React.ComponentType>; format: "currency" | "number"; }; // ============================================================================ // Formatting Helpers // ============================================================================ const currencyFormatter = new Intl.NumberFormat("fa-IR", { style: "currency", currency: "IRR", minimumFractionDigits: 0, maximumFractionDigits: 0, }); const numberFormatter = new Intl.NumberFormat("fa-IR", { maximumFractionDigits: 0, }); const percentFormatter = new Intl.NumberFormat("fa-IR", { style: "percent", maximumFractionDigits: 0, }); const compactCurrencyFormatter = new Intl.NumberFormat("fa-IR", { style: "currency", currency: "IRR", notation: "compact", minimumFractionDigits: 0, maximumFractionDigits: 0, }); /** `font-mono tabular-nums` for large hero KPI values only; smaller figures stay sans (see `tabular-nums` where alignment helps). */ const numericMonoClass = "font-mono tabular-nums"; const chartCurrencyTickProps = { fontSize: 10, fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace", } as const; const monthLabel = (monthIndex: number) => new Intl.DateTimeFormat("fa-IR", { month: "short" }).format( new Date(2025, monthIndex, 1), ); // ============================================================================ // Chart Palette (color-mix from primary) // ============================================================================ 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})`, }, }; // ============================================================================ // Mock Data // ============================================================================ const sidebarData: SidebarData = { logo: { src: "/block-media/shadcnblocks/block/logos/NovaSales-logo.svg", alt: "نوافروش", title: "NovaSales", description: "پلتفرم فروش ابری", href: "https://www.NovaSales", }, navGroups: [ { title: "نمای کلی", defaultOpen: true, items: [ { label: "داشبورد", icon: LayoutDashboard, href: "#", isActive: true, }, { label: "تحلیل فروش", icon: BarChart3, href: "#" }, { label: "فعالیت تیم", icon: Activity, href: "#" }, ], }, { title: "اعضای تیم", defaultOpen: true, items: [ { label: "فهرست معاملات", icon: Users, href: "#", children: [ { label: "همه اعضای تیم", icon: User, href: "#" }, { label: "فضاهای کاری", icon: Building2, href: "#" }, ], }, { label: "دعوت‌ها", icon: UserPlus, href: "#" }, ], }, { title: "صورتحساب", defaultOpen: false, items: [ { label: "اشتراک‌ها", icon: CreditCard, href: "#" }, { label: "مصرف", icon: Zap, href: "#" }, { label: "فاکتورها", icon: Receipt, href: "#" }, ], }, { title: "گزارش‌ها", defaultOpen: false, items: [ { label: "گزارش‌های ذخیره‌شده", icon: FileText, href: "#" }, { label: "خروجی‌ها", icon: Download, href: "#" }, ], }, ], footerGroup: { title: "تنظیمات", items: [{ label: "تنظیمات", icon: Settings, href: "#" }], }, user: { name: "مریم الیس", email: "morgan.ellis@northwind.app", avatar: "/block-media/shadcnblocks/block/avatar-1.webp", }, }; /** Highlights for the welcome line (growth + revenue health). */ const dashboardHighlights = { signupsThisWeek: 86, trialsEndingSoon: 14, } as const; const headerNotificationItems = [ { id: "1", title: "پرداخت دریافت شد", body: "شرکت آکمه فاکتور ۱۰۴۲ را (۲٬۴۰۰ ریال) پرداخت کرد.", time: "۲ دقیقه پیش", }, { id: "2", title: "هشدار سقف صندلی", body: "نورث‌ویند به ۹۰٪ صندلی‌های مجاز رسیده است.", time: "۱ ساعت پیش", }, { id: "3", title: "پایان دوره آزمایشی", body: "۳ فضای کاری ظرف ۴۸ ساعت دوره آزمایشی‌شان تمام می‌شود.", time: "۳ ساعت پیش", }, { id: "4", title: "گزارش هفتگی آماده است", body: "خلاصه MRR هفته گذشته در دسترس است.", time: "دیروز", }, ] as const; const unreadNotificationCount = headerNotificationItems.length; const statsData: StatItem[] = [ { title: "درآمد ماهانه (درآمد ماهانه تکرارشونده)", previousValue: 148_230.4, value: 189_540.75, changePercent: 27.86, isPositive: true, icon: CircleDollarSign, format: "currency", }, { title: "اعضای تیم فعال ماهانه", previousValue: 45_890, value: 52_340, changePercent: 14.06, isPositive: true, icon: Users, format: "number", }, { title: "مشتریان پرداخت‌کننده", previousValue: 1_842, value: 2_047, changePercent: 11.13, isPositive: true, icon: Building2, format: "number", }, { title: "درآمد ماهانه تکرارشونده از دست‌رفته", previousValue: 11_234.56, value: 9_847.23, changePercent: 12.35, isPositive: true, icon: TrendingDown, format: "currency", }, ]; const channelRevenueData = [ { month: monthLabel(0), starter: 18_200, pro: 28_640, enterprise: 31_850, addOns: 10_520, }, { month: monthLabel(1), starter: 17_410, pro: 29_450, enterprise: 33_720, addOns: 9_380, }, { month: monthLabel(2), starter: 19_840, pro: 30_920, enterprise: 34_240, addOns: 8_900, }, { month: monthLabel(3), starter: 18_970, pro: 31_880, enterprise: 35_910, addOns: 10_140, }, { month: monthLabel(4), starter: 20_620, pro: 32_510, enterprise: 36_680, addOns: 11_290, }, { month: monthLabel(5), starter: 21_190, pro: 33_340, enterprise: 38_620, addOns: 11_740, }, ]; const fullYearData = [ { month: monthLabel(0), thisYear: 41_280, prevYear: 38_450 }, { month: monthLabel(1), thisYear: 37_920, prevYear: 44_680 }, { month: monthLabel(2), thisYear: 52_140, prevYear: 41_230 }, { month: monthLabel(3), thisYear: 45_890, prevYear: 47_520 }, { month: monthLabel(4), thisYear: 57_640, prevYear: 43_910 }, { month: monthLabel(5), thisYear: 41_580, prevYear: 51_240 }, { month: monthLabel(6), thisYear: 54_720, prevYear: 46_880 }, { month: monthLabel(7), thisYear: 48_310, prevYear: 52_690 }, { month: monthLabel(8), thisYear: 61_050, prevYear: 49_420 }, { month: monthLabel(9), thisYear: 53_880, prevYear: 57_910 }, { month: monthLabel(10), thisYear: 66_420, prevYear: 52_340 }, { month: monthLabel(11), thisYear: 70_890, prevYear: 60_760 }, ]; /** * Weekly buckets for “This month” total revenue (same unit scale as `fullYearData` months). * Sums match March vs February `thisYear` in `fullYearData` so MTD stays below full-year total. */ const revenueMonthTimelineData = [ { label: "هفته ۱", current: 12_600, previous: 9_200 }, { label: "هفته ۲", current: 13_050, previous: 9_600 }, { label: "هفته ۳", current: 13_200, previous: 9_450 }, { label: "هفته ۴", current: 13_290, previous: 9_670 }, ]; const chartDates = Array.from({ length: 28 }, (_, index) => new Intl.DateTimeFormat("fa-IR", { day: "numeric", month: "short" }).format( new Date(2025, 1, index + 1), ), ); const aovValues = [ 687, 918, 763, 1036, 824, 1174, 719, 983, 1116, 742, 957, 1083, 704, 938, 1194, 862, 778, 1157, 827, 1094, 976, 764, 1253, 883, 1138, 963, 1216, 1077, ]; const aovData = chartDates.map((date, index) => ({ date, value: aovValues[index], })); const chartDates90 = Array.from( { length: 90 }, (_, i) => `روز ${(i + 1).toLocaleString("fa-IR")}`, ); const aovValues90 = Array.from({ length: 90 }, (_, i) => { const base = aovValues[i % aovValues.length]; return Math.round(base + ((i * 19) % 47) - 23); }); const aovData90 = chartDates90.map((date, index) => ({ date, value: aovValues90[index], })); const aovAverage90 = aovValues90.reduce((total, value) => total + value, 0) / aovValues90.length; const aovAverage = aovValues.reduce((total, value) => total + value, 0) / aovValues.length; const averageSalesThisMonth = [ 6380, 7240, 6820, 7360, 7930, 8170, 7580, 7030, 7820, 8470, 8320, 7880, 7630, 7180, 7970, 8760, 8360, 8230, 8580, 8970, 8720, 9070, 9470, 9820, 9960, 10180, 9770, 10340, ]; const averageSalesLastMonth = [ 5620, 5970, 5920, 6180, 6430, 6970, 6620, 6280, 6530, 7170, 7360, 7030, 6770, 6630, 6920, 7380, 7080, 7020, 7280, 7580, 7420, 7760, 8170, 8470, 8680, 8870, 8580, 8940, ]; const averageSalesData = chartDates.map((date, index) => ({ date, thisMonth: averageSalesThisMonth[index], lastMonth: averageSalesLastMonth[index], })); type PlanMixRow = { name: string; value: number; color: string; }; const channelMixBase: PlanMixRow[] = [ { name: "رایگان", value: 44.2, color: palette.primary }, { name: "حرفه‌ای", value: 28.6, color: `color-mix(in oklch, var(--primary) 80%, ${mixBase})`, }, { name: "سازمانی", value: 19.8, color: `color-mix(in oklch, var(--primary) 60%, ${mixBase})`, }, { name: "تیمی", value: 7.4, color: `color-mix(in oklch, var(--primary) 42%, ${mixBase})`, }, ]; const channelMixByWindow: Record<"7d" | "28d" | "90d", PlanMixRow[]> = { "7d": [ { ...channelMixBase[0], value: 41.2 }, { ...channelMixBase[1], value: 29.4 }, { ...channelMixBase[2], value: 20.1 }, { ...channelMixBase[3], value: 9.3 }, ], "28d": channelMixBase, "90d": [ { ...channelMixBase[0], value: 46.8 }, { ...channelMixBase[1], value: 26.2 }, { ...channelMixBase[2], value: 18.9 }, { ...channelMixBase[3], value: 8.1 }, ], }; // ============================================================================ // Chart Configs // ============================================================================ const revenueFlowChartConfig = { thisYear: { label: "امسال", color: palette.primary }, prevYear: { label: "سال قبل", theme: palette.secondary }, } satisfies ChartConfig; const revenueMonthChartConfig = { current: { label: "این ماه", color: palette.primary }, previous: { label: "ماه قبل", theme: palette.secondary }, } satisfies ChartConfig; const aovChartConfig = { value: { label: "ARPU", color: palette.primary }, reference: { label: "میانگین", theme: palette.secondary }, } satisfies ChartConfig; const averageSalesChartConfig = { thisMonth: { label: "این ماه", color: palette.primary }, lastMonth: { label: "ماه قبل", theme: palette.secondary }, } satisfies ChartConfig; const channelChartConfig = { starter: { label: "پایه", color: palette.primary }, pro: { label: "حرفه‌ای", theme: palette.secondary }, enterprise: { label: "سازمانی", theme: palette.tertiary }, addOns: { label: "افزونه‌ها", theme: palette.quaternary }, } satisfies ChartConfig; const channelMixChartConfig = { free: { label: "رایگان", color: palette.primary }, pro: { label: "حرفه‌ای", theme: palette.secondary }, enterprise: { label: "سازمانی", theme: palette.tertiary }, team: { label: "تیمی", theme: palette.quaternary }, } satisfies ChartConfig; // ============================================================================ // Sidebar Components // ============================================================================ 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 }) => { const initials = user.name .split(" ") .map((n) => n[0]) .join(""); const userAvatar = ( {initials} ); const userInfo = (
{user.name} {user.email}
); return ( {userAvatar} {userInfo}
{userAvatar} {userInfo}
); }; const AppSidebar = ({ ...props }: React.ComponentProps) => { return (
{sidebarData.navGroups.map((group) => ( {group.title} {group.items.map((item) => ( ))} ))} {sidebarData.user && }
); }; // ============================================================================ // Dashboard Header // ============================================================================ const DashboardHeader = () => { return (
); }; // ============================================================================ // Welcome Section // ============================================================================ const WelcomeSection = () => { const [inviteOpen, setInviteOpen] = React.useState(false); const [inviteEmail, setInviteEmail] = React.useState(""); return (

{dashboardHighlights.signupsThisWeek.toLocaleString("fa-IR")} ثبت‌نام {" "} این هفته ·{" "} {dashboardHighlights.trialsEndingSoon.toLocaleString("fa-IR")} دوره آزمایشی {" "} در ۷ روز آینده منقضی می‌شود

دعوت افراد دعوت‌نامه را با ایمیل ارسال کنید. آن‌ها لینک پیوستن به فضای کاری شما را دریافت می‌کنند.
) => setInviteEmail(e.target.value) } />
); }; // ============================================================================ // Stats Cards // ============================================================================ const StatsCards = () => { return (
{statsData.map((stat, index) => { const formatter = stat.format === "currency" ? currencyFormatter : numberFormatter; return (

{formatter.format(stat.previousValue)} ماه قبل

{formatter.format(stat.value)}

{stat.isPositive ? (
{index < statsData.length - 1 && (
)}
); })}
); }; // ============================================================================ // Channel Revenue Chart // ============================================================================ function ChannelTooltip({ active, payload, label, }: TooltipContentProps) { if (!active || !payload?.length) return null; const total = payload.reduce( (sum, entry) => sum + Number(entry.value ?? 0), 0, ); return (

{label}

{payload.map((entry) => { const dataKey = String( entry.dataKey ?? "", ) as keyof typeof channelChartConfig; const label = channelChartConfig[dataKey]?.label ?? entry.name ?? dataKey; return (
{label}: {compactCurrencyFormatter.format(Number(entry.value))}
); })}
جمع: {compactCurrencyFormatter.format(total)}
); } const ChannelRevenueChart = () => { const [mrrRange, setMrrRange] = React.useState<"3m" | "6m" | "ytd">("6m"); const mrrChartData = React.useMemo(() => { if (mrrRange === "3m") return channelRevenueData.slice(-3); if (mrrRange === "ytd") return channelRevenueData.slice(0, 4); return channelRevenueData; }, [mrrRange]); return (

درآمد ماهانه تکرارشونده بر اساس پلن

{[ { label: channelChartConfig.starter.label, color: palette.primary }, { label: channelChartConfig.pro.label, color: palette.secondary.light }, { label: channelChartConfig.enterprise.label, color: palette.tertiary.light, }, { label: channelChartConfig.addOns.label, color: palette.quaternary.light }, ].map((item) => (
{item.label}
))}
compactCurrencyFormatter.format(v)} />
); }; // ============================================================================ // Total Revenue Chart (from Dashboard9) // ============================================================================ function RevenueTooltip({ active, payload, label, colors, variant, primaryLabel, secondaryLabel, comparisonPhrase, }: TooltipContentProps & { colors: { primary: string; secondary: string }; variant: "year" | "month"; primaryLabel: string; secondaryLabel: string; comparisonPhrase: string; }) { if (!active || !payload?.length) return null; const primaryKey = variant === "year" ? "thisYear" : "current"; const secondaryKey = variant === "year" ? "prevYear" : "previous"; const primaryVal = payload.find((p) => p.dataKey === primaryKey)?.value ?? 0; const secondaryVal = payload.find((p) => p.dataKey === secondaryKey)?.value ?? 0; const diff = Number(primaryVal) - Number(secondaryVal); const percentage = secondaryVal ? diff / Number(secondaryVal) : 0; const currentYear = new Date().getFullYear().toLocaleString("fa-IR"); const formattedDelta = `${diff >= 0 ? "+" : ""}${percentFormatter.format( Math.abs(percentage), )}`; const title = variant === "year" ? `${label}, ${currentYear}` : `${label} · ${currentYear}`; return (

{title}

{primaryLabel}: {currencyFormatter.format(Number(primaryVal))}
{secondaryLabel}: {currencyFormatter.format(Number(secondaryVal))}
= 0 ? "text-emerald-500" : "text-red-500", )} > {formattedDelta} {comparisonPhrase}
); } const TotalRevenueChart = () => { const [timeline, setTimeline] = React.useState<"year" | "month">("year"); const isYear = timeline === "year"; const chartData = isYear ? fullYearData : revenueMonthTimelineData; const xKey = isYear ? "month" : "label"; const lineKey = isYear ? "thisYear" : "current"; const areaKey = isYear ? "prevYear" : "previous"; const chartConfig = isYear ? revenueFlowChartConfig : revenueMonthChartConfig; const lineColorVar = isYear ? "ارزش افزوده(--color-thisYear)" : "ارزش افزوده(--color-current)"; const areaColorVar = isYear ? "ارزش افزوده(--color-prevYear)" : "ارزش افزوده(--color-previous)"; const totalRevenue = isYear ? fullYearData.reduce((acc, item) => acc + item.thisYear, 0) : revenueMonthTimelineData.reduce((acc, item) => acc + item.current, 0); const legendDotClass = "size-2 rounded-full sm:size-2.5"; const primaryLegend = isYear ? "امسال" : "این ماه"; const secondaryLegend = isYear ? "سال قبل" : "ماه قبل"; const subtitle = isYear ? "امسال در برابر سال قبل" : "این ماه در برابر ماه قبل"; return (

درآمد کل

{primaryLegend}
{secondaryLegend}

{currencyFormatter.format(totalRevenue)}

{subtitle}

compactCurrencyFormatter.format(v)} width={40} /> ( )} cursor={{ strokeOpacity: 0.2 }} />
); }; // ============================================================================ // Mini Chart Cards // ============================================================================ const standardChartMenuLabels = [ "مشاهده جزئیات", "خروجی جدول", "باز کردن در تحلیل فروش", ] as const; type MiniChartCardProps = { title: string; value: string; changePercent: number; isPositive: boolean; helper: string; icon: React.ComponentType>; legend?: React.ReactNode; footer?: React.ReactNode; children: React.ReactNode; toolbar?: React.ReactNode; menuLabels?: readonly string[]; }; const MiniChartCard = ({ title, value, changePercent, isPositive, helper, icon: Icon, legend, footer, children, toolbar, menuLabels = standardChartMenuLabels, }: MiniChartCardProps) => { return (

{title}

{value} {isPositive ? ( {helper}
{toolbar} {menuLabels.map((label) => ( {label} ))}
{legend && (
{legend}
)}
{children}
{footer ? (
{footer}
) : (
{chartDates[0]} {chartDates[chartDates.length - 1]}
)}
); }; const renderActiveShape = (props: unknown) => { const p = props as { cx: number; cy: number; innerRadius: number; outerRadius: number; startAngle: number; endAngle: number; fill: string; }; return ( ); }; const MiniChartsSection = () => { const [activeSlice, setActiveSlice] = React.useState(null); const [planWindow, setPlanWindow] = React.useState<"7d" | "28d" | "90d">( "28d", ); const [arpuRange, setArpuRange] = React.useState<"28d" | "90d">("28d"); const [dauWindow, setDauWindow] = React.useState<"14d" | "28d">("28d"); const planMix = channelMixByWindow[planWindow]; const topPlan = planMix.reduce((top, item) => item.value > top.value ? item : top, ); const arpuChartData = arpuRange === "90d" ? aovData90 : aovData; const arpuRefAverage = arpuRange === "90d" ? aovAverage90 : aovAverage; const arpuHeadline = Math.round( (arpuRange === "90d" ? aovValues90 : aovValues).reduce((a, b) => a + b, 0) / (arpuRange === "90d" ? aovValues90.length : aovValues.length), ); const dauChartData = React.useMemo( () => averageSalesData.slice(-(dauWindow === "14d" ? 14 : 28)), [dauWindow], ); const dauHeadline = Math.round( dauChartData.reduce((acc, row) => acc + row.thisMonth, 0) / Math.max(dauChartData.length, 1), ); const planMixCaption = planWindow === "7d" ? "۷ روز اخیر" : planWindow === "90d" ? "۹۰ روز اخیر" : "۲۸ روز اخیر"; const arpuToolbar = ( ); const dauToolbar = ( ); return (
{arpuChartData[0]?.date} –{" "} {arpuChartData[arpuChartData.length - 1]?.date} } > { if (!active || !payload?.length) return null; const value = payload[0].value as number; const diff = value - arpuRefAverage; const diffPercent = Math.round((diff / arpuRefAverage) * 100); return (

{label}

{currencyFormatter.format(value)}

{diff >= 0 ? "+" : ""} {diffPercent.toLocaleString("fa-IR")}٪ نسبت به میانگین

); }} cursor={{ fillOpacity: 0.05 }} />
{averageSalesChartConfig.thisMonth.label} {averageSalesChartConfig.lastMonth.label} } footer={ <> {dauChartData[0]?.date} –{" "} {dauChartData[dauChartData.length - 1]?.date} } > { if (!active || !payload?.length) return null; const thisMonth = payload.find((p) => p.dataKey === "thisMonth") ?.value as number; const lastMonth = payload.find((p) => p.dataKey === "lastMonth") ?.value as number; const diff = thisMonth - lastMonth; const diffPercent = Math.round((diff / lastMonth) * 100); return (

{label}

{averageSalesChartConfig.thisMonth.label}: {numberFormatter.format(thisMonth)}
{averageSalesChartConfig.lastMonth.label}: {numberFormatter.format(lastMonth)}

{diff >= 0 ? "+" : ""} {diffPercent.toLocaleString("fa-IR")}٪ تغییر

); }} cursor={{ strokeOpacity: 0.2 }} />
اعضای تیم بر اساس پلن
{standardChartMenuLabels.map((label) => ( {label} ))}
setActiveSlice(index) } onMouseLeave={() => setActiveSlice(null)} > {planMix.map((entry) => ( ))}
{Math.round(topPlan.value).toLocaleString("fa-IR")}٪ {topPlan.name}
{planMix.map((item, index) => (
setActiveSlice(index)} onMouseLeave={() => setActiveSlice(null)} >
{item.name} {Math.round(item.value).toLocaleString("fa-IR")}٪
))}
{planMixCaption}
); }; // ============================================================================ // Dashboard Content // ============================================================================ const DashboardContent = () => { return (
); }; // ============================================================================ // Main Dashboard Component // ============================================================================ const Dashboard1 = ({ className }: { className?: string }) => { return ( رفتن به محتوای اصلی ); }; export { Dashboard1 };