From 10a37fde751a01152ed4a84ff1cb1da7a4213ede Mon Sep 17 00:00:00 2001 From: randy-ar Date: Mon, 29 Dec 2025 15:01:42 +0700 Subject: [PATCH] fix(FE): fix delete and update button row in master data production standards --- .../form/ProductionStandardForm.schema.ts | 4 +- .../form/ProductionStandardForm.tsx | 91 +++++++++++-------- 2 files changed, 57 insertions(+), 38 deletions(-) diff --git a/src/components/pages/master-data/production-standard/form/ProductionStandardForm.schema.ts b/src/components/pages/master-data/production-standard/form/ProductionStandardForm.schema.ts index 6fc3799b..55e68039 100644 --- a/src/components/pages/master-data/production-standard/form/ProductionStandardForm.schema.ts +++ b/src/components/pages/master-data/production-standard/form/ProductionStandardForm.schema.ts @@ -68,7 +68,9 @@ export const createProductionStandardRepeaterFormSchema = ( export const createProductionStandardFormSchema = (category: string) => { return Yup.object({ name: Yup.string().required('Nama wajib diisi!'), - project_category: Yup.string().required('Kategori proyek wajib diisi!'), + project_category: Yup.string() + .min(1, 'Kategori proyek wajib diisi!') + .required('Kategori proyek wajib diisi!'), details: Yup.array().of( createProductionStandardRepeaterFormSchema(category) ), diff --git a/src/components/pages/master-data/production-standard/form/ProductionStandardForm.tsx b/src/components/pages/master-data/production-standard/form/ProductionStandardForm.tsx index 99edb852..fe424838 100644 --- a/src/components/pages/master-data/production-standard/form/ProductionStandardForm.tsx +++ b/src/components/pages/master-data/production-standard/form/ProductionStandardForm.tsx @@ -29,6 +29,7 @@ import toast from 'react-hot-toast'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import { useModal } from '@/components/Modal'; import RequirePermission from '@/components/helper/RequirePermission'; +import Tooltip from '@/components/Tooltip'; type TableRowsType = { customRow: boolean; @@ -175,13 +176,15 @@ const ProductionStandardForm = ({ } = useFormStore(); // ===== Formik ===== + // Initial values - only recalculate when initialValue changes (for edit/detail mode) + // For add mode, we load from cache via useEffect instead to avoid race conditions const formikInitialValues = useMemo(() => { - // For add mode, merge cached data with initial values - if (formType === 'add' && formData) { + if (formType === 'add') { + // Don't use formData here - will be loaded via useEffect return { - name: formData.name || '', - project_category: formData.project_category || '', - details: formData.details || [], + name: '', + project_category: '', + details: [], } as ProductionStandardFormValues; } @@ -190,10 +193,11 @@ const ProductionStandardForm = ({ project_category: initialValue?.project_category || '', details: convertStandardValueToFormValues(initialValue?.details || []), } as ProductionStandardFormValues; - }, [initialValue, formData, formType]); + }, [initialValue, formType]); const formik = useFormik({ initialValues: formikInitialValues as ProductionStandardFormValues, - enableReinitialize: true, + // Only enable reinitialize for edit/detail mode, not add mode + enableReinitialize: formType !== 'add', onSubmit: (values) => { switch (formType) { case 'add': @@ -255,36 +259,38 @@ const ProductionStandardForm = ({ const { setValues: repeaterFormikSetValues } = repeaterFormik; // ===== Effect ===== - // Load initial values only when component mounts or when initialValue changes (for edit mode) - // This allows: - // 1. Add mode: Load cached data from formData store - // 2. Edit mode: Load existing data from initialValue - // We use initialValue?.id as dependency to avoid infinite loops + // Load cached data only once on mount for add mode + const [isInitialized, setIsInitialized] = useState(false); + useEffect(() => { - if (formType === 'add' && formData) { - // For add mode, load from cache + if (formType === 'add' && formData && !isInitialized) { + // For add mode, load from cache only on initial mount formikSetValues({ name: formData.name || '', project_category: formData.project_category || '', details: formData.details || [], } as ProductionStandardFormValues); - } else if (formType === 'detail' && initialValue) { - // For detail mode, load from initialValue and convert the details + setIsInitialized(true); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); // Only run once on mount + + // For edit/detail mode, update when initialValue changes + useEffect(() => { + if (formType === 'detail' && initialValue) { formikSetValues({ name: initialValue.name || '', project_category: initialValue.project_category || '', details: convertStandardValueToFormValues(initialValue.details || []), } as ProductionStandardFormValues); } else if (formType === 'edit' && initialValue) { - // For edit mode, load from initialValue and convert the details formikSetValues({ name: initialValue.name || '', project_category: initialValue.project_category || '', details: convertStandardValueToFormValues(initialValue.details || []), } as ProductionStandardFormValues); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [formData, initialValue?.id]); // Trigger when formData or initialValue.id changes + }, [initialValue?.id, formType]); // ===== Data Table ===== const tableRows = useMemo(() => { @@ -323,11 +329,6 @@ const ProductionStandardForm = ({ }, [formik.values.details]); const columns = useMemo[]>(() => { const baseColumns: ColumnDef[] = [ - { - header: 'No', - accessorFn: (row, index) => index + 1, - enableSorting: false, - }, { header: 'Minggu', accessorKey: 'week', @@ -407,6 +408,7 @@ const ProductionStandardForm = ({ variant='outline' color='warning' className='p-2' + type='button' onClick={() => handleEditClick(row.row.original.week)} > @@ -415,6 +417,7 @@ const ProductionStandardForm = ({ variant='outline' color='error' className='p-2' + type='button' onClick={() => handleRemoveRow(row.row.original.week)} > @@ -430,7 +433,7 @@ const ProductionStandardForm = ({ ...uniformityColumns, ...(formType !== 'detail' ? [actionColumn] : []), ]; - }, [formik.values.project_category, formType]); + }, [formik.values, formType]); // ===== Handler ===== const handleAddRow = async ( @@ -488,9 +491,11 @@ const ProductionStandardForm = ({ setIsAddingRow(false); }; - const handleRemoveRow = (week: number) => { - const newValues = (formik.values.details || []).filter( - (detail) => detail.week !== week + const handleRemoveRow = async (week: number) => { + // Access formik.values directly to get the latest values + const currentDetails = formik.values.details || []; + const newValues = currentDetails.filter( + (detail) => Number(detail.week) !== Number(week) ); const updatedFormValues = { @@ -745,6 +750,7 @@ const ProductionStandardForm = ({ } required isDisabled={formType === 'detail'} + isClearable /> @@ -1105,16 +1111,27 @@ const ProductionStandardForm = ({ Batal )} - + + {/* Should not be absolute */}