mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
833 lines
26 KiB
TypeScript
833 lines
26 KiB
TypeScript
'use client';
|
||
|
||
import { ChangeEventHandler, useEffect, useMemo, useState } from 'react';
|
||
import { usePathname } from 'next/navigation';
|
||
import { useUiStore } from '@/stores/ui/ui.store';
|
||
import useSWR from 'swr';
|
||
import {
|
||
CellContext,
|
||
ColumnDef,
|
||
Row,
|
||
SortingState,
|
||
} from '@tanstack/react-table';
|
||
import toast from 'react-hot-toast';
|
||
|
||
import { Icon } from '@iconify/react';
|
||
import Table from '@/components/Table';
|
||
import Button from '@/components/Button';
|
||
import { useModal } from '@/components/Modal';
|
||
import CheckboxInput from '@/components/input/CheckboxInput';
|
||
import RequirePermission from '@/components/helper/RequirePermission';
|
||
import PopoverButton from '@/components/popover/PopoverButton';
|
||
import PopoverContent from '@/components/popover/PopoverContent';
|
||
import Dropdown from '@/components/Dropdown';
|
||
import StatusBadge from '@/components/helper/StatusBadge';
|
||
import TransferToLayingFilterModal from '@/components/pages/production/transfer-to-laying/TransferToLayingFilterModal';
|
||
import TransferToLayingConfirmationModal from '@/components/pages/production/transfer-to-laying/TransferToLayingConfirmationModal';
|
||
import TransferToLayingTableSkeleton from '@/components/pages/production/transfer-to-laying/skeleton/TransferToLayingTableSkeleton';
|
||
|
||
import { TransferToLaying } from '@/types/api/production/transfer-to-laying';
|
||
import { TransferToLayingFilterValues } from '@/components/pages/production/transfer-to-laying/filter/TransferToLayingFilter';
|
||
import { OptionType } from '@/components/input/SelectInput';
|
||
import { TransferToLayingApi } from '@/services/api/production/transfer-to-laying';
|
||
import { cn, formatDate, formatNumber } from '@/lib/helper';
|
||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
||
import { Color } from '@/types/theme';
|
||
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
|
||
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||
|
||
const RowOptionsMenu = ({
|
||
props,
|
||
popoverPosition = 'bottom',
|
||
|
||
deleteClickHandler,
|
||
}: {
|
||
props: CellContext<TransferToLaying, unknown>;
|
||
popoverPosition: 'bottom' | 'top';
|
||
deleteClickHandler: () => void;
|
||
}) => {
|
||
const showEditButton = props.row.original.approval.action !== 'APPROVED';
|
||
|
||
const showDeleteButton =
|
||
props.row.original.approval.action === 'APPROVED' ||
|
||
props.row.original.approval.step_name.toLowerCase() === 'pengajuan';
|
||
|
||
const popoverId = `transferToLaying#${props.row.original.id}`;
|
||
const popoverAnchorName = `--anchor-transferToLaying#${props.row.original.id}`;
|
||
|
||
return (
|
||
<div className='relative'>
|
||
<PopoverButton
|
||
tabIndex={0}
|
||
variant='ghost'
|
||
color='none'
|
||
popoverTarget={popoverId}
|
||
anchorName={popoverAnchorName}
|
||
>
|
||
<Icon icon='material-symbols:more-vert' width={16} height={16} />
|
||
</PopoverButton>
|
||
|
||
<PopoverContent
|
||
id={popoverId}
|
||
anchorName={popoverAnchorName}
|
||
position={popoverPosition === 'bottom' ? 'bottom-start' : 'left'}
|
||
className='w-full max-w-40 rounded-xl border border-base-content/5 shadow-sm'
|
||
>
|
||
<div className='flex flex-col bg-base-100 rounded-xl'>
|
||
<RequirePermission permissions='lti.production.transfer_to_laying.detail'>
|
||
<Button
|
||
href={`/production/transfer-to-laying/?action=detail&id=${props.row.original.id}`}
|
||
variant='ghost'
|
||
color='none'
|
||
className='p-3 justify-start text-sm font-semibold w-full'
|
||
>
|
||
<Icon icon='heroicons:eye' width={20} height={20} />
|
||
View Details
|
||
</Button>
|
||
</RequirePermission>
|
||
|
||
{showEditButton && (
|
||
<RequirePermission permissions='lti.production.transfer_to_laying.update'>
|
||
<Button
|
||
href={`/production/transfer-to-laying/?action=edit&id=${props.row.original.id}`}
|
||
variant='ghost'
|
||
color='none'
|
||
className='p-3 justify-start text-sm font-semibold w-full'
|
||
>
|
||
<Icon icon='heroicons:pencil-square' width={20} height={20} />
|
||
Edit
|
||
</Button>
|
||
</RequirePermission>
|
||
)}
|
||
|
||
{showDeleteButton && (
|
||
<RequirePermission permissions='lti.production.transfer_to_laying.delete'>
|
||
<hr className='mx-3 border-base-content/10 h-px' />
|
||
<Button
|
||
onClick={deleteClickHandler}
|
||
variant='ghost'
|
||
color='error'
|
||
className='p-3 justify-start text-sm font-semibold w-full'
|
||
>
|
||
<Icon icon='heroicons:trash' width={20} height={20} />
|
||
Delete
|
||
</Button>
|
||
</RequirePermission>
|
||
)}
|
||
</div>
|
||
</PopoverContent>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
const TransferToLayingsTable = () => {
|
||
const { searchValue, setSearchValue, setTableState } = useUiStore();
|
||
const pathname = usePathname();
|
||
|
||
const {
|
||
state: tableFilterState,
|
||
updateFilter,
|
||
setPage,
|
||
setPageSize,
|
||
toQueryString: getTableFilterQueryString,
|
||
} = useTableFilter({
|
||
initial: {
|
||
search: '',
|
||
startDate: '',
|
||
endDate: '',
|
||
flockSource: '',
|
||
flockDestination: '',
|
||
status: '',
|
||
filter_by: '',
|
||
sort_by: '',
|
||
flockSourceNames: '',
|
||
flockDestinationNames: '',
|
||
},
|
||
paramMap: {
|
||
page: 'page',
|
||
pageSize: 'limit',
|
||
startDate: 'start_date',
|
||
endDate: 'end_date',
|
||
flockSource: 'flock_source',
|
||
flockDestination: 'flock_destination',
|
||
status: 'status',
|
||
filter_by: 'filter_by',
|
||
sort_by: 'sort_by',
|
||
},
|
||
excludeKeysFromUrl: ['flockSourceNames', 'flockDestinationNames'],
|
||
persist: true,
|
||
storeName: 'transfer-to-laying-table',
|
||
});
|
||
|
||
const {
|
||
data: transferToLayings,
|
||
isLoading,
|
||
mutate: refreshTransferToLayings,
|
||
} = useSWR(
|
||
`${TransferToLayingApi.basePath}${getTableFilterQueryString()}`,
|
||
TransferToLayingApi.getAllFetcher
|
||
);
|
||
|
||
const [isLoadingExportingToExcel, setIsLoadingExportingToExcel] =
|
||
useState(false);
|
||
|
||
// Modal hooks
|
||
const filterModal = useModal();
|
||
const deleteModal = useModal();
|
||
const approveModal = useModal();
|
||
const rejectModal = useModal();
|
||
|
||
const [selectedTransferToLaying, setSelectedTransferToLaying] = useState<
|
||
TransferToLaying | undefined
|
||
>(undefined);
|
||
|
||
// Modal loading state
|
||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||
const [isApproveLoading, setIsApproveLoading] = useState(false);
|
||
const [isRejectLoading, setIsRejectLoading] = useState(false);
|
||
|
||
const [sorting, setSorting] = useState<SortingState>([]);
|
||
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
||
const selectedRowIds = Object.keys(rowSelection).map((item) =>
|
||
parseInt(item)
|
||
);
|
||
|
||
const transferToLayingsColumns: ColumnDef<TransferToLaying>[] = [
|
||
{
|
||
id: 'select',
|
||
header: ({ table }) => (
|
||
<div className='w-full flex flex-row justify-center'>
|
||
<CheckboxInput
|
||
name='allRow'
|
||
checked={table.getIsAllRowsSelected()}
|
||
indeterminate={table.getIsSomeRowsSelected()}
|
||
onChange={table.getToggleAllRowsSelectedHandler()}
|
||
/>
|
||
</div>
|
||
),
|
||
cell: ({ row }) => {
|
||
const isCheckboxDisabled =
|
||
!row.getCanSelect() ||
|
||
row.original.approval.action === 'APPROVED' ||
|
||
row.original.approval.action === 'REJECTED';
|
||
|
||
return (
|
||
<div>
|
||
<CheckboxInput
|
||
name='row'
|
||
checked={row.getIsSelected()}
|
||
disabled={isCheckboxDisabled}
|
||
indeterminate={row.getIsSomeSelected()}
|
||
onChange={row.getToggleSelectedHandler()}
|
||
/>
|
||
</div>
|
||
);
|
||
},
|
||
},
|
||
{
|
||
accessorKey: 'transfer_date',
|
||
header: 'Tanggal Transfer',
|
||
cell: (props) => formatDate(props.getValue() as string, 'DD MMM YYYY'),
|
||
},
|
||
{
|
||
accessorKey: 'transfer_number',
|
||
header: 'No. Transfer',
|
||
},
|
||
{
|
||
accessorKey: 'flock_source',
|
||
header: 'Flock Asal',
|
||
cell: (props) => props.row.original.from_project_flock.flock_name,
|
||
},
|
||
{
|
||
accessorKey: 'flock_destination',
|
||
header: 'Flock Tujuan',
|
||
cell: (props) => props.row.original.to_project_flock.flock_name,
|
||
},
|
||
{
|
||
accessorKey: 'usage_qty',
|
||
header: 'Kuantitas',
|
||
cell: (props) => {
|
||
const totalQuantity = props.row.original.targets.reduce(
|
||
(total, target) => total + target.qty,
|
||
0
|
||
);
|
||
|
||
return formatNumber(totalQuantity, 'en-US');
|
||
},
|
||
},
|
||
{
|
||
accessorKey: 'notes',
|
||
header: 'Alasan Transfer',
|
||
enableSorting: false,
|
||
cell: (props) => {
|
||
return (
|
||
<span title={props.row.original.notes} className='line-clamp-1'>
|
||
{props.row.original.notes}
|
||
</span>
|
||
);
|
||
},
|
||
},
|
||
{
|
||
header: 'Status',
|
||
cell: (props) => {
|
||
const isLatestApprovalRejected =
|
||
props.row.original.approval.action === 'REJECTED';
|
||
let latestApprovalStepName = props.row.original.approval.step_name;
|
||
|
||
let badgeColor: Color = 'neutral';
|
||
|
||
switch (latestApprovalStepName.toLowerCase()) {
|
||
case 'pengajuan':
|
||
badgeColor = 'neutral';
|
||
break;
|
||
|
||
case 'disetujui':
|
||
badgeColor = 'success';
|
||
break;
|
||
}
|
||
|
||
if (isLatestApprovalRejected) {
|
||
badgeColor = 'error';
|
||
latestApprovalStepName = 'Ditolak';
|
||
}
|
||
|
||
return <StatusBadge color={badgeColor} text={latestApprovalStepName} />;
|
||
},
|
||
},
|
||
{
|
||
id: 'actions',
|
||
cell: (props) => {
|
||
const currentPageSize = props.table.getPaginationRowModel().rows.length;
|
||
const currentPageRows = props.table.getPaginationRowModel().flatRows;
|
||
const currentRowRelativeIndex =
|
||
currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
|
||
|
||
const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
|
||
|
||
const deleteClickHandler = () => {
|
||
setSelectedTransferToLaying(props.row.original);
|
||
|
||
// Set row selection
|
||
setRowSelection({
|
||
[String(props.row.original.id)]: true,
|
||
});
|
||
|
||
deleteModal.openModal();
|
||
};
|
||
|
||
return (
|
||
<RowOptionsMenu
|
||
props={props}
|
||
deleteClickHandler={deleteClickHandler}
|
||
popoverPosition={isLast2Rows ? 'top' : 'bottom'}
|
||
/>
|
||
);
|
||
},
|
||
},
|
||
];
|
||
|
||
const tableEnableRowSelectionHandler: (
|
||
row: Row<TransferToLaying>
|
||
) => boolean = (row) => {
|
||
return (
|
||
row.original.approval.action !== 'APPROVED' &&
|
||
row.original.approval.action !== 'REJECTED'
|
||
);
|
||
};
|
||
|
||
const bulkApproveClickHandler = () => {
|
||
approveModal.openModal();
|
||
};
|
||
|
||
const bulkRejectClickHandler = () => {
|
||
rejectModal.openModal();
|
||
};
|
||
|
||
// Modal confirm click handler
|
||
const confirmationModalDeleteClickHandler = async () => {
|
||
setIsDeleteLoading(true);
|
||
|
||
const deleteResponse = await TransferToLayingApi.delete(
|
||
selectedTransferToLaying?.id as number
|
||
);
|
||
|
||
if (isResponseError(deleteResponse)) {
|
||
toast.error(deleteResponse.message);
|
||
setIsDeleteLoading(false);
|
||
return;
|
||
}
|
||
|
||
refreshTransferToLayings();
|
||
|
||
setRowSelection({});
|
||
setSelectedTransferToLaying(undefined);
|
||
deleteModal.closeModal();
|
||
toast.success('Berhasil menghapus data transfer ke laying!');
|
||
setIsDeleteLoading(false);
|
||
};
|
||
|
||
const confirmationModalApproveClickHandler = async (notes: string) => {
|
||
setIsApproveLoading(true);
|
||
|
||
const bulkApproveResponse = await TransferToLayingApi.bulkApprove(
|
||
selectedRowIds,
|
||
notes
|
||
);
|
||
|
||
if (isResponseSuccess(bulkApproveResponse)) {
|
||
refreshTransferToLayings();
|
||
approveModal.closeModal();
|
||
|
||
toast.success(
|
||
`Berhasil approve ${selectedRowIds.length} data transfer ke laying!`
|
||
);
|
||
|
||
setRowSelection({});
|
||
} else {
|
||
approveModal.closeModal();
|
||
|
||
toast.error(
|
||
`Gagal approve ${selectedRowIds.length} data transfer ke laying!`
|
||
);
|
||
}
|
||
|
||
setIsApproveLoading(false);
|
||
};
|
||
|
||
const confirmationModalRejectClickHandler = async (notes: string) => {
|
||
setIsRejectLoading(true);
|
||
|
||
const bulkRejectResponse = await TransferToLayingApi.bulkReject(
|
||
selectedRowIds,
|
||
notes
|
||
);
|
||
|
||
if (isResponseSuccess(bulkRejectResponse)) {
|
||
refreshTransferToLayings();
|
||
rejectModal.closeModal();
|
||
|
||
toast.success(
|
||
`Berhasil reject ${selectedRowIds.length} data transfer ke laying!`
|
||
);
|
||
setRowSelection({});
|
||
} else {
|
||
rejectModal.closeModal();
|
||
|
||
toast.error(
|
||
`Gagal reject ${selectedRowIds.length} data transfer ke laying!`
|
||
);
|
||
}
|
||
|
||
setIsRejectLoading(false);
|
||
};
|
||
|
||
useEffect(() => {
|
||
updateFilter('search', searchValue);
|
||
}, [searchValue, updateFilter]);
|
||
|
||
useEffect(() => {
|
||
setTableState('transfer-to-laying-table', pathname);
|
||
}, [pathname, setTableState]);
|
||
|
||
const searchChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||
setSearchValue(e.target.value);
|
||
updateFilter('search', e.target.value);
|
||
};
|
||
|
||
const STATUS_FILTER_OPTIONS = [
|
||
{ value: 'PENDING', label: 'Pengajuan' },
|
||
{ value: 'APPROVED', label: 'Disetujui' },
|
||
{ value: 'REJECTED', label: 'Ditolak' },
|
||
];
|
||
|
||
const filterModalInitialValues = useMemo(() => {
|
||
const flockSourceIds = tableFilterState.flockSource
|
||
? tableFilterState.flockSource.split(',')
|
||
: [];
|
||
const flockSourceNameList = tableFilterState.flockSourceNames
|
||
? tableFilterState.flockSourceNames.split(',')
|
||
: [];
|
||
const flockSourceOptions = flockSourceIds.filter(Boolean).map((id, i) => ({
|
||
value: parseInt(id),
|
||
label: flockSourceNameList[i] || id,
|
||
}));
|
||
|
||
const flockDestIds = tableFilterState.flockDestination
|
||
? tableFilterState.flockDestination.split(',')
|
||
: [];
|
||
const flockDestNameList = tableFilterState.flockDestinationNames
|
||
? tableFilterState.flockDestinationNames.split(',')
|
||
: [];
|
||
const flockDestOptions = flockDestIds.filter(Boolean).map((id, i) => ({
|
||
value: parseInt(id),
|
||
label: flockDestNameList[i] || id,
|
||
}));
|
||
|
||
const statusIds = tableFilterState.status
|
||
? tableFilterState.status.split(',')
|
||
: [];
|
||
const statusOptions = statusIds.filter(Boolean).map((id) => {
|
||
const found = STATUS_FILTER_OPTIONS.find((opt) => opt.value === id);
|
||
return found || { value: id, label: id };
|
||
});
|
||
|
||
return {
|
||
startDate: tableFilterState.startDate || '',
|
||
endDate: tableFilterState.endDate || '',
|
||
flockSource: flockSourceOptions,
|
||
flockDestination: flockDestOptions,
|
||
status: statusOptions,
|
||
};
|
||
}, [
|
||
tableFilterState.startDate,
|
||
tableFilterState.endDate,
|
||
tableFilterState.flockSource,
|
||
tableFilterState.flockDestination,
|
||
tableFilterState.status,
|
||
tableFilterState.flockSourceNames,
|
||
tableFilterState.flockDestinationNames,
|
||
]);
|
||
|
||
const filterSubmitHandler = (values: TransferToLayingFilterValues) => {
|
||
const flockSourceOpts = (values.flockSource as OptionType[]) || [];
|
||
const flockDestOpts = (values.flockDestination as OptionType[]) || [];
|
||
const statusOpts = (values.status as OptionType[]) || [];
|
||
|
||
updateFilter('startDate', values.startDate || '');
|
||
updateFilter('endDate', values.endDate || '');
|
||
updateFilter(
|
||
'flockSource',
|
||
flockSourceOpts.map((o) => String(o.value)).join(',')
|
||
);
|
||
updateFilter(
|
||
'flockDestination',
|
||
flockDestOpts.map((o) => String(o.value)).join(',')
|
||
);
|
||
updateFilter('status', statusOpts.map((o) => String(o.value)).join(','));
|
||
updateFilter(
|
||
'flockSourceNames',
|
||
flockSourceOpts.map((o) => String(o.label)).join(',')
|
||
);
|
||
updateFilter(
|
||
'flockDestinationNames',
|
||
flockDestOpts.map((o) => String(o.label)).join(',')
|
||
);
|
||
};
|
||
|
||
const filterResetHandler = () => {
|
||
updateFilter('startDate', '');
|
||
updateFilter('endDate', '');
|
||
updateFilter('flockSource', '');
|
||
updateFilter('flockDestination', '');
|
||
updateFilter('status', '');
|
||
updateFilter('flockSourceNames', '');
|
||
updateFilter('flockDestinationNames', '');
|
||
};
|
||
|
||
const exportToExcelHandler = async () => {
|
||
setIsLoadingExportingToExcel(true);
|
||
|
||
await TransferToLayingApi.exportToExcel(getTableFilterQueryString());
|
||
|
||
setIsLoadingExportingToExcel(false);
|
||
};
|
||
|
||
useEffect(() => {
|
||
if (sorting.length === 1) {
|
||
updateFilter('filter_by', sorting[0].id);
|
||
updateFilter('sort_by', sorting[0].desc ? 'desc' : 'asc');
|
||
} else {
|
||
updateFilter('filter_by', '');
|
||
updateFilter('sort_by', '');
|
||
}
|
||
}, [sorting]);
|
||
|
||
return (
|
||
<>
|
||
<div className='@container w-full'>
|
||
<div className='w-full p-3 flex flex-row justify-between gap-3 flex-wrap border-b border-base-content/10'>
|
||
<div className='w-fit flex flex-row gap-3 flex-wrap'>
|
||
<RequirePermission permissions='lti.production.transfer_to_laying.create'>
|
||
<Button
|
||
href={{
|
||
pathname: '/production/transfer-to-laying',
|
||
query: {
|
||
action: 'add',
|
||
},
|
||
}}
|
||
color='primary'
|
||
className='px-3 py-2.5 w-fit text-sm text-base-100 rounded-lg shadow-sm'
|
||
>
|
||
<Icon icon='heroicons:plus' width={20} height={20} />
|
||
Add Transfer to Laying
|
||
</Button>
|
||
</RequirePermission>
|
||
|
||
{selectedRowIds.length > 0 && (
|
||
<>
|
||
<hr className='w-px h-full border-none bg-base-content/10 hidden @sm:block' />
|
||
|
||
<RequirePermission permissions='lti.production.transfer_to_laying.approve'>
|
||
<Button
|
||
variant='outline'
|
||
color='none'
|
||
onClick={bulkRejectClickHandler}
|
||
disabled={selectedRowIds.length === 0}
|
||
className='px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft'
|
||
>
|
||
<Icon
|
||
icon='heroicons:x-mark'
|
||
width={20}
|
||
height={20}
|
||
className='text-error'
|
||
/>
|
||
Reject
|
||
</Button>
|
||
</RequirePermission>
|
||
|
||
<RequirePermission permissions='lti.production.transfer_to_laying.approve'>
|
||
<Button
|
||
variant='outline'
|
||
color='none'
|
||
onClick={bulkApproveClickHandler}
|
||
disabled={selectedRowIds.length === 0}
|
||
className='px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft'
|
||
>
|
||
<Icon
|
||
icon='heroicons:check'
|
||
width={20}
|
||
height={20}
|
||
className='text-success'
|
||
/>
|
||
Approve
|
||
</Button>
|
||
</RequirePermission>
|
||
</>
|
||
)}
|
||
</div>
|
||
|
||
<div className='flex flex-1 flex-row justify-start sm:justify-end items-center gap-3 flex-wrap'>
|
||
<DebouncedTextInput
|
||
name='search'
|
||
placeholder='Search'
|
||
value={tableFilterState.search ?? ''}
|
||
onChange={searchChangeHandler}
|
||
startAdornment={
|
||
<Icon
|
||
icon='heroicons:magnifying-glass'
|
||
width={20}
|
||
height={20}
|
||
/>
|
||
}
|
||
className={{
|
||
wrapper: 'w-full min-w-24 max-w-3xs',
|
||
inputWrapper: 'rounded-xl! shadow-button-soft',
|
||
input:
|
||
'placeholder:font-semibold placeholder:text-base-content/50',
|
||
}}
|
||
/>
|
||
|
||
<ButtonFilter
|
||
values={tableFilterState}
|
||
excludeFields={[
|
||
'page',
|
||
'pageSize',
|
||
'search',
|
||
'filter_by',
|
||
'sort_by',
|
||
'flockSourceNames',
|
||
'flockDestinationNames',
|
||
]}
|
||
fieldGroups={[['startDate', 'endDate']]}
|
||
onClick={filterModal.openModal}
|
||
className='px-3 py-2.5'
|
||
/>
|
||
|
||
<Dropdown
|
||
align='end'
|
||
direction='bottom'
|
||
className={{
|
||
content:
|
||
'mt-1 rounded-xl border border-base-content/5 shadow-sm overflow-hidden',
|
||
}}
|
||
trigger={
|
||
<Button
|
||
variant='outline'
|
||
color='none'
|
||
className='px-3 py-2.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft'
|
||
>
|
||
<div className='flex flex-row items-center gap-1.5'>
|
||
<Icon
|
||
icon='heroicons:cloud-arrow-down'
|
||
width={20}
|
||
height={20}
|
||
/>
|
||
|
||
<span>Export</span>
|
||
|
||
<div className='w-px self-stretch bg-base-content/10' />
|
||
|
||
<Icon
|
||
icon='heroicons:chevron-down'
|
||
width={14}
|
||
height={14}
|
||
/>
|
||
</div>
|
||
</Button>
|
||
}
|
||
>
|
||
<Button
|
||
variant='ghost'
|
||
color='none'
|
||
onClick={exportToExcelHandler}
|
||
isLoading={isLoadingExportingToExcel}
|
||
className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
|
||
>
|
||
<Icon icon='heroicons:table-cells' width={20} height={20} />
|
||
Export to Excel
|
||
</Button>
|
||
</Dropdown>
|
||
</div>
|
||
</div>
|
||
|
||
<div className='flex flex-col mb-4'>
|
||
{isLoading ? (
|
||
<div className='w-full flex flex-row justify-center items-center p-4'>
|
||
<span className='loading loading-spinner loading-xl' />
|
||
</div>
|
||
) : !isResponseSuccess(transferToLayings) ||
|
||
transferToLayings.data?.length === 0 ? (
|
||
<div className='p-3'>
|
||
<TransferToLayingTableSkeleton
|
||
columns={transferToLayingsColumns}
|
||
icon={
|
||
<Icon
|
||
icon='heroicons:document-text'
|
||
className='text-white'
|
||
width={20}
|
||
height={20}
|
||
/>
|
||
}
|
||
/>
|
||
</div>
|
||
) : (
|
||
<Table<TransferToLaying>
|
||
data={
|
||
isResponseSuccess(transferToLayings)
|
||
? transferToLayings?.data
|
||
: []
|
||
}
|
||
columns={transferToLayingsColumns}
|
||
pageSize={tableFilterState.pageSize}
|
||
page={
|
||
isResponseSuccess(transferToLayings)
|
||
? transferToLayings?.meta?.page
|
||
: 0
|
||
}
|
||
totalItems={
|
||
isResponseSuccess(transferToLayings)
|
||
? transferToLayings?.meta?.total_results
|
||
: 0
|
||
}
|
||
onPageChange={setPage}
|
||
onPageSizeChange={setPageSize}
|
||
isLoading={isLoading}
|
||
sorting={sorting}
|
||
setSorting={setSorting}
|
||
rowSelection={rowSelection}
|
||
setRowSelection={setRowSelection}
|
||
enableRowSelection={tableEnableRowSelectionHandler}
|
||
withCheckbox
|
||
className={{
|
||
containerClassName: cn('p-3 mb-0'),
|
||
headerColumnClassName: 'text-nowrap',
|
||
}}
|
||
/>
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
<TransferToLayingFilterModal
|
||
ref={filterModal.ref}
|
||
initialValues={filterModalInitialValues}
|
||
onSubmit={filterSubmitHandler}
|
||
onReset={filterResetHandler}
|
||
/>
|
||
|
||
<TransferToLayingConfirmationModal
|
||
ref={deleteModal.ref}
|
||
type='error'
|
||
text='Delete This Data?'
|
||
subtitleText='Are you sure you want to delete this data? '
|
||
transferToLayingIds={selectedRowIds}
|
||
primaryButton={{
|
||
text: 'Delete',
|
||
isLoading: isDeleteLoading,
|
||
color: 'error',
|
||
onClick: confirmationModalDeleteClickHandler,
|
||
}}
|
||
secondaryButton={{
|
||
text: 'Cancel',
|
||
color: 'none',
|
||
onClick: () => {
|
||
setRowSelection({});
|
||
deleteModal.closeModal();
|
||
},
|
||
}}
|
||
/>
|
||
|
||
{/* Approve Modal */}
|
||
<TransferToLayingConfirmationModal
|
||
ref={approveModal.ref}
|
||
text='Approve This Submission?'
|
||
subtitleText='Are you sure you want to approve this submission?'
|
||
type='success'
|
||
transferToLayingIds={selectedRowIds}
|
||
withNote
|
||
noteLabel='Notes Approval'
|
||
primaryButton={{
|
||
text: 'Approve',
|
||
isLoading: isApproveLoading,
|
||
onClick: confirmationModalApproveClickHandler,
|
||
}}
|
||
secondaryButton={{
|
||
text: 'Cancel',
|
||
color: 'none',
|
||
onClick: () => {
|
||
setRowSelection({});
|
||
approveModal.closeModal();
|
||
},
|
||
}}
|
||
/>
|
||
|
||
{/* Reject Modal */}
|
||
<TransferToLayingConfirmationModal
|
||
ref={rejectModal.ref}
|
||
type='error'
|
||
text='Reject This Submission?'
|
||
subtitleText='Are you sure you want to reject this submission?'
|
||
transferToLayingIds={selectedRowIds}
|
||
withNote
|
||
noteLabel='Notes Reject'
|
||
secondaryButton={{
|
||
text: 'Cancel',
|
||
color: 'none',
|
||
onClick: () => {
|
||
setRowSelection({});
|
||
rejectModal.closeModal();
|
||
},
|
||
}}
|
||
primaryButton={{
|
||
text: 'Reject',
|
||
isLoading: isRejectLoading,
|
||
color: 'error',
|
||
onClick: confirmationModalRejectClickHandler,
|
||
}}
|
||
/>
|
||
</>
|
||
);
|
||
};
|
||
|
||
export default TransferToLayingsTable;
|