137 lines
4.1 KiB
Vue
137 lines
4.1 KiB
Vue
<script setup lang="ts">
|
|
import {
|
|
Sidebar,
|
|
SidebarContent,
|
|
SidebarFooter,
|
|
SidebarGroup,
|
|
SidebarGroupContent,
|
|
SidebarGroupLabel,
|
|
SidebarHeader,
|
|
SidebarMenu,
|
|
SidebarMenuButton,
|
|
SidebarMenuItem,
|
|
SidebarMenuSub,
|
|
SidebarMenuSubButton,
|
|
SidebarMenuSubItem,
|
|
SidebarRail,
|
|
} from '@/components/ui/sidebar'
|
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'
|
|
import { LayoutGrid, Boxes, Settings, Home, ChevronRight, Database, Layers } from 'lucide-vue-next'
|
|
|
|
const menuItems = [
|
|
{
|
|
title: 'Home',
|
|
url: '/',
|
|
icon: Home,
|
|
},
|
|
{
|
|
title: 'Setup',
|
|
icon: Settings,
|
|
items: [
|
|
{
|
|
title: 'Apps',
|
|
url: '/setup/apps',
|
|
icon: LayoutGrid,
|
|
},
|
|
{
|
|
title: 'Objects',
|
|
url: '/setup/objects',
|
|
icon: Boxes,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
title: 'Runtime',
|
|
icon: Database,
|
|
items: [
|
|
{
|
|
title: 'My Apps',
|
|
url: '/app',
|
|
icon: Layers,
|
|
},
|
|
],
|
|
},
|
|
]
|
|
</script>
|
|
|
|
<template>
|
|
<Sidebar collapsible="icon">
|
|
<SidebarHeader>
|
|
<SidebarMenu>
|
|
<SidebarMenuItem>
|
|
<SidebarMenuButton size="lg" as-child>
|
|
<NuxtLink to="/">
|
|
<div
|
|
class="flex aspect-square size-8 items-center justify-center rounded-lg bg-primary text-primary-foreground"
|
|
>
|
|
<LayoutGrid class="size-4" />
|
|
</div>
|
|
<div class="flex flex-col gap-0.5 leading-none">
|
|
<span class="font-semibold">Neo Platform</span>
|
|
<span class="text-xs">Multi-tenant CRM</span>
|
|
</div>
|
|
</NuxtLink>
|
|
</SidebarMenuButton>
|
|
</SidebarMenuItem>
|
|
</SidebarMenu>
|
|
</SidebarHeader>
|
|
<SidebarContent>
|
|
<SidebarGroup>
|
|
<SidebarGroupLabel>Application</SidebarGroupLabel>
|
|
<SidebarGroupContent>
|
|
<SidebarMenu>
|
|
<template v-for="item in menuItems" :key="item.title">
|
|
<!-- Simple menu item -->
|
|
<SidebarMenuItem v-if="!item.items">
|
|
<SidebarMenuButton as-child>
|
|
<NuxtLink :to="item.url">
|
|
<component :is="item.icon" />
|
|
<span>{{ item.title }}</span>
|
|
</NuxtLink>
|
|
</SidebarMenuButton>
|
|
</SidebarMenuItem>
|
|
|
|
<!-- Collapsible menu item with submenu -->
|
|
<Collapsible v-else as-child :default-open="false" class="group/collapsible">
|
|
<SidebarMenuItem>
|
|
<CollapsibleTrigger as-child>
|
|
<SidebarMenuButton tooltip="{item.title}">
|
|
<component :is="item.icon" />
|
|
<span>{{ item.title }}</span>
|
|
<ChevronRight
|
|
class="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90"
|
|
/>
|
|
</SidebarMenuButton>
|
|
</CollapsibleTrigger>
|
|
<CollapsibleContent>
|
|
<SidebarMenuSub>
|
|
<SidebarMenuSubItem v-for="subItem in item.items" :key="subItem.title">
|
|
<SidebarMenuSubButton as-child>
|
|
<NuxtLink :to="subItem.url">
|
|
<component :is="subItem.icon" />
|
|
<span>{{ subItem.title }}</span>
|
|
</NuxtLink>
|
|
</SidebarMenuSubButton>
|
|
</SidebarMenuSubItem>
|
|
</SidebarMenuSub>
|
|
</CollapsibleContent>
|
|
</SidebarMenuItem>
|
|
</Collapsible>
|
|
</template>
|
|
</SidebarMenu>
|
|
</SidebarGroupContent>
|
|
</SidebarGroup>
|
|
</SidebarContent>
|
|
<SidebarFooter>
|
|
<SidebarMenu>
|
|
<SidebarMenuItem>
|
|
<SidebarMenuButton>
|
|
<span class="text-sm text-muted-foreground">Logged in as user</span>
|
|
</SidebarMenuButton>
|
|
</SidebarMenuItem>
|
|
</SidebarMenu>
|
|
</SidebarFooter>
|
|
<SidebarRail />
|
|
</Sidebar>
|
|
</template>
|