Files

322 lines
10 KiB
TypeScript

"use client";
import {
Book,
ChevronRight,
ExternalLink,
FileText,
Search,
} from "lucide-react";
import * as React from "react";
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { Label } from "@/components/ui/label";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Separator } from "@/components/ui/separator";
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarInput,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarTrigger,
} from "@/components/ui/sidebar";
import { cn } from "@/lib/utils";
// Documentation structure
const docsNav = [
{
title: "شروع کار",
defaultOpen: true,
items: [
{ title: "مقدمه", href: "#", isActive: true },
{ title: "راه‌اندازی حساب", href: "#" },
{ title: "ساختار فضای کاری", href: "#" },
{ title: "پیکربندی", href: "#" },
],
},
{
title: "مفاهیم اصلی",
defaultOpen: true,
items: [
{ title: "ماژول‌ها", href: "#" },
{ title: "سفارشی‌سازی", href: "#" },
{ title: "تم برند", href: "#" },
{ title: "حالت تاریک", href: "#" },
{ title: "فیلدهای سفارشی", href: "#" },
],
},
{
title: "فهرست ماژول‌ها",
defaultOpen: false,
items: [
{ title: "Accordion", href: "#" },
{ title: "Alert", href: "#" },
{ title: "Avatar", href: "#" },
{ title: "Badge", href: "#" },
{ title: "Button", href: "#" },
{ title: "Card", href: "#" },
{ title: "Checkbox", href: "#" },
{ title: "Dialog", href: "#" },
{ title: "Dropdown Menu", href: "#" },
{ title: "Input", href: "#" },
{ title: "Select", href: "#" },
{ title: "Sidebar", href: "#" },
{ title: "Table", href: "#" },
{ title: "Tabs", href: "#" },
{ title: "Toast", href: "#" },
],
},
{
title: "راهنماها",
defaultOpen: false,
items: [
{ title: "دسترسی کاربران", href: "#" },
{ title: "فرم لید", href: "#" },
{ title: "درون‌ریزی مخاطب", href: "#" },
{ title: "مراحل فرصت", href: "#" },
{ title: "آزمایش جریان", href: "#" },
{ title: "انتشار اتوماسیون", href: "#" },
],
},
{
title: "مرجع API",
defaultOpen: false,
items: [
{ title: "CLI", href: "#" },
{ title: "پیکربندی", href: "#" },
{ title: "ابزارها", href: "#" },
],
},
];
// On this page - table of contents
const tableOfContents = [
{ title: "نمای کلی", href: "#overview", level: 1 },
{ title: "پیش‌نیازها", href: "#prerequisites", level: 2 },
{ title: "شروع سریع", href: "#quick-start", level: 1 },
{ title: "استفاده از API", href: "#using-the-cli", level: 2 },
{ title: "راه‌اندازی دستی", href: "#manual-setup", level: 2 },
{ title: "پیکربندی", href: "#configuration", level: 1 },
{ title: "گزینه‌های پایه", href: "#basic-options", level: 2 },
{ title: "گزینه‌های پیشرفته", href: "#advanced-options", level: 2 },
{ title: "گام‌های بعدی", href: "#next-steps", level: 1 },
];
const SearchForm = () => {
return (
<form>
<SidebarGroup className="py-0">
<SidebarGroupContent className="relative">
<Label htmlFor="search" className="sr-only">
جستجو
</Label>
<SidebarInput
id="search"
placeholder="جستجو در راهنمای وندوک..."
className="ps-8"
/>
<Search className="pointer-events-none absolute top-1/2 start-2 size-4 -translate-y-1/2 opacity-50 select-none" />
</SidebarGroupContent>
</SidebarGroup>
</form>
);
};
const DocSection = ({ section }: { section: (typeof docsNav)[0] }) => {
const [isOpen, setIsOpen] = React.useState(section.defaultOpen);
return (
<Collapsible open={isOpen} onOpenChange={setIsOpen}>
<SidebarGroup className="py-0">
<SidebarGroupLabel asChild className="group/label">
<CollapsibleTrigger className="flex w-full items-center">
<ChevronRight className="ms-1 size-3.5 transition-transform group-data-[state=open]/label:rotate-90" />
<span>{section.title}</span>
</CollapsibleTrigger>
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
{section.items.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild isActive={item.isActive}>
<a href={item.href}>
<FileText className="size-4" />
<span>{item.title}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</CollapsibleContent>
</SidebarGroup>
</Collapsible>
);
};
const SidebarLeft = ({ ...props }: React.ComponentProps<typeof Sidebar>) => {
return (
<Sidebar side="right" {...props}>
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size="lg" asChild>
<a href="#">
<div className="flex aspect-square size-8 items-center justify-center rounded-sm bg-primary">
<Book className="size-5 text-primary-foreground" />
</div>
<div className="grid flex-1 text-start text-sm leading-tight">
<span className="truncate font-semibold">مستندات</span>
<span className="truncate text-xs text-muted-foreground">
v2.0.0
</span>
</div>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
<SearchForm />
</SidebarHeader>
<SidebarContent className="overflow-hidden">
<ScrollArea className="min-h-0 flex-1">
{docsNav.map((section) => (
<DocSection key={section.title} section={section} />
))}
{/* لینک‌های خارجی */}
<SidebarGroup className="mt-auto">
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#" target="_blank" rel="noopener noreferrer">
<ExternalLink className="size-4" />
<span>وضعیت سرویس</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#" target="_blank" rel="noopener noreferrer">
<ExternalLink className="size-4" />
<span>انجمن کاربران</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</ScrollArea>
</SidebarContent>
</Sidebar>
);
};
const SidebarRight = ({ ...props }: React.ComponentProps<typeof Sidebar>) => {
const [activeSection, setActiveSection] = React.useState("#overview");
return (
<Sidebar
side="left"
collapsible="none"
className="sticky top-0 hidden h-svh w-56 border-s lg:flex"
{...props}
>
<SidebarHeader className="h-16 justify-center border-b">
<div className="px-2">
<span className="text-sm font-medium">در این صفحه</span>
</div>
</SidebarHeader>
<SidebarContent className="overflow-hidden">
<ScrollArea className="min-h-0 flex-1">
<SidebarGroup>
<SidebarGroupContent>
<nav className="flex flex-col gap-1">
{tableOfContents.map((item) => (
<a
key={item.href}
href={item.href}
onClick={() => setActiveSection(item.href)}
className={cn(
"block rounded-md px-2 py-1 text-sm transition-colors hover:text-foreground",
item.level === 2 && "ps-4",
activeSection === item.href
? "font-medium text-foreground"
: "text-muted-foreground",
)}
>
{item.title}
</a>
))}
</nav>
</SidebarGroupContent>
</SidebarGroup>
</ScrollArea>
</SidebarContent>
</Sidebar>
);
};
interface Sidebar20Props {
className?: string;
}
const Sidebar20 = ({ className }: Sidebar20Props) => {
return (
<SidebarProvider dir="rtl" lang="fa" className={cn(className)}>
<SidebarLeft />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 border-b px-4">
<SidebarTrigger className="-ms-1" />
<Separator
orientation="vertical"
className="ms-2 data-[orientation=vertical]:h-4"
/>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">مستندات</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">شروع کار</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>مقدمه</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
<SidebarRight />
</SidebarProvider>
);
};
export { Sidebar20 };