mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE-331): implement permission guard in purchase
This commit is contained in:
@@ -15,6 +15,7 @@ import SelectInput, { OptionType } from '@/components/input/SelectInput';
|
|||||||
import RowDropdownOptions from '@/components/table/RowDropdownOptions';
|
import RowDropdownOptions from '@/components/table/RowDropdownOptions';
|
||||||
import RowCollapseOptions from '@/components/table/RowCollapseOptions';
|
import RowCollapseOptions from '@/components/table/RowCollapseOptions';
|
||||||
import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper';
|
import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper';
|
||||||
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
|
|
||||||
import { cn, formatDate } from '@/lib/helper';
|
import { cn, formatDate } from '@/lib/helper';
|
||||||
import { isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
@@ -38,15 +39,17 @@ const RowOptionsMenu = ({
|
|||||||
}: RowOptionsMenuProps) => {
|
}: RowOptionsMenuProps) => {
|
||||||
return (
|
return (
|
||||||
<RowOptionsMenuWrapper type={type}>
|
<RowOptionsMenuWrapper type={type}>
|
||||||
<Button
|
<RequirePermission permissions='lti.purchase.detail'>
|
||||||
href={`/purchase/detail/?purchaseId=${props.row.original.id}`}
|
<Button
|
||||||
variant='ghost'
|
href={`/purchase/detail/?purchaseId=${props.row.original.id}`}
|
||||||
color='primary'
|
variant='ghost'
|
||||||
className='justify-start text-sm'
|
color='primary'
|
||||||
>
|
className='justify-start text-sm'
|
||||||
<Icon icon='mdi:eye-outline' width={16} height={16} />
|
>
|
||||||
Detail
|
<Icon icon='mdi:eye-outline' width={16} height={16} />
|
||||||
</Button>
|
Detail
|
||||||
|
</Button>
|
||||||
|
</RequirePermission>
|
||||||
|
|
||||||
{/*<Button*/}
|
{/*<Button*/}
|
||||||
{/* href={`/purchase/detail/edit/?purchaseId=${props.row.original.id}`}*/}
|
{/* href={`/purchase/detail/edit/?purchaseId=${props.row.original.id}`}*/}
|
||||||
@@ -58,20 +61,22 @@ const RowOptionsMenu = ({
|
|||||||
{/* Edit*/}
|
{/* Edit*/}
|
||||||
{/*</Button>*/}
|
{/*</Button>*/}
|
||||||
|
|
||||||
<Button
|
<RequirePermission permissions='lti.purchase.delete'>
|
||||||
onClick={deleteClickHandler}
|
<Button
|
||||||
variant='ghost'
|
onClick={deleteClickHandler}
|
||||||
color='error'
|
variant='ghost'
|
||||||
className='justify-start text-sm text-error focus-visible:text-error-content hover:text-error-content'
|
color='error'
|
||||||
>
|
className='justify-start text-sm text-error focus-visible:text-error-content hover:text-error-content'
|
||||||
<Icon
|
>
|
||||||
icon='material-symbols:delete-outline-rounded'
|
<Icon
|
||||||
width={16}
|
icon='material-symbols:delete-outline-rounded'
|
||||||
height={16}
|
width={16}
|
||||||
className='justify-start text-sm'
|
height={16}
|
||||||
/>
|
className='justify-start text-sm'
|
||||||
Delete
|
/>
|
||||||
</Button>
|
Delete
|
||||||
|
</Button>
|
||||||
|
</RequirePermission>
|
||||||
</RowOptionsMenuWrapper>
|
</RowOptionsMenuWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -227,15 +232,17 @@ const PurchaseTable = () => {
|
|||||||
<div className='flex flex-col gap-2 mb-4'>
|
<div className='flex flex-col gap-2 mb-4'>
|
||||||
<div className='w-full flex flex-col xl:flex-row justify-between items-end xl:items-center gap-2'>
|
<div className='w-full flex flex-col xl:flex-row justify-between items-end xl:items-center gap-2'>
|
||||||
<div className='w-full flex flex-row gap-2'>
|
<div className='w-full flex flex-row gap-2'>
|
||||||
<Button
|
<RequirePermission permissions='lti.purchase.create'>
|
||||||
href='/purchase/add'
|
<Button
|
||||||
variant='outline'
|
href='/purchase/add'
|
||||||
color='primary'
|
variant='outline'
|
||||||
className='w-full sm:w-fit'
|
color='primary'
|
||||||
>
|
className='w-full sm:w-fit'
|
||||||
<Icon icon='ic:round-plus' width={24} height={24} />
|
>
|
||||||
Tambah
|
<Icon icon='ic:round-plus' width={24} height={24} />
|
||||||
</Button>
|
Tambah
|
||||||
|
</Button>
|
||||||
|
</RequirePermission>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<DebouncedTextInput
|
<DebouncedTextInput
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import {
|
|||||||
} from '@/types/api/purchase/purchase';
|
} from '@/types/api/purchase/purchase';
|
||||||
import { BaseApproval, BaseGroupedApproval } from '@/types/api/api-general';
|
import { BaseApproval, BaseGroupedApproval } from '@/types/api/api-general';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
|
|
||||||
interface PurchaseOrderStaffApprovalFormProps {
|
interface PurchaseOrderStaffApprovalFormProps {
|
||||||
type?: 'add' | 'edit';
|
type?: 'add' | 'edit';
|
||||||
@@ -897,20 +898,25 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
<div className='flex justify-center'>
|
<div className='flex justify-center'>
|
||||||
{canUpdatePurchaseItems &&
|
{canUpdatePurchaseItems &&
|
||||||
canShowDeleteAddButtons && (
|
canShowDeleteAddButtons && (
|
||||||
<Button
|
<RequirePermission permissions='lti.purchase.delete.item'>
|
||||||
type='button'
|
<Button
|
||||||
color='error'
|
type='button'
|
||||||
onClick={() =>
|
color='error'
|
||||||
removePurchaseItem(formItemIndex)
|
className='text-sm w-fit'
|
||||||
}
|
onClick={() =>
|
||||||
title='Hapus item'
|
removePurchaseItem(
|
||||||
>
|
formItemIndex
|
||||||
<Icon
|
)
|
||||||
icon='mdi:trash-can'
|
}
|
||||||
width={16}
|
title='Hapus item'
|
||||||
height={16}
|
>
|
||||||
/>
|
<Icon
|
||||||
</Button>
|
icon='mdi:trash-can'
|
||||||
|
width={16}
|
||||||
|
height={16}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</RequirePermission>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -39,19 +39,22 @@ import { toast } from 'react-hot-toast';
|
|||||||
import { useSearchParams } from 'next/navigation';
|
import { useSearchParams } from 'next/navigation';
|
||||||
import { formatCurrency, formatNumber, formatDate } from '@/lib/helper';
|
import { formatCurrency, formatNumber, formatDate } from '@/lib/helper';
|
||||||
import { PURCHASE_ORDER_APPROVAL_LINE } from '@/config/approval-line';
|
import { PURCHASE_ORDER_APPROVAL_LINE } from '@/config/approval-line';
|
||||||
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
|
|
||||||
const ItemPembelianDropdown = ({ onEdit }: { onEdit: () => void }) => {
|
const ItemPembelianDropdown = ({ onEdit }: { onEdit: () => void }) => {
|
||||||
return (
|
return (
|
||||||
<RowOptionsMenuWrapper type='dropdown'>
|
<RowOptionsMenuWrapper type='dropdown'>
|
||||||
<Button
|
<RequirePermission permissions='lti.purchase.update'>
|
||||||
onClick={onEdit}
|
<Button
|
||||||
variant='ghost'
|
onClick={onEdit}
|
||||||
color='warning'
|
variant='ghost'
|
||||||
className='justify-start text-sm'
|
color='warning'
|
||||||
>
|
className='justify-start text-sm'
|
||||||
<Icon icon='material-symbols:edit-outline' width={16} height={16} />
|
>
|
||||||
Edit
|
<Icon icon='material-symbols:edit-outline' width={16} height={16} />
|
||||||
</Button>
|
Edit
|
||||||
|
</Button>
|
||||||
|
</RequirePermission>
|
||||||
</RowOptionsMenuWrapper>
|
</RowOptionsMenuWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -59,15 +62,17 @@ const ItemPembelianDropdown = ({ onEdit }: { onEdit: () => void }) => {
|
|||||||
const PenerimaanBarangDropdown = ({ onEdit }: { onEdit: () => void }) => {
|
const PenerimaanBarangDropdown = ({ onEdit }: { onEdit: () => void }) => {
|
||||||
return (
|
return (
|
||||||
<RowOptionsMenuWrapper type='dropdown'>
|
<RowOptionsMenuWrapper type='dropdown'>
|
||||||
<Button
|
<RequirePermission permissions='lti.purchase.receive'>
|
||||||
onClick={onEdit}
|
<Button
|
||||||
variant='ghost'
|
onClick={onEdit}
|
||||||
color='warning'
|
variant='ghost'
|
||||||
className='justify-start text-sm'
|
color='warning'
|
||||||
>
|
className='justify-start text-sm'
|
||||||
<Icon icon='material-symbols:edit-outline' width={16} height={16} />
|
>
|
||||||
Edit
|
<Icon icon='material-symbols:edit-outline' width={16} height={16} />
|
||||||
</Button>
|
Edit
|
||||||
|
</Button>
|
||||||
|
</RequirePermission>
|
||||||
</RowOptionsMenuWrapper>
|
</RowOptionsMenuWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -496,14 +501,16 @@ const PurchaseOrderDetail = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<RequirePermission permissions='lti.purchase.delete.item'>
|
||||||
type='button'
|
<Button
|
||||||
color='error'
|
type='button'
|
||||||
className='text-sm'
|
color='error'
|
||||||
onClick={deleteClickHandler}
|
className='text-sm'
|
||||||
>
|
onClick={deleteClickHandler}
|
||||||
<Icon icon='mdi:trash-can' width={16} height={16} />
|
>
|
||||||
</Button>
|
<Icon icon='mdi:trash-can' width={16} height={16} />
|
||||||
|
</Button>
|
||||||
|
</RequirePermission>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -632,25 +639,45 @@ const PurchaseOrderDetail = ({
|
|||||||
|
|
||||||
{showApprovalButton && (
|
{showApprovalButton && (
|
||||||
<div className='flex flex-row gap-2'>
|
<div className='flex flex-row gap-2'>
|
||||||
<Button
|
<RequirePermission
|
||||||
onClick={handleApprovalClick}
|
permissions={
|
||||||
variant='outline'
|
approvalStep === 1
|
||||||
color='success'
|
? 'lti.purchase.approve.staff'
|
||||||
className='w-full sm:w-fit'
|
: approvalStep === 2
|
||||||
|
? 'lti.purchase.approve.manager'
|
||||||
|
: 'lti.purchase.receive'
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<Icon icon='material-symbols:check' width={24} height={24} />
|
<Button
|
||||||
Approve
|
onClick={handleApprovalClick}
|
||||||
</Button>
|
variant='outline'
|
||||||
|
color='success'
|
||||||
|
className='w-full sm:w-fit'
|
||||||
|
>
|
||||||
|
<Icon icon='material-symbols:check' width={24} height={24} />
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
</RequirePermission>
|
||||||
|
|
||||||
<Button
|
<RequirePermission
|
||||||
variant='outline'
|
permissions={
|
||||||
color='error'
|
approvalStep === 1
|
||||||
className='w-full sm:w-fit'
|
? 'lti.purchase.approve.staff'
|
||||||
onClick={handleRejectionClick}
|
: approvalStep === 2
|
||||||
|
? 'lti.purchase.approve.manager'
|
||||||
|
: 'lti.purchase.receive'
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<Icon icon='material-symbols:close' width={24} height={24} />
|
<Button
|
||||||
Reject
|
variant='outline'
|
||||||
</Button>
|
color='error'
|
||||||
|
className='w-full sm:w-fit'
|
||||||
|
onClick={handleRejectionClick}
|
||||||
|
>
|
||||||
|
<Icon icon='material-symbols:close' width={24} height={24} />
|
||||||
|
Reject
|
||||||
|
</Button>
|
||||||
|
</RequirePermission>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user