This commit is contained in:
Dede Fuji Abdul 2023-10-17 09:20:08 +07:00
parent 1080aeca75
commit fc37eab5db
11 changed files with 303 additions and 831 deletions

View File

@ -1,10 +1,17 @@
<script setup lang="ts">
import { RouterView } from 'vue-router'
import { NotificationProvider } from '@/components/Notification'
import { useDialogStore } from '@/stores/dialog'
import ActionDialog from '@/components/Dialogs/ActionDialog.vue';
const dialog = useDialogStore()
</script>
<template>
<NotificationProvider>
<ActionDialog :type="dialog.type" :title="dialog.title" :message="dialog.content" :cancel-text="dialog.cancelText"
:confirm-text="dialog.confirmText" :open="dialog.open" @onClose="dialog.dismissOnAction"
@onConfirm="dialog.onConfirm" />
<RouterView />
</NotificationProvider>
</template>

View File

@ -1,78 +1,3 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition: color 0.5s, background-color 0.5s;
line-height: 1.6;
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Firefox */
* {
scrollbar-width: 4px;
@ -93,4 +18,40 @@ body {
background-color: var(--secondary);
border-radius: 14px;
border: 3px solid var(--primary);
}
* { -webkit-tap-highlight-color: rgba(0,0,0,0); }
.no-scroll-bar {
-ms-overflow-style: none;
scrollbar-width: none;
}
.no-scroll-bar::-webkit-scrollbar {
display: none;
}
.scroll-container::-webkit-scrollbar {
width: 8px;
height: 8px;
background-color: #F3F4F6;
transition: background-color 0.5s;
}
.scroll-container::-webkit-scrollbar-thumb {
border-radius: 8px;
background-color: #D1D5DB;
transition: background-color 0.5s;
}
.scroll-hidden::-webkit-scrollbar {
width: 8px;
height: 8px;
background-color: transparent;
transition: background-color 0.5s;
}
.scroll-hidden::-webkit-scrollbar-thumb {
border-radius: 8px;
background-color: transparent;
transition: background-color 0.5s;
}

View File

@ -1,39 +1,3 @@
/* @import './base.css'; */
@import './base.css';
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;700&display=swap');
@import './style.css';
/* #app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
} */
/* a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
} */
@import './style.css';

View File

@ -1068,6 +1068,10 @@ select {
height: 74vh;
}
.h-\[calc\(100\%-64px\)\] {
height: calc(100% - 64px);
}
.h-fit {
height: -moz-fit-content;
height: fit-content;
@ -1081,18 +1085,6 @@ select {
height: 80vh;
}
.h-\[calc\(100\%-56px\)\] {
height: calc(100% - 56px);
}
.h-\[calc\(100\%-60px\)\] {
height: calc(100% - 60px);
}
.h-\[calc\(100\%-64px\)\] {
height: calc(100% - 64px);
}
.max-h-0 {
max-height: 0px;
}
@ -1105,10 +1097,6 @@ select {
max-height: 1000px;
}
.max-h-full {
max-height: 100%;
}
.min-h-0 {
min-height: 0px;
}
@ -1221,10 +1209,6 @@ select {
width: 100vw;
}
.w-\[200px\] {
width: 200px;
}
.min-w-0 {
min-width: 0px;
}
@ -1521,10 +1505,6 @@ select {
border-radius: 0.75rem;
}
.rounded-3xl {
border-radius: 1.5rem;
}
.rounded-l-full {
border-top-left-radius: 9999px;
border-bottom-left-radius: 9999px;
@ -1723,6 +1703,11 @@ select {
background-color: rgb(204 0 0 / var(--tw-bg-opacity));
}
.bg-secondary-100 {
--tw-bg-opacity: 1;
background-color: rgb(204 235 239 / var(--tw-bg-opacity));
}
.bg-transparent {
background-color: transparent;
}
@ -1747,11 +1732,6 @@ select {
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
.bg-secondary-100 {
--tw-bg-opacity: 1;
background-color: rgb(204 235 239 / var(--tw-bg-opacity));
}
.bg-opacity-25 {
--tw-bg-opacity: 0.25;
}
@ -2168,6 +2148,11 @@ select {
color: rgb(234 88 12 / var(--tw-text-opacity));
}
.text-primary-50 {
--tw-text-opacity: 1;
color: rgb(230 239 241 / var(--tw-text-opacity));
}
.text-primary-500 {
--tw-text-opacity: 1;
color: rgb(3 91 113 / var(--tw-text-opacity));
@ -2213,11 +2198,6 @@ select {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.text-primary-50 {
--tw-text-opacity: 1;
color: rgb(230 239 241 / var(--tw-text-opacity));
}
.text-opacity-100 {
--tw-text-opacity: 1;
}
@ -3022,14 +3002,14 @@ select {
margin-left: 20rem;
}
.md\:mr-6 {
margin-right: 1.5rem;
}
.md\:mr-4 {
margin-right: 1rem;
}
.md\:mr-6 {
margin-right: 1.5rem;
}
.md\:block {
display: block;
}
@ -3050,10 +3030,6 @@ select {
width: 20rem;
}
.md\:w-\[200px\] {
width: 200px;
}
.md\:w-\[300px\] {
width: 300px;
}
@ -3093,21 +3069,6 @@ select {
padding-bottom: 1.5rem;
}
.md\:px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.md\:py-1 {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
.md\:px-1 {
padding-left: 0.25rem;
padding-right: 0.25rem;
}
.md\:pl-80 {
padding-left: 20rem;
}

View File

@ -1,8 +1,8 @@
<script setup lang="ts">
import { watch } from 'vue';
import { useRoute } from 'vue-router';
import { watch } from 'vue'
import { useRoute } from 'vue-router'
import { RouterLink } from 'vue-router'
import Icon from '@/assets/images/pln-with-text.png';
import Icon from '@/assets/images/pln-with-text.png'
import { ref } from 'vue'
import {
Dialog,
@ -24,287 +24,29 @@ import {
FolderOpenIcon,
ShieldCheckIcon,
XMarkIcon
} from '@heroicons/vue/24/solid'
} from '@heroicons/vue/24/outline'
import { useMenuStore } from '@/stores/menu'
const navigation = [
const nav = useMenuStore()
const navigation = nav.navigation
{
name: 'Daftar Transaksi',
icon: DocumentDuplicateIcon,
href: '/daftar-transaksi',
children: [
{ name: 'Transaksi Aktif Individual', href: '/daftar-transaksi/aktif-bulanan', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Transaksi Aktif PLN Mobile', href: '/daftar-transaksi/aktif-pln-mobile', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Transaksi Aktif Periksa dan Return Order', href: '/daftar-transaksi/periksa-return-order', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Transaksi Aktif TM', href: '/daftar-transaksi/aktif-tm', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Transaksi Aktif Historis', href: '/daftar-transaksi/aktif-historis', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Monitoring Alih Unit', href: '/daftar-transaksi/monitoring-alih-unit', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Monitoring All', href: '/daftar-transaksi/monitoring-all', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Monitoring Tiket', href: '/daftar-transaksi/monitoring-tiket', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Monitoring History', href: '/daftar-transaksi/monitoring-history', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Monitoring Aktif', href: '/daftar-transaksi/monitoring-aktif', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Monitoring Close di CC', href: '/daftar-transaksi/monitoring-close-cc', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Monitoring Log AutoDispatch', href: '/daftar-transaksi/monitoring-log-autodispatch', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Monitoring Yang Perlu Diperhatikan', href: '/daftar-transaksi/monitoring-perlu-diperhatikan', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Monitoring Log Break Regu', href: '/daftar-transaksi/monitoring-log-break-regu', icon: DocumentDuplicateIcon, children: [], },
{ name: 'Monitoring Log Alih Regu', href: '/daftar-transaksi/monitoring-log-alih-regu', icon: DocumentDuplicateIcon, children: [], },
],
},
{
name: 'Administration',
icon: ShieldCheckIcon,
href: '/administration',
children: [
{
name: 'Audit Trails',
icon: ShieldCheckIcon,
href: '/administration/audit-trails',
children: [
{
name: 'Log Login',
href: '/administration/audit-trails/log-login',
icon: ShieldCheckIcon,
children: [],
},
{
name: 'Log Activity',
href: '/administration/audit-trails/log-aktivity',
icon: ShieldCheckIcon,
children: [],
},
{
name: 'Log Error',
href: '/administration/audit-trails/log-error',
icon: ShieldCheckIcon,
children: [],
},
],
},
{
name: 'Task Management',
icon: ShieldCheckIcon,
href: '/administration/task-management',
children: [
{ name: 'Menu Management', href: '/administration/task-management/menu-management', icon: ShieldCheckIcon, children: [], },
{ name: 'System Parameter', href: '/administration/task-management/system-parameter', icon: ShieldCheckIcon, children: [], },
{ name: 'User Profile Manager', href: '/administration/task-management/ubah-profile-manager', icon: ShieldCheckIcon, children: [], },
{ name: 'Security Projek', href: '/administration/task-management/security-projek', icon: ShieldCheckIcon, children: [], },
{ name: 'User Role Manager', href: '/administration/task-management/user-role-manager', icon: ShieldCheckIcon, children: [], },
{ name: 'Menu Authorization', href: '/administration/task-management/menu-authorization', icon: ShieldCheckIcon, children: [], },
{ name: 'Workflow Designer', href: '/administration/task-management/workflow-designer', icon: ShieldCheckIcon, children: [], },
{ name: 'APKT News', href: '/administration/task-management/apkt-news', icon: ShieldCheckIcon, children: [], },
],
},
{
name: 'Master Borderless',
icon: ShieldCheckIcon,
href: '/administration/master-borderless',
children: [
{ name: 'Zone Borderless', href: '/administration/master-borderless/zone-borderless', icon: ShieldCheckIcon, children: [], },
{ name: 'User Zone Borderless', href: '/administration/master-borderless/user-zone-borderless', icon: ShieldCheckIcon, children: [], },
],
},
],
},
{
name: 'Master Yantek',
icon: FolderOpenIcon,
href: '/master-yantek',
children: [
{ name: 'Unit', href: '/master-yantek/unit', icon: FolderOpenIcon, children: [], },
{ name: 'Unit Jaringan', href: '/master-yantek/unit-jaringan', icon: FolderOpenIcon, children: [], },
{ name: 'Unit Pelayanan', href: '/master-yantek/unit-pelayanan', icon: FolderOpenIcon, children: [], },
{ name: 'Regu Yantek', href: '/master-yantek/regu-yantek', icon: FolderOpenIcon, children: [], },
{ name: 'Gardu Induk', href: '/master-yantek/gardu-induk', icon: FolderOpenIcon, children: [], },
{ name: 'Gardu Penyulang TM', href: '/master-yantek/gardu-penyulang-tm', icon: FolderOpenIcon, children: [], },
{ name: 'Gardu Distribusi', href: '/master-yantek/gardu-distribusi', icon: FolderOpenIcon, children: [], },
{ name: 'Group Gangguan', href: '/master-yantek/group-gangguan', icon: FolderOpenIcon, children: [], },
{ name: 'Wilayah Yantek', href: '/master-yantek/wilayah-yantek', icon: FolderOpenIcon, children: [], },
{ name: 'Material', href: '/master-yantek/material', icon: FolderOpenIcon, children: [], },
],
},
{
name: 'Transaksi',
icon: DocumentTextIcon,
href: '/transaksi',
children: [
{ name: 'Gangguan dan Keluhan', href: '/transaksi/gangguan-dan-keluhan', icon: DocumentTextIcon, children: [], },
{ name: 'Gangguan Tegangan Menengah', href: '/transaksi/gangguan-tegangan-menengah', icon: DocumentTextIcon, children: [], },
{ name: 'Pemadaman Terencana', href: '/transaksi/pemadaman-terencana', icon: DocumentTextIcon, children: [], },
{ name: 'Aplikasi Off-Line', href: '/transaksi/aplikasi-off-line', icon: DocumentTextIcon, children: [], },
{ name: 'Penugasan Khusus', href: '/transaksi/penugasan-khusus', icon: DocumentTextIcon, children: [], },
{ name: 'Mutasi Pengaduan', href: '/transaksi/mutasi-pengaduan', icon: DocumentTextIcon, children: [], },
],
},
{
name: 'Saidi Saifi',
icon: ComputerDesktopIcon,
href: '/saidi-saifi',
children: [
{
name: 'Monitor Jaringan',
icon: ComputerDesktopIcon,
href: '/saidi-saifi/monitor-jaringan',
children: [
{
name: 'Dashboard Asset',
href: '/saidi-saifi/monitor-jaringan/dashboard-asset',
icon: ComputerDesktopIcon,
children: [],
},
{
name: 'Manuver Topologi Jaringan',
href: '/saidi-saifi/monitor-jaringan/manuver-topologi-jaringan',
icon: ComputerDesktopIcon,
children: [],
},
{
name: 'Pencarian Segment Jaringan',
href: '/saidi-saifi/monitor-jaringan/pencarian-segment-jaringan',
icon: ComputerDesktopIcon,
children: [],
},
{
name: 'Penormalan Manuver Jaringan',
href: '/saidi-saifi/monitor-jaringan/penormalan-manuver-jaringan',
icon: ComputerDesktopIcon,
children: [],
},
{
name: 'Pindah Jaringan',
href: '/saidi-saifi/monitor-jaringan/pindah-jaringan',
icon: ComputerDesktopIcon,
children: [],
},
],
},
{
name: 'Monitoring SCADA',
icon: ComputerDesktopIcon,
href: '/saidi-saifi/monitor-scada/',
children: [
{ name: 'Monitoring Mapping Database', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Monitoring Log SCADA', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Mapping Gardu Induk', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Mapping Feeder', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Mapping Zona', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Mapping Lateral', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Mapping Section', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Mapping Segment', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Mapping Sub Lateral', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Mapping Gardu Distribusi', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Mapping Trafo', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Mapping Jurusan', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Monitoring Integrasi ????', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Monitoring Integrasi per No Tiang', href: '/saidi-saifi/monitor-scada/', icon: ComputerDesktopIcon, children: [], },
],
},
{
name: 'Master Jaringan',
icon: ComputerDesktopIcon,
href: '/saidi-saifi/master-jaringan/',
children: [
{ name: 'Master Gardu Induk', href: '/saidi-saifi/master-jaringan/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Master Feeder', href: '/saidi-saifi/master-jaringan/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Master Zona', href: '/saidi-saifi/master-jaringan/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Master Section', href: '/saidi-saifi/master-jaringan/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Master Segement', href: '/saidi-saifi/master-jaringan/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Master Lateral', href: '/saidi-saifi/master-jaringan/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Master Gardu Distribusi', href: '/saidi-saifi/master-jaringan/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Master Switch', href: '/saidi-saifi/master-jaringan/', icon: ComputerDesktopIcon, children: [], },
],
},
{
name: 'Master Perhitungan',
icon: ComputerDesktopIcon,
href: '/saidi-saifi/master-perhitungan/',
children: [
{ name: 'Master Asumsi', href: '/saidi-saifi/master-perhitungan/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Master Asumsi Salatiga', href: '/saidi-saifi/master-perhitungan/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Master Faktor Daya & Beban', href: '/saidi-saifi/master-perhitungan/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Data III-09', href: '/saidi-saifi/master-perhitungan/', icon: ComputerDesktopIcon, children: [], },
],
},
{
name: 'Laporan Saidi Saifi',
icon: ComputerDesktopIcon,
href: '/saidi-saifi/laporan-saidi-saifi/',
children: [
{ name: 'Laporan Saidi Saifi per Penyulang', href: '/saidi-saifi/laporan-saidi-saifi/', icon: ComputerDesktopIcon, children: [], },
],
},
{
name: 'Pelanggan Prioritas',
icon: ComputerDesktopIcon,
href: '/saidi-saifi/pelanggan-prioritas/',
children: [
{ name: 'Daftar Pelanggan Prioritas', href: '/saidi-saifi/pelanggan-prioritas/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Monitoring Pelanggan Prioritas', href: '/saidi-saifi/pelanggan-prioritas/', icon: ComputerDesktopIcon, children: [], },
],
},
{
name: 'Koreksi dan Cleansing',
icon: ComputerDesktopIcon,
href: '/saidi-saifi/koreksi-dan-cleansing/',
children: [
{ name: 'Monitoring Koreksi dan Cleansing', href: '/saidi-saifi/koreksi-dan-cleansing/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Koreksi Transaksi Individual', href: '/saidi-saifi/koreksi-dan-cleansing/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Koreksi dan Cleansing TM', href: '/saidi-saifi/koreksi-dan-cleansing/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Koreksi Kode Gangguan dan ANEV', href: '/saidi-saifi/koreksi-dan-cleansing/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Laporan Koreksi dan Cleansing', href: '/saidi-saifi/koreksi-dan-cleansing/', icon: ComputerDesktopIcon, children: [], },
{ name: 'Delegasi Koreksi dan Cleansing', href: '/saidi-saifi/koreksi-dan-cleansing/', icon: ComputerDesktopIcon, children: [], },
],
},
],
},
{
name: 'Utility',
icon: BoltIcon,
href: '/utility',
children: [
{ name: 'Piket Obank', href: '/utility/piket-obank', icon: BoltIcon, children: [], },
],
},
{
name: 'EIS',
icon: FolderArrowDownIcon,
href: '/eis',
children: [],
},
{
name: 'Pengaturan',
icon: Cog6ToothIcon,
href: '/pengaturan',
children: [
{ name: 'Ganti Password', href: '/pengaturan/gantu-password', icon: Cog6ToothIcon, children: [], },
],
},
]
const route = useRoute();
const menuSelected = ref(route.fullPath);
const route = useRoute()
const menuSelected = ref(route.fullPath)
watch(route, (to, _) => {
menuSelected.value = to.fullPath
});
closeSideBar()
})
const isMenu = (name: string) => {
return menuSelected.value === name
}
const props = defineProps({
sideBarStatus: Boolean,
});
const emits = defineEmits(['onChangeSideBarStatus']);
const localSideBarStatus = ref(props.sideBarStatus)
function closeSideBar() {
localSideBarStatus.value = false;
emits('onChangeSideBarStatus', false);
};
const closeSideBar = () => nav.toggleSidebar()
</script>
<template>
<TransitionRoot as="template" :show="sideBarStatus">
<TransitionRoot as="template" :show="nav.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"
@ -317,7 +59,7 @@ function closeSideBar() {
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-white">
<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">
@ -331,17 +73,89 @@ function closeSideBar() {
</div>
</TransitionChild>
<div class="flex items-center flex-shrink-0 px-4">
<img class="w-auto h-16" :src="Icon" alt="PLN" />
<RouterLink to="/">
<img class="w-auto h-16" :src="Icon" alt="PLN" />
</RouterLink>
</div>
<div class="flex-1 h-0 mt-5 overflow-y-auto">
<nav class="px-2 space-y-1">
<RouterLink v-for="item in navigation" :key="item.name" :to="item.href"
:class="[isMenu(item.href) ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900', 'group flex items-center px-2 py-2 text-base font-medium rounded-md']">
<component :is="item.icon"
:class="[isMenu(item.href) ? 'text-gray-500' : 'text-gray-400 group-hover:text-gray-500', 'mr-4 flex-shrink-0 h-6 w-6']"
aria-hidden="true" />
{{ item.name }}
</RouterLink>
<template v-for="item in navigation" :key="item.name">
<div v-if="!item.children || item.children.length === 0">
<!-- 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']">
<component :is="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']"
aria-hidden="true" />
<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 || 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>
</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>
</DisclosurePanel>
</template>
</Disclosure>
</template>
</DisclosurePanel>
</template>
</Disclosure>
</template>
</nav>
</div>
</DialogPanel>
@ -353,86 +167,102 @@ function closeSideBar() {
</Dialog>
</TransitionRoot>
<!-- Static sidebar for desktop -->
<div class="z-10 hidden bg-gray-600 md:fixed md:inset-y-0 md:flex md:w-80 md:flex-col">
<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">
<img class="w-auto h-11" :src="Icon" alt="PLN" />
<div class="flex items-center flex-shrink-0 h-16 px-5 border-b border-gray-100 border-dashed">
<RouterLink to="/">
<img class="w-auto h-11" :src="Icon" alt="PLN" />
</RouterLink>
</div>
<div class="flex flex-col flex-grow bg-gray-600 hover:overflow-y-auto">
<div class="flex flex-col flex-grow mt-5 ">
<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 || item.children.length === 0">
<!-- Single-level item -->
<RouterLink :to="item.href"
:class="[isMenu(item.href) ? 'bg-primary-500 text-white font-medium' : 'text-gray-500 hover:bg-primary-100 hover:text-gray-900', 'group w-full flex items-center pl-2 py-2 text-xs font-medium rounded-md']">
: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-gray-500 group-hover:text-gray-900', 'mr-3 flex-shrink-0 h-6 w-6']"
: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
<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 -->
<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-medium' : 'text-gray-500 hover:bg-primary-100 hover:text-gray-900', 'group w-full flex items-center pl-2 pr-1 py-2 text-left text-xs font-medium rounded-md focus:outline-none focus:ring-0 focus:ring-indigo-500']">
<component :is="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']"
aria-hidden="true" />
<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>
<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']">
<component :is="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']"
aria-hidden="true" />
<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="transition duration-500 transform ease"
enter-from-class="-translate-y-12 opacity-0" enter-to-class="translate-y-0 opacity-100"
leave-active-class="duration-300 transform dtransition ease"
leave-from-class="translate-y-0 opacity-100" leave-to-class="-translate-y-12 opacity-0"> -->
<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 in item.children" :key="subItem.name">
<template v-for="(subItem, index) in item.children" :key="subItem.href">
<div v-if="!subItem.children || subItem.children.length === 0">
<!-- Single-level child -->
<RouterLink :to="subItem.href"
:class="[isMenu(subItem.href) ? 'text-white font-medium bg-primary-500' : 'text-gray-500 hover:bg-primary-100 hover:text-gray-900', 'flex items-center w-11/12 py-2 px-2 text-xs font-medium rounded-md group ml-auto']">
: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>
</div>
<Disclosure v-else
<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 -->
<template v-slot="{ open }">
<DisclosureButton
:class="[subItem.children.find((d: any) => d.href === menuSelected) ? 'text-primary-500 font-medium' : 'text-gray-500 hover:bg-primary-100 hover:text-gray-900', 'group w-11/12 flex items-center px-2 py-2 text-left text-xs font-medium rounded-md 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>
<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 -->
<RouterLink v-for="nestedSubItem in subItem.children"
:key="nestedSubItem.name" :to="nestedSubItem.href"
:class="[isMenu(nestedSubItem.href) ? 'text-white font-medium bg-primary-500' : 'text-gray-500 hover:bg-primary-100 hover:text-gray-900', 'flex items-center w-12/12 py-2 px-2 text-xs font-medium rounded-md group ml-auto']">
:key="nestedSubItem.href" :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>
</DisclosurePanel>
</template>
</transition>
</Disclosure>
</template>
</DisclosurePanel>
</template>
</transition>
</Disclosure>
@ -442,4 +272,5 @@ function closeSideBar() {
</div>
</div>
</div>
</template>
</template>

View File

@ -1,285 +0,0 @@
<script setup lang="ts">
import { watch } from 'vue'
import { useRoute } from 'vue-router'
import { RouterLink } from 'vue-router'
import Icon from '@/assets/images/pln-with-text.png'
import { ref } from 'vue'
import {
Dialog,
DialogPanel,
Disclosure,
DisclosureButton,
DisclosurePanel,
TransitionChild,
TransitionRoot,
} from '@headlessui/vue'
import {
BoltIcon,
Cog6ToothIcon,
ComputerDesktopIcon,
DocumentDuplicateIcon,
DocumentTextIcon,
FolderArrowDownIcon,
FolderOpenIcon,
ShieldCheckIcon,
XMarkIcon
} from '@heroicons/vue/24/outline'
import { useMenuStore } from '@/stores/menu'
const nav = useMenuStore()
const navigation = nav.navigation
const route = useRoute()
const menuSelected = ref(route.fullPath)
watch(route, (to, _) => {
menuSelected.value = to.fullPath
closeSideBar()
});
const isMenu = (name: string) => {
return menuSelected.value === name
}
const props = defineProps({
sideBarStatus: Boolean,
});
const emits = defineEmits(['onChangeSideBarStatus'])
const localSideBarStatus = ref(props.sideBarStatus)
const closeSideBar = () => {
localSideBarStatus.value = false
emits('onChangeSideBarStatus', false)
}
</script>
<template>
<TransitionRoot as="template" :show="sideBarStatus">
<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="Icon" 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">
<!-- 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']">
<component :is="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']"
aria-hidden="true" />
<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 || 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>
</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>
</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 border-b border-gray-100 border-dashed">
<RouterLink to="/">
<img class="w-auto h-11" :src="Icon" 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 || item.children.length === 0">
<!-- 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-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']">
<component :is="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']"
aria-hidden="true" />
<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="transition duration-500 transform ease"
enter-from-class="-translate-y-12 opacity-0" enter-to-class="translate-y-0 opacity-100"
leave-active-class="duration-300 transform dtransition ease"
leave-from-class="translate-y-0 opacity-100" leave-to-class="-translate-y-12 opacity-0"> -->
<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 -->
<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>
</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 -->
<RouterLink v-for="nestedSubItem in subItem.children"
:key="nestedSubItem.href" :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>
</DisclosurePanel>
</transition>
</Disclosure>
</template>
</DisclosurePanel>
</transition>
</Disclosure>
</template>
</nav>
</div>
</div>
</div>
</template>

View File

@ -8,6 +8,7 @@ import { useAuthStore } from '@/stores/auth'
import { useUserStore } from '@/stores/user'
import { useCommandPalattesStore } from '@/stores/command'
import { useMessageStore } from '@/stores/message'
import { useMenuStore } from '@/stores/menu'
import {
Menu,
MenuButton,
@ -23,22 +24,18 @@ import {
import { MagnifyingGlassIcon } from '@heroicons/vue/24/solid'
import { onMounted, onUnmounted, ref } from 'vue'
import PictureInitial from './PictureInitial.vue'
import Icon from '@/assets/images/pln-with-text.png'
import { useDialogStore } from '@/stores/dialog'
const authStore = useAuthStore()
const userStore = useUserStore()
const messageStore = useMessageStore()
const commandStore = useCommandPalattesStore()
const menu = useMenuStore()
const dialog = useDialogStore()
const props = defineProps({ sideBarStatus: Boolean })
const status = ref(props.sideBarStatus)
const emits = defineEmits(['onChangeSideBarStatus'])
const openSideBar = () => menu.toggleSidebar()
const openSideBar = () => {
status.value = true
emits('onChangeSideBarStatus', true)
};
const dialogLogout = ref(false)
const dialogChangePassword = ref(false)
const handleOnDismissDialogChangePassword = () => {
@ -49,38 +46,30 @@ const showDialogChangePassword = () => {
dialogChangePassword.value = true
}
const handleOnDismissDialogLogout = () => {
dialogLogout.value = false
}
const showDialogLogout = () => {
dialogLogout.value = true
dialog.type = 'error'
dialog.title = 'Keluar dari akun?'
dialog.content = 'Apakah Anda sudah yakin akan keluar dari akun ini?'
dialog.cancelText = 'Batalkan'
dialog.confirmText = 'Ya, keluar'
dialog.showCancelButton = true
dialog.onConfirm = () => {
window.location.href = '/login'
}
dialog.open = true
}
const handleOnConfirmDialogLogout = () => {
authStore.logout()
window.location.href = '/login'
}
onMounted(() => {
// document.addEventListener('keydown', commandStore.onKeyPressed);
// document.addEventListener('keyup', commandStore.onKeyUp);
});
onUnmounted(() => {
// document.removeEventListener('keydown', commandStore.onKeyPressed);
// document.removeEventListener('keyup', commandStore.onKeyUp);
});
</script>
<template>
<div class="sticky top-0 z-10 flex flex-shrink-0 h-16 bg-primary-50 md:ml-80">
<button type="button" class="px-4 text-gray-500 border-gray-200 focus:outline-none focus:ring-0 md:hidden"
@click="openSideBar">
<button type="button" class="px-4 text-gray-500 focus:outline-none focus:ring-0 md:hidden" @click="openSideBar">
<span class="sr-only">Open sidebar</span>
<Bars3BottomLeftIcon class="w-6 h-6" aria-hidden="true" />
</button>
<div class="flex items-center flex-shrink-0 my-auto ml-2 md:hidden">
<img class="w-auto h-11" :src="Icon" alt="PLN" />
</div>
<div class="flex justify-end w-full px-4">
<!-- <div class="flex flex-1">
<div class="flex w-full md:ml-0">
@ -91,6 +80,7 @@ onUnmounted(() => {
<span class="hidden ml-2 sm:text-sm md:block">Cari menu...</span>
</div>
</button>
<img :src="Icon" alt="pln" class="md:hidden">
</div>
</div> -->
@ -174,9 +164,6 @@ onUnmounted(() => {
</div>
</div>
<ActionDialog type="error" title="Keluar dari akun?" message="Apakah Anda sudah yakin akan keluar dari akun ini?"
cancel-text="Batalkan" confirm-text="Ya, keluar" :open="dialogLogout" @onClose="handleOnDismissDialogLogout"
@onConfirm="handleOnConfirmDialogLogout" />
<ChangePasswordDialog :open="dialogChangePassword" @onClose="handleOnDismissDialogChangePassword" />
<CommandPalettes :open="commandStore.open" @onClose="commandStore.handleOnDismissCommandPalettes" />
<MessageBox :open="messageStore.open" @onClose="messageStore.handleOnDismissMessageBox" />

View File

@ -1,5 +1,6 @@
<template>
<main class="flex-1 px-2 py-2 overflow-y-auto bg-white md:mr-4 sm:px-4 md:px-6 sm:py-4 md:py-6 rounded-t-3xl">
<main
class="flex-1 px-2 py-2 overflow-y-auto bg-white md:mr-4 sm:px-4 md:px-6 sm:py-4 md:py-6 rounded-t-3xl no-scroll-bar">
<div v-if="route.path !== '/home'" class="mx-auto max-w-7xl">
<h1 class="text-lg font-medium md:text-2xl lg:text-3xl text-dark">{{ currentRouteName }}</h1>
</div>

View File

@ -1,16 +1,9 @@
<script setup lang="ts">
import Aside from '@/components/AsideWhite.vue'
import Aside from '@/components/Aside.vue'
import Header from '@/components/Header.vue'
import { ref } from 'vue'
const sideBarStatus = ref(false)
const handleChangeSideBarStatus = (status: boolean) => {
sideBarStatus.value = status
}
</script>
<template>
<Header :sideBarStatus="sideBarStatus" @onChangeSideBarStatus="handleChangeSideBarStatus" />
<Aside :sideBarStatus="sideBarStatus" @onChangeSideBarStatus="handleChangeSideBarStatus" />
<Header />
<Aside />
</template>

50
src/stores/dialog.ts Normal file
View File

@ -0,0 +1,50 @@
import { defineStore } from 'pinia'
import { ref, watch } from 'vue'
export const useDialogStore = defineStore('dialog', () => {
const onConfirm = ref<Function>()
const onCancel = ref<Function>()
const confirmText = ref('')
const cancelText = ref('')
const open = ref(false)
const title = ref('')
const content = ref('')
const type = ref('normal')
const showCancelButton = ref(true)
const dismissOnAction = ref(true)
const timer = ref<any>()
watch(open, (value) => {
if (!value) {
// check if timer is set
if (timer.value) {
clearTimeout(timer.value)
}
timer.value = setTimeout(() => {
onConfirm.value = () => { }
onCancel.value = () => { }
dismissOnAction.value = true
showCancelButton.value = true
}, 2000)
} else {
if (timer.value) {
clearTimeout(timer.value)
}
}
})
return {
showCancelButton,
dismissOnAction,
onConfirm,
onCancel,
title,
content,
type,
open,
confirmText,
cancelText,
}
})

View File

@ -2,11 +2,9 @@ import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
import {
BoltIcon,
Cog6ToothIcon,
ComputerDesktopIcon,
DocumentDuplicateIcon,
DocumentTextIcon,
FolderArrowDownIcon,
FolderOpenIcon,
ShieldCheckIcon,
} from '@heroicons/vue/24/outline'
@ -252,8 +250,12 @@ export const useMenuStore = defineStore('menu', () => {
],
},
]
const sidebarOpen = ref(false)
const toggleSidebar = () => (sidebarOpen.value = !sidebarOpen.value)
// expose everything
return { navigation }
return {
navigation,
toggleSidebar,
sidebarOpen
}
})