From d7938245209f87d3d595347682a368e4b6c60be4 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Sun, 2 Nov 2025 21:33:38 +0700 Subject: [PATCH] refactor(FE-Storyless): enhance MovementForm schema and validation, improve handling of product quantities and delivery costs --- .../movement/form/MovementForm.schema.ts | 64 ++++++++++++++--- .../inventory/movement/form/MovementForm.tsx | 70 +++++++++++-------- 2 files changed, 98 insertions(+), 36 deletions(-) diff --git a/src/components/pages/inventory/movement/form/MovementForm.schema.ts b/src/components/pages/inventory/movement/form/MovementForm.schema.ts index 20f2fb7d..195873b7 100644 --- a/src/components/pages/inventory/movement/form/MovementForm.schema.ts +++ b/src/components/pages/inventory/movement/form/MovementForm.schema.ts @@ -1,34 +1,82 @@ import * as Yup from 'yup'; import { Movement } from '@/types/api/inventory/movement'; +type MovementFormSchemaType = { + transfer_reason: string; + transfer_date: string; + source_warehouse?: { + value: number; + label: string; + area?: string; + location?: string; + } | null; + source_warehouse_id: number; + destination_warehouse?: { + value: number; + label: string; + area?: string; + location?: string; + } | null; + destination_warehouse_id: number; + products: { + product?: { + value: number; + label: string; + } | null; + product_id: number; + product_qty: number | string; + }[]; + deliveries: { + delivery_cost?: number | string; + delivery_cost_per_item?: number | string; + document?: File | string | null; + document_path?: string | null; + driver_name: string; + vehicle_plate: string; + supplier?: { + value: number; + label: string; + } | null; + supplier_id: number; + products: { + product?: { + value: number; + label: string; + } | null; + product_id: number; + product_qty: number | string; + }[]; + }[]; +}; + export type ProductSchema = { - product: { + product?: { value: number; label: string; } | null; product_id: number; - product_qty: number; + product_qty: number | string; }; export type DeliverySchema = { - delivery_cost?: number | undefined; - delivery_cost_per_item?: number | undefined; + delivery_cost?: number | string; + delivery_cost_per_item?: number | string; document?: File | string | null; document_path?: string | null; driver_name: string; vehicle_plate: string; - supplier: { + supplier?: { value: number; label: string; } | null; supplier_id: number; products: { - product: { + product?: { value: number; label: string; } | null; product_id: number; - product_qty: number; + product_qty: number | string; }[]; }; @@ -102,7 +150,7 @@ const DeliveryObjectSchema: Yup.ObjectSchema = Yup.object({ .required('Produk wajib diisi!'), }); -export const MovementFormSchema = Yup.object({ +export const MovementFormSchema: Yup.ObjectSchema = Yup.object({ transfer_reason: Yup.string().required('Alasan transfer wajib diisi!'), transfer_date: Yup.string().required('Tanggal transfer wajib diisi!'), source_warehouse: Yup.object({ diff --git a/src/components/pages/inventory/movement/form/MovementForm.tsx b/src/components/pages/inventory/movement/form/MovementForm.tsx index 0bfb94c3..56038f6a 100644 --- a/src/components/pages/inventory/movement/form/MovementForm.tsx +++ b/src/components/pages/inventory/movement/form/MovementForm.tsx @@ -173,8 +173,9 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { } return { - delivery_cost: d.delivery_cost ?? 0, - delivery_cost_per_item: d.delivery_cost_per_item ?? 0, + delivery_cost: parseInt((d.delivery_cost || '').toString()) || 0, + delivery_cost_per_item: + parseInt((d.delivery_cost_per_item || '').toString()) || 0, document_index: documentIndex, document_path: d.document_path, driver_name: d.driver_name, @@ -182,7 +183,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { supplier_id: d.supplier_id, products: d.products.map((p) => ({ product_id: p.product_id, - product_qty: p.product_qty, + product_qty: parseInt(p.product_qty.toString()) || 0, })), }; }); @@ -194,7 +195,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { destination_warehouse_id: values.destination_warehouse_id, products: values.products.map((p) => ({ product_id: p.product_id, - product_qty: p.product_qty, + product_qty: parseInt(p.product_qty.toString()) || 0, })), deliveries: deliveriesPayload, }; @@ -304,7 +305,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { { product: null, product_id: 0, - product_qty: 0, + product_qty: '', }, ]; formik.setFieldValue('products', newProducts); @@ -339,8 +340,8 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { formik.setFieldValue('deliveries', [ ...(formik.values.deliveries || []), { - delivery_cost: undefined, - delivery_cost_per_item: undefined, + delivery_cost: '', + delivery_cost_per_item: '', document: null, driver_name: '', vehicle_plate: '', @@ -350,7 +351,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { { product: null, product_id: 0, - product_qty: 0, + product_qty: '', }, ], }, @@ -392,7 +393,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { const delivery = formik.values.deliveries?.[idx]; if (delivery) { const productQty = delivery.products.reduce( - (sum, p) => sum + p.product_qty, + (sum, p) => sum + (parseInt(p.product_qty.toString()) || 0), 0 ); if (productQty > 0 && value > 0) { @@ -416,7 +417,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { const delivery = formik.values.deliveries?.[idx]; if (delivery) { const productQty = delivery.products.reduce( - (sum, p) => sum + p.product_qty, + (sum, p) => sum + (parseInt(p.product_qty.toString()) || 0), 0 ); if (productQty > 0 && value > 0) { @@ -690,36 +691,38 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { useEffect(() => { formik.values.deliveries?.forEach((delivery, idx) => { const productQty = delivery.products.reduce( - (sum, p) => sum + p.product_qty, + (sum, p) => sum + (parseInt(p.product_qty.toString()) || 0), 0 ); - if ( - delivery.delivery_cost && - delivery.delivery_cost > 0 && - productQty > 0 - ) { - const perItem = delivery.delivery_cost / productQty; - if (Math.abs((delivery.delivery_cost_per_item || 0) - perItem) > 0.01) { + const deliveryCost = + parseInt((delivery.delivery_cost || '').toString()) || 0; + const deliveryCostPerItem = + parseInt((delivery.delivery_cost_per_item || '').toString()) || 0; + + if (deliveryCost > 0 && productQty > 0) { + const perItem = deliveryCost / productQty; + if (Math.abs(deliveryCostPerItem - perItem) > 0.01) { formik.setFieldValue( `deliveries.${idx}.delivery_cost_per_item`, perItem ); } - } else if ( - delivery.delivery_cost_per_item && - delivery.delivery_cost_per_item > 0 && - productQty > 0 - ) { - const totalCost = delivery.delivery_cost_per_item * productQty; - if (Math.abs((delivery.delivery_cost || 0) - totalCost) > 0.01) { + } else if (deliveryCostPerItem > 0 && productQty > 0) { + const totalCost = deliveryCostPerItem * productQty; + if (Math.abs(deliveryCost - totalCost) > 0.01) { formik.setFieldValue(`deliveries.${idx}.delivery_cost`, totalCost); } } }); }, [ formik.values.deliveries - ?.map((d) => d.products.reduce((sum, p) => sum + p.product_qty, 0)) + ?.map((d) => + d.products.reduce( + (sum, p) => sum + (parseInt(p.product_qty.toString()) || 0), + 0 + ) + ) .join(','), ]); @@ -765,6 +768,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { required label='Alasan Transfer' name='transfer_reason' + placeholder='Masukkan alasan transfer...' value={formik.values.transfer_reason} onChange={formik.handleChange} onBlur={formik.handleBlur} @@ -802,6 +806,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { { formik.setFieldTouched('source_warehouse', true); @@ -869,6 +874,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { { formik.setFieldTouched('destination_warehouse', true); @@ -1055,8 +1061,8 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { } placeholder={ !formik.values.source_warehouse_id - ? 'Pilih gudang asal terlebih dahulu' - : 'Pilih produk' + ? 'Pilih gudang asal terlebih dahulu...' + : 'Pilih produk...' } isClearable {...isRepeaterInputError( @@ -1074,6 +1080,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { { { formik.setFieldTouched( @@ -1334,6 +1342,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { { { formik.setFieldTouched( @@ -1403,6 +1413,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { { { {