Organize/components/nav/side-nav.tsx

91 lines
3.6 KiB
TypeScript

"use client";
import { ChevronLeft, ChevronRight, LogOut, NotebookPen } from "lucide-react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { useSideNav } from "@/components/nav/side-nav-provider";
import { SideNavItem } from "@/components/nav/side-nav-item";
import { ProjectsNavSection } from "@/components/nav/projects-nav-section";
import { NAV_ITEMS, ADMIN_NAV_ITEM } from "@/components/nav/nav-items";
import { ThemeToggle } from "@/components/theme/theme-toggle";
import { logout } from "@/lib/actions/auth";
import { Role } from "@/lib/generated/prisma/enums";
export function SideNav({ userEmail, role }: { userEmail: string; role: Role }) {
const { collapsed, toggle } = useSideNav();
const adminItem = role === Role.ADMIN ? [ADMIN_NAV_ITEM] : [];
return (
<aside
className={cn(
"flex h-screen flex-col border-r bg-sidebar text-sidebar-foreground transition-[width] duration-300 ease-out",
collapsed ? "w-16" : "w-60"
)}
>
<div className={cn("flex items-center gap-2.5 px-4 py-4", collapsed && "justify-center px-0")}>
<span className="flex size-8 shrink-0 items-center justify-center rounded-xl bg-primary text-primary-foreground shadow-sm">
<NotebookPen className="size-4.5" />
</span>
{!collapsed && (
<span className="truncate font-heading text-[17px] font-bold tracking-tight">
Organize
</span>
)}
</div>
<nav className="flex flex-1 flex-col gap-0.5 overflow-y-auto px-2.5 pt-1 pb-2">
{NAV_ITEMS.map((item) => (
<SideNavItem key={item.href} item={item} collapsed={collapsed} />
))}
<ProjectsNavSection collapsed={collapsed} />
{adminItem.map((item) => (
<SideNavItem key={item.href} item={item} collapsed={collapsed} />
))}
</nav>
<div className="space-y-0.5 px-2.5 pb-2">
<ThemeToggle collapsed={collapsed} />
{collapsed ? (
<form action={logout}>
<Tooltip>
<TooltipTrigger
render={
<Button variant="ghost" size="icon" type="submit" className="w-full">
<LogOut className="size-4" />
</Button>
}
/>
<TooltipContent side="right">Log out ({userEmail})</TooltipContent>
</Tooltip>
</form>
) : (
<form action={logout}>
<Button variant="ghost" type="submit" className="w-full justify-start gap-2.5">
<LogOut className="size-4" />
<span className="truncate">Log out</span>
</Button>
</form>
)}
</div>
<div className={cn("flex items-center gap-2 border-t px-4 py-3", collapsed && "justify-center px-0")}>
<span className="flex size-7 shrink-0 items-center justify-center rounded-full bg-primary/10 text-xs font-bold text-primary uppercase">
{(userEmail[0] ?? "?").slice(0, 1)}
</span>
{!collapsed && (
<span className="truncate text-[13px] font-medium text-muted-foreground">{userEmail}</span>
)}
</div>
<div className={cn("flex border-t px-2 py-1.5", collapsed ? "justify-center" : "justify-end")}>
<Button variant="ghost" size="icon" onClick={toggle} aria-label="Toggle sidebar">
{collapsed ? <ChevronRight className="size-4" /> : <ChevronLeft className="size-4" />}
</Button>
</div>
</aside>
);
}