feat(FE-177): Integrate API sales order and fixing sales order initial state

This commit is contained in:
randy-ar
2025-11-17 15:59:31 +07:00
parent d3c4706d87
commit a9bdb6c36e
9 changed files with 277 additions and 308 deletions
@@ -1,6 +1,7 @@
import * as Yup from 'yup';
type SalesOrderProductSchemaType = {
id?: number | undefined;
kandang_id?: number;
kandang?: {
value: number;
@@ -16,10 +17,13 @@ type SalesOrderProductSchemaType = {
qty: string | number | undefined;
avg_weight: string | number | undefined;
total_price: string | number | undefined;
vehicle_number?: string | undefined;
};
export const SalesOrderProductSchema: Yup.ObjectSchema<SalesOrderProductSchemaType> =
Yup.object({
id: Yup.number(),
vehicle_number: Yup.string().required('Nomor Kendaraan wajib diisi!'),
kandang: Yup.object({
value: Yup.number().min(1).required(),
label: Yup.string().required(),
@@ -4,8 +4,8 @@ import { useFormik } from 'formik';
import {
SalesOrderProductFormValues,
SalesOrderProductSchema,
} from './SalesOrderProduct.schema';
import { RefObject, useEffect, useState } from 'react';
} from '@/components/pages/marketing/form/repeater/sales-order/SalesOrderProduct.schema';
import { RefObject, useState } from 'react';
import SelectInput, {
OptionType,
useSelect,
@@ -17,75 +17,24 @@ import { ProductWarehouseApi } from '@/services/api/inventory';
import NumberInput from '@/components/input/NumberInput';
import Button from '@/components/Button';
import { isResponseSuccess } from '@/lib/api-helper';
import { formatVechicleNumber } from '@/lib/helper';
import PatternInput from '@/components/input/PatternInput';
import Alert from '@/components/Alert';
const SalesOrderProductForm = ({
initialValues,
modalRef,
onSubmitForm,
}: {
initialValues?: SalesOrderProductFormValues;
modalRef?: RefObject<HTMLDialogElement | null>;
onSubmitForm?: (value: SalesOrderProductFormValues) => Promise<void>;
}) => {
// State
const [selectedOptionsKandang, setSelectedOptionsKandang] =
useState<OptionType | null>(null);
const [selectedOptionsWarehouse, setSelectedOptionsWarehouse] = useState<
OptionType | null | undefined
>(undefined);
const [formErrorMessage, setFormErrorMessage] = useState('');
// Options Data
const {
options: kandangSourceOptions,
rawData: kandangSourceRawData,
isLoadingOptions: isLoadingKandangSourceOptions,
} = useSelect<Kandang>(KandangApi.basePath, 'id', 'name');
const {
options: warehouseSourceOptions,
rawData: warehouseSourceRawData,
isLoadingOptions: isLoadingWarehouseSourceOptions,
} = useSelect<ProductWarehouse>(
ProductWarehouseApi.basePath,
'id',
'product.name',
'search',
{
warehouse_id: selectedOptionsKandang?.value?.toString() ?? '',
}
);
// Handler
const kandangChangeHandler = (val: OptionType | OptionType[] | null) => {
setSelectedOptionsKandang(val as OptionType);
formik.setFieldValue('kandang', val as OptionType);
formik.setFieldValue('kandang_id', (val as OptionType)?.value);
formik.setFieldValue('product_warehouse_id', null);
formik.setFieldValue('qty', null);
warehouseChangeHandler(null);
};
const warehouseChangeHandler = (val: OptionType | OptionType[] | null) => {
setSelectedOptionsWarehouse(val as OptionType);
formik.setFieldValue('product_warehouse', val as OptionType);
formik.setFieldValue('product_warehouse_id', (val as OptionType)?.value);
if (isResponseSuccess(warehouseSourceRawData)) {
const productWarehouse = warehouseSourceRawData?.data.find(
(item: ProductWarehouse) => item.id === (val as OptionType)?.value
);
if (selectedOptionsWarehouse?.value !== null) {
formik.setFieldValue('qty', productWarehouse?.quantity);
handleBlurField('qty');
} else {
formik.setFieldValue('qty', null);
}
}
};
// Formik
const formik = useFormik<SalesOrderProductFormValues>({
enableReinitialize: true,
initialValues: {
vehicle_number: initialValues?.vehicle_number || undefined,
kandang_id: initialValues?.kandang_id || undefined,
kandang: initialValues?.kandang || undefined,
product_warehouse: initialValues?.product_warehouse || undefined,
@@ -99,34 +48,59 @@ const SalesOrderProductForm = ({
validationSchema: SalesOrderProductSchema,
onSubmit: async (values) => {
setFormErrorMessage('');
if (
isResponseSuccess(kandangSourceRawData) &&
isResponseSuccess(warehouseSourceRawData)
) {
const productWarehouse = warehouseSourceRawData?.data.find(
(item: ProductWarehouse) => item.id === values.product_warehouse_id
);
const kandang = kandangSourceRawData?.data.find(
(item: Kandang) => item.id === values.kandang_id
);
onSubmitForm?.(values);
handleResetForm();
}
onSubmitForm?.(values);
handleResetForm();
},
});
const { setValues: formikSetValues } = formik;
useEffect(() => {
formikSetValues(formik.initialValues);
}, [formikSetValues, formik.initialValues]);
const {
options: kandangSourceOptions,
isLoadingOptions: isLoadingKandangSourceOptions,
} = useSelect<Kandang>(KandangApi.basePath, 'id', 'name');
const {
options: warehouseSourceOptions,
rawData: warehouseSourceRawData,
isLoadingOptions: isLoadingWarehouseSourceOptions,
} = useSelect<ProductWarehouse>(
ProductWarehouseApi.basePath,
'id',
'product.name',
'search',
{
warehouse_id: formik.values.kandang_id?.toString() ?? '',
}
);
const kandangChangeHandler = (val: OptionType | OptionType[] | null) => {
formik.setFieldValue('kandang', val as OptionType);
formik.setFieldValue('kandang_id', (val as OptionType)?.value);
formik.setFieldValue('product_warehouse_id', null);
formik.setFieldValue('product_warehouse', null);
formik.setFieldValue('qty', null);
};
const warehouseChangeHandler = (val: OptionType | OptionType[] | null) => {
formik.setFieldValue('product_warehouse', val as OptionType);
const newId = (val as OptionType)?.value;
formik.setFieldValue('product_warehouse_id', newId);
if (isResponseSuccess(warehouseSourceRawData) && newId) {
const productWarehouse = warehouseSourceRawData?.data.find(
(item: ProductWarehouse) => item.id === newId
);
formik.setFieldValue('qty', productWarehouse?.quantity);
handleBlurField('qty');
} else {
formik.setFieldValue('qty', null);
}
};
const handleResetForm = () => {
setSelectedOptionsKandang(null);
setSelectedOptionsWarehouse(null);
setFormErrorMessage('');
formik.resetForm({
values: {
vehicle_number: '',
kandang_id: undefined,
kandang: null,
product_warehouse: null,
@@ -145,7 +119,7 @@ const SalesOrderProductForm = ({
formik.values;
if (field === 'unit_price' || field === 'total_price' || field === 'qty') {
if (qty && unit_price && field === 'unit_price') {
if (qty && unit_price && (field === 'unit_price' || field === 'qty')) {
formik.setFieldValue(
'total_price',
(qty as number) * (unit_price as number)
@@ -159,7 +133,7 @@ const SalesOrderProductForm = ({
}
if (field === 'avg_weight' || field === 'total_weight' || field === 'qty') {
if (qty && avg_weight && field === 'avg_weight') {
if (qty && avg_weight && (field === 'avg_weight' || field === 'qty')) {
formik.setFieldValue(
'total_weight',
(qty as number) * (avg_weight as number)
@@ -180,8 +154,15 @@ const SalesOrderProductForm = ({
onSubmit={formik.handleSubmit}
onReset={handleResetForm}
>
{formErrorMessage && (
<div onClick={() => setFormErrorMessage('')} className='my-3 w-full'>
<Alert color='error'>
{formErrorMessage ? formErrorMessage : ''}
</Alert>
</div>
)}
<div className='grid grid-cols-2 gap-4 z-200'>
{/* <PatternInput
<PatternInput
name='vehicle_number'
label='No. Polisi'
format='AA #### AAA'
@@ -198,16 +179,15 @@ const SalesOrderProductForm = ({
Boolean(formik.errors.vehicle_number)
}
errorMessage={formik.errors.vehicle_number}
/> */}
/>
<SelectInput
required
label='Kandang'
options={kandangSourceOptions}
isLoading={isLoadingKandangSourceOptions}
value={selectedOptionsKandang}
value={formik.values.kandang}
onChange={kandangChangeHandler}
isClearable
menuPortalTarget={modalRef?.current}
isError={
formik.touched.kandang_id && Boolean(formik.errors.kandang_id)
}
@@ -219,12 +199,11 @@ const SalesOrderProductForm = ({
label='Produk'
options={warehouseSourceOptions}
isLoading={isLoadingWarehouseSourceOptions}
value={selectedOptionsWarehouse}
value={formik.values.product_warehouse}
onChange={warehouseChangeHandler}
isClearable
menuPortalTarget={modalRef?.current}
placeholder='Pilih Kandang Terlebih Dahulu'
isDisabled={!selectedOptionsKandang?.value}
isDisabled={!formik.values.kandang_id}
isError={
formik.touched.product_warehouse_id &&
Boolean(formik.errors.product_warehouse_id)