refactor(FE-208,212): enhance PurchaseRequestForm with product data fetching, update price and UOM fields based on selected products

This commit is contained in:
rstubryan
2025-11-04 08:56:57 +07:00
parent ee24ceaff1
commit 289c8d5672
@@ -27,8 +27,10 @@ import {
AreaApi,
LocationApi,
WarehouseApi,
ProductApi,
} from '@/services/api/master-data';
import { Supplier } from '@/types/api/master-data/supplier';
import { Product } from '@/types/api/master-data/product';
import { ProductWarehouseApi } from '@/services/api/inventory';
import { isResponseSuccess, isResponseError } from '@/lib/api-helper';
import { PurchaseApi } from '@/services/api/purchasing';
@@ -63,11 +65,6 @@ const PurchaseRequestForm = ({
] = useState('');
// ===== INTERFACES =====
interface WarehouseOptionType extends OptionType {
area?: string;
location?: string;
}
interface ProductWarehouseOptionType extends OptionType {
product_id: number;
warehouse_id: number;
@@ -293,6 +290,37 @@ const PurchaseRequestForm = ({
},
});
// ===== PRODUCT DATA FETCHING =====
const productUrl = useMemo(() => {
const productIds =
formik.values.purchase_items
?.filter(
(item) => item.product_id && typeof item.product_id === 'number'
)
.map((item) => item.product_id as number) || [];
return productIds.length > 0
? `${ProductApi.basePath}?${new URLSearchParams({
id: productIds.join(','),
}).toString()}`
: null;
}, [formik.values.purchase_items]);
const { data: productsResponse } = useSWR(
productUrl,
ProductApi.getAllFetcher
);
const productData = useMemo(() => {
if (!isResponseSuccess(productsResponse)) return {};
const data: Record<number, Product> = {};
productsResponse?.data?.forEach((product: Product) => {
data[product.id] = product;
});
return data;
}, [productsResponse]);
// ===== API DATA FETCHING =====
const locationsUrl = useMemo(() => {
const params = new URLSearchParams({
@@ -760,10 +788,12 @@ const PurchaseRequestForm = ({
(productWarehouse as ProductWarehouseOptionType)
?.value || 0
);
const productId =
(productWarehouse as ProductWarehouseOptionType)
?.product_id || 0;
formik.setFieldValue(
`purchase_items.${idx}.product_id`,
(productWarehouse as ProductWarehouseOptionType)
?.product_id || 0
productId
);
}}
options={getProductWarehouseOptionsForItem(
@@ -821,6 +851,16 @@ const PurchaseRequestForm = ({
<TextInput
required
name={`purchase_items.${idx}.price`}
value={
item.product_id && productData[item.product_id]
? (
productData[item.product_id].product_price *
(parseFloat(
item.sub_qty?.toString() || '0'
) || 0)
).toLocaleString('en-US')
: ''
}
onChange={(e) =>
handlePurchaseItemChange(
idx,
@@ -829,26 +869,48 @@ const PurchaseRequestForm = ({
)
}
onBlur={formik.handleBlur}
type='number'
type='text'
className={{
wrapper: 'min-w-24',
}}
disabled={true}
readOnly={true}
inputPrefix={'Rp'}
placeholder={
item.product_id
? 'Loading...'
: 'Pilih produk terlebih dahulu'
}
bottomLabel={
item.product_id && productData[item.product_id]
? `Harga per unit: Rp ${productData[
item.product_id
].product_price.toLocaleString('en-US')}`
: ''
}
/>
</td>
<td>
<TextInput
required
name={`purchase_items.${idx}.uom`}
value={
item.product_id && productData[item.product_id]
? productData[item.product_id].uom.name
: ''
}
onBlur={formik.handleBlur}
type='number'
type='text'
readOnly={true}
disabled={true}
className={{
wrapper: 'min-w-24',
}}
placeholder={
item.product_id
? 'Loading...'
: 'Pilih produk terlebih dahulu'
}
/>
</td>
{type !== 'detail' && (