feat(FE-331): implement permission guard in transfer to laying

This commit is contained in:
ValdiANS
2025-12-27 16:05:50 +07:00
parent 507c4005af
commit 500c30c2bc
2 changed files with 180 additions and 148 deletions
@@ -26,6 +26,7 @@ import TextInput from '@/components/input/TextInput';
import CheckboxInput from '@/components/input/CheckboxInput'; import CheckboxInput from '@/components/input/CheckboxInput';
import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper'; import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper';
import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes'; import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
import RequirePermission from '@/components/helper/RequirePermission';
import { TransferToLaying } from '@/types/api/production/transfer-to-laying'; import { TransferToLaying } from '@/types/api/production/transfer-to-laying';
import { TransferToLayingApi } from '@/services/api/production/transfer-to-laying'; import { TransferToLayingApi } from '@/services/api/production/transfer-to-laying';
@@ -56,72 +57,81 @@ const RowOptionsMenu = ({
const showDeleteButton = showEditButton; const showDeleteButton = showEditButton;
// TODO: apply RBAC
const showApproveButton = showEditButton; const showApproveButton = showEditButton;
const showRejectButton = showEditButton; const showRejectButton = showEditButton;
return ( return (
<RowOptionsMenuWrapper type={type}> <RowOptionsMenuWrapper type={type}>
<Button <RequirePermission permissions='lti.production.transfer_to_laying.detail'>
href={`/production/transfer-to-laying/detail/?transferToLayingId=${props.row.original.id}`}
variant='ghost'
color='primary'
className='justify-start text-sm'
>
<Icon icon='mdi:eye-outline' width={16} height={16} />
Detail
</Button>
{showEditButton && (
<Button <Button
href={`/production/transfer-to-laying/detail/edit/?transferToLayingId=${props.row.original.id}`} href={`/production/transfer-to-laying/detail/?transferToLayingId=${props.row.original.id}`}
variant='ghost' variant='ghost'
color='warning' color='primary'
className='justify-start text-sm' className='justify-start text-sm'
> >
<Icon icon='material-symbols:edit-outline' width={16} height={16} /> <Icon icon='mdi:eye-outline' width={16} height={16} />
Edit Detail
</Button> </Button>
</RequirePermission>
{showEditButton && (
<RequirePermission permissions='lti.production.transfer_to_laying.update'>
<Button
href={`/production/transfer-to-laying/detail/edit/?transferToLayingId=${props.row.original.id}`}
variant='ghost'
color='warning'
className='justify-start text-sm'
>
<Icon icon='material-symbols:edit-outline' width={16} height={16} />
Edit
</Button>
</RequirePermission>
)} )}
{/* TODO: apply RBAC */} {/* TODO: apply RBAC */}
{showApproveButton && ( {showApproveButton && (
<Button <RequirePermission permissions='lti.production.transfer_to_laying.approve'>
variant='ghost' <Button
color='success' variant='ghost'
onClick={approveClickHandler} color='success'
className='justify-start text-sm' onClick={approveClickHandler}
> className='justify-start text-sm'
<Icon icon='material-symbols:check' width={24} height={24} /> >
Approve <Icon icon='material-symbols:check' width={24} height={24} />
</Button> Approve
</Button>
</RequirePermission>
)} )}
{showRejectButton && ( {showRejectButton && (
<Button <RequirePermission permissions='lti.production.transfer_to_laying.approve'>
variant='ghost' <Button
color='error' variant='ghost'
onClick={rejectClickHandler} color='error'
className='justify-start text-sm' onClick={rejectClickHandler}
> className='justify-start text-sm'
<Icon icon='material-symbols:close' width={24} height={24} /> >
Reject <Icon icon='material-symbols:close' width={24} height={24} />
</Button> Reject
</Button>
</RequirePermission>
)} )}
{showDeleteButton && ( {showDeleteButton && (
<Button <RequirePermission permissions='lti.production.transfer_to_laying.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>
); );
@@ -502,47 +512,53 @@ const TransferToLayingsTable = () => {
<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 sm:w-fit flex flex-col sm:flex-row self-start gap-2'> <div className='w-full sm:w-fit flex flex-col sm:flex-row self-start gap-2'>
<Button <RequirePermission permissions='lti.production.transfer_to_laying.create'>
href='/production/transfer-to-laying/add' <Button
variant='outline' href='/production/transfer-to-laying/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>
{selectedRowIds.length > 0 && ( {selectedRowIds.length > 0 && (
<> <>
<Button <RequirePermission permissions='lti.production.transfer_to_laying.approve'>
variant='outline' <Button
color='success' variant='outline'
onClick={bulkApproveClickHandler} color='success'
disabled={selectedRowIds.length === 0} onClick={bulkApproveClickHandler}
className='w-full sm:w-fit' disabled={selectedRowIds.length === 0}
> className='w-full sm:w-fit'
<Icon >
icon='material-symbols:check' <Icon
width={24} icon='material-symbols:check'
height={24} width={24}
/> height={24}
Approve />
</Button> Approve
</Button>
</RequirePermission>
<Button <RequirePermission permissions='lti.production.transfer_to_laying.approve'>
variant='outline' <Button
color='error' variant='outline'
onClick={bulkRejectClickHandler} color='error'
disabled={selectedRowIds.length === 0} onClick={bulkRejectClickHandler}
className='w-full sm:w-fit' disabled={selectedRowIds.length === 0}
> className='w-full sm:w-fit'
<Icon >
icon='material-symbols:close' <Icon
width={24} icon='material-symbols:close'
height={24} width={24}
/> height={24}
Reject />
</Button> Reject
</Button>
</RequirePermission>
</> </>
)} )}
</div> </div>
@@ -8,6 +8,7 @@ import useSWR from 'swr';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import Button from '@/components/Button'; import Button from '@/components/Button';
import RequirePermission from '@/components/helper/RequirePermission';
import SelectInput, { import SelectInput, {
OptionType, OptionType,
useSelect, useSelect,
@@ -500,34 +501,37 @@ const TransferToLayingForm = ({
<> <>
{isShowApproveRejectButton && ( {isShowApproveRejectButton && (
<div className='w-full flex flex-row justify-end gap-2'> <div className='w-full flex flex-row justify-end gap-2'>
{/* TODO: apply RBAC */} <RequirePermission permissions='lti.production.transfer_to_laying.approve'>
<Button <Button
variant='outline' variant='outline'
color='success' color='success'
onClick={approveClickHandler} onClick={approveClickHandler}
className='w-full sm:w-fit' className='w-full sm:w-fit'
> >
<Icon <Icon
icon='material-symbols:check' icon='material-symbols:check'
width={24} width={24}
height={24} height={24}
/> />
Approve Approve
</Button> </Button>
</RequirePermission>
<Button <RequirePermission permissions='lti.production.transfer_to_laying.approve'>
variant='outline' <Button
color='error' variant='outline'
onClick={rejectClickHandler} color='error'
className='w-full sm:w-fit' onClick={rejectClickHandler}
> className='w-full sm:w-fit'
<Icon >
icon='material-symbols:close' <Icon
width={24} icon='material-symbols:close'
height={24} width={24}
/> height={24}
Reject />
</Button> Reject
</Button>
</RequirePermission>
</div> </div>
)} )}
</> </>
@@ -788,37 +792,41 @@ const TransferToLayingForm = ({
{type !== 'add' && ( {type !== 'add' && (
<div className='flex flex-row justify-start gap-2'> <div className='flex flex-row justify-start gap-2'>
{isShowDeleteButton && ( {isShowDeleteButton && (
<Button <RequirePermission permissions='lti.production.transfer_to_laying.delete'>
type='button' <Button
color='error' type='button'
onClick={deleteTransferToLayingClickHandler} color='error'
className='px-4' onClick={deleteTransferToLayingClickHandler}
> className='px-4'
<Icon >
icon='material-symbols:delete-outline-rounded' <Icon
width={24} icon='material-symbols:delete-outline-rounded'
height={24} width={24}
className='justify-start text-sm' height={24}
/> className='justify-start text-sm'
Delete />
</Button> Delete
</Button>
</RequirePermission>
)} )}
{type !== 'edit' && isShowEditButton && ( {type !== 'edit' && isShowEditButton && (
<Button <RequirePermission permissions='lti.production.transfer_to_laying.update'>
type='button' <Button
color='warning' type='button'
href={`/production/transfer-to-laying/detail/edit/?transferToLayingId=${initialValues?.id}`} color='warning'
className='px-4' href={`/production/transfer-to-laying/detail/edit/?transferToLayingId=${initialValues?.id}`}
> className='px-4'
<Icon >
icon='material-symbols:edit-outline' <Icon
width={24} icon='material-symbols:edit-outline'
height={24} width={24}
className='justify-start text-sm' height={24}
/> className='justify-start text-sm'
Edit />
</Button> Edit
</Button>
</RequirePermission>
)} )}
</div> </div>
)} )}
@@ -833,15 +841,23 @@ const TransferToLayingForm = ({
Reset Reset
</Button> </Button>
<Button <RequirePermission
type='submit' permissions={
color='primary' type === 'add'
isLoading={formik.isSubmitting} ? 'lti.production.transfer_to_laying.create'
disabled={!formik.isValid || formik.isSubmitting} : 'lti.production.transfer_to_laying.update'
className='px-4' }
> >
Submit <Button
</Button> type='submit'
color='primary'
isLoading={formik.isSubmitting}
disabled={!formik.isValid || formik.isSubmitting}
className='px-4'
>
Submit
</Button>
</RequirePermission>
</div> </div>
)} )}
</div> </div>