fix(FE): fix delete and update button row in master data production standards

This commit is contained in:
randy-ar
2025-12-29 15:01:42 +07:00
parent cd3a5ad441
commit 10a37fde75
2 changed files with 57 additions and 38 deletions
@@ -68,7 +68,9 @@ export const createProductionStandardRepeaterFormSchema = (
export const createProductionStandardFormSchema = (category: string) => { export const createProductionStandardFormSchema = (category: string) => {
return Yup.object({ return Yup.object({
name: Yup.string().required('Nama wajib diisi!'), 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( details: Yup.array().of(
createProductionStandardRepeaterFormSchema(category) createProductionStandardRepeaterFormSchema(category)
), ),
@@ -29,6 +29,7 @@ import toast from 'react-hot-toast';
import ConfirmationModal from '@/components/modal/ConfirmationModal'; import ConfirmationModal from '@/components/modal/ConfirmationModal';
import { useModal } from '@/components/Modal'; import { useModal } from '@/components/Modal';
import RequirePermission from '@/components/helper/RequirePermission'; import RequirePermission from '@/components/helper/RequirePermission';
import Tooltip from '@/components/Tooltip';
type TableRowsType = { type TableRowsType = {
customRow: boolean; customRow: boolean;
@@ -175,13 +176,15 @@ const ProductionStandardForm = ({
} = useFormStore(); } = useFormStore();
// ===== Formik ===== // ===== 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(() => { const formikInitialValues = useMemo(() => {
// For add mode, merge cached data with initial values if (formType === 'add') {
if (formType === 'add' && formData) { // Don't use formData here - will be loaded via useEffect
return { return {
name: formData.name || '', name: '',
project_category: formData.project_category || '', project_category: '',
details: formData.details || [], details: [],
} as ProductionStandardFormValues; } as ProductionStandardFormValues;
} }
@@ -190,10 +193,11 @@ const ProductionStandardForm = ({
project_category: initialValue?.project_category || '', project_category: initialValue?.project_category || '',
details: convertStandardValueToFormValues(initialValue?.details || []), details: convertStandardValueToFormValues(initialValue?.details || []),
} as ProductionStandardFormValues; } as ProductionStandardFormValues;
}, [initialValue, formData, formType]); }, [initialValue, formType]);
const formik = useFormik<ProductionStandardFormValues>({ const formik = useFormik<ProductionStandardFormValues>({
initialValues: formikInitialValues as ProductionStandardFormValues, initialValues: formikInitialValues as ProductionStandardFormValues,
enableReinitialize: true, // Only enable reinitialize for edit/detail mode, not add mode
enableReinitialize: formType !== 'add',
onSubmit: (values) => { onSubmit: (values) => {
switch (formType) { switch (formType) {
case 'add': case 'add':
@@ -255,36 +259,38 @@ const ProductionStandardForm = ({
const { setValues: repeaterFormikSetValues } = repeaterFormik; const { setValues: repeaterFormikSetValues } = repeaterFormik;
// ===== Effect ===== // ===== Effect =====
// Load initial values only when component mounts or when initialValue changes (for edit mode) // Load cached data only once on mount for add mode
// This allows: const [isInitialized, setIsInitialized] = useState(false);
// 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
useEffect(() => { useEffect(() => {
if (formType === 'add' && formData) { if (formType === 'add' && formData && !isInitialized) {
// For add mode, load from cache // For add mode, load from cache only on initial mount
formikSetValues({ formikSetValues({
name: formData.name || '', name: formData.name || '',
project_category: formData.project_category || '', project_category: formData.project_category || '',
details: formData.details || [], details: formData.details || [],
} as ProductionStandardFormValues); } as ProductionStandardFormValues);
} else if (formType === 'detail' && initialValue) { setIsInitialized(true);
// For detail mode, load from initialValue and convert the details }
// 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({ formikSetValues({
name: initialValue.name || '', name: initialValue.name || '',
project_category: initialValue.project_category || '', project_category: initialValue.project_category || '',
details: convertStandardValueToFormValues(initialValue.details || []), details: convertStandardValueToFormValues(initialValue.details || []),
} as ProductionStandardFormValues); } as ProductionStandardFormValues);
} else if (formType === 'edit' && initialValue) { } else if (formType === 'edit' && initialValue) {
// For edit mode, load from initialValue and convert the details
formikSetValues({ formikSetValues({
name: initialValue.name || '', name: initialValue.name || '',
project_category: initialValue.project_category || '', project_category: initialValue.project_category || '',
details: convertStandardValueToFormValues(initialValue.details || []), details: convertStandardValueToFormValues(initialValue.details || []),
} as ProductionStandardFormValues); } as ProductionStandardFormValues);
} }
// eslint-disable-next-line react-hooks/exhaustive-deps }, [initialValue?.id, formType]);
}, [formData, initialValue?.id]); // Trigger when formData or initialValue.id changes
// ===== Data Table ===== // ===== Data Table =====
const tableRows = useMemo(() => { const tableRows = useMemo(() => {
@@ -323,11 +329,6 @@ const ProductionStandardForm = ({
}, [formik.values.details]); }, [formik.values.details]);
const columns = useMemo<ColumnDef<TableRowsType>[]>(() => { const columns = useMemo<ColumnDef<TableRowsType>[]>(() => {
const baseColumns: ColumnDef<TableRowsType>[] = [ const baseColumns: ColumnDef<TableRowsType>[] = [
{
header: 'No',
accessorFn: (row, index) => index + 1,
enableSorting: false,
},
{ {
header: 'Minggu', header: 'Minggu',
accessorKey: 'week', accessorKey: 'week',
@@ -407,6 +408,7 @@ const ProductionStandardForm = ({
variant='outline' variant='outline'
color='warning' color='warning'
className='p-2' className='p-2'
type='button'
onClick={() => handleEditClick(row.row.original.week)} onClick={() => handleEditClick(row.row.original.week)}
> >
<Icon icon='mdi:pencil' /> <Icon icon='mdi:pencil' />
@@ -415,6 +417,7 @@ const ProductionStandardForm = ({
variant='outline' variant='outline'
color='error' color='error'
className='p-2' className='p-2'
type='button'
onClick={() => handleRemoveRow(row.row.original.week)} onClick={() => handleRemoveRow(row.row.original.week)}
> >
<Icon icon='mdi:delete' /> <Icon icon='mdi:delete' />
@@ -430,7 +433,7 @@ const ProductionStandardForm = ({
...uniformityColumns, ...uniformityColumns,
...(formType !== 'detail' ? [actionColumn] : []), ...(formType !== 'detail' ? [actionColumn] : []),
]; ];
}, [formik.values.project_category, formType]); }, [formik.values, formType]);
// ===== Handler ===== // ===== Handler =====
const handleAddRow = async ( const handleAddRow = async (
@@ -488,9 +491,11 @@ const ProductionStandardForm = ({
setIsAddingRow(false); setIsAddingRow(false);
}; };
const handleRemoveRow = (week: number) => { const handleRemoveRow = async (week: number) => {
const newValues = (formik.values.details || []).filter( // Access formik.values directly to get the latest values
(detail) => detail.week !== week const currentDetails = formik.values.details || [];
const newValues = currentDetails.filter(
(detail) => Number(detail.week) !== Number(week)
); );
const updatedFormValues = { const updatedFormValues = {
@@ -745,6 +750,7 @@ const ProductionStandardForm = ({
} }
required required
isDisabled={formType === 'detail'} isDisabled={formType === 'detail'}
isClearable
/> />
</div> </div>
<Table<TableRowsType> <Table<TableRowsType>
@@ -1105,16 +1111,27 @@ const ProductionStandardForm = ({
<Icon icon='mdi:close' /> Batal <Icon icon='mdi:close' /> Batal
</Button> </Button>
)} )}
<Button <Tooltip
type='submit' content={
color={editMode ? 'warning' : 'success'} formik.values.project_category === ''
className='min-w-24' ? 'Isi kategori proyek terlebih dahulu'
disabled={isAddingRow} : ''
isLoading={isAddingRow} }
> >
<Icon icon={editMode ? 'mdi:pencil' : 'mdi:plus'} />{' '} <Button
{editMode ? 'Edit Data' : 'Tambah Data'} type='submit'
</Button> color={editMode ? 'warning' : 'success'}
className='min-w-24'
disabled={
isAddingRow ||
formik.values.project_category === ''
}
isLoading={isAddingRow}
>
<Icon icon={editMode ? 'mdi:pencil' : 'mdi:plus'} />{' '}
{editMode ? 'Edit Data' : 'Tambah Data'}
</Button>
</Tooltip>
{/* Should not be absolute */} {/* Should not be absolute */}
<Button <Button
type='button' type='button'