mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +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(', ') || '-',
|
||||
},
|
||||
{
|
||||
accessorKey: 'flags',
|
||||
header: 'Flags',
|
||||
accessorKey: 'flag',
|
||||
header: 'Flag',
|
||||
cell: (props) =>
|
||||
props.row.original.flags?.length
|
||||
? props.row.original.flags.join(', ')
|
||||
props.row.original.flag ? props.row.original.flag : '-',
|
||||
},
|
||||
{
|
||||
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;
|
||||
price: number;
|
||||
}[];
|
||||
flags: string[];
|
||||
flag: string;
|
||||
sub_flags?: string[];
|
||||
};
|
||||
|
||||
export const ProductFormSchema: Yup.ObjectSchema<ProductFormSchemaType> =
|
||||
@@ -94,10 +95,12 @@ export const ProductFormSchema: Yup.ObjectSchema<ProductFormSchemaType> =
|
||||
)
|
||||
.required('Supplier wajib diisi!'),
|
||||
|
||||
flags: Yup.array()
|
||||
.of(Yup.string().required())
|
||||
.min(1, 'Minimal harus ada 1 flag!')
|
||||
.required('Flag wajib diisi!'),
|
||||
flag: Yup.string()
|
||||
.min(1, 'Flag wajib diisi!')
|
||||
.required('Flag wajib diisi!')
|
||||
.typeError('Flag wajib diisi!'),
|
||||
|
||||
sub_flags: Yup.array().of(Yup.string().required()),
|
||||
});
|
||||
|
||||
export const UpdateProductFormSchema = ProductFormSchema;
|
||||
|
||||
@@ -36,8 +36,10 @@ import {
|
||||
ProductApi,
|
||||
} from '@/services/api/master-data';
|
||||
import { cn } from '@/lib/helper';
|
||||
import { PRODUCT_FLAG_OPTIONS } from '@/config/constant';
|
||||
|
||||
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||
import { PRODUCT_FLAG_MAPPING } from '@/config/constant';
|
||||
|
||||
import { Supplier } from '@/types/api/master-data/supplier';
|
||||
import Card from '@/components/Card';
|
||||
import { removeArrayItemAndSync } from '@/lib/utils/formik';
|
||||
@@ -110,7 +112,8 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
price: supplier.price,
|
||||
}))
|
||||
: [],
|
||||
flags: initialValues?.flags ?? [],
|
||||
flag: initialValues?.flag ?? '',
|
||||
sub_flags: initialValues?.sub_flags ?? [],
|
||||
}),
|
||||
[initialValues]
|
||||
);
|
||||
@@ -139,7 +142,8 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
supplier_id: s.supplier?.value as number,
|
||||
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) {
|
||||
case 'add':
|
||||
@@ -200,6 +204,28 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
});
|
||||
}, [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 = () => {
|
||||
formik.setFieldValue('suppliers', [
|
||||
...formik.values.suppliers,
|
||||
@@ -213,7 +239,6 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
const deleteSupplierItemHandler = (idx: number) => {
|
||||
const path = 'suppliers';
|
||||
|
||||
// trims values, errors, and touched at idx
|
||||
removeArrayItemAndSync(formik, path, idx);
|
||||
};
|
||||
|
||||
@@ -428,26 +453,45 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
||||
readOnly={type === 'detail'}
|
||||
/>
|
||||
</div>
|
||||
<div className='grid sm:grid-cols-1 gap-4'>
|
||||
<div className='grid grid-cols-1 sm:grid-cols-2 gap-4'>
|
||||
<SelectInput
|
||||
required
|
||||
label='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
|
||||
value={PRODUCT_FLAG_OPTIONS.filter((opt) =>
|
||||
(formik.values.flags || []).includes(opt.value)
|
||||
)}
|
||||
required={isSubFlagRequired}
|
||||
value={selectedSubFlagValues}
|
||||
onChange={(val) => {
|
||||
const arr = Array.isArray(val) ? val : val ? [val] : [];
|
||||
formik.setFieldValue(
|
||||
'flags',
|
||||
'sub_flags',
|
||||
arr.map((v) => (v as OptionType).value)
|
||||
);
|
||||
}}
|
||||
options={PRODUCT_FLAG_OPTIONS}
|
||||
isError={formik.touched.flags && Boolean(formik.errors.flags)}
|
||||
errorMessage={formik.errors.flags as string}
|
||||
isDisabled={type === 'detail'}
|
||||
options={subFlagOptions}
|
||||
isError={
|
||||
formik.touched.sub_flags && Boolean(formik.errors.sub_flags)
|
||||
}
|
||||
errorMessage={formik.errors.sub_flags as string}
|
||||
isDisabled={type === 'detail' || !formik.values.flag}
|
||||
isClearable
|
||||
/>
|
||||
</div>
|
||||
|
||||
+6
-2
@@ -15,7 +15,10 @@ export type BaseProduct = {
|
||||
uom: Uom;
|
||||
product_category: ProductCategory;
|
||||
suppliers: (BaseSupplier & { price: number })[];
|
||||
flags: string[];
|
||||
flag: string;
|
||||
sub_flag?: string;
|
||||
sub_flags?: string[];
|
||||
flags?: string[];
|
||||
};
|
||||
|
||||
export type Product = BaseMetadata & BaseProduct;
|
||||
@@ -34,7 +37,8 @@ export type CreateProductPayload = {
|
||||
supplier_id: number;
|
||||
price: number;
|
||||
}[];
|
||||
flags: string[];
|
||||
flag: string;
|
||||
sub_flags?: string[];
|
||||
};
|
||||
|
||||
export type UpdateProductPayload = CreateProductPayload;
|
||||
|
||||
Reference in New Issue
Block a user