refactor(FE-62,63): update MovementForm to handle 'detail' type with appropriate validations and stock checks

This commit is contained in:
rstubryan
2025-10-16 16:46:33 +07:00
parent 57dbcf3624
commit 1bdec0c9ae
@@ -462,7 +462,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
}
} catch (error) {
console.error(`Failed to fetch product ${productId}:`, error);
newFetchedIds.add(productId); // Mark as fetched to avoid retry loops
newFetchedIds.add(productId);
}
}
@@ -535,16 +535,18 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
const getAvailableStock = useCallback(
(productId: number) => {
if (type === 'detail') return 0;
const productWarehouse = productWarehouseOptions.find(
(pw) => pw.product_id === productId
);
return productWarehouse?.quantity ?? 0;
},
[productWarehouseOptions]
[productWarehouseOptions, type]
);
const getProductQtyError = useCallback(
(productIdx: number) => {
if (type === 'detail') return null;
const product = formik.values.products?.[productIdx];
if (!product || !product.product_id) return null;
@@ -557,11 +559,12 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
return null;
},
[formik.values.products, getAvailableStock]
[formik.values.products, getAvailableStock, type]
);
const validateDeliveryQty = useCallback(
(deliveryIdx: number, deliveryProductIdx: number, qty: number) => {
if (type === 'detail') return true;
const delivery = formik.values.deliveries?.[deliveryIdx];
if (!delivery) return true;
@@ -592,11 +595,12 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
return totalQtyUsed + qty <= Number(relatedProduct.product_qty);
},
[formik.values.deliveries, formik.values.products]
[formik.values.deliveries, formik.values.products, type]
);
const getDeliveryQtyError = useCallback(
(deliveryIdx: number, deliveryProductIdx: number) => {
if (type === 'detail') return null;
const delivery = formik.values.deliveries?.[deliveryIdx];
if (!delivery) return null;
@@ -633,32 +637,40 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
return null;
},
[formik.values.deliveries, formik.values.products]
[formik.values.deliveries, formik.values.products, type]
);
const invalidQtyRows = useMemo(
() =>
formik.values.deliveries?.flatMap((delivery, deliveryIdx) =>
delivery.products.map((product, productIdx) => {
const qty = Number(product.product_qty) || 0;
return !validateDeliveryQty(deliveryIdx, productIdx, qty);
})
) ?? [],
[formik.values.deliveries, formik.values.products, validateDeliveryQty]
type === 'detail'
? []
: (formik.values.deliveries?.flatMap((delivery, deliveryIdx) =>
delivery.products.map((product, productIdx) => {
const qty = Number(product.product_qty) || 0;
return !validateDeliveryQty(deliveryIdx, productIdx, qty);
})
) ?? []),
[
formik.values.deliveries,
formik.values.products,
validateDeliveryQty,
type,
]
);
const hasInvalidQty = useMemo(
() => invalidQtyRows.some(Boolean),
[invalidQtyRows]
() => (type === 'detail' ? false : invalidQtyRows.some(Boolean)),
[invalidQtyRows, type]
);
const hasExceededStock = useMemo(() => {
if (type === 'detail') return false;
return (
formik.values.products?.some((product, idx) => {
return getProductQtyError(idx) !== null;
}) ?? false
);
}, [formik.values.products, getProductQtyError]);
}, [formik.values.products, getProductQtyError, type]);
return (
<>
@@ -960,7 +972,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
wrapper: 'w-full min-w-24',
}}
/>
{product.product_id && (
{type !== 'detail' && product.product_id && (
<div className='text-sm text-gray-600'>
<span className='font-semibold'>
Stok tersedia: