mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 15:25:46 +00:00
refactor(FE): Refactor product flags to support single flag and
sub-flags
This commit is contained in:
@@ -180,11 +180,17 @@ const ProductsTable = () => {
|
|||||||
props.row.original.suppliers?.map((s) => s.name).join(', ') || '-',
|
props.row.original.suppliers?.map((s) => s.name).join(', ') || '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: 'flags',
|
accessorKey: 'flag',
|
||||||
header: 'Flags',
|
header: 'Flag',
|
||||||
cell: (props) =>
|
cell: (props) =>
|
||||||
props.row.original.flags?.length
|
props.row.original.flag ? props.row.original.flag : '-',
|
||||||
? props.row.original.flags.join(', ')
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'subs_flags',
|
||||||
|
header: 'Sub Flags',
|
||||||
|
cell: (props) =>
|
||||||
|
props.row.original.sub_flags?.length
|
||||||
|
? props.row.original.sub_flags.join(', ')
|
||||||
: '-',
|
: '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ type ProductFormSchemaType = {
|
|||||||
} | null;
|
} | null;
|
||||||
price: number;
|
price: number;
|
||||||
}[];
|
}[];
|
||||||
flags: string[];
|
flag: string;
|
||||||
|
sub_flags?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ProductFormSchema: Yup.ObjectSchema<ProductFormSchemaType> =
|
export const ProductFormSchema: Yup.ObjectSchema<ProductFormSchemaType> =
|
||||||
@@ -94,10 +95,12 @@ export const ProductFormSchema: Yup.ObjectSchema<ProductFormSchemaType> =
|
|||||||
)
|
)
|
||||||
.required('Supplier wajib diisi!'),
|
.required('Supplier wajib diisi!'),
|
||||||
|
|
||||||
flags: Yup.array()
|
flag: Yup.string()
|
||||||
.of(Yup.string().required())
|
.min(1, 'Flag wajib diisi!')
|
||||||
.min(1, 'Minimal harus ada 1 flag!')
|
.required('Flag wajib diisi!')
|
||||||
.required('Flag wajib diisi!'),
|
.typeError('Flag wajib diisi!'),
|
||||||
|
|
||||||
|
sub_flags: Yup.array().of(Yup.string().required()),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const UpdateProductFormSchema = ProductFormSchema;
|
export const UpdateProductFormSchema = ProductFormSchema;
|
||||||
|
|||||||
@@ -36,8 +36,10 @@ import {
|
|||||||
ProductApi,
|
ProductApi,
|
||||||
} from '@/services/api/master-data';
|
} from '@/services/api/master-data';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
import { PRODUCT_FLAG_OPTIONS } from '@/config/constant';
|
|
||||||
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
import { PRODUCT_FLAG_MAPPING } from '@/config/constant';
|
||||||
|
|
||||||
import { Supplier } from '@/types/api/master-data/supplier';
|
import { Supplier } from '@/types/api/master-data/supplier';
|
||||||
import Card from '@/components/Card';
|
import Card from '@/components/Card';
|
||||||
import { removeArrayItemAndSync } from '@/lib/utils/formik';
|
import { removeArrayItemAndSync } from '@/lib/utils/formik';
|
||||||
@@ -110,7 +112,8 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
|||||||
price: supplier.price,
|
price: supplier.price,
|
||||||
}))
|
}))
|
||||||
: [],
|
: [],
|
||||||
flags: initialValues?.flags ?? [],
|
flag: initialValues?.flag ?? '',
|
||||||
|
sub_flags: initialValues?.sub_flags ?? [],
|
||||||
}),
|
}),
|
||||||
[initialValues]
|
[initialValues]
|
||||||
);
|
);
|
||||||
@@ -139,7 +142,8 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
|||||||
supplier_id: s.supplier?.value as number,
|
supplier_id: s.supplier?.value as number,
|
||||||
price: parseInt(s.price.toString()) || 0,
|
price: parseInt(s.price.toString()) || 0,
|
||||||
})),
|
})),
|
||||||
flags: values.flags.filter((f): f is string => typeof f === 'string'),
|
flag: values.flag,
|
||||||
|
sub_flags: values.sub_flags,
|
||||||
};
|
};
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'add':
|
case 'add':
|
||||||
@@ -200,6 +204,28 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
|||||||
});
|
});
|
||||||
}, [supplierOptions, formik.values.suppliers]);
|
}, [supplierOptions, formik.values.suppliers]);
|
||||||
|
|
||||||
|
const selectedFlagMapping = useMemo(() => {
|
||||||
|
return PRODUCT_FLAG_MAPPING.options.find(
|
||||||
|
(opt) => opt.flag.value === formik.values.flag
|
||||||
|
);
|
||||||
|
}, [formik.values.flag]);
|
||||||
|
|
||||||
|
const subFlagOptions = useMemo<OptionType[]>(() => {
|
||||||
|
return (selectedFlagMapping?.sub_flags as unknown as OptionType[]) ?? [];
|
||||||
|
}, [selectedFlagMapping]);
|
||||||
|
|
||||||
|
const selectedSubFlagValues = useMemo<OptionType[]>(() => {
|
||||||
|
return (
|
||||||
|
(selectedFlagMapping?.sub_flags.filter((subFlag) =>
|
||||||
|
formik.values.sub_flags?.includes(subFlag.value)
|
||||||
|
) as unknown as OptionType[]) ?? []
|
||||||
|
);
|
||||||
|
}, [selectedFlagMapping, formik.values.sub_flags]);
|
||||||
|
|
||||||
|
const isSubFlagRequired = useMemo(() => {
|
||||||
|
return selectedFlagMapping?.allow_without_sub_flag === false;
|
||||||
|
}, [selectedFlagMapping]);
|
||||||
|
|
||||||
const addSupplierHandler = () => {
|
const addSupplierHandler = () => {
|
||||||
formik.setFieldValue('suppliers', [
|
formik.setFieldValue('suppliers', [
|
||||||
...formik.values.suppliers,
|
...formik.values.suppliers,
|
||||||
@@ -213,7 +239,6 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
|||||||
const deleteSupplierItemHandler = (idx: number) => {
|
const deleteSupplierItemHandler = (idx: number) => {
|
||||||
const path = 'suppliers';
|
const path = 'suppliers';
|
||||||
|
|
||||||
// trims values, errors, and touched at idx
|
|
||||||
removeArrayItemAndSync(formik, path, idx);
|
removeArrayItemAndSync(formik, path, idx);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -428,26 +453,45 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
|||||||
readOnly={type === 'detail'}
|
readOnly={type === 'detail'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='grid sm:grid-cols-1 gap-4'>
|
<div className='grid grid-cols-1 sm:grid-cols-2 gap-4'>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
required
|
required
|
||||||
label='Flags'
|
label='Flags'
|
||||||
placeholder='Pilih flags...'
|
placeholder='Pilih flags...'
|
||||||
|
value={(
|
||||||
|
PRODUCT_FLAG_MAPPING.flags as unknown as OptionType[]
|
||||||
|
).find((opt) => opt.value === formik.values.flag)}
|
||||||
|
onChange={(val) => {
|
||||||
|
const selectedFlag = (val as OptionType)?.value ?? '';
|
||||||
|
formik.setFieldValue('flag', selectedFlag);
|
||||||
|
formik.setFieldValue('sub_flags', []);
|
||||||
|
}}
|
||||||
|
options={PRODUCT_FLAG_MAPPING.flags as unknown as OptionType[]}
|
||||||
|
isError={formik.touched.flag && Boolean(formik.errors.flag)}
|
||||||
|
errorMessage={formik.errors.flag as string}
|
||||||
|
isDisabled={type === 'detail'}
|
||||||
|
isClearable
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SelectInput
|
||||||
|
label='Sub Flags'
|
||||||
|
placeholder='Pilih sub flags...'
|
||||||
isMulti
|
isMulti
|
||||||
value={PRODUCT_FLAG_OPTIONS.filter((opt) =>
|
required={isSubFlagRequired}
|
||||||
(formik.values.flags || []).includes(opt.value)
|
value={selectedSubFlagValues}
|
||||||
)}
|
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
const arr = Array.isArray(val) ? val : val ? [val] : [];
|
const arr = Array.isArray(val) ? val : val ? [val] : [];
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
'flags',
|
'sub_flags',
|
||||||
arr.map((v) => (v as OptionType).value)
|
arr.map((v) => (v as OptionType).value)
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
options={PRODUCT_FLAG_OPTIONS}
|
options={subFlagOptions}
|
||||||
isError={formik.touched.flags && Boolean(formik.errors.flags)}
|
isError={
|
||||||
errorMessage={formik.errors.flags as string}
|
formik.touched.sub_flags && Boolean(formik.errors.sub_flags)
|
||||||
isDisabled={type === 'detail'}
|
}
|
||||||
|
errorMessage={formik.errors.sub_flags as string}
|
||||||
|
isDisabled={type === 'detail' || !formik.values.flag}
|
||||||
isClearable
|
isClearable
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+6
-2
@@ -15,7 +15,10 @@ export type BaseProduct = {
|
|||||||
uom: Uom;
|
uom: Uom;
|
||||||
product_category: ProductCategory;
|
product_category: ProductCategory;
|
||||||
suppliers: (BaseSupplier & { price: number })[];
|
suppliers: (BaseSupplier & { price: number })[];
|
||||||
flags: string[];
|
flag: string;
|
||||||
|
sub_flag?: string;
|
||||||
|
sub_flags?: string[];
|
||||||
|
flags?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Product = BaseMetadata & BaseProduct;
|
export type Product = BaseMetadata & BaseProduct;
|
||||||
@@ -34,7 +37,8 @@ export type CreateProductPayload = {
|
|||||||
supplier_id: number;
|
supplier_id: number;
|
||||||
price: number;
|
price: number;
|
||||||
}[];
|
}[];
|
||||||
flags: string[];
|
flag: string;
|
||||||
|
sub_flags?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UpdateProductPayload = CreateProductPayload;
|
export type UpdateProductPayload = CreateProductPayload;
|
||||||
|
|||||||
Reference in New Issue
Block a user