mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
refactor(FE-208,212): enhance PurchaseRequestForm with location and warehouse handling, update validation and reset logic for dependent fields
This commit is contained in:
@@ -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 = ({
|
||||
<SelectInput
|
||||
required
|
||||
label='Lokasi'
|
||||
placeholder='Pilih Lokasi...'
|
||||
placeholder={
|
||||
!formik.values.area_id
|
||||
? 'Pilih Area terlebih dahulu'
|
||||
: 'Pilih Lokasi...'
|
||||
}
|
||||
value={formik.values.location}
|
||||
onChange={locationChangeHandler}
|
||||
options={locationOptions}
|
||||
@@ -466,8 +568,8 @@ const PurchaseRequestForm = ({
|
||||
Boolean(formik.errors.location_id)
|
||||
}
|
||||
errorMessage={formik.errors.location_id as string}
|
||||
isDisabled={type === 'detail'}
|
||||
isClearable
|
||||
isDisabled={type === 'detail' || !formik.values.area_id}
|
||||
isClearable={type !== 'detail' && !!formik.values.area_id}
|
||||
/>
|
||||
|
||||
<div className={type === 'detail' ? 'col-span-1' : 'col-span-2'}>
|
||||
@@ -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',
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user