From 910ea85b62d238c72c4da1fc8062c5a13bf86c70 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Mon, 2 Mar 2026 15:24:14 +0700 Subject: [PATCH] refactor(FE): Refactor InventoryAdjustmentForm to simplify product handling --- .../form/InventoryAdjustmentForm.tsx | 150 +++--------------- 1 file changed, 18 insertions(+), 132 deletions(-) diff --git a/src/components/pages/inventory/adjustment/form/InventoryAdjustmentForm.tsx b/src/components/pages/inventory/adjustment/form/InventoryAdjustmentForm.tsx index e2853b37..012713d9 100644 --- a/src/components/pages/inventory/adjustment/form/InventoryAdjustmentForm.tsx +++ b/src/components/pages/inventory/adjustment/form/InventoryAdjustmentForm.tsx @@ -1,10 +1,8 @@ 'use client'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; -import { - InventoryAdjustmentApi, - ProductWarehouseApi, -} from '@/services/api/inventory'; +import { InventoryAdjustmentApi } from '@/services/api/inventory'; +import { ProductApi } from '@/services/api/master-data'; import { CreateInventoryAdjustmentPayload, InventoryAdjustment, @@ -28,8 +26,7 @@ import SelectInput, { OptionType, useSelect, } from '@/components/input/SelectInput'; -import { components as ReactSelectComponents, OptionProps } from 'react-select'; -import StatusBadge from '@/components/helper/StatusBadge'; + import TextArea from '@/components/input/TextArea'; import { useFormikErrorList } from '@/services/hooks/useFormikErrorList'; import AlertErrorList from '@/components/helper/form/FormErrors'; @@ -37,7 +34,7 @@ import { Location } from '@/types/api/master-data/location'; import { ProjectFlock } from '@/types/api/production/project-flock'; import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang'; import { Kandang } from '@/types/api/master-data/kandang'; -import { ProductWarehouse } from '@/types/api/inventory/product-warehouse'; +import { Product } from '@/types/api/master-data/product'; import { ProjectFlockKandangLookup } from '@/types/api/production/project-flock'; import { BaseApiResponse } from '@/types/api/api-general'; import useSWR from 'swr'; @@ -46,7 +43,6 @@ import { TRANSACTION_SUBTYPE_OPTIONS, } from '@/config/constant'; import NumberInput from '@/components/input/NumberInput'; -import { formatNumber } from '@/lib/helper'; interface InventoryAdjustmentFormProps { type?: 'add' | 'detail'; @@ -62,8 +58,6 @@ const InventoryAdjustmentForm = ({ InventoryAdjustmentFormErrorMessage, setInventoryAdjustmentFormErrorMessage, ] = useState(''); - const [quantityLabel, setQuantityLabel] = useState('Kuantitas'); - const [quantityError, setQuantityError] = useState(''); const [selectedLocation, setSelectedLocation] = useState( null @@ -188,53 +182,24 @@ const InventoryAdjustmentForm = ({ setInputValue: setProductInputValue, isLoadingOptions: isLoadingProductOptions, loadMore: loadMoreProducts, - rawData: productWarehouses, - } = useSelect( - selectedKandang && selectedProjectFlockLocationId - ? ProductWarehouseApi.basePath - : '', - 'id', - 'product.name', - 'search', - { - kandang_id: selectedKandang?.value?.toString() || '', - location_id: selectedProjectFlockLocationId, - } - ); + rawData: products, + } = useSelect(ProductApi.basePath, 'id', 'name', 'search'); const productOptions = useMemo(() => { - if (!isResponseSuccess(productWarehouses)) return []; + if (!isResponseSuccess(products)) return []; const excludedFlags = ['AYAM-AFKIR', 'AYAM-CULLING', 'AYAM-MATI']; - const filteredProducts = productWarehouses.data.filter((pw) => { - const productFlags = (pw.product.flags as string[]) || []; + const filteredProducts = products.data.filter((product) => { + const productFlags = (product.flags as string[]) || []; return !productFlags.some((flag) => excludedFlags.includes(flag)); }); - return filteredProducts.map((pw) => ({ - value: pw.product.id, - label: pw.product.name, - quantity: pw.quantity, - flags: pw.product.flags, + return filteredProducts.map((product) => ({ + value: product.id, + label: product.name, + flags: product.flags, })); - }, [productWarehouses]); - - const selectedProductQuantity = useMemo(() => { - if (!selectedProduct) return 0; - const product = productOptions.find( - (opt) => opt.value === selectedProduct.value - ); - return product?.quantity ?? 0; - }, [selectedProduct, productOptions]); - - const isStockOutSubtype = useMemo(() => { - const subtype = selectedTransactionSubtype?.value; - return ( - subtype === 'RECORDING_STOCK_OUT' || - subtype === 'RECORDING_DEPLETION_OUT' || - subtype === 'MARKETING_OUT' - ); - }, [selectedTransactionSubtype]); + }, [products]); const selectedProductFlags = useMemo(() => { if (!selectedProduct) return []; @@ -244,31 +209,6 @@ const InventoryAdjustmentForm = ({ return (product?.flags as string[]) || []; }, [selectedProduct, productOptions]); - const ProductOption = useMemo(() => { - const OptionComponent = ( - props: OptionProps - ) => { - const { data, children } = props; - const quantity = data.quantity ?? 0; - const isAvailable = quantity > 0; - - return ( - -
- {children} - -
-
- ); - }; - OptionComponent.displayName = 'ProductOption'; - return OptionComponent; - }, []); - const kandangOptions = useMemo(() => { let options: OptionType[] = []; @@ -378,42 +318,6 @@ const InventoryAdjustmentForm = ({ return transactionType === 'PEMBELIAN' || transactionType === 'PENJUALAN'; }, [selectedTransactionType]); - useEffect(() => { - const subtype = selectedTransactionSubtype?.value; - if ( - subtype === 'RECORDING_STOCK_OUT' || - subtype === 'RECORDING_DEPLETION_OUT' || - subtype === 'MARKETING_OUT' - ) { - setQuantityLabel('Kurangi Stok'); - } else if (subtype === 'RECORDING_EGG_IN' || subtype === 'PURCHASE_IN') { - setQuantityLabel('Tambah Stok'); - } else { - setQuantityLabel('Kuantitas'); - } - }, [selectedTransactionSubtype]); - - useEffect(() => { - const qty = Number(formik.values.qty); - if ( - isStockOutSubtype && - selectedProduct && - qty > 0 && - qty > selectedProductQuantity - ) { - setQuantityError( - `Kuantitas ${formatNumber(qty)} melebihi stok tersedia (${formatNumber(selectedProductQuantity)})` - ); - } else { - setQuantityError(''); - } - }, [ - formik.values.qty, - isStockOutSubtype, - selectedProduct, - selectedProductQuantity, - ]); - useEffect(() => { if (selectedTransactionType?.value === 'RECORDING' && selectedProduct) { setSelectedTransactionSubtype(null); @@ -541,7 +445,6 @@ const InventoryAdjustmentForm = ({ const resetHandler = () => { formik.resetForm(); - setQuantityLabel('Kuantitas'); setSelectedLocation(null); setSelectedProjectFlock(null); setSelectedKandang(null); @@ -764,7 +667,6 @@ const InventoryAdjustmentForm = ({ onChange={productChangeHandler} onInputChange={setProductInputValue} options={productOptions} - optionComponent={ProductOption} onMenuScrollToBottom={loadMoreProducts} isLoading={isLoadingProductOptions} isError={ @@ -777,14 +679,6 @@ const InventoryAdjustmentForm = ({ ? 'Pilih Produk' : 'Pilih Kandang terlebih dahulu' } - inputPrefix={ - selectedProduct - ? 'Stock: ' + - (productOptions.find( - (opt) => opt.value === selectedProduct?.value - )?.quantity ?? 0) - : undefined - } isClearable isSearchable /> @@ -841,22 +735,14 @@ const InventoryAdjustmentForm = ({ wrapper: `${selectedTransactionSubtype ? '' : 'hidden'}`, }} required - label={quantityLabel} + label='Kuantitas' name='qty' value={formik.values.qty} onChange={formik.handleChange} onBlur={formik.handleBlur} - isError={ - (formik.touched.qty && Boolean(formik.errors.qty)) || - Boolean(quantityError) - } - errorMessage={(formik.errors.qty as string) || quantityError} + isError={formik.touched.qty && Boolean(formik.errors.qty)} + errorMessage={formik.errors.qty as string} readOnly={type === 'detail'} - bottomLabel={ - selectedProduct - ? `Tersedia: ${formatNumber(selectedProductQuantity)}` - : undefined - } /> {/* Number Input Price */} Submit