mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 23:35:45 +00:00
Merge branch 'fix/adjustment-confirmation-modal-and-recording-form' into 'development'
[HOTFIX/FE] Adjustment Confirmation Modal with Notes Usage and Recording Form See merge request mbugroup/lti-web-client!298
This commit is contained in:
@@ -13,6 +13,7 @@ interface ConfirmationModalWithNotesProps
|
|||||||
extends Omit<ConfirmationModalProps, 'children' | 'primaryButton'> {
|
extends Omit<ConfirmationModalProps, 'children' | 'primaryButton'> {
|
||||||
rows?: number;
|
rows?: number;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
onClose?: () => void;
|
||||||
|
|
||||||
primaryButton?: {
|
primaryButton?: {
|
||||||
text?: string;
|
text?: string;
|
||||||
@@ -32,6 +33,7 @@ const ConfirmationModalWithNotes: React.FC<ConfirmationModalWithNotesProps> = ({
|
|||||||
className,
|
className,
|
||||||
rows = 3,
|
rows = 3,
|
||||||
placeholder = 'Catatan...',
|
placeholder = 'Catatan...',
|
||||||
|
onClose,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const randomId = useId();
|
const randomId = useId();
|
||||||
@@ -41,6 +43,11 @@ const ConfirmationModalWithNotes: React.FC<ConfirmationModalWithNotesProps> = ({
|
|||||||
setNotes(e.target.value);
|
setNotes(e.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const closeModalHandler = () => {
|
||||||
|
onClose?.();
|
||||||
|
ref.current?.close();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@@ -49,12 +56,32 @@ const ConfirmationModalWithNotes: React.FC<ConfirmationModalWithNotesProps> = ({
|
|||||||
closeOnBackdrop={closeOnBackdrop}
|
closeOnBackdrop={closeOnBackdrop}
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
...primaryButton,
|
...primaryButton,
|
||||||
onClick: () => {
|
onClick: (e) => {
|
||||||
primaryButton?.onClick?.(notes);
|
if (primaryButton && primaryButton?.onClick) {
|
||||||
|
primaryButton?.onClick?.(notes);
|
||||||
|
} else {
|
||||||
|
closeModalHandler();
|
||||||
|
}
|
||||||
|
|
||||||
setNotes('');
|
setNotes('');
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
secondaryButton={secondaryButton}
|
secondaryButton={
|
||||||
|
secondaryButton
|
||||||
|
? {
|
||||||
|
text: secondaryButton?.text ?? 'Tidak',
|
||||||
|
onClick: (e) => {
|
||||||
|
if (secondaryButton && secondaryButton?.onClick) {
|
||||||
|
secondaryButton.onClick?.(e);
|
||||||
|
} else {
|
||||||
|
closeModalHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
setNotes('');
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
className={className}
|
className={className}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ const ExpenseRequestContent = ({
|
|||||||
const [isCompleteLoading, setIsCompleteLoading] = useState(false);
|
const [isCompleteLoading, setIsCompleteLoading] = useState(false);
|
||||||
const [isApproveLoading, setIsApproveLoading] = useState(false);
|
const [isApproveLoading, setIsApproveLoading] = useState(false);
|
||||||
const [isRejectLoading, setIsRejectLoading] = useState(false);
|
const [isRejectLoading, setIsRejectLoading] = useState(false);
|
||||||
|
const [, setApprovalNotes] = useState('');
|
||||||
|
|
||||||
const formik = useFormik<UploadRequestDocumentsFormValues>({
|
const formik = useFormik<UploadRequestDocumentsFormValues>({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
@@ -130,10 +131,12 @@ const ExpenseRequestContent = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const approveClickHandler = () => {
|
const approveClickHandler = () => {
|
||||||
|
setApprovalNotes('');
|
||||||
approveModal.openModal();
|
approveModal.openModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
const rejectClickHandler = () => {
|
const rejectClickHandler = () => {
|
||||||
|
setApprovalNotes('');
|
||||||
rejectModal.openModal();
|
rejectModal.openModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -200,6 +203,7 @@ const ExpenseRequestContent = ({
|
|||||||
approveModal.closeModal();
|
approveModal.closeModal();
|
||||||
|
|
||||||
toast.success(approveResponse?.message);
|
toast.success(approveResponse?.message);
|
||||||
|
setApprovalNotes('');
|
||||||
router.push('/expense');
|
router.push('/expense');
|
||||||
} else {
|
} else {
|
||||||
approveModal.closeModal();
|
approveModal.closeModal();
|
||||||
@@ -234,6 +238,7 @@ const ExpenseRequestContent = ({
|
|||||||
rejectModal.closeModal();
|
rejectModal.closeModal();
|
||||||
|
|
||||||
toast.success(rejectResponse.message);
|
toast.success(rejectResponse.message);
|
||||||
|
setApprovalNotes('');
|
||||||
router.push('/expense');
|
router.push('/expense');
|
||||||
} else {
|
} else {
|
||||||
rejectModal.closeModal();
|
rejectModal.closeModal();
|
||||||
@@ -710,6 +715,10 @@ const ExpenseRequestContent = ({
|
|||||||
text='Apakah anda yakin ingin approve data biaya operasional ini?'
|
text='Apakah anda yakin ingin approve data biaya operasional ini?'
|
||||||
secondaryButton={{
|
secondaryButton={{
|
||||||
text: 'Tidak',
|
text: 'Tidak',
|
||||||
|
onClick: () => {
|
||||||
|
setApprovalNotes('');
|
||||||
|
approveModal.closeModal();
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: 'Ya',
|
text: 'Ya',
|
||||||
@@ -725,6 +734,10 @@ const ExpenseRequestContent = ({
|
|||||||
text='Apakah anda yakin ingin reject data biaya operasional ini?'
|
text='Apakah anda yakin ingin reject data biaya operasional ini?'
|
||||||
secondaryButton={{
|
secondaryButton={{
|
||||||
text: 'Tidak',
|
text: 'Tidak',
|
||||||
|
onClick: () => {
|
||||||
|
setApprovalNotes('');
|
||||||
|
rejectModal.closeModal();
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: 'Ya',
|
text: 'Ya',
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ const ExpensesTable = () => {
|
|||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
const [isApproveLoading, setIsApproveLoading] = useState(false);
|
const [isApproveLoading, setIsApproveLoading] = useState(false);
|
||||||
const [isRejectLoading, setIsRejectLoading] = useState(false);
|
const [isRejectLoading, setIsRejectLoading] = useState(false);
|
||||||
|
const [, setApprovalNotes] = useState('');
|
||||||
|
|
||||||
const [sorting, setSorting] = useState<SortingState>([]);
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
||||||
@@ -342,6 +343,7 @@ const ExpensesTable = () => {
|
|||||||
[String(props.row.original.id)]: true,
|
[String(props.row.original.id)]: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setApprovalNotes('');
|
||||||
approveModal.openModal();
|
approveModal.openModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -353,6 +355,7 @@ const ExpensesTable = () => {
|
|||||||
[String(props.row.original.id)]: true,
|
[String(props.row.original.id)]: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setApprovalNotes('');
|
||||||
rejectModal.openModal();
|
rejectModal.openModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -412,10 +415,12 @@ const ExpensesTable = () => {
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
const bulkApproveClickHandler = () => {
|
const bulkApproveClickHandler = () => {
|
||||||
|
setApprovalNotes('');
|
||||||
approveModal.openModal();
|
approveModal.openModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
const bulkRejectClickHandler = () => {
|
const bulkRejectClickHandler = () => {
|
||||||
|
setApprovalNotes('');
|
||||||
rejectModal.openModal();
|
rejectModal.openModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -468,6 +473,7 @@ const ExpensesTable = () => {
|
|||||||
`Berhasil approve ${selectedRowIds.length} data biaya operasional!`
|
`Berhasil approve ${selectedRowIds.length} data biaya operasional!`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
setApprovalNotes('');
|
||||||
setRowSelection({});
|
setRowSelection({});
|
||||||
} else {
|
} else {
|
||||||
approveModal.closeModal();
|
approveModal.closeModal();
|
||||||
@@ -509,6 +515,7 @@ const ExpensesTable = () => {
|
|||||||
toast.success(
|
toast.success(
|
||||||
`Berhasil reject ${selectedRowIds.length} data biaya operasional!`
|
`Berhasil reject ${selectedRowIds.length} data biaya operasional!`
|
||||||
);
|
);
|
||||||
|
setApprovalNotes('');
|
||||||
setRowSelection({});
|
setRowSelection({});
|
||||||
} else {
|
} else {
|
||||||
rejectModal.closeModal();
|
rejectModal.closeModal();
|
||||||
@@ -787,6 +794,10 @@ const ExpensesTable = () => {
|
|||||||
text='Apakah anda yakin ingin approve data biaya operasional ini?'
|
text='Apakah anda yakin ingin approve data biaya operasional ini?'
|
||||||
secondaryButton={{
|
secondaryButton={{
|
||||||
text: 'Tidak',
|
text: 'Tidak',
|
||||||
|
onClick: () => {
|
||||||
|
setApprovalNotes('');
|
||||||
|
approveModal.closeModal();
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: 'Ya',
|
text: 'Ya',
|
||||||
@@ -802,6 +813,10 @@ const ExpensesTable = () => {
|
|||||||
text='Apakah anda yakin ingin reject data biaya operasional ini?'
|
text='Apakah anda yakin ingin reject data biaya operasional ini?'
|
||||||
secondaryButton={{
|
secondaryButton={{
|
||||||
text: 'Tidak',
|
text: 'Tidak',
|
||||||
|
onClick: () => {
|
||||||
|
setApprovalNotes('');
|
||||||
|
rejectModal.closeModal();
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: 'Ya',
|
text: 'Ya',
|
||||||
|
|||||||
@@ -241,6 +241,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
new Date().toISOString().split('T')[0]
|
new Date().toISOString().split('T')[0]
|
||||||
);
|
);
|
||||||
const [duplicateErrorShown, setDuplicateErrorShown] = useState(false);
|
const [duplicateErrorShown, setDuplicateErrorShown] = useState(false);
|
||||||
|
const [nextDayErrorShown, setNextDayErrorShown] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
@@ -553,6 +554,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
|
|
||||||
const nextDayRecordingUrl = useMemo(() => {
|
const nextDayRecordingUrl = useMemo(() => {
|
||||||
if (!projectFlockKandangLookup) return null;
|
if (!projectFlockKandangLookup) return null;
|
||||||
|
if (!selectedRecordDate) return null;
|
||||||
const projectFlockKandangId = projectFlockKandangLookup.id;
|
const projectFlockKandangId = projectFlockKandangLookup.id;
|
||||||
return `${RecordingApi.basePath}/next-day?project_flock_kandang_id=${projectFlockKandangId}&record_date=${selectedRecordDate}`;
|
return `${RecordingApi.basePath}/next-day?project_flock_kandang_id=${projectFlockKandangId}&record_date=${selectedRecordDate}`;
|
||||||
}, [projectFlockKandangLookup, selectedRecordDate]);
|
}, [projectFlockKandangLookup, selectedRecordDate]);
|
||||||
@@ -575,10 +577,28 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
setNextDayRecording(
|
setNextDayRecording(
|
||||||
nextDayRecordingData.data as unknown as NextDayRecording
|
nextDayRecordingData.data as unknown as NextDayRecording
|
||||||
);
|
);
|
||||||
|
if (nextDayErrorShown) {
|
||||||
|
toast.dismiss();
|
||||||
|
setNextDayErrorShown(false);
|
||||||
|
}
|
||||||
|
} else if (nextDayRecordingData?.status === 'error') {
|
||||||
|
setNextDayRecording(null);
|
||||||
|
if (!nextDayErrorShown) {
|
||||||
|
toast.error(
|
||||||
|
nextDayRecordingData.message ||
|
||||||
|
'Terjadi kesalahan saat memuat data hari berikutnya',
|
||||||
|
{ duration: Infinity }
|
||||||
|
);
|
||||||
|
setNextDayErrorShown(true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setNextDayRecording(null);
|
setNextDayRecording(null);
|
||||||
|
if (nextDayErrorShown) {
|
||||||
|
toast.dismiss();
|
||||||
|
setNextDayErrorShown(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [nextDayRecordingData]);
|
}, [nextDayRecordingData, nextDayErrorShown]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
rawData: eggProductsData,
|
rawData: eggProductsData,
|
||||||
@@ -1196,6 +1216,66 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
[stockProducts, depletionProductsData, eggProductsData, initialValues, type]
|
[stockProducts, depletionProductsData, eggProductsData, initialValues, type]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getAvailableStockProductOptions = useCallback(
|
||||||
|
(currentIdx: number) => {
|
||||||
|
const selectedProductIds =
|
||||||
|
formik.values.stocks
|
||||||
|
?.filter((s, idx) => {
|
||||||
|
return (
|
||||||
|
idx !== currentIdx &&
|
||||||
|
s.product_warehouse_id &&
|
||||||
|
s.product_warehouse_id !== 0
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.map((s) => s.product_warehouse_id) || [];
|
||||||
|
|
||||||
|
return unifiedStockProducts.filter(
|
||||||
|
(opt) => !selectedProductIds.includes(Number(opt.value))
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[formik.values.stocks, unifiedStockProducts]
|
||||||
|
);
|
||||||
|
|
||||||
|
const getAvailableDepletionProductOptions = useCallback(
|
||||||
|
(currentIdx: number) => {
|
||||||
|
const selectedProductIds =
|
||||||
|
formik.values.depletions
|
||||||
|
?.filter((d, idx) => {
|
||||||
|
return (
|
||||||
|
idx !== currentIdx &&
|
||||||
|
d.product_warehouse_id &&
|
||||||
|
d.product_warehouse_id !== 0
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.map((d) => d.product_warehouse_id) || [];
|
||||||
|
|
||||||
|
return depletionProducts.filter(
|
||||||
|
(opt) => !selectedProductIds.includes(Number(opt.value))
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[formik.values.depletions, depletionProducts]
|
||||||
|
);
|
||||||
|
|
||||||
|
const getAvailableEggProductOptions = useCallback(
|
||||||
|
(currentIdx: number) => {
|
||||||
|
const selectedProductIds =
|
||||||
|
(formik.values as RecordingLayingFormValues).eggs
|
||||||
|
?.filter((e, idx) => {
|
||||||
|
return (
|
||||||
|
idx !== currentIdx &&
|
||||||
|
e.product_warehouse_id &&
|
||||||
|
e.product_warehouse_id !== 0
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.map((e) => e.product_warehouse_id) || [];
|
||||||
|
|
||||||
|
return eggProducts.filter(
|
||||||
|
(opt) => !selectedProductIds.includes(Number(opt.value))
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[formik.values, eggProducts]
|
||||||
|
);
|
||||||
|
|
||||||
const hasExceededStock = useMemo(() => {
|
const hasExceededStock = useMemo(() => {
|
||||||
if ((type as 'add' | 'edit' | 'detail') === 'detail') return false;
|
if ((type as 'add' | 'edit' | 'detail') === 'detail') return false;
|
||||||
return (
|
return (
|
||||||
@@ -1255,6 +1335,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
setDuplicateErrorShown(false);
|
setDuplicateErrorShown(false);
|
||||||
}
|
}
|
||||||
|
if (nextDayErrorShown) {
|
||||||
|
toast.dismiss();
|
||||||
|
setNextDayErrorShown(false);
|
||||||
|
}
|
||||||
setSelectedProjectFlockLocationId(
|
setSelectedProjectFlockLocationId(
|
||||||
location ? location.value.toString() : ''
|
location ? location.value.toString() : ''
|
||||||
);
|
);
|
||||||
@@ -1275,6 +1359,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
setDuplicateErrorShown(false);
|
setDuplicateErrorShown(false);
|
||||||
}
|
}
|
||||||
|
if (nextDayErrorShown) {
|
||||||
|
toast.dismiss();
|
||||||
|
setNextDayErrorShown(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const kandangChangeHandler = (val: OptionType | OptionType[] | null) => {
|
const kandangChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||||
@@ -1291,6 +1379,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
setDuplicateErrorShown(false);
|
setDuplicateErrorShown(false);
|
||||||
}
|
}
|
||||||
|
if (nextDayErrorShown) {
|
||||||
|
toast.dismiss();
|
||||||
|
setNextDayErrorShown(false);
|
||||||
|
}
|
||||||
if (selectedLocation && kandang) {
|
if (selectedLocation && kandang) {
|
||||||
setStockProductsLocationId(selectedLocation.value.toString());
|
setStockProductsLocationId(selectedLocation.value.toString());
|
||||||
setStockProductsKandangId(kandang.value.toString());
|
setStockProductsKandangId(kandang.value.toString());
|
||||||
@@ -1320,11 +1412,15 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
setDuplicateErrorShown(false);
|
setDuplicateErrorShown(false);
|
||||||
}
|
}
|
||||||
|
if (nextDayErrorShown) {
|
||||||
|
toast.dismiss();
|
||||||
|
setNextDayErrorShown(false);
|
||||||
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
formik.validateField('project_flock_kandang_id');
|
formik.validateField('project_flock_kandang_id');
|
||||||
}, 0);
|
}, 0);
|
||||||
},
|
},
|
||||||
[formik, duplicateErrorShown]
|
[formik, duplicateErrorShown, nextDayErrorShown]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { formErrorList, handleFormSubmit, close } = useFormikErrorList(formik);
|
const { formErrorList, handleFormSubmit, close } = useFormikErrorList(formik);
|
||||||
@@ -1350,28 +1446,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
setDuplicateErrorShown(false);
|
setDuplicateErrorShown(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
nextDayRecording &&
|
|
||||||
nextDayRecording.project_flock_kandang_id === projectFlockKandangId
|
|
||||||
) {
|
|
||||||
const hasSameDayRecording = isResponseSuccess(existingRecordings)
|
|
||||||
? existingRecordings.data?.some(
|
|
||||||
(recording: Recording) =>
|
|
||||||
recording.project_flock.project_flock_kandang_id ===
|
|
||||||
projectFlockKandangId &&
|
|
||||||
recording.day === nextDayRecording.next_day
|
|
||||||
)
|
|
||||||
: false;
|
|
||||||
|
|
||||||
if (hasSameDayRecording) {
|
|
||||||
toast.error(
|
|
||||||
`Recording untuk hari ke-${nextDayRecording.next_day} sudah ada datanya.
|
|
||||||
Tidak bisa membuat recording di hari yang sama dengan project flock yang sama, mohon perbarui recording yang sudah ada terlebih dahulu.`
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formik.values.project_flock_kandang_id !== projectFlockKandangId) {
|
if (formik.values.project_flock_kandang_id !== projectFlockKandangId) {
|
||||||
@@ -1831,8 +1905,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
<div>
|
<div>
|
||||||
<span className='text-sm text-gray-600'>Umur</span>
|
<span className='text-sm text-gray-600'>Umur</span>
|
||||||
<p className='font-semibold'>
|
<p className='font-semibold'>
|
||||||
{nextDayRecording
|
{type === 'add'
|
||||||
? `Hari ke-${nextDayRecording.next_day} (Minggu ke-${Math.ceil(nextDayRecording.next_day / 7)})`
|
? nextDayRecording
|
||||||
|
? `Hari ke-${nextDayRecording.next_day} (Minggu ke-${Math.ceil(nextDayRecording.next_day / 7)})`
|
||||||
|
: '-'
|
||||||
: initialValues?.day
|
: initialValues?.day
|
||||||
? `Hari ke-${initialValues.day} (Minggu ke-${Math.ceil(initialValues.day / 7)})`
|
? `Hari ke-${initialValues.day} (Minggu ke-${Math.ceil(initialValues.day / 7)})`
|
||||||
: '-'}
|
: '-'}
|
||||||
@@ -2398,7 +2474,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
option?.value || 0
|
option?.value || 0
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
options={unifiedStockProducts}
|
options={getAvailableStockProductOptions(idx)}
|
||||||
placeholder={
|
placeholder={
|
||||||
!formik.values.project_flock_kandang_id
|
!formik.values.project_flock_kandang_id
|
||||||
? 'Pilih kandang terlebih dahulu'
|
? 'Pilih kandang terlebih dahulu'
|
||||||
@@ -2619,7 +2695,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
option?.value || 0
|
option?.value || 0
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
options={depletionProducts}
|
options={getAvailableDepletionProductOptions(idx)}
|
||||||
placeholder='Pilih Kondisi'
|
placeholder='Pilih Kondisi'
|
||||||
isLoading={isLoadingDepletionProducts}
|
isLoading={isLoadingDepletionProducts}
|
||||||
onMenuScrollToBottom={loadMoreDepletionProducts}
|
onMenuScrollToBottom={loadMoreDepletionProducts}
|
||||||
@@ -2837,7 +2913,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
option?.value || 0
|
option?.value || 0
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
options={eggProducts}
|
options={getAvailableEggProductOptions(idx)}
|
||||||
placeholder='Pilih Kondisi Telur'
|
placeholder='Pilih Kondisi Telur'
|
||||||
isLoading={isLoadingEggProducts}
|
isLoading={isLoadingEggProducts}
|
||||||
onMenuScrollToBottom={loadMoreEggProducts}
|
onMenuScrollToBottom={loadMoreEggProducts}
|
||||||
@@ -3116,7 +3192,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
text='Apakah anda yakin ingin menyetujui data Recording ini?'
|
text='Apakah anda yakin ingin menyetujui data Recording ini?'
|
||||||
secondaryButton={{
|
secondaryButton={{
|
||||||
text: 'Tidak',
|
text: 'Tidak',
|
||||||
onClick: () => setApprovalNotes(''),
|
onClick: () => {
|
||||||
|
setApprovalNotes('');
|
||||||
|
approveModal.closeModal();
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: 'Ya',
|
text: 'Ya',
|
||||||
@@ -3138,7 +3217,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
text='Apakah anda yakin ingin menolak data Recording ini?'
|
text='Apakah anda yakin ingin menolak data Recording ini?'
|
||||||
secondaryButton={{
|
secondaryButton={{
|
||||||
text: 'Tidak',
|
text: 'Tidak',
|
||||||
onClick: () => setApprovalNotes(''),
|
onClick: () => {
|
||||||
|
setApprovalNotes('');
|
||||||
|
rejectModal.closeModal();
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: 'Ya',
|
text: 'Ya',
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ const PurchaseOrderDetail = ({
|
|||||||
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
const [selectedItem, setSelectedItem] = useState<PurchaseItem | null>(null);
|
const [selectedItem, setSelectedItem] = useState<PurchaseItem | null>(null);
|
||||||
|
const [, setApprovalNotes] = useState('');
|
||||||
|
|
||||||
const selectedRowIds = Object.keys(rowSelection).map((item) =>
|
const selectedRowIds = Object.keys(rowSelection).map((item) =>
|
||||||
parseInt(item)
|
parseInt(item)
|
||||||
@@ -207,12 +208,15 @@ const PurchaseOrderDetail = ({
|
|||||||
|
|
||||||
switch (approvalStep) {
|
switch (approvalStep) {
|
||||||
case 1:
|
case 1:
|
||||||
|
setApprovalNotes('');
|
||||||
staffApprovalModal.openModal();
|
staffApprovalModal.openModal();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
setApprovalNotes('');
|
||||||
confirmationModalWithNotes.openModal();
|
confirmationModalWithNotes.openModal();
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
setApprovalNotes('');
|
||||||
acceptApprovalModal.openModal();
|
acceptApprovalModal.openModal();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -225,12 +229,15 @@ const PurchaseOrderDetail = ({
|
|||||||
|
|
||||||
switch (approvalStep) {
|
switch (approvalStep) {
|
||||||
case 1:
|
case 1:
|
||||||
|
setApprovalNotes('');
|
||||||
staffRejectionModal.openModal();
|
staffRejectionModal.openModal();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
setApprovalNotes('');
|
||||||
managerRejectionModal.openModal();
|
managerRejectionModal.openModal();
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
setApprovalNotes('');
|
||||||
acceptRejectionModal.openModal();
|
acceptRejectionModal.openModal();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -406,6 +413,56 @@ const PurchaseOrderDetail = ({
|
|||||||
refetchData,
|
refetchData,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// ===== APPROVAL/REJECTION HANDLERS =====
|
||||||
|
const managerApprovalHandler = async (notes: string) => {
|
||||||
|
const payload: CreateManagerApprovalRequestPayload = {
|
||||||
|
action: 'APPROVED',
|
||||||
|
notes: notes || null,
|
||||||
|
};
|
||||||
|
|
||||||
|
await createManagerApprovalHandler(payload);
|
||||||
|
await refreshApprovals();
|
||||||
|
await refetchData?.();
|
||||||
|
setApprovalNotes('');
|
||||||
|
confirmationModalWithNotes.closeModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const staffRejectionHandler = async (notes: string) => {
|
||||||
|
const payload: CreateStaffApprovalRequestPayload = {
|
||||||
|
action: 'REJECTED',
|
||||||
|
notes: notes || null,
|
||||||
|
};
|
||||||
|
|
||||||
|
await createStaffApprovalHandler(payload);
|
||||||
|
await refetchData?.();
|
||||||
|
setApprovalNotes('');
|
||||||
|
staffRejectionModal.closeModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const acceptRejectionHandler = async (notes: string) => {
|
||||||
|
const payload: CreateAcceptApprovalRequestPayload = {
|
||||||
|
action: 'REJECTED',
|
||||||
|
notes: notes || null,
|
||||||
|
};
|
||||||
|
|
||||||
|
await createAcceptApprovalHandler(payload);
|
||||||
|
await refetchData?.();
|
||||||
|
setApprovalNotes('');
|
||||||
|
acceptRejectionModal.closeModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const managerRejectionHandler = async (notes: string) => {
|
||||||
|
const payload: CreateManagerApprovalRequestPayload = {
|
||||||
|
action: 'REJECTED',
|
||||||
|
notes: notes || null,
|
||||||
|
};
|
||||||
|
|
||||||
|
await createManagerApprovalHandler(payload);
|
||||||
|
await refetchData?.();
|
||||||
|
setApprovalNotes('');
|
||||||
|
managerRejectionModal.closeModal();
|
||||||
|
};
|
||||||
|
|
||||||
if (!initialValues) {
|
if (!initialValues) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -969,20 +1026,14 @@ const PurchaseOrderDetail = ({
|
|||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: 'Ya, Lanjutkan',
|
text: 'Ya, Lanjutkan',
|
||||||
color: 'success',
|
color: 'success',
|
||||||
onClick: async (notes) => {
|
onClick: managerApprovalHandler,
|
||||||
const payload: CreateManagerApprovalRequestPayload = {
|
|
||||||
action: 'APPROVED',
|
|
||||||
notes: notes || null,
|
|
||||||
};
|
|
||||||
|
|
||||||
await createManagerApprovalHandler(payload);
|
|
||||||
await refreshApprovals();
|
|
||||||
await refetchData?.();
|
|
||||||
confirmationModalWithNotes.closeModal();
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
secondaryButton={{
|
secondaryButton={{
|
||||||
text: 'Batal',
|
text: 'Batal',
|
||||||
|
onClick: () => {
|
||||||
|
setApprovalNotes('');
|
||||||
|
confirmationModalWithNotes.closeModal();
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -1071,19 +1122,14 @@ const PurchaseOrderDetail = ({
|
|||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: 'Ya, Tolak',
|
text: 'Ya, Tolak',
|
||||||
color: 'error',
|
color: 'error',
|
||||||
onClick: async (notes) => {
|
onClick: staffRejectionHandler,
|
||||||
const payload: CreateStaffApprovalRequestPayload = {
|
|
||||||
action: 'REJECTED',
|
|
||||||
notes: notes || null,
|
|
||||||
};
|
|
||||||
|
|
||||||
await createStaffApprovalHandler(payload);
|
|
||||||
await refetchData?.();
|
|
||||||
staffRejectionModal.closeModal();
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
secondaryButton={{
|
secondaryButton={{
|
||||||
text: 'Batal',
|
text: 'Batal',
|
||||||
|
onClick: () => {
|
||||||
|
setApprovalNotes('');
|
||||||
|
staffRejectionModal.closeModal();
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -1098,19 +1144,14 @@ const PurchaseOrderDetail = ({
|
|||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: 'Ya, Tolak',
|
text: 'Ya, Tolak',
|
||||||
color: 'error',
|
color: 'error',
|
||||||
onClick: async (notes) => {
|
onClick: acceptRejectionHandler,
|
||||||
const payload: CreateAcceptApprovalRequestPayload = {
|
|
||||||
action: 'REJECTED',
|
|
||||||
notes: notes || null,
|
|
||||||
};
|
|
||||||
|
|
||||||
await createAcceptApprovalHandler(payload);
|
|
||||||
await refetchData?.();
|
|
||||||
acceptRejectionModal.closeModal();
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
secondaryButton={{
|
secondaryButton={{
|
||||||
text: 'Batal',
|
text: 'Batal',
|
||||||
|
onClick: () => {
|
||||||
|
setApprovalNotes('');
|
||||||
|
acceptRejectionModal.closeModal();
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -1125,19 +1166,14 @@ const PurchaseOrderDetail = ({
|
|||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: 'Ya, Tolak',
|
text: 'Ya, Tolak',
|
||||||
color: 'error',
|
color: 'error',
|
||||||
onClick: async (notes) => {
|
onClick: managerRejectionHandler,
|
||||||
const payload: CreateManagerApprovalRequestPayload = {
|
|
||||||
action: 'REJECTED',
|
|
||||||
notes: notes || null,
|
|
||||||
};
|
|
||||||
|
|
||||||
await createManagerApprovalHandler(payload);
|
|
||||||
await refetchData?.();
|
|
||||||
managerRejectionModal.closeModal();
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
secondaryButton={{
|
secondaryButton={{
|
||||||
text: 'Batal',
|
text: 'Batal',
|
||||||
|
onClick: () => {
|
||||||
|
setApprovalNotes('');
|
||||||
|
managerRejectionModal.closeModal();
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user