mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-21 13:55:45 +00:00
fix(resolve): fix resolve merge
This commit is contained in:
+13
-9
@@ -1,14 +1,18 @@
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export const ProductCategoryFormSchema = Yup.object({
|
||||
code: Yup.string()
|
||||
.required('Kode wajib diisi!')
|
||||
.max(3, 'Kode kategori produk melebihi 3 karakter!'),
|
||||
name: Yup.string().required('Nama wajib diisi!'),
|
||||
});
|
||||
type ProductCategoryFormSchemaType = {
|
||||
code: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export const ProductCategoryFormSchema: Yup.ObjectSchema<ProductCategoryFormSchemaType> =
|
||||
Yup.object({
|
||||
code: Yup.string()
|
||||
.required('Kode wajib diisi!')
|
||||
.max(3, 'Kode kategori produk melebihi 3 karakter!'),
|
||||
name: Yup.string().required('Nama wajib diisi!'),
|
||||
});
|
||||
|
||||
export const UpdateProductCategoryFormSchema = ProductCategoryFormSchema;
|
||||
|
||||
export type ProductCategoryFormValues = Yup.InferType<
|
||||
typeof ProductCategoryFormSchema
|
||||
>;
|
||||
export type ProductCategoryFormValues = Yup.InferType<typeof ProductCategoryFormSchema>;
|
||||
@@ -71,12 +71,13 @@ const ProductCategoryForm = ({
|
||||
[router]
|
||||
);
|
||||
|
||||
const formikInitialValues = useMemo<ProductCategoryFormValues>(() => {
|
||||
return {
|
||||
const formikInitialValues = useMemo<ProductCategoryFormValues>(
|
||||
() => ({
|
||||
code: initialValues?.code ?? '',
|
||||
name: initialValues?.name ?? '',
|
||||
};
|
||||
}, [initialValues]);
|
||||
}),
|
||||
[initialValues]
|
||||
);
|
||||
|
||||
const formik = useFormik<ProductCategoryFormValues>({
|
||||
initialValues: formikInitialValues,
|
||||
@@ -118,7 +119,7 @@ const ProductCategoryForm = ({
|
||||
await ProductCategoryApi.delete(initialValues?.id as number);
|
||||
|
||||
deleteModal.closeModal();
|
||||
toast.success('Successfully delete Product Category!');
|
||||
toast.success('Berhasil menghapus data Kategori Produk!');
|
||||
setIsDeleteLoading(false);
|
||||
router.push('/master-data/product-category');
|
||||
};
|
||||
@@ -129,7 +130,7 @@ const ProductCategoryForm = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className='w-full max-w-xl'>
|
||||
<section className='w-full max-w-2xl'>
|
||||
<header className='flex flex-col gap-4'>
|
||||
<Button
|
||||
href='/master-data/product-category'
|
||||
@@ -141,9 +142,9 @@ const ProductCategoryForm = ({
|
||||
</Button>
|
||||
|
||||
<h1 className='text-2xl font-bold text-center'>
|
||||
{type === 'add' && 'Tambah Product Category'}
|
||||
{type === 'edit' && 'Edit Product Category'}
|
||||
{type === 'detail' && 'Detail Product Category'}
|
||||
{type === 'add' && 'Tambah Kategori Produk'}
|
||||
{type === 'edit' && 'Edit Kategori Produk'}
|
||||
{type === 'detail' && 'Detail Kategori Produk'}
|
||||
</h1>
|
||||
</header>
|
||||
|
||||
@@ -157,7 +158,7 @@ const ProductCategoryForm = ({
|
||||
required
|
||||
label='Kode'
|
||||
name='code'
|
||||
placeholder='Masukkan kode kategori produk'
|
||||
placeholder='Masukkan kode...'
|
||||
value={formik.values.code}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
@@ -169,7 +170,7 @@ const ProductCategoryForm = ({
|
||||
required
|
||||
label='Nama'
|
||||
name='name'
|
||||
placeholder='Masukkan nama kategori produk'
|
||||
placeholder='Masukkan nama...'
|
||||
value={formik.values.name}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
@@ -256,7 +257,7 @@ const ProductCategoryForm = ({
|
||||
<ConfirmationModal
|
||||
ref={deleteModal.ref}
|
||||
type='error'
|
||||
text={`Apakah anda yakin ingin menghapus data Product Category ini (${initialValues?.name})?`}
|
||||
text={`Apakah anda yakin ingin menghapus data Kategori Produk ini (${initialValues?.name})?`}
|
||||
secondaryButton={{
|
||||
text: 'Tidak',
|
||||
}}
|
||||
|
||||
@@ -1,53 +1,82 @@
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export const ProductFormSchema = Yup.object({
|
||||
name: Yup.string().required('Nama wajib diisi!'),
|
||||
brand: Yup.string().required('Merek wajib diisi!'),
|
||||
sku: Yup.string().required('SKU wajib diisi!'),
|
||||
uom: Yup.object({
|
||||
value: Yup.number().min(1).required(),
|
||||
label: Yup.string().required(),
|
||||
}).nullable(),
|
||||
uom_id: Yup.number()
|
||||
.required('Satuan wajib diisi!')
|
||||
.typeError('Satuan wajib diisi!'),
|
||||
product_category: Yup.object({
|
||||
value: Yup.number().min(1).required(),
|
||||
label: Yup.string().required(),
|
||||
}).nullable(),
|
||||
product_category_id: Yup.number()
|
||||
.required('Kategori produk wajib diisi!')
|
||||
.typeError('Kategori produk wajib diisi!'),
|
||||
product_price: Yup.number()
|
||||
.required('Harga produk wajib diisi!')
|
||||
.typeError('Harga produk wajib diisi!')
|
||||
.min(0, 'Harga produk tidak boleh kurang dari 0!'),
|
||||
selling_price: Yup.number()
|
||||
.required('Harga jual wajib diisi!')
|
||||
.typeError('Harga jual wajib diisi!')
|
||||
.min(0, 'Harga jual tidak boleh kurang dari 0!'),
|
||||
tax: Yup.number()
|
||||
.required('Pajak wajib diisi!')
|
||||
.typeError('Pajak wajib diisi!')
|
||||
.min(0, 'Pajak tidak boleh kurang dari 0!')
|
||||
.max(100, 'Pajak tidak boleh lebih dari 100%!'),
|
||||
expiry_period: Yup.number()
|
||||
.required('Periode kadaluarsa wajib diisi!')
|
||||
.typeError('Periode kadaluarsa wajib diisi!')
|
||||
.min(0, 'Periode kadaluarsa tidak boleh kurang dari 0!'),
|
||||
supplier: Yup.object({
|
||||
value: Yup.number().min(1).required(),
|
||||
label: Yup.string().required(),
|
||||
}).nullable(),
|
||||
supplier_ids: Yup.array()
|
||||
.of(Yup.number().typeError('Supplier tidak valid!'))
|
||||
.min(1, 'Minimal harus ada 1 supplier!')
|
||||
.required('Supplier wajib diisi!'),
|
||||
flags: Yup.array()
|
||||
.of(Yup.string())
|
||||
.min(1, 'Minimal harus ada 1 flag!')
|
||||
.required('Flag wajib diisi!'),
|
||||
});
|
||||
type ProductFormSchemaType = {
|
||||
name: string;
|
||||
brand: string;
|
||||
sku: string;
|
||||
uom?: {
|
||||
value: number;
|
||||
label: string;
|
||||
} | null;
|
||||
uom_id: number;
|
||||
product_category?: {
|
||||
value: number;
|
||||
label: string;
|
||||
} | null;
|
||||
product_category_id: number;
|
||||
product_price: number | string;
|
||||
selling_price: number | string;
|
||||
tax: number | string;
|
||||
expiry_period: number | string;
|
||||
supplier_ids: number[];
|
||||
flags: string[];
|
||||
};
|
||||
|
||||
export const ProductFormSchema: Yup.ObjectSchema<ProductFormSchemaType> =
|
||||
Yup.object({
|
||||
name: Yup.string().required('Nama wajib diisi!'),
|
||||
brand: Yup.string().required('Merek wajib diisi!'),
|
||||
sku: Yup.string().required('SKU wajib diisi!'),
|
||||
|
||||
uom: Yup.object({
|
||||
value: Yup.number().min(1).required(),
|
||||
label: Yup.string().required(),
|
||||
}).nullable().required('Satuan wajib diisi!'),
|
||||
|
||||
uom_id: Yup.number()
|
||||
.required('Satuan wajib diisi!')
|
||||
.typeError('Satuan wajib diisi!'),
|
||||
|
||||
product_category: Yup.object({
|
||||
value: Yup.number().min(1).required(),
|
||||
label: Yup.string().required(),
|
||||
}).nullable().required('Kategori produk wajib diisi!'),
|
||||
|
||||
product_category_id: Yup.number()
|
||||
.required('Kategori produk wajib diisi!')
|
||||
.typeError('Kategori produk wajib diisi!'),
|
||||
|
||||
product_price: Yup.number()
|
||||
.required('Harga produk wajib diisi!')
|
||||
.typeError('Harga produk wajib diisi!')
|
||||
.min(0, 'Harga produk tidak boleh kurang dari 0!'),
|
||||
|
||||
selling_price: Yup.number()
|
||||
.required('Harga jual wajib diisi!')
|
||||
.typeError('Harga jual wajib diisi!')
|
||||
.min(0, 'Harga jual tidak boleh kurang dari 0!'),
|
||||
|
||||
tax: Yup.number()
|
||||
.required('Pajak wajib diisi!')
|
||||
.typeError('Pajak wajib diisi!')
|
||||
.min(0, 'Pajak tidak boleh kurang dari 0!')
|
||||
.max(100, 'Pajak tidak boleh lebih dari 100%!'),
|
||||
|
||||
expiry_period: Yup.number()
|
||||
.required('Periode kadaluarsa wajib diisi!')
|
||||
.typeError('Periode kadaluarsa wajib diisi!')
|
||||
.min(0, 'Periode kadaluarsa tidak boleh kurang dari 0!'),
|
||||
|
||||
supplier_ids: Yup.array()
|
||||
.of(Yup.number().required().typeError('Supplier tidak valid!'))
|
||||
.min(1, 'Minimal harus ada 1 supplier!')
|
||||
.required('Supplier wajib diisi!'),
|
||||
|
||||
flags: Yup.array()
|
||||
.of(Yup.string().required())
|
||||
.min(1, 'Minimal harus ada 1 flag!')
|
||||
.required('Flag wajib diisi!'),
|
||||
});
|
||||
|
||||
export const UpdateProductFormSchema = ProductFormSchema;
|
||||
|
||||
|
||||
@@ -9,7 +9,11 @@ import useSWR from 'swr';
|
||||
import { Icon } from '@iconify/react';
|
||||
import Button from '@/components/Button';
|
||||
import TextInput from '@/components/input/TextInput';
|
||||
import SelectInput, { OptionType } from '@/components/input/SelectInput';
|
||||
import NumberInput from '@/components/input/NumberInput';
|
||||
import SelectInput, {
|
||||
OptionType,
|
||||
useSelect,
|
||||
} from '@/components/input/SelectInput';
|
||||
import { useModal } from '@/components/Modal';
|
||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
||||
|
||||
@@ -79,20 +83,19 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
sku: initialValues?.sku ?? '',
|
||||
uom: initialValues?.uom
|
||||
? { value: initialValues.uom.id, label: initialValues.uom.name }
|
||||
: null,
|
||||
: undefined,
|
||||
uom_id: initialValues?.uom?.id ?? 0,
|
||||
product_category: initialValues?.product_category
|
||||
? {
|
||||
value: initialValues.product_category.id,
|
||||
label: initialValues.product_category.name,
|
||||
}
|
||||
: null,
|
||||
: undefined,
|
||||
product_category_id: initialValues?.product_category?.id ?? 0,
|
||||
product_price: initialValues?.product_price ?? 0,
|
||||
selling_price: initialValues?.selling_price ?? 0,
|
||||
tax: initialValues?.tax ?? 0,
|
||||
expiry_period: initialValues?.expiry_period ?? 0,
|
||||
supplier: null, // not used for payload, just for UI
|
||||
product_price: initialValues?.product_price ?? '',
|
||||
selling_price: initialValues?.selling_price ?? '',
|
||||
tax: initialValues?.tax ?? '',
|
||||
expiry_period: initialValues?.expiry_period ?? '',
|
||||
supplier_ids: initialValues?.suppliers?.map((s) => s.id) ?? [],
|
||||
flags: initialValues?.flags ?? [],
|
||||
}),
|
||||
@@ -111,14 +114,14 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
sku: values.sku,
|
||||
uom_id: values.uom_id,
|
||||
product_category_id: values.product_category_id,
|
||||
product_price: values.product_price,
|
||||
selling_price: values.selling_price,
|
||||
tax: values.tax,
|
||||
expiry_period: values.expiry_period,
|
||||
supplier_ids: (values.supplier_ids ?? []).filter(
|
||||
product_price: parseInt(values.product_price.toString()) || 0,
|
||||
selling_price: parseInt(values.selling_price.toString()) || 0,
|
||||
tax: parseInt(values.tax.toString()) || 0,
|
||||
expiry_period: parseInt(values.expiry_period.toString()) || 0,
|
||||
supplier_ids: values.supplier_ids.filter(
|
||||
(id): id is number => typeof id === 'number'
|
||||
),
|
||||
flags: (values.flags ?? []).filter(
|
||||
flags: values.flags.filter(
|
||||
(f): f is string => typeof f === 'string'
|
||||
),
|
||||
};
|
||||
@@ -136,15 +139,11 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
const { setValues: formikSetValues } = formik;
|
||||
|
||||
// UOM
|
||||
const [uomSelectInputValue, setUomSelectInputValue] = useState('');
|
||||
const uomsUrl = `${UomApi.basePath}?${new URLSearchParams({ search: uomSelectInputValue ?? '' }).toString()}`;
|
||||
const { data: uoms, isLoading: isLoadingUoms } = useSWR(
|
||||
uomsUrl,
|
||||
UomApi.getAllFetcher
|
||||
);
|
||||
const uomOptions = isResponseSuccess(uoms)
|
||||
? uoms?.data.map((uom) => ({ value: uom.id, label: uom.name }))
|
||||
: [];
|
||||
const {
|
||||
setInputValue: setUomSelectInputValue,
|
||||
options: uomOptions,
|
||||
isLoadingOptions: isLoadingUoms,
|
||||
} = useSelect(UomApi.basePath, 'id', 'name');
|
||||
const uomChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||
formik.setFieldTouched('uom', true);
|
||||
formik.setFieldValue('uom', val);
|
||||
@@ -153,15 +152,11 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
};
|
||||
|
||||
// Product Category
|
||||
const [categorySelectInputValue, setCategorySelectInputValue] = useState('');
|
||||
const categoriesUrl = `${ProductCategoryApi.basePath}?${new URLSearchParams({ search: categorySelectInputValue ?? '' }).toString()}`;
|
||||
const { data: categories, isLoading: isLoadingCategories } = useSWR(
|
||||
categoriesUrl,
|
||||
ProductCategoryApi.getAllFetcher
|
||||
);
|
||||
const categoryOptions = isResponseSuccess(categories)
|
||||
? categories?.data.map((cat) => ({ value: cat.id, label: cat.name }))
|
||||
: [];
|
||||
const {
|
||||
setInputValue: setCategorySelectInputValue,
|
||||
options: categoryOptions,
|
||||
isLoadingOptions: isLoadingCategories,
|
||||
} = useSelect(ProductCategoryApi.basePath, 'id', 'name');
|
||||
const categoryChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||
formik.setFieldTouched('product_category', true);
|
||||
formik.setFieldValue('product_category', val);
|
||||
@@ -169,7 +164,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
formik.setFieldValue('product_category_id', (val as OptionType)?.value);
|
||||
};
|
||||
|
||||
// Supplier (multi select)
|
||||
// Supplier (multi select) - using SWR to filter by category
|
||||
const [supplierSelectInputValue, setSupplierSelectInputValue] = useState('');
|
||||
const suppliersUrl = `${SupplierApi.basePath}?${new URLSearchParams({ search: supplierSelectInputValue ?? '' }).toString()}`;
|
||||
const { data: suppliers, isLoading: isLoadingSuppliers } = useSWR(
|
||||
@@ -209,7 +204,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className='w-full max-w-xl'>
|
||||
<section className='w-full max-w-2xl'>
|
||||
<header className='flex flex-col gap-4'>
|
||||
<Button
|
||||
href='/master-data/product'
|
||||
@@ -235,7 +230,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
required
|
||||
label='Nama'
|
||||
name='name'
|
||||
placeholder='Masukkan nama produk'
|
||||
placeholder='Masukkan nama...'
|
||||
value={formik.values.name}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
@@ -247,7 +242,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
required
|
||||
label='Merek'
|
||||
name='brand'
|
||||
placeholder='Masukkan merek produk'
|
||||
placeholder='Masukkan merek...'
|
||||
value={formik.values.brand}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
@@ -259,7 +254,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
required
|
||||
label='SKU'
|
||||
name='sku'
|
||||
placeholder='Masukkan SKU produk'
|
||||
placeholder='Masukkan SKU...'
|
||||
value={formik.values.sku}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
@@ -270,6 +265,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
<SelectInput
|
||||
required
|
||||
label='Satuan'
|
||||
placeholder='Pilih satuan...'
|
||||
value={formik.values.uom ?? undefined}
|
||||
onChange={uomChangeHandler}
|
||||
options={uomOptions}
|
||||
@@ -283,6 +279,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
<SelectInput
|
||||
required
|
||||
label='Kategori Produk'
|
||||
placeholder='Pilih kategori produk...'
|
||||
value={formik.values.product_category ?? undefined}
|
||||
onChange={categoryChangeHandler}
|
||||
options={categoryOptions}
|
||||
@@ -296,15 +293,19 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
isDisabled={type === 'detail'}
|
||||
isClearable
|
||||
/>
|
||||
<TextInput
|
||||
<NumberInput
|
||||
required
|
||||
label='Harga Produk'
|
||||
name='product_price'
|
||||
type='number'
|
||||
placeholder='Masukkan harga produk'
|
||||
placeholder='Masukkan harga produk...'
|
||||
value={formik.values.product_price}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
decimalScale={2}
|
||||
allowNegative={false}
|
||||
thousandSeparator=','
|
||||
decimalSeparator='.'
|
||||
inputPrefix='Rp '
|
||||
isError={
|
||||
formik.touched.product_price &&
|
||||
Boolean(formik.errors.product_price)
|
||||
@@ -312,15 +313,19 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
errorMessage={formik.errors.product_price as string}
|
||||
readOnly={type === 'detail'}
|
||||
/>
|
||||
<TextInput
|
||||
<NumberInput
|
||||
required
|
||||
label='Harga Jual'
|
||||
name='selling_price'
|
||||
type='number'
|
||||
placeholder='Masukkan harga jual'
|
||||
placeholder='Masukkan harga jual...'
|
||||
value={formik.values.selling_price}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
decimalScale={2}
|
||||
allowNegative={false}
|
||||
thousandSeparator=','
|
||||
decimalSeparator='.'
|
||||
inputPrefix='Rp '
|
||||
isError={
|
||||
formik.touched.selling_price &&
|
||||
Boolean(formik.errors.selling_price)
|
||||
@@ -328,28 +333,36 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
errorMessage={formik.errors.selling_price as string}
|
||||
readOnly={type === 'detail'}
|
||||
/>
|
||||
<TextInput
|
||||
<NumberInput
|
||||
required
|
||||
label='Pajak (%)'
|
||||
name='tax'
|
||||
type='number'
|
||||
placeholder='Masukkan pajak'
|
||||
placeholder='Masukkan pajak...'
|
||||
value={formik.values.tax}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
decimalScale={2}
|
||||
allowNegative={false}
|
||||
thousandSeparator=','
|
||||
decimalSeparator='.'
|
||||
inputSuffix='%'
|
||||
isError={formik.touched.tax && Boolean(formik.errors.tax)}
|
||||
errorMessage={formik.errors.tax as string}
|
||||
readOnly={type === 'detail'}
|
||||
/>
|
||||
<TextInput
|
||||
<NumberInput
|
||||
required
|
||||
label='Periode Kadaluarsa (hari)'
|
||||
name='expiry_period'
|
||||
type='number'
|
||||
placeholder='Masukkan periode kadaluarsa'
|
||||
placeholder='Masukkan periode kadaluarsa...'
|
||||
value={formik.values.expiry_period}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
decimalScale={0}
|
||||
allowNegative={false}
|
||||
thousandSeparator=','
|
||||
decimalSeparator='.'
|
||||
inputSuffix='hari'
|
||||
isError={
|
||||
formik.touched.expiry_period &&
|
||||
Boolean(formik.errors.expiry_period)
|
||||
@@ -360,9 +373,10 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
<SelectInput
|
||||
required
|
||||
label='Supplier'
|
||||
placeholder='Pilih supplier...'
|
||||
isMulti
|
||||
value={supplierOptions.filter((opt) =>
|
||||
formik.values.supplier_ids.includes(opt.value)
|
||||
(formik.values.supplier_ids || []).includes(opt.value)
|
||||
)}
|
||||
onChange={supplierChangeHandler}
|
||||
options={supplierOptions}
|
||||
@@ -379,9 +393,10 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
<SelectInput
|
||||
required
|
||||
label='Flags'
|
||||
placeholder='Pilih flags...'
|
||||
isMulti
|
||||
value={PRODUCT_FLAG_OPTIONS.filter((opt) =>
|
||||
formik.values.flags.includes(opt.value)
|
||||
(formik.values.flags || []).includes(opt.value)
|
||||
)}
|
||||
onChange={(val) => {
|
||||
const arr = Array.isArray(val) ? val : val ? [val] : [];
|
||||
|
||||
Reference in New Issue
Block a user