119 lines
3.0 KiB
Vue
119 lines
3.0 KiB
Vue
<script setup lang="ts">
|
|
type NavGroup = {
|
|
heading?: string
|
|
items: any[]
|
|
}
|
|
|
|
const { getActiveRole } = useUserStore()
|
|
|
|
const navMenu = ref<NavGroup[]>([])
|
|
|
|
const teams: {
|
|
name: string
|
|
logo: string
|
|
plan: string
|
|
}[] = [
|
|
{
|
|
name: 'SIMRS - RSSA',
|
|
logo: '/rssa-logo.png',
|
|
plan: 'Saiful Anwar Hospital',
|
|
},
|
|
]
|
|
|
|
type Sidebar = {
|
|
collapsible: 'offcanvas' | 'icon' | 'none'
|
|
side: 'left' | 'right'
|
|
variant: 'sidebar' | 'floating' | 'inset'
|
|
}
|
|
|
|
const sidebar: Sidebar = {
|
|
collapsible: 'offcanvas', // 'offcanvas' | 'icon' | 'none'
|
|
side: 'left', // 'left' | 'right'
|
|
variant: 'sidebar', // 'sidebar' | 'floating' | 'inset'
|
|
}
|
|
const navMenuBottom: any[] = [
|
|
{
|
|
title: 'Help & Support',
|
|
icon: 'i-lucide-circle-help',
|
|
link: 'https://github.com/simrs/simrs-fe',
|
|
},
|
|
]
|
|
|
|
onMounted(async () => {
|
|
await setMenu()
|
|
})
|
|
|
|
async function setMenu() {
|
|
const activeRole = getActiveRole()
|
|
const activeRoleParts = activeRole ? activeRole.split('|') : []
|
|
const role = activeRoleParts[0]+(activeRoleParts.length > 1 ? `-${activeRoleParts[1]}` : '')
|
|
try {
|
|
const res = await fetch(`/side-menu-items/${role.toLowerCase()}.json`)
|
|
const rawMenu = await res.text()
|
|
navMenu.value = JSON.parse(rawMenu)
|
|
} catch (e) {
|
|
const res = await fetch(`/side-menu-items/blank.json`)
|
|
const rawMenu = await res.text()
|
|
navMenu.value = JSON.parse(rawMenu)
|
|
}
|
|
}
|
|
|
|
function resolveNavItemComponent(item: any): any {
|
|
if ('children' in item) return resolveComponent('LayoutSidebarNavGroup')
|
|
|
|
return resolveComponent('LayoutSidebarNavLink')
|
|
}
|
|
|
|
watch(getActiveRole, async () => {
|
|
await setMenu()
|
|
// const activeRole = getActiveRole()
|
|
// const res = await fetch(`/side-menu-items/${activeRole}.json`)
|
|
// const rawMenu = await res.text()
|
|
// navMenu.value = JSON.parse(rawMenu)
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<Sidebar :collapsible="sidebar.collapsible" :side="sidebar.side" :variant="sidebar.variant">
|
|
<SidebarHeader>
|
|
<LayoutSidebarNavHeader :teams="teams" />
|
|
</SidebarHeader>
|
|
<SidebarContent>
|
|
<template v-if="navMenu.length > 0">
|
|
<SidebarGroup v-for="(nav, indexGroup) in navMenu" :key="indexGroup">
|
|
<SidebarGroupLabel v-if="nav.heading">
|
|
{{ nav.heading }}
|
|
</SidebarGroupLabel>
|
|
<component
|
|
:is="resolveNavItemComponent(item)"
|
|
v-for="(item, index) in nav.items"
|
|
:key="index"
|
|
:item="item"
|
|
class="my-1 mb-1"
|
|
/>
|
|
</SidebarGroup>
|
|
</template>
|
|
<template v-else>
|
|
<div class="p-5">
|
|
<div v-for="n in 10" :key="n" class="my-4 h-8 animate-pulse rounded bg-gray-200 py-2"></div>
|
|
</div>
|
|
</template>
|
|
<SidebarGroup class="mt-auto">
|
|
<component
|
|
:is="resolveNavItemComponent(item)"
|
|
v-for="(item, index) in navMenuBottom"
|
|
:key="index"
|
|
:item="item"
|
|
size="sm"
|
|
/>
|
|
</SidebarGroup>
|
|
</SidebarContent>
|
|
<SidebarFooter>
|
|
<LayoutSidebarNavFooter />
|
|
</SidebarFooter>
|
|
<SidebarRail />
|
|
</Sidebar>
|
|
</template>
|
|
|
|
<style scoped></style>
|