Merge branch 'fix/refactor-project-flock-detail' into 'development'

[FIX/FE] Refactor Project Flock Detail UI

See merge request mbugroup/lti-web-client!326
This commit is contained in:
Rivaldi A N S
2026-02-18 08:21:57 +00:00
4 changed files with 360 additions and 274 deletions
+16 -6
View File
@@ -85,8 +85,8 @@ const DUMMY_SKELETON_DATA = Array.from({ length: 10 }, (_, index) => ({
})); }));
const emptyContentDefaultValue = ( const emptyContentDefaultValue = (
<div className='w-full p-5 text-center'> <div className='w-full text-center py-4'>
<span className='text-lg opacity-50'> <span className='text-sm opacity-50'>
Tidak ada data yang dapat ditampilkan... Tidak ada data yang dapat ditampilkan...
</span> </span>
</div> </div>
@@ -452,6 +452,20 @@ const Table = <TData extends object>({
</Fragment> </Fragment>
); );
})} })}
{(data.length === 0 || table.getRowModel().rows.length === 0) &&
!isLoading && (
<tr>
<td
colSpan={
table.getAllLeafColumns().length + (withCheckbox ? 1 : 0)
}
className='p-0'
>
{emptyContent}
</td>
</tr>
)}
</tbody> </tbody>
<tfoot <tfoot
className={cn( className={cn(
@@ -489,10 +503,6 @@ const Table = <TData extends object>({
</table> </table>
</div> </div>
{(data.length === 0 || table.getRowModel().rows.length === 0) &&
!isLoading &&
emptyContent}
{data.length > 0 && {data.length > 0 &&
table.getRowModel().rows.length > 0 && table.getRowModel().rows.length > 0 &&
!isLoading && !isLoading &&
@@ -16,6 +16,7 @@ import ChickinLogsView from '@/components/pages/production/chickin/form/tabs/Chi
import DrawerHeader from '@/components/helper/drawer/DrawerHeader'; import DrawerHeader from '@/components/helper/drawer/DrawerHeader';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import Badge from '@/components/Badge'; import Badge from '@/components/Badge';
import StatusBadge from '@/components/helper/StatusBadge';
import { CHICKINS_APPROVAL_LINE } from '@/config/approval-line'; import { CHICKINS_APPROVAL_LINE } from '@/config/approval-line';
import RequirePermission from '@/components/helper/RequirePermission'; import RequirePermission from '@/components/helper/RequirePermission';
import { BaseApproval } from '@/types/api/api-general'; import { BaseApproval } from '@/types/api/api-general';
@@ -53,135 +54,126 @@ const ChickinFormKandang = ({
}; };
return ( return (
<section className='w-full h-full sm:w-[446px] overflow-y-auto'> <div className='h-full w-full flex flex-col overflow-x-hidden overflow-y-auto'>
{/* Header */}
<DrawerHeader <DrawerHeader
subtitle={`Chick In ${initialValues.kandang?.name ?? 'Kandang'}`} leftIcon='heroicons:chevron-left'
leftIcon='mdi:arrow-left'
leftIconHref={`/production/project-flock/detail?projectFlockId=${initialValues?.project_flock?.id}`} leftIconHref={`/production/project-flock/detail?projectFlockId=${initialValues?.project_flock?.id}`}
leftIconClassName='hover:text-gray-400'
subtitle={`Chick In ${initialValues.kandang?.name ?? 'Kandang'}`}
className='sticky top-0 z-10 bg-base-100'
/> />
{/* Informasi Kandang */} {approvals && !approvalsLoading && (
<div className='divider'></div> <ApprovalSteps approvals={approvals} />
<div className='px-4 pb-4 flex flex-col gap-4'> )}
<h2 className='text-xl font-semibold'>Informasi Kandang</h2>
{approvals && !approvalsLoading && ( {/* Informasi Kandang */}
<div className='mb-3 text-sm'> <div className='w-full p-4 flex flex-col gap-3 border-b border-base-content/10'>
<ApprovalSteps approvals={approvals} /> <h4 className='text-base font-medium text-base-content/50 font-roboto'>
</div> Informasi Kandang
)} </h4>
{/* Badge Row */} {/* Badge Row */}
<div className='flex flex-row gap-2'> <div className='flex flex-row gap-2'>
<Badge <StatusBadge
variant='soft' color='success'
color='primary' text='Active'
className={{ className={{ badge: 'w-fit text-nowrap' }}
badge: 'rounded-lg px-2', />
}}
>
<Icon icon='mdi:circle' width={12} height={12} color='primary' />{' '}
Aktif
</Badge>
<div className='divider divider-horizontal p-0 m-0'></div> <div className='divider divider-horizontal p-0 m-0'></div>
<Badge <StatusBadge
color='neutral' color='neutral'
variant='soft' text={` Kapasitas ${formatNumber(initialValues.kandang.capacity)} Ekor`}
className={{ badge: 'rounded-lg px-2' }} className={{ badge: 'w-fit text-nowrap' }}
> />
<Icon icon='mdi:home' width={12} height={12} />
{` Kapasitas ${formatNumber(initialValues.kandang.capacity)} Ekor`}
</Badge>
</div> </div>
{/* Information Grid */} {/* Information Card */}
<div className='grid grid-cols-3 gap-4'> <Card
{/* Area */} variant='bordered'
<div className={{
className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2 wrapper: 'w-full rounded-lg',
relative body: 'p-3',
before:content-[""] before:absolute before:left-[5px] before:top-[90%] before:bottom-[-100%] before:w-[1px] before:border-1 before:border-dashed before:border-gray-400' }}
> >
<Icon width={14} height={14} icon='mdi:circle-slice-8' /> Area <div className='flex flex-col gap-6'>
<div className='flex flex-row justify-between items-center'>
<div className='flex flex-row gap-2 items-center text-gray-400'>
<Icon icon={'mdi:circle-slice-8'} width={14} height={14} />{' '}
<span>Area</span>
</div>
<div className='text-end text-gray-500'>
{initialValues.project_flock.area.name}
</div>
</div>
<div className='flex flex-row justify-between items-center'>
<div className='flex flex-row gap-2 items-center text-gray-400'>
<Icon icon={'mdi:circle-slice-8'} width={14} height={14} />{' '}
<span>Lokasi</span>
</div>
<div className='text-end text-gray-500'>
{initialValues.project_flock?.location.name}
</div>
</div>
<div className='flex flex-row justify-between items-center'>
<div className='flex flex-row gap-2 items-center text-gray-400'>
<Icon icon={'mdi:circle-slice-8'} width={14} height={14} />{' '}
<span>Kandang</span>
</div>
<div className='text-end text-gray-500'>
{initialValues.kandang.name}
</div>
</div>
<div className='flex flex-row justify-between items-center'>
<div className='flex flex-row gap-2 items-center text-gray-400'>
<Icon icon={'mdi:circle-slice-8'} width={14} height={14} />{' '}
<span>Jumlah DOC</span>
</div>
<div className='text-end text-gray-500'>
{formatNumber(
initialValues.chickins?.reduce(
(total, chickin) => total + chickin.usage_qty,
0
) ?? 0
)}{' '}
Ekor
</div>
</div>
</div> </div>
<div className='col-span-2'> </Card>
{initialValues.project_flock.area.name}
</div>
{/* Lokasi */}
<div
className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2
relative
before:content-[""] before:absolute before:left-[5px] before:top-[90%] before:bottom-[-100%] before:w-[1px] before:border-1 before:border-dashed before:border-gray-400'
>
<Icon width={14} height={14} icon='mdi:circle-slice-8' /> Lokasi
</div>
<div className='col-span-2'>
{initialValues.project_flock?.location.name}
</div>
{/* Kandang */}
<div
className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2
relative
before:content-[""] before:absolute before:left-[5px] before:top-[90%] before:bottom-[-100%] before:w-[1px] before:border-1 before:border-dashed before:border-gray-400'
>
<Icon width={14} height={14} icon='mdi:circle-slice-8' /> Kandang
</div>
<div className='col-span-2'>{initialValues.kandang.name}</div>
{/* Jumlah DOC */}
<div className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2'>
<Icon width={14} height={14} icon='mdi:circle-slice-8' /> Jumlah DOC
</div>
<div className='col-span-2'>
{formatNumber(
initialValues.chickins?.reduce(
(total, chickin) => total + chickin.usage_qty,
0
) ?? 0
)}{' '}
Ekor
</div>
</div>
</div> </div>
<div className='divider'></div> {/* Informasi Chick In */}
<div className='px-4 pb-4 flex flex-col gap-4'> <div className='w-full p-4 flex flex-col gap-3 border-b border-base-content/10'>
<h2 className='text-xl font-semibold'>Informasi Chick In</h2> <h4 className='text-base font-medium text-base-content/50 font-roboto'>
Informasi Chick In
</h4>
{/* Badge Row */} {/* Badge Row */}
<div className='flex flex-row gap-2'> <div className='flex flex-row gap-2'>
<RequirePermission permissions='lti.production.chickins.create'> <RequirePermission permissions='lti.production.chickins.create'>
<Badge <StatusBadge
variant='soft' color='success'
color={'success'} text={`Perlu Chick In (${initialValues.available_qtys?.length ?? 0})`}
className={{ className={{ badge: 'w-fit text-nowrap' }}
badge: 'rounded-lg px-2', />
}}
>
<Icon
icon='mdi:circle'
width={12}
height={12}
color={'success'}
/>{' '}
Perlu Chick In ({initialValues.available_qtys?.length ?? 0})
</Badge>
<div className='divider divider-horizontal p-0 m-0'></div> <div className='divider divider-horizontal p-0 m-0'></div>
</RequirePermission> </RequirePermission>
<Badge <StatusBadge
color='neutral' color='neutral'
variant='soft'
className={{ badge: 'rounded-lg px-2 cursor-pointer' }}
onClick={() => setOpenChickin(!openChickin)} onClick={() => setOpenChickin(!openChickin)}
> text={
{`Riwayat Chick In ${formatNumber(initialValues.chickins?.length ?? 0)}`} <>
<Icon {`Riwayat Chick In ${formatNumber(initialValues.chickins?.length ?? 0)}`}
icon={`mdi:${openChickin ? 'eye' : 'eye-off'}`} <Icon
width={12} icon={`mdi:${openChickin ? 'eye' : 'eye-off'}`}
height={12} width={12}
/> height={12}
</Badge> />
</>
}
className={{ badge: 'w-fit text-nowrap cursor-pointer' }}
/>
</div> </div>
</div> </div>
{openChickin && ( {openChickin && (
@@ -198,7 +190,7 @@ const ChickinFormKandang = ({
afterSubmit={afterSubmitFormChickin} afterSubmit={afterSubmitFormChickin}
/> />
</RequirePermission> </RequirePermission>
</section> </div>
); );
}; };
@@ -1,10 +1,12 @@
'use client'; 'use client';
import Button from '@/components/Button'; import Button from '@/components/Button';
import Card from '@/components/Card';
import DrawerHeader from '@/components/helper/drawer/DrawerHeader'; import DrawerHeader from '@/components/helper/drawer/DrawerHeader';
import Table from '@/components/Table'; import Table from '@/components/Table';
import Badge from '@/components/Badge'; import Badge from '@/components/Badge';
import { cn, formatDate, formatNumber, formatTitleCase } from '@/lib/helper'; import StatusBadge from '@/components/helper/StatusBadge';
import { formatDate, formatNumber, formatTitleCase } from '@/lib/helper';
import { ProjectFlock } from '@/types/api/production/project-flock'; import { ProjectFlock } from '@/types/api/production/project-flock';
import { import {
ClosingExpense, ClosingExpense,
@@ -20,9 +22,28 @@ import ConfirmationModal from '@/components/modal/ConfirmationModal';
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { ProductWarehouse } from '@/types/api/inventory/product-warehouse';
import { ApprovalApi } from '@/services/api/approval'; import { ApprovalApi } from '@/services/api/approval';
import RequirePermission from '@/components/helper/RequirePermission'; import RequirePermission from '@/components/helper/RequirePermission';
import { Color } from '@/types/theme';
const getExpenseStatusBadgeColor = (step: number): Color => {
switch (step) {
case 1:
return 'neutral';
case 2:
return 'info';
case 3:
return 'warning';
case 4:
return 'error';
case 5:
return 'warning';
case 6:
return 'success';
default:
return 'neutral';
}
};
const ProjectFlockClosingForm = ({ const ProjectFlockClosingForm = ({
projectFlock, projectFlock,
@@ -49,6 +70,10 @@ const ProjectFlockClosingForm = ({
) )
); );
const isKandangClosed = useMemo(() => {
return projectFlockKandang.kandang?.status === 'NON_ACTIVE';
}, [projectFlockKandang]);
const isCanClose = useMemo(() => { const isCanClose = useMemo(() => {
return isResponseSuccess(projectFlockKandangApprovals) return isResponseSuccess(projectFlockKandangApprovals)
? projectFlockKandangApprovals?.data?.[0]?.step_number <= 2 ? projectFlockKandangApprovals?.data?.[0]?.step_number <= 2
@@ -60,8 +85,10 @@ const ProjectFlockClosingForm = ({
const deleteProjectFlockRes = await ProjectFlockKandangApi.closing( const deleteProjectFlockRes = await ProjectFlockKandangApi.closing(
projectFlockKandang?.id as number, projectFlockKandang?.id as number,
{ {
closed_date: isCanClose ? formatDate(new Date(), 'YYYY-MM-DD') : '', closed_date: !isKandangClosed
action: isCanClose ? 'close' : 'unclose', ? formatDate(new Date(), 'YYYY-MM-DD')
: '',
action: !isKandangClosed ? 'close' : 'unclose',
} }
); );
@@ -78,160 +105,167 @@ const ProjectFlockClosingForm = ({
closeModal.closeModal(); closeModal.closeModal();
}; };
const errorStock = useMemo(() => { // const errorStock = useMemo(() => {
return isResponseSuccess(closingData) // return isResponseSuccess(closingData)
? closingData?.data?.stock_remaining.every((stock) => stock.quantity > 0) // ? closingData?.data?.stock_remaining.every((stock) => stock.quantity > 0)
: true; // : true;
}, [closingData]); // }, [closingData]);
const errorExpense = useMemo(() => { // const errorExpense = useMemo(() => {
return isResponseSuccess(closingData) // return isResponseSuccess(closingData)
? closingData?.data?.expenses.every((expense) => expense.step < 5) // ? closingData?.data?.expenses.every((expense) => expense.step < 5)
: true; // : true;
}, [closingData]); // }, [closingData]);
const isCanCloseValid = true; const isCanCloseValid = true;
return ( return (
<> <>
<section className='w-full h-full sm:w-[446px] overflow-y-auto'> <div className='h-full w-full flex flex-col overflow-x-hidden overflow-y-auto'>
{/* Header */}
<DrawerHeader <DrawerHeader
leftIcon='mdi:arrow-left' leftIcon='heroicons:chevron-left'
leftIconHref={`/production/project-flock/detail?projectFlockId=${projectFlock.id}`} leftIconHref={`/production/project-flock/detail?projectFlockId=${projectFlock.id}`}
subtitle={`Close ${projectFlock.flock_name}`} leftIconClassName='hover:text-gray-400'
></DrawerHeader> subtitle={isKandangClosed ? 'Unclose Flock' : 'Close Flock'}
className='sticky top-0 z-10 bg-base-100'
/>
{/* Informasi Kandang */} {/* Informasi Kandang */}
<div className='divider'></div> <div className='w-full p-4 flex flex-col gap-3 border-b border-base-content/10'>
<div className='px-4 pb-4 flex flex-col gap-4'> <h4 className='text-base font-medium text-base-content/50 font-roboto'>
<h2 className='text-2xl font-semibold'>Informasi Kandang</h2> Informasi Kandang
</h4>
{/* Badge Row */} {/* Badge Row */}
<div className='flex flex-row gap-2'> <div className='flex flex-row gap-2'>
<Badge <StatusBadge
variant='soft' color={isKandangClosed ? 'error' : 'success'}
color='success' text={isKandangClosed ? 'Closed' : 'Active'}
className={{ className={{ badge: 'w-fit text-nowrap' }}
badge: 'rounded-lg px-2', />
}}
>
<Icon icon='mdi:circle' width={12} height={12} color='success' />{' '}
Aktif
</Badge>
<div className='divider divider-horizontal p-0 m-0'></div> <div className='divider divider-horizontal p-0 m-0'></div>
<Badge <StatusBadge
color='neutral' color='neutral'
variant='soft' text={` Kapasitas ${formatNumber(projectFlockKandang.kandang?.capacity)} Ekor`}
className={{ badge: 'rounded-lg px-2' }} className={{ badge: 'w-fit text-nowrap' }}
> />
<Icon icon='mdi:home' width={12} height={12} />
{` Kapasitas ${formatNumber(projectFlockKandang.kandang?.capacity)} Ekor`}
</Badge>
</div> </div>
{/* Information Grid */} {/* Information Card */}
<div className='grid grid-cols-3 gap-4'> <Card
{/* Area */} variant='bordered'
<div className={{
className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2 wrapper: 'w-full rounded-lg',
relative body: 'p-3',
before:content-[""] before:absolute before:left-[5px] before:top-[90%] before:bottom-[-100%] before:w-[1px] before:border-1 before:border-dashed before:border-gray-400' }}
> >
<Icon width={14} height={14} icon='mdi:circle-slice-8' /> Area <div className='flex flex-col gap-6'>
<div className='flex flex-row justify-between items-center'>
<div className='flex flex-row gap-2 items-center text-gray-400'>
<Icon icon={'mdi:circle-slice-8'} width={14} height={14} />{' '}
<span>Area</span>
</div>
<div className='text-end text-gray-500'>
{projectFlock.area?.name}
</div>
</div>
<div className='flex flex-row justify-between items-center'>
<div className='flex flex-row gap-2 items-center text-gray-400'>
<Icon icon={'mdi:circle-slice-8'} width={14} height={14} />{' '}
<span>Lokasi</span>
</div>
<div className='text-end text-gray-500'>
{projectFlock.location?.name}
</div>
</div>
<div className='flex flex-row justify-between items-center'>
<div className='flex flex-row gap-2 items-center text-gray-400'>
<Icon icon={'mdi:circle-slice-8'} width={14} height={14} />{' '}
<span>Kandang</span>
</div>
<div className='text-end text-gray-500'>
{projectFlockKandang.kandang?.name}
</div>
</div>
<div className='flex flex-row justify-between items-center'>
<div className='flex flex-row gap-2 items-center text-gray-400'>
<Icon icon={'mdi:circle-slice-8'} width={14} height={14} />{' '}
<span>Jumlah DOC</span>
</div>
<div className='text-end text-gray-500'>
{formatNumber(
projectFlockKandang.chickins?.reduce(
(total, chickin) => total + chickin.usage_qty,
0
) ?? 0
)}{' '}
Ekor
</div>
</div>
</div> </div>
<div className='col-span-2'>{projectFlock.area?.name}</div> </Card>
{/* Lokasi */}
<div
className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2
relative
before:content-[""] before:absolute before:left-[5px] before:top-[90%] before:bottom-[-100%] before:w-[1px] before:border-1 before:border-dashed before:border-gray-400'
>
<Icon width={14} height={14} icon='mdi:circle-slice-8' /> Lokasi
</div>
<div className='col-span-2'>{projectFlock.location?.name}</div>
{/* Kandang */}
<div
className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2
relative
before:content-[""] before:absolute before:left-[5px] before:top-[90%] before:bottom-[-100%] before:w-[1px] before:border-1 before:border-dashed before:border-gray-400'
>
<Icon width={14} height={14} icon='mdi:circle-slice-8' /> Kandang
</div>
<div className='col-span-2'>
{projectFlockKandang.kandang?.name}
</div>
{/* Jumlah DOC */}
<div className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2'>
<Icon width={14} height={14} icon='mdi:circle-slice-8' /> Jumlah
DOC
</div>
<div className='col-span-2'>
{formatNumber(
projectFlockKandang.chickins?.reduce(
(total, chickin) => total + chickin.usage_qty,
0
) ?? 0
)}{' '}
Ekor
</div>
</div>
</div> </div>
{/* Table Biaya */} {/* Table Biaya */}
<div className='divider'></div> <div className='w-full p-4 flex flex-col gap-3 border-b border-base-content/10'>
<div className='px-4 pb-4'> <h4 className='text-base font-medium text-base-content/50 font-roboto'>
<h2 className='text-2xl font-semibold'>Biaya</h2> Biaya
</h4>
<Table<ClosingExpense> <Table<ClosingExpense>
data={ data={
isResponseSuccess(closingData) ? closingData.data?.expenses : [] isResponseSuccess(closingData) ? closingData.data?.expenses : []
} }
columns={[ columns={[
{
header: 'Ref Number',
accessorKey: 'reference_number',
cell(props) {
return props.row.original.reference_number || '-';
},
},
{ {
header: 'PO Number', header: 'PO Number',
accessorKey: 'po_number', accessorKey: 'po_number',
cell(props) {
return props.row.original.po_number || '-';
},
}, },
{ {
header: 'Total', header: 'Total',
accessorKey: 'total', accessorKey: 'total',
cell(props) {
return formatNumber(props.row.original.total);
},
}, },
{ {
header: 'Status', header: 'Status',
accessorKey: 'status', accessorKey: 'status',
cell(props) { cell(props) {
return ( return (
<Badge <StatusBadge
color={getExpenseStatusBadgeColor(
props.row.original.step
)}
text={formatTitleCase(props.row.original.step_name)}
className={{ className={{
badge: 'rounded-lg', badge: 'whitespace-nowrap max-w-max w-fit',
}} }}
variant='soft' />
color={
props.row.original.step < 5
? props.row.original.step == 1
? 'neutral'
: 'success'
: 'error'
}
>
{formatTitleCase(props.row.original.step_name)}
</Badge>
); );
}, },
}, },
]} ]}
className={{ className={{
containerClassName: cn('my-4'), containerClassName: 'mb-0',
tableWrapperClassName: 'overflow-x-auto min-h-full! max-w-120', tableWrapperClassName: 'overflow-x-auto max-w-120',
tableClassName: 'font-inter w-full table-sm min-h-full!', tableClassName: 'font-inter w-full table-sm',
headerRowClassName: 'border-b border-b-gray-200', headerRowClassName: 'border-b border-base-content/10',
headerColumnClassName: headerColumnClassName:
'px-3 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', 'px-3 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
bodyRowClassName: 'border-b border-b-gray-200', bodyRowClassName: 'border-b border-base-content/10',
bodyColumnClassName: bodyColumnClassName:
'px-3 py-3 last:flex last:flex-row last:justify-end', 'px-3 py-3 last:flex last:flex-row last:justify-end',
paginationClassName: 'hidden',
}} }}
/> />
{/* {errorExpense && ( {/* {errorExpense && (
@@ -242,9 +276,10 @@ const ProjectFlockClosingForm = ({
</div> </div>
{/* Table Persediaan Gudang */} {/* Table Persediaan Gudang */}
<div className='divider'></div> <div className='w-full p-4 flex flex-col gap-3 border-b border-base-content/10'>
<div className='px-4 pb-4'> <h4 className='text-base font-medium text-base-content/50 font-roboto'>
<h2 className='text-2xl font-semibold'>Persediaan Gudang</h2> Persediaan Gudang
</h4>
<Table<StockItem> <Table<StockItem>
data={ data={
isResponseSuccess(closingData) isResponseSuccess(closingData)
@@ -263,6 +298,9 @@ const ProjectFlockClosingForm = ({
{ {
header: 'Quantity', header: 'Quantity',
accessorKey: 'quantity', accessorKey: 'quantity',
cell(props) {
return formatNumber(props.row.original.quantity);
},
}, },
{ {
header: 'UOM', header: 'UOM',
@@ -270,16 +308,15 @@ const ProjectFlockClosingForm = ({
}, },
]} ]}
className={{ className={{
containerClassName: cn('my-4'), containerClassName: 'mb-0',
tableWrapperClassName: 'overflow-x-auto min-h-full! max-w-120', tableWrapperClassName: 'overflow-x-auto max-w-120',
tableClassName: 'font-inter w-full table-sm min-h-full!', tableClassName: 'font-inter w-full table-sm',
headerRowClassName: 'border-b border-b-gray-200', headerRowClassName: 'border-b border-base-content/10',
headerColumnClassName: headerColumnClassName:
'px-3 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', 'px-3 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
bodyRowClassName: 'border-b border-b-gray-200', bodyRowClassName: 'border-b border-base-content/10',
bodyColumnClassName: bodyColumnClassName:
'px-3 py-3 last:flex last:flex-row last:justify-end', 'px-3 py-3 last:flex last:flex-row last:justify-end',
paginationClassName: 'hidden',
}} }}
/> />
{/* {errorStock && ( {/* {errorStock && (
@@ -289,17 +326,24 @@ const ProjectFlockClosingForm = ({
)} */} )} */}
</div> </div>
<div className='p-4 mt-6'> <div className='p-4'>
<RequirePermission permissions='lti.production.project_flock_kandangs.closing'> <RequirePermission permissions='lti.production.project_flock_kandangs.closing'>
<Button <Button
className='w-full' className='w-full'
variant='outline'
color='error' color='error'
isLoading={isLoading} isLoading={isLoading}
disabled={!isCanCloseValid} disabled={!isCanCloseValid}
onClick={() => closeModal.openModal()} onClick={() => closeModal.openModal()}
> >
<Icon icon='mdi:checkbox-marked-circle-outline' />{' '} <Icon
{isCanClose ? 'Close' : 'Unclose'} icon={
isKandangClosed
? 'mdi:lock-open-variant'
: 'mdi:checkbox-marked-circle-outline'
}
/>{' '}
{isKandangClosed ? 'Unclose' : 'Close'}
</Button> </Button>
</RequirePermission> </RequirePermission>
</div> </div>
@@ -308,7 +352,7 @@ const ProjectFlockClosingForm = ({
ref={closeModal.ref} ref={closeModal.ref}
type='error' type='error'
text={ text={
isCanClose !isKandangClosed
? 'Apakah kamu yakin ingin mengakhiri project ini ? *Pastikan persediaan produk di gudang terkait sudah kosong, dan BOP sudah selesai' ? 'Apakah kamu yakin ingin mengakhiri project ini ? *Pastikan persediaan produk di gudang terkait sudah kosong, dan BOP sudah selesai'
: 'Apakah kamu yakin ingin membuka kembali project ini ? *Project ini akan kembali ke status aktif' : 'Apakah kamu yakin ingin membuka kembali project ini ? *Project ini akan kembali ke status aktif'
} }
@@ -322,7 +366,7 @@ const ProjectFlockClosingForm = ({
onClick: confirmationModalCloseClickHandler, onClick: confirmationModalCloseClickHandler,
}} }}
/> />
</section> </div>
</> </>
); );
}; };
@@ -226,15 +226,37 @@ const ProjectFlockDetail = ({
<div className='w-full p-4 flex flex-col gap-3 border-b border-base-content/10'> <div className='w-full p-4 flex flex-col gap-3 border-b border-base-content/10'>
<h4 className='text-base font-medium text-base-content/50 font-roboto'> <h4 className='text-base font-medium text-base-content/50 font-roboto'>
Kandang Aktif Kandang
</h4> </h4>
<div className='flex flex-row gap-2'> <div className='flex flex-row flex-wrap gap-2 overflow-hidden'>
<StatusBadge {projectFlock.kandangs?.filter(
color='info' (kandang) => kandang.status !== 'NON_ACTIVE'
text={`Kandang Aktif (${projectFlock.kandangs?.length})`} ).length > 0 && (
className={{ badge: 'w-fit text-nowrap' }} <StatusBadge
/> color='success'
text={`Kandang Active (${
projectFlock.kandangs?.filter(
(kandang) => kandang.status !== 'NON_ACTIVE'
).length ?? 0
})`}
className={{ badge: 'w-fit' }}
/>
)}
{projectFlock.kandangs?.filter(
(kandang) => kandang.status === 'NON_ACTIVE'
).length > 0 && (
<StatusBadge
color='error'
text={`Kandang Closed (${
projectFlock.kandangs?.filter(
(kandang) => kandang.status === 'NON_ACTIVE'
).length ?? 0
})`}
className={{ badge: 'w-fit' }}
/>
)}
<StatusBadge <StatusBadge
color='neutral' color='neutral'
@@ -256,7 +278,7 @@ const ProjectFlockDetail = ({
/> />
</> </>
} }
className={{ badge: 'w-fit text-nowrap cursor-pointer' }} className={{ badge: 'w-fit cursor-pointer' }}
/> />
</div> </div>
@@ -355,43 +377,53 @@ const ProjectFlockDetail = ({
disabled={projectFlock?.approval?.step_number == 1} disabled={projectFlock?.approval?.step_number == 1}
/> />
<div className='text-end'> <div className='text-end'>
<Badge <StatusBadge
className={{ color={
badge: 'rounded-lg', kandang?.status === 'NON_ACTIVE' ? 'error' : 'success'
}} }
> text={<>Kapasitas {kandang?.capacity} Ekor</>}
Kapasitas {kandang?.capacity} Ekor className={{ badge: 'w-fit text-nowrap' }}
</Badge> />
</div> </div>
</div> </div>
))} ))}
</RadioGroup> </RadioGroup>
</Card> </Card>
<ApprovalStepsV2 <div className='-mx-4'>
approvals={projectFlockKandangApproval} <ApprovalStepsV2
steps={APPROVAL_WORKFLOWS.PROJECT_FLOCK_KANDANGS} approvals={projectFlockKandangApproval}
/> steps={APPROVAL_WORKFLOWS.PROJECT_FLOCK_KANDANGS}
/>
</div>
<div className='grid grid-cols-4 gap-3'> <div
<RequirePermission permissions='lti.production.chickins.detail'> className={`grid gap-3 ${
<Link selectedKandang?.status !== 'NON_ACTIVE'
href={`/production/project-flock/chickin/add/kandang?projectFlockKandangId=${selectedKandang?.project_flock_kandang_id}&projectFlockId=${projectFlock.id}`} ? 'grid-cols-2'
className='m-0 p-0' : 'grid-cols-1'
> }`}
<Button >
className='w-full px-2 py-1 text-sm' {selectedKandang?.status !== 'NON_ACTIVE' && (
variant='outline' <RequirePermission permissions='lti.production.chickins.detail'>
color='success' <Link
disabled={ href={`/production/project-flock/chickin/add/kandang?projectFlockKandangId=${selectedKandang?.project_flock_kandang_id}&projectFlockId=${projectFlock.id}`}
!selectedKandangId || className='m-0 p-0'
projectFlock?.approval?.step_number == 1
}
> >
Chickin <Icon icon='mdi:checkbox-marked-outline' /> <Button
</Button> className='w-full px-2 py-1 text-sm'
</Link> variant='outline'
</RequirePermission> color='success'
disabled={
!selectedKandangId ||
projectFlock?.approval?.step_number == 1
}
>
Chickin <Icon icon='mdi:checkbox-marked-outline' />
</Button>
</Link>
</RequirePermission>
)}
<RequirePermission permissions='lti.production.project_flock_kandangs.closing.detail'> <RequirePermission permissions='lti.production.project_flock_kandangs.closing.detail'>
<Link <Link
href={`/production/project-flock/closing?projectFlockId=${projectFlock.id}&projectFlockKandangId=${selectedKandang?.project_flock_kandang_id}`} href={`/production/project-flock/closing?projectFlockId=${projectFlock.id}&projectFlockKandangId=${selectedKandang?.project_flock_kandang_id}`}
@@ -406,7 +438,15 @@ const ProjectFlockDetail = ({
projectFlock?.approval?.step_number == 1 projectFlock?.approval?.step_number == 1
} }
> >
Close <Icon icon='mdi:checkbox-marked-circle-outline' /> {selectedKandang?.status === 'NON_ACTIVE' ? (
<>
Unclose <Icon icon='mdi:lock-open-variant' />
</>
) : (
<>
Close <Icon icon='mdi:checkbox-marked-circle-outline' />
</>
)}
</Button> </Button>
</Link> </Link>
</RequirePermission> </RequirePermission>