"use client"; import { Activity, ArrowDownRight, ArrowUpRight, BarChart3, Bell, Building2, CheckCircle2, ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, ChevronsUpDown, CircleDollarSign, Clock, Copy, CreditCard, Download, Eye, FileText, Filter, LayoutDashboard, LogOut, MoreHorizontal, Pencil, Plus, Receipt, RotateCcw, Search, Settings, ShoppingCart, User, UserPlus, Users, Wallet, X, XCircle, Zap, } from "lucide-react"; import * as React from "react"; import type { TooltipProps } from "recharts"; import { Area, AreaChart, Bar, BarChart, CartesianGrid, 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 { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; 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 { 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; href: string; }; navGroups: NavGroup[]; footerGroup: NavGroup; user?: UserData; }; type TransactionStatus = "completed" | "pending" | "failed" | "refunded"; type TransactionType = "Sale" | "Refund" | "Subscription"; type Transaction = { id: string; txnId: string; amount: number; customerName: string; customerInitials: string; type: TransactionType; paymentMethod: "Credit Card" | "Debit Card" | "PayPal" | "Bank Transfer"; date: string; status: TransactionStatus; }; type PeriodKey = "30days" | "3months" | "1year"; type RevenueDataPoint = { month: string; revenue: number; }; type CostDataPoint = { month: string; cogs: number; operatingExpenses: number; }; type PeriodSummary = { total: number; change: number; isPositive: boolean; }; type StatItem = { title: string; previousValue: number; value: number; changePercent: number; isPositive: boolean; icon: React.ComponentType>; format: "currency" | "percentage"; }; const currencyFormatter = new Intl.NumberFormat("fa-IR", { style: "currency", currency: "IRR", }); const compactCurrencyFormatter = new Intl.NumberFormat("fa-IR", { style: "currency", currency: "IRR", notation: "compact", maximumFractionDigits: 0, }); const percentFormatter = new Intl.NumberFormat("fa-IR", { style: "percent", minimumFractionDigits: 1, maximumFractionDigits: 1, }); const monthLabel = (monthIndex: number) => new Intl.DateTimeFormat("fa-IR", { month: "short" }).format( new Date(2025, monthIndex, 1), ); const formatTransactionDate = (date: string): string => { if (date === "Today") return "امروز"; const dayAgoMatch = date.match(/^(\d+) day ago$/); if (dayAgoMatch) { return `${Number(dayAgoMatch[1]).toLocaleString("fa-IR")} روز پیش`; } const daysAgoMatch = date.match(/^(\d+) days ago$/); if (daysAgoMatch) { return `${Number(daysAgoMatch[1]).toLocaleString("fa-IR")} روز پیش`; } return date; }; const transactionTypeLabels: Record = { Sale: "فروش", Refund: "بازپرداخت", Subscription: "اشتراک", }; const paymentMethodLabels: Record = { "Credit Card": "کارت اعتباری", "Debit Card": "کارت نقدی", PayPal: "پی‌پال", "Bank Transfer": "انتقال بانکی", }; 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})`, }, }; const revenueChartConfig = { revenue: { label: "درآمد", color: palette.primary }, } satisfies ChartConfig; const costsChartConfig = { cogs: { label: "بهای تمام‌شده", color: palette.primary }, operatingExpenses: { label: "هزینه‌های عملیاتی", theme: palette.secondary, }, } satisfies ChartConfig; 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", }, }; const headerNotificationItems = [ { id: "1", title: "فید بانکی همگام شد", body: "۴۲ تراکنش جدید از حساب جاری نورث‌ویند وارد شد.", time: "۴ دقیقه پیش", }, { id: "2", title: "آستانه بودجه", body: "هزینه بازاریابی به ۸۸٪ سقف فصلی رسیده است.", time: "۱ ساعت پیش", }, { id: "3", title: "یادآوری تطبیق", body: "۳ حساب برای بستن پایان ماه نیاز به بررسی دارند.", time: "۳ ساعت پیش", }, { id: "4", title: "گزارش CFO آماده است", body: "صورت سود و زیان یکپارچه ماه گذشته برای خروجی در دسترس است.", time: "دیروز", }, ] as const; const unreadNotificationCount = headerNotificationItems.length; const revenueData: Record = { "30days": [ { month: "هفته ۱", revenue: 87500 }, { month: "هفته ۲", revenue: 95200 }, { month: "هفته ۳", revenue: 102800 }, { month: "هفته ۴", revenue: 91400 }, { month: "هفته ۵", revenue: 110600 }, ], "3months": [ { month: monthLabel(9), revenue: 342000 }, { month: monthLabel(10), revenue: 378000 }, { month: monthLabel(11), revenue: 456000 }, { month: monthLabel(0), revenue: 398000 }, { month: monthLabel(1), revenue: 412000 }, { month: monthLabel(2), revenue: 445000 }, ], "1year": [ { month: monthLabel(0), revenue: 285000 }, { month: monthLabel(1), revenue: 312000 }, { month: monthLabel(2), revenue: 338000 }, { month: monthLabel(3), revenue: 356000 }, { month: monthLabel(4), revenue: 342000 }, { month: monthLabel(5), revenue: 378000 }, { month: monthLabel(6), revenue: 395000 }, { month: monthLabel(7), revenue: 418000 }, { month: monthLabel(8), revenue: 432000 }, { month: monthLabel(9), revenue: 456000 }, { month: monthLabel(10), revenue: 478000 }, { month: monthLabel(11), revenue: 512000 }, ], }; const costsData: Record = { "30days": [ { month: "هفته ۱", cogs: 31500, operatingExpenses: 18200 }, { month: "هفته ۲", cogs: 34100, operatingExpenses: 19800 }, { month: "هفته ۳", cogs: 37000, operatingExpenses: 20500 }, { month: "هفته ۴", cogs: 32800, operatingExpenses: 19100 }, { month: "هفته ۵", cogs: 39800, operatingExpenses: 21600 }, ], "3months": [ { month: monthLabel(9), cogs: 123100, operatingExpenses: 68400 }, { month: monthLabel(10), cogs: 136100, operatingExpenses: 75600 }, { month: monthLabel(11), cogs: 164200, operatingExpenses: 91200 }, { month: monthLabel(0), cogs: 143300, operatingExpenses: 79600 }, { month: monthLabel(1), cogs: 148300, operatingExpenses: 82400 }, { month: monthLabel(2), cogs: 160200, operatingExpenses: 89000 }, ], "1year": [ { month: monthLabel(0), cogs: 102600, operatingExpenses: 57000 }, { month: monthLabel(1), cogs: 112300, operatingExpenses: 62400 }, { month: monthLabel(2), cogs: 121700, operatingExpenses: 67600 }, { month: monthLabel(3), cogs: 128200, operatingExpenses: 71200 }, { month: monthLabel(4), cogs: 123100, operatingExpenses: 68400 }, { month: monthLabel(5), cogs: 136100, operatingExpenses: 75600 }, { month: monthLabel(6), cogs: 142200, operatingExpenses: 79000 }, { month: monthLabel(7), cogs: 150500, operatingExpenses: 83600 }, { month: monthLabel(8), cogs: 155500, operatingExpenses: 86400 }, { month: monthLabel(9), cogs: 164200, operatingExpenses: 91200 }, { month: monthLabel(10), cogs: 172100, operatingExpenses: 95600 }, { month: monthLabel(11), cogs: 184300, operatingExpenses: 102400 }, ], }; const revenueSummary: Record = { "30days": { total: 487500, change: 14.2, isPositive: true }, "3months": { total: 2431000, change: 11.8, isPositive: true }, "1year": { total: 4702000, change: 18.5, isPositive: true }, }; const costsSummary: Record = { "30days": { total: 274400, change: 8.6, isPositive: false }, "3months": { total: 1361400, change: 9.3, isPositive: false }, "1year": { total: 2705800, change: 12.1, isPositive: false }, }; const statsData: StatItem[] = [ { title: "درآمد ناخالص", previousValue: 426800, value: 487500, changePercent: 14.2, isPositive: true, icon: CircleDollarSign, format: "currency", }, { title: "سود خالص", previousValue: 168200, value: 213100, changePercent: 26.7, isPositive: true, icon: Wallet, format: "currency", }, { title: "نرخ بازپرداخت", previousValue: 0.042, value: 0.031, changePercent: 26.2, isPositive: true, icon: RotateCcw, format: "percentage", }, { title: "میانگین تراکنش", previousValue: 68.4, value: 74.2, changePercent: 8.5, isPositive: true, icon: CreditCard, format: "currency", }, ]; const transactionRecords: Transaction[] = [ { id: "1", txnId: "TXN-100201", amount: 129.99, customerName: "Sarah Johnson", customerInitials: "SJ", type: "Sale", paymentMethod: "Credit Card", date: "Today", status: "completed", }, { id: "2", txnId: "TXN-100202", amount: 84.5, customerName: "Michael Chen", customerInitials: "MC", type: "Sale", paymentMethod: "PayPal", date: "Today", status: "completed", }, { id: "3", txnId: "TXN-100203", amount: 249.0, customerName: "Emma Wilson", customerInitials: "EW", type: "Subscription", paymentMethod: "Credit Card", date: "Today", status: "pending", }, { id: "4", txnId: "TXN-100204", amount: 45.99, customerName: "James Rodriguez", customerInitials: "JR", type: "Refund", paymentMethod: "Debit Card", date: "Today", status: "refunded", }, { id: "5", txnId: "TXN-100205", amount: 312.0, customerName: "Lisa Park", customerInitials: "LP", type: "Sale", paymentMethod: "Bank Transfer", date: "Today", status: "failed", }, { id: "6", txnId: "TXN-100206", amount: 67.25, customerName: "David Kim", customerInitials: "DK", type: "Sale", paymentMethod: "Credit Card", date: "1 day ago", status: "completed", }, { id: "7", txnId: "TXN-100207", amount: 189.99, customerName: "Anna Martinez", customerInitials: "AM", type: "Subscription", paymentMethod: "PayPal", date: "1 day ago", status: "completed", }, { id: "8", txnId: "TXN-100208", amount: 95.0, customerName: "Robert Taylor", customerInitials: "RT", type: "Sale", paymentMethod: "Debit Card", date: "1 day ago", status: "pending", }, { id: "9", txnId: "TXN-100209", amount: 156.5, customerName: "Jennifer Lee", customerInitials: "JL", type: "Refund", paymentMethod: "Credit Card", date: "1 day ago", status: "refunded", }, { id: "10", txnId: "TXN-100210", amount: 78.99, customerName: "William Brown", customerInitials: "WB", type: "Sale", paymentMethod: "PayPal", date: "2 days ago", status: "completed", }, { id: "11", txnId: "TXN-100211", amount: 425.0, customerName: "Sophia Davis", customerInitials: "SD", type: "Subscription", paymentMethod: "Credit Card", date: "2 days ago", status: "completed", }, { id: "12", txnId: "TXN-100212", amount: 34.99, customerName: "Daniel Garcia", customerInitials: "DG", type: "Sale", paymentMethod: "Debit Card", date: "2 days ago", status: "failed", }, { id: "13", txnId: "TXN-100213", amount: 210.0, customerName: "Olivia White", customerInitials: "OW", type: "Sale", paymentMethod: "Bank Transfer", date: "3 days ago", status: "completed", }, { id: "14", txnId: "TXN-100214", amount: 149.99, customerName: "Thomas Anderson", customerInitials: "TA", type: "Sale", paymentMethod: "Credit Card", date: "3 days ago", status: "completed", }, { id: "15", txnId: "TXN-100215", amount: 62.5, customerName: "Emily Thompson", customerInitials: "ET", type: "Refund", paymentMethod: "PayPal", date: "3 days ago", status: "refunded", }, { id: "16", txnId: "TXN-100216", amount: 299.0, customerName: "Christopher Moore", customerInitials: "CM", type: "Subscription", paymentMethod: "Credit Card", date: "4 days ago", status: "completed", }, { id: "17", txnId: "TXN-100217", amount: 88.75, customerName: "Isabella Jackson", customerInitials: "IJ", type: "Sale", paymentMethod: "Debit Card", date: "4 days ago", status: "pending", }, { id: "18", txnId: "TXN-100218", amount: 175.0, customerName: "Matthew Harris", customerInitials: "MH", type: "Sale", paymentMethod: "Bank Transfer", date: "5 days ago", status: "completed", }, { id: "19", txnId: "TXN-100219", amount: 42.99, customerName: "Ava Clark", customerInitials: "AC", type: "Sale", paymentMethod: "PayPal", date: "5 days ago", status: "failed", }, { id: "20", txnId: "TXN-100220", amount: 520.0, customerName: "Joshua Lewis", customerInitials: "JL", type: "Subscription", paymentMethod: "Credit Card", date: "5 days ago", status: "completed", }, { id: "21", txnId: "TXN-100221", amount: 37.5, customerName: "Mia Robinson", customerInitials: "MR", type: "Refund", paymentMethod: "Debit Card", date: "6 days ago", status: "refunded", }, { id: "22", txnId: "TXN-100222", amount: 165.0, customerName: "Ethan Walker", customerInitials: "EW", type: "Sale", paymentMethod: "Credit Card", date: "6 days ago", status: "completed", }, { id: "23", txnId: "TXN-100223", amount: 99.99, customerName: "Charlotte Hall", customerInitials: "CH", type: "Sale", paymentMethod: "PayPal", date: "7 days ago", status: "pending", }, { id: "24", txnId: "TXN-100224", amount: 284.0, customerName: "Alexander Young", customerInitials: "AY", type: "Sale", paymentMethod: "Bank Transfer", date: "7 days ago", status: "completed", }, { id: "25", txnId: "TXN-100225", amount: 55.99, customerName: "Amelia King", customerInitials: "AK", type: "Sale", paymentMethod: "Debit Card", date: "8 days ago", status: "completed", }, { id: "26", txnId: "TXN-100226", amount: 399.0, customerName: "Benjamin Wright", customerInitials: "BW", type: "Subscription", paymentMethod: "Credit Card", date: "8 days ago", status: "completed", }, { id: "27", txnId: "TXN-100227", amount: 72.25, customerName: "Harper Lopez", customerInitials: "HL", type: "Refund", paymentMethod: "PayPal", date: "9 days ago", status: "refunded", }, { id: "28", txnId: "TXN-100228", amount: 198.0, customerName: "Lucas Hill", customerInitials: "LH", type: "Sale", paymentMethod: "Credit Card", date: "10 days ago", status: "failed", }, { id: "29", txnId: "TXN-100229", amount: 145.5, customerName: "Evelyn Scott", customerInitials: "ES", type: "Sale", paymentMethod: "Debit Card", date: "10 days ago", status: "completed", }, { id: "30", txnId: "TXN-100230", amount: 89.99, customerName: "Henry Green", customerInitials: "HG", type: "Sale", paymentMethod: "Bank Transfer", date: "12 days ago", status: "completed", }, { id: "31", txnId: "TXN-100231", amount: 349.0, customerName: "Abigail Adams", customerInitials: "AA", type: "Subscription", paymentMethod: "Credit Card", date: "12 days ago", status: "completed", }, { id: "32", txnId: "TXN-100232", amount: 27.99, customerName: "Sebastian Baker", customerInitials: "SB", type: "Sale", paymentMethod: "PayPal", date: "14 days ago", status: "pending", }, { id: "33", txnId: "TXN-100233", amount: 462.0, customerName: "Ella Nelson", customerInitials: "EN", type: "Sale", paymentMethod: "Credit Card", date: "14 days ago", status: "completed", }, { id: "34", txnId: "TXN-100234", amount: 58.5, customerName: "Jack Carter", customerInitials: "JC", type: "Refund", paymentMethod: "Debit Card", date: "15 days ago", status: "refunded", }, { id: "35", txnId: "TXN-100235", amount: 225.0, customerName: "Scarlett Mitchell", customerInitials: "SM", type: "Sale", paymentMethod: "Bank Transfer", date: "16 days ago", status: "completed", }, { id: "36", txnId: "TXN-100236", amount: 134.75, customerName: "Owen Perez", customerInitials: "OP", type: "Sale", paymentMethod: "Credit Card", date: "16 days ago", status: "completed", }, { id: "37", txnId: "TXN-100237", amount: 499.0, customerName: "Grace Roberts", customerInitials: "GR", type: "Subscription", paymentMethod: "PayPal", date: "18 days ago", status: "completed", }, { id: "38", txnId: "TXN-100238", amount: 82.0, customerName: "Liam Turner", customerInitials: "LT", type: "Sale", paymentMethod: "Debit Card", date: "18 days ago", status: "failed", }, { id: "39", txnId: "TXN-100239", amount: 178.5, customerName: "Chloe Phillips", customerInitials: "CP", type: "Sale", paymentMethod: "Credit Card", date: "20 days ago", status: "completed", }, { id: "40", txnId: "TXN-100240", amount: 93.99, customerName: "Noah Campbell", customerInitials: "NC", type: "Refund", paymentMethod: "Bank Transfer", date: "20 days ago", status: "refunded", }, { id: "41", txnId: "TXN-100241", amount: 267.0, customerName: "Lily Parker", customerInitials: "LP", type: "Sale", paymentMethod: "Credit Card", date: "22 days ago", status: "completed", }, { id: "42", txnId: "TXN-100242", amount: 149.0, customerName: "Mason Evans", customerInitials: "ME", type: "Subscription", paymentMethod: "PayPal", date: "22 days ago", status: "completed", }, { id: "43", txnId: "TXN-100243", amount: 41.25, customerName: "Zoe Edwards", customerInitials: "ZE", type: "Sale", paymentMethod: "Debit Card", date: "25 days ago", status: "pending", }, { id: "44", txnId: "TXN-100244", amount: 315.0, customerName: "Aiden Collins", customerInitials: "AC", type: "Sale", paymentMethod: "Credit Card", date: "25 days ago", status: "completed", }, { id: "45", txnId: "TXN-100245", amount: 68.99, customerName: "Nora Stewart", customerInitials: "NS", type: "Sale", paymentMethod: "Bank Transfer", date: "28 days ago", status: "completed", }, { id: "46", txnId: "TXN-100246", amount: 599.0, customerName: "Logan Sanchez", customerInitials: "LS", type: "Subscription", paymentMethod: "Credit Card", date: "28 days ago", status: "completed", }, { id: "47", txnId: "TXN-100247", amount: 112.5, customerName: "Aria Morris", customerInitials: "AM", type: "Refund", paymentMethod: "PayPal", date: "30 days ago", status: "refunded", }, { id: "48", txnId: "TXN-100248", amount: 246.0, customerName: "Carter Rogers", customerInitials: "CR", type: "Sale", paymentMethod: "Debit Card", date: "30 days ago", status: "failed", }, { id: "49", txnId: "TXN-100249", amount: 79.99, customerName: "Penelope Reed", customerInitials: "PR", type: "Sale", paymentMethod: "Credit Card", date: "33 days ago", status: "completed", }, { id: "50", txnId: "TXN-100250", amount: 189.0, customerName: "Caleb Cook", customerInitials: "CC", type: "Sale", paymentMethod: "Bank Transfer", date: "36 days ago", status: "completed", }, ]; const PAGE_SIZE_OPTIONS = [5, 10, 20]; 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 (
); }; const periodLabels: Record = { "1year": "۱ سال", "3months": "۳ ماه", "30days": "۳۰ روز", }; const PeriodTabs = ({ activePeriod, onPeriodChange, }: { activePeriod: PeriodKey; onPeriodChange: (period: PeriodKey) => void; }) => { return (
{(Object.keys(periodLabels) as PeriodKey[]).map((key) => ( ))}
); }; function RevenueTooltip({ active, payload, label, }: any) { if (!active || !payload?.length) return null; const value = payload[0]?.value || 0; return (

{label}

{revenueChartConfig.revenue.label}: {currencyFormatter.format(Number(value))}
); } const RevenueChart = ({ period }: { period: PeriodKey }) => { const data = revenueData[period]; const summary = revenueSummary[period]; return (

نمای کلی درآمد

{currencyFormatter.format(summary.total)}

{summary.isPositive ? (
compactCurrencyFormatter.format(value)} width={40} /> } cursor={{ strokeOpacity: 0.2 }} />
); }; function CostsTooltip({ active, payload, label, colors, }: any & { colors: { primary: string; secondary: string }; }) { if (!active || !payload?.length) return null; const cogs = payload.find((p: any) => p.dataKey === "cogs")?.value || 0; const operatingExpenses = payload.find((p: any) => p.dataKey === "operatingExpenses")?.value || 0; const total = Number(cogs) + Number(operatingExpenses); return (

{label}

{costsChartConfig.cogs.label}: {currencyFormatter.format(Number(cogs))}
هزینه عملیاتی: {currencyFormatter.format(Number(operatingExpenses))}
جمع: {currencyFormatter.format(total)}
); } const CostsChart = ({ period }: { period: PeriodKey }) => { const data = costsData[period]; const summary = costsSummary[period]; return (

تفکیک هزینه‌ها

{costsChartConfig.cogs.label}
{costsChartConfig.operatingExpenses.label}

{currencyFormatter.format(summary.total)}

{summary.isPositive ? (
compactCurrencyFormatter.format(value)} width={40} /> } cursor={{ fillOpacity: 0.05 }} />
); }; const StatsCards = () => { return (
{statsData.map((stat, index) => { const formatter = stat.format === "currency" ? currencyFormatter : percentFormatter; return (

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

{formatter.format(stat.value)}

{stat.isPositive ? (
{index < statsData.length - 1 && (
)}
); })}
); }; const transactionStatusStyles: Record = { completed: "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", pending: "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", failed: "bg-red-50 text-red-700 ring-1 ring-inset ring-red-600/20 dark:bg-red-900/30 dark:text-red-400 dark:ring-red-400/20", refunded: "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", }; const transactionStatusIcons: Record< TransactionStatus, React.ComponentType> > = { completed: CheckCircle2, pending: Clock, failed: XCircle, refunded: RotateCcw, }; const transactionStatusLabels: Record = { completed: "تکمیل‌شده", pending: "در انتظار", failed: "ناموفق", refunded: "بازپرداخت‌شده", }; const allTransactionStatuses: TransactionStatus[] = [ "completed", "pending", "failed", "refunded", ]; const allPaymentMethods = [ "Credit Card", "Debit Card", "PayPal", "Bank Transfer", ] as const; const dateFilterOptions = [ { label: "همه", value: "all" }, { label: "امروز", value: "today" }, { label: "دیروز", value: "yesterday" }, { label: "۷ روز اخیر", value: "7days" }, { label: "۳۰ روز اخیر", value: "30days" }, ]; const filterChipClassName = "inline-flex h-5 cursor-pointer items-center gap-1 rounded-md bg-gray-50 px-2 text-[10px] font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 sm:h-6 sm:text-xs dark:bg-gray-800/50 dark:text-gray-400 dark:ring-gray-400/20"; const TransactionsTable = () => { const [searchQuery, setSearchQuery] = React.useState(""); const [statusFilter, setStatusFilter] = React.useState("all"); const [dateFilter, setDateFilter] = React.useState("all"); const [paymentMethodFilter, setPaymentMethodFilter] = React.useState("all"); const [currentPage, setCurrentPage] = React.useState(1); const [pageSize, setPageSize] = React.useState(10); const [isHydrated, setIsHydrated] = React.useState(false); const hasActiveFilters = statusFilter !== "all" || dateFilter !== "all" || paymentMethodFilter !== "all"; const clearFilters = () => { setStatusFilter("all"); setDateFilter("all"); setPaymentMethodFilter("all"); }; React.useEffect(() => { if (typeof window === "undefined") return; const params = new URLSearchParams(window.location.search); setSearchQuery(params.get("q") ?? ""); const nextStatus = params.get("status"); if ( nextStatus && (nextStatus === "all" || allTransactionStatuses.includes(nextStatus as TransactionStatus)) ) { setStatusFilter(nextStatus); } const nextDate = params.get("date"); if ( nextDate && dateFilterOptions.some((option) => option.value === nextDate) ) { setDateFilter(nextDate); } const nextPayment = params.get("payment"); if ( nextPayment && (nextPayment === "all" || allPaymentMethods.includes( nextPayment as (typeof allPaymentMethods)[number], )) ) { setPaymentMethodFilter(nextPayment); } const nextPage = Number(params.get("page")); if (!Number.isNaN(nextPage) && nextPage > 0) { setCurrentPage(nextPage); } const nextPageSize = Number(params.get("pageSize")); if ( !Number.isNaN(nextPageSize) && PAGE_SIZE_OPTIONS.includes(nextPageSize) ) { setPageSize(nextPageSize); } setIsHydrated(true); }, []); const filteredTransactions = React.useMemo(() => { const query = searchQuery.toLowerCase(); return transactionRecords.filter((txn) => { const matchesSearch = txn.txnId.toLowerCase().includes(query) || txn.customerName.toLowerCase().includes(query); const matchesStatus = statusFilter === "all" || txn.status === statusFilter; const matchesPaymentMethod = paymentMethodFilter === "all" || txn.paymentMethod === paymentMethodFilter; let matchesDate = true; const pd = txn.date.toLowerCase(); switch (dateFilter) { case "today": matchesDate = pd === "today"; break; case "yesterday": matchesDate = pd === "1 day ago"; break; case "7days": matchesDate = pd === "today" || pd.includes("day ago") || (pd.includes("days ago") && parseInt(pd) <= 7); break; case "30days": matchesDate = pd === "today" || pd.includes("day ago") || (pd.includes("days ago") && parseInt(pd) <= 30); break; } return ( matchesSearch && matchesStatus && matchesPaymentMethod && matchesDate ); }); }, [searchQuery, statusFilter, dateFilter, paymentMethodFilter]); const totalPages = Math.ceil(filteredTransactions.length / pageSize); const paginatedTransactions = React.useMemo(() => { const startIndex = (currentPage - 1) * pageSize; const endIndex = startIndex + pageSize; return filteredTransactions.slice(startIndex, endIndex); }, [filteredTransactions, currentPage, pageSize]); React.useEffect(() => { setCurrentPage(1); }, [searchQuery, statusFilter, dateFilter, paymentMethodFilter, pageSize]); React.useEffect(() => { if (!isHydrated || typeof window === "undefined") return; const params = new URLSearchParams(window.location.search); if (searchQuery) { params.set("q", searchQuery); } else { params.delete("q"); } if (statusFilter !== "all") { params.set("status", statusFilter); } else { params.delete("status"); } if (dateFilter !== "all") { params.set("date", dateFilter); } else { params.delete("date"); } if (paymentMethodFilter !== "all") { params.set("payment", paymentMethodFilter); } else { params.delete("payment"); } if (currentPage > 1) { params.set("page", String(currentPage)); } else { params.delete("page"); } if (pageSize !== PAGE_SIZE_OPTIONS[0]) { params.set("pageSize", String(pageSize)); } else { params.delete("pageSize"); } const nextQuery = params.toString(); const nextUrl = nextQuery ? `${window.location.pathname}?${nextQuery}` : window.location.pathname; window.history.replaceState(null, "", nextUrl); }, [ searchQuery, statusFilter, dateFilter, paymentMethodFilter, currentPage, pageSize, isHydrated, ]); const goToPage = (page: number) => { setCurrentPage(Math.max(1, Math.min(page, totalPages))); }; return (
تراکنش‌ها {filteredTransactions.length.toLocaleString("fa-IR")}
فیلتر بر اساس وضعیت setStatusFilter("all")} > همه وضعیت‌ها {allTransactionStatuses.map((status) => ( setStatusFilter(status)} > {transactionStatusLabels[status]} ))} روش پرداخت setPaymentMethodFilter("all")} > همه روش‌ها {allPaymentMethods.map((method) => ( setPaymentMethodFilter(method)} > {paymentMethodLabels[method]} ))}
{hasActiveFilters && (
فیلترها: {statusFilter !== "all" && ( )} {dateFilter !== "all" && ( )} {paymentMethodFilter !== "all" && ( )}
)}
شناسه تراکنش مشتری مبلغ نوع روش پرداخت تاریخ وضعیت {paginatedTransactions.length === 0 ? ( تراکنشی با این فیلترها یافت نشد. ) : ( paginatedTransactions.map((txn) => { const StatusIcon = transactionStatusIcons[txn.status]; return ( {txn.txnId}
{txn.customerInitials} {txn.customerName}
{currencyFormatter.format(txn.amount)} {transactionTypeLabels[txn.type]} {paymentMethodLabels[txn.paymentMethod]} {formatTransactionDate(txn.date)} { event.preventDefault(); if (typeof window === "undefined") return; window.confirm( "این تراکنش باطل شود؟ این عمل قابل بازگشت نیست.", ); }} >
); }) )}
ردیف در هر صفحه: {filteredTransactions.length === 0 ? "۰" : `${((currentPage - 1) * pageSize + 1).toLocaleString("fa-IR")}-${Math.min( currentPage * pageSize, filteredTransactions.length, ).toLocaleString("fa-IR")}`}{" "} از {filteredTransactions.length.toLocaleString("fa-IR")}
{Array.from({ length: Math.min(totalPages, 5) }, (_, i) => { let pageNum: number; if (totalPages <= 5) { pageNum = i + 1; } else if (currentPage <= 3) { pageNum = i + 1; } else if (currentPage >= totalPages - 2) { pageNum = totalPages - 4 + i; } else { pageNum = currentPage - 2 + i; } return ( ); })}
); }; const DashboardContent = () => { const [period, setPeriod] = React.useState("1year"); const [newTxnOpen, setNewTxnOpen] = React.useState(false); const [txnNote, setTxnNote] = React.useState(""); React.useEffect(() => { if (typeof window === "undefined") return; const params = new URLSearchParams(window.location.search); const nextPeriod = params.get("period"); if ( nextPeriod === "1year" || nextPeriod === "3months" || nextPeriod === "30days" ) { setPeriod(nextPeriod); } }, []); React.useEffect(() => { if (typeof window === "undefined") return; const params = new URLSearchParams(window.location.search); if (period !== "1year") { 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]); return (
ثبت تراکنش یادداشت سریعی برای چک‌لیست بستن حساب‌ها ثبت کنید. این نمایش آزمایشی داده را ذخیره نمی‌کند.
) => setTxnNote(e.target.value) } placeholder="مثلاً حواله پرداخت مالیات فصل اول" />
); }; const Dashboard2 = ({ className }: { className?: string }) => { return ( رفتن به محتوای اصلی ); }; export { Dashboard2 };