store/resources/js/components/AppSidebar.vue

145 lines
6.7 KiB
Vue

<script setup lang="ts">
import { Link, usePage } from '@inertiajs/vue3';
import { Banknote, CalendarDays, Clock, ClipboardList, FolderTree, History, Layers, LayoutDashboard, Package, Receipt, Scissors, Settings2, Shield, ShoppingBag, ShoppingCart, TrendingUp, User, UserCheck, Users, Wallet, WalletCards, Warehouse } from '@lucide/vue';
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarMenu,
SidebarMenuBadge,
SidebarMenuButton,
SidebarMenuItem,
SidebarRail,
} from '@/components/ui/sidebar';
import { useCan } from '@/composables/useCan';
import admin from '@/routes/admin';
const page = usePage();
const { can } = useCan();
interface MenuItem {
title: string;
href: string;
icon: any;
permission?: string;
badgeKey?: 'pendingLeaveRequests' | 'pendingEmployeeAdvances' | 'pendingCuttings';
}
interface MenuGroup {
label: string;
items: MenuItem[];
}
const menuGroups: MenuGroup[] = [
{
label: 'Menu',
items: [
{ title: 'Dasbor', href: admin.dashboard.url(), icon: LayoutDashboard },
{ title: 'Analisa', href: admin.analysis.url(), icon: TrendingUp, permission: 'analysis.view' },
],
},
{
label: 'Master',
items: [
{ title: 'Kategori', href: admin.master.categories.index.url(), icon: FolderTree, permission: 'categories.view' },
{ title: 'Produk', href: admin.master.products.index.url(), icon: Package, permission: 'products.view' },
{ title: 'Bahan Baku', href: admin.master.raw_materials.index.url(), icon: Layers, permission: 'raw_materials.view' },
{ title: 'Supplier', href: admin.master.suppliers.index.url(), icon: User, permission: 'suppliers.view' },
{ title: 'Customer', href: admin.master.customers.index.url(), icon: UserCheck, permission: 'customers.view' },
],
},
{
label: 'Kelola',
items: [
{ title: 'Belanja', href: admin.manage.purchases.index.url(), icon: ShoppingBag, permission: 'purchases.view' },
{ title: 'Cutting', href: admin.manage.cuttings.index.url(), icon: Scissors, permission: 'cuttings.view' },
{ title: 'Stok Gudang', href: admin.manage.stocks.index.url(), icon: Warehouse, permission: 'stocks.view', badgeKey: 'pendingCuttings' },
{ title: 'Stok Opname', href: admin.manage.stokOpnames.index.url(), icon: ClipboardList, permission: 'stok_opnames.view' },
{ title: 'Pesanan', href: admin.manage.orders.index.url(), icon: ShoppingCart, permission: 'orders.view' },
],
},
{
label: 'Keuangan',
items: [
{ title: 'Kas Toko', href: admin.finance.cash.index.url(), icon: Wallet, permission: 'cash.view' },
{ title: 'Pengeluaran', href: admin.finance.expenses.index.url(), icon: Receipt, permission: 'expenses.view' },
{ title: 'Kasbon', href: admin.finance.employee_advances.index.url(), icon: Banknote, permission: 'employee_advances.view', badgeKey: 'pendingEmployeeAdvances' },
{ title: 'Gaji', href: admin.finance.payroll.index.url(), icon: WalletCards, permission: 'payroll.view' },
],
},
{
label: 'HR',
items: [
{ title: 'Pegawai', href: admin.hr.employees.index.url(), icon: Users, permission: 'employees.view' },
{ title: 'Presensi', href: admin.hr.attendances.index.url(), icon: Clock, permission: 'attendances.view' },
{ title: 'Cuti', href: admin.hr.leave_requests.index.url(), icon: CalendarDays, permission: 'leave_requests.view', badgeKey: 'pendingLeaveRequests' },
],
},
{
label: 'Sistem',
items: [
{ title: 'Role & Permission', href: admin.system.roles.index.url(), icon: Shield, permission: 'roles.view' },
{ title: 'Pengaturan', href: admin.system.settings.index.url(), icon: Settings2, permission: 'settings.view' },
{ title: 'Log Aktivitas', href: admin.system.activity_logs.index.url(), icon: History, permission: 'activity_logs.view' },
],
},
];
</script>
<template>
<Sidebar collapsible="icon">
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size="lg" as-child>
<Link :href="admin.dashboard.url()">
<img
v-if="page.props.logo_url"
:src="page.props.logo_url"
:alt="page.props.name"
class="h-8 w-auto object-contain"
/>
<div v-else class="grid flex-1 text-left text-sm leading-tight">
<span class="truncate font-semibold">{{ page.props.name }}</span>
</div>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<template v-for="group in menuGroups" :key="group.label">
<SidebarGroup v-if="group.items.some(item => !item.permission || can(item.permission))">
<SidebarGroupLabel>{{ group.label }}</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<template v-for="item in group.items" :key="item.href">
<SidebarMenuItem v-if="!item.permission || can(item.permission)">
<SidebarMenuButton
as-child
:tooltip="item.title"
:is-active="page.url.startsWith(item.href)"
>
<Link :href="item.href">
<component :is="item.icon" />
<span>{{ item.title }}</span>
</Link>
</SidebarMenuButton>
<SidebarMenuBadge v-if="item.badgeKey && (page.props as any)[item.badgeKey] > 0">
{{ (page.props as any)[item.badgeKey] }}
</SidebarMenuBadge>
</SidebarMenuItem>
</template>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</template>
</SidebarContent>
<SidebarRail />
</Sidebar>
</template>