mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 15:25:46 +00:00
refactor(FE): Replace Badge with StatusBadge in uniformity views
This commit is contained in:
@@ -19,6 +19,7 @@ import { isResponseSuccess } from '@/lib/api-helper';
|
|||||||
import { type BaseApiResponse } from '@/types/api/api-general';
|
import { type BaseApiResponse } from '@/types/api/api-general';
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import Badge from '@/components/Badge';
|
import Badge from '@/components/Badge';
|
||||||
|
import StatusBadge from '@/components/helper/StatusBadge';
|
||||||
import CheckboxInput from '@/components/input/CheckboxInput';
|
import CheckboxInput from '@/components/input/CheckboxInput';
|
||||||
import { useModal } from '@/components/Modal';
|
import { useModal } from '@/components/Modal';
|
||||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
||||||
@@ -45,6 +46,7 @@ import {
|
|||||||
getStatusColor,
|
getStatusColor,
|
||||||
getStatusIndicatorColor,
|
getStatusIndicatorColor,
|
||||||
getStatusText,
|
getStatusText,
|
||||||
|
getStatusBadgeColor,
|
||||||
} from '@/components/pages/production/uniformity/uniformity-utils';
|
} from '@/components/pages/production/uniformity/uniformity-utils';
|
||||||
import { generateUniformityPDF } from '@/components/pages/production/uniformity/export/UniformityExportPDF';
|
import { generateUniformityPDF } from '@/components/pages/production/uniformity/export/UniformityExportPDF';
|
||||||
import { generateUniformityExcel } from '@/components/pages/production/uniformity/export/UniformityExportExcel';
|
import { generateUniformityExcel } from '@/components/pages/production/uniformity/export/UniformityExportExcel';
|
||||||
@@ -832,7 +834,7 @@ const UniformityTable = () => {
|
|||||||
},
|
},
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className='w-full flex flex-row justify-center'>
|
||||||
<CheckboxInput
|
<CheckboxInput
|
||||||
name='row'
|
name='row'
|
||||||
checked={row.getIsSelected()}
|
checked={row.getIsSelected()}
|
||||||
@@ -862,8 +864,11 @@ const UniformityTable = () => {
|
|||||||
{
|
{
|
||||||
accessorKey: 'week',
|
accessorKey: 'week',
|
||||||
header: 'Tanggal (Week)',
|
header: 'Tanggal (Week)',
|
||||||
cell: (props) =>
|
cell: (props) => (
|
||||||
`${formatDate(props.row.original.applied_at, 'DD MMM YYYY')} (${props.row.original.week})`,
|
<span className='text-nowrap'>
|
||||||
|
{`${formatDate(props.row.original.applied_at, 'DD MMM YYYY')} (${props.row.original.week})`}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: 'status',
|
accessorKey: 'status',
|
||||||
@@ -872,20 +877,11 @@ const UniformityTable = () => {
|
|||||||
const uniformity = props.row.original;
|
const uniformity = props.row.original;
|
||||||
const status =
|
const status =
|
||||||
uniformity.latest_approval?.action ?? uniformity.status;
|
uniformity.latest_approval?.action ?? uniformity.status;
|
||||||
return (
|
|
||||||
<div className='w-full'>
|
const badgeColor = getStatusBadgeColor(status);
|
||||||
<Badge
|
const statusText = getStatusText(status);
|
||||||
statusIndicator={true}
|
|
||||||
variant='soft'
|
return <StatusBadge color={badgeColor} text={statusText} />;
|
||||||
className={{
|
|
||||||
badge: `rounded-xl w-full justify-start border border-gray-200 text-black ${getStatusColor(status)}`,
|
|
||||||
status: getStatusIndicatorColor(status),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{getStatusText(status)}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1039,425 +1035,413 @@ const UniformityTable = () => {
|
|||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section className='p-3 pt-0'>
|
<Table<Uniformity>
|
||||||
<Table<Uniformity>
|
data={isResponseSuccess(uniformities) ? uniformities?.data : []}
|
||||||
data={isResponseSuccess(uniformities) ? uniformities?.data : []}
|
columns={uniformityColumns}
|
||||||
columns={uniformityColumns}
|
pageSize={tableFilterState.pageSize}
|
||||||
pageSize={tableFilterState.pageSize}
|
page={isResponseSuccess(uniformities) ? uniformities?.meta?.page : 0}
|
||||||
page={isResponseSuccess(uniformities) ? uniformities?.meta?.page : 0}
|
totalItems={
|
||||||
totalItems={
|
isResponseSuccess(uniformities)
|
||||||
isResponseSuccess(uniformities)
|
? uniformities?.meta?.total_results
|
||||||
? uniformities?.meta?.total_results
|
: 0
|
||||||
: 0
|
}
|
||||||
}
|
onPageChange={setPage}
|
||||||
onPageChange={setPage}
|
isLoading={isLoading}
|
||||||
isLoading={isLoading}
|
sorting={sorting}
|
||||||
sorting={sorting}
|
setSorting={setSorting}
|
||||||
setSorting={setSorting}
|
rowSelection={rowSelection}
|
||||||
rowSelection={rowSelection}
|
setRowSelection={setRowSelection}
|
||||||
setRowSelection={setRowSelection}
|
className={{
|
||||||
className={{
|
containerClassName: cn('p-3 pt-0', {
|
||||||
containerClassName: cn({
|
'mb-20':
|
||||||
'mb-20':
|
isResponseSuccess(uniformities) &&
|
||||||
isResponseSuccess(uniformities) &&
|
uniformities?.data?.length === 0,
|
||||||
uniformities?.data?.length === 0,
|
}),
|
||||||
}),
|
headerColumnClassName: 'text-nowrap',
|
||||||
tableWrapperClassName: 'overflow-x-auto min-h-full rounded-xl',
|
}}
|
||||||
tableClassName: 'font-inter w-full table-auto min-h-full!',
|
emptyContent={<UniformityTableSkeleton />}
|
||||||
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',
|
|
||||||
}}
|
|
||||||
emptyContent={<UniformityTableSkeleton />}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
ref={successModal.ref}
|
ref={successModal.ref}
|
||||||
type='success'
|
type='success'
|
||||||
iconPosition='left'
|
iconPosition='left'
|
||||||
text='Data Berhasil Ditambahkan'
|
text='Data Berhasil Ditambahkan'
|
||||||
subtitleText='Data uniformity telah berhasil disimpan.'
|
subtitleText='Data uniformity telah berhasil disimpan.'
|
||||||
closeOnBackdrop={false}
|
closeOnBackdrop={false}
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: 'Ok',
|
text: 'Ok',
|
||||||
color: 'primary',
|
color: 'primary',
|
||||||
onClick: handleSuccessModalClose,
|
onClick: handleSuccessModalClose,
|
||||||
}}
|
}}
|
||||||
className={{
|
className={{
|
||||||
modalBox: 'rounded-2xl',
|
modalBox: 'rounded-2xl',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className='flex flex-col gap-4 mt-4'>
|
<div className='flex flex-col gap-4 mt-4'>
|
||||||
{createdUniformity ? (
|
{createdUniformity ? (
|
||||||
<UniformityConfirmationPreview
|
<UniformityConfirmationPreview
|
||||||
uniformityDetail={createdUniformity}
|
uniformityDetail={createdUniformity}
|
||||||
/>
|
/>
|
||||||
) : selectedRowIds.length === 1 ? (
|
) : selectedRowIds.length === 1 ? (
|
||||||
<UniformityConfirmationPreview
|
<UniformityConfirmationPreview
|
||||||
uniformity={selectedUniformities[0]}
|
uniformity={selectedUniformities[0]}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className='text-center text-gray-500'>
|
<div className='text-center text-gray-500'>
|
||||||
{selectedRowIds.length} data dipilih
|
{selectedRowIds.length} data dipilih
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</ConfirmationModal>
|
|
||||||
|
|
||||||
<ConfirmationModal
|
|
||||||
ref={singleDeleteModal.ref}
|
|
||||||
type='error'
|
|
||||||
iconPosition='left'
|
|
||||||
text={`Delete This Data?`}
|
|
||||||
subtitleText='Are you sure you want to delete this data?'
|
|
||||||
secondaryButton={{
|
|
||||||
text: 'Cancel',
|
|
||||||
}}
|
|
||||||
primaryButton={{
|
|
||||||
text: 'Delete',
|
|
||||||
color: 'primary',
|
|
||||||
isLoading: isDeleteLoading,
|
|
||||||
onClick: singleDeleteHandler,
|
|
||||||
}}
|
|
||||||
className={{
|
|
||||||
modalBox: 'rounded-2xl',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className='flex flex-col gap-4 mt-4'>
|
|
||||||
<UniformityConfirmationPreview uniformity={selectedUniformity} />
|
|
||||||
</div>
|
|
||||||
</ConfirmationModal>
|
|
||||||
|
|
||||||
<ConfirmationModal
|
|
||||||
ref={singleApproveModal.ref}
|
|
||||||
type='success'
|
|
||||||
iconPosition='left'
|
|
||||||
text='Approve This Submission?'
|
|
||||||
subtitleText='Are you sure you want to approve this submission?'
|
|
||||||
secondaryButton={{
|
|
||||||
text: 'Cancel',
|
|
||||||
}}
|
|
||||||
primaryButton={{
|
|
||||||
text: 'Approve',
|
|
||||||
color: 'primary',
|
|
||||||
isLoading: isDeleteLoading,
|
|
||||||
onClick: singleApproveHandler,
|
|
||||||
}}
|
|
||||||
className={{
|
|
||||||
modalBox: 'rounded-2xl',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className='flex flex-col gap-4 mt-4'>
|
|
||||||
{selectedRowIds.length === 1 ? (
|
|
||||||
<UniformityConfirmationPreview
|
|
||||||
uniformity={selectedUniformities[0]}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className='text-center text-gray-500'>
|
|
||||||
{selectedRowIds.length} data dipilih
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</ConfirmationModal>
|
|
||||||
|
|
||||||
<ConfirmationModal
|
|
||||||
ref={bulkApproveModal.ref}
|
|
||||||
type='success'
|
|
||||||
iconPosition='left'
|
|
||||||
text={`Approve This Submission?`}
|
|
||||||
subtitleText={`Are you sure you want to approve this submission? (${selectedRowIds.length} data)`}
|
|
||||||
secondaryButton={{
|
|
||||||
text: 'Cancel',
|
|
||||||
}}
|
|
||||||
primaryButton={{
|
|
||||||
text: 'Approve',
|
|
||||||
color: 'primary',
|
|
||||||
isLoading: isBulkActionLoading,
|
|
||||||
onClick: bulkApproveHandler,
|
|
||||||
}}
|
|
||||||
className={{
|
|
||||||
modalBox: 'rounded-2xl',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className='flex flex-col gap-4 mt-4'>
|
|
||||||
<UniformityConfirmationPreview uniformity={selectedUniformity} />
|
|
||||||
</div>
|
|
||||||
</ConfirmationModal>
|
|
||||||
|
|
||||||
<ConfirmationModal
|
|
||||||
ref={singleRejectModal.ref}
|
|
||||||
type='error'
|
|
||||||
iconPosition='left'
|
|
||||||
text='Reject This Submission?'
|
|
||||||
subtitleText='Are you sure you want to reject this submission?'
|
|
||||||
secondaryButton={{
|
|
||||||
text: 'Cancel',
|
|
||||||
}}
|
|
||||||
primaryButton={{
|
|
||||||
text: 'Reject',
|
|
||||||
color: 'primary',
|
|
||||||
isLoading: isDeleteLoading,
|
|
||||||
onClick: singleRejectHandler,
|
|
||||||
}}
|
|
||||||
className={{
|
|
||||||
modalBox: 'rounded-2xl',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className='flex flex-col gap-4 mt-4'>
|
|
||||||
{selectedRowIds.length === 1 ? (
|
|
||||||
<UniformityConfirmationPreview
|
|
||||||
uniformity={selectedUniformities[0]}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className='text-center text-gray-500'>
|
|
||||||
{selectedRowIds.length} data dipilih
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</ConfirmationModal>
|
|
||||||
|
|
||||||
<ConfirmationModal
|
|
||||||
ref={bulkRejectModal.ref}
|
|
||||||
type='error'
|
|
||||||
iconPosition='left'
|
|
||||||
text={`Apakah anda yakin ingin menolak ${selectedRowIds.length} data Uniformity yang dipilih?`}
|
|
||||||
secondaryButton={{
|
|
||||||
text: 'Cancel',
|
|
||||||
}}
|
|
||||||
primaryButton={{
|
|
||||||
text: 'Reject',
|
|
||||||
color: 'primary',
|
|
||||||
isLoading: isBulkActionLoading,
|
|
||||||
onClick: bulkRejectHandler,
|
|
||||||
}}
|
|
||||||
className={{
|
|
||||||
modalBox: 'rounded-2xl',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className='flex flex-col gap-4 mt-4'>
|
|
||||||
{selectedRowIds.length === 1 ? (
|
|
||||||
<UniformityConfirmationPreview
|
|
||||||
uniformity={selectedUniformities[0]}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className='text-center text-gray-500'>
|
|
||||||
{selectedRowIds.length} data dipilih
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</ConfirmationModal>
|
|
||||||
|
|
||||||
{/* Filter Modal */}
|
|
||||||
<Modal
|
|
||||||
ref={filterModal.ref}
|
|
||||||
className={{
|
|
||||||
modal: 'p-0',
|
|
||||||
modalBox: 'p-0 rounded-2xl xl:max-w-4/12 max-w-sm',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className='space-y-6'>
|
|
||||||
{/* Modal Header */}
|
|
||||||
<div className='flex items-center justify-between gap-2 py-3 border-b border-gray-300 px-4'>
|
|
||||||
<div className='flex items-center gap-2 text-primary'>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
<h3 className='font-semibold'>Filter Data</h3>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
variant='link'
|
|
||||||
onClick={filterModal.closeModal}
|
|
||||||
className='text-gray-500 hover:text-gray-700 transition-colors cursor-pointer'
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ConfirmationModal>
|
||||||
|
|
||||||
<div className='space-y-1.5 px-4'>
|
<ConfirmationModal
|
||||||
<div className='grid grid-cols-1 sm:grid-cols-2 sm:gap-1.5'>
|
ref={singleDeleteModal.ref}
|
||||||
<div>
|
type='error'
|
||||||
<DateInput
|
iconPosition='left'
|
||||||
required
|
text={`Delete This Data?`}
|
||||||
label='Tanggal mulai'
|
subtitleText='Are you sure you want to delete this data?'
|
||||||
name='start_date'
|
secondaryButton={{
|
||||||
value={filterFormik.values.start_date}
|
text: 'Cancel',
|
||||||
onChange={handleFilterStartDateChange}
|
}}
|
||||||
onBlur={filterFormik.handleBlur}
|
primaryButton={{
|
||||||
isError={
|
text: 'Delete',
|
||||||
filterFormik.touched.start_date &&
|
color: 'primary',
|
||||||
Boolean(filterFormik.errors.start_date)
|
isLoading: isDeleteLoading,
|
||||||
}
|
onClick: singleDeleteHandler,
|
||||||
errorMessage={filterFormik.errors.start_date}
|
}}
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{
|
||||||
/>
|
modalBox: 'rounded-2xl',
|
||||||
</div>
|
}}
|
||||||
|
>
|
||||||
|
<div className='flex flex-col gap-4 mt-4'>
|
||||||
|
<UniformityConfirmationPreview uniformity={selectedUniformity} />
|
||||||
|
</div>
|
||||||
|
</ConfirmationModal>
|
||||||
|
|
||||||
<div>
|
<ConfirmationModal
|
||||||
<DateInput
|
ref={singleApproveModal.ref}
|
||||||
required
|
type='success'
|
||||||
label='Tanggal akhir'
|
iconPosition='left'
|
||||||
name='end_date'
|
text='Approve This Submission?'
|
||||||
value={filterFormik.values.end_date}
|
subtitleText='Are you sure you want to approve this submission?'
|
||||||
onChange={handleFilterEndDateChange}
|
secondaryButton={{
|
||||||
onBlur={filterFormik.handleBlur}
|
text: 'Cancel',
|
||||||
isError={
|
}}
|
||||||
filterFormik.touched.end_date &&
|
primaryButton={{
|
||||||
Boolean(filterFormik.errors.end_date)
|
text: 'Approve',
|
||||||
}
|
color: 'primary',
|
||||||
errorMessage={filterFormik.errors.end_date}
|
isLoading: isDeleteLoading,
|
||||||
className={{ wrapper: 'w-full' }}
|
onClick: singleApproveHandler,
|
||||||
/>
|
}}
|
||||||
</div>
|
className={{
|
||||||
</div>
|
modalBox: 'rounded-2xl',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='flex flex-col gap-4 mt-4'>
|
||||||
|
{selectedRowIds.length === 1 ? (
|
||||||
|
<UniformityConfirmationPreview
|
||||||
|
uniformity={selectedUniformities[0]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className='text-center text-gray-500'>
|
||||||
|
{selectedRowIds.length} data dipilih
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ConfirmationModal>
|
||||||
|
|
||||||
|
<ConfirmationModal
|
||||||
|
ref={bulkApproveModal.ref}
|
||||||
|
type='success'
|
||||||
|
iconPosition='left'
|
||||||
|
text={`Approve This Submission?`}
|
||||||
|
subtitleText={`Are you sure you want to approve this submission? (${selectedRowIds.length} data)`}
|
||||||
|
secondaryButton={{
|
||||||
|
text: 'Cancel',
|
||||||
|
}}
|
||||||
|
primaryButton={{
|
||||||
|
text: 'Approve',
|
||||||
|
color: 'primary',
|
||||||
|
isLoading: isBulkActionLoading,
|
||||||
|
onClick: bulkApproveHandler,
|
||||||
|
}}
|
||||||
|
className={{
|
||||||
|
modalBox: 'rounded-2xl',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='flex flex-col gap-4 mt-4'>
|
||||||
|
<UniformityConfirmationPreview uniformity={selectedUniformity} />
|
||||||
|
</div>
|
||||||
|
</ConfirmationModal>
|
||||||
|
|
||||||
|
<ConfirmationModal
|
||||||
|
ref={singleRejectModal.ref}
|
||||||
|
type='error'
|
||||||
|
iconPosition='left'
|
||||||
|
text='Reject This Submission?'
|
||||||
|
subtitleText='Are you sure you want to reject this submission?'
|
||||||
|
secondaryButton={{
|
||||||
|
text: 'Cancel',
|
||||||
|
}}
|
||||||
|
primaryButton={{
|
||||||
|
text: 'Reject',
|
||||||
|
color: 'primary',
|
||||||
|
isLoading: isDeleteLoading,
|
||||||
|
onClick: singleRejectHandler,
|
||||||
|
}}
|
||||||
|
className={{
|
||||||
|
modalBox: 'rounded-2xl',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='flex flex-col gap-4 mt-4'>
|
||||||
|
{selectedRowIds.length === 1 ? (
|
||||||
|
<UniformityConfirmationPreview
|
||||||
|
uniformity={selectedUniformities[0]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className='text-center text-gray-500'>
|
||||||
|
{selectedRowIds.length} data dipilih
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ConfirmationModal>
|
||||||
|
|
||||||
|
<ConfirmationModal
|
||||||
|
ref={bulkRejectModal.ref}
|
||||||
|
type='error'
|
||||||
|
iconPosition='left'
|
||||||
|
text={`Apakah anda yakin ingin menolak ${selectedRowIds.length} data Uniformity yang dipilih?`}
|
||||||
|
secondaryButton={{
|
||||||
|
text: 'Cancel',
|
||||||
|
}}
|
||||||
|
primaryButton={{
|
||||||
|
text: 'Reject',
|
||||||
|
color: 'primary',
|
||||||
|
isLoading: isBulkActionLoading,
|
||||||
|
onClick: bulkRejectHandler,
|
||||||
|
}}
|
||||||
|
className={{
|
||||||
|
modalBox: 'rounded-2xl',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='flex flex-col gap-4 mt-4'>
|
||||||
|
{selectedRowIds.length === 1 ? (
|
||||||
|
<UniformityConfirmationPreview
|
||||||
|
uniformity={selectedUniformities[0]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className='text-center text-gray-500'>
|
||||||
|
{selectedRowIds.length} data dipilih
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ConfirmationModal>
|
||||||
|
|
||||||
|
{/* Filter Modal */}
|
||||||
|
<Modal
|
||||||
|
ref={filterModal.ref}
|
||||||
|
className={{
|
||||||
|
modal: 'p-0',
|
||||||
|
modalBox: 'p-0 rounded-2xl xl:max-w-4/12 max-w-sm',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='space-y-6'>
|
||||||
|
{/* Modal Header */}
|
||||||
|
<div className='flex items-center justify-between gap-2 py-3 border-b border-gray-300 px-4'>
|
||||||
|
<div className='flex items-center gap-2 text-primary'>
|
||||||
|
<Icon icon='heroicons:funnel' width={20} height={20} />
|
||||||
|
<h3 className='font-semibold'>Filter Data</h3>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant='link'
|
||||||
|
onClick={filterModal.closeModal}
|
||||||
|
className='text-gray-500 hover:text-gray-700 transition-colors cursor-pointer'
|
||||||
|
>
|
||||||
|
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='space-y-1.5 px-4'>
|
||||||
|
<div className='grid grid-cols-1 sm:grid-cols-2 sm:gap-1.5'>
|
||||||
<div>
|
<div>
|
||||||
<SelectInput
|
<DateInput
|
||||||
required
|
required
|
||||||
label='Lokasi'
|
label='Tanggal mulai'
|
||||||
placeholder='Pilih Lokasi...'
|
name='start_date'
|
||||||
value={filterFormik.values.location}
|
value={filterFormik.values.start_date}
|
||||||
onChange={(value) => {
|
onChange={handleFilterStartDateChange}
|
||||||
handleFilterLocationChange(value);
|
onBlur={filterFormik.handleBlur}
|
||||||
}}
|
|
||||||
options={filterLocationOptions}
|
|
||||||
onInputChange={setFilterLocationInputValue}
|
|
||||||
isLoading={isLoadingFilterLocations}
|
|
||||||
onMenuScrollToBottom={loadMoreFilterLocations}
|
|
||||||
isError={
|
isError={
|
||||||
filterFormik.touched.location &&
|
filterFormik.touched.start_date &&
|
||||||
Boolean(filterFormik.errors.location)
|
Boolean(filterFormik.errors.start_date)
|
||||||
}
|
}
|
||||||
errorMessage={filterFormik.errors.location}
|
errorMessage={filterFormik.errors.start_date}
|
||||||
isClearable
|
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full' }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<SelectInput
|
<DateInput
|
||||||
required
|
required
|
||||||
label='Project Flock'
|
label='Tanggal akhir'
|
||||||
placeholder='Pilih Project Flock...'
|
name='end_date'
|
||||||
value={filterFormik.values.project_flock}
|
value={filterFormik.values.end_date}
|
||||||
onChange={(value) => {
|
onChange={handleFilterEndDateChange}
|
||||||
handleFilterProjectFlockChange(value);
|
onBlur={filterFormik.handleBlur}
|
||||||
}}
|
|
||||||
options={filterProjectFlockOptions}
|
|
||||||
onInputChange={setFilterProjectFlockSearchValue}
|
|
||||||
isLoading={isLoadingFilterProjectFlocks}
|
|
||||||
onMenuScrollToBottom={loadMoreFilterProjectFlocks}
|
|
||||||
isDisabled={!filterFormik.values.location}
|
|
||||||
isError={
|
isError={
|
||||||
filterFormik.touched.project_flock &&
|
filterFormik.touched.end_date &&
|
||||||
Boolean(filterFormik.errors.project_flock)
|
Boolean(filterFormik.errors.end_date)
|
||||||
}
|
}
|
||||||
errorMessage={filterFormik.errors.project_flock}
|
errorMessage={filterFormik.errors.end_date}
|
||||||
isClearable
|
|
||||||
className={{ wrapper: 'w-full' }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<SelectInput
|
|
||||||
required
|
|
||||||
label='Kandang'
|
|
||||||
placeholder='Pilih Kandang...'
|
|
||||||
value={filterFormik.values.kandang}
|
|
||||||
onChange={(value) => {
|
|
||||||
handleFilterKandangChange(value);
|
|
||||||
}}
|
|
||||||
options={filterKandangOptions}
|
|
||||||
isDisabled={!filterFormik.values.project_flock}
|
|
||||||
isError={
|
|
||||||
filterFormik.touched.kandang &&
|
|
||||||
Boolean(filterFormik.errors.kandang)
|
|
||||||
}
|
|
||||||
errorMessage={filterFormik.errors.kandang}
|
|
||||||
isClearable
|
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full' }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='w-full'>
|
<div>
|
||||||
{/* Error List Alert */}
|
<SelectInput
|
||||||
{formErrorList.length > 0 && (
|
required
|
||||||
<div className='w-full px-4'>
|
label='Lokasi'
|
||||||
<AlertErrorList
|
placeholder='Pilih Lokasi...'
|
||||||
formErrorList={formErrorList}
|
value={filterFormik.values.location}
|
||||||
onClose={close}
|
onChange={(value) => {
|
||||||
/>
|
handleFilterLocationChange(value);
|
||||||
</div>
|
}}
|
||||||
)}
|
options={filterLocationOptions}
|
||||||
|
onInputChange={setFilterLocationInputValue}
|
||||||
|
isLoading={isLoadingFilterLocations}
|
||||||
|
onMenuScrollToBottom={loadMoreFilterLocations}
|
||||||
|
isError={
|
||||||
|
filterFormik.touched.location &&
|
||||||
|
Boolean(filterFormik.errors.location)
|
||||||
|
}
|
||||||
|
errorMessage={filterFormik.errors.location}
|
||||||
|
isClearable
|
||||||
|
className={{ wrapper: 'w-full' }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Action Buttons */}
|
<div>
|
||||||
<div className='flex justify-between gap-4 py-4 mt-8 border-t border-gray-300 bg-gray-100'>
|
<SelectInput
|
||||||
<Button
|
required
|
||||||
variant='soft'
|
label='Project Flock'
|
||||||
className='ms-4 min-w-36 rounded-lg'
|
placeholder='Pilih Project Flock...'
|
||||||
onClick={handleResetFilters}
|
value={filterFormik.values.project_flock}
|
||||||
>
|
onChange={(value) => {
|
||||||
Reset Filter
|
handleFilterProjectFlockChange(value);
|
||||||
</Button>
|
}}
|
||||||
<Button
|
options={filterProjectFlockOptions}
|
||||||
className='me-4 min-w-36 rounded-lg'
|
onInputChange={setFilterProjectFlockSearchValue}
|
||||||
onClick={handleApplyFilters}
|
isLoading={isLoadingFilterProjectFlocks}
|
||||||
>
|
onMenuScrollToBottom={loadMoreFilterProjectFlocks}
|
||||||
Apply Filter
|
isDisabled={!filterFormik.values.location}
|
||||||
</Button>
|
isError={
|
||||||
|
filterFormik.touched.project_flock &&
|
||||||
|
Boolean(filterFormik.errors.project_flock)
|
||||||
|
}
|
||||||
|
errorMessage={filterFormik.errors.project_flock}
|
||||||
|
isClearable
|
||||||
|
className={{ wrapper: 'w-full' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<SelectInput
|
||||||
|
required
|
||||||
|
label='Kandang'
|
||||||
|
placeholder='Pilih Kandang...'
|
||||||
|
value={filterFormik.values.kandang}
|
||||||
|
onChange={(value) => {
|
||||||
|
handleFilterKandangChange(value);
|
||||||
|
}}
|
||||||
|
options={filterKandangOptions}
|
||||||
|
isDisabled={!filterFormik.values.project_flock}
|
||||||
|
isError={
|
||||||
|
filterFormik.touched.kandang &&
|
||||||
|
Boolean(filterFormik.errors.kandang)
|
||||||
|
}
|
||||||
|
errorMessage={filterFormik.errors.kandang}
|
||||||
|
isClearable
|
||||||
|
className={{ wrapper: 'w-full' }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
|
||||||
|
|
||||||
{/* Floating Actions Button */}
|
<div className='w-full'>
|
||||||
<FloatingActionsButton
|
{/* Error List Alert */}
|
||||||
actions={[
|
{formErrorList.length > 0 && (
|
||||||
{
|
<div className='w-full px-4'>
|
||||||
action: 'DETAIL',
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
icon: 'mdi:eye-outline',
|
</div>
|
||||||
label: 'Lihat Detail',
|
)}
|
||||||
hidden: selectedRowIds.length !== 1,
|
</div>
|
||||||
onClick() {
|
|
||||||
router.push(
|
{/* Action Buttons */}
|
||||||
`/production/uniformity/detail?uniformityId=${selectedRowIds[0]}`
|
<div className='flex justify-between gap-4 py-4 mt-8 border-t border-gray-300 bg-gray-100'>
|
||||||
);
|
<Button
|
||||||
setRowSelection({});
|
variant='soft'
|
||||||
},
|
className='ms-4 min-w-36 rounded-lg'
|
||||||
permissions: 'lti.production.uniformity.detail',
|
onClick={handleResetFilters}
|
||||||
|
>
|
||||||
|
Reset Filter
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className='me-4 min-w-36 rounded-lg'
|
||||||
|
onClick={handleApplyFilters}
|
||||||
|
>
|
||||||
|
Apply Filter
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
{/* Floating Actions Button */}
|
||||||
|
<FloatingActionsButton
|
||||||
|
actions={[
|
||||||
|
{
|
||||||
|
action: 'DETAIL',
|
||||||
|
icon: 'mdi:eye-outline',
|
||||||
|
label: 'Lihat Detail',
|
||||||
|
hidden: selectedRowIds.length !== 1,
|
||||||
|
onClick() {
|
||||||
|
router.push(
|
||||||
|
`/production/uniformity/detail?uniformityId=${selectedRowIds[0]}`
|
||||||
|
);
|
||||||
|
setRowSelection({});
|
||||||
},
|
},
|
||||||
{
|
permissions: 'lti.production.uniformity.detail',
|
||||||
action: 'DELETE',
|
},
|
||||||
icon: 'mdi:delete-outline',
|
{
|
||||||
label: 'Delete',
|
action: 'DELETE',
|
||||||
hidden: selectedRowIds.length !== 1,
|
icon: 'mdi:delete-outline',
|
||||||
onClick: handleDelete,
|
label: 'Delete',
|
||||||
permissions: 'lti.production.uniformity.delete',
|
hidden: selectedRowIds.length !== 1,
|
||||||
},
|
onClick: handleDelete,
|
||||||
]}
|
permissions: 'lti.production.uniformity.delete',
|
||||||
approvals={[
|
},
|
||||||
{
|
]}
|
||||||
action: 'APPROVED',
|
approvals={[
|
||||||
icon: 'mdi:check-circle-outline',
|
{
|
||||||
label: 'Approve',
|
action: 'APPROVED',
|
||||||
onClick: handleBulkApprove,
|
icon: 'mdi:check-circle-outline',
|
||||||
permissions: 'lti.production.uniformity.approve',
|
label: 'Approve',
|
||||||
disabled: !canApproveReject,
|
onClick: handleBulkApprove,
|
||||||
},
|
permissions: 'lti.production.uniformity.approve',
|
||||||
{
|
disabled: !canApproveReject,
|
||||||
action: 'REJECTED',
|
},
|
||||||
icon: 'mdi:close-circle-outline',
|
{
|
||||||
label: 'Reject',
|
action: 'REJECTED',
|
||||||
onClick: handleBulkReject,
|
icon: 'mdi:close-circle-outline',
|
||||||
permissions: 'lti.production.uniformity.approve',
|
label: 'Reject',
|
||||||
disabled: !canApproveReject,
|
onClick: handleBulkReject,
|
||||||
},
|
permissions: 'lti.production.uniformity.approve',
|
||||||
]}
|
disabled: !canApproveReject,
|
||||||
selectedRowIds={selectedRowIds}
|
},
|
||||||
onClose={handleCloseFab}
|
]}
|
||||||
/>
|
selectedRowIds={selectedRowIds}
|
||||||
</section>
|
onClose={handleCloseFab}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,11 +10,10 @@ import {
|
|||||||
UniformityInfoUmum,
|
UniformityInfoUmum,
|
||||||
} from '@/types/api/production/uniformity';
|
} from '@/types/api/production/uniformity';
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import Badge from '@/components/Badge';
|
import StatusBadge from '@/components/helper/StatusBadge';
|
||||||
import {
|
import {
|
||||||
getWeightStatusColor,
|
|
||||||
getWeightStatusIndicatorColor,
|
|
||||||
getWeightStatusText,
|
getWeightStatusText,
|
||||||
|
getWeightStatusBadgeColor,
|
||||||
} from '@/components/pages/production/uniformity/uniformity-utils';
|
} from '@/components/pages/production/uniformity/uniformity-utils';
|
||||||
import { BodyWeightData } from '@/types/api/production/uniformity';
|
import { BodyWeightData } from '@/types/api/production/uniformity';
|
||||||
|
|
||||||
@@ -65,30 +64,12 @@ const UniformityDetailsPreview = ({
|
|||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const status = props.row.original.status;
|
const status = props.row.original.status;
|
||||||
return status ? (
|
return status ? (
|
||||||
<div className='w-full'>
|
<StatusBadge
|
||||||
<Badge
|
color={getWeightStatusBadgeColor(status)}
|
||||||
statusIndicator={true}
|
text={getWeightStatusText(status)}
|
||||||
variant='soft'
|
/>
|
||||||
className={{
|
|
||||||
badge: `rounded-xl w-full justify-start border border-gray-200 text-black ${getWeightStatusColor(status)}`,
|
|
||||||
status: getWeightStatusIndicatorColor(status),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{getWeightStatusText(status)}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<Badge
|
<StatusBadge color='info' text='Unknown' />
|
||||||
statusIndicator={true}
|
|
||||||
variant='soft'
|
|
||||||
className={{
|
|
||||||
badge:
|
|
||||||
'rounded-xl w-full justify-start border border-gray-200 text-black bg-info/10',
|
|
||||||
status: 'bg-info',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Unknown
|
|
||||||
</Badge>
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,12 +14,11 @@ import { useRouter } from 'next/navigation';
|
|||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { UniformityApi } from '@/services/api/uniformity';
|
import { UniformityApi } from '@/services/api/uniformity';
|
||||||
import { isResponseError } from '@/lib/api-helper';
|
import { isResponseError } from '@/lib/api-helper';
|
||||||
import Badge from '@/components/Badge';
|
import StatusBadge from '@/components/helper/StatusBadge';
|
||||||
import { formatNumber } from '@/lib/helper';
|
import { formatNumber } from '@/lib/helper';
|
||||||
import {
|
import {
|
||||||
getWeightStatusColor,
|
|
||||||
getWeightStatusIndicatorColor,
|
|
||||||
getWeightStatusText,
|
getWeightStatusText,
|
||||||
|
getWeightStatusBadgeColor,
|
||||||
} from '@/components/pages/production/uniformity/uniformity-utils';
|
} from '@/components/pages/production/uniformity/uniformity-utils';
|
||||||
import { DetailOptionType } from '@/types/api/production/uniformity';
|
import { DetailOptionType } from '@/types/api/production/uniformity';
|
||||||
import {
|
import {
|
||||||
@@ -204,30 +203,12 @@ const UniformityResultForm = () => {
|
|||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const status = props.row.original.status;
|
const status = props.row.original.status;
|
||||||
return status ? (
|
return status ? (
|
||||||
<div className='w-full'>
|
<StatusBadge
|
||||||
<Badge
|
color={getWeightStatusBadgeColor(status)}
|
||||||
statusIndicator={true}
|
text={getWeightStatusText(status)}
|
||||||
variant='soft'
|
/>
|
||||||
className={{
|
|
||||||
badge: `rounded-xl w-full justify-start border border-gray-200 text-black ${getWeightStatusColor(status)}`,
|
|
||||||
status: getWeightStatusIndicatorColor(status),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{getWeightStatusText(status)}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<Badge
|
<StatusBadge color='info' text='Unknown' />
|
||||||
statusIndicator={true}
|
|
||||||
variant='soft'
|
|
||||||
className={{
|
|
||||||
badge:
|
|
||||||
'rounded-xl w-full justify-start border border-gray-200 text-black bg-info/10',
|
|
||||||
status: 'bg-info',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Unknown
|
|
||||||
</Badge>
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user