mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
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:
@@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+166
-122
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user