refactor(FE-114,136): improve form validation handling and set touched state asynchronously

This commit is contained in:
rstubryan
2025-10-22 10:54:20 +07:00
parent b35d513e44
commit 9c114628c7
@@ -512,44 +512,43 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
};
// HELPER FUNCTIONS
const isRepeaterInputError = <T extends keyof CreateRecordingPayload>(
const isRepeaterInputError = <
T extends 'feed_data' | 'body_weight' | 'vaccination' | 'mortality',
>(
arrayName: T,
field: T extends 'feed_data'
? keyof CreateRecordingPayload['feed_data'][0]
column: T extends 'feed_data'
? keyof RecordingFormValues['feed_data'][0]
: T extends 'body_weight'
? keyof CreateRecordingPayload['body_weight'][0]
? keyof RecordingFormValues['body_weight'][0]
: T extends 'vaccination'
? keyof CreateRecordingPayload['vaccination'][0]
? keyof RecordingFormValues['vaccination'][0]
: T extends 'mortality'
? keyof CreateRecordingPayload['mortality'][0]
? keyof RecordingFormValues['mortality'][0]
: never,
idx: number
) => {
const touched = formik.touched[arrayName] as
| {
[key: string]: boolean | undefined;
}[]
| undefined;
const errors = formik.errors[arrayName] as
| {
[key: string]: string | undefined;
}[]
| undefined;
if (!touched || !Array.isArray(touched)) {
if (
!formik.touched[arrayName] ||
!Array.isArray(formik.touched[arrayName])
) {
return {
isError: false,
errorMessage: undefined,
errorMessage: '',
};
}
const touchedField = touched[idx]?.[field as string];
const errorField = errors?.[idx]?.[field as string];
const touchedField = formik.touched[arrayName]?.[idx]?.[column as string];
const errorField = formik.errors[arrayName]?.[idx] as Record<
string,
string
>;
return {
isError: touchedField && Boolean(errorField),
errorMessage: touchedField ? errorField : undefined,
isError: touchedField && Boolean(errorField?.[column as string]),
errorMessage:
touchedField && errorField?.[column as string]
? errorField[column as string]
: '',
};
};
@@ -576,9 +575,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
label='Lokasi'
value={formik.values.location ?? undefined}
onChange={(val) => {
formik.setFieldTouched('location', true);
formik.setFieldTouched('location_id', true);
locationChangeHandler(val);
setTimeout(() => {
formik.setFieldTouched('location', true);
formik.setFieldTouched('location_id', true);
}, 0);
}}
options={locationOptions}
onInputChange={setLocationSelectInputValue}
@@ -625,9 +626,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
label='Flock'
value={formik.values.flock ?? undefined}
onChange={(val) => {
formik.setFieldTouched('flock', true);
formik.setFieldTouched('flock_id', true);
flockChangeHandler(val);
setTimeout(() => {
formik.setFieldTouched('flock', true);
formik.setFieldTouched('flock_id', true);
}, 0);
}}
options={flockOptions}
onInputChange={setFlockSelectInputValue}
@@ -651,9 +654,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
label='Kandang'
value={formik.values.coop ?? undefined}
onChange={(val) => {
formik.setFieldTouched('coop', true);
formik.setFieldTouched('coop_id', true);
coopChangeHandler(val);
setTimeout(() => {
formik.setFieldTouched('coop', true);
formik.setFieldTouched('coop_id', true);
}, 0);
}}
options={coopOptions}
isError={
@@ -756,14 +761,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
) ?? '')
: '';
formik.setFieldTouched(
`feed_data.${idx}.feed`,
true
);
formik.setFieldTouched(
`feed_data.${idx}.feed_id`,
true
);
formik.setFieldValue(
`feed_data.${idx}.feed`,
val
@@ -780,6 +777,16 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
`feed_data.${idx}.feed_stock`,
0
);
setTimeout(() => {
formik.setFieldTouched(
`feed_data.${idx}.feed`,
true
);
formik.setFieldTouched(
`feed_data.${idx}.feed_id`,
true
);
}, 0);
}}
options={pakanOptions}
isLoading={isLoadingPakan}
@@ -1220,14 +1227,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
productWarehouseId as number
) ?? '')
: '';
formik.setFieldTouched(
`vaccination.${idx}.vaccine`,
true
);
formik.setFieldTouched(
`vaccination.${idx}.vaccine_id`,
true
);
formik.setFieldValue(
`vaccination.${idx}.vaccine`,
val
@@ -1244,6 +1243,17 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
`vaccination.${idx}.used_stock`,
0
);
// Set touched after setting values to trigger validation
setTimeout(() => {
formik.setFieldTouched(
`vaccination.${idx}.vaccine`,
true
);
formik.setFieldTouched(
`vaccination.${idx}.vaccine_id`,
true
);
}, 0);
}}
options={ovkOptions}
isLoading={isLoadingOvk}