diff --git a/app/components/content/resume/list.vue b/app/components/content/resume/list.vue index d8d8c721..4b5b5001 100644 --- a/app/components/content/resume/list.vue +++ b/app/components/content/resume/list.vue @@ -19,9 +19,17 @@ import Confirmation from '~/components/pub/my-ui/confirmation/confirmation.vue' import type { ExposedForm } from '~/types/form' import { VerificationSchema } from '~/schemas/verification.schema' import DocPreviewDialog from '~/components/pub/my-ui/modal/doc-preview-dialog.vue' - +import type { PagePermission } from '~/models/role' +import { PAGE_PERMISSIONS } from '~/lib/page-permission' +import { unauthorizedToast } from '~/lib/utils' // #endregion + +// #region Permission +const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/encounter'] +const { getPagePermissions } = useRBAC() +const pagePermission = getPagePermissions(roleAccess) + // #region State const { data, isLoading, paginationMeta, searchInput, handlePageChange, handleSearch, fetchData } = usePaginatedList({ fetchFn: (params) => getPatients({ ...params, includes: ['person', 'person-Addresses'] }), @@ -55,11 +63,13 @@ provide('isCaptchaValid', isCaptchaValid) const headerPrep: HeaderPrep = { title: "Resume", icon: 'i-lucide-newspaper', - addNav: { - label: "Resume", - onClick: () => navigateTo('/resume/add'), - }, -} + } + if (pagePermission.canCreate) { + headerPrep.addNav = { + label: "Resume", + onClick: () => navigateTo('/resume/add'), + } + } // #endregion // #region Lifecycle Hooks @@ -146,17 +156,25 @@ provide('table_data_loader', isLoading) // #region Watchers watch([recId, recAction], () => { - switch (recAction.value) { - case ActionEvents.showVerify: - isVerifyDialogOpen.value = true - break - case ActionEvents.showValidate: - isRecordConfirmationOpen.value = true - break - case ActionEvents.showPrint: - isDocPreviewDialogOpen.value = true - break - } + switch (recAction.value) { + case ActionEvents.showVerify: + if(pagePermission.canUpdate) { + isVerifyDialogOpen.value = true + } else { + unauthorizedToast() + } + break + case ActionEvents.showValidate: + if(pagePermission.canUpdate) { + isRecordConfirmationOpen.value = true + } else { + unauthorizedToast() + } + break + case ActionEvents.showPrint: + isDocPreviewDialogOpen.value = true + break + } }) // #endregion diff --git a/app/composables/useRBAC.ts b/app/composables/useRBAC.ts index ced57e3e..fcc28144 100644 --- a/app/composables/useRBAC.ts +++ b/app/composables/useRBAC.ts @@ -1,5 +1,13 @@ import type { Permission, RoleAccess } from '~/models/role' +export interface PageOperationPermission { + canRead: boolean + canCreate: boolean + canUpdate: boolean + canDelete: boolean +} + + /** * Check if user has access to a page */ @@ -36,6 +44,14 @@ export function useRBAC() { const hasUpdateAccess = (roleAccess: RoleAccess) => checkPermission(roleAccess, 'U') const hasDeleteAccess = (roleAccess: RoleAccess) => checkPermission(roleAccess, 'D') + const getPagePermissions = (roleAccess: RoleAccess): PageOperationPermission => ({ + canRead : hasReadAccess(roleAccess), + canCreate: hasCreateAccess(roleAccess), + canUpdate: hasUpdateAccess(roleAccess), + canDelete: hasDeleteAccess(roleAccess), + }) + + return { checkRole, checkPermission, @@ -44,5 +60,7 @@ export function useRBAC() { hasReadAccess, hasUpdateAccess, hasDeleteAccess, + getPagePermissions, + } } diff --git a/app/lib/utils.ts b/app/lib/utils.ts index 357d8700..64248caf 100644 --- a/app/lib/utils.ts +++ b/app/lib/utils.ts @@ -1,6 +1,7 @@ import type { ClassValue } from 'clsx' import { clsx } from 'clsx' import { twMerge } from 'tailwind-merge' +import { toast } from '~/components/pub/ui/toast' export interface SelectOptionType<_T = string> { value: string @@ -104,3 +105,11 @@ export function calculateAge(birthDate: Date | string | null | undefined): strin return `${years} tahun ${months} bulan` } } + +export function unauthorizedToast() { + toast({ + title: 'Unauthorized', + description: 'You are not authorized to perform this action.', + variant: 'destructive', + }) +} \ No newline at end of file