import { defineNuxtPlugin } from '#app'; import { usePermissionStore } from '~/stores/permissionStore'; import type { HakAksesMenu } from '~/server/utils/schemas/permissionSchema'; export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.directive('permission', { mounted(el, binding) { const permissionStore = usePermissionStore(); // Determine what action to check based on modifiers or value. // If it's an array: v-permission="['canEdit', 'canDelete']" // If it's a string: v-permission="'canEdit'" const permissionsRequired = Array.isArray(binding.value) ? binding.value : [binding.value]; // Determine the menuKey context. // In a real app, you might inject this context from the page component. // For now, we extract it from the current route name. const currentRoute = useRoute(); let menuKey = ""; if (currentRoute && currentRoute.name) { // Convert vue-router route name to our menuKey format menuKey = currentRoute.name.toString().toLowerCase().replace(/_|-/g, '-'); } let hasPermission = true; for (const action of permissionsRequired) { if (!permissionStore.can(menuKey, action as keyof HakAksesMenu)) { hasPermission = false; break; } } if (!hasPermission) { if (binding.arg === 'disable') { el.disabled = true; el.classList.add('v-btn--disabled'); // If it's vuetify button el.setAttribute('title', 'Anda tidak memiliki izin untuk aksi ini'); el.style.opacity = '0.5'; el.style.pointerEvents = 'none'; } else { // Default: hide el.style.display = 'none'; // Better hide by removing from DOM if possible, // but display: none is safer for custom directives that don't want to break layout engines // To truly remove: el.parentNode?.removeChild(el) (but breaks if Vue tries to update it) } } }, updated(el, binding) { // Handle reactivity if permissions change or route changes const permissionStore = usePermissionStore(); const permissionsRequired = Array.isArray(binding.value) ? binding.value : [binding.value]; const currentRoute = useRoute(); let menuKey = ""; if (currentRoute && currentRoute.name) { menuKey = currentRoute.name.toString().toLowerCase().replace(/_|-/g, '-'); } let hasPermission = true; for (const action of permissionsRequired) { if (!permissionStore.can(menuKey, action as keyof HakAksesMenu)) { hasPermission = false; break; } } if (!hasPermission) { if (binding.arg === 'disable') { el.disabled = true; el.classList.add('v-btn--disabled'); el.setAttribute('title', 'Anda tidak memiliki izin untuk aksi ini'); el.style.opacity = '0.5'; el.style.pointerEvents = 'none'; } else { el.style.display = 'none'; } } else { // Restore if permission was granted if (binding.arg === 'disable') { el.disabled = false; el.classList.remove('v-btn--disabled'); el.removeAttribute('title'); el.style.opacity = '1'; el.style.pointerEvents = 'auto'; } else { el.style.display = ''; // Revert to original display } } } }); });