diff --git a/src/components/pages/expense/form/ExpenseRequestForm.schema.ts b/src/components/pages/expense/form/ExpenseRequestForm.schema.ts index cd34e5a3..227a2ea9 100644 --- a/src/components/pages/expense/form/ExpenseRequestForm.schema.ts +++ b/src/components/pages/expense/form/ExpenseRequestForm.schema.ts @@ -41,11 +41,16 @@ type ExpenseFormSchemaType = { export const ExpenseRequestFormSchema: Yup.ObjectSchema = Yup.object({ category: Yup.object({ - value: Yup.string().oneOf(['BOP', 'NON-BOP']).required(), - label: Yup.string().oneOf(['BOP', 'NON-BOP']).required(), + value: Yup.string() + .oneOf(['BOP', 'NON-BOP']) + .required('Kategori wajib diisi!'), + label: Yup.string() + .oneOf(['BOP', 'NON-BOP']) + .required('Kategori wajib diisi!'), }) .nullable() - .optional(), + .required('Kategori wajib diisi!') + .typeError('Kategori wajib diisi!'), location: Yup.object({ value: Yup.number().min(1).required(), @@ -104,9 +109,12 @@ export const ExpenseRequestFormSchema: Yup.ObjectSchema = .of( Yup.object({ nonstock: Yup.object({ - value: Yup.number().min(1).required(), - label: Yup.string().required(), - }).nullable(), + value: Yup.number().min(1).required('Nonstock wajib diisi!'), + label: Yup.string().required('Nonstock wajib diisi!'), + }) + .nullable() + .required('Nonstock wajib diisi!') + .typeError('Nonstock wajib diisi!'), nonstock_id: Yup.number() .required('Nonstock wajib diisi!') .min(1, 'Nonstock wajib diisi!') diff --git a/src/components/pages/expense/form/ExpenseRequestForm.tsx b/src/components/pages/expense/form/ExpenseRequestForm.tsx index 03238b83..63cdb2b7 100644 --- a/src/components/pages/expense/form/ExpenseRequestForm.tsx +++ b/src/components/pages/expense/form/ExpenseRequestForm.tsx @@ -192,6 +192,7 @@ const ExpenseRequestForm = ({ const locationChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('location', true); + formik.setFieldTouched('location_id', true); formik.setFieldValue('location', val); const locationId = Array.isArray(val) ? val[0]?.value : val?.value; @@ -268,6 +269,7 @@ const ExpenseRequestForm = ({ const supplierChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('supplier', true); + formik.setFieldTouched('supplier_id', true); formik.setFieldValue('supplier', val); const supplierId = Array.isArray(val) ? val[0]?.value : val?.value; @@ -407,6 +409,16 @@ const ExpenseRequestForm = ({ placeholder='Pilih Kategori' value={formik.values.category} onChange={categoryChangeHandler} + isError={ + formik.touched.category && Boolean(formik.errors.category) + } + errorMessage={ + formik.touched.category && formik.errors.category + ? typeof formik.errors.category === 'object' + ? 'Kategori wajib diisi!' + : (formik.errors.category as string) + : undefined + } options={[ { value: 'BOP', @@ -426,6 +438,10 @@ const ExpenseRequestForm = ({ placeholder='Pilih Lokasi' value={formik.values.location} onChange={locationChangeHandler} + isError={ + formik.touched.location_id && Boolean(formik.errors.location_id) + } + errorMessage={formik.errors.location_id as string} options={locationOptions} isLoading={isLoadingLocationOptions} onInputChange={setLocationInputValue} @@ -438,6 +454,12 @@ const ExpenseRequestForm = ({ required value={formik.values.transaction_date} onChange={formik.handleChange} + onBlur={formik.handleBlur} + isError={ + formik.touched.transaction_date && + Boolean(formik.errors.transaction_date) + } + errorMessage={formik.errors.transaction_date as string} className={{ wrapper: 'col-span-12 sm:col-span-4', }} @@ -459,6 +481,16 @@ const ExpenseRequestForm = ({ placeholder='Pilih Vendor' value={formik.values.supplier} onChange={supplierChangeHandler} + isError={ + formik.touched.supplier_id && Boolean(formik.errors.supplier_id) + } + errorMessage={ + formik.touched.supplier_id && formik.errors.supplier_id + ? typeof formik.errors.supplier_id === 'object' + ? 'Vendor wajib diisi!' + : (formik.errors.supplier_id as string) + : undefined + } options={supplierOptions} isLoading={isLoadingVendorOptions} onInputChange={setVendorInputValue} diff --git a/src/components/pages/expense/form/ExpenseRequestKandangDetailExpense.tsx b/src/components/pages/expense/form/ExpenseRequestKandangDetailExpense.tsx index 41eb40f8..3ccc8768 100644 --- a/src/components/pages/expense/form/ExpenseRequestKandangDetailExpense.tsx +++ b/src/components/pages/expense/form/ExpenseRequestKandangDetailExpense.tsx @@ -55,6 +55,10 @@ const ExpenseRequestKandangDetailExpense: React.FC< `expense_nonstocks[${kandangExpenseIdx}].cost_items[${expenseIdx}].nonstock`, true ); + formik.setFieldTouched( + `expense_nonstocks[${kandangExpenseIdx}].cost_items[${expenseIdx}].nonstock_id`, + true + ); formik.setFieldValue( `expense_nonstocks[${kandangExpenseIdx}].cost_items[${expenseIdx}].nonstock`, val @@ -105,11 +109,14 @@ const ExpenseRequestKandangDetailExpense: React.FC< expenseIdx ]?.[column] && Boolean( - formik.errors.expense_nonstocks?.[kandangExpenseIdx] instanceof - Object && + formik.errors.expense_nonstocks?.[kandangExpenseIdx] && + typeof formik.errors.expense_nonstocks?.[kandangExpenseIdx] === + 'object' && formik.errors.expense_nonstocks?.[kandangExpenseIdx].cost_items?.[ expenseIdx - ] instanceof Object && + ] && + typeof formik.errors.expense_nonstocks?.[kandangExpenseIdx] + .cost_items?.[expenseIdx] === 'object' && formik.errors.expense_nonstocks?.[kandangExpenseIdx].cost_items?.[ expenseIdx ]?.[column] @@ -117,6 +124,32 @@ const ExpenseRequestKandangDetailExpense: React.FC< ); }; + const getExpenseRepeaterErrorMessage = ( + column: 'nonstock' | 'quantity' | 'price' | 'notes', + kandangExpenseIdx: number, + expenseIdx: number + ): string => { + const kandangError = formik.errors.expense_nonstocks?.[kandangExpenseIdx]; + + if (!kandangError || typeof kandangError !== 'object') return ''; + + if (!('cost_items' in kandangError)) return ''; + + const costItemsError = kandangError.cost_items?.[expenseIdx]; + + if (!costItemsError || typeof costItemsError !== 'object') return ''; + + const fieldError = costItemsError[column as keyof typeof costItemsError]; + + if (!fieldError) return ''; + + if (typeof fieldError === 'object' && fieldError !== null) { + return 'Nonstock wajib diisi!'; + } + + return String(fieldError); + }; + return ( @@ -246,6 +294,11 @@ const ExpenseRequestKandangDetailExpense: React.FC< kandangExpenseIdx, expenseIdx )} + errorMessage={getExpenseRepeaterErrorMessage( + 'price', + kandangExpenseIdx, + expenseIdx + )} inputPrefix={ Rp @@ -271,6 +324,11 @@ const ExpenseRequestKandangDetailExpense: React.FC< kandangExpenseIdx, expenseIdx )} + errorMessage={getExpenseRepeaterErrorMessage( + 'notes', + kandangExpenseIdx, + expenseIdx + )} className={{ wrapper: 'min-w-24' }} />