refactor(FE): Validate duplicates by selected record date

This commit is contained in:
rstubryan
2026-01-17 12:03:32 +07:00
parent 67d695303e
commit 4c4c70e10f
2 changed files with 75 additions and 14 deletions
@@ -104,7 +104,7 @@ export const RecordingGrowingFormSchema: Yup.ObjectSchema<RecordingGrowingFormSc
.required('Project Flock Kandang wajib diisi!') .required('Project Flock Kandang wajib diisi!')
.test( .test(
'not-already-recorded', 'not-already-recorded',
'Project Flock ini sudah direcord hari ini!', 'Project Flock ini sudah direcord pada tanggal tersebut!',
function (value) { function (value) {
const recordedProjectFlockIds = this.options.context const recordedProjectFlockIds = this.options.context
?.recordedProjectFlockIds as Set<number>; ?.recordedProjectFlockIds as Set<number>;
@@ -56,6 +56,7 @@ import {
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang'; import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
import { Kandang } from '@/types/api/master-data/kandang'; import { Kandang } from '@/types/api/master-data/kandang';
import * as Yup from 'yup';
import { import {
RecordingGrowingFormSchema, RecordingGrowingFormSchema,
RecordingLayingFormSchema, RecordingLayingFormSchema,
@@ -231,6 +232,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const [, setNewRecordingData] = useState<Recording | null>(null); const [, setNewRecordingData] = useState<Recording | null>(null);
const [nextDayRecording, setNextDayRecording] = const [nextDayRecording, setNextDayRecording] =
useState<NextDayRecording | null>(null); useState<NextDayRecording | null>(null);
const [currentRecordDate, setCurrentRecordDate] = useState<string>(
new Date().toISOString().split('T')[0]
);
const [duplicateErrorShown, setDuplicateErrorShown] = useState(false);
const approveModal = useModal(); const approveModal = useModal();
const rejectModal = useModal(); const rejectModal = useModal();
@@ -719,18 +724,18 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const recordedProjectFlockKandangIds = useMemo(() => { const recordedProjectFlockKandangIds = useMemo(() => {
if (!isResponseSuccess(existingRecordings)) return new Set<number>(); if (!isResponseSuccess(existingRecordings)) return new Set<number>();
const todayRecordings = existingRecordings.data; const allRecordings = existingRecordings.data;
const recordedIds = new Set<number>(); const recordedIds = new Set<number>();
todayRecordings.forEach((recording) => { allRecordings.forEach((recording) => {
const recordingDate = recording.record_datetime?.split('T')[0]; const recordingDate = recording.record_datetime?.split('T')[0];
if (recordingDate === today) { if (recordingDate === currentRecordDate) {
recordedIds.add(recording.project_flock?.project_flock_kandang_id); recordedIds.add(recording.project_flock?.project_flock_kandang_id);
} }
}); });
return recordedIds; return recordedIds;
}, [existingRecordings, today]); }, [existingRecordings, currentRecordDate]);
const currentTotalChickQty = useMemo(() => { const currentTotalChickQty = useMemo(() => {
if (type === 'add' && projectFlockKandangLookup) { if (type === 'add' && projectFlockKandangLookup) {
@@ -910,14 +915,38 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
initialValues: formikInitialValues, initialValues: formikInitialValues,
enableReinitialize: true, enableReinitialize: true,
validationSchema: (() => { validationSchema: (() => {
let schema;
if (isLayingCategory) { if (isLayingCategory) {
return type === 'edit' schema =
type === 'edit'
? UpdateRecordingLayingFormSchema ? UpdateRecordingLayingFormSchema
: RecordingLayingFormSchema; : RecordingLayingFormSchema;
} } else {
return type === 'edit' schema =
type === 'edit'
? UpdateRecordingGrowingFormSchema ? UpdateRecordingGrowingFormSchema
: RecordingGrowingFormSchema; : RecordingGrowingFormSchema;
}
return schema.clone().concat(
Yup.object().shape({
project_flock_kandang_id: Yup.number().test(
'not-already-recorded',
'Project Flock ini sudah direcord pada tanggal tersebut!',
function (value) {
if (type !== 'add') return true;
if (value && recordedProjectFlockKandangIds.has(value)) {
if (this.createError) {
return this.createError({
message: `Project Flock ini sudah direcord pada tanggal ${formatDate(currentRecordDate, 'DD MMMM YYYY')}!`,
});
}
return false;
}
return true;
}
),
})
);
})(), })(),
validateOnChange: true, validateOnChange: true,
validateOnBlur: true, validateOnBlur: true,
@@ -1149,6 +1178,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
setSelectedLocation(location); setSelectedLocation(location);
setSelectedProjectFlock(null); setSelectedProjectFlock(null);
setSelectedKandang(null); setSelectedKandang(null);
if (duplicateErrorShown) {
toast.dismiss();
setDuplicateErrorShown(false);
}
setSelectedProjectFlockLocationId( setSelectedProjectFlockLocationId(
location ? location.value.toString() : '' location ? location.value.toString() : ''
); );
@@ -1159,6 +1192,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const projectFlockChangeHandler = (val: OptionType | OptionType[] | null) => { const projectFlockChangeHandler = (val: OptionType | OptionType[] | null) => {
setSelectedProjectFlock(val as OptionType); setSelectedProjectFlock(val as OptionType);
setSelectedKandang(null); setSelectedKandang(null);
if (duplicateErrorShown) {
toast.dismiss();
setDuplicateErrorShown(false);
}
formik.setFieldValue('project_flock_kandang', null); formik.setFieldValue('project_flock_kandang', null);
formik.setFieldValue('project_flock_kandang_id', 0); formik.setFieldValue('project_flock_kandang_id', 0);
}; };
@@ -1166,6 +1203,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const kandangChangeHandler = (val: OptionType | OptionType[] | null) => { const kandangChangeHandler = (val: OptionType | OptionType[] | null) => {
const kandang = val as OptionType; const kandang = val as OptionType;
setSelectedKandang(kandang); setSelectedKandang(kandang);
if (duplicateErrorShown) {
toast.dismiss();
setDuplicateErrorShown(false);
}
if (selectedLocation && kandang) { if (selectedLocation && kandang) {
setStockProductsLocationId(selectedLocation.value.toString()); setStockProductsLocationId(selectedLocation.value.toString());
setStockProductsKandangId(kandang.value.toString()); setStockProductsKandangId(kandang.value.toString());
@@ -1187,9 +1228,18 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const handleRecordDateChange = useCallback( const handleRecordDateChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => { (e: React.ChangeEvent<HTMLInputElement>) => {
formik.setFieldValue('record_date', e.target.value); const newDate = e.target.value;
formik.setFieldValue('record_date', newDate);
setCurrentRecordDate(newDate);
if (duplicateErrorShown) {
toast.dismiss();
setDuplicateErrorShown(false);
}
setTimeout(() => {
formik.validateField('project_flock_kandang_id');
}, 0);
}, },
[formik] [formik, duplicateErrorShown]
); );
useEffect(() => { useEffect(() => {
@@ -1199,8 +1249,19 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
if (type === 'add') { if (type === 'add') {
if (recordedProjectFlockKandangIds.has(projectFlockKandangId)) { if (recordedProjectFlockKandangIds.has(projectFlockKandangId)) {
toast.error('Project Flock Kandang ini sudah direcord hari ini!'); if (!duplicateErrorShown) {
toast.error(
`Project Flock Kandang ini sudah direcord pada tanggal ${formatDate(currentRecordDate, 'DD MMMM YYYY')}!`,
{ duration: Infinity }
);
setDuplicateErrorShown(true);
}
return; return;
} else {
if (duplicateErrorShown) {
toast.dismiss();
setDuplicateErrorShown(false);
}
} }
if ( if (