mirror of
https://github.com/xCyanGrizzly/DragonsStash.git
synced 2026-05-11 06:11:15 +00:00
121 lines
3.1 KiB
TypeScript
121 lines
3.1 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import Link from "next/link";
|
|
import { usePathname } from "next/navigation";
|
|
import { useSession } from "next-auth/react";
|
|
import {
|
|
LayoutDashboard,
|
|
Cylinder,
|
|
Droplets,
|
|
Paintbrush,
|
|
Gem,
|
|
FileBox,
|
|
Send,
|
|
ClipboardList,
|
|
Building2,
|
|
MapPin,
|
|
Settings,
|
|
Flame,
|
|
PanelLeftClose,
|
|
PanelLeft,
|
|
} from "lucide-react";
|
|
import { cn } from "@/lib/utils";
|
|
import { APP_NAME, NAV_ITEMS } from "@/lib/constants";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
|
|
|
const icons = {
|
|
LayoutDashboard,
|
|
Cylinder,
|
|
Droplets,
|
|
Paintbrush,
|
|
Gem,
|
|
FileBox,
|
|
Send,
|
|
ClipboardList,
|
|
Building2,
|
|
MapPin,
|
|
Settings,
|
|
} as const;
|
|
|
|
export function Sidebar() {
|
|
const pathname = usePathname();
|
|
const [collapsed, setCollapsed] = useState(false);
|
|
const { data: session } = useSession();
|
|
const isAdmin = session?.user?.role === "ADMIN";
|
|
|
|
const visibleItems = NAV_ITEMS.filter((item) => !item.adminOnly || isAdmin);
|
|
|
|
return (
|
|
<aside
|
|
className={cn(
|
|
"flex h-screen flex-col border-r border-border bg-card transition-all duration-200",
|
|
collapsed ? "w-16" : "w-60"
|
|
)}
|
|
>
|
|
{/* Logo */}
|
|
<div className="flex h-14 items-center gap-2 border-b border-border px-4">
|
|
<Flame className="h-6 w-6 shrink-0 text-primary" />
|
|
{!collapsed && (
|
|
<span className="text-sm font-bold tracking-tight">{APP_NAME}</span>
|
|
)}
|
|
</div>
|
|
|
|
{/* Navigation */}
|
|
<nav className="flex-1 space-y-1 p-2">
|
|
{visibleItems.map((item) => {
|
|
const Icon = icons[item.icon];
|
|
const isActive = pathname.startsWith(item.href);
|
|
|
|
const link = (
|
|
<Link
|
|
key={item.href}
|
|
href={item.href}
|
|
className={cn(
|
|
"flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors",
|
|
isActive
|
|
? "border-l-2 border-primary bg-primary/10 text-primary"
|
|
: "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
)}
|
|
>
|
|
<Icon className="h-4 w-4 shrink-0" />
|
|
{!collapsed && <span>{item.label}</span>}
|
|
</Link>
|
|
);
|
|
|
|
if (collapsed) {
|
|
return (
|
|
<Tooltip key={item.href}>
|
|
<TooltipTrigger asChild>{link}</TooltipTrigger>
|
|
<TooltipContent side="right">{item.label}</TooltipContent>
|
|
</Tooltip>
|
|
);
|
|
}
|
|
|
|
return link;
|
|
})}
|
|
</nav>
|
|
|
|
{/* Collapse toggle */}
|
|
<div className="border-t border-border p-2">
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="w-full justify-center"
|
|
onClick={() => setCollapsed(!collapsed)}
|
|
>
|
|
{collapsed ? (
|
|
<PanelLeft className="h-4 w-4" />
|
|
) : (
|
|
<>
|
|
<PanelLeftClose className="h-4 w-4 mr-2" />
|
|
<span className="text-xs">Collapse</span>
|
|
</>
|
|
)}
|
|
</Button>
|
|
</div>
|
|
</aside>
|
|
);
|
|
}
|