Kuma/src/modules/dashboard/ui/components/DashboardSidebar.tsx
2026-08-17 15:32:22 +02:00

165 lines
4.6 KiB
TypeScript

"use client";
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupContent,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from "@/src/components/ui/sidebar";
import { CreditCard, DoorOpen, Dumbbell, IdCardLanyard, LayoutDashboard, User } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
import { usePathname } from "next/navigation";
import Logo from "@/src/public/logo-dark.png";
import { cn } from "@/src/lib/utils";
import DashboardFooter from "./DashboardFooter";
import type { AuthUserData, EmployeeData } from "@/src/lib/auth/getUser";
import { useSidebar } from "@/src/components/ui/sidebar";
type MenuItem = {
icon: React.ComponentType<{ className?: string }>;
label: string;
href: string;
roles?: string[];
permission?: (p: EmployeeData["permissions"]) => boolean;
};
const allMenuItems: MenuItem[] = [
{
icon: LayoutDashboard,
label: "Dashboard",
href: "/dashboard",
roles: ["manager", "user", "employee"],
},
{
icon: Dumbbell,
label: "Meine Kurse",
href: "/courses/myCourses",
roles: ["user"],
},
{
icon: Dumbbell,
label: "Kurse",
href: "/courses",
roles: ["manager"],
},
{
icon: Dumbbell,
label: "Kurse",
href: "/courses",
roles: ["employee"],
permission: (p) => p.courses.view,
},
{
icon: IdCardLanyard,
label: "Mitarbeiter",
href: "/employee",
roles: ["manager"],
},
{
icon: IdCardLanyard,
label: "Mitarbeiter",
href: "/employee",
roles: ["employee"],
permission: (p) => p.employees.view,
},
{
icon: User,
label: "Kunden",
href: "/kunden",
roles: ["manager"],
},
{
icon: CreditCard,
label: "Zahlungen",
href: "/zahlungen",
roles: ["manager"],
},
{
icon: DoorOpen,
label: "Räume",
href: "/rooms",
roles: ["manager"],
},
{
icon: DoorOpen,
label: "Räume",
href: "/rooms",
roles: ["employee"],
permission: (p) => p.rooms.view,
},
];
interface DashboardSidebarProps {
userData: AuthUserData;
displayName: string;
}
const DashboardSidebar = ({ userData, displayName }: DashboardSidebarProps) => {
const pathname = usePathname();
const { setOpenMobile } = useSidebar();
const userRole = userData.role;
const menu = allMenuItems.filter((item) => {
if (!item.roles?.includes(userRole)) return false;
if (userRole === "employee" && item.permission) {
const employeeData = userData as EmployeeData;
return item.permission(employeeData.permissions);
}
return true;
});
return (
<Sidebar className="border-r-0 bg-white/55 backdrop-blur-xl supports-backdrop-filter:bg-white/45 shadow-[1px_0_0_0_oklch(0.85_0_0/30%)]">
<SidebarHeader className="text-sidebar-accent-foreground">
<Link href="/" className="flex justify-center items-center gap-2 px-2 pt-2">
<Image src={Logo} height={45} alt="Kumasy Logo" />
</Link>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupContent>
<SidebarMenu className="mt-10">
{menu.map((item) => (
<SidebarMenuItem key={item.href + item.label}>
<SidebarMenuButton
asChild
className={cn(
"h-10 hover:bg-linear-to-r/oklch border border-transparent hover:border-[#5D6B68]/10 from-sidebar-accent from-5% via-30% via-sidebar/50 to-sidebar/50",
pathname === item.href && "bg-linear-to-r/oklch border-[#5D6B68]/10 "
)}
isActive={pathname === item.href}
>
<Link
href={item.href}
className="flex items-center gap-3 w-full"
onClick={() => setOpenMobile(false)}
>
<item.icon className={cn(pathname === item.href && "text-blue")} />
<span
className={`${pathname === item.href && "text-blue font-semibold"} text-lg font-medium tracking-tight mt-1.5`}
>
{item.label}
</span>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
<DashboardFooter displayName={displayName} userData={userData} />
</SidebarFooter>
</Sidebar>
);
};
export default DashboardSidebar;