mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 15:25:46 +00:00
chore: adjust TransferToLayingsTable styling
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { ChangeEventHandler, useState } from 'react';
|
import { ChangeEventHandler, useEffect, useState } from 'react';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import {
|
import {
|
||||||
CellContext,
|
CellContext,
|
||||||
@@ -20,33 +20,32 @@ import SelectInput, {
|
|||||||
OptionType,
|
OptionType,
|
||||||
useSelect,
|
useSelect,
|
||||||
} from '@/components/input/SelectInput';
|
} from '@/components/input/SelectInput';
|
||||||
import RowDropdownOptions from '@/components/table/RowDropdownOptions';
|
|
||||||
import RowCollapseOptions from '@/components/table/RowCollapseOptions';
|
|
||||||
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 ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
|
import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
|
import DateInput from '@/components/input/DateInput';
|
||||||
|
import PopoverButton from '@/components/popover/PopoverButton';
|
||||||
|
|
||||||
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';
|
||||||
import { cn, formatDate } from '@/lib/helper';
|
import { cn, formatDate } from '@/lib/helper';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
||||||
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 { ProjectFlockApi } from '@/services/api/production';
|
||||||
import PillBadge from '@/components/PillBadge';
|
import Badge from '@/components/Badge';
|
||||||
|
import { Color } from '@/types/theme';
|
||||||
|
import PopoverContent from '@/components/popover/PopoverContent';
|
||||||
|
|
||||||
const RowOptionsMenu = ({
|
const RowOptionsMenu = ({
|
||||||
type = 'dropdown',
|
|
||||||
props,
|
props,
|
||||||
|
popoverPosition = 'bottom',
|
||||||
approveClickHandler,
|
approveClickHandler,
|
||||||
rejectClickHandler,
|
rejectClickHandler,
|
||||||
deleteClickHandler,
|
deleteClickHandler,
|
||||||
}: {
|
}: {
|
||||||
type: 'dropdown' | 'collapse';
|
|
||||||
props: CellContext<TransferToLaying, unknown>;
|
props: CellContext<TransferToLaying, unknown>;
|
||||||
|
popoverPosition: 'bottom' | 'top';
|
||||||
approveClickHandler: () => void;
|
approveClickHandler: () => void;
|
||||||
rejectClickHandler: () => void;
|
rejectClickHandler: () => void;
|
||||||
deleteClickHandler: () => void;
|
deleteClickHandler: () => void;
|
||||||
@@ -60,80 +59,99 @@ const RowOptionsMenu = ({
|
|||||||
const showApproveButton = showEditButton;
|
const showApproveButton = showEditButton;
|
||||||
const showRejectButton = showEditButton;
|
const showRejectButton = showEditButton;
|
||||||
|
|
||||||
|
const popoverId = `transferToLaying#${props.row.original.id}`;
|
||||||
|
const popoverAnchorName = `--anchor-transferToLaying#${props.row.original.id}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RowOptionsMenuWrapper type={type}>
|
<div className='relative'>
|
||||||
<RequirePermission permissions='lti.production.transfer_to_laying.detail'>
|
<PopoverButton
|
||||||
<Button
|
tabIndex={0}
|
||||||
href={`/production/transfer-to-laying/detail/?transferToLayingId=${props.row.original.id}`}
|
variant='ghost'
|
||||||
variant='ghost'
|
color='none'
|
||||||
color='primary'
|
popoverTarget={popoverId}
|
||||||
className='justify-start text-sm'
|
anchorName={popoverAnchorName}
|
||||||
>
|
>
|
||||||
<Icon icon='mdi:eye-outline' width={16} height={16} />
|
<Icon icon='material-symbols:more-vert' width={16} height={16} />
|
||||||
Detail
|
</PopoverButton>
|
||||||
</Button>
|
|
||||||
</RequirePermission>
|
|
||||||
|
|
||||||
{showEditButton && (
|
<PopoverContent
|
||||||
<RequirePermission permissions='lti.production.transfer_to_laying.update'>
|
id={popoverId}
|
||||||
<Button
|
anchorName={popoverAnchorName}
|
||||||
href={`/production/transfer-to-laying/detail/edit/?transferToLayingId=${props.row.original.id}`}
|
position={popoverPosition === 'bottom' ? 'bottom-start' : 'left'}
|
||||||
variant='ghost'
|
className='rounded-xl border border-base-content/5 shadow-sm'
|
||||||
color='warning'
|
>
|
||||||
className='justify-start text-sm'
|
<div className='flex flex-col bg-base-100 rounded-xl'>
|
||||||
>
|
<RequirePermission permissions='lti.production.transfer_to_laying.detail'>
|
||||||
<Icon icon='material-symbols:edit-outline' width={16} height={16} />
|
<Button
|
||||||
Edit
|
href={`/production/transfer-to-laying/detail/?transferToLayingId=${props.row.original.id}`}
|
||||||
</Button>
|
variant='ghost'
|
||||||
</RequirePermission>
|
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>
|
||||||
|
|
||||||
{/* TODO: apply RBAC */}
|
{showEditButton && (
|
||||||
{showApproveButton && (
|
<RequirePermission permissions='lti.production.transfer_to_laying.update'>
|
||||||
<RequirePermission permissions='lti.production.transfer_to_laying.approve'>
|
<Button
|
||||||
<Button
|
href={`/production/transfer-to-laying/detail/edit/?transferToLayingId=${props.row.original.id}`}
|
||||||
variant='ghost'
|
variant='ghost'
|
||||||
color='success'
|
color='none'
|
||||||
onClick={approveClickHandler}
|
className='p-3 justify-start text-sm font-semibold w-full'
|
||||||
className='justify-start text-sm'
|
>
|
||||||
>
|
<Icon icon='heroicons:pencil-square' width={20} height={20} />
|
||||||
<Icon icon='material-symbols:check' width={24} height={24} />
|
Edit
|
||||||
Approve
|
</Button>
|
||||||
</Button>
|
</RequirePermission>
|
||||||
</RequirePermission>
|
)}
|
||||||
)}
|
|
||||||
{showRejectButton && (
|
{showApproveButton && (
|
||||||
<RequirePermission permissions='lti.production.transfer_to_laying.approve'>
|
<RequirePermission permissions='lti.production.transfer_to_laying.approve'>
|
||||||
<Button
|
<Button
|
||||||
variant='ghost'
|
variant='ghost'
|
||||||
color='error'
|
color='success'
|
||||||
onClick={rejectClickHandler}
|
onClick={approveClickHandler}
|
||||||
className='justify-start text-sm'
|
className='p-3 justify-start text-sm font-semibold w-full'
|
||||||
>
|
>
|
||||||
<Icon icon='material-symbols:close' width={24} height={24} />
|
<Icon icon='heroicons:check' width={20} height={20} />
|
||||||
Reject
|
Approve
|
||||||
</Button>
|
</Button>
|
||||||
</RequirePermission>
|
</RequirePermission>
|
||||||
)}
|
)}
|
||||||
{showDeleteButton && (
|
|
||||||
<RequirePermission permissions='lti.production.transfer_to_laying.delete'>
|
{showRejectButton && (
|
||||||
<Button
|
<RequirePermission permissions='lti.production.transfer_to_laying.approve'>
|
||||||
onClick={deleteClickHandler}
|
<Button
|
||||||
variant='ghost'
|
variant='ghost'
|
||||||
color='error'
|
color='error'
|
||||||
className='justify-start text-sm text-error focus-visible:text-error-content hover:text-error-content'
|
onClick={rejectClickHandler}
|
||||||
>
|
className='p-3 justify-start text-sm font-semibold w-full'
|
||||||
<Icon
|
>
|
||||||
icon='material-symbols:delete-outline-rounded'
|
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
||||||
width={16}
|
Reject
|
||||||
height={16}
|
</Button>
|
||||||
className='justify-start text-sm'
|
</RequirePermission>
|
||||||
/>
|
)}
|
||||||
Delete
|
|
||||||
</Button>
|
{showDeleteButton && (
|
||||||
</RequirePermission>
|
<RequirePermission permissions='lti.production.transfer_to_laying.delete'>
|
||||||
)}
|
<hr className='mx-3 border-base-content/10 h-px' />
|
||||||
</RowOptionsMenuWrapper>
|
<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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -150,6 +168,8 @@ const TransferToLayingsTable = () => {
|
|||||||
transferDate: '',
|
transferDate: '',
|
||||||
flockSource: '',
|
flockSource: '',
|
||||||
flockDestination: '',
|
flockDestination: '',
|
||||||
|
filter_by: '',
|
||||||
|
sort_by: '',
|
||||||
},
|
},
|
||||||
paramMap: {
|
paramMap: {
|
||||||
page: 'page',
|
page: 'page',
|
||||||
@@ -157,6 +177,8 @@ const TransferToLayingsTable = () => {
|
|||||||
transferDate: 'transfer_date',
|
transferDate: 'transfer_date',
|
||||||
flockSource: 'flock_source',
|
flockSource: 'flock_source',
|
||||||
flockDestination: 'flock_destination',
|
flockDestination: 'flock_destination',
|
||||||
|
filter_by: 'filter_by',
|
||||||
|
sort_by: 'sort_by',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -181,7 +203,7 @@ const TransferToLayingsTable = () => {
|
|||||||
isLoadingOptions: isLoadingFlockSourceOptions,
|
isLoadingOptions: isLoadingFlockSourceOptions,
|
||||||
loadMore: loadMoreFlockSource,
|
loadMore: loadMoreFlockSource,
|
||||||
hasMore: hasMoreFlockSource,
|
hasMore: hasMoreFlockSource,
|
||||||
} = useSelect<Flock>(FlockApi.basePath, 'id', 'name');
|
} = useSelect<Flock>(ProjectFlockApi.basePath, 'id', 'flock_name');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
setInputValue: setFlockDestinationInputValue,
|
setInputValue: setFlockDestinationInputValue,
|
||||||
@@ -189,7 +211,7 @@ const TransferToLayingsTable = () => {
|
|||||||
isLoadingOptions: isLoadingFlockDestinationOptions,
|
isLoadingOptions: isLoadingFlockDestinationOptions,
|
||||||
loadMore: loadMoreFlockDestination,
|
loadMore: loadMoreFlockDestination,
|
||||||
hasMore: hasMoreFlockDestination,
|
hasMore: hasMoreFlockDestination,
|
||||||
} = useSelect<Flock>(FlockApi.basePath, 'id', 'name');
|
} = useSelect<Flock>(ProjectFlockApi.basePath, 'id', 'flock_name');
|
||||||
|
|
||||||
// Flocks value
|
// Flocks value
|
||||||
const [selectedFlockSource, setSelectedFlockSource] =
|
const [selectedFlockSource, setSelectedFlockSource] =
|
||||||
@@ -244,13 +266,6 @@ const TransferToLayingsTable = () => {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
header: '#',
|
|
||||||
cell: (props) =>
|
|
||||||
tableFilterState.pageSize * (tableFilterState.page - 1) +
|
|
||||||
props.row.index +
|
|
||||||
1,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
accessorKey: 'transfer_date',
|
accessorKey: 'transfer_date',
|
||||||
header: 'Tanggal Transfer',
|
header: 'Tanggal Transfer',
|
||||||
@@ -274,6 +289,7 @@ const TransferToLayingsTable = () => {
|
|||||||
{
|
{
|
||||||
accessorKey: 'notes',
|
accessorKey: 'notes',
|
||||||
header: 'Alasan Transfer',
|
header: 'Alasan Transfer',
|
||||||
|
enableSorting: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'Status',
|
header: 'Status',
|
||||||
@@ -282,34 +298,39 @@ const TransferToLayingsTable = () => {
|
|||||||
props.row.original.approval.action === 'REJECTED';
|
props.row.original.approval.action === 'REJECTED';
|
||||||
let latestApprovalStepName = props.row.original.approval.step_name;
|
let latestApprovalStepName = props.row.original.approval.step_name;
|
||||||
|
|
||||||
let pillBadgeColor: 'yellow' | 'green' | 'gray' | 'red' = 'gray';
|
let badgeColor: Color = 'neutral';
|
||||||
|
|
||||||
switch (latestApprovalStepName.toLowerCase()) {
|
switch (latestApprovalStepName.toLowerCase()) {
|
||||||
case 'pengajuan':
|
case 'pengajuan':
|
||||||
pillBadgeColor = 'yellow';
|
badgeColor = 'neutral';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'disetujui':
|
case 'disetujui':
|
||||||
pillBadgeColor = 'green';
|
badgeColor = 'success';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLatestApprovalRejected) {
|
if (isLatestApprovalRejected) {
|
||||||
pillBadgeColor = 'red';
|
badgeColor = 'error';
|
||||||
latestApprovalStepName = 'Ditolak';
|
latestApprovalStepName = 'Ditolak';
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PillBadge
|
<Badge
|
||||||
content={latestApprovalStepName}
|
variant='soft'
|
||||||
color={pillBadgeColor}
|
className={{
|
||||||
className='text-sm'
|
badge: 'rounded-lg px-2 w-full flex flex-row justify-start',
|
||||||
/>
|
}}
|
||||||
|
color={badgeColor}
|
||||||
|
>
|
||||||
|
<Icon icon='mdi:circle' width={12} height={12} color={badgeColor} />
|
||||||
|
{latestApprovalStepName}
|
||||||
|
</Badge>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'Aksi',
|
id: 'actions',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const currentPageSize = props.table.getPaginationRowModel().rows.length;
|
const currentPageSize = props.table.getPaginationRowModel().rows.length;
|
||||||
const currentPageRows = props.table.getPaginationRowModel().flatRows;
|
const currentPageRows = props.table.getPaginationRowModel().flatRows;
|
||||||
@@ -346,31 +367,13 @@ const TransferToLayingsTable = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<RowOptionsMenu
|
||||||
{currentPageSize > 3 && (
|
props={props}
|
||||||
<RowDropdownOptions isLast2Rows={isLast2Rows}>
|
approveClickHandler={approveClickHandler}
|
||||||
<RowOptionsMenu
|
rejectClickHandler={rejectClickHandler}
|
||||||
type='dropdown'
|
deleteClickHandler={deleteClickHandler}
|
||||||
props={props}
|
popoverPosition={isLast2Rows ? 'top' : 'bottom'}
|
||||||
approveClickHandler={approveClickHandler}
|
/>
|
||||||
rejectClickHandler={rejectClickHandler}
|
|
||||||
deleteClickHandler={deleteClickHandler}
|
|
||||||
/>
|
|
||||||
</RowDropdownOptions>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{currentPageSize <= 3 && (
|
|
||||||
<RowCollapseOptions>
|
|
||||||
<RowOptionsMenu
|
|
||||||
type='collapse'
|
|
||||||
props={props}
|
|
||||||
approveClickHandler={approveClickHandler}
|
|
||||||
rejectClickHandler={rejectClickHandler}
|
|
||||||
deleteClickHandler={deleteClickHandler}
|
|
||||||
/>
|
|
||||||
</RowCollapseOptions>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -503,20 +506,19 @@ const TransferToLayingsTable = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// track sorting
|
useEffect(() => {
|
||||||
// useEffect(() => {
|
if (sorting.length === 1) {
|
||||||
// const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name');
|
updateFilter('filter_by', sorting[0].id);
|
||||||
|
updateFilter('sort_by', sorting[0].desc ? 'desc' : 'asc');
|
||||||
// if (!isNameSorted) {
|
} else {
|
||||||
// updateFilter('nameSort', '');
|
updateFilter('filter_by', '');
|
||||||
// } else {
|
updateFilter('sort_by', '');
|
||||||
// updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc');
|
}
|
||||||
// }
|
}, [sorting]);
|
||||||
// }, [sorting, updateFilter]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='w-full p-0 sm:p-4'>
|
<div className='w-full p-0'>
|
||||||
<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'>
|
||||||
@@ -583,12 +585,10 @@ const TransferToLayingsTable = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='grid grid-cols-12 justify-end gap-4'>
|
<div className='grid grid-cols-12 justify-end gap-4'>
|
||||||
<TextInput
|
<DateInput
|
||||||
required
|
|
||||||
type='date'
|
|
||||||
label='Tanggal Transfer'
|
|
||||||
name='transfer_date'
|
name='transfer_date'
|
||||||
placeholder='Masukkan tanggal transfer'
|
label='Tanggal Transfer'
|
||||||
|
placeholder='Tanggal Transfer'
|
||||||
value={tableFilterState.transferDate}
|
value={tableFilterState.transferDate}
|
||||||
onChange={transferDateChangeHandler}
|
onChange={transferDateChangeHandler}
|
||||||
className={{
|
className={{
|
||||||
@@ -623,20 +623,6 @@ const TransferToLayingsTable = () => {
|
|||||||
wrapper: 'col-span-12 sm:col-span-3',
|
wrapper: 'col-span-12 sm:col-span-3',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SelectInput
|
|
||||||
label='Baris'
|
|
||||||
options={ROWS_OPTIONS}
|
|
||||||
value={{
|
|
||||||
label: String(tableFilterState.pageSize),
|
|
||||||
value: tableFilterState.pageSize,
|
|
||||||
}}
|
|
||||||
onChange={pageSizeChangeHandler}
|
|
||||||
className={{
|
|
||||||
wrapper:
|
|
||||||
'col-span-6 sm:col-span-3 max-w-28 sm:justify-self-end',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -657,26 +643,21 @@ const TransferToLayingsTable = () => {
|
|||||||
: 0
|
: 0
|
||||||
}
|
}
|
||||||
onPageChange={setPage}
|
onPageChange={setPage}
|
||||||
|
onPageSizeChange={setPageSize}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
sorting={sorting}
|
sorting={sorting}
|
||||||
setSorting={setSorting}
|
setSorting={setSorting}
|
||||||
rowSelection={rowSelection}
|
rowSelection={rowSelection}
|
||||||
setRowSelection={setRowSelection}
|
setRowSelection={setRowSelection}
|
||||||
enableRowSelection={tableEnableRowSelectionHandler}
|
enableRowSelection={tableEnableRowSelectionHandler}
|
||||||
|
withCheckbox
|
||||||
className={{
|
className={{
|
||||||
containerClassName: cn({
|
containerClassName: cn({
|
||||||
'mb-20':
|
'w-full mb-20':
|
||||||
isResponseSuccess(transferToLayings) &&
|
isResponseSuccess(transferToLayings) &&
|
||||||
transferToLayings?.data?.length === 0,
|
transferToLayings?.data?.length === 0,
|
||||||
}),
|
}),
|
||||||
tableWrapperClassName: 'overflow-x-auto min-h-full!',
|
headerColumnClassName: 'text-nowrap',
|
||||||
tableClassName: 'font-inter w-full table-auto min-h-full!',
|
|
||||||
headerRowClassName: 'border-b border-b-gray-200',
|
|
||||||
headerColumnClassName:
|
|
||||||
'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
|
|
||||||
bodyRowClassName: 'border-b border-b-gray-200',
|
|
||||||
bodyColumnClassName:
|
|
||||||
'px-6 py-3 last:flex last:flex-row last:justify-end',
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user