"use client"; import { motion } from "framer-motion"; import { BadgeCheck, Bell, Bookmark, ChevronDown, ClipboardCheck, Clock, CreditCard, FileText, Folder, Hash, Inbox, Layers, LayoutGrid, LogOut, MessageSquare, MessageSquareText, MessagesSquare, PhoneCall, Pin, Settings, Sparkles, UserPlus, Users, } from "lucide-react"; import * as React from "react"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Badge } from "@/components/ui/badge"; import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "@/components/ui/breadcrumb"; import { Button } from "@/components/ui/button"; import { Drawer, DrawerContent, DrawerHeader, DrawerTitle, } from "@/components/ui/drawer"; import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger, } from "@/components/ui/sheet"; import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarProvider, SidebarTrigger, useSidebar, } from "@/components/ui/sidebar"; import { cn } from "@/lib/utils"; type ModuleId = "messages" | "spaces" | "threads" | "calls" | "files"; type NavItem = { label: string; icon: React.ComponentType>; href: string; badge?: string; active?: boolean; }; type NavSection = { title?: string; items: NavItem[]; }; type NavModule = { id: ModuleId; label: string; icon: NavItem["icon"]; sections: NavSection[]; }; function getItemKey(moduleId: ModuleId, item: NavItem) { return `${moduleId}:${item.label}`; } function getDefaultItemKey(module: NavModule) { const items = module.sections.flatMap((section) => section.items); const activeItem = items.find((item) => item.active) ?? items[0]; return activeItem ? getItemKey(module.id, activeItem) : `${module.id}:`; } function getActiveItemLabel(module: NavModule, activeItemKey: string) { const items = module.sections.flatMap((section) => section.items); const match = items.find( (item) => getItemKey(module.id, item) === activeItemKey, ); return match?.label ?? module.sections[0]?.items[0]?.label ?? module.label; } function getInitials(name: string) { return ( name .split(" ") .filter(Boolean) .slice(0, 2) .map((part) => part[0]?.toUpperCase()) .join("") || "U" ); } const navModules: NavModule[] = [ { id: "messages", label: "پیام‌ها", icon: MessagesSquare, sections: [ { title: "صندوق ورودی", items: [ { label: "همه پیام‌ها", icon: Inbox, href: "#", active: true }, { label: "ارجاع‌ها", icon: UserPlus, href: "#", badge: "۴" }, { label: "اعلان‌ها", icon: Bell, href: "#", badge: "۱۲" }, { label: "ذخیره‌شده", icon: Bookmark, href: "#" }, ], }, { title: "نماها", items: [ { label: "خوانده‌نشده", icon: Bell, href: "#" }, { label: "زمان‌بندی‌شده", icon: Clock, href: "#" }, ], }, ], }, { id: "spaces", label: "فضاها", icon: LayoutGrid, sections: [ { title: "فضاها", items: [ { label: "به‌روزرسانی محصول", icon: Hash, href: "#", active: true }, { label: "موفقیت مشتری", icon: Users, href: "#", badge: "۲" }, { label: "عملیات انتشار", icon: Layers, href: "#" }, ], }, { title: "مستقیم", items: [ { label: "Kai", icon: Users, href: "#", badge: "۱" }, { label: "Mina", icon: Users, href: "#" }, { label: "Diego", icon: Users, href: "#" }, ], }, ], }, { id: "threads", label: "گفتگوها", icon: MessageSquareText, sections: [ { title: "گفتگوها", items: [ { label: "دنبال‌شده", icon: Bookmark, href: "#", active: true }, { label: "محول‌شده", icon: Users, href: "#" }, { label: "بسته‌شده", icon: MessageSquareText, href: "#" }, ], }, { title: "برجسته‌ها", items: [ { label: "ارجاع‌ها", icon: UserPlus, href: "#", badge: "۳" }, { label: "سنجاق‌شده", icon: Bookmark, href: "#" }, ], }, ], }, { id: "calls", label: "تماس‌ها", icon: PhoneCall, sections: [ { title: "جلسات", items: [ { label: "پیش‌رو", icon: Clock, href: "#", active: true }, { label: "ضبط‌ها", icon: FileText, href: "#" }, ], }, { title: "دستگاه‌ها", items: [ { label: "صدا و تصویر", icon: PhoneCall, href: "#" }, { label: "اعلان‌ها", icon: Bell, href: "#" }, ], }, ], }, { id: "files", label: "فایل‌ها", icon: Folder, sections: [ { title: "مرور", items: [ { label: "اخیر", icon: Clock, href: "#", active: true }, { label: "اشتراکی با من", icon: Users, href: "#" }, { label: "بارگذاری‌ها", icon: Folder, href: "#" }, { label: "مجموعه‌ها", icon: Layers, href: "#" }, ], }, { title: "فیلترهای سریع", items: [ { label: "اسناد", icon: FileText, href: "#" }, { label: "نظرات خوانده‌نشده", icon: Bell, href: "#", badge: "۵" }, ], }, ], }, ]; const utilities: NavItem[] = [ { label: "اعلان‌ها", icon: Bell, href: "#" }, { label: "تنظیمات", icon: Settings, href: "#" }, ]; const data = { user: { name: "علی رضایی", email: "ali@example.com", avatar: "/block-media/shadcnblocks/block/avatar/avatar3.webp", }, participants: [ { id: "you", name: "علی رضایی", title: "شما", status: "online", }, { id: "riley", name: "ریحانه Park", title: "محصول", status: "online", }, { id: "sam", name: "Sam Rivera", title: "طراحی", status: "away", }, { id: "noah", name: "Noah Patel", title: "مهندسی", status: "offline", }, { id: "maya", name: "نگار Singh", title: "پشتیبانی", status: "online", }, { id: "jules", name: "Jules Tan", title: "عملیات", status: "offline", }, ] as const, activity: [ { id: "a1", icon: MessageSquare, title: "گفتگوی جدید شروع شد", detail: "Riley در به‌روزرسانی محصول پست گذاشت.", time: "۲ دقیقه", }, { id: "a2", icon: UserPlus, title: "ارجاع جدید", detail: "سام شما را به تیکت پشتیبانی مشتری ارجاع داد.", time: "۱۸ دقیقه", }, { id: "a3", icon: Pin, title: "پیام سنجاق شد", detail: "Maya «چک‌لیست انتشار نسخه ۳» را سنجاق کرد.", time: "۱ ساعت", }, { id: "a4", icon: ClipboardCheck, title: "وظیفه تکمیل شد", detail: "Noah «پاکسازی API» را انجام‌شده علامت زد.", time: "امروز", }, { id: "a5", icon: PhoneCall, title: "تماس پایان یافت", detail: "همگام‌سازی هفتگی • ۲۴ دقیقه", time: "دیروز", }, { id: "a6", icon: FileText, title: "فایل بارگذاری شد", detail: "Jules «incident-notes.pdf» را به اشتراک گذاشت.", time: "دیروز", }, ] as const, }; interface ShellBreadcrumbProps { className?: string; moduleLabel: string; itemLabel: string; } function ShellBreadcrumb({ className, moduleLabel, itemLabel, }: ShellBreadcrumbProps) { return ( {moduleLabel} {itemLabel} ); } interface ModulePanelProps { className?: string; module: NavModule; activeItemKey: string; onSelectItem: (key: string) => void; } function ModulePanel({ className, module, activeItemKey, onSelectItem, }: ModulePanelProps) { return (
{module.sections.map((section, index) => (
{section.title && ( {section.title} )} {section.items.map((item) => { const Icon = item.icon; const itemKey = getItemKey(module.id, item); return ( { e.preventDefault(); onSelectItem(itemKey); }} > {item.badge && ( {item.badge} )} {item.label} ); })}
))}
ترجیحات {utilities.map((item) => { const Icon = item.icon; return ( {item.label} ); })}
); } interface AppSidebarProps extends Omit< React.ComponentProps, "className" > { className?: string; activeKey: ModuleId; activeItemKey: string; onNavChange: (key: ModuleId) => void; onItemChange: (key: string) => void; } function AppSidebar({ className, activeKey, activeItemKey, onNavChange, onItemChange, ...props }: AppSidebarProps) { const { state, setOpen, isMobile } = useSidebar(); const isCollapsed = state === "collapsed"; const showFooter = isCollapsed || isMobile; const activeModule = navModules.find((module) => module.id === activeKey) ?? navModules[0]; return (
شاد‌سی‌ان بلاکس
ری یو آی
{" "} {navModules.map((module) => { const Icon = module.icon; return ( { onNavChange(module.id); setOpen(true); }} isActive={activeKey === module.id} aria-label={module.label} className="px-2.5 md:px-2" > {module.label} ); })} {utilities.map((item) => { const Icon = item.icon; return ( {item.label} ); })} {" "}
تنظیمات فضای کار ⌥⇧S دعوت هم‌تیمی‌ها دعوت به Pulse
EM
دعوت با ایمیل
LK
کپی لینک دعوت ⌘C
دعوت‌های در انتظار نقش‌ها و دسترسی
خروج ⌥⇧Q
); } interface NavUserProps { className?: string; user: { name: string; email: string; avatar: string; }; } function NavUser({ className, user }: NavUserProps) { const { isMobile } = useSidebar(); const initials = getInitials(user.name); return ( {initials} {user.name}
{initials}
{user.name} {user.email}
ارتقا به حرفه‌ای حساب کاربری صورتحساب اعلان‌ها خروج
); } interface SidebarRightProps extends Omit< React.ComponentProps, "className" > { className?: string; } function RightPanelContent() { return (
شرکت‌کنندگان
{data.participants.map((participant) => { const statusClassName = participant.status === "online" ? "bg-emerald-500" : participant.status === "away" ? "bg-amber-500" : "bg-muted-foreground/50"; const initials = getInitials(participant.name); const isYou = participant.id === "you"; return ( ); })}
فعالیت تیم‌ها
{data.activity.map((event) => { const Icon = event.icon; return (
{event.title}
{event.time}
{event.detail}
); })}
); } export function SidebarRight({ className, ...props }: SidebarRightProps) { return ( ); } interface ApplicationShell7Props { className?: string; } export function ApplicationShell7({ className }: ApplicationShell7Props) { const [activeKey, setActiveKey] = React.useState(navModules[0].id); const [isMobilePanelOpen, setIsMobilePanelOpen] = React.useState(false); const [activeItemKey, setActiveItemKey] = React.useState(() => getDefaultItemKey(navModules[0]), ); const activeModule = navModules.find((module) => module.id === activeKey) ?? navModules[0]; const activeItemLabel = getActiveItemLabel(activeModule, activeItemKey); React.useEffect(() => { setActiveItemKey(getDefaultItemKey(activeModule)); }, [activeModule]); return (
شاد‌سی‌ان بلاکس
تیم
{activeModule.label}
{ setActiveItemKey(key); setIsMobilePanelOpen(false); }} />
); }