From 3d3569bbc094a0132b755b2d83345520c4567ca2 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Thu, 6 Nov 2025 10:33:45 +0700 Subject: [PATCH] feat(FE-170,175): integrate ProjectFlockKandang API and enhance RecordingForm with detailed project flock and kandang options --- .../recording/form/RecordingForm.tsx | 416 +++++++++++------- 1 file changed, 264 insertions(+), 152 deletions(-) diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 571bd0db..6831a0c0 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -11,7 +11,10 @@ import NumberInput from '@/components/input/NumberInput'; import SelectInput, { OptionType } from '@/components/input/SelectInput'; import CheckboxInput from '@/components/input/CheckboxInput'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; -import { RecordingApi } from '@/services/api/production'; +import { + ProjectFlockKandangApi, + RecordingApi, +} from '@/services/api/production'; import { CreateGrowingRecordingPayload, CreateLayingRecordingPayload, @@ -36,6 +39,7 @@ import { ProductWarehouseApi } from '@/services/api/inventory'; import { isResponseSuccess, isResponseError } from '@/lib/api-helper'; import { cn, formatDate } from '@/lib/helper'; import { ProjectFlockKandangLookup } from '@/types/api/production/project-flock'; +import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang'; import { useModal } from '@/components/Modal'; import toast from 'react-hot-toast'; @@ -175,6 +179,26 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { ? projectFlockKandangLookupData.data : undefined; + const projectFlockKandangDetailUrl = useMemo(() => { + if (type === 'add' || !initialValues?.project_flock_kandang_id) return null; + return `${ProjectFlockKandangApi.basePath}/${initialValues.project_flock_kandang_id}`; + }, [type, initialValues?.project_flock_kandang_id]); + + const { data: projectFlockKandangDetailData } = useSWR( + projectFlockKandangDetailUrl, + projectFlockKandangDetailUrl + ? () => + ProjectFlockKandangApi.getAllFetcher( + projectFlockKandangDetailUrl + ) as Promise> + : null + ); + + const projectFlockKandangDetail = + projectFlockKandangDetailData?.status === 'success' + ? projectFlockKandangDetailData.data + : undefined; + const stockProductsUrl = useMemo(() => { if (!selectedLocation) return null; const params = new URLSearchParams({ @@ -228,40 +252,94 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { // ===== DATA PROCESSING ===== const locationOptions = useMemo(() => { - if (!isResponseSuccess(locations)) return []; - return ( - locations?.data.map((location) => ({ - value: location.id, - label: location.name, - })) || [] - ); - }, [locations]); + let options: OptionType[] = []; + + if (isResponseSuccess(locations)) { + options = options.concat( + locations?.data.map((location) => ({ + value: location.id, + label: location.name, + })) || [] + ); + } + + if (projectFlockKandangDetail && (type === 'edit' || type === 'detail')) { + const currentLocation = projectFlockKandangDetail.project_flock.location; + if ( + currentLocation && + !options.find((opt) => opt.value === currentLocation.id) + ) { + options.push({ + value: currentLocation.id, + label: currentLocation.name, + }); + } + } + + return options; + }, [locations, projectFlockKandangDetail, type]); const projectFlockOptions = useMemo(() => { - if (!isResponseSuccess(projectFlocks)) return []; - return ( - projectFlocks?.data.map((projectFlock) => ({ - value: projectFlock.id, - label: projectFlock.flock_name, - })) || [] - ); - }, [projectFlocks]); + let options: OptionType[] = []; + + if (isResponseSuccess(projectFlocks)) { + options = options.concat( + projectFlocks?.data.map((projectFlock) => ({ + value: projectFlock.id, + label: projectFlock.flock_name, + })) || [] + ); + } + + if (projectFlockKandangDetail && (type === 'edit' || type === 'detail')) { + const currentProjectFlock = projectFlockKandangDetail.project_flock; + if ( + currentProjectFlock && + !options.find((opt) => opt.value === currentProjectFlock.id) + ) { + options.push({ + value: currentProjectFlock.id, + label: currentProjectFlock.flock_name, + }); + } + } + + return options; + }, [projectFlocks, projectFlockKandangDetail, type]); const kandangOptions = useMemo(() => { - if (!selectedProjectFlock || !isResponseSuccess(projectFlocks)) return []; + let options: OptionType[] = []; - const selectedProjectFlockData = projectFlocks.data.find( - (pf) => pf.id === selectedProjectFlock.value - ); + if (selectedProjectFlock && isResponseSuccess(projectFlocks)) { + const selectedProjectFlockData = projectFlocks.data.find( + (pf) => pf.id === selectedProjectFlock.value + ); - if (!selectedProjectFlockData || !selectedProjectFlockData.kandangs) - return []; + if (selectedProjectFlockData?.kandangs) { + options = options.concat( + selectedProjectFlockData.kandangs.map((kandang: Kandang) => ({ + value: kandang.id, + label: kandang.name, + })) + ); + } + } - return selectedProjectFlockData.kandangs.map((kandang: Kandang) => ({ - value: kandang.id, - label: kandang.name, - })); - }, [selectedProjectFlock, projectFlocks]); + if (projectFlockKandangDetail && (type === 'edit' || type === 'detail')) { + const currentKandang = projectFlockKandangDetail.kandang; + if ( + currentKandang && + !options.find((opt) => opt.value === currentKandang.id) + ) { + options.push({ + value: currentKandang.id, + label: currentKandang.name, + }); + } + } + + return options; + }, [selectedProjectFlock, projectFlocks, projectFlockKandangDetail, type]); const recordedProjectFlockKandangIds = useMemo(() => { if (!isResponseSuccess(existingRecordings)) return new Set(); @@ -408,16 +486,28 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { const isLayingCategory = initialValues?.project_flock_category === 'LAYING' || - projectFlockKandangLookup?.project_flock?.category === 'LAYING'; + projectFlockKandangLookup?.project_flock?.category === 'LAYING' || + projectFlockKandangDetail?.project_flock?.category === 'LAYING'; const formikInitialValues = useMemo(() => { + let baseValues; if (isLayingCategory) { - return getRecordingLayingFormInitialValues( + baseValues = getRecordingLayingFormInitialValues( initialValues ) as RecordingLayingFormValues; + } else { + baseValues = getRecordingGrowingFormInitialValues(initialValues); } - return getRecordingGrowingFormInitialValues(initialValues); - }, [initialValues, isLayingCategory]); + + if (projectFlockKandangDetail && (type === 'edit' || type === 'detail')) { + baseValues.project_flock_kandang = { + value: projectFlockKandangDetail.project_flock.id, + label: projectFlockKandangDetail.project_flock.flock_name, + }; + } + + return baseValues; + }, [initialValues, isLayingCategory, projectFlockKandangDetail, type]); const formik = useFormik< RecordingGrowingFormValues | RecordingLayingFormValues @@ -756,7 +846,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { formik.setFieldValue('project_flock_kandang', { value: projectFlockKandangId, - label: `${selectedProjectFlock?.label || ''} - ${selectedKandang?.label || ''}`, + label: projectFlockKandangLookup + ? `${projectFlockKandangLookup.project_flock.flock_name} - ${projectFlockKandangLookup.kandang.name}` + : `${selectedProjectFlock?.label || ''} - ${selectedKandang?.label || ''}`, }); } }, [ @@ -767,6 +859,47 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { recordedProjectFlockKandangIds, ]); + useEffect(() => { + if (projectFlockKandangDetail && (type === 'edit' || type === 'detail')) { + const location = projectFlockKandangDetail.project_flock.location; + const projectFlock = projectFlockKandangDetail.project_flock; + const kandang = projectFlockKandangDetail.kandang; + + if (location) { + const locationOption = { + value: location.id, + label: location.name, + }; + setSelectedLocation(locationOption); + + if (projectFlock) { + const projectFlockOption = { + value: projectFlock.id, + label: projectFlock.flock_name, + }; + setSelectedProjectFlock(projectFlockOption); + + if (kandang) { + const kandangOption = { + value: kandang.id, + label: kandang.name, + }; + setSelectedKandang(kandangOption); + + formik.setFieldValue( + 'project_flock_kandang_id', + projectFlockKandangDetail.id + ); + formik.setFieldValue('project_flock_kandang', { + value: projectFlockKandangDetail.id, + label: `${projectFlock.flock_name} - ${kandang.name}`, + }); + } + } + } + } + }, [projectFlockKandangDetail, type, projectFlockOptions]); + const approveHandler = async () => { setIsApproveLoading(true); @@ -1041,7 +1174,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { formik.setFieldValue('eggs', [{ product_warehouse_id: 0, qty: '' }]); } } - }, [isLayingCategory, type, formik]); + }, [isLayingCategory, type]); useEffect(() => { if (isLayingCategory) { @@ -1120,73 +1253,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { {type === 'detail' && 'Detail Recording'} - {/* Project Flock Info Card */} - {projectFlockKandangLookup && ( -
- {/* Form Steps for LAYING Category */} - {formSteps && ( -
-
-
    - {formSteps.map((step, idx) => ( - - ) : ( - idx + 1 - ) - } - > - {step.name} - - ))} -
-
- - {/* Action buttons for multi-form navigation */} - {type === 'detail' && ( -
- - -
- )} -
- )} -
- )}
{ /> { /> { : 'Pilih Project Flock terlebih dahulu' } isClearable - isSearchable={false} + isSearchable startAdornment={ - projectFlockKandangLookup + projectFlockKandangLookup || projectFlockKandangDetail ? getProjectFlockBadgeAdornment() : undefined } @@ -1263,54 +1329,100 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { )} - {/* Recording Info for Detail View */} - {type === 'detail' && initialValues && ( - -
-
- Recording ID -

#{initialValues.id}

+ {/* Combined Info Card for Detail View */} + {type === 'detail' && + initialValues && + (projectFlockKandangLookup || projectFlockKandangDetail) && ( + +
+
+ Recording ID +

#{initialValues.id}

+
+
+ Lokasi +

+ {projectFlockKandangLookup?.project_flock?.location + ?.name || + projectFlockKandangDetail?.project_flock?.location + ?.name || + '-'} +

+
+
+ Project Flock +

+ {projectFlockKandangLookup?.project_flock?.flock_name || + projectFlockKandangDetail?.project_flock?.flock_name || + '-'} +

+
+
+ Kandang +

+ {projectFlockKandangLookup?.kandang?.name || + projectFlockKandangDetail?.kandang?.name || + '-'} +

+
+
+ + Tanggal Recording + +

+ {formatDate( + initialValues.record_datetime || '', + 'DD MMMM YYYY' + )} +

+
+
+ Hari +

Hari ke-{initialValues.day}

+
+
+ Kategori +

+ + {initialValues.project_flock_category} + +

+
+
+ Periode +

+ + Periode{' '} + {projectFlockKandangLookup?.project_flock?.period || + projectFlockKandangDetail?.project_flock?.period || + '-'} + +

+
-
- - Tanggal Recording - -

- {formatDate( - initialValues.record_datetime || '', - 'DD MMMM YYYY' - )} -

-
-
- Hari -

Hari ke-{initialValues.day}

-
-
- Kategori -

- - {initialValues.project_flock_category} - -

-
-
- - )} + + )} {/* Body Weights Table */}