mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE): Add Production Standard modal and table
This commit is contained in:
@@ -30,8 +30,12 @@ import {
|
||||
RecordingApi,
|
||||
ProjectFlockApi,
|
||||
} from '@/services/api/production';
|
||||
import { FcrApi } from '@/services/api/master-data';
|
||||
import { FcrApi, ProductionStandardApi } from '@/services/api/master-data';
|
||||
import { FcrWithStandards, FcrStandard } from '@/types/api/master-data/fcr';
|
||||
import {
|
||||
ProductionStandard,
|
||||
StandardDetails,
|
||||
} from '@/types/api/master-data/production-standard';
|
||||
import { LocationApi } from '@/services/api/master-data';
|
||||
import { ProductWarehouseApi } from '@/services/api/inventory';
|
||||
import { ProductWarehouse } from '@/types/api/inventory/product-warehouse';
|
||||
@@ -98,6 +102,94 @@ const fcrStandardColumns: ColumnDef<FcrStandard>[] = [
|
||||
},
|
||||
];
|
||||
|
||||
const productionStandardColumns: ColumnDef<StandardDetails>[] = [
|
||||
{
|
||||
accessorKey: 'week',
|
||||
header: 'Minggu',
|
||||
cell: (props) => `Minggu ${props.getValue() as number}`,
|
||||
},
|
||||
{
|
||||
accessorKey: 'growth_standard_detail.target_mean_bw',
|
||||
header: 'Target Mean BW (gram)',
|
||||
cell: (props) =>
|
||||
formatNumber(
|
||||
(props.row.original.growth_standard_detail?.target_mean_bw as number) ||
|
||||
0
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: 'growth_standard_detail.max_depletion',
|
||||
header: 'Max Depletion (%)',
|
||||
cell: (props) =>
|
||||
`${
|
||||
(props.row.original.growth_standard_detail?.max_depletion as number) ||
|
||||
0
|
||||
}%`,
|
||||
},
|
||||
{
|
||||
accessorKey: 'growth_standard_detail.min_uniformity',
|
||||
header: 'Min Uniformity (%)',
|
||||
cell: (props) =>
|
||||
`${
|
||||
(props.row.original.growth_standard_detail?.min_uniformity as number) ||
|
||||
0
|
||||
}%`,
|
||||
},
|
||||
{
|
||||
accessorKey: 'growth_standard_detail.feed_intake',
|
||||
header: 'Feed Intake (gram)',
|
||||
cell: (props) =>
|
||||
formatNumber(
|
||||
(props.row.original.growth_standard_detail?.feed_intake as number) || 0
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: 'egg_production_standard_detail.target_hen_day_production',
|
||||
header: 'Target Hen Day (%)',
|
||||
cell: (props) =>
|
||||
`${
|
||||
(props.row.original.egg_production_standard_detail
|
||||
?.target_hen_day_production as number) || 0
|
||||
}%`,
|
||||
},
|
||||
{
|
||||
accessorKey: 'egg_production_standard_detail.target_hen_house_production',
|
||||
header: 'Target Hen House (%)',
|
||||
cell: (props) =>
|
||||
`${
|
||||
(props.row.original.egg_production_standard_detail
|
||||
?.target_hen_house_production as number) || 0
|
||||
}%`,
|
||||
},
|
||||
{
|
||||
accessorKey: 'egg_production_standard_detail.target_egg_weight',
|
||||
header: 'Target Egg Weight (gram)',
|
||||
cell: (props) =>
|
||||
formatNumber(
|
||||
(props.row.original.egg_production_standard_detail
|
||||
?.target_egg_weight as number) || 0
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: 'egg_production_standard_detail.target_egg_mass',
|
||||
header: 'Target Egg Mass (gram)',
|
||||
cell: (props) =>
|
||||
formatNumber(
|
||||
(props.row.original.egg_production_standard_detail
|
||||
?.target_egg_mass as number) || 0
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: 'egg_production_standard_detail.standard_fcr',
|
||||
header: 'Standard FCR',
|
||||
cell: (props) =>
|
||||
formatNumber(
|
||||
(props.row.original.egg_production_standard_detail
|
||||
?.standard_fcr as number) || 0
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
// ===== HOOKS & ROUTER =====
|
||||
const router = useRouter();
|
||||
@@ -147,8 +239,12 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
const productionStandardModal = useModal();
|
||||
|
||||
const [fcrStandards, setFcrStandards] = useState<FcrStandard[]>([]);
|
||||
const [productionStandards, setProductionStandards] =
|
||||
useState<ProductionStandard | null>(null);
|
||||
|
||||
const [isFcrModalOpen, setIsFcrModalOpen] = useState(false);
|
||||
const [isProductionStandardModalOpen, setIsProductionStandardModalOpen] =
|
||||
useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const checkFcrModalOpen = () => {
|
||||
@@ -169,6 +265,25 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
return () => observer.disconnect();
|
||||
}, [fcrStandardModal.ref]);
|
||||
|
||||
useEffect(() => {
|
||||
const checkProductionStandardModalOpen = () => {
|
||||
const isOpen = productionStandardModal.ref.current?.open || false;
|
||||
setIsProductionStandardModalOpen(isOpen);
|
||||
};
|
||||
|
||||
checkProductionStandardModalOpen();
|
||||
|
||||
const observer = new MutationObserver(checkProductionStandardModalOpen);
|
||||
if (productionStandardModal.ref.current) {
|
||||
observer.observe(productionStandardModal.ref.current, {
|
||||
attributes: true,
|
||||
attributeFilter: ['open'],
|
||||
});
|
||||
}
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, [productionStandardModal.ref]);
|
||||
|
||||
const { data: fcr, isLoading: isLoadingFcrStandards } = useSWR(
|
||||
isFcrModalOpen && initialValues?.project_flock?.fcr?.id
|
||||
? `fcr-detail-${initialValues.project_flock.fcr.id}`
|
||||
@@ -182,6 +297,26 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
}
|
||||
}, [fcr]);
|
||||
|
||||
const { data: productionStandard, isLoading: isLoadingProductionStandards } =
|
||||
useSWR(
|
||||
isProductionStandardModalOpen &&
|
||||
initialValues?.project_flock?.production_standart?.id
|
||||
? `production-standard-detail-${initialValues.project_flock.production_standart.id}`
|
||||
: null,
|
||||
() =>
|
||||
ProductionStandardApi.getSingle(
|
||||
initialValues!.project_flock!.production_standart!.id!
|
||||
)
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (productionStandard?.status === 'success') {
|
||||
setProductionStandards(
|
||||
productionStandard.data as ProductionStandard | null
|
||||
);
|
||||
}
|
||||
}, [productionStandard]);
|
||||
|
||||
const isRecordingApproved = useCallback((recording?: Recording) => {
|
||||
return (
|
||||
recording?.approval?.action === 'APPROVED' &&
|
||||
@@ -2828,10 +2963,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
|
||||
{/* Production Standard Modal */}
|
||||
<Modal
|
||||
closeOnBackdrop={true}
|
||||
ref={productionStandardModal.ref}
|
||||
className={{
|
||||
modal: 'p-0',
|
||||
modalBox: 'p-0 rounded-2xl xl:max-w-4/12 max-w-sm',
|
||||
modalBox: 'p-0 rounded-2xl xl:max-w-full max-w-sm',
|
||||
}}
|
||||
>
|
||||
<div className='space-y-6'>
|
||||
@@ -2849,81 +2985,35 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
||||
</Button>
|
||||
</div>
|
||||
<div className='space-y-4 px-4 pb-4'>
|
||||
<div>
|
||||
<span className='text-sm text-gray-600'>Nama Standard</span>
|
||||
<p className='font-semibold'>
|
||||
{initialValues?.project_flock?.production_standart?.name || '-'}
|
||||
<div className='px-4'>
|
||||
{isLoadingProductionStandards ? (
|
||||
<div className='flex justify-center py-8'>
|
||||
<span className='loading loading-spinner loading-lg'></span>
|
||||
</div>
|
||||
) : productionStandards?.details &&
|
||||
productionStandards.details.length > 0 ? (
|
||||
<Table<StandardDetails>
|
||||
data={productionStandards.details}
|
||||
columns={productionStandardColumns}
|
||||
pageSize={100}
|
||||
className={{
|
||||
tableWrapperClassName: 'overflow-x-auto',
|
||||
tableClassName: 'w-full table-auto text-sm',
|
||||
headerRowClassName: 'border-b border-b-gray-200',
|
||||
headerColumnClassName:
|
||||
'px-4 py-3 text-xs font-semibold text-gray-500 whitespace-nowrap border-l border-l-gray-200 border-r border-r-gray-200 border-t border-t-gray-200 border-gray-200 border-b-0',
|
||||
bodyRowClassName:
|
||||
'hover:bg-gray-50 transition-colors border-b border-gray-200 first:border-t first:border-t-gray-200 border-l border-l-gray-200 border-r border-r-gray-200',
|
||||
bodyColumnClassName:
|
||||
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
|
||||
paginationClassName: 'hidden',
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<p className='text-sm text-gray-500'>
|
||||
Tidak ada data Production standards
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<span className='text-sm text-gray-600'>Minggu</span>
|
||||
<p className='font-semibold'>
|
||||
{initialValues?.project_flock?.production_standart?.week || '-'}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<span className='text-sm text-gray-600'>
|
||||
Hen Day Standard (%)
|
||||
</span>
|
||||
<p className='font-semibold'>
|
||||
{initialValues?.project_flock?.production_standart
|
||||
?.hen_day_std != null
|
||||
? `${initialValues?.project_flock?.production_standart?.hen_day_std}%`
|
||||
: '-'}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<span className='text-sm text-gray-600'>
|
||||
Hen House Standard (%)
|
||||
</span>
|
||||
<p className='font-semibold'>
|
||||
{initialValues?.project_flock?.production_standart
|
||||
?.hen_house_std != null
|
||||
? `${initialValues?.project_flock?.production_standart?.hen_house_std}%`
|
||||
: '-'}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<span className='text-sm text-gray-600'>
|
||||
Feed Intake Standard (KG)
|
||||
</span>
|
||||
<p className='font-semibold'>
|
||||
{initialValues?.project_flock?.production_standart
|
||||
?.feed_intake_std != null
|
||||
? formatNumber(
|
||||
initialValues?.project_flock?.production_standart
|
||||
?.feed_intake_std || 0
|
||||
)
|
||||
: '-'}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<span className='text-sm text-gray-600'>Egg Mass Standard</span>
|
||||
<p className='font-semibold'>
|
||||
{initialValues?.project_flock?.production_standart
|
||||
?.egg_mass_std != null
|
||||
? formatNumber(
|
||||
initialValues?.project_flock?.production_standart
|
||||
?.egg_mass_std || 0
|
||||
)
|
||||
: '-'}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<span className='text-sm text-gray-600'>
|
||||
Egg Weight Standard (KG)
|
||||
</span>
|
||||
<p className='font-semibold'>
|
||||
{initialValues?.project_flock?.production_standart
|
||||
?.egg_weight_std != null
|
||||
? formatNumber(
|
||||
initialValues?.project_flock?.production_standart
|
||||
?.egg_weight_std || 0
|
||||
)
|
||||
: '-'}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
Reference in New Issue
Block a user