Files
buzz-sheet/components/admin/admin-sidebar.tsx
T

149 lines
4.6 KiB
TypeScript

"use client";
import Link from "next/link";
import { useRouter } from "next/navigation";
import {
BookOpenIcon,
BoxesIcon,
ChevronRightIcon,
LayoutTemplateIcon,
LogOutIcon,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
SidebarRail,
} from "@/components/ui/sidebar";
import type { CharacterIdentity, PageIdentity } from "@/lib/content/types";
import { authClient } from "@/lib/auth/client";
export interface AdminNavigation {
characters: Array<CharacterIdentity & { pages: PageIdentity[] }>;
templates: Array<{
id: string;
slug: string;
name: string;
description: string | null;
category: string;
builtIn: boolean;
}>;
}
export function AdminSidebar({
navigation,
currentCharacter,
currentPage,
}: {
navigation: AdminNavigation;
currentCharacter?: string;
currentPage?: string;
}) {
const router = useRouter();
return (
<Sidebar collapsible="icon">
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
size="lg"
tooltip="Buzz Sheet"
render={<Link href="/admin" />}
>
<span className="grid size-8 place-items-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<BookOpenIcon aria-hidden="true" />
</span>
<span className="grid flex-1 text-left leading-tight">
<span className="font-semibold">Buzz Sheet</span>
<span className="text-xs text-sidebar-foreground/60">ตัวแก้ไขคู่มือ</span>
</span>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>ตัวละครและหน้า</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{navigation.characters.map((character) => (
<SidebarMenuItem key={character.id}>
<SidebarMenuButton
tooltip={character.nameTh}
isActive={character.slug === currentCharacter && !currentPage}
>
<BoxesIcon aria-hidden="true" />
<span>{character.nameTh}</span>
<ChevronRightIcon aria-hidden="true" className="ml-auto" />
</SidebarMenuButton>
<SidebarMenuSub>
{character.pages.map((page) => (
<SidebarMenuSubItem key={page.id}>
<SidebarMenuSubButton
render={<Link href={`/admin/${character.slug}/${page.slug}`} />}
isActive={character.slug === currentCharacter && page.slug === currentPage}
>
<span>{page.title}</span>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))}
</SidebarMenuSub>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
<SidebarGroup>
<SidebarGroupLabel>โครงสร้าง</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
tooltip="เทมเพลต"
render={<Link href="/admin/templates" />}
>
<LayoutTemplateIcon aria-hidden="true" />
<span>เทมเพลต</span>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
<Button
variant="ghost"
className="w-full justify-start"
onClick={() =>
authClient.signOut({
fetchOptions: {
onSuccess: () => {
router.push("/admin/login");
router.refresh();
},
},
})
}
>
<LogOutIcon aria-hidden="true" />
<span className="group-data-[collapsible=icon]:hidden">ออกจากระบบ</span>
</Button>
</SidebarFooter>
<SidebarRail />
</Sidebar>
);
}