125 lines
2.9 KiB
TypeScript
125 lines
2.9 KiB
TypeScript
"use client";
|
|
|
|
import type React from "react";
|
|
|
|
import { cn } from "@/lib/utils";
|
|
import {
|
|
BookOpen,
|
|
Share2,
|
|
Palette,
|
|
GitFork,
|
|
Building2,
|
|
Users,
|
|
User,
|
|
Calendar,
|
|
} from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
import { useRouter, usePathname } from "next/navigation";
|
|
|
|
interface SidebarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
}
|
|
|
|
const menuItems = [
|
|
{
|
|
title: "Users",
|
|
icon: Users,
|
|
href: "/users",
|
|
},
|
|
{
|
|
title: "Calendar",
|
|
icon: Calendar,
|
|
href: "http://cloud.neah.local/apps/calendar/dayGridMonth/now",
|
|
external: true,
|
|
},
|
|
{
|
|
title: "Flow",
|
|
icon: Share2,
|
|
href: "/flow",
|
|
iframe: "https://example.com/flow",
|
|
},
|
|
{
|
|
title: "Design",
|
|
icon: Palette,
|
|
href: "/design",
|
|
iframe: "https://example.com/design",
|
|
},
|
|
{
|
|
title: "GitLab",
|
|
icon: GitFork,
|
|
href: "/gitlab",
|
|
iframe: "https://gitlab.com",
|
|
badge: 1,
|
|
},
|
|
{
|
|
title: "CRM",
|
|
icon: Building2,
|
|
href: "/crm",
|
|
iframe: "https://example.com/crm",
|
|
},
|
|
{
|
|
title: "The Great Missions",
|
|
icon: Users,
|
|
href: "/missions",
|
|
iframe: "https://example.com/missions",
|
|
},
|
|
];
|
|
|
|
export function Sidebar({ isOpen, onClose, className }: SidebarProps) {
|
|
const router = useRouter();
|
|
const pathname = usePathname();
|
|
|
|
const handleNavigation = (href: string, external?: boolean) => {
|
|
if (external) {
|
|
window.open(href, "_blank");
|
|
} else {
|
|
router.push(href);
|
|
}
|
|
onClose();
|
|
};
|
|
|
|
return (
|
|
<>
|
|
{isOpen && (
|
|
<div
|
|
className='fixed inset-0 z-40 bg-background/80 backdrop-blur-sm'
|
|
onClick={onClose}
|
|
/>
|
|
)}
|
|
<div
|
|
className={cn(
|
|
"fixed top-0 left-0 z-50 h-full w-64 transform bg-black text-white transition-transform duration-200 ease-in-out",
|
|
isOpen ? "translate-x-0" : "-translate-x-full",
|
|
className
|
|
)}
|
|
>
|
|
<ScrollArea className='h-full w-full'>
|
|
<div className='space-y-1 p-4'>
|
|
{menuItems.map((item) => (
|
|
<Button
|
|
key={item.title}
|
|
variant='ghost'
|
|
className={cn(
|
|
"w-full justify-start gap-2 text-white hover:bg-gray-800 hover:text-white",
|
|
pathname === item.href && !item.external && "bg-gray-800"
|
|
)}
|
|
onClick={() => handleNavigation(item.href, item.external)}
|
|
>
|
|
<item.icon className='h-5 w-5' />
|
|
<span>{item.title}</span>
|
|
{item.badge && (
|
|
<span className='ml-auto flex h-5 w-5 items-center justify-center rounded-full bg-blue-500 text-xs text-white'>
|
|
{item.badge}
|
|
</span>
|
|
)}
|
|
</Button>
|
|
))}
|
|
</div>
|
|
</ScrollArea>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|