fix(FE): remove bypass permission and integrate table filter

This commit is contained in:
randy-ar
2026-01-02 10:04:56 +07:00
parent 046fb74cab
commit d6b8b10183
2 changed files with 141 additions and 146 deletions
+130 -108
View File
@@ -2,7 +2,10 @@
import Button from '@/components/Button';
import CheckboxInput from '@/components/input/CheckboxInput';
import SelectInput, { OptionType } from '@/components/input/SelectInput';
import SelectInput, {
OptionType,
useSelect,
} from '@/components/input/SelectInput';
import Modal, { useModal } from '@/components/Modal';
import ConfirmationModal from '@/components/modal/ConfirmationModal';
import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
@@ -28,6 +31,8 @@ import toast from 'react-hot-toast';
import useSWR from 'swr';
import RequirePermission from '@/components/helper/RequirePermission';
import { useAuth } from '@/services/hooks/useAuth';
import { CustomerApi, ProductApi } from '@/services/api/master-data';
import { MARKETING_APPROVAL_LINE } from '@/config/approval-line';
const RowsOptionsMenu = ({
type = 'dropdown',
@@ -52,7 +57,7 @@ const RowsOptionsMenu = ({
)}
>
<div className='flex flex-col gap-1'>
{/* <RequirePermission permissions='lti.marketing.delivery_order.detail'>
<RequirePermission permissions='lti.marketing.delivery_order.detail'>
<Button
href={`/marketing/detail?marketingId=${props.row.original.id}`}
variant='ghost'
@@ -62,19 +67,10 @@ const RowsOptionsMenu = ({
<Icon icon='mdi:eye-outline' width={16} height={16} />
Detail
</Button>
</RequirePermission> */}
<Button
href={`/marketing/detail?marketingId=${props.row.original.id}`}
variant='ghost'
color='primary'
className='justify-start text-sm'
>
<Icon icon='mdi:eye-outline' width={16} height={16} />
Detail
</Button>
</RequirePermission>
{props.row.original.latest_approval.step_number != 1 && (
<>
{/* <RequirePermission
<RequirePermission
permissions={
props.row.original.latest_approval.step_number == 3
? 'lti.marketing.delivery_order.update'
@@ -101,32 +97,12 @@ const RowsOptionsMenu = ({
<Icon icon='mdi:truck' width={16} height={16} />
Deliver
</Button>
</RequirePermission> */}
<Button
href={
props.row.original.latest_approval.step_number == 3
? `/marketing/detail/delivery-orders/edit?marketingId=${props.row.original.id}`
: props.row.original.latest_approval.step_number == 2
? `/marketing/add/delivery-orders?marketingId=${props.row.original.id}`
: undefined
}
onClick={() => {
if (props.row.original.latest_approval.step_number == 2) {
deliveryClickHandler?.();
}
}}
variant='ghost'
color='success'
className='justify-start text-sm'
>
<Icon icon='mdi:truck' width={16} height={16} />
Deliver
</Button>
</RequirePermission>
</>
)}
{props.row.original.latest_approval.step_number != 3 && (
<>
{/* <RequirePermission permissions='lti.marketing.sales_order.update'>
<RequirePermission permissions='lti.marketing.sales_order.update'>
<Button
href={`/marketing/detail/sales-orders/edit?marketingId=${props.row.original.id}`}
variant='ghost'
@@ -136,19 +112,10 @@ const RowsOptionsMenu = ({
<Icon icon='mdi:pencil-outline' width={16} height={16} />
Edit
</Button>
</RequirePermission> */}
<Button
href={`/marketing/detail/sales-orders/edit?marketingId=${props.row.original.id}`}
variant='ghost'
color='warning'
className='justify-start text-sm'
>
<Icon icon='mdi:pencil-outline' width={16} height={16} />
Edit
</Button>
</RequirePermission>
</>
)}
{/* <RequirePermission permissions='lti.marketing.sales_order.delete'>
<RequirePermission permissions='lti.marketing.sales_order.delete'>
<Button
onClick={deleteClickHandler}
variant='ghost'
@@ -158,16 +125,7 @@ const RowsOptionsMenu = ({
<Icon icon='mdi:delete-outline' width={16} height={16} />
Delete
</Button>
</RequirePermission> */}
<Button
onClick={deleteClickHandler}
variant='ghost'
color='error'
className='text-error hover:text-inherit justify-start text-sm'
>
<Icon icon='mdi:delete-outline' width={16} height={16} />
Delete
</Button>
</RequirePermission>
</div>
</div>
);
@@ -175,8 +133,6 @@ const RowsOptionsMenu = ({
const MarketingTable = () => {
const [search, setSearch] = useState('');
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [approveAction, setApproveAction] = useState<'APPROVED' | 'REJECTED'>(
'APPROVED'
@@ -186,18 +142,64 @@ const MarketingTable = () => {
const { permissionCheck } = useAuth();
const router = useRouter();
const {
data: marketing,
isLoading: isLoadingMarketing,
mutate: refreshMarketing,
} = useSWR(MarketingApi.basePath, MarketingApi.getAllFetcher);
const deleteModal = useModal();
const confirmationModal = useModal();
const productsModal = useModal();
const deliveryModal = useModal();
const {
state: tableFilterState,
updateFilter,
setPage,
setPageSize,
toQueryString: getTableFilterToQueryString,
} = useTableFilter({
initial: {
search: '',
product_ids: '',
status: '',
customer_id: '',
page: 1,
limit: 10,
},
paramMap: {
page: 'page',
pageSize: 'limit',
product_ids: 'product_ids',
status: 'status',
customer_id: 'customer_id',
},
});
// ===== FETCH DATA =====
const {
data: marketing,
isLoading: isLoadingMarketing,
mutate: refreshMarketing,
} = useSWR(
`${MarketingApi.basePath}${getTableFilterToQueryString()}`,
MarketingApi.getAllFetcher
);
// ===== OPTIONS =====
const {
options: productsOptions,
isLoadingOptions: isLoadingProductsOptions,
} = useSelect(ProductApi.basePath, 'id', 'name', '', {
limit: 'limit',
});
const {
options: customersOptions,
isLoadingOptions: isLoadingCustomersOptions,
} = useSelect(CustomerApi.basePath, 'id', 'name', '', {
limit: 'limit',
});
const statusOptions = MARKETING_APPROVAL_LINE.map((item) => ({
value: item.step_number,
label: item.step_name,
}));
// ===== HANDLER =====
const searchChangeHandler = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value);
@@ -209,7 +211,8 @@ const MarketingTable = () => {
(val: OptionType | OptionType[] | null) => {
const newVal = val as OptionType;
setPageSize(newVal.value as number);
setPage(1);
updateFilter('page', 1);
updateFilter('limit', newVal.value as number);
},
[]
);
@@ -314,20 +317,6 @@ const MarketingTable = () => {
);
};
const {
state: tableFilterState,
updateFilter,
toQueryString: getTableFilterToQueryString,
} = useTableFilter({
initial: {
search: '',
},
paramMap: {
page: 'page',
pageSize: 'limit',
},
});
const getRowCanSelect = (row: Row<Marketing>): boolean => {
const approval = row.original.latest_approval;
return approval?.step_number === 1 && approval?.action !== 'REJECTED';
@@ -353,7 +342,7 @@ const MarketingTable = () => {
}}
/>
<div className='flex flex-row gap-2'>
{/* <RequirePermission permissions='lti.marketing.sales_order.approve'>
<RequirePermission permissions='lti.marketing.sales_order.approve'>
<Button
color='success'
onClick={approveClickHandler}
@@ -363,18 +352,9 @@ const MarketingTable = () => {
<Icon icon='material-symbols:check' width={24} height={24} />
Approve
</Button>
</RequirePermission> */}
<Button
color='success'
onClick={approveClickHandler}
className='justify-start text-sm'
disabled={disableApprove}
>
<Icon icon='material-symbols:check' width={24} height={24} />
Approve
</Button>
</RequirePermission>
{/* <RequirePermission permissions='lti.marketing.sales_order.approve'>
<RequirePermission permissions='lti.marketing.sales_order.approve'>
<Button
color='error'
onClick={rejectClickHandler}
@@ -384,19 +364,10 @@ const MarketingTable = () => {
<Icon icon='material-symbols:close' width={24} height={24} />
Reject
</Button>
</RequirePermission> */}
<Button
color='error'
onClick={rejectClickHandler}
className='justify-start text-sm'
disabled={disableReject}
>
<Icon icon='material-symbols:close' width={24} height={24} />
Reject
</Button>
</RequirePermission>
</div>
<TableRowSizeSelector
value={pageSize}
value={tableFilterState.pageSize}
onChange={pageSizeChangeHandler}
options={ROWS_OPTIONS}
className='flex sm:flex-row flex-col gap-3 items-end justify-end'
@@ -406,7 +377,29 @@ const MarketingTable = () => {
label='Product'
isClearable
placeholder='Pilih product'
options={[]}
options={productsOptions}
isLoading={isLoadingProductsOptions}
value={
tableFilterState.product_ids
?.split(',')
.map((id) =>
productsOptions.find(
(option) => option.value === Number(id)
)
)
.filter(
(option): option is { value: number; label: string } =>
option !== undefined
) ?? null
}
onChange={(value: OptionType | OptionType[] | null) =>
updateFilter(
'product_ids',
(value as OptionType[])
?.map((item: OptionType) => item.value.toString())
.join(',') || ''
)
}
isMulti
/>
{/* select status */}
@@ -414,14 +407,43 @@ const MarketingTable = () => {
label='Status'
isClearable
placeholder='Pilih status'
options={[]}
options={statusOptions}
value={
tableFilterState.status
? statusOptions.find(
(option) =>
option.value === Number(tableFilterState.status)
)
: null
}
onChange={(value: OptionType | OptionType[] | null) =>
updateFilter(
'status',
(value as OptionType)?.value.toString() || ''
)
}
/>
{/* select customer */}
<SelectInput
label='Customer'
isClearable
placeholder='Pilih customer'
options={[]}
options={customersOptions}
isLoading={isLoadingCustomersOptions}
value={
tableFilterState.customer_id
? customersOptions.find(
(option) =>
option.value === Number(tableFilterState.customer_id)
)
: null
}
onChange={(value: OptionType | OptionType[] | null) =>
updateFilter(
'customer_id',
(value as OptionType)?.value.toString() || ''
)
}
/>
</TableRowSizeSelector>
</div>
@@ -587,8 +609,8 @@ const MarketingTable = () => {
},
},
]}
pageSize={pageSize}
page={page}
pageSize={tableFilterState.pageSize}
page={tableFilterState.page}
onPageChange={setPage}
className={{
tableWrapperClassName: 'overflow-x-auto min-h-full!',
+11 -38
View File
@@ -3,7 +3,6 @@ export const ROUTE_PERMISSIONS: Record<string, string[]> = {
// Dashboard
'/dashboard/': ['lti.dashboard.list'],
'/dashboard': ['lti.dashboard.list'],
// Production
// Production - Project Flock
@@ -58,27 +57,14 @@ export const ROUTE_PERMISSIONS: Record<string, string[]> = {
'/purchase/detail/edit/': ['lti.purchase.update'],
// Marketing
'/marketing/': ['lti.dashboard.list', 'lti.marketing.delivery_order.list'],
'/marketing/add/delivery-orders/': [
'lti.dashboard.list',
'lti.marketing.delivery_order.create',
],
'/marketing/add/sales-orders/': [
'lti.dashboard.list',
'lti.marketing.sales_order.create',
],
'/marketing/detail/': [
'lti.dashboard.list',
'lti.marketing.delivery_order.detail',
],
'/marketing/': ['lti.marketing.delivery_order.list'],
'/marketing/add/delivery-orders/': ['lti.marketing.delivery_order.create'],
'/marketing/add/sales-orders/': ['lti.marketing.sales_order.create'],
'/marketing/detail/': ['lti.marketing.delivery_order.detail'],
'/marketing/detail/delivery-orders/edit/': [
'lti.dashboard.list',
'lti.marketing.delivery_order.update',
],
'/marketing/detail/sales-orders/edit/': [
'lti.dashboard.list',
'lti.marketing.sales_order.update',
],
'/marketing/detail/sales-orders/edit/': ['lti.marketing.sales_order.update'],
// Expense
'/expense/': ['lti.expense.list'],
@@ -89,19 +75,12 @@ export const ROUTE_PERMISSIONS: Record<string, string[]> = {
'/expense/realization/edit/': ['lti.expense.update.realization'],
// Finance
'/finance/': ['lti.dashboard.list', 'lti.finance.transaction.list'],
'/finance/detail/': ['lti.dashboard.list', 'lti.finance.transaction.detail'],
'/finance/add/': ['lti.dashboard.list', 'lti.finance.payments.create'],
'/finance/detail/edit/': [
'lti.dashboard.list',
'lti.finance.payments.update',
],
'/finance/add/initial-balance/': [
'lti.dashboard.list',
'lti.finance.initial_balances.create',
],
'/finance/': ['lti.finance.transaction.list'],
'/finance/detail/': ['lti.finance.transaction.detail'],
'/finance/add/': ['lti.finance.payments.create'],
'/finance/detail/edit/': ['lti.finance.payments.update'],
'/finance/add/initial-balance/': ['lti.finance.initial_balances.create'],
'/finance/detail/edit/initial-balance/': [
'lti.dashboard.list',
'lti.finance.initial_balances.update',
],
'/finance/add/injection/': ['lti.finance.injections.create'],
@@ -203,20 +182,14 @@ export const ROUTE_PERMISSIONS: Record<string, string[]> = {
'/master-data/flock/detail/': ['lti.master.flocks.detail'],
'/master-data/flock/detail/edit/': ['lti.master.flocks.update'],
'/master-data/production-standard/': [
'lti.dashboard.list',
'lti.master.production_standards.list',
],
'/master-data/production-standard/': ['lti.master.production_standards.list'],
'/master-data/production-standard/add/': [
'lti.dashboard.list',
'lti.master.production_standards.create',
],
'/master-data/production-standard/detail/': [
'lti.dashboard.list',
'lti.master.production_standards.detail',
],
'/master-data/production-standard/detail/edit/': [
'lti.dashboard.list',
'lti.master.production_standards.update',
],
};