refactor(FE): Display form error list in purchase forms

This commit is contained in:
rstubryan
2026-01-08 12:35:16 +07:00
parent 346c731c42
commit 325f3f1bd8
3 changed files with 87 additions and 6 deletions
@@ -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<string[]>([]);
const [key, setKey] = useState(0);
const fileInputRef = useRef<HTMLInputElement>(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<HTMLFormElement>) => {
e.preventDefault();
handleValidateForm();
formik.handleSubmit(e);
};
// ===== API DATA FETCHING =====
const purchaseItems = useMemo(() => {
if (initialValues?.items) {
@@ -336,7 +355,7 @@ const PurchaseOrderAcceptApprovalForm = ({
return (
<form
key={key}
onSubmit={formik.handleSubmit}
onSubmit={handleFormSubmit}
className='w-full flex flex-col gap-6'
>
<div className='w-full'>
@@ -355,6 +374,15 @@ const PurchaseOrderAcceptApprovalForm = ({
<span>{purchaseOrderFormErrorMessage}</span>
</div>
)}
{/* Error List Alert */}
{formErrorList.length > 0 && (
<AlertErrorList
formErrorList={formErrorList}
onClose={() => setFormErrorList([])}
/>
)}
<div className='overflow-x-auto'>
<table className='table'>
<thead>
@@ -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<string[]>([]);
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<HTMLFormElement>) => {
e.preventDefault();
handleValidateForm();
formik.handleSubmit(e);
};
const supplierProductOptions = baseSupplierProductOptions;
// ===== API DATA FETCHING =====
@@ -652,10 +671,7 @@ const PurchaseOrderStaffApprovalForm = ({
return (
<>
<form
onSubmit={formik.handleSubmit}
className='w-full flex flex-col gap-6'
>
<form onSubmit={handleFormSubmit} className='w-full flex flex-col gap-6'>
<div className='w-full'>
<h2 className='text-lg font-semibold mb-4'>
{type === 'add'
@@ -672,6 +688,15 @@ const PurchaseOrderStaffApprovalForm = ({
<span>{purchaseOrderFormErrorMessage}</span>
</div>
)}
{/* Error List Alert */}
{formErrorList.length > 0 && (
<AlertErrorList
formErrorList={formErrorList}
onClose={() => setFormErrorList([])}
/>
)}
<div className='overflow-x-auto'>
{groupedPurchaseItems.length > 0 ? (
<div>
@@ -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<string[]>([]);
// ===== 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<HTMLFormElement>) => {
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 = ({
</h1>
</header>
<form
onSubmit={formik.handleSubmit}
onSubmit={handleFormSubmit}
onReset={formik.handleReset}
className='w-full mt-8 flex flex-col gap-6'
>
@@ -501,6 +520,15 @@ const PurchaseRequestForm = ({
<span>{purchaseRequestFormErrorMessage}</span>
</div>
)}
{/* Error List Alert */}
{formErrorList.length > 0 && (
<AlertErrorList
formErrorList={formErrorList}
onClose={() => setFormErrorList([])}
/>
)}
{/* Basic Info Card */}
<Card
title='Informasi Purchase Request'