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) { } catch (error) {
console.error(`Failed to fetch product ${productId}:`, 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( const getAvailableStock = useCallback(
(productId: number) => { (productId: number) => {
if (type === 'detail') return 0;
const productWarehouse = productWarehouseOptions.find( const productWarehouse = productWarehouseOptions.find(
(pw) => pw.product_id === productId (pw) => pw.product_id === productId
); );
return productWarehouse?.quantity ?? 0; return productWarehouse?.quantity ?? 0;
}, },
[productWarehouseOptions] [productWarehouseOptions, type]
); );
const getProductQtyError = useCallback( const getProductQtyError = useCallback(
(productIdx: number) => { (productIdx: number) => {
if (type === 'detail') return null;
const product = formik.values.products?.[productIdx]; const product = formik.values.products?.[productIdx];
if (!product || !product.product_id) return null; if (!product || !product.product_id) return null;
@@ -557,11 +559,12 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
return null; return null;
}, },
[formik.values.products, getAvailableStock] [formik.values.products, getAvailableStock, type]
); );
const validateDeliveryQty = useCallback( const validateDeliveryQty = useCallback(
(deliveryIdx: number, deliveryProductIdx: number, qty: number) => { (deliveryIdx: number, deliveryProductIdx: number, qty: number) => {
if (type === 'detail') return true;
const delivery = formik.values.deliveries?.[deliveryIdx]; const delivery = formik.values.deliveries?.[deliveryIdx];
if (!delivery) return true; if (!delivery) return true;
@@ -592,11 +595,12 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
return totalQtyUsed + qty <= Number(relatedProduct.product_qty); return totalQtyUsed + qty <= Number(relatedProduct.product_qty);
}, },
[formik.values.deliveries, formik.values.products] [formik.values.deliveries, formik.values.products, type]
); );
const getDeliveryQtyError = useCallback( const getDeliveryQtyError = useCallback(
(deliveryIdx: number, deliveryProductIdx: number) => { (deliveryIdx: number, deliveryProductIdx: number) => {
if (type === 'detail') return null;
const delivery = formik.values.deliveries?.[deliveryIdx]; const delivery = formik.values.deliveries?.[deliveryIdx];
if (!delivery) return null; if (!delivery) return null;
@@ -633,32 +637,40 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
return null; return null;
}, },
[formik.values.deliveries, formik.values.products] [formik.values.deliveries, formik.values.products, type]
); );
const invalidQtyRows = useMemo( const invalidQtyRows = useMemo(
() => () =>
formik.values.deliveries?.flatMap((delivery, deliveryIdx) => type === 'detail'
delivery.products.map((product, productIdx) => { ? []
const qty = Number(product.product_qty) || 0; : (formik.values.deliveries?.flatMap((delivery, deliveryIdx) =>
return !validateDeliveryQty(deliveryIdx, productIdx, qty); delivery.products.map((product, productIdx) => {
}) const qty = Number(product.product_qty) || 0;
) ?? [], return !validateDeliveryQty(deliveryIdx, productIdx, qty);
[formik.values.deliveries, formik.values.products, validateDeliveryQty] })
) ?? []),
[
formik.values.deliveries,
formik.values.products,
validateDeliveryQty,
type,
]
); );
const hasInvalidQty = useMemo( const hasInvalidQty = useMemo(
() => invalidQtyRows.some(Boolean), () => (type === 'detail' ? false : invalidQtyRows.some(Boolean)),
[invalidQtyRows] [invalidQtyRows, type]
); );
const hasExceededStock = useMemo(() => { const hasExceededStock = useMemo(() => {
if (type === 'detail') return false;
return ( return (
formik.values.products?.some((product, idx) => { formik.values.products?.some((product, idx) => {
return getProductQtyError(idx) !== null; return getProductQtyError(idx) !== null;
}) ?? false }) ?? false
); );
}, [formik.values.products, getProductQtyError]); }, [formik.values.products, getProductQtyError, type]);
return ( return (
<> <>
@@ -960,7 +972,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
wrapper: 'w-full min-w-24', wrapper: 'w-full min-w-24',
}} }}
/> />
{product.product_id && ( {type !== 'detail' && product.product_id && (
<div className='text-sm text-gray-600'> <div className='text-sm text-gray-600'>
<span className='font-semibold'> <span className='font-semibold'>
Stok tersedia: Stok tersedia: