Initial commit
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { cn } from '@/lib/utils';
|
||||
import Image from 'next/image';
|
||||
import { Josefin_Sans } from 'next/font/google';
|
||||
import { Montserrat } from 'next/font/google';
|
||||
import {
|
||||
LayoutDashboard,
|
||||
FolderOpen,
|
||||
Users,
|
||||
UserCog,
|
||||
Settings,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
ListTodo,
|
||||
CalendarRange,
|
||||
} from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
const navItems = [
|
||||
{ href: '/dashboard', label: 'Dashboard', icon: LayoutDashboard },
|
||||
{ href: '/projects', label: 'Projects', icon: FolderOpen },
|
||||
{ href: '/tasks', label: 'My Tasks', icon: ListTodo, hideForClient: true },
|
||||
{ href: '/schedule', label: 'Schedule', icon: CalendarRange, adminOnly: true },
|
||||
{ href: '/clients', label: 'Clients', icon: Users, adminOnly: true },
|
||||
{ href: '/users', label: 'Users', icon: UserCog, adminOnly: true, adminStrictOnly: true },
|
||||
{ href: '/settings', label: 'Settings', icon: Settings },
|
||||
];
|
||||
|
||||
const josefin = Josefin_Sans({
|
||||
subsets: ['latin'],
|
||||
weight: ['300', '400'],
|
||||
});
|
||||
const montserrat = Montserrat({
|
||||
subsets: ['latin'],
|
||||
weight: ['200', '500', '600'],
|
||||
});
|
||||
|
||||
export function Sidebar() {
|
||||
const pathname = usePathname();
|
||||
const { data: session } = useSession();
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const isAdmin = ['ADMIN', 'PRODUCER'].includes(session?.user?.role ?? '');
|
||||
|
||||
return (
|
||||
<aside
|
||||
className={cn(
|
||||
'flex flex-col border-r border-zinc-800 bg-zinc-900 transition-all duration-200',
|
||||
collapsed ? 'w-16' : 'w-60',
|
||||
)}
|
||||
>
|
||||
{/* Logo */}
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center gap-3 px-4 py-5 border-b border-zinc-800',
|
||||
collapsed && 'justify-center px-0',
|
||||
)}
|
||||
>
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-md bg-black">
|
||||
<Image src="/logo.svg" alt="Logo" width={32} height={32} />
|
||||
</div>
|
||||
|
||||
{!collapsed && (
|
||||
<div className={montserrat.className}>
|
||||
<span className="block text-2xl font-light text-white leading-none">
|
||||
TWO TALES
|
||||
</span>
|
||||
|
||||
<span className="block text-[11px] tracking-[0.18em] italic text-zinc-400 leading-none -mt-0.25">
|
||||
vfx review
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Navigation */}
|
||||
<nav className="flex-1 px-2 py-4 space-y-1">
|
||||
{navItems.map((item) => {
|
||||
if (item.adminOnly && !isAdmin) return null;
|
||||
if ((item as any).adminStrictOnly && session?.user?.role !== 'ADMIN') return null;
|
||||
if ((item as any).hideForClient && session?.user?.role === 'CLIENT')
|
||||
return null;
|
||||
const Icon = item.icon;
|
||||
const isActive =
|
||||
pathname === item.href || pathname.startsWith(item.href + '/');
|
||||
|
||||
return (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className={cn(
|
||||
'flex items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors',
|
||||
collapsed && 'justify-center px-0 w-full',
|
||||
isActive
|
||||
? 'bg-amber-500/10 text-amber-400'
|
||||
: 'text-zinc-400 hover:text-white hover:bg-zinc-800',
|
||||
)}
|
||||
title={collapsed ? item.label : undefined}
|
||||
>
|
||||
<Icon className="h-4 w-4 shrink-0" />
|
||||
{!collapsed && <span>{item.label}</span>}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
|
||||
{/* Collapse toggle */}
|
||||
<div className="border-t border-zinc-800 p-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
className="w-full"
|
||||
onClick={() => setCollapsed(!collapsed)}
|
||||
title={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
|
||||
>
|
||||
{collapsed ? (
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
) : (
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user