diff --git a/src/components/pages/purchase/form/PurchaseRequestForm.tsx b/src/components/pages/purchase/form/PurchaseRequestForm.tsx index 5f15e54e..0f7b7225 100644 --- a/src/components/pages/purchase/form/PurchaseRequestForm.tsx +++ b/src/components/pages/purchase/form/PurchaseRequestForm.tsx @@ -164,12 +164,7 @@ const PurchaseRequestForm = ({ isLoadingOptions: isLoadingAreas, } = useSelect(AreaApi.basePath, 'id', 'name', 'search'); - const { - inputValue: locationSelectInputValue, - setInputValue: setLocationSelectInputValue, - options: locationOptions, - isLoadingOptions: isLoadingLocations, - } = useSelect(LocationApi.basePath, 'id', 'name', 'search'); + const [locationSelectInputValue, setLocationSelectInputValue] = useState(''); const { inputValue: warehouseSelectInputValue, @@ -177,34 +172,12 @@ const PurchaseRequestForm = ({ isLoadingOptions: isLoadingWarehouses, } = useSelect(WarehouseApi.basePath, 'id', 'name', 'search'); - const warehousesUrl = `${WarehouseApi.basePath}?${new URLSearchParams({ search: warehouseSelectInputValue }).toString()}`; - const { data: warehouses } = useSWR( - warehousesUrl, - WarehouseApi.getAllFetcher - ); - - // ===== DATA PROCESSING ===== - const warehouseOptions = useMemo(() => { - if (!isResponseSuccess(warehouses)) return []; - - return ( - warehouses?.data.map((w) => ({ - value: w.id, - label: w.name, - area: w.area?.name, - location: - 'type' in w && (w.type === 'LOKASI' || w.type === 'KANDANG') - ? w.location?.name - : undefined, - })) || [] - ); - }, [warehouses]); - // ===== PRODUCT WAREHOUSE FETCHING ===== const getProductWarehousesUrl = useCallback(() => { const productWarehouseParams = new URLSearchParams({ search: productWarehouseSelectInputValue, }); + return `${ProductWarehouseApi.basePath}?${productWarehouseParams.toString()}`; }, [productWarehouseSelectInputValue]); @@ -212,6 +185,33 @@ const PurchaseRequestForm = ({ const { data: productWarehouses, isLoading: isLoadingProductWarehouses } = useSWR(productWarehousesUrl, ProductWarehouseApi.getAllFetcher); + // Filter product warehouses per item based on selected warehouse + const getProductWarehouseOptionsForItem = useCallback( + (warehouseId: number | string) => { + if (!isResponseSuccess(productWarehouses)) return []; + + const warehouseIdNum = + typeof warehouseId === 'string' + ? parseInt(warehouseId) || 0 + : warehouseId; + if (warehouseIdNum === 0) return []; + + return ( + productWarehouses?.data + .filter((pw) => pw.warehouse.id === warehouseIdNum) + .map((pw) => ({ + value: pw.product.id, + label: pw.product.name, + product_id: pw.product.id, + warehouse_id: pw.warehouse.id, + warehouse_name: pw.warehouse.name, + quantity: pw.quantity, + })) || [] + ); + }, + [productWarehouses] + ); + const productWarehouseOptions = isResponseSuccess(productWarehouses) ? productWarehouses?.data.map((pw) => ({ value: pw.product.id, @@ -281,6 +281,71 @@ const PurchaseRequestForm = ({ }, }); + // ===== API DATA FETCHING ===== + const locationsUrl = useMemo(() => { + const params = new URLSearchParams({ + search: locationSelectInputValue, + ...(formik.values.area_id && formik.values.area_id > 0 + ? { area_id: formik.values.area_id.toString() } + : {}), + }); + return `${LocationApi.basePath}?${params.toString()}`; + }, [locationSelectInputValue, formik.values.area_id]); + + const { data: locations, isLoading: isLoadingLocations } = useSWR( + locationsUrl, + LocationApi.getAllFetcher + ); + + const locationOptions = useMemo(() => { + if (!isResponseSuccess(locations)) return []; + return ( + locations?.data.map((location) => ({ + value: location.id, + label: location.name, + })) || [] + ); + }, [locations]); + + const warehousesUrl = useMemo(() => { + const params = new URLSearchParams({ search: warehouseSelectInputValue }); + + if (formik.values.area_id && formik.values.area_id > 0) { + params.append('area_id', formik.values.area_id.toString()); + } + + if (formik.values.location_id && formik.values.location_id > 0) { + params.append('location_id', formik.values.location_id.toString()); + } + + return `${WarehouseApi.basePath}?${params.toString()}`; + }, [ + warehouseSelectInputValue, + formik.values.area_id, + formik.values.location_id, + ]); + + const { data: warehouses } = useSWR( + warehousesUrl, + WarehouseApi.getAllFetcher + ); + + const warehouseOptions = useMemo(() => { + if (!isResponseSuccess(warehouses)) return []; + + return ( + warehouses?.data.map((w) => ({ + value: w.id, + label: w.name, + area: w.area?.name, + location: + 'type' in w && (w.type === 'LOKASI' || w.type === 'KANDANG') + ? w.location?.name + : undefined, + })) || [] + ); + }, [warehouses]); + // ===== EVENT HANDLERS ===== const supplierChangeHandler = (val: OptionType | OptionType[] | null) => { const supplier = val as OptionType | null; @@ -296,6 +361,25 @@ const PurchaseRequestForm = ({ formik.setFieldValue('area', area); formik.setFieldTouched('area_id', true); formik.setFieldValue('area_id', (area as OptionType)?.value || 0); + + // Reset area dependent fields + formik.setFieldValue('location', null); + formik.setFieldValue('location_id', 0); + setLocationSelectInputValue(''); + + // Reset area dependent fields in all purchase items + if (formik.values.purchase_items) { + formik.values.purchase_items.forEach((_, idx) => { + formik.setFieldValue(`purchase_items.${idx}.warehouse`, null); + formik.setFieldValue(`purchase_items.${idx}.warehouse_id`, ''); + formik.setFieldValue(`purchase_items.${idx}.product_warehouse`, null); + formik.setFieldValue( + `purchase_items.${idx}.product_warehouse_id`, + null + ); + formik.setFieldValue(`purchase_items.${idx}.product_id`, ''); + }); + } }; const locationChangeHandler = (val: OptionType | OptionType[] | null) => { @@ -304,6 +388,20 @@ const PurchaseRequestForm = ({ formik.setFieldValue('location', location); formik.setFieldTouched('location_id', true); formik.setFieldValue('location_id', (location as OptionType)?.value || 0); + + // Reset location dependent fields in all purchase items + if (formik.values.purchase_items) { + formik.values.purchase_items.forEach((_, idx) => { + formik.setFieldValue(`purchase_items.${idx}.warehouse`, null); + formik.setFieldValue(`purchase_items.${idx}.warehouse_id`, ''); + formik.setFieldValue(`purchase_items.${idx}.product_warehouse`, null); + formik.setFieldValue( + `purchase_items.${idx}.product_warehouse_id`, + null + ); + formik.setFieldValue(`purchase_items.${idx}.product_id`, ''); + }); + } }; // Purchase Items Handlers @@ -455,7 +553,11 @@ const PurchaseRequestForm = ({
@@ -577,6 +679,18 @@ const PurchaseRequestForm = ({ `purchase_items.${idx}.warehouse_id`, (warehouse as OptionType)?.value || 0 ); + formik.setFieldValue( + `purchase_items.${idx}.product_warehouse`, + null + ); + formik.setFieldValue( + `purchase_items.${idx}.product_warehouse_id`, + null + ); + formik.setFieldValue( + `purchase_items.${idx}.product_id`, + '' + ); }} options={warehouseOptions} onInputChange={setWarehouseSelectInputValue} @@ -618,7 +732,9 @@ const PurchaseRequestForm = ({ ?.product_id || 0 ); }} - options={productWarehouseOptions} + options={getProductWarehouseOptionsForItem( + item.warehouse_id + )} onInputChange={setProductWarehouseSelectInputValue} isLoading={isLoadingProductWarehouses} isError={ @@ -629,9 +745,13 @@ const PurchaseRequestForm = ({ getPurchaseItemError(idx, 'product_warehouse_id') .errorMessage } - isDisabled={type === 'detail'} - isClearable - placeholder='Pilih Produk' + isDisabled={type === 'detail' || !item.warehouse_id} + isClearable={type !== 'detail' && !!item.warehouse_id} + placeholder={ + !item.warehouse_id + ? 'Pilih Gudang terlebih dahulu' + : 'Pilih Produk' + } className={{ wrapper: 'min-w-32', }}