Dede Fuji Abdul cce938fa8f update menu
2023-10-17 16:48:44 +07:00

256 lines
21 KiB
Vue

<script setup lang="ts">
import { computed, watch } from 'vue'
import { useRoute } from 'vue-router'
import { RouterLink } from 'vue-router'
import { ref } from 'vue'
import {
Dialog,
DialogPanel,
Disclosure,
DisclosureButton,
DisclosurePanel,
TransitionChild,
TransitionRoot,
} from '@headlessui/vue'
import { XMarkIcon } from '@heroicons/vue/24/outline'
import { useMenuStore } from '@/stores/menu'
import { IconApp } from '@/utils/icons'
import AsideMenuSingle from './AsideMenuSingle.vue'
import type { MenuItemModel } from '@/utils/interfaces'
const menu = useMenuStore()
const route = useRoute()
const navigation = ref<MenuItemModel[]>(menu.navigation)
const menuSelected = ref(route.fullPath)
watch(route, (to, _) => {
menuSelected.value = to.fullPath
closeSideBar()
})
const isMenu = (name: string) => {
return menuSelected.value === name
}
const closeSideBar = () => menu.toggleSidebar()
</script>
<template>
<TransitionRoot as="template" :show="menu.sidebarOpen">
<Dialog as="div" class="relative z-40 md:hidden" @close="closeSideBar">
<TransitionChild as="template" enter="transition-opacity ease-linear duration-300" enter-from="opacity-0"
enter-to="opacity-100" leave="transition-opacity ease-linear duration-300" leave-from="opacity-100"
leave-to="opacity-0">
<div class="fixed inset-0 bg-gray-600 bg-opacity-75" />
</TransitionChild>
<div class="fixed inset-0 z-40 flex">
<TransitionChild as="template" enter="transition ease-in-out duration-300 transform"
enter-from="-translate-x-full" enter-to="translate-x-0"
leave="transition ease-in-out duration-300 transform" leave-from="translate-x-0"
leave-to="-translate-x-full">
<DialogPanel class="relative flex flex-col flex-1 w-full max-w-xs pt-5 pb-4 bg-primary-50">
<TransitionChild as="template" enter="ease-in-out duration-300" enter-from="opacity-0"
enter-to="opacity-100" leave="ease-in-out duration-300" leave-from="opacity-100"
leave-to="opacity-0">
<div class="absolute top-0 right-0 pt-2 -mr-12">
<button type="button"
class="flex items-center justify-center w-10 h-10 ml-1 rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
@click="closeSideBar">
<span class="sr-only">Close sidebar</span>
<XMarkIcon class="w-6 h-6 text-white" aria-hidden="true" />
</button>
</div>
</TransitionChild>
<div class="flex items-center flex-shrink-0 px-4">
<RouterLink to="/">
<img class="w-auto h-16" :src="IconApp" alt="PLN" />
</RouterLink>
</div>
<div class="flex-1 h-0 mt-5 overflow-y-auto">
<nav class="px-2 space-y-1">
<template v-for="item in navigation" :key="item.name">
<div v-if="!item.children || item.children.length === 0">
<AsideMenuSingle :item="item" :is-menu-selected="isMenu(item.href)" />
<!-- Single-level item -->
<!-- <RouterLink :to="item.href"
:class="[isMenu(item.href) ? 'bg-primary-500 text-white font-bold' : 'font-semibold text-aside hover:bg-primary-100 hover:text-gray-900', 'group w-full flex items-center pl-2 py-2 text-xs rounded-lg']">
<component :is="item.icon"
:class="[isMenu(item.href) ? 'text-white' : 'text-aside group-hover:text-gray-900', 'mr-3 flex-shrink-0 h-6 w-6']"
aria-hidden="true" />
{{ item.name }}
</RouterLink> -->
</div>
<Disclosure v-else
v-bind:default-open="item.children.find((d) => d.href === menuSelected) || item.children.find((d) => d.children.find((e) => e.href === menuSelected)) ? true : false">
<!-- Nested item with children -->
<template v-slot="{ open }">
<DisclosureButton
:class="[item.children.find((d) => d.href === menuSelected) || item.children.find((d) => d.children.find((e) => e.href === menuSelected)) ? 'text-primary-500 font-bold' : 'font-semibold text-aside hover:bg-primary-100 hover:text-gray-900', 'group w-full flex items-center pl-2 pr-1 py-2 text-left text-xs rounded-lg focus:outline-none focus:ring-0 focus:ring-indigo-500']">
<embed :data="item.icon"
:class="[item.children.find((d: any) => d.href === menuSelected) || item.children.find((d) => d.children.find((e) => e.href === menuSelected)) ? 'text-primary-500' : 'text-gray-400 group-hover:text-gray-500', 'flex-shrink-0 w-6 h-6 mr-3']"
type="image/svg+xml" />
<span class="flex-1">{{ item.name }}</span>
<svg :class="[item.children.find((d: any) => d.href === menuSelected) || item.children.find((d) => d.children.find((e) => e.href === menuSelected)) ? 'text-primary-500' : 'text-gray-300 group-hover:text-gray-500', open ? 'rotate-180' : '', 'ml-3 flex-shrink-0 transform transition-colors duration-150 ease-in-out ']"
width="16" height="16" viewBox="0 0 24 24" fill="none"
aria-hidden="true">
<path
d="M4.44002 8.9399C4.72127 8.659 5.10252 8.50122 5.50002 8.50122C5.89752 8.50122 6.27877 8.659 6.56002 8.9399L12 14.3799L17.44 8.9399C17.7244 8.67494 18.1005 8.53069 18.4891 8.53755C18.8777 8.54441 19.2484 8.70183 19.5233 8.97666C19.7981 9.25148 19.9555 9.62225 19.9624 10.0109C19.9692 10.3995 19.825 10.7756 19.56 11.0599L13.06 17.5599C12.7788 17.8408 12.3975 17.9986 12 17.9986C11.6025 17.9986 11.2213 17.8408 10.94 17.5599L4.44002 11.0599C4.15912 10.7787 4.00134 10.3974 4.00134 9.9999C4.00134 9.6024 4.15912 9.22115 4.44002 8.9399Z"
:fill="item.children.find((d: any) => d.href === menuSelected) || item.children.find((d) => d.children.find((e) => e.href === menuSelected)) ? '#14A2BA' : '#647375'" />
</svg>
</DisclosureButton>
<DisclosurePanel class="space-y-1">
<!-- Nested children -->
<template v-for="subItem in item.children" :key="subItem.name">
<div v-if="subItem.children.length === 0">
<!-- Single-level child -->
<!-- <RouterLink :to="subItem.href"
:class="[isMenu(subItem.href) ? 'text-white font-bold bg-primary-500' : 'font-semibold text-aside hover:bg-primary-100 hover:text-gray-900', 'flex items-center w-11/12 py-2 px-2 text-xs rounded-lg group ml-auto']">
{{ subItem.name }}
</RouterLink> -->
<AsideMenuSingle :item="subItem"
:is-menu-selected="isMenu(subItem.href)" :is-children="true" />
</div>
<Disclosure v-else
:default-open="subItem.children.find((d: any) => d.href === menuSelected) ? true : false">
<!-- Nested child with children -->
<template v-slot="{ open }">
<DisclosureButton
:class="[subItem.children.find((d: any) => d.href === menuSelected) ? 'text-primary-500 font-bold' : 'font-semibold text-aside hover:bg-primary-100 hover:text-gray-900', 'group w-11/12 flex items-center px-2 py-2 text-left text-xs rounded-lg focus:outline-none focus:ring-0 focus:ring-indigo-500 ml-auto']">
<span class="flex-1">{{ subItem.name }}</span>
<svg :class="[subItem.children.find((d: any) => d.href === menuSelected) ? 'text-primary-500' : 'text-gray-300 group-hover:text-gray-500', open ? 'rotate-180' : '', 'ml-3 flex-shrink-0 transform transition-colors duration-150 ease-in-out ']"
width="16" height="16" viewBox="0 0 24 24" fill="none"
aria-hidden="true">
<path
d="M4.44002 8.9399C4.72127 8.659 5.10252 8.50122 5.50002 8.50122C5.89752 8.50122 6.27877 8.659 6.56002 8.9399L12 14.3799L17.44 8.9399C17.7244 8.67494 18.1005 8.53069 18.4891 8.53755C18.8777 8.54441 19.2484 8.70183 19.5233 8.97666C19.7981 9.25148 19.9555 9.62225 19.9624 10.0109C19.9692 10.3995 19.825 10.7756 19.56 11.0599L13.06 17.5599C12.7788 17.8408 12.3975 17.9986 12 17.9986C11.6025 17.9986 11.2213 17.8408 10.94 17.5599L4.44002 11.0599C4.15912 10.7787 4.00134 10.3974 4.00134 9.9999C4.00134 9.6024 4.15912 9.22115 4.44002 8.9399Z"
:fill="subItem.children.find((d: any) => d.href === menuSelected) ? '#14A2BA' : '#647375'" />
</svg>
</DisclosureButton>
<DisclosurePanel class="space-y-1 pl-11">
<!-- Nested children of nested child -->
<!-- <RouterLink v-for="nestedSubItem in subItem.children"
:key="nestedSubItem.name" :to="nestedSubItem.href"
:class="[isMenu(nestedSubItem.href) ? 'text-white font-bold bg-primary-500' : 'font-semibold text-aside hover:bg-primary-100 hover:text-gray-900', 'flex items-center w-12/12 py-2 px-2 text-xs rounded-lg group ml-auto']">
{{ nestedSubItem.name }}
</RouterLink> -->
<AsideMenuSingle v-for="nestedSubItem in subItem.children"
:key="nestedSubItem.name" :item="nestedSubItem"
:is-menu-selected="isMenu(nestedSubItem.href)"
:is-children="true" />
</DisclosurePanel>
</template>
</Disclosure>
</template>
</DisclosurePanel>
</template>
</Disclosure>
</template>
</nav>
</div>
</DialogPanel>
</TransitionChild>
<div class="flex-shrink-0 w-14" aria-hidden="true">
<!-- Dummy element to force sidebar to shrink to fit close icon -->
</div>
</div>
</Dialog>
</TransitionRoot>
<!-- Static sidebar for desktop -->
<div class="z-10 hidden bg-primary-50 md:fixed md:inset-y-0 md:flex md:w-80 md:flex-col">
<!-- Sidebar component, swap this element with another sidebar if you like -->
<div class="flex items-center flex-shrink-0 h-16 px-5">
<RouterLink to="/">
<img class="w-auto h-11" :src="IconApp" alt="PLN" />
</RouterLink>
</div>
<div class="flex flex-col flex-grow hover:overflow-y-auto">
<div class="flex flex-col flex-grow mt-5">
<nav class="flex-1 px-2 pb-4 space-y-1">
<template v-for="item in navigation" :key="item.name">
<div v-if="item.children.length === 0">
<!-- Single-level item -->
<AsideMenuSingle :item="item" :is-menu-selected="isMenu(item.href)" />
</div>
<Disclosure v-slot="{ open }" v-else
v-bind:default-open="item.children.find((d) => d.href === menuSelected) || item.children.find((d) => d.children.find((e) => e.href === menuSelected)) ? true : false">
<!-- Nested item with children -->
<DisclosureButton
:class="[item.children.find((d) => d.href === menuSelected) || item.children.find((d) => d.children.find((e) => e.href === menuSelected)) ? 'text-primary-500 font-bold' : 'font-semibold text-aside hover:bg-primary-100 hover:text-gray-900', 'group w-full flex items-center pl-2 pr-1 py-2 text-left text-xs rounded-lg focus:outline-none focus:ring-0 focus:ring-indigo-500']">
<embed :src="item.icon"
:class="[item.children.find((d: any) => d.href === menuSelected) || item.children.find((d) => d.children.find((e) => e.href === menuSelected)) ? 'fill-primary-500' : 'fill-gray-400 group-hover:fill-gray-500', 'flex-shrink-0 w-6 h-6 mr-3']"
type="image/svg+xml" />
<span class="flex-1">{{ item.name }}</span>
<svg :class="[item.children.find((d: any) => d.href === menuSelected) || item.children.find((d) => d.children.find((e) => e.href === menuSelected)) ? 'text-primary-500' : 'text-gray-300 group-hover:text-gray-500', open ? 'rotate-180' : '', 'ml-3 flex-shrink-0 transform transition-colors duration-150 ease-in-out ']"
width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path
d="M4.44002 8.9399C4.72127 8.659 5.10252 8.50122 5.50002 8.50122C5.89752 8.50122 6.27877 8.659 6.56002 8.9399L12 14.3799L17.44 8.9399C17.7244 8.67494 18.1005 8.53069 18.4891 8.53755C18.8777 8.54441 19.2484 8.70183 19.5233 8.97666C19.7981 9.25148 19.9555 9.62225 19.9624 10.0109C19.9692 10.3995 19.825 10.7756 19.56 11.0599L13.06 17.5599C12.7788 17.8408 12.3975 17.9986 12 17.9986C11.6025 17.9986 11.2213 17.8408 10.94 17.5599L4.44002 11.0599C4.15912 10.7787 4.00134 10.3974 4.00134 9.9999C4.00134 9.6024 4.15912 9.22115 4.44002 8.9399Z"
:fill="item.children.find((d: any) => d.href === menuSelected) || item.children.find((d) => d.children.find((e) => e.href === menuSelected)) ? '#14A2BA' : '#647375'" />
</svg>
</DisclosureButton>
<transition enter-active-class="overflow-hidden transition-all duration-300"
enter-from-class="transform scale-95 opacity-0 max-h-0"
enter-to-class="transform scale-300 opacity-300 max-h-[1000px]"
leave-active-class="overflow-hidden transition-all duration-300"
leave-from-class="transform scale-300 opacity-300 max-h-[1000px]"
leave-to-class="transform scale-95 opacity-0 max-h-0">
<DisclosurePanel class="space-y-1">
<!-- Nested children -->
<template v-for="(subItem, index) in item.children" :key="subItem.href">
<div v-if="!subItem.children || subItem.children.length === 0">
<!-- Single-level child -->
<AsideMenuSingle :item="subItem" :is-children="true"
:is-menu-selected="isMenu(subItem.href)" />
</div>
<Disclosure :key="subItem.href + index" v-slot="{ open }" v-else
:default-open="subItem.children.find((d: any) => d.href === menuSelected) ? true : false">
<!-- Nested child with children -->
<DisclosureButton
:class="[subItem.children.find((d: any) => d.href === menuSelected) ? 'text-primary-500 font-bold' : 'font-semibold text-aside hover:bg-primary-100 hover:text-gray-900', 'group w-11/12 flex items-center px-2 py-2 text-left text-xs rounded-lg focus:outline-none focus:ring-0 focus:ring-indigo-500 ml-auto']">
<span class="flex-1">{{ subItem.name }}</span>
<svg :class="[subItem.children.find((d: any) => d.href === menuSelected) ? 'text-primary-500' : 'text-gray-300 group-hover:text-gray-500', open ? 'rotate-180' : '', 'ml-3 flex-shrink-0 transform transition-colors duration-150 ease-in-out ']"
width="16" height="16" viewBox="0 0 24 24" fill="none"
aria-hidden="true">
<path
d="M4.44002 8.9399C4.72127 8.659 5.10252 8.50122 5.50002 8.50122C5.89752 8.50122 6.27877 8.659 6.56002 8.9399L12 14.3799L17.44 8.9399C17.7244 8.67494 18.1005 8.53069 18.4891 8.53755C18.8777 8.54441 19.2484 8.70183 19.5233 8.97666C19.7981 9.25148 19.9555 9.62225 19.9624 10.0109C19.9692 10.3995 19.825 10.7756 19.56 11.0599L13.06 17.5599C12.7788 17.8408 12.3975 17.9986 12 17.9986C11.6025 17.9986 11.2213 17.8408 10.94 17.5599L4.44002 11.0599C4.15912 10.7787 4.00134 10.3974 4.00134 9.9999C4.00134 9.6024 4.15912 9.22115 4.44002 8.9399Z"
:fill="subItem.children.find((d: any) => d.href === menuSelected) ? '#14A2BA' : '#647375'" />
</svg>
</DisclosureButton>
<transition enter-active-class="overflow-hidden transition-all duration-300"
enter-from-class="transform scale-95 opacity-0 max-h-0"
enter-to-class="transform scale-300 opacity-300 max-h-[1000px]"
leave-active-class="overflow-hidden transition-all duration-300"
leave-from-class="transform scale-300 opacity-300 max-h-[1000px]"
leave-to-class="transform scale-95 opacity-0 max-h-0">
<DisclosurePanel class="space-y-1 pl-11">
<!-- Nested children of nested child -->
<AsideMenuSingle v-for="nestedSubItem in subItem.children"
:item="nestedSubItem" :is-children="true"
:is-menu-selected="isMenu(subItem.href)" />
</DisclosurePanel>
</transition>
</Disclosure>
</template>
</DisclosurePanel>
</transition>
</Disclosure>
</template>
</nav>
</div>
</div>
</div>
</template>