Add detectOS function to helper.ts and update style.css with new utility classes

This commit is contained in:
Dede Fuji Abdul
2024-04-06 22:17:19 +07:00
parent b27972b0b5
commit dd6da0f25a
6 changed files with 506 additions and 311 deletions

View File

@ -2206,6 +2206,12 @@ body {
margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
}
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(1rem * var(--tw-space-x-reverse));
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
}
.space-y-1 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0;
margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
@ -2224,12 +2230,6 @@ body {
margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));
}
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(1rem * var(--tw-space-x-reverse));
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
}
.divide-y > :not([hidden]) ~ :not([hidden]) {
--tw-divide-y-reverse: 0;
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
@ -2475,6 +2475,10 @@ body {
border-bottom-width: 0px;
}
.border-b-2 {
border-bottom-width: 2px;
}
.border-l-4 {
border-left-width: 4px;
}
@ -2491,10 +2495,6 @@ body {
border-top-width: 0px;
}
.border-b-2 {
border-bottom-width: 2px;
}
.border-solid {
border-style: solid;
}
@ -2582,6 +2582,11 @@ body {
border-color: rgb(255 51 51 / var(--tw-border-opacity));
}
.border-secondary-500 {
--tw-border-opacity: 1;
border-color: rgb(0 162 185 / var(--tw-border-opacity));
}
.border-transparent {
border-color: transparent;
}
@ -2596,11 +2601,6 @@ body {
border-color: rgb(255 255 51 / var(--tw-border-opacity));
}
.border-secondary-500 {
--tw-border-opacity: 1;
border-color: rgb(0 162 185 / var(--tw-border-opacity));
}
.bg-black {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
@ -3715,6 +3715,16 @@ body {
color: rgb(102 102 0 / var(--tw-text-opacity));
}
.text-slate-300 {
--tw-text-opacity: 1;
color: rgb(203 213 225 / var(--tw-text-opacity));
}
.text-slate-500 {
--tw-text-opacity: 1;
color: rgb(100 116 139 / var(--tw-text-opacity));
}
.text-opacity-40 {
--tw-text-opacity: 0.4;
}
@ -3723,6 +3733,10 @@ body {
text-decoration-line: underline;
}
.no-underline {
text-decoration-line: none;
}
.placeholder-gray-500::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(107 114 128 / var(--tw-placeholder-opacity));
@ -5252,6 +5266,11 @@ body {
color: rgb(51 51 0 / 0.9);
}
:is(.dark .dark\:text-slate-500) {
--tw-text-opacity: 1;
color: rgb(100 116 139 / var(--tw-text-opacity));
}
:is(.dark .dark\:text-opacity-70) {
--tw-text-opacity: 0.7;
}

View File

@ -1,33 +1,54 @@
<template>
<TransitionRoot :show="command.open" @after-leave="onQueryChange('')" appear>
<Dialog as="div" class="relative z-10" @close="command.closeCommand">
<TransitionChild enter="ease-out duration-300" enter-from="opacity-0" enter-to="opacity-100"
leave="ease-in duration-200" leave-from="opacity-100" leave-to="opacity-0">
<TransitionChild
enter="ease-out duration-300"
enter-from="opacity-0"
enter-to="opacity-100"
leave="ease-in duration-200"
leave-from="opacity-100"
leave-to="opacity-0"
>
<div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-25 backdrop-blur" />
</TransitionChild>
<div class="fixed inset-0 z-10 p-4 overflow-y-auto sm:p-6 md:p-20">
<TransitionChild enter="ease-out duration-300" enter-from="opacity-0 scale-95"
enter-to="opacity-100 scale-100" leave="ease-in duration-200" leave-from="opacity-100 scale-100"
leave-to="opacity-0 scale-95">
<TransitionChild
enter="ease-out duration-300"
enter-from="opacity-0 scale-95"
enter-to="opacity-100 scale-100"
leave="ease-in duration-200"
leave-from="opacity-100 scale-100"
leave-to="opacity-0 scale-95"
>
<!-- max-w-2xl mx-auto overflow-hidden transition-all transform bg-white bg-opacity-80 divide-y divide-gray-500 shadow-2xl divide-opacity-10 rounded-xl ring-0 ring-black ring-opacity-5 -->
<DialogPanel
class="max-w-2xl mx-auto overflow-hidden transition-all transform bg-white bg-opacity-100 divide-y divide-gray-500 shadow-2xl divide-opacity-10 rounded-xl ring-0 ring-black ring-opacity-5">
class="max-w-2xl mx-auto overflow-hidden transition-all transform bg-white bg-opacity-100 divide-y divide-gray-500 shadow-2xl divide-opacity-10 rounded-xl ring-0 ring-black ring-opacity-5"
>
<Combobox>
<div class="relative">
<MagnifyingGlassIcon
class="pointer-events-none absolute top-3.5 left-4 h-5 w-5 text-gray-900 text-opacity-40"
aria-hidden="true" />
<ComboboxInput :autofocus="false"
aria-hidden="true"
/>
<ComboboxInput
:autofocus="false"
class="w-full h-12 pr-4 text-gray-900 placeholder-gray-500 bg-white border-0 pl-11 focus:ring-0 sm:text-sm"
placeholder="Cari menu..." @change="onQueryChange($event.target.value)" />
placeholder="Cari menu..."
@change="onQueryChange($event.target.value)"
/>
</div>
<ComboboxOptions v-if="query === '' || filteredMenus.length > 0" static
class="overflow-y-auto divide-y divide-gray-500 scroll-py-2 divide-opacity-10">
<ComboboxOptions
v-if="query === '' || filteredMenus.length > 0"
static
class="overflow-y-auto divide-y divide-gray-500 scroll-py-2 divide-opacity-10"
>
<li class="p-2" v-if="filteredMenus.length > 0 || recent.length > 0">
<h2 v-if="query === '' && recent.length > 0"
class="px-3 mt-4 mb-2 text-xs font-semibold text-gray-900">
<h2
v-if="query === '' && recent.length > 0"
class="px-3 mt-4 mb-2 text-xs font-semibold text-gray-900"
>
Terakhir Diakses
</h2>
<!-- <ul class="text-sm text-gray-700">
@ -78,65 +99,104 @@
</ComboboxOption>
</ul> -->
<ul class="text-sm text-gray-700">
<ComboboxOption as="template" v-for="menu in query === '' ? recent : filteredMenus"
:key="menu.path" v-slot="{ active }">
<ComboboxOption
as="template"
v-for="menu in query === '' ? recent : filteredMenus"
:key="menu.path"
v-slot="{ active }"
>
<li @click="command.openMenu(menu)" class="group">
<div class="flex flex-row items-center justify-between px-3 py-2 rounded-md cursor-pointer select-none lex group-hover:bg-primary-500 group-hover:text-white group-hover:bg-opacity-80">
<component v-if="menu.path.includes('/gangguan/')" :is="navigationIcon[0]"
<div
class="flex flex-row items-center justify-between px-3 py-2 rounded-md cursor-pointer select-none lex group-hover:bg-primary-500 group-hover:text-white group-hover:bg-opacity-80"
>
<component
v-if="menu.path.includes('/gangguan/')"
:is="navigationIcon[0]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/keluhan/')"
:is="navigationIcon[1]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/monalisa/')"
:is="navigationIcon[2]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/check-in-out/')"
:is="navigationIcon[3]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/anomali-pengaduan/')"
:is="navigationIcon[4]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/ctt-kwh-periksa/')"
:is="navigationIcon[5]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/material/')"
:is="navigationIcon[6]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/transaksi/')"
:is="navigationIcon[7]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else :is="navigationIcon[8]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/keluhan/')"
:is="navigationIcon[1]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/monalisa/')"
:is="navigationIcon[2]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/check-in-out/')"
:is="navigationIcon[3]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/anomali-pengaduan/')"
:is="navigationIcon[4]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/ctt-kwh-periksa/')"
:is="navigationIcon[5]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/material/')"
:is="navigationIcon[6]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/transaksi/')"
:is="navigationIcon[7]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else
:is="navigationIcon[8]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<div class="flex flex-col flex-1 ml-3 space-y-1">
<span
class="w-full text-sm font-medium text-gray-800 text-start group-hover:text-white line-clamp-1">
class="w-full text-sm font-medium text-gray-800 text-start group-hover:text-white line-clamp-1"
>
{{ menu.name }}
</span>
<span
class="w-full text-xs text-gray-500 text-start group-hover:text-white line-clamp-1">
class="w-full text-xs text-gray-500 text-start group-hover:text-white line-clamp-1"
>
{{ menu.path.replace('/home/', '') }}
</span>
</div>
<span class="hidden ml-3 text-sm text-gray-500 group-hover:block group-hover:text-white">
<span
class="hidden ml-3 text-sm text-gray-500 group-hover:block group-hover:text-white"
>
Buka
</span>
</div>
</li>
</ComboboxOption>
</ul>
</li>
</ComboboxOptions>
<div v-if="query !== '' && filteredMenus.length === 0" class="px-6 text-center py-14 sm:px-14">
<div
v-if="query !== '' && filteredMenus.length === 0"
class="px-6 text-center py-14 sm:px-14"
>
<h2 class="font-semibold text-slate-900">Tidak ada hasil</h2>
<p class="mt-2 text-sm leading-6 text-slate-600">
Kami tidak dapat menemukan menu apa pun dengan istilah itu saat ini, silahkan gunakan
kata kunci lainnya.
Kami tidak dapat menemukan menu apa pun dengan istilah itu saat ini, silahkan
gunakan kata kunci lainnya.
</p>
</div>
</Combobox>
@ -148,7 +208,7 @@
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import { computed, onMounted, ref } from 'vue'
import { MagnifyingGlassIcon } from '@heroicons/vue/20/solid'
import {
Combobox,
@ -158,25 +218,23 @@ import {
Dialog,
DialogPanel,
TransitionChild,
TransitionRoot,
TransitionRoot
} from '@headlessui/vue'
import { routes } from '@/router'
import { useCommandPalattesStore } from '@/stores/command'
import { navigationIcon } from '@/utils/route'
const command = useCommandPalattesStore()
const recent = computed(() => command.open ? command.readRecent() : [])
const recent = computed(() => (command.open ? command.readRecent() : []))
const query = ref('')
const filteredMenus = computed(() =>
query.value === ''
? []
: command.searchRoutesByName(routes, query.value)
query.value === '' ? [] : command.searchRoutesByName(routes, query.value)
)
let debounceTimeout: ReturnType<typeof setTimeout> | null = null;
let debounceTimeout: ReturnType<typeof setTimeout> | null = null
const onQueryChange = (value: string) => {
if (debounceTimeout) {
clearTimeout(debounceTimeout);
clearTimeout(debounceTimeout)
}
debounceTimeout = setTimeout(() => {
// check if value is empty or only spaces
@ -185,7 +243,10 @@ const onQueryChange = (value: string) => {
return
}
query.value = value
}, 300);
}, 300)
}
onMounted(() => {
window.addEventListener('keydown', (e) => command.onKeyPressed(e))
})
</script>

View File

@ -9,12 +9,15 @@ import PictureInitial from '@/components/PictureInitial.vue'
import { useDialogStore } from '@/stores/dialog'
import { IconApp, IconBars3 } from '@/utils/icons'
import { RouterLink } from 'vue-router'
import { ref } from 'vue'
import { detectOS } from '@/utils/helper'
const auth = useAuthStore()
const user = useUserStore()
const command = useCommandPalattesStore()
const menu = useMenuStore()
const dialog = useDialogStore()
const os = ref(detectOS())
const openSideBar = () => menu.toggleSidebar()
@ -35,7 +38,11 @@ const showDialogLogout = () => {
<template>
<div class="sticky top-0 z-10 flex flex-shrink-0 h-16 bg-primary-50 lg:ml-80">
<button type="button" class="px-4 text-gray-500 focus:outline-none focus:ring-0 lg:hidden" @click="openSideBar">
<button
type="button"
class="px-4 text-gray-500 focus:outline-none focus:ring-0 lg:hidden"
@click="openSideBar"
>
<span class="sr-only">Open sidebar</span>
<IconBars3 class="w-6 h-6 fill-gray-600" />
</button>
@ -44,36 +51,57 @@ const showDialogLogout = () => {
</RouterLink>
<div class="flex justify-end w-full px-4">
<div class="flex items-center ml-4 md:ml-6">
<button @click="command.showCommandPalettes" type="button"
class="flex flex-row items-center md:w-[300px] p-2 mr-2 text-gray-400 bg-white rounded-full hover:text-primary-500 focus:outline-none focus:ring-0">
<button
@click="command.showCommandPalettes"
type="button"
class="justify-between flex flex-row items-center md:w-[300px] p-2 mr-2 text-gray-400 bg-white rounded-full hover:text-primary-500 focus:outline-none focus:ring-0"
>
<span class="sr-only">Search</span>
<MagnifyingGlassIcon class="w-6 h-6 text-primary-500" aria-hidden="true" />
<span class="hidden px-3 text-sm font-medium text-gray-500 md:block text-md">Cari menu</span>
<span
class="flex-1 hidden px-3 text-sm font-medium text-left text-gray-500 md:block text-md"
>Cari menu</span
>
<button class="hidden mx-2 md:block" v-if="os == 'macOS'"> M</button>
</button>
<!-- Profile dropdown -->
<Menu as="div" class="relative ml-1">
<div>
<MenuButton
class="flex items-center max-w-xs px-1 py-1 text-sm rounded-full bg-secondary-100 md:bg-primary-500 focus:outline-none focus:ring-0 line-clamp-1">
class="flex items-center max-w-xs px-1 py-1 text-sm rounded-full bg-secondary-100 md:bg-primary-500 focus:outline-none focus:ring-0 line-clamp-1"
>
<span class="sr-only">Open user menu</span>
<PictureInitial size-class="w-8 h-8" background-class="bg-secondary-100"
font-class="text-xs font-bold text-primary-500" :name="user.user_name" />
<PictureInitial
size-class="w-8 h-8"
background-class="bg-secondary-100"
font-class="text-xs font-bold text-primary-500"
:name="user.user_name"
/>
<span class="hidden px-3 text-xs font-medium md:block text-primary-50 line-clamp-1">
{{ user.user_name }}
</span>
</MenuButton>
</div>
<transition enter-active-class="transition duration-100 ease-out"
enter-from-class="transform scale-95 opacity-0" enter-to-class="transform scale-100 opacity-100"
leave-active-class="transition duration-75 ease-in" leave-from-class="transform scale-100 opacity-100"
leave-to-class="transform scale-95 opacity-0">
<transition
enter-active-class="transition duration-100 ease-out"
enter-from-class="transform scale-95 opacity-0"
enter-to-class="transform scale-100 opacity-100"
leave-active-class="transition duration-75 ease-in"
leave-from-class="transform scale-100 opacity-100"
leave-to-class="transform scale-95 opacity-0"
>
<MenuItems class="container-menu-item">
<div class="container-menu-profile group">
<div class="flex items-center">
<div>
<PictureInitial class-name="inline-block" size-class="w-9 h-9" background-class="bg-secondary-100"
font-class="text-xs font-normal font-semibold text-primary-500" :name="user.user_name" />
<PictureInitial
class-name="inline-block"
size-class="w-9 h-9"
background-class="bg-secondary-100"
font-class="text-xs font-normal font-semibold text-primary-500"
:name="user.user_name"
/>
</div>
<div class="ml-3 space-y-1">
<p class="text-sm font-medium text-primary-50">
@ -89,7 +117,10 @@ const showDialogLogout = () => {
</div>
</div>
<MenuItem v-slot="{ active }">
<button @click="showDialogLogout" :class="[active ? 'menu-item-active' : 'menu-item']">
<button
@click="showDialogLogout"
:class="[active ? 'menu-item-active' : 'menu-item']"
>
Log out
</button>
</MenuItem>

View File

@ -1,12 +1,20 @@
<template>
<div class="flex flex-col items-center justify-between px-4 text-center whitespace-pre-wrap h-[calc(90vh-24px)]">
<div
class="flex flex-col items-center justify-between px-4 text-center whitespace-pre-wrap h-[calc(90vh-24px)]"
>
<div class="w-full flex-1 md:w-[440px] justify-center py-4 md:py-0 flex flex-col items-center">
<img :src="IconApp" alt="pln" class="h-[66px] object-contain mx-auto mb-4">
<button @click="command.showCommandPalettes" type="button"
class="flex flex-row items-center w-full p-2 text-gray-400 rounded-full bg-gray-50 hover:text-primary-500 focus:outline-none focus:ring-0">
<img :src="IconApp" alt="pln" class="h-[66px] object-contain mx-auto mb-4" />
<button
@click="command.showCommandPalettes"
type="button"
class="flex flex-row items-center justify-between w-full p-2 text-gray-400 rounded-full bg-gray-50 hover:text-primary-500 focus:outline-none focus:ring-0"
>
<span class="sr-only">Search</span>
<MagnifyingGlassIcon class="w-6 h-6 text-primary-500" aria-hidden="true" />
<span class="px-3 text-sm font-medium text-gray-500 text-md">Cari menu</span>
<span class="flex-1 px-3 text-sm font-medium text-left text-gray-500 text-md">
Cari menu</span
>
<button class="mx-2" v-if="os == 'macOS'"> M</button>
</button>
<div class="flex mt-3.5" v-if="filteredMenus.length === 0 && recent.length === 0">
@ -15,51 +23,103 @@
</h1>
</div>
<div v-if="query === '' || filteredMenus.length > 0" static class="w-full mt-6 md:mt-8 lg:mt-12">
<div class="flex flex-col items-start w-full p-2" v-if="filteredMenus.length > 0 || recent.length > 0">
<h2 v-if="query === '' && recent.length > 0" class="mb-2 text-xs font-semibold text-gray-900 ">
<div
v-if="query === '' || filteredMenus.length > 0"
static
class="w-full mt-6 md:mt-8 lg:mt-12"
>
<div
class="flex flex-col items-start w-full p-2"
v-if="filteredMenus.length > 0 || recent.length > 0"
>
<h2
v-if="query === '' && recent.length > 0"
class="mb-2 text-xs font-semibold text-gray-900"
>
Terakhir Diakses
</h2>
<div class="flex flex-col w-full space-y-3" v-for="menu in query === '' ? recent : filteredMenus"
:key="menu.path">
<div
class="flex flex-col w-full space-y-3"
v-for="menu in query === '' ? recent : filteredMenus"
:key="menu.path"
>
<div @click="command.openMenu(menu)" class="group">
<div
class="flex flex-row items-center justify-between px-3 py-2 rounded-md cursor-pointer select-none group-hover:bg-primary-500 group-hover:text-white group-hover:bg-opacity-80">
<component v-if="menu.path.includes('/gangguan/')" :is="navigationIcon[0]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/keluhan/')" :is="navigationIcon[1]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/monalisa/')" :is="navigationIcon[2]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/check-in-out/')" :is="navigationIcon[3]"
alt="icon" :class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/anomali-pengaduan/')" :is="navigationIcon[4]"
alt="icon" :class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/ctt-kwh-periksa/')" :is="navigationIcon[5]"
alt="icon" :class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/material/')" :is="navigationIcon[6]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else-if="menu.path.includes('/transaksi/')" :is="navigationIcon[7]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
<component v-else :is="navigationIcon[8]" alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']" />
class="flex flex-row items-center justify-between px-3 py-2 rounded-md cursor-pointer select-none group-hover:bg-primary-500 group-hover:text-white group-hover:bg-opacity-80"
>
<component
v-if="menu.path.includes('/gangguan/')"
:is="navigationIcon[0]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/keluhan/')"
:is="navigationIcon[1]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/monalisa/')"
:is="navigationIcon[2]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/check-in-out/')"
:is="navigationIcon[3]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/anomali-pengaduan/')"
:is="navigationIcon[4]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/ctt-kwh-periksa/')"
:is="navigationIcon[5]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/material/')"
:is="navigationIcon[6]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else-if="menu.path.includes('/transaksi/')"
:is="navigationIcon[7]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<component
v-else
:is="navigationIcon[8]"
alt="icon"
:class="['w-8 h-8 fill-gray-600 group-hover:fill-white flex']"
/>
<div class="flex flex-col items-start flex-1 w-full pl-3 space-y-1">
<span
class="w-full text-sm font-medium text-gray-800 text-start group-hover:text-white line-clamp-1">
class="w-full text-sm font-medium text-gray-800 text-start group-hover:text-white line-clamp-1"
>
{{ menu.name }}
</span>
<span
class="w-full text-xs text-gray-500 text-start group-hover:text-white line-clamp-1">
class="w-full text-xs text-gray-500 text-start group-hover:text-white line-clamp-1"
>
{{ menu.path.replace('/home/', '') }}
</span>
</div>
<span class="hidden ml-3 text-sm text-gray-500 group-hover:block group-hover:text-white">
<span
class="hidden ml-3 text-sm text-gray-500 group-hover:block group-hover:text-white"
>
Buka
</span>
</div>
</div>
</div>
</div>
@ -74,27 +134,30 @@
</template>
<script setup lang="ts">
import { MagnifyingGlassIcon } from '@heroicons/vue/20/solid';
import { MagnifyingGlassIcon } from '@heroicons/vue/20/solid'
import { computed, ref } from 'vue'
import { useCommandPalattesStore } from '@/stores/command'
import { IconApp } from '@/utils/icons'
import { type RouteRecordRaw } from 'vue-router'
import { routes, extractLeafRoutes } from '@/router'
import { navigationIcon } from '@/utils/route';
import { navigationIcon } from '@/utils/route'
import { detectOS } from '@/utils/helper'
const os = ref(detectOS())
const command = useCommandPalattesStore()
const recent = computed(() => query.value === '' ? command.readRecent() : [])
const recent = computed(() => (query.value === '' ? command.readRecent() : []))
const query = ref('')
const searchRoutesByName = (routes: RouteRecordRaw[], query: string): RouteRecordRaw[] => {
const matchingRoutes = extractLeafRoutes(routes, '').filter((item: RouteRecordRaw) => item.path.includes('home/') && item.name?.toString().toLocaleLowerCase().includes(query.toLocaleLowerCase()))
const matchingRoutes = extractLeafRoutes(routes, '').filter(
(item: RouteRecordRaw) =>
item.path.includes('home/') &&
item.name?.toString().toLocaleLowerCase().includes(query.toLocaleLowerCase())
)
return matchingRoutes
}
const filteredMenus = computed(() =>
query.value === ''
? []
: searchRoutesByName(routes, query.value)
query.value === '' ? [] : searchRoutesByName(routes, query.value)
)
</script>

View File

@ -17,29 +17,30 @@ export const useCommandPalattesStore = defineStore('command_palettes', () => {
}
const onKeyPressed = (event: KeyboardEvent) => {
if (event.key === 'Control') {
console.log('control pressed');
controlStatus.value = true
}
if (event.key === 'f') {
console.log('f pressed');
keyFStatus.value = true
}
if (controlStatus.value && keyFStatus.value) {
if ((event.metaKey || event.ctrlKey) && event.key === 'm') {
showCommandPalettes()
// console.log('control pressed')
// controlStatus.value = true
}
// if (event.key === 'f') {
// console.log('f pressed');
// keyFStatus.value = true
// }
// if (controlStatus.value && keyFStatus.value) {
// showCommandPalettes()
// }
}
const onKeyUp = (event: KeyboardEvent) => {
if (event.key === 'Control') {
console.log('control released');
console.log('control released')
controlStatus.value = false
}
if (event.key === 'f') {
console.log('f released');
console.log('f released')
keyFStatus.value = false
}
}
@ -71,12 +72,18 @@ export const useCommandPalattesStore = defineStore('command_palettes', () => {
}
const searchRoutesByName = (routes: RouteRecordRaw[], query: string): RouteRecordRaw[] => {
const matchingRoutes = extractLeafRoutes(routes, '').filter((item: RouteRecordRaw) => item.path.includes('home/') && item.name?.toString().toLocaleLowerCase().includes(query.toLocaleLowerCase()))
const matchingRoutes = extractLeafRoutes(routes, '').filter(
(item: RouteRecordRaw) =>
item.path.includes('home/') &&
item.name?.toString().toLocaleLowerCase().includes(query.toLocaleLowerCase())
)
return matchingRoutes
}
const searchRoutesPath = (routes: RouteRecordRaw[], query: string): RouteRecordRaw[] => {
const matchingRoutes = extractLeafRoutes(routes, '').filter((item: RouteRecordRaw) => item.path.includes('home/') && item.path === query)
const matchingRoutes = extractLeafRoutes(routes, '').filter(
(item: RouteRecordRaw) => item.path.includes('home/') && item.path === query
)
return matchingRoutes
}
@ -86,7 +93,7 @@ export const useCommandPalattesStore = defineStore('command_palettes', () => {
closeCommand()
setTimeout(() => {
menu.expandCurrentActiveMenu()
}, 200);
}, 200)
}
const closeCommand = () => {

View File

@ -37,3 +37,17 @@ export const getDataRowGroup = (data: any): any => {
}
}
}
export const detectOS = () => {
const platform = navigator.userAgent.toLowerCase()
if (platform.includes('mac')) {
return 'macOS'
} else if (platform.includes('win')) {
return 'Windows'
} else if (platform.includes('linux')) {
return 'Linux'
} else {
return 'Unknown'
}
}