mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 23:35:45 +00:00
feat(FE): Add Production Standard modal and table
This commit is contained in:
@@ -30,8 +30,12 @@ import {
|
|||||||
RecordingApi,
|
RecordingApi,
|
||||||
ProjectFlockApi,
|
ProjectFlockApi,
|
||||||
} from '@/services/api/production';
|
} 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 { 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 { LocationApi } from '@/services/api/master-data';
|
||||||
import { ProductWarehouseApi } from '@/services/api/inventory';
|
import { ProductWarehouseApi } from '@/services/api/inventory';
|
||||||
import { ProductWarehouse } from '@/types/api/inventory/product-warehouse';
|
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) => {
|
const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||||
// ===== HOOKS & ROUTER =====
|
// ===== HOOKS & ROUTER =====
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -147,8 +239,12 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
const productionStandardModal = useModal();
|
const productionStandardModal = useModal();
|
||||||
|
|
||||||
const [fcrStandards, setFcrStandards] = useState<FcrStandard[]>([]);
|
const [fcrStandards, setFcrStandards] = useState<FcrStandard[]>([]);
|
||||||
|
const [productionStandards, setProductionStandards] =
|
||||||
|
useState<ProductionStandard | null>(null);
|
||||||
|
|
||||||
const [isFcrModalOpen, setIsFcrModalOpen] = useState(false);
|
const [isFcrModalOpen, setIsFcrModalOpen] = useState(false);
|
||||||
|
const [isProductionStandardModalOpen, setIsProductionStandardModalOpen] =
|
||||||
|
useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const checkFcrModalOpen = () => {
|
const checkFcrModalOpen = () => {
|
||||||
@@ -169,6 +265,25 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
return () => observer.disconnect();
|
return () => observer.disconnect();
|
||||||
}, [fcrStandardModal.ref]);
|
}, [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(
|
const { data: fcr, isLoading: isLoadingFcrStandards } = useSWR(
|
||||||
isFcrModalOpen && initialValues?.project_flock?.fcr?.id
|
isFcrModalOpen && initialValues?.project_flock?.fcr?.id
|
||||||
? `fcr-detail-${initialValues.project_flock.fcr.id}`
|
? `fcr-detail-${initialValues.project_flock.fcr.id}`
|
||||||
@@ -182,6 +297,26 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
}
|
}
|
||||||
}, [fcr]);
|
}, [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) => {
|
const isRecordingApproved = useCallback((recording?: Recording) => {
|
||||||
return (
|
return (
|
||||||
recording?.approval?.action === 'APPROVED' &&
|
recording?.approval?.action === 'APPROVED' &&
|
||||||
@@ -2828,10 +2963,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
|
|
||||||
{/* Production Standard Modal */}
|
{/* Production Standard Modal */}
|
||||||
<Modal
|
<Modal
|
||||||
|
closeOnBackdrop={true}
|
||||||
ref={productionStandardModal.ref}
|
ref={productionStandardModal.ref}
|
||||||
className={{
|
className={{
|
||||||
modal: 'p-0',
|
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'>
|
<div className='space-y-6'>
|
||||||
@@ -2849,81 +2985,35 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className='space-y-4 px-4 pb-4'>
|
<div className='px-4'>
|
||||||
<div>
|
{isLoadingProductionStandards ? (
|
||||||
<span className='text-sm text-gray-600'>Nama Standard</span>
|
<div className='flex justify-center py-8'>
|
||||||
<p className='font-semibold'>
|
<span className='loading loading-spinner loading-lg'></span>
|
||||||
{initialValues?.project_flock?.production_standart?.name || '-'}
|
</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>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
Reference in New Issue
Block a user