"use client"; import { Archive, ArrowLeft, Bug, ChevronDown, Clock, CommandIcon, File, Inbox, Lightbulb, MailOpen, MessageSquare, MoreHorizontal, PanelRight, Plus, Search, Send, Sparkles, Trash2, User, UserCheck, Users, } from "lucide-react"; import * as React from "react"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, } from "@/components/ui/command"; import { Drawer, DrawerContent, DrawerHeader, DrawerTitle, } from "@/components/ui/drawer"; import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarProvider, useSidebar, } from "@/components/ui/sidebar"; import { Textarea } from "@/components/ui/textarea"; import { cn } from "@/lib/utils"; type NavItemId = | "inbox" | "unassigned" | "assigned" | "drafts" | "archived" | "spam"; type BucketId = "support" | "bugs" | "features" | "internal"; type TicketStatus = "active" | "pending" | "closed"; type NavItem = { id: NavItemId; label: string; icon: React.ComponentType>; count?: number; }; type Bucket = { id: BucketId; label: string; icon: React.ComponentType>; }; type User = { id: string; name: string; email: string; avatar: string; role?: string; }; type Customer = { id: string; name: string; email: string; company: string; role: string; avatar: string; isHighValue: boolean; }; type Message = { id: string; sender: User | Customer; content: string; timestamp: string; date: string; isStaff: boolean; }; type Ticket = { id: string; subject: string; preview: string; timestamp: string; read: boolean; customer: Customer; assignee?: User; status: TicketStatus; messages: Message[]; respondingUser?: User; }; type PreviousConversation = { id: string; subject: string; timestamp: string; }; const navItems: NavItem[] = [ { id: "inbox", label: "صندوق ورودی", icon: Inbox, count: 6 }, { id: "unassigned", label: "بدون مسئول", icon: MailOpen, count: 10 }, { id: "assigned", label: "محول‌شده", icon: UserCheck, count: 3 }, { id: "drafts", label: "پیش‌نویس‌ها", icon: File, count: 1 }, { id: "archived", label: "بایگانی", icon: Archive }, { id: "spam", label: "هرزنامه", icon: Trash2 }, ]; const buckets: Bucket[] = [ { id: "support", label: "درخواست‌های پشتیبانی", icon: MessageSquare }, { id: "bugs", label: "گزارش باگ", icon: Bug }, { id: "features", label: "درخواست ویژگی", icon: Lightbulb }, { id: "internal", label: "داخلی", icon: Users }, ]; const staffUsers: User[] = [ { id: "peter", name: "رضا کریمی", email: "peter.lann@cloudstar.com", avatar: "/block-media/shadcnblocks/block/avatar/avatar3.webp", role: "کارشناس پشتیبانی", }, { id: "alex", name: "امیر چناری", email: "alex.chen@cloudstar.com", avatar: "/block-media/shadcnblocks/block/avatar/avatar3.webp", role: "کارشناس پشتیبانی", }, ]; const mockCustomers: Customer[] = [ { id: "sarah", name: "مریم Tran", email: "sarah.tran@example.com", company: "BrightWave Marketing", role: "مدیر عملیات", avatar: "/block-media/shadcnblocks/block/avatar/avatar2.webp", isHighValue: true, }, { id: "mike", name: "محمد جعفری", email: "mike.j@techcorp.io", company: "TechCorp", role: "توسعه‌دهنده", avatar: "/block-media/shadcnblocks/block/avatar/avatar5.webp", isHighValue: false, }, ]; const mockTickets: Ticket[] = [ { id: "1", subject: "مشکل اتصال یکپارچه‌سازی Slack", preview: "تیم ما می‌خواهد Slack را به CloudStar وصل کند، اما فرایند احراز هویت با خطا مواجه می‌شود...", timestamp: "۶ ساعت پیش", read: false, customer: mockCustomers[0], assignee: staffUsers[0], status: "active", respondingUser: staffUsers[0], messages: [ { id: "m1", sender: mockCustomers[0], content: `سلام پشتیبانی CloudStar، تیم ما می‌خواهد پیام‌رسان تیمی را به CloudStar وصل کند، اما فرایند احراز هویت با این خطا متوقف می‌شود: «احراز هویت token invalid». چند بار دوباره وصل شدیم و حتی workspace را ری‌استارت کردیم، اما نتیجه‌ای نگرفتیم. می‌توانید کمک کنید این یکپارچه‌سازی کار کند؟ ممنون، مریم Tran مدیر عملیات، BrightWave Marketing`, timestamp: "۸:۰۳", date: "۲۹ مرداد", isStaff: false, }, { id: "m2", sender: staffUsers[0], content: `سلام مریم، ممنون از پیام‌تان خوشحال می‌شوم کمک کنم! این خطا معمولاً وقتی رخ می‌دهد که پیام‌رسان تیمی هنگام اتصال، مجوزهای لازم را به CloudStar نمی‌دهد. این موارد را امتحان کنید: ۱ قبل از شروع اتصال، در workspace درست پیام‌رسان تیمی وارد شده باشید. ۲ هنگام درخواست، همه مجوزها را به CloudStar بدهید (گاهی «Deny» اشتباهی زده می‌شود). ۳. یک پنجره ناشناس/خصوصی امتحان کنید تا credentialهای قدیمی مزاحم نباشند. اگر جواب داد یا هنوز خطا می‌بینید، خبر دهید!`, timestamp: "۱۲:۵۶", date: "۲۹ مرداد", isStaff: true, }, ], }, { id: "2", subject: "فایل‌های گم‌شده در فضای کار مشترک", preview: "دیروز مجموعه‌ای از فایل‌های پروژه را در فضای کار مشترک بارگذاری کردم. امروز دو فایل دیگر نیست...", timestamp: "۶ ساعت پیش", read: false, customer: mockCustomers[1], status: "active", respondingUser: staffUsers[1], messages: [], }, { id: "3", subject: "مغایرت در صورتحساب آخر", preview: "فاکتور این ماه ۱۰ لایسنس Pro نشان می‌دهد، در حالی که فقط ۸ کاربر فعال داریم. لطفاً بررسی کنید...", timestamp: "۸ ساعت پیش", read: true, customer: mockCustomers[0], status: "pending", messages: [], }, { id: "4", subject: "امکان بازنشانی رمز عبور نیست", preview: 'با لینک «فراموشی رمز عبور» سعی کردم رمز CloudStar را بازنشانی کنم، اما ایمیل بازنشانی هرگز نرسید...', timestamp: "۱۲ ساعت پیش", read: true, customer: mockCustomers[1], status: "active", messages: [], }, { id: "5", subject: "آمار داشبورد به‌روز نمی‌شود", preview: "داشبورد آمار از دیروز حدود ساعت ۱۵ به‌روزرسانی نمی‌شود. همه نمودارها روی همان مقادیر مانده‌اند...", timestamp: "۱ روز پیش", read: true, customer: mockCustomers[0], status: "closed", messages: [], }, { id: "6", subject: "درخواست مستندات انطباق HIPAA", preview: "قبل از ادامه فرایند onboarding، تیم حقوقی ما به مستندات CloudStar درباره HIPAA نیاز دارد...", timestamp: "۲ هفته پیش", read: true, customer: mockCustomers[1], status: "pending", messages: [], }, ]; const previousConversations: PreviousConversation[] = [ { id: "prev1", subject: "مشکل اتصال یکپارچه‌سازی Slack", timestamp: "۶ ساعت پیش", }, { id: "prev2", subject: "انقضای توکن API", timestamp: "۲ هفته پیش", }, ]; function getInitials(name: string) { return ( name .split(" ") .filter(Boolean) .slice(0, 2) .map((part) => part[0]?.toUpperCase()) .join("") || "U" ); } function getStatusColor(status: TicketStatus) { switch (status) { case "active": return "bg-emerald-500"; case "pending": return "bg-amber-500"; case "closed": return "bg-muted-foreground"; default: return "bg-muted-foreground"; } } function getStatusLabel(status: TicketStatus) { switch (status) { case "active": return "فعال"; case "pending": return "در انتظار"; case "closed": return "بسته"; default: return status; } } interface AppSidebarProps extends React.ComponentProps { activeNavItem: NavItemId; activeBucket: BucketId | null; onNavItemChange: (id: NavItemId) => void; onBucketChange: (id: BucketId | null) => void; onSearchClick: () => void; } function AppSidebar({ activeNavItem, activeBucket, onNavItemChange, onBucketChange, onSearchClick, className, ...props }: AppSidebarProps) { const { state } = useSidebar(); const isCollapsed = state === "collapsed"; return (
فضای کار تنظیمات فضای کار دعوت هم‌تیمی‌ها صورتحساب خروج
جستجو K {navItems.map((item) => { const Icon = item.icon; const isActive = activeNavItem === item.id && activeBucket === null; return ( { onNavItemChange(item.id); onBucketChange(null); }} isActive={isActive} className="px-2" > {item.label} {item.count !== undefined && ( {item.count} )} ); })} دسته‌ها {buckets.map((bucket) => { const Icon = bucket.icon; return ( onBucketChange(bucket.id)} isActive={activeBucket === bucket.id} className="px-2" > {bucket.label} ); })}
); } interface TicketListPanelProps { tickets: Ticket[]; selectedTicketId: string | null; onTicketSelect: (ticketId: string) => void; activeNavItem: NavItemId; } function TicketListPanel({ tickets, selectedTicketId, onTicketSelect, activeNavItem, }: TicketListPanelProps) { const navItem = navItems.find((item) => item.id === activeNavItem); const title = navItem?.label ?? "صندوق ورودی"; return (
{title} شما
{tickets.map((ticket) => { const isSelected = selectedTicketId === ticket.id; return ( ); })}
); } interface MessageBubbleProps { message: Message; } function MessageBubble({ message }: MessageBubbleProps) { const sender = message.sender; const isCustomer = "company" in sender; return (
{getInitials(sender.name)}
{sender.name} {!isCustomer && ( پشتیبانی )}
از {sender.email}
{message.date}, {message.timestamp}
{message.content}
); } interface ReplyComposerProps { recipientEmail: string; respondingUser?: User; } function ReplyComposer({ recipientEmail, respondingUser }: ReplyComposerProps) { return (
{recipientEmail}