refactor(FE): Manage product and delivery quantity error toasts

This commit is contained in:
rstubryan
2026-01-23 12:52:54 +07:00
parent 359f0f7b01
commit bcc2f71623
@@ -54,6 +54,8 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
const [selectedProducts, setSelectedProducts] = useState<number[]>([]);
const [selectedDeliveries, setSelectedDeliveries] = useState<number[]>([]);
const [formErrorList, setFormErrorList] = useState<string[]>([]);
const [productQtyErrorShown, setProductQtyErrorShown] = useState(false);
const [deliveryQtyErrorShown, setDeliveryQtyErrorShown] = useState(false);
// ===== FORM HANDLERS =====
const createMovementHandler = useCallback(
@@ -465,7 +467,8 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
formik.setFieldValue('products', newProducts);
}, []);
const removeProduct = useCallback((i: number) => {
const removeProduct = useCallback(
(i: number) => {
const updatedProducts =
formik.values.products?.reduce((acc: ProductSchema[], item, index) => {
if (index !== i) {
@@ -475,7 +478,14 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
}, []) ?? [];
formik.setFieldValue('products', updatedProducts);
}, []);
if (productQtyErrorShown) {
toast.dismiss();
setProductQtyErrorShown(false);
}
},
[productQtyErrorShown]
);
const bulkRemoveProduct = useCallback(() => {
const updatedProducts =
@@ -484,7 +494,12 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
) ?? [];
formik.setFieldValue('products', updatedProducts);
setSelectedProducts([]);
}, [formik, selectedProducts, setSelectedProducts]);
if (productQtyErrorShown) {
toast.dismiss();
setProductQtyErrorShown(false);
}
}, [formik, selectedProducts, setSelectedProducts, productQtyErrorShown]);
const handleProductChange = useCallback(
(idx: number, val: OptionType | OptionType[] | null) => {
@@ -544,17 +559,28 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
]);
}, []);
const removeDelivery = useCallback((i: number) => {
const removeDelivery = useCallback(
(i: number) => {
const updatedDeliveries =
formik.values.deliveries?.reduce((acc: DeliverySchema[], item, index) => {
formik.values.deliveries?.reduce(
(acc: DeliverySchema[], item, index) => {
if (index !== i) {
acc.push(item);
}
return acc;
}, []) ?? [];
},
[]
) ?? [];
formik.setFieldValue('deliveries', updatedDeliveries);
}, []);
if (deliveryQtyErrorShown) {
toast.dismiss();
setDeliveryQtyErrorShown(false);
}
},
[deliveryQtyErrorShown]
);
const bulkRemoveDelivery = useCallback(() => {
const updatedDeliveries =
@@ -563,7 +589,17 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
) ?? [];
formik.setFieldValue('deliveries', updatedDeliveries);
setSelectedDeliveries([]);
}, [formik, selectedDeliveries, setSelectedDeliveries]);
if (deliveryQtyErrorShown) {
toast.dismiss();
setDeliveryQtyErrorShown(false);
}
}, [
formik,
selectedDeliveries,
setSelectedDeliveries,
deliveryQtyErrorShown,
]);
const handleDeliverySelectAllChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
@@ -1038,6 +1074,73 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
formik.errors.destination_warehouse_id,
]);
useEffect(() => {
if (productQtyErrorShown) {
toast.dismiss();
setProductQtyErrorShown(false);
}
}, [formik.values.products?.map((p) => p.product_qty).join(',')]);
useEffect(() => {
if (deliveryQtyErrorShown) {
toast.dismiss();
setDeliveryQtyErrorShown(false);
}
}, [
formik.values.deliveries
?.map((d) => d.products.map((p) => p.product_qty).join(','))
.join('|'),
]);
useEffect(() => {
if (hasExceededStock && !productQtyErrorShown && type !== 'detail') {
const firstErrorIndex = formik.values.products?.findIndex(
(product, idx) => getProductQtyError(idx) !== null
);
if (firstErrorIndex !== undefined && firstErrorIndex >= 0) {
const errorMsg = getProductQtyError(firstErrorIndex);
if (errorMsg) {
toast.error(errorMsg, { duration: Infinity });
setProductQtyErrorShown(true);
}
}
}
}, [
hasExceededStock,
productQtyErrorShown,
type,
formik.values.products,
getProductQtyError,
]);
useEffect(() => {
if (hasInvalidQty && !deliveryQtyErrorShown && type !== 'detail') {
const firstError = formik.values.deliveries?.find(
(delivery, deliveryIdx) =>
delivery.products.some(
(product, productIdx) =>
getDeliveryQtyError(deliveryIdx, productIdx) !== null
)
);
if (firstError) {
const deliveryIdx = formik.values.deliveries?.indexOf(firstError);
if (deliveryIdx !== undefined && deliveryIdx >= 0) {
const errorMsg = getDeliveryQtyError(deliveryIdx, 0);
if (errorMsg) {
toast.error(errorMsg, { duration: Infinity });
setDeliveryQtyErrorShown(true);
}
}
}
}
}, [
hasInvalidQty,
deliveryQtyErrorShown,
type,
formik.values.deliveries,
getDeliveryQtyError,
]);
const handleValidateForm = async () => {
const errors = await formik.validateForm();
@@ -1856,8 +1959,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
className='px-4'
isLoading={formik.isSubmitting}
disabled={
hasInvalidQty ||
hasExceededStock ||
formik.isSubmitting ||
(formik.values.source_warehouse_id ===
formik.values.destination_warehouse_id &&