mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 15:25:46 +00:00
feat(FE-149): integrate TransferToLayingsTable to API
This commit is contained in:
@@ -2,7 +2,12 @@
|
|||||||
|
|
||||||
import { ChangeEventHandler, useState } from 'react';
|
import { ChangeEventHandler, useState } from 'react';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table';
|
import {
|
||||||
|
CellContext,
|
||||||
|
ColumnDef,
|
||||||
|
Row,
|
||||||
|
SortingState,
|
||||||
|
} from '@tanstack/react-table';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
|
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
@@ -20,6 +25,7 @@ import RowCollapseOptions from '@/components/table/RowCollapseOptions';
|
|||||||
import TextInput from '@/components/input/TextInput';
|
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 { 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';
|
||||||
@@ -29,6 +35,7 @@ import { useTableFilter } from '@/services/hooks/useTableFilter';
|
|||||||
import { ROWS_OPTIONS } from '@/config/constant';
|
import { ROWS_OPTIONS } from '@/config/constant';
|
||||||
import { Flock } from '@/types/api/master-data/flock';
|
import { Flock } from '@/types/api/master-data/flock';
|
||||||
import { FlockApi } from '@/services/api/master-data';
|
import { FlockApi } from '@/services/api/master-data';
|
||||||
|
import PillBadge from '@/components/PillBadge';
|
||||||
|
|
||||||
const RowOptionsMenu = ({
|
const RowOptionsMenu = ({
|
||||||
type = 'dropdown',
|
type = 'dropdown',
|
||||||
@@ -43,6 +50,16 @@ const RowOptionsMenu = ({
|
|||||||
rejectClickHandler: () => void;
|
rejectClickHandler: () => void;
|
||||||
deleteClickHandler: () => void;
|
deleteClickHandler: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
|
const showEditButton =
|
||||||
|
props.row.original.approval.action !== 'APPROVED' &&
|
||||||
|
props.row.original.approval.action !== 'REJECTED';
|
||||||
|
|
||||||
|
const showDeleteButton = showEditButton;
|
||||||
|
|
||||||
|
// TODO: apply RBAC
|
||||||
|
const showApproveButton = showEditButton;
|
||||||
|
const showRejectButton = showEditButton;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RowOptionsMenuWrapper type={type}>
|
<RowOptionsMenuWrapper type={type}>
|
||||||
<Button
|
<Button
|
||||||
@@ -55,50 +72,57 @@ const RowOptionsMenu = ({
|
|||||||
Detail
|
Detail
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
{showEditButton && (
|
||||||
href={`/production/transfer-to-laying/detail/edit/?transferToLayingId=${props.row.original.id}`}
|
<Button
|
||||||
variant='ghost'
|
href={`/production/transfer-to-laying/detail/edit/?transferToLayingId=${props.row.original.id}`}
|
||||||
color='warning'
|
variant='ghost'
|
||||||
className='justify-start text-sm'
|
color='warning'
|
||||||
>
|
|
||||||
<Icon icon='material-symbols:edit-outline' width={16} height={16} />
|
|
||||||
Edit
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
variant='ghost'
|
|
||||||
color='success'
|
|
||||||
onClick={approveClickHandler}
|
|
||||||
className='justify-start text-sm'
|
|
||||||
>
|
|
||||||
<Icon icon='material-symbols:check' width={24} height={24} />
|
|
||||||
Approve
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
variant='ghost'
|
|
||||||
color='error'
|
|
||||||
onClick={rejectClickHandler}
|
|
||||||
className='justify-start text-sm'
|
|
||||||
>
|
|
||||||
<Icon icon='material-symbols:close' width={24} height={24} />
|
|
||||||
Reject
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
onClick={deleteClickHandler}
|
|
||||||
variant='ghost'
|
|
||||||
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'
|
|
||||||
width={16}
|
|
||||||
height={16}
|
|
||||||
className='justify-start text-sm'
|
className='justify-start text-sm'
|
||||||
/>
|
>
|
||||||
Delete
|
<Icon icon='material-symbols:edit-outline' width={16} height={16} />
|
||||||
</Button>
|
Edit
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* TODO: apply RBAC */}
|
||||||
|
{showApproveButton && (
|
||||||
|
<Button
|
||||||
|
variant='ghost'
|
||||||
|
color='success'
|
||||||
|
onClick={approveClickHandler}
|
||||||
|
className='justify-start text-sm'
|
||||||
|
>
|
||||||
|
<Icon icon='material-symbols:check' width={24} height={24} />
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{showRejectButton && (
|
||||||
|
<Button
|
||||||
|
variant='ghost'
|
||||||
|
color='error'
|
||||||
|
onClick={rejectClickHandler}
|
||||||
|
className='justify-start text-sm'
|
||||||
|
>
|
||||||
|
<Icon icon='material-symbols:close' width={24} height={24} />
|
||||||
|
Reject
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{showDeleteButton && (
|
||||||
|
<Button
|
||||||
|
onClick={deleteClickHandler}
|
||||||
|
variant='ghost'
|
||||||
|
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'
|
||||||
|
width={16}
|
||||||
|
height={16}
|
||||||
|
className='justify-start text-sm'
|
||||||
|
/>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</RowOptionsMenuWrapper>
|
</RowOptionsMenuWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -187,17 +211,24 @@ const TransferToLayingsTable = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => {
|
||||||
<div>
|
const isCheckboxDisabled =
|
||||||
<CheckboxInput
|
!row.getCanSelect() ||
|
||||||
name='row'
|
row.original.approval.action === 'APPROVED' ||
|
||||||
checked={row.getIsSelected()}
|
row.original.approval.action === 'REJECTED';
|
||||||
disabled={!row.getCanSelect()}
|
|
||||||
indeterminate={row.getIsSomeSelected()}
|
return (
|
||||||
onChange={row.getToggleSelectedHandler()}
|
<div>
|
||||||
/>
|
<CheckboxInput
|
||||||
</div>
|
name='row'
|
||||||
),
|
checked={row.getIsSelected()}
|
||||||
|
disabled={isCheckboxDisabled}
|
||||||
|
indeterminate={row.getIsSomeSelected()}
|
||||||
|
onChange={row.getToggleSelectedHandler()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: '#',
|
header: '#',
|
||||||
@@ -214,21 +245,55 @@ const TransferToLayingsTable = () => {
|
|||||||
{
|
{
|
||||||
accessorKey: 'flock_source',
|
accessorKey: 'flock_source',
|
||||||
header: 'Flock Asal',
|
header: 'Flock Asal',
|
||||||
cell: (props) => props.row.original.flock_source.name,
|
cell: (props) => props.row.original.from_project_flock.flock_name,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: 'flock_destination',
|
accessorKey: 'flock_destination',
|
||||||
header: 'Flock Tujuan',
|
header: 'Flock Tujuan',
|
||||||
cell: (props) => props.row.original.flock_destination.name,
|
cell: (props) => props.row.original.to_project_flock.flock_name,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: 'quantity',
|
accessorKey: 'usage_qty',
|
||||||
header: 'Kuantitas',
|
header: 'Kuantitas',
|
||||||
|
cell: (props) => props.getValue() ?? props.row.original.pending_usage_qty,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: 'reason',
|
accessorKey: 'notes',
|
||||||
header: 'Alasan Transfer',
|
header: 'Alasan Transfer',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
header: 'Status',
|
||||||
|
cell: (props) => {
|
||||||
|
const isLatestApprovalRejected =
|
||||||
|
props.row.original.approval.action === 'REJECTED';
|
||||||
|
let latestApprovalStepName = props.row.original.approval.step_name;
|
||||||
|
|
||||||
|
let pillBadgeColor: 'yellow' | 'green' | 'gray' | 'red' = 'gray';
|
||||||
|
|
||||||
|
switch (latestApprovalStepName.toLowerCase()) {
|
||||||
|
case 'pengajuan':
|
||||||
|
pillBadgeColor = 'yellow';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'disetujui':
|
||||||
|
pillBadgeColor = 'green';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLatestApprovalRejected) {
|
||||||
|
pillBadgeColor = 'red';
|
||||||
|
latestApprovalStepName = 'Ditolak';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PillBadge
|
||||||
|
content={latestApprovalStepName}
|
||||||
|
color={pillBadgeColor}
|
||||||
|
className='text-sm'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
header: 'Aksi',
|
header: 'Aksi',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
@@ -237,7 +302,7 @@ const TransferToLayingsTable = () => {
|
|||||||
const currentRowRelativeIndex =
|
const currentRowRelativeIndex =
|
||||||
currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
|
currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
|
||||||
|
|
||||||
const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
|
const isLast2Rows = currentRowRelativeIndex > currentPageSize - 3;
|
||||||
|
|
||||||
const approveClickHandler = () => {
|
const approveClickHandler = () => {
|
||||||
setSelectedTransferToLaying(props.row.original);
|
setSelectedTransferToLaying(props.row.original);
|
||||||
@@ -268,7 +333,7 @@ const TransferToLayingsTable = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{currentPageSize > 2 && (
|
{currentPageSize > 3 && (
|
||||||
<RowDropdownOptions isLast2Rows={isLast2Rows}>
|
<RowDropdownOptions isLast2Rows={isLast2Rows}>
|
||||||
<RowOptionsMenu
|
<RowOptionsMenu
|
||||||
type='dropdown'
|
type='dropdown'
|
||||||
@@ -280,7 +345,7 @@ const TransferToLayingsTable = () => {
|
|||||||
</RowDropdownOptions>
|
</RowDropdownOptions>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{currentPageSize <= 2 && (
|
{currentPageSize <= 3 && (
|
||||||
<RowCollapseOptions>
|
<RowCollapseOptions>
|
||||||
<RowOptionsMenu
|
<RowOptionsMenu
|
||||||
type='collapse'
|
type='collapse'
|
||||||
@@ -297,6 +362,15 @@ const TransferToLayingsTable = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const tableEnableRowSelectionHandler: (
|
||||||
|
row: Row<TransferToLaying>
|
||||||
|
) => boolean = (row) => {
|
||||||
|
return (
|
||||||
|
row.original.approval.action !== 'APPROVED' &&
|
||||||
|
row.original.approval.action !== 'REJECTED'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const bulkApproveClickHandler = () => {
|
const bulkApproveClickHandler = () => {
|
||||||
approveModal.openModal();
|
approveModal.openModal();
|
||||||
};
|
};
|
||||||
@@ -309,27 +383,31 @@ const TransferToLayingsTable = () => {
|
|||||||
const confirmationModalDeleteClickHandler = async () => {
|
const confirmationModalDeleteClickHandler = async () => {
|
||||||
setIsDeleteLoading(true);
|
setIsDeleteLoading(true);
|
||||||
|
|
||||||
await TransferToLayingApi.delete(selectedTransferToLaying?.id as number);
|
try {
|
||||||
refreshTransferToLayings();
|
await TransferToLayingApi.delete(selectedTransferToLaying?.id as number);
|
||||||
|
|
||||||
deleteModal.closeModal();
|
toast.success('Berhasil menghapus data transfer ke laying!');
|
||||||
toast.success('Berhasil menghapus data transfer ke laying!');
|
refreshTransferToLayings();
|
||||||
setIsDeleteLoading(false);
|
} catch (error) {
|
||||||
|
toast.success('Gagal menghapus data transfer ke laying!');
|
||||||
|
} finally {
|
||||||
|
deleteModal.closeModal();
|
||||||
|
setIsDeleteLoading(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const confirmationModalApproveClickHandler = async () => {
|
const confirmationModalApproveClickHandler = async (notes: string) => {
|
||||||
setIsApproveLoading(true);
|
setIsApproveLoading(true);
|
||||||
|
|
||||||
const bulkApproveResponse =
|
const bulkApproveResponse = await TransferToLayingApi.bulkApprove(
|
||||||
await TransferToLayingApi.bulkApprove(selectedRowIds);
|
selectedRowIds,
|
||||||
|
notes
|
||||||
|
);
|
||||||
|
|
||||||
if (isResponseSuccess(bulkApproveResponse)) {
|
if (isResponseSuccess(bulkApproveResponse)) {
|
||||||
refreshTransferToLayings();
|
refreshTransferToLayings();
|
||||||
approveModal.closeModal();
|
approveModal.closeModal();
|
||||||
|
|
||||||
// TODO: remove console.log
|
|
||||||
console.log('Approved data:', selectedRowIds);
|
|
||||||
|
|
||||||
toast.success(
|
toast.success(
|
||||||
`Berhasil approve ${selectedRowIds.length} data transfer ke laying!`
|
`Berhasil approve ${selectedRowIds.length} data transfer ke laying!`
|
||||||
);
|
);
|
||||||
@@ -346,19 +424,18 @@ const TransferToLayingsTable = () => {
|
|||||||
setIsApproveLoading(false);
|
setIsApproveLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const confirmationModalRejectClickHandler = async () => {
|
const confirmationModalRejectClickHandler = async (notes: string) => {
|
||||||
setIsRejectLoading(true);
|
setIsRejectLoading(true);
|
||||||
|
|
||||||
const bulkRejectResponse =
|
const bulkRejectResponse = await TransferToLayingApi.bulkReject(
|
||||||
await TransferToLayingApi.bulkReject(selectedRowIds);
|
selectedRowIds,
|
||||||
|
notes
|
||||||
|
);
|
||||||
|
|
||||||
if (isResponseSuccess(bulkRejectResponse)) {
|
if (isResponseSuccess(bulkRejectResponse)) {
|
||||||
refreshTransferToLayings();
|
refreshTransferToLayings();
|
||||||
rejectModal.closeModal();
|
rejectModal.closeModal();
|
||||||
|
|
||||||
// TODO: remove console.log
|
|
||||||
console.log('Rejected data:', selectedRowIds);
|
|
||||||
|
|
||||||
toast.success(
|
toast.success(
|
||||||
`Berhasil reject ${selectedRowIds.length} data transfer ke laying!`
|
`Berhasil reject ${selectedRowIds.length} data transfer ke laying!`
|
||||||
);
|
);
|
||||||
@@ -559,6 +636,7 @@ const TransferToLayingsTable = () => {
|
|||||||
setSorting={setSorting}
|
setSorting={setSorting}
|
||||||
rowSelection={rowSelection}
|
rowSelection={rowSelection}
|
||||||
setRowSelection={setRowSelection}
|
setRowSelection={setRowSelection}
|
||||||
|
enableRowSelection={tableEnableRowSelectionHandler}
|
||||||
className={{
|
className={{
|
||||||
containerClassName: cn({
|
containerClassName: cn({
|
||||||
'mb-20':
|
'mb-20':
|
||||||
@@ -592,7 +670,7 @@ const TransferToLayingsTable = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ConfirmationModal
|
<ConfirmationModalWithNotes
|
||||||
ref={approveModal.ref}
|
ref={approveModal.ref}
|
||||||
type='success'
|
type='success'
|
||||||
text={`Apakah anda yakin ingin approve data transfer ke laying ini (${selectedRowIds.length} data)?`}
|
text={`Apakah anda yakin ingin approve data transfer ke laying ini (${selectedRowIds.length} data)?`}
|
||||||
@@ -607,7 +685,7 @@ const TransferToLayingsTable = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ConfirmationModal
|
<ConfirmationModalWithNotes
|
||||||
ref={rejectModal.ref}
|
ref={rejectModal.ref}
|
||||||
type='error'
|
type='error'
|
||||||
text={`Apakah anda yakin ingin reject data transfer ke laying ini (${selectedRowIds.length} data)?`}
|
text={`Apakah anda yakin ingin reject data transfer ke laying ini (${selectedRowIds.length} data)?`}
|
||||||
|
|||||||
Reference in New Issue
Block a user