import { type ReactNode } from "react";
export interface MenuItem {
path: string;
label: string;
end?: boolean;
permission?: string | string[];
matchPrefix?: string;
matchAlso?: string[];
matchExclude?: string[];
icon: ReactNode;
}
export interface MenuSection {
label: string;
items: MenuItem[];
}
export const menuSections: MenuSection[] = [
{
label: "Přehled",
items: [
{
path: "/",
label: "Přehled",
end: true,
icon: (
),
},
],
},
{
label: "Docházka",
items: [
{
path: "/attendance",
label: "Záznam",
permission: "attendance.record",
end: true,
icon: (
),
},
{
path: "/attendance/history",
label: "Moje historie",
permission: "attendance.history",
icon: (
),
},
{
path: "/attendance/requests",
label: "Žádosti",
permission: "attendance.record",
icon: (
),
},
{
path: "/attendance/approval",
label: "Schvalování",
permission: "attendance.approve",
icon: (
),
},
{
path: "/attendance/admin",
label: "Správa",
permission: "attendance.manage",
matchPrefix: "/attendance/admin",
matchAlso: ["/attendance/create", "/attendance/location"],
icon: (
),
},
{
path: "/attendance/balances",
label: "Správa bilancí",
permission: "attendance.balances",
icon: (
),
},
{
path: "/plan-work",
label: "Plán prací",
permission: ["attendance.manage", "attendance.record"],
icon: (
),
},
],
},
{
label: "Kniha jízd",
items: [
{
path: "/trips",
label: "Záznam",
permission: "trips.record",
end: true,
icon: (
),
},
{
path: "/trips/history",
label: "Moje historie",
permission: "trips.history",
icon: (
),
},
{
path: "/trips/admin",
label: "Správa",
permission: "trips.manage",
icon: (
),
},
{
path: "/vehicles",
label: "Vozidla",
permission: "vehicles.manage",
icon: (
),
},
],
},
{
label: "Administrativa",
items: [
{
path: "/offers",
label: "Nabídky",
permission: "offers.view",
matchPrefix: "/offers",
matchExclude: ["/offers/customers", "/offers/templates"],
icon: (
),
},
{
path: "/orders",
label: "Objednávky",
permission: "orders.view",
matchPrefix: "/orders",
icon: (
),
},
{
path: "/invoices",
label: "Faktury",
permission: "invoices.view",
matchPrefix: "/invoices",
icon: (
),
},
{
path: "/projects",
label: "Projekty",
permission: "projects.view",
matchPrefix: "/projects",
icon: (
),
},
{
path: "/offers/customers",
label: "Zákazníci",
permission: "customers.view",
icon: (
),
},
],
},
{
label: "Sklad",
items: [
{
path: "/warehouse",
label: "Přehled",
permission: "warehouse.view",
end: true,
icon: (
),
},
{
path: "/warehouse/items",
label: "Položky",
permission: "warehouse.view",
matchPrefix: "/warehouse/items",
icon: (
),
},
{
path: "/warehouse/receipts",
label: "Příjmy",
permission: "warehouse.operate",
matchPrefix: "/warehouse/receipts",
icon: (
),
},
{
path: "/warehouse/issues",
label: "Výdeje",
permission: "warehouse.operate",
matchPrefix: "/warehouse/issues",
icon: (
),
},
{
path: "/warehouse/reservations",
label: "Rezervace",
permission: "warehouse.operate",
matchPrefix: "/warehouse/reservations",
icon: (
),
},
{
path: "/warehouse/inventory",
label: "Inventura",
permission: "warehouse.inventory",
matchPrefix: "/warehouse/inventory",
icon: (
),
},
{
path: "/warehouse/reports",
label: "Reporty",
permission: "warehouse.view",
end: true,
icon: (
),
},
{
path: "/warehouse/categories",
label: "Kategorie",
permission: "warehouse.manage",
matchPrefix: "/warehouse/categories",
icon: (
),
},
{
path: "/warehouse/locations",
label: "Lokace",
permission: "warehouse.manage",
matchPrefix: "/warehouse/locations",
icon: (
),
},
{
path: "/warehouse/suppliers",
label: "Dodavatelé",
permission: "warehouse.manage",
matchPrefix: "/warehouse/suppliers",
icon: (
),
},
],
},
{
label: "Systém",
items: [
{
path: "/users",
label: "Uživatelé",
permission: "users.view",
icon: (
),
},
{
path: "/settings",
label: "Nastavení",
permission: [
"settings.company",
"settings.banking",
"settings.roles",
"settings.system",
"settings.templates",
],
icon: (
),
},
{
path: "/audit-log",
label: "Audit log",
permission: "settings.audit",
icon: (
),
},
],
},
];
/** Active-state matching (mirrors the original Sidebar logic, incl. matchAlso). */
export function isItemActive(item: MenuItem, pathname: string): boolean {
if (item.matchPrefix) {
let active = pathname.startsWith(item.matchPrefix);
if (active && item.matchExclude) {
active = !item.matchExclude.some((ex) => pathname.startsWith(ex));
}
if (!active && item.matchAlso) {
active = item.matchAlso.some((p) => pathname.startsWith(p));
}
return active;
}
if (item.matchAlso && item.matchAlso.some((p) => pathname.startsWith(p))) {
return true;
}
if (item.end) return pathname === item.path;
return pathname.startsWith(item.path);
}
/** Permission check: true if no permission, or any listed permission is held. */
export function hasItemPermission(
item: MenuItem,
hasPermission: (p: string) => boolean,
): boolean {
if (!item.permission) return true;
if (Array.isArray(item.permission)) {
return item.permission.some((p) => hasPermission(p));
}
return hasPermission(item.permission);
}