refactor(FE-208): enhance PurchaseRequestForm to fetch and display supplier-specific products

This commit is contained in:
rstubryan
2025-11-21 18:54:17 +07:00
parent 95a7afdaa6
commit b9990e0253
2 changed files with 59 additions and 31 deletions
@@ -30,9 +30,9 @@ import {
WarehouseApi, WarehouseApi,
ProductApi, ProductApi,
} from '@/services/api/master-data'; } from '@/services/api/master-data';
import { Supplier } from '@/types/api/master-data/supplier'; import { Supplier, SupplierProducts } from '@/types/api/master-data/supplier';
import { Product } from '@/types/api/master-data/product';
import { isResponseSuccess, isResponseError } from '@/lib/api-helper'; import { isResponseSuccess, isResponseError } from '@/lib/api-helper';
import { formatNumber } from '@/lib/helper';
import { PurchaseApi } from '@/services/api/purchase'; import { PurchaseApi } from '@/services/api/purchase';
import Card from '@/components/Card'; import Card from '@/components/Card';
@@ -148,7 +148,9 @@ const PurchaseRequestForm = ({
options: supplierOptions, options: supplierOptions,
isLoadingOptions: isLoadingSuppliers, isLoadingOptions: isLoadingSuppliers,
rawData: supplierRawData, rawData: supplierRawData,
} = useSelect<Supplier>(SupplierApi.basePath, 'id', 'name', 'search'); } = useSelect<Supplier>(SupplierApi.basePath, 'id', 'name', 'search', {
category: 'SAPRONAK',
});
const { const {
setInputValue: setAreaSelectInputValue, setInputValue: setAreaSelectInputValue,
@@ -211,31 +213,39 @@ const PurchaseRequestForm = ({
}); });
// ===== API DATA FETCHING ===== // ===== API DATA FETCHING =====
const { data: productsResponse, isLoading: isLoadingProducts } = useSWR( const { data: supplierData, isLoading: isLoadingProducts } = useSWR(
`${ProductApi.basePath}`, formik.values.supplier_id?.toString(),
ProductApi.getAllFetcher (id: string) => SupplierApi.getSingle(Number(id))
); );
const productOptions = useMemo(() => { const supplierProductOptions = useMemo(() => {
if (!isResponseSuccess(productsResponse)) return []; if (!supplierData || !isResponseSuccess(supplierData)) {
return [];
}
return ( const supplier = supplierData.data as SupplierProducts;
productsResponse?.data.map((product: Product) => ({ const products = supplier.products || [];
value: product.id, return products.map((product) => ({
label: product.name, value: product.id,
})) || [] label: product.name,
); }));
}, [productsResponse]); }, [supplierData]);
const productData = useMemo(() => { const supplierProductData = useMemo(() => {
if (!isResponseSuccess(productsResponse)) return {}; if (!supplierData || !isResponseSuccess(supplierData)) {
return {};
}
const data: Record<number, Product> = {}; const supplier = supplierData.data as SupplierProducts;
productsResponse?.data?.forEach((product: Product) => { const products = supplier.products || [];
const data: Record<number, NonNullable<typeof supplier.products>[0]> = {};
products.forEach((product) => {
data[product.id] = product; data[product.id] = product;
}); });
return data; return data;
}, [productsResponse]); }, [supplierData]);
const locationsUrl = useMemo(() => { const locationsUrl = useMemo(() => {
const params = new URLSearchParams({ const params = new URLSearchParams({
@@ -704,7 +714,7 @@ const PurchaseRequestForm = ({
productId productId
); );
}} }}
options={productOptions} options={supplierProductOptions}
isLoading={isLoadingProducts} isLoading={isLoadingProducts}
isError={ isError={
isRepeaterInputError(idx, 'product_id').isError isRepeaterInputError(idx, 'product_id').isError
@@ -764,11 +774,13 @@ const PurchaseRequestForm = ({
required required
name={`items.${idx}.price`} name={`items.${idx}.price`}
value={ value={
item.product_id && productData[item.product_id] item.product_id &&
? ( supplierProductData[item.product_id]
productData[item.product_id].product_price * ? formatNumber(
supplierProductData[item.product_id]
.ProductPrice *
(parseFloat(item.qty?.toString() || '0') || 0) (parseFloat(item.qty?.toString() || '0') || 0)
).toLocaleString('en-US') )
: '' : ''
} }
onChange={() => {}} onChange={() => {}}
@@ -786,10 +798,13 @@ const PurchaseRequestForm = ({
: 'Pilih produk terlebih dahulu' : 'Pilih produk terlebih dahulu'
} }
bottomLabel={ bottomLabel={
item.product_id && productData[item.product_id] item.product_id &&
? `Harga per unit: Rp ${productData[ supplierProductData[item.product_id]
item.product_id ? `Harga per unit: Rp ${formatNumber(
].product_price.toLocaleString('en-US')}` supplierProductData[
item.product_id
].ProductPrice
)}`
: '' : ''
} }
/> />
@@ -799,8 +814,9 @@ const PurchaseRequestForm = ({
required required
name={`items.${idx}.uom`} name={`items.${idx}.uom`}
value={ value={
item.product_id && productData[item.product_id] item.product_id &&
? productData[item.product_id].uom.name supplierProductData[item.product_id]
? supplierProductData[item.product_id].uom.name
: '' : ''
} }
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
+12
View File
@@ -1,4 +1,5 @@
import { BaseMetadata } from '@/types/api/api-general'; import { BaseMetadata } from '@/types/api/api-general';
import { Uom } from '@/types/api/master-data/uom';
export type BaseSupplier = { export type BaseSupplier = {
id: number; id: number;
@@ -19,6 +20,17 @@ export type BaseSupplier = {
export type Supplier = BaseMetadata & BaseSupplier; export type Supplier = BaseMetadata & BaseSupplier;
export type SupplierProducts = Supplier & {
products?: Array<{
id: number;
name: string;
ProductPrice: number;
SellingPrice?: number;
uom: Uom;
flags: string[];
}>;
};
export type CreateSupplierPayload = { export type CreateSupplierPayload = {
name: string; name: string;
alias: string; alias: string;