feat(FE-170,175): implement payload creation for growing and laying recordings in RecordingForm

This commit is contained in:
rstubryan
2025-11-06 23:27:46 +07:00
parent 2e5530cf91
commit f032f71136
@@ -89,6 +89,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const [recordingFormErrorMessage, setRecordingFormErrorMessage] = const [recordingFormErrorMessage, setRecordingFormErrorMessage] =
useState(''); useState('');
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const [newRecordingData, setNewRecordingData] = useState<Recording | null>(
null
);
const approveModal = useModal(); const approveModal = useModal();
const rejectModal = useModal(); const rejectModal = useModal();
@@ -112,6 +115,71 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
); );
}, []); }, []);
// ===== PAYLOAD CREATION HELPERS =====
const createGrowingPayload = useCallback(
(values: RecordingGrowingFormValues) => {
return {
project_flock_kandang_id: values.project_flock_kandang_id,
body_weights: (values.body_weights ?? []).map((bw) => {
const qty = Number(bw.qty) || 0;
const weight = Number(bw.weight) || 0;
const totalWeight = qty * weight;
return {
avg_weight:
typeof bw.avg_weight === 'number'
? bw.avg_weight
: parseFloat(String(bw.avg_weight)) || 0,
qty: qty,
total_weight: parseFloat(String(totalWeight)) || 0,
};
}),
stocks: (values.stocks ?? []).map((stock) => ({
product_warehouse_id: stock.product_warehouse_id,
qty: Number(stock.qty) || 0,
})),
depletions: (values.depletions ?? []).map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id,
qty: Number(depletion.qty) || 0,
})),
};
},
[]
);
const createLayingPayload = useCallback(
(values: RecordingLayingFormValues) => {
return {
project_flock_kandang_id: values.project_flock_kandang_id,
body_weights: (values.body_weights ?? []).map((bw) => {
const qty = Number(bw.qty) || 0;
const weight = Number(bw.weight) || 0;
const totalWeight = qty * weight;
return {
avg_weight:
typeof bw.avg_weight === 'number'
? bw.avg_weight
: parseFloat(String(bw.avg_weight)) || 0,
qty: qty,
total_weight: parseFloat(String(totalWeight)) || 0,
};
}),
stocks: (values.stocks ?? []).map((stock) => ({
product_warehouse_id: stock.product_warehouse_id,
qty: Number(stock.qty) || 0,
})),
depletions: (values.depletions ?? []).map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id,
qty: Number(depletion.qty) || 0,
})),
eggs: (values.eggs ?? []).map((egg) => ({
product_warehouse_id: egg.product_warehouse_id,
qty: Number(egg.qty) || 0,
})),
};
},
[]
);
// ===== FORM HANDLERS ===== // ===== FORM HANDLERS =====
const createRecordingHandler = useCallback( const createRecordingHandler = useCallback(
async ( async (
@@ -128,6 +196,35 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
[router] [router]
); );
const createRecordingHandlerWithRedirect = useCallback(
async (
payload: CreateGrowingRecordingPayload | CreateLayingRecordingPayload,
redirectToGrading: boolean = false
) => {
const res = await RecordingApi.create(payload);
if (isResponseError(res)) {
setRecordingFormErrorMessage(res.message);
return null;
}
toast.success(res?.message as string);
if (res?.status === 'success' && res.data) {
setNewRecordingData(res.data);
return res.data;
}
if (redirectToGrading) {
toast.error(
'Gagal mendapatkan ID recording. Silakan coba dari halaman list.'
);
router.push('/production/recording');
}
return null;
},
[router]
);
const updateRecordingHandler = useCallback( const updateRecordingHandler = useCallback(
async ( async (
recordingId: number, recordingId: number,
@@ -370,7 +467,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const recordedProjectFlockKandangIds = useMemo(() => { const recordedProjectFlockKandangIds = useMemo(() => {
if (!isResponseSuccess(existingRecordings)) return new Set<number>(); if (!isResponseSuccess(existingRecordings)) return new Set<number>();
const todayRecordings = existingRecordings?.data || []; const todayRecordings = existingRecordings.data;
const recordedIds = new Set<number>(); const recordedIds = new Set<number>();
todayRecordings.forEach((recording) => { todayRecordings.forEach((recording) => {
@@ -558,36 +655,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
onSubmit: async (values) => { onSubmit: async (values) => {
if (isLayingCategory) { if (isLayingCategory) {
const layingValues = values as RecordingLayingFormValues; const layingValues = values as RecordingLayingFormValues;
const layingPayload = createLayingPayload(layingValues);
const layingPayload = {
project_flock_kandang_id: layingValues.project_flock_kandang_id,
body_weights: (layingValues.body_weights ?? []).map((bw) => {
const qty = Number(bw.qty) || 0;
const weight = Number(bw.weight) || 0;
const totalWeight = qty * weight;
return {
avg_weight:
typeof bw.avg_weight === 'number'
? bw.avg_weight
: parseFloat(String(bw.avg_weight)) || 0,
qty: qty,
total_weight: parseFloat(String(totalWeight)) || 0,
};
}),
stocks: (layingValues.stocks ?? []).map((stock) => ({
product_warehouse_id: stock.product_warehouse_id,
qty: Number(stock.qty) || 0,
})),
depletions: (layingValues.depletions ?? []).map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id,
qty: Number(depletion.qty) || 0,
})),
eggs: (layingValues.eggs ?? []).map((egg) => ({
product_warehouse_id: egg.product_warehouse_id,
qty: Number(egg.qty) || 0,
})),
};
switch (type) { switch (type) {
case 'add': case 'add':
@@ -604,32 +672,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
} }
} else { } else {
const growingValues = values as RecordingGrowingFormValues; const growingValues = values as RecordingGrowingFormValues;
const growingPayload = createGrowingPayload(growingValues);
const growingPayload = {
project_flock_kandang_id: growingValues.project_flock_kandang_id,
body_weights: (growingValues.body_weights ?? []).map((bw) => {
const qty = Number(bw.qty) || 0;
const weight = Number(bw.weight) || 0;
const totalWeight = qty * weight;
return {
avg_weight:
typeof bw.avg_weight === 'number'
? bw.avg_weight
: parseFloat(String(bw.avg_weight)) || 0,
qty: qty,
total_weight: parseFloat(String(totalWeight)) || 0,
};
}),
stocks: (growingValues.stocks ?? []).map((stock) => ({
product_warehouse_id: stock.product_warehouse_id,
qty: Number(stock.qty) || 0,
})),
depletions: (growingValues.depletions ?? []).map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id,
qty: Number(depletion.qty) || 0,
})),
};
switch (type) { switch (type) {
case 'add': case 'add':
@@ -1243,6 +1286,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
} else { } else {
setFormSteps(null); setFormSteps(null);
} }
if (type !== 'add') {
setNewRecordingData(null);
}
}, [isLayingCategory, type]); }, [isLayingCategory, type]);
const bodyWeightValues = useMemo(() => { const bodyWeightValues = useMemo(() => {
@@ -2464,13 +2510,22 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
type='button' type='button'
color='primary' color='primary'
onClick={() => { onClick={() => {
router.push( const recordingId =
`/production/recording/grading/add?recording_id=${initialValues?.id}` newRecordingData?.id || initialValues?.id;
); if (recordingId) {
router.push(
`/production/recording/grading/add?recording_id=${recordingId}`
);
} else {
toast.error(
'Recording ID tidak ditemukan. Silakan refresh halaman.'
);
}
}} }}
> >
<Icon icon='material-symbols:egg' width={24} height={24} /> <Icon icon='material-symbols:egg' width={24} height={24} />
{hasGradingData(initialValues) {hasGradingData(initialValues) ||
hasGradingData(newRecordingData || undefined)
? 'Edit Grading' ? 'Edit Grading'
: 'Lanjut ke Grading'} : 'Lanjut ke Grading'}
</Button> </Button>
@@ -2536,20 +2591,45 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
formik.isSubmitting formik.isSubmitting
} }
onClick={async () => { onClick={async () => {
await formik.submitForm(); if (!formik.isValid) {
if ( await formik.validateForm();
formik.isValid && return;
!formik.isSubmitting && }
!hasExceededStock
) { setRecordingFormErrorMessage('');
toast.success( formik.setSubmitting(true);
'Recording berhasil disimpan! Mengalihkan ke form Grading...'
try {
if (isLayingCategory) {
const layingValues =
formik.values as RecordingLayingFormValues;
const layingPayload =
createLayingPayload(layingValues);
const recordingData =
await createRecordingHandlerWithRedirect(
layingPayload as CreateLayingRecordingPayload,
true
);
if (recordingData?.id) {
toast.success(
'Recording berhasil disimpan! Mengalihkan ke form Grading...'
);
setTimeout(() => {
router.push(
`/production/recording/grading/add?recording_id=${recordingData.id}`
);
}, 1000);
}
}
} catch (error) {
console.error('Error creating recording:', error);
toast.error(
'Gagal membuat recording. Silakan coba lagi.'
); );
setTimeout(() => { } finally {
router.push( formik.setSubmitting(false);
`/production/recording/grading/add?recording_id=${initialValues?.id || ''}`
);
}, 1000);
} }
}} }}
> >