diff --git a/src/components/pages/purchase/form/request/PurchaseRequestForm.schema.ts b/src/components/pages/purchase/form/request/PurchaseRequestForm.schema.ts index 06c8606d..a2ecdce3 100644 --- a/src/components/pages/purchase/form/request/PurchaseRequestForm.schema.ts +++ b/src/components/pages/purchase/form/request/PurchaseRequestForm.schema.ts @@ -18,18 +18,13 @@ type PurchaseRequestFormSchemaType = { label: string; } | null; location_id: number; - warehouse?: { - value: number; - label: string; - } | null; - warehouse_id: number; notes: string | null; items: { - product_warehouse?: { + warehouse?: { value: number; label: string; } | null; - product_warehouse_id: number; + warehouse_id: number; product?: { value: number; label: string; @@ -40,11 +35,11 @@ type PurchaseRequestFormSchemaType = { }; export type PurchaseItemSchema = { - product_warehouse?: { + warehouse?: { value: number; label: string; } | null; - product_warehouse_id: number; + warehouse_id: number; product?: { value: number; label: string; @@ -55,14 +50,14 @@ export type PurchaseItemSchema = { const PurchaseItemObjectSchema: Yup.ObjectSchema = Yup.object({ - product_warehouse: Yup.object({ + warehouse: Yup.object({ value: Yup.number().min(1).required(), label: Yup.string().required(), }).nullable(), - product_warehouse_id: Yup.number() - .required('Produk wajib dipilih!') - .min(1, 'Produk wajib dipilih!') - .typeError('Produk wajib dipilih!'), + warehouse_id: Yup.number() + .required('Gudang wajib dipilih!') + .min(1, 'Gudang wajib dipilih!') + .typeError('Gudang wajib dipilih!'), product: Yup.object({ value: Yup.number().min(1).required(), label: Yup.string().required(), @@ -107,14 +102,6 @@ export const PurchaseRequestFormSchema: Yup.ObjectSchema { if (!formik.touched.items || !Array.isArray(formik.touched.items)) { return { @@ -83,7 +79,13 @@ const PurchaseRequestForm = ({ }; } - const touchedField = formik.touched.items[idx]?.[field]; + const touchedField = ( + formik.touched.items[idx] as Partial<{ + warehouse_id: boolean; + product_id: boolean; + qty: boolean; + }> + )?.[field]; const errorItem = formik.errors.items?.[idx] as | Record | undefined; @@ -142,7 +144,6 @@ const PurchaseRequestForm = ({ // ===== SELECT INPUT DATA ===== const { - inputValue: supplierSelectInputValue, setInputValue: setSupplierSelectInputValue, options: supplierOptions, isLoadingOptions: isLoadingSuppliers, @@ -150,7 +151,6 @@ const PurchaseRequestForm = ({ } = useSelect(SupplierApi.basePath, 'id', 'name', 'search'); const { - inputValue: areaSelectInputValue, setInputValue: setAreaSelectInputValue, options: areaOptions, isLoadingOptions: isLoadingAreas, @@ -176,27 +176,23 @@ const PurchaseRequestForm = ({ : PurchaseRequestFormSchema, validateOnChange: true, validateOnBlur: true, + validateOnMount: false, + enableReinitialize: true, onSubmit: async (values) => { const payload: CreatePurchaseRequestPayload = { supplier_id: typeof values.supplier_id === 'string' ? parseInt(values.supplier_id) || 0 : values.supplier_id || 0, - credit_term: values.credit_term || 0, + credit_term: + typeof values.credit_term === 'string' + ? parseInt(values.credit_term) || 0 + : values.credit_term || 0, notes: values.notes || '', items: (values.items || []).map((item) => ({ - warehouse_id: - typeof values.warehouse_id === 'string' - ? parseInt(values.warehouse_id) || 0 - : values.warehouse_id || 0, - product_id: - typeof item.product_id === 'string' - ? parseInt(item.product_id) || 0 - : item.product_id || 0, - qty: - typeof item.qty === 'string' - ? parseFloat(item.qty) || 0 - : item.qty || 0, + warehouse_id: Number(item.warehouse_id) || 0, + product_id: Number(item.product_id) || 0, + qty: Number(item.qty) || 0, })), }; @@ -215,57 +211,22 @@ const PurchaseRequestForm = ({ }); // ===== API DATA FETCHING ===== - const productWarehousesUrl = useMemo(() => { - if (!formik.values.warehouse_id || formik.values.warehouse_id === 0) { - return null; - } - - const params = new URLSearchParams({ - warehouse_id: formik.values.warehouse_id.toString(), - }); - - return `${ProductWarehouseApi.basePath}?${params.toString()}`; - }, [formik.values.warehouse_id]); - - const { data: productWarehouses, isLoading: isLoadingProductWarehouses } = - useSWR(productWarehousesUrl, ProductWarehouseApi.getAllFetcher); - - const getProductWarehouseOptionsForItem = useCallback(() => { - if (!isResponseSuccess(productWarehouses)) return []; - - return ( - productWarehouses?.data.map((pw) => ({ - value: pw.id, - label: pw.product.name, - product_id: pw.product.id, - product_warehouse_id: pw.id, - warehouse_id: pw.warehouse.id, - warehouse_name: pw.warehouse.name, - qty: pw.quantity, - })) || [] - ); - }, [productWarehouses]); - - const productUrl = useMemo(() => { - const productIds = - formik.values.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.items]); - - const { data: productsResponse } = useSWR( - productUrl, + const { data: productsResponse, isLoading: isLoadingProducts } = useSWR( + `${ProductApi.basePath}`, ProductApi.getAllFetcher ); + const productOptions = useMemo(() => { + if (!isResponseSuccess(productsResponse)) return []; + + return ( + productsResponse?.data.map((product: Product) => ({ + value: product.id, + label: product.name, + })) || [] + ); + }, [productsResponse]); + const productData = useMemo(() => { if (!isResponseSuccess(productsResponse)) return {}; @@ -340,19 +301,18 @@ const PurchaseRequestForm = ({ ); }, [warehouses]); - // Purchase Items Handlers const addPurchaseItem = () => { - const newPurchaseItems = [ + const newItems = [ ...(formik.values.items || []), { - product_warehouse: null, - product_warehouse_id: null, + warehouse: null, + warehouse_id: 0, product: null, - product_id: '', - qty: '', + product_id: 0, + qty: 0, }, ]; - formik.setFieldValue('items', newPurchaseItems); + formik.setFieldValue('items', newItems); }; const removePurchaseItem = (idx: number) => { @@ -445,9 +405,25 @@ const PurchaseRequestForm = ({ supplierData.due_date.toString() ); } + + if (formik.values.items) { + formik.values.items.forEach((_, idx) => { + formik.setFieldValue(`items.${idx}.product`, null); + formik.setFieldValue(`items.${idx}.product_id`, 0); + formik.setFieldValue(`items.${idx}.qty`, 0); + }); + } } else { formik.setFieldTouched('credit_term', false); formik.setFieldValue('credit_term', ''); + + if (formik.values.items) { + formik.values.items.forEach((_, idx) => { + formik.setFieldValue(`items.${idx}.product`, null); + formik.setFieldValue(`items.${idx}.product_id`, 0); + formik.setFieldValue(`items.${idx}.qty`, 0); + }); + } } }} options={supplierOptions} @@ -508,16 +484,8 @@ const PurchaseRequestForm = ({ if (formik.values.items) { formik.values.items.forEach((_, idx) => { - formik.setFieldValue( - `items.${idx}.product_warehouse`, - null - ); - formik.setFieldValue( - `items.${idx}.product_warehouse_id`, - null - ); formik.setFieldValue(`items.${idx}.product`, null); - formik.setFieldValue(`items.${idx}.product_id`, ''); + formik.setFieldValue(`items.${idx}.product_id`, 0); }); } }} @@ -553,16 +521,8 @@ const PurchaseRequestForm = ({ if (formik.values.items) { formik.values.items.forEach((_, idx) => { - formik.setFieldValue( - `items.${idx}.product_warehouse`, - null - ); - formik.setFieldValue( - `items.${idx}.product_warehouse_id`, - null - ); formik.setFieldValue(`items.${idx}.product`, null); - formik.setFieldValue(`items.${idx}.product_id`, ''); + formik.setFieldValue(`items.${idx}.product_id`, 0); }); } }} @@ -691,45 +651,42 @@ const PurchaseRequestForm = ({ ? 'Pilih Gudang...' : 'Pilih Area dan Lokasi terlebih dahulu' } - value={formik.values.warehouse} + value={item.warehouse} onChange={(val) => { const warehouse = val as OptionType | null; - formik.setFieldTouched('warehouse_id', true); - formik.setFieldValue( - 'warehouse_id', - (warehouse as OptionType)?.value || 0 + const warehouseId = + (warehouse as OptionType)?.value || 0; + + formik.setFieldTouched( + `items.${idx}.warehouse`, + true ); - formik.setFieldTouched('warehouse', true); - formik.setFieldValue('warehouse', warehouse); - if (formik.values.items) { - formik.values.items.forEach((_, idx) => { - formik.setFieldValue( - `items.${idx}.product_warehouse`, - null - ); - formik.setFieldValue( - `items.${idx}.product_warehouse_id`, - null - ); - formik.setFieldValue( - `items.${idx}.product`, - null - ); - formik.setFieldValue( - `items.${idx}.product_id`, - '' - ); - }); - } + formik.setFieldValue( + `items.${idx}.warehouse`, + warehouse + ); + formik.setFieldTouched( + `items.${idx}.warehouse_id`, + true + ); + formik.setFieldValue( + `items.${idx}.warehouse_id`, + warehouseId + ); + + formik.setFieldValue(`items.${idx}.product`, null); + formik.setFieldValue(`items.${idx}.product_id`, 0); }} options={warehouseOptions} onInputChange={setWarehouseSelectInputValue} isLoading={isLoadingWarehouses} isError={ - formik.touched.warehouse_id && - Boolean(formik.errors.warehouse_id) + isRepeaterInputError(idx, 'warehouse_id').isError + } + errorMessage={ + isRepeaterInputError(idx, 'warehouse_id') + .errorMessage } - errorMessage={formik.errors.warehouse_id as string} isDisabled={ type === 'detail' || !formik.values.area_id || @@ -746,32 +703,20 @@ const PurchaseRequestForm = ({ { - const productWarehouse = - val as ProductWarehouseOptionType | null; - formik.setFieldTouched( - `items.${idx}.product_warehouse`, - true - ); - formik.setFieldValue( - `items.${idx}.product_warehouse`, - productWarehouse - ); - formik.setFieldTouched( - `items.${idx}.product_warehouse_id`, - true - ); - formik.setFieldValue( - `items.${idx}.product_warehouse_id`, - (productWarehouse as ProductWarehouseOptionType) - ?.value || 0 - ); - + const product = val as ProductOptionType | null; const productId = - (productWarehouse as ProductWarehouseOptionType) - ?.product_id || 0; + (product as ProductOptionType)?.value || 0; + + formik.setFieldTouched( + `items.${idx}.product`, + true + ); + formik.setFieldValue( + `items.${idx}.product`, + product + ); formik.setFieldTouched( `items.${idx}.product_id`, true @@ -781,27 +726,17 @@ const PurchaseRequestForm = ({ productId ); }} - options={getProductWarehouseOptionsForItem()} - isLoading={isLoadingProductWarehouses} + options={productOptions} + isLoading={isLoadingProducts} isError={ - isRepeaterInputError(idx, 'product_warehouse_id') - .isError + isRepeaterInputError(idx, 'product_id').isError } errorMessage={ - isRepeaterInputError(idx, 'product_warehouse_id') - .errorMessage - } - isDisabled={ - type === 'detail' || !formik.values.warehouse_id - } - isClearable={ - type !== 'detail' && !!formik.values.warehouse_id - } - placeholder={ - !formik.values.warehouse_id - ? 'Pilih Gudang terlebih dahulu' - : 'Pilih Produk' + isRepeaterInputError(idx, 'product_id').errorMessage } + isDisabled={type === 'detail'} + isClearable={type !== 'detail'} + placeholder='Pilih Produk' className={{ wrapper: 'min-w-32', }} @@ -841,7 +776,7 @@ const PurchaseRequestForm = ({ ).toLocaleString('en-US') : '' } - onChange={(e) => {}} + onChange={() => {}} onBlur={formik.handleBlur} type='text' className={{