chore: adjust TransferToLayingsTable styling

This commit is contained in:
ValdiANS
2026-01-20 17:07:24 +07:00
parent 7a45926c49
commit 26d89c35a5
@@ -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>