169 lines
3.9 KiB
TypeScript
169 lines
3.9 KiB
TypeScript
"use client"
|
|
|
|
import {
|
|
BarChart,
|
|
Clipboard,
|
|
Home,
|
|
Package,
|
|
Shield,
|
|
ShoppingCart,
|
|
User,
|
|
} from "lucide-react"
|
|
import Link from "next/link"
|
|
import { usePathname } from "next/navigation"
|
|
import {
|
|
Sidebar,
|
|
SidebarContent,
|
|
SidebarGroup,
|
|
SidebarGroupContent,
|
|
SidebarHeader,
|
|
SidebarMenu,
|
|
SidebarMenuButton,
|
|
SidebarMenuItem,
|
|
} from "@/components/ui/sidebar"
|
|
import type { UserRole } from "@/generated/prisma/client"
|
|
import type { Dictionary } from "@/i18n/dictionaries"
|
|
|
|
import { SidebarSection } from "./sidebar/sidebarSection"
|
|
|
|
type SidebarCopy = Dictionary["layout"]["sidebar"]
|
|
|
|
type SidebarLabelKey = keyof SidebarCopy
|
|
|
|
type SidebarItem =
|
|
| {
|
|
type: "item"
|
|
labelKey: SidebarLabelKey
|
|
url: string
|
|
icon: React.ElementType
|
|
}
|
|
| {
|
|
type: "section"
|
|
labelKey: SidebarLabelKey
|
|
url: string
|
|
icon: React.ElementType
|
|
items: { labelKey: SidebarLabelKey; url: string }[]
|
|
}
|
|
|
|
const items: SidebarItem[] = [
|
|
{
|
|
type: "item",
|
|
labelKey: "home",
|
|
url: "/",
|
|
icon: Home,
|
|
},
|
|
{
|
|
type: "section",
|
|
labelKey: "inventory",
|
|
url: "#",
|
|
icon: Package,
|
|
items: [
|
|
{
|
|
labelKey: "items",
|
|
url: "/inventory/items",
|
|
},
|
|
{
|
|
labelKey: "categories",
|
|
url: "/inventory/categories",
|
|
},
|
|
{
|
|
labelKey: "assets",
|
|
url: "/inventory/assets",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
type: "item",
|
|
labelKey: "recipients",
|
|
url: "/recipients",
|
|
icon: User,
|
|
},
|
|
{
|
|
type: "item",
|
|
labelKey: "movements",
|
|
url: "/movements",
|
|
icon: BarChart,
|
|
},
|
|
{
|
|
type: "item",
|
|
labelKey: "assignments",
|
|
url: "/assignments",
|
|
icon: Clipboard,
|
|
},
|
|
]
|
|
|
|
export default function AppSidebar({
|
|
copy,
|
|
userRole,
|
|
...props
|
|
}: React.ComponentProps<typeof Sidebar> & {
|
|
copy: SidebarCopy
|
|
userRole?: UserRole
|
|
}) {
|
|
const pathname = usePathname()
|
|
const visibleItems =
|
|
userRole === "ADMIN"
|
|
? [
|
|
...items,
|
|
{
|
|
type: "item",
|
|
labelKey: "users",
|
|
url: "/admin/users",
|
|
icon: Shield,
|
|
} satisfies SidebarItem,
|
|
]
|
|
: items
|
|
|
|
return (
|
|
<Sidebar {...props}>
|
|
<SidebarHeader className="flex items-center gap-2 p-4">
|
|
<Link href="/" className="flex flex-col items-center gap-2">
|
|
<ShoppingCart className="h-6 w-6" />
|
|
<span>Stock Manager</span>
|
|
</Link>
|
|
</SidebarHeader>
|
|
<SidebarContent className="flex flex-col gap-1 p-2">
|
|
<SidebarGroup>
|
|
<SidebarGroupContent>
|
|
<SidebarMenu>
|
|
{visibleItems.map((item) => {
|
|
if (item.type === "item") {
|
|
const isActive =
|
|
item.url === "/"
|
|
? pathname === "/"
|
|
: pathname.startsWith(item.url)
|
|
|
|
return (
|
|
<SidebarMenuItem key={`item-${item.labelKey}`}>
|
|
<SidebarMenuButton asChild isActive={isActive}>
|
|
<Link href={item.url}>
|
|
<item.icon className="mr-2 h-4 w-4" />
|
|
<span>{copy[item.labelKey]}</span>
|
|
</Link>
|
|
</SidebarMenuButton>
|
|
</SidebarMenuItem>
|
|
)
|
|
}
|
|
if (item.type === "section") {
|
|
return (
|
|
<SidebarSection
|
|
key={`section-${item.labelKey}`}
|
|
title={copy[item.labelKey]}
|
|
icon={item.icon}
|
|
items={item.items.map((subItem) => ({
|
|
title: copy[subItem.labelKey],
|
|
url: subItem.url,
|
|
}))}
|
|
/>
|
|
)
|
|
}
|
|
return null
|
|
})}
|
|
</SidebarMenu>
|
|
</SidebarGroupContent>
|
|
</SidebarGroup>
|
|
</SidebarContent>
|
|
</Sidebar>
|
|
)
|
|
}
|