From 325f3f1bd824b6fd111a83392ae4419c66263b2a Mon Sep 17 00:00:00 2001 From: rstubryan Date: Thu, 8 Jan 2026 12:35:16 +0700 Subject: [PATCH] refactor(FE): Display form error list in purchase forms --- .../order/PurchaseOrderAcceptApprovalForm.tsx | 30 ++++++++++++++++- .../order/PurchaseOrderStaffApprovalForm.tsx | 33 ++++++++++++++++--- .../form/request/PurchaseRequestForm.tsx | 30 ++++++++++++++++- 3 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx b/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx index 5c093895..2b18afee 100644 --- a/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx +++ b/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx @@ -14,6 +14,7 @@ import SelectInput, { useSelect, } from '@/components/input/SelectInput'; import { useRouter } from 'next/navigation'; +import AlertErrorList from '@/components/helper/form/FormErrors'; import { PurchaseRequestAcceptApprovalFormDefaultValues, @@ -28,6 +29,7 @@ import { } from '@/types/api/purchase/purchase'; import DateInput from '@/components/input/DateInput'; import { formatNumber } from '@/lib/helper'; +import { getUniqueFormikErrors } from '@/lib/formik-helper'; import { Supplier } from '@/types/api/master-data/supplier'; import { SupplierApi } from '@/services/api/master-data'; @@ -52,6 +54,7 @@ const PurchaseOrderAcceptApprovalForm = ({ const searchParams = useSearchParams(); const [purchaseOrderFormErrorMessage, setPurchaseOrderFormErrorMessage] = useState(''); + const [formErrorList, setFormErrorList] = useState([]); const [key, setKey] = useState(0); const fileInputRef = useRef(null); @@ -209,6 +212,22 @@ const PurchaseOrderAcceptApprovalForm = ({ }, }); + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(e); + }; + // ===== API DATA FETCHING ===== const purchaseItems = useMemo(() => { if (initialValues?.items) { @@ -336,7 +355,7 @@ const PurchaseOrderAcceptApprovalForm = ({ return (
@@ -355,6 +374,15 @@ const PurchaseOrderAcceptApprovalForm = ({ {purchaseOrderFormErrorMessage}
)} + + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} +
diff --git a/src/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm.tsx b/src/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm.tsx index 95ca2f50..729b6782 100644 --- a/src/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm.tsx +++ b/src/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm.tsx @@ -12,10 +12,12 @@ import NumberInput from '@/components/input/NumberInput'; import SelectInput, { OptionType } from '@/components/input/SelectInput'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import { useModal } from '@/components/Modal'; +import AlertErrorList from '@/components/helper/form/FormErrors'; import { SupplierApi } from '@/services/api/master-data'; import { SupplierProducts } from '@/types/api/master-data/supplier'; import { isResponseSuccess } from '@/lib/api-helper'; +import { getUniqueFormikErrors } from '@/lib/formik-helper'; import { PurchaseRequestStaffApprovalFormDefaultValues, PurchaseRequestStaffApprovalFormInitialValues, @@ -87,6 +89,7 @@ const PurchaseOrderStaffApprovalForm = ({ const deleteModal = useModal(); const [purchaseOrderFormErrorMessage, setPurchaseOrderFormErrorMessage] = useState(''); + const [formErrorList, setFormErrorList] = useState([]); const [selectedItemForDelete, setSelectedItemForDelete] = useState< number | null >(null); @@ -415,6 +418,22 @@ const PurchaseOrderStaffApprovalForm = ({ }, }); + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(e); + }; + const supplierProductOptions = baseSupplierProductOptions; // ===== API DATA FETCHING ===== @@ -652,10 +671,7 @@ const PurchaseOrderStaffApprovalForm = ({ return ( <> - +

{type === 'add' @@ -672,6 +688,15 @@ const PurchaseOrderStaffApprovalForm = ({ {purchaseOrderFormErrorMessage}

)} + + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} +
{groupedPurchaseItems.length > 0 ? (
diff --git a/src/components/pages/purchase/form/request/PurchaseRequestForm.tsx b/src/components/pages/purchase/form/request/PurchaseRequestForm.tsx index ef428b25..0c319f5a 100644 --- a/src/components/pages/purchase/form/request/PurchaseRequestForm.tsx +++ b/src/components/pages/purchase/form/request/PurchaseRequestForm.tsx @@ -16,6 +16,7 @@ import SelectInput, { } from '@/components/input/SelectInput'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import { useModal } from '@/components/Modal'; +import AlertErrorList from '@/components/helper/form/FormErrors'; import { PurchaseRequestFormSchema, @@ -32,6 +33,7 @@ import { import { Supplier, SupplierProducts } from '@/types/api/master-data/supplier'; import { isResponseSuccess, isResponseError } from '@/lib/api-helper'; import { formatNumber } from '@/lib/helper'; +import { getUniqueFormikErrors } from '@/lib/formik-helper'; import { PurchaseApi } from '@/services/api/purchase'; import Card from '@/components/Card'; @@ -59,6 +61,7 @@ const PurchaseRequestForm = ({ ); const [purchaseRequestFormErrorMessage, setPurchaseRequestFormErrorMessage] = useState(''); + const [formErrorList, setFormErrorList] = useState([]); // ===== TYPE DEFINITIONS ===== interface ProductOptionType { @@ -211,6 +214,22 @@ const PurchaseRequestForm = ({ }, }); + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(e); + }; + // ===== API DATA FETCHING ===== const { data: supplierData, isLoading: isLoadingProducts } = useSWR( formik.values.supplier_id && Number(formik.values.supplier_id) > 0 @@ -487,7 +506,7 @@ const PurchaseRequestForm = ({ @@ -501,6 +520,15 @@ const PurchaseRequestForm = ({ {purchaseRequestFormErrorMessage}
)} + + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} + {/* Basic Info Card */}