feat(FE-62): add quantity validation for ekspedisi in MovementForm and filter product options

This commit is contained in:
rstubryan
2025-10-10 13:43:30 +07:00
parent a1dc13ceb4
commit 757893c757
@@ -30,6 +30,7 @@ import {
SupplierApi,
WarehouseApi,
} from '@/services/api/master-data';
import { toast } from 'react-hot-toast';
interface MovementFormProps {
type?: 'add' | 'edit' | 'detail';
@@ -251,6 +252,37 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
formikSetValues(formikInitialValues);
}, [formikSetValues, formikInitialValues]);
const getFilteredProductOptions = useCallback(() => {
return (
formik.values.product
?.filter((p) => p.product)
.map((p) => ({
value: p.product_id,
label: (p.product as OptionType)?.label,
})) ?? []
);
}, [formik.values.product]);
const validateEkspedisiQty = (ekspedisiIdx: number, qty: number) => {
const productId = formik.values.ekspedisi?.[ekspedisiIdx]?.product_id;
if (!productId) return true;
const relatedProduct = formik.values.product?.find(
(p) => p.product_id === productId
);
if (!relatedProduct) return true;
const totalQtyUsed =
formik.values.ekspedisi?.reduce((total, eks, i) => {
if (eks.product_id === productId && i !== ekspedisiIdx) {
return total + (Number(eks.qty) || 0);
}
return total;
}, 0) || 0;
return totalQtyUsed + qty <= Number(relatedProduct.qty_product);
};
return (
<>
<section className='w-full max-w-5xl'>
@@ -419,6 +451,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
</div>
</div>
</div>
{/* Products table */}
<div className='card bg-base-100 shadow mb-4'>
<div className='card-body'>
@@ -657,10 +690,9 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
`ekspedisi.${idx}.product_id`,
(val as OptionType)?.value
);
formik.setFieldValue(`ekspedisi.${idx}.qty`, '');
}}
options={productOptions}
onInputChange={setProductSelectInputValue}
isLoading={isLoadingProducts}
options={getFilteredProductOptions()}
isDisabled={type === 'detail'}
isClearable
isError={isRepeaterInputError(
@@ -676,7 +708,16 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
type='number'
name={`ekspedisi.${idx}.qty`}
value={ekspedisi.qty ?? ''}
onChange={formik.handleChange}
onChange={(e) => {
const newQty = Number(e.target.value);
if (validateEkspedisiQty(idx, newQty)) {
formik.handleChange(e);
} else {
toast.error(
'Quantity exceeds available product quantity'
);
}
}}
onBlur={formik.handleBlur}
isError={isRepeaterInputError(
'ekspedisi',