core/app/components/AppSidebar.vue

105 lines
3.0 KiB
Vue

<script setup lang="ts">
import {
BriefcaseBusiness,
CreditCard,
Database,
FolderKanban,
LayoutDashboard
} from "@lucide/vue"
import { computed, ref, watch } from 'vue'
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/components/ui/tooltip'
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from '@/components/ui/sidebar'
const route = useRoute()
const groups = [
{
title: 'Master',
icon: FolderKanban,
items: [
{ title: 'Dashboard', url: '/admin/dashboard', icon: LayoutDashboard },
{ title: 'Jenis Bisnis', url: '/admin/business-types', icon: BriefcaseBusiness },
{ title: 'Plans', url: '/admin/plans', icon: CreditCard },
],
},
]
const activeGroup = ref(
groups.find(g => g.items.some(it => route.path === it.url))?.title ?? groups[0].title
)
watch(() => route.path, (path) => {
const found = groups.find(g => g.items.some(it => it.url === path))
if (found) activeGroup.value = found.title
})
const currentGroup = computed(() => groups.find(g => g.title === activeGroup.value))
</script>
<template>
<Sidebar collapsible="icon">
<div class="flex flex-row h-full w-full">
<!-- Left: Icon Rail -->
<div class="flex w-(--sidebar-width-icon) shrink-0 flex-col items-center border-r py-2 gap-1">
<SidebarMenuButton as-child class="p-1.5! mb-2">
<a href="#">
<img src="/assets/icon.png" class="size-6!" />
</a>
</SidebarMenuButton>
<Tooltip v-for="g in groups" :key="g.title">
<TooltipTrigger as-child>
<SidebarMenuButton as-child size="lg" :data-active="activeGroup === g.title || undefined"
@click="activeGroup = g.title">
<button>
<component :is="g.icon" />
</button>
</SidebarMenuButton>
</TooltipTrigger>
<TooltipContent side="right">
{{ g.title }}
</TooltipContent>
</Tooltip>
</div>
<!-- Right: Content Panel -->
<div class="flex flex-1 flex-col min-w-0">
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel class="text-lg font-bold mb-5">
{{ currentGroup?.title }}
</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem v-for="item in currentGroup?.items" :key="item.title">
<SidebarMenuButton as-child :is-active="route.path === item.url">
<NuxtLink :to="item.url">
<component :is="item.icon" v-if="item.icon" />
<span>{{ item.title }}</span>
</NuxtLink>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</div>
</div>
</Sidebar>
</template>