mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
refactor(FE): Add depletion product handling in inventory adjustment
forms
This commit is contained in:
@@ -282,6 +282,9 @@ const InventoryAdjustmentTable = () => {
|
||||
if (recordingOption) {
|
||||
return recordingOption.label;
|
||||
}
|
||||
if (subtypeValue === 'RECORDING_DEPLETION_OUT') {
|
||||
return 'Recording Depletion';
|
||||
}
|
||||
return subtypeValue || '-';
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,11 @@ export type InventoryAdjustmentFormSchemaType = {
|
||||
label: string;
|
||||
} | null;
|
||||
product_id: number;
|
||||
depletion_product: {
|
||||
value: number;
|
||||
label: string;
|
||||
} | null;
|
||||
depletion_product_id: number;
|
||||
transaction_type: string;
|
||||
transaction_subtype: string;
|
||||
qty: number | string;
|
||||
@@ -80,6 +85,13 @@ export const InventoryAdjustmentFormSchema: Yup.ObjectSchema<InventoryAdjustment
|
||||
.min(1, 'Produk wajib diisi!')
|
||||
.required('Produk wajib diisi!')
|
||||
.typeError('Produk wajib diisi!'),
|
||||
depletion_product: Yup.object({
|
||||
value: Yup.number().min(1).required(),
|
||||
label: Yup.string().required(),
|
||||
}).nullable(),
|
||||
depletion_product_id: Yup.number()
|
||||
.default(0)
|
||||
.typeError('Jenis deplesi harus berupa angka'),
|
||||
transaction_type: Yup.string()
|
||||
.min(1, 'Tipe transaksi wajib diisi!')
|
||||
.oneOf(
|
||||
|
||||
@@ -74,6 +74,8 @@ const InventoryAdjustmentForm = ({
|
||||
useState<OptionType | null>(null);
|
||||
const [selectedTransactionSubtype, setSelectedTransactionSubtype] =
|
||||
useState<OptionType | null>(null);
|
||||
const [selectedDepletionProduct, setSelectedDepletionProduct] =
|
||||
useState<OptionType | null>(null);
|
||||
const [selectedProjectFlockLocationId, setSelectedProjectFlockLocationId] =
|
||||
useState<string>('');
|
||||
|
||||
@@ -185,6 +187,15 @@ const InventoryAdjustmentForm = ({
|
||||
rawData: products,
|
||||
} = useSelect<Product>(ProductApi.basePath, 'id', 'name', 'search');
|
||||
|
||||
const {
|
||||
setInputValue: setDepletionProductInputValue,
|
||||
options: depletionProductOptions,
|
||||
isLoadingOptions: isLoadingDepletionProductOptions,
|
||||
loadMore: loadMoreDepletionProducts,
|
||||
} = useSelect<Product>(ProductApi.basePath, 'id', 'name', 'search', {
|
||||
is_depletion: 'true',
|
||||
});
|
||||
|
||||
const productOptions = useMemo(() => {
|
||||
if (!isResponseSuccess(products)) return [];
|
||||
|
||||
@@ -241,6 +252,8 @@ const InventoryAdjustmentForm = ({
|
||||
project_flock_kandang_id: 0,
|
||||
product: null,
|
||||
product_id: 0,
|
||||
depletion_product: null,
|
||||
depletion_product_id: 0,
|
||||
transaction_type: '',
|
||||
transaction_subtype: '',
|
||||
qty: '',
|
||||
@@ -260,7 +273,10 @@ const InventoryAdjustmentForm = ({
|
||||
setInventoryAdjustmentFormErrorMessage('');
|
||||
const payload: CreateInventoryAdjustmentPayload = {
|
||||
project_flock_kandang_id: values.project_flock_kandang_id,
|
||||
product_id: values.product_id,
|
||||
product_id:
|
||||
values.depletion_product_id > 0
|
||||
? values.depletion_product_id
|
||||
: values.product_id,
|
||||
transaction_subtype: values.transaction_subtype,
|
||||
qty: Number(values.qty),
|
||||
price: Number(values.price),
|
||||
@@ -275,6 +291,8 @@ const InventoryAdjustmentForm = ({
|
||||
},
|
||||
});
|
||||
|
||||
const { setFieldValue, setFieldTouched, resetForm, setValues } = formik;
|
||||
|
||||
const transactionSubtypeOptions = useMemo(() => {
|
||||
const transactionType = selectedTransactionType?.value;
|
||||
|
||||
@@ -321,19 +339,31 @@ const InventoryAdjustmentForm = ({
|
||||
useEffect(() => {
|
||||
if (selectedTransactionType?.value === 'RECORDING' && selectedProduct) {
|
||||
setSelectedTransactionSubtype(null);
|
||||
formik.setFieldValue('transaction_subtype', '');
|
||||
setFieldValue('transaction_subtype', '');
|
||||
}
|
||||
}, [selectedProduct, selectedTransactionType]);
|
||||
}, [setFieldValue, selectedProduct, selectedTransactionType]);
|
||||
|
||||
const isDepletionProductVisible = useMemo(() => {
|
||||
return selectedTransactionSubtype?.value === 'RECORDING_DEPLETION_IN';
|
||||
}, [selectedTransactionSubtype]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDepletionProductVisible) {
|
||||
setSelectedDepletionProduct(null);
|
||||
setFieldValue('depletion_product', null);
|
||||
setFieldValue('depletion_product_id', 0);
|
||||
}
|
||||
}, [isDepletionProductVisible, setFieldValue]);
|
||||
|
||||
// ===== EVENT HANDLERS =====
|
||||
const locationChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||
const location = val as OptionType | null;
|
||||
const locationId = location ? Number(location.value) : 0;
|
||||
|
||||
formik.setFieldTouched('location', true);
|
||||
formik.setFieldValue('location', location);
|
||||
formik.setFieldTouched('location_id', true);
|
||||
formik.setFieldValue('location_id', locationId);
|
||||
setFieldTouched('location', true);
|
||||
setFieldValue('location', location);
|
||||
setFieldTouched('location_id', true);
|
||||
setFieldValue('location_id', locationId);
|
||||
|
||||
setSelectedLocation(location);
|
||||
setSelectedProjectFlock(null);
|
||||
@@ -348,10 +378,10 @@ const InventoryAdjustmentForm = ({
|
||||
const projectFlock = val as OptionType | null;
|
||||
const projectFlockId = Number(projectFlock?.value);
|
||||
|
||||
formik.setFieldTouched('project_flock', true);
|
||||
formik.setFieldValue('project_flock', projectFlock);
|
||||
formik.setFieldTouched('project_flock_id', true);
|
||||
formik.setFieldValue('project_flock_id', projectFlockId);
|
||||
setFieldTouched('project_flock', true);
|
||||
setFieldValue('project_flock', projectFlock);
|
||||
setFieldTouched('project_flock_id', true);
|
||||
setFieldValue('project_flock_id', projectFlockId);
|
||||
|
||||
setSelectedProjectFlock(projectFlock);
|
||||
setSelectedKandang(null);
|
||||
@@ -362,44 +392,58 @@ const InventoryAdjustmentForm = ({
|
||||
const kandang = val as OptionType | null;
|
||||
const kandangId = Number(kandang?.value);
|
||||
|
||||
formik.setFieldTouched('kandang', true);
|
||||
formik.setFieldValue('kandang', kandang);
|
||||
formik.setFieldTouched('kandang_id', true);
|
||||
formik.setFieldValue('kandang_id', kandangId);
|
||||
setFieldTouched('kandang', true);
|
||||
setFieldValue('kandang', kandang);
|
||||
setFieldTouched('kandang_id', true);
|
||||
setFieldValue('kandang_id', kandangId);
|
||||
|
||||
setSelectedKandang(kandang);
|
||||
setSelectedProduct(null);
|
||||
formik.setFieldTouched('project_flock_kandang', true);
|
||||
formik.setFieldTouched('project_flock_kandang_id', true);
|
||||
setFieldTouched('project_flock_kandang', true);
|
||||
setFieldTouched('project_flock_kandang_id', true);
|
||||
};
|
||||
|
||||
const productChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||
const product = val as OptionType | null;
|
||||
const productId = (product?.value as number) ?? 0;
|
||||
|
||||
formik.setFieldTouched('product', true);
|
||||
formik.setFieldValue('product', product);
|
||||
formik.setFieldTouched('product_id', true);
|
||||
formik.setFieldValue('product_id', productId);
|
||||
setFieldTouched('product', true);
|
||||
setFieldValue('product', product);
|
||||
setFieldTouched('product_id', true);
|
||||
setFieldValue('product_id', productId);
|
||||
|
||||
setSelectedProduct(product);
|
||||
};
|
||||
|
||||
const depletionProductChangeHandler = (
|
||||
val: OptionType | OptionType[] | null
|
||||
) => {
|
||||
const depletionProduct = val as OptionType | null;
|
||||
const depletionProductId = (depletionProduct?.value as number) ?? 0;
|
||||
|
||||
setFieldTouched('depletion_product', true);
|
||||
setFieldValue('depletion_product', depletionProduct);
|
||||
setFieldTouched('depletion_product_id', true);
|
||||
setFieldValue('depletion_product_id', depletionProductId);
|
||||
|
||||
setSelectedDepletionProduct(depletionProduct);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const transactionType = formik.values.transaction_type;
|
||||
|
||||
if (!transactionType) {
|
||||
setSelectedTransactionSubtype(null);
|
||||
formik.setFieldValue('transaction_subtype', '');
|
||||
setFieldValue('transaction_subtype', '');
|
||||
return;
|
||||
}
|
||||
|
||||
setSelectedTransactionSubtype(null);
|
||||
formik.setFieldValue('transaction_subtype', '');
|
||||
formik.setFieldTouched('transaction_subtype', true);
|
||||
setFieldValue('transaction_subtype', '');
|
||||
setFieldTouched('transaction_subtype', true);
|
||||
|
||||
if (transactionType === 'PEMBELIAN') {
|
||||
formik.setFieldValue(
|
||||
setFieldValue(
|
||||
'transaction_subtype',
|
||||
TRANSACTION_SUBTYPE_OPTIONS.PEMBELIAN.value
|
||||
);
|
||||
@@ -408,7 +452,7 @@ const InventoryAdjustmentForm = ({
|
||||
label: TRANSACTION_SUBTYPE_OPTIONS.PEMBELIAN.label,
|
||||
});
|
||||
} else if (transactionType === 'PENJUALAN') {
|
||||
formik.setFieldValue(
|
||||
setFieldValue(
|
||||
'transaction_subtype',
|
||||
TRANSACTION_SUBTYPE_OPTIONS.PENJUALAN.value
|
||||
);
|
||||
@@ -417,7 +461,7 @@ const InventoryAdjustmentForm = ({
|
||||
label: TRANSACTION_SUBTYPE_OPTIONS.PENJUALAN.label,
|
||||
});
|
||||
}
|
||||
}, [formik.values.transaction_type]);
|
||||
}, [setFieldTouched, setFieldValue, formik.values.transaction_type]);
|
||||
|
||||
const transactionTypeChangeHandler = (
|
||||
val: OptionType | OptionType[] | null
|
||||
@@ -425,8 +469,8 @@ const InventoryAdjustmentForm = ({
|
||||
const typeOption = val as OptionType | null;
|
||||
const selectedType = typeOption?.value as string;
|
||||
|
||||
formik.setFieldValue('transaction_type', selectedType);
|
||||
formik.setFieldTouched('transaction_type', true);
|
||||
setFieldValue('transaction_type', selectedType);
|
||||
setFieldTouched('transaction_type', true);
|
||||
|
||||
setSelectedTransactionType(typeOption);
|
||||
};
|
||||
@@ -437,20 +481,21 @@ const InventoryAdjustmentForm = ({
|
||||
const subtypeOption = val as OptionType | null;
|
||||
const selectedSubtype = subtypeOption?.value as string;
|
||||
|
||||
formik.setFieldTouched('transaction_subtype', true);
|
||||
formik.setFieldValue('transaction_subtype', selectedSubtype);
|
||||
setFieldTouched('transaction_subtype', true);
|
||||
setFieldValue('transaction_subtype', selectedSubtype);
|
||||
|
||||
setSelectedTransactionSubtype(subtypeOption);
|
||||
};
|
||||
|
||||
const resetHandler = () => {
|
||||
formik.resetForm();
|
||||
resetForm();
|
||||
setSelectedLocation(null);
|
||||
setSelectedProjectFlock(null);
|
||||
setSelectedKandang(null);
|
||||
setSelectedProduct(null);
|
||||
setSelectedTransactionType(null);
|
||||
setSelectedTransactionSubtype(null);
|
||||
setSelectedDepletionProduct(null);
|
||||
setSelectedProjectFlockLocationId('');
|
||||
};
|
||||
|
||||
@@ -460,14 +505,18 @@ const InventoryAdjustmentForm = ({
|
||||
projectFlockKandangLookup.project_flock_kandang_id;
|
||||
|
||||
if (formik.values.project_flock_kandang_id !== projectFlockKandangId) {
|
||||
formik.setFieldValue('project_flock_kandang_id', projectFlockKandangId);
|
||||
formik.setFieldValue('project_flock_kandang', {
|
||||
setFieldValue('project_flock_kandang_id', projectFlockKandangId);
|
||||
setFieldValue('project_flock_kandang', {
|
||||
value: projectFlockKandangId,
|
||||
label: `${projectFlockKandangLookup.project_flock.flock_name} - ${projectFlockKandangLookup.kandang.name}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [projectFlockKandangLookup, formik.values.project_flock_kandang_id]);
|
||||
}, [
|
||||
projectFlockKandangLookup,
|
||||
formik.values.project_flock_kandang_id,
|
||||
setFieldValue,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (initialValues && type === 'detail') {
|
||||
@@ -519,7 +568,7 @@ const InventoryAdjustmentForm = ({
|
||||
});
|
||||
}
|
||||
|
||||
formik.setValues({
|
||||
setValues({
|
||||
location: initialValues.location
|
||||
? {
|
||||
value: initialValues.location.id,
|
||||
@@ -550,6 +599,8 @@ const InventoryAdjustmentForm = ({
|
||||
}
|
||||
: null,
|
||||
product_id: initialValues.product_warehouse?.product?.id ?? 0,
|
||||
depletion_product: null,
|
||||
depletion_product_id: 0,
|
||||
transaction_type: transactionType,
|
||||
transaction_subtype: transactionSubtype,
|
||||
qty: initialValues.qty ?? '',
|
||||
@@ -557,7 +608,7 @@ const InventoryAdjustmentForm = ({
|
||||
notes: initialValues.notes ?? '',
|
||||
});
|
||||
}
|
||||
}, [formik.setValues, initialValues, type]);
|
||||
}, [setValues, initialValues, type]);
|
||||
|
||||
// ===== Formik Error List =====
|
||||
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||
@@ -729,6 +780,29 @@ const InventoryAdjustmentForm = ({
|
||||
isSearchable
|
||||
/>
|
||||
|
||||
{/* RECORDING_DEPLETION_IN */}
|
||||
{isDepletionProductVisible && (
|
||||
<SelectInput
|
||||
required
|
||||
label='Jenis Deplesi'
|
||||
value={selectedDepletionProduct}
|
||||
onChange={depletionProductChangeHandler}
|
||||
onInputChange={setDepletionProductInputValue}
|
||||
options={depletionProductOptions}
|
||||
onMenuScrollToBottom={loadMoreDepletionProducts}
|
||||
isLoading={isLoadingDepletionProductOptions}
|
||||
isError={
|
||||
formik.touched.depletion_product_id &&
|
||||
Boolean(formik.errors.depletion_product_id)
|
||||
}
|
||||
errorMessage={formik.errors.depletion_product_id as string}
|
||||
isDisabled={type === 'detail'}
|
||||
placeholder='Pilih Jenis Deplesi'
|
||||
isClearable
|
||||
isSearchable
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Number Input Quantity */}
|
||||
<NumberInput
|
||||
className={{
|
||||
|
||||
Reference in New Issue
Block a user