112 lines
3.5 KiB
TypeScript
112 lines
3.5 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import Link from "next/link";
|
|
import { usePathname } from "next/navigation";
|
|
import {
|
|
LayoutDashboard,
|
|
Activity,
|
|
Calendar,
|
|
Kanban,
|
|
FileText,
|
|
Wrench,
|
|
Target,
|
|
Menu,
|
|
X,
|
|
} from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
const navItems = [
|
|
{ name: "Dashboard", href: "/", icon: LayoutDashboard },
|
|
{ name: "Activity", href: "/activity", icon: Activity },
|
|
{ name: "Calendar", href: "/calendar", icon: Calendar },
|
|
{ name: "Tasks", href: "/tasks", icon: Kanban },
|
|
{ name: "Documents", href: "/documents", icon: FileText },
|
|
{ name: "Tool Builder", href: "/tools", icon: Wrench },
|
|
{ name: "Mission", href: "/mission", icon: Target },
|
|
];
|
|
|
|
function SidebarContent({ pathname }: { pathname: string }) {
|
|
return (
|
|
<div className="flex flex-col h-full">
|
|
<div className="flex items-center gap-2 px-4 py-6">
|
|
<div className="w-8 h-8 rounded-lg bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
|
<span className="text-white font-bold text-sm">MC</span>
|
|
</div>
|
|
<span className="font-bold text-lg">Mission Control</span>
|
|
</div>
|
|
|
|
<nav className="flex-1 px-3 py-4 space-y-1">
|
|
{navItems.map((item) => {
|
|
const Icon = item.icon;
|
|
const isActive = pathname === item.href;
|
|
return (
|
|
<Link
|
|
key={item.href}
|
|
href={item.href}
|
|
className={cn(
|
|
"flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-colors",
|
|
isActive
|
|
? "bg-primary text-primary-foreground"
|
|
: "text-muted-foreground hover:bg-accent hover:text-accent-foreground"
|
|
)}
|
|
>
|
|
<Icon className="w-4 h-4" />
|
|
{item.name}
|
|
</Link>
|
|
);
|
|
})}
|
|
</nav>
|
|
|
|
<div className="p-4 border-t border-border">
|
|
<div className="flex items-center gap-3">
|
|
<div className="w-8 h-8 rounded-full bg-gradient-to-br from-green-400 to-blue-500" />
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-sm font-medium truncate">Matt Bruce</p>
|
|
<p className="text-xs text-muted-foreground truncate">TopDogLabs</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function Sidebar() {
|
|
const pathname = usePathname();
|
|
const [open, setOpen] = useState(false);
|
|
|
|
return (
|
|
<>
|
|
{/* Desktop Sidebar */}
|
|
<div className="hidden lg:flex w-64 flex-col fixed inset-y-0 left-0 border-r border-border bg-card">
|
|
<SidebarContent pathname={pathname} />
|
|
</div>
|
|
|
|
{/* Mobile Sidebar */}
|
|
<Sheet open={open} onOpenChange={setOpen}>
|
|
<SheetTrigger asChild className="lg:hidden">
|
|
<Button variant="ghost" size="icon" className="absolute top-4 left-4 z-50">
|
|
<Menu className="w-5 h-5" />
|
|
</Button>
|
|
</SheetTrigger>
|
|
<SheetContent side="left" className="w-64 p-0">
|
|
<SidebarContent pathname={pathname} />
|
|
</SheetContent>
|
|
</Sheet>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export function DashboardLayout({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<div className="min-h-screen bg-background">
|
|
<Sidebar />
|
|
<main className="lg:pl-64">
|
|
<div className="p-4 lg:p-8">{children}</div>
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|