mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
Merge branch 'dev/randy' into 'fix/submit-form'
[FIX/FE] Create Custom Hooks for Formik Error List See merge request mbugroup/lti-web-client!158
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import Alert from '@/components/Alert';
|
import Alert from '@/components/Alert';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alert Unique Error List
|
* Alert Unique Error List
|
||||||
@@ -14,8 +15,10 @@ const AlertErrorList = ({
|
|||||||
formErrorList: string[];
|
formErrorList: string[];
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
|
if (formErrorList.length === 0) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Alert color='error' className='flex flex-col gap-2 px-4 m-4'>
|
<Alert color='error' className='w-full flex flex-col gap-2 px-4 m-4'>
|
||||||
<div className='flex justify-between items-center gap-2 w-full'>
|
<div className='flex justify-between items-center gap-2 w-full'>
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
<Icon icon='material-symbols:error-outline' width={24} height={24} />
|
<Icon icon='material-symbols:error-outline' width={24} height={24} />
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import HppExpeditionReportTable from './hpp-ekspedisi/HppExpeditionReportTable';
|
|||||||
import ClosingKandangList from '@/components/pages/closing/ClosingKandangList';
|
import ClosingKandangList from '@/components/pages/closing/ClosingKandangList';
|
||||||
import { ProjectFlock } from '@/types/api/production/project-flock';
|
import { ProjectFlock } from '@/types/api/production/project-flock';
|
||||||
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
|
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
|
||||||
|
|
||||||
interface ClosingDetailProps {
|
interface ClosingDetailProps {
|
||||||
id: number;
|
id: number;
|
||||||
initialValue?: ClosingGeneralInformation;
|
initialValue?: ClosingGeneralInformation;
|
||||||
@@ -56,7 +55,6 @@ const ClosingDetail: React.FC<ClosingDetailProps> = ({
|
|||||||
<ClosingSapronakCalculationTabContent
|
<ClosingSapronakCalculationTabContent
|
||||||
closingGeneralInformation={initialValue}
|
closingGeneralInformation={initialValue}
|
||||||
projectFlockId={id}
|
projectFlockId={id}
|
||||||
projectKandangId={kandangData?.id}
|
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,13 +5,11 @@ import { ClosingGeneralInformation } from '@/types/api/closing';
|
|||||||
|
|
||||||
interface ClosingSapronakCalculationTabContentProps {
|
interface ClosingSapronakCalculationTabContentProps {
|
||||||
projectFlockId?: number;
|
projectFlockId?: number;
|
||||||
projectKandangId?: number;
|
|
||||||
closingGeneralInformation?: ClosingGeneralInformation;
|
closingGeneralInformation?: ClosingGeneralInformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ClosingSapronakCalculationTabContent = ({
|
const ClosingSapronakCalculationTabContent = ({
|
||||||
projectFlockId,
|
projectFlockId,
|
||||||
projectKandangId,
|
|
||||||
closingGeneralInformation,
|
closingGeneralInformation,
|
||||||
}: ClosingSapronakCalculationTabContentProps) => {
|
}: ClosingSapronakCalculationTabContentProps) => {
|
||||||
return (
|
return (
|
||||||
@@ -21,7 +19,6 @@ const ClosingSapronakCalculationTabContent = ({
|
|||||||
<ClosingSapronakCalculationTable
|
<ClosingSapronakCalculationTable
|
||||||
closingGeneralInformation={closingGeneralInformation}
|
closingGeneralInformation={closingGeneralInformation}
|
||||||
projectFlockId={projectFlockId}
|
projectFlockId={projectFlockId}
|
||||||
projectKandangId={projectKandangId}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -14,21 +14,23 @@ import useSWR from 'swr';
|
|||||||
import { ClosingApi } from '@/services/api/closing';
|
import { ClosingApi } from '@/services/api/closing';
|
||||||
import { isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { ClosingGeneralInformation } from '@/types/api/closing';
|
import { ClosingGeneralInformation } from '@/types/api/closing';
|
||||||
|
import { useSearchParams } from 'next/navigation';
|
||||||
|
|
||||||
interface ClosingSapronakCalculationTableProps {
|
interface ClosingSapronakCalculationTableProps {
|
||||||
projectFlockId: number;
|
projectFlockId: number;
|
||||||
projectKandangId?: number;
|
|
||||||
closingGeneralInformation?: ClosingGeneralInformation;
|
closingGeneralInformation?: ClosingGeneralInformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ClosingSapronakCalculationTable = ({
|
const ClosingSapronakCalculationTable = ({
|
||||||
projectFlockId,
|
projectFlockId,
|
||||||
closingGeneralInformation,
|
closingGeneralInformation,
|
||||||
projectKandangId,
|
|
||||||
}: ClosingSapronakCalculationTableProps) => {
|
}: ClosingSapronakCalculationTableProps) => {
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const kandangId = searchParams.get('kandangId');
|
||||||
|
|
||||||
const { data: sapronakCalculation, isLoading } = useSWR(
|
const { data: sapronakCalculation, isLoading } = useSWR(
|
||||||
`/closing/sapronak-calculation/${projectFlockId}${projectKandangId ? `/${projectKandangId}` : ''}`,
|
`/closing/sapronak-calculation/${projectFlockId}${kandangId ? `/${kandangId}` : ''}`,
|
||||||
() => ClosingApi.getPerhitunganSapronak(projectFlockId, projectKandangId),
|
() => ClosingApi.getPerhitunganSapronak(projectFlockId, Number(kandangId)),
|
||||||
{
|
{
|
||||||
keepPreviousData: true,
|
keepPreviousData: true,
|
||||||
}
|
}
|
||||||
@@ -180,7 +182,7 @@ const ClosingSapronakCalculationTable = ({
|
|||||||
{/* Table DOC jika kategori Project Flock Growing */}
|
{/* Table DOC jika kategori Project Flock Growing */}
|
||||||
<Card
|
<Card
|
||||||
title={
|
title={
|
||||||
closingGeneralInformation?.project_category === 'GROWING'
|
closingGeneralInformation?.project_type == 'GROWING'
|
||||||
? 'DOC'
|
? 'DOC'
|
||||||
: 'Pullet'
|
: 'Pullet'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,8 @@ import { DashboardApi } from '@/services/api/dashboard';
|
|||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { ProjectFlockApi } from '@/services/api/production';
|
import { ProjectFlockApi } from '@/services/api/production';
|
||||||
import { KandangApi, LocationApi } from '@/services/api/master-data';
|
import { KandangApi, LocationApi } from '@/services/api/master-data';
|
||||||
import Alert from '@/components/Alert';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DashboardFilterSchema,
|
|
||||||
DashboardFilterType,
|
DashboardFilterType,
|
||||||
getDashboardFilterSchema,
|
getDashboardFilterSchema,
|
||||||
} from '@/components/pages/dashboard/filter/DashboardProductionFilter.schema';
|
} from '@/components/pages/dashboard/filter/DashboardProductionFilter.schema';
|
||||||
@@ -31,7 +29,7 @@ import {
|
|||||||
import DashboardStats from '@/components/pages/dashboard/chart/DashboardStats';
|
import DashboardStats from '@/components/pages/dashboard/chart/DashboardStats';
|
||||||
import { isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
import AlertErrorList from '@/components/helper/form/FormErrors';
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
import { getUniqueFormikErrors } from '@/lib/formik-helper';
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
// Helper function to normalize values to array
|
// Helper function to normalize values to array
|
||||||
const normalizeToArray = (
|
const normalizeToArray = (
|
||||||
@@ -51,7 +49,6 @@ const DashboardProduction = () => {
|
|||||||
);
|
);
|
||||||
const [endpointUrl, setEndpointUrl] = useState('/dashboards');
|
const [endpointUrl, setEndpointUrl] = useState('/dashboards');
|
||||||
const [selectedLocationIds, setSelectedLocationIds] = useState<number[]>([]);
|
const [selectedLocationIds, setSelectedLocationIds] = useState<number[]>([]);
|
||||||
const [formErrorList, setFormErrorList] = useState<string[]>([]);
|
|
||||||
|
|
||||||
// ===== FETCH DATA =====
|
// ===== FETCH DATA =====
|
||||||
const {
|
const {
|
||||||
@@ -149,22 +146,8 @@ const DashboardProduction = () => {
|
|||||||
formik.resetForm();
|
formik.resetForm();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleValidateForm = async () => {
|
// ===== Formik Error List =====
|
||||||
const errors = await formik.validateForm();
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
if (Object.keys(errors).length > 0) {
|
|
||||||
// Parse and display errors
|
|
||||||
const errorMessages = getUniqueFormikErrors(errors);
|
|
||||||
setFormErrorList(errorMessages);
|
|
||||||
return; // Stop submission
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
|
||||||
e.preventDefault();
|
|
||||||
handleValidateForm();
|
|
||||||
formik.handleSubmit();
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isLoadingDashboardProductionData) {
|
if (isLoadingDashboardProductionData) {
|
||||||
return (
|
return (
|
||||||
@@ -482,13 +465,7 @@ const DashboardProduction = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Error List Alert */}
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
{formErrorList.length > 0 && (
|
|
||||||
<AlertErrorList
|
|
||||||
formErrorList={formErrorList}
|
|
||||||
onClose={() => setFormErrorList([])}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Action Buttons */}
|
{/* Action Buttons */}
|
||||||
<div className='flex justify-between gap-4 py-4 mt-8 border-t border-gray-300 bg-gray-100'>
|
<div className='flex justify-between gap-4 py-4 mt-8 border-t border-gray-300 bg-gray-100'>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import Card from '@/components/Card';
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
import { FormHeader } from '@/components/helper/form/FormHeader';
|
import { FormHeader } from '@/components/helper/form/FormHeader';
|
||||||
import DateInput from '@/components/input/DateInput';
|
import DateInput from '@/components/input/DateInput';
|
||||||
import NumberInput from '@/components/input/NumberInput';
|
import NumberInput from '@/components/input/NumberInput';
|
||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
} from '@/config/constant';
|
} from '@/config/constant';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { formatDate, formatTitleCase } from '@/lib/helper';
|
import { formatDate, formatTitleCase } from '@/lib/helper';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
import { FinanceApi } from '@/services/api/finance';
|
import { FinanceApi } from '@/services/api/finance';
|
||||||
import { BankApi, CustomerApi, SupplierApi } from '@/services/api/master-data';
|
import { BankApi, CustomerApi, SupplierApi } from '@/services/api/master-data';
|
||||||
import {
|
import {
|
||||||
@@ -104,6 +105,9 @@ const FormFinanceAdd = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
// ===== Options =====
|
// ===== Options =====
|
||||||
const {
|
const {
|
||||||
options: partyOptions,
|
options: partyOptions,
|
||||||
@@ -180,7 +184,7 @@ const FormFinanceAdd = ({
|
|||||||
title={`${type === 'add' ? 'Tambah' : 'Ubah'} Data Keuangan`}
|
title={`${type === 'add' ? 'Tambah' : 'Ubah'} Data Keuangan`}
|
||||||
backUrl='/finance'
|
backUrl='/finance'
|
||||||
/>
|
/>
|
||||||
<form className='flex flex-col gap-4' onSubmit={formik.handleSubmit}>
|
<form className='flex flex-col gap-4' onSubmit={handleFormSubmit}>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
label='Jenis Transaksi'
|
label='Jenis Transaksi'
|
||||||
placeholder='Pilih jenis transaksi'
|
placeholder='Pilih jenis transaksi'
|
||||||
@@ -384,6 +388,7 @@ const FormFinanceAdd = ({
|
|||||||
}
|
}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
<div className='flex justify-center gap-4'>
|
<div className='flex justify-center gap-4'>
|
||||||
<Button
|
<Button
|
||||||
type='reset'
|
type='reset'
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
import { FormHeader } from '@/components/helper/form/FormHeader';
|
import { FormHeader } from '@/components/helper/form/FormHeader';
|
||||||
import NumberInput from '@/components/input/NumberInput';
|
import NumberInput from '@/components/input/NumberInput';
|
||||||
import SelectInput, {
|
import SelectInput, { useSelect } from '@/components/input/SelectInput';
|
||||||
OptionType,
|
|
||||||
useSelect,
|
|
||||||
} from '@/components/input/SelectInput';
|
|
||||||
import TextArea from '@/components/input/TextArea';
|
import TextArea from '@/components/input/TextArea';
|
||||||
import TextInput from '@/components/input/TextInput';
|
import TextInput from '@/components/input/TextInput';
|
||||||
import {
|
import {
|
||||||
@@ -17,6 +15,7 @@ import {
|
|||||||
FINANCE_INITIAL_BALANCE_TYPE_OPTIONS,
|
FINANCE_INITIAL_BALANCE_TYPE_OPTIONS,
|
||||||
FINANCE_PARTY_TYPE_OPTIONS,
|
FINANCE_PARTY_TYPE_OPTIONS,
|
||||||
} from '@/config/constant';
|
} from '@/config/constant';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { formatTitleCase } from '@/lib/helper';
|
import { formatTitleCase } from '@/lib/helper';
|
||||||
import { FinanceApi } from '@/services/api/finance';
|
import { FinanceApi } from '@/services/api/finance';
|
||||||
@@ -173,6 +172,9 @@ const FormFinanceAddInitialBalance = ({
|
|||||||
[router]
|
[router]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className='w-full max-w-xl mx-auto'>
|
<section className='w-full max-w-xl mx-auto'>
|
||||||
@@ -181,7 +183,7 @@ const FormFinanceAddInitialBalance = ({
|
|||||||
title={`${type === 'add' ? 'Tambah' : 'Ubah'} Saldo Awal`}
|
title={`${type === 'add' ? 'Tambah' : 'Ubah'} Saldo Awal`}
|
||||||
backUrl='/finance'
|
backUrl='/finance'
|
||||||
/>
|
/>
|
||||||
<form className='flex flex-col gap-4' onSubmit={formik.handleSubmit}>
|
<form className='flex flex-col gap-4' onSubmit={handleFormSubmit}>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
label='Jenis Pihak'
|
label='Jenis Pihak'
|
||||||
placeholder='Pilih jenis pihak'
|
placeholder='Pilih jenis pihak'
|
||||||
@@ -352,6 +354,7 @@ const FormFinanceAddInitialBalance = ({
|
|||||||
}
|
}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
<div className='flex justify-center gap-4'>
|
<div className='flex justify-center gap-4'>
|
||||||
<Button
|
<Button
|
||||||
type='reset'
|
type='reset'
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
import { FormHeader } from '@/components/helper/form/FormHeader';
|
import { FormHeader } from '@/components/helper/form/FormHeader';
|
||||||
import DateInput from '@/components/input/DateInput';
|
import DateInput from '@/components/input/DateInput';
|
||||||
import NumberInput from '@/components/input/NumberInput';
|
import NumberInput from '@/components/input/NumberInput';
|
||||||
import SelectInput, {
|
import SelectInput, { useSelect } from '@/components/input/SelectInput';
|
||||||
OptionType,
|
|
||||||
useSelect,
|
|
||||||
} from '@/components/input/SelectInput';
|
|
||||||
import TextArea from '@/components/input/TextArea';
|
import TextArea from '@/components/input/TextArea';
|
||||||
import {
|
import {
|
||||||
InjectionFormSchema,
|
InjectionFormSchema,
|
||||||
InjectionFormValues,
|
InjectionFormValues,
|
||||||
} from '@/components/pages/finance/add/injection/FormFinanceInjection.schema';
|
} from '@/components/pages/finance/add/injection/FormFinanceInjection.schema';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { formatDate } from '@/lib/helper';
|
import { formatDate } from '@/lib/helper';
|
||||||
import { FinanceApi } from '@/services/api/finance';
|
import { FinanceApi } from '@/services/api/finance';
|
||||||
@@ -128,6 +127,9 @@ const FormFinanceInjection = ({
|
|||||||
[router]
|
[router]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className='w-full max-w-xl mx-auto'>
|
<section className='w-full max-w-xl mx-auto'>
|
||||||
@@ -136,7 +138,7 @@ const FormFinanceInjection = ({
|
|||||||
title={`${type === 'add' ? 'Tambah' : 'Ubah'} Injeksi Dana`}
|
title={`${type === 'add' ? 'Tambah' : 'Ubah'} Injeksi Dana`}
|
||||||
backUrl='/finance'
|
backUrl='/finance'
|
||||||
/>
|
/>
|
||||||
<form className='flex flex-col gap-4' onSubmit={formik.handleSubmit}>
|
<form className='flex flex-col gap-4' onSubmit={handleFormSubmit}>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
label='Bank'
|
label='Bank'
|
||||||
placeholder='Pilih bank'
|
placeholder='Pilih bank'
|
||||||
@@ -223,6 +225,7 @@ const FormFinanceInjection = ({
|
|||||||
}
|
}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
<div className='flex justify-center gap-4'>
|
<div className='flex justify-center gap-4'>
|
||||||
<Button
|
<Button
|
||||||
type='reset'
|
type='reset'
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { Icon } from '@iconify/react';
|
|||||||
import { ColumnDef, ColumnSort, SortingState } from '@tanstack/react-table';
|
import { ColumnDef, ColumnSort, SortingState } from '@tanstack/react-table';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
const InventoryAdjustmentTable = () => {
|
const InventoryAdjustmentTable = () => {
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -1,26 +1,42 @@
|
|||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
|
import { OptionType } from '@/components/input/SelectInput';
|
||||||
|
|
||||||
export const InventoryAdjustmentFormSchema = Yup.object({
|
export const InventoryAdjustmentFormSchema = Yup.object({
|
||||||
product_category: Yup.object({
|
product_category: Yup.mixed<OptionType>()
|
||||||
value: Yup.number().required('ID Kategori Produk wajib diisi!'),
|
.nullable()
|
||||||
label: Yup.string().required('Nama Kategori Produk wajib diisi!'),
|
.test(
|
||||||
}).nullable(),
|
'is-valid-option',
|
||||||
|
'Kategori Produk wajib diisi!',
|
||||||
|
(value) => value !== null && value !== undefined
|
||||||
|
),
|
||||||
|
|
||||||
product_category_id: Yup.number().nullable(),
|
product_category_id: Yup.number().nullable(),
|
||||||
|
|
||||||
product: Yup.object({
|
product: Yup.mixed<OptionType>()
|
||||||
value: Yup.number().required('ID Produk wajib diisi!'),
|
.nullable()
|
||||||
label: Yup.string().required('Nama Produk wajib diisi!'),
|
.test(
|
||||||
}).nullable(),
|
'is-valid-option',
|
||||||
|
'Produk wajib diisi!',
|
||||||
|
(value) => value !== null && value !== undefined
|
||||||
|
),
|
||||||
|
|
||||||
product_id: Yup.number().nullable(),
|
product_id: Yup.number()
|
||||||
|
.nullable()
|
||||||
|
.required('Produk wajib diisi!')
|
||||||
|
.min(1, 'Produk wajib diisi!'),
|
||||||
|
|
||||||
warehouse: Yup.object({
|
warehouse: Yup.mixed<OptionType>()
|
||||||
value: Yup.number().required('ID Gudang wajib diisi!'),
|
.nullable()
|
||||||
label: Yup.string().required('Nama Gudang wajib diisi!'),
|
.test(
|
||||||
}).nullable(),
|
'is-valid-option',
|
||||||
|
'Warehouse wajib diisi!',
|
||||||
|
(value) => value !== null && value !== undefined
|
||||||
|
),
|
||||||
|
|
||||||
warehouse_id: Yup.number().nullable(),
|
warehouse_id: Yup.number()
|
||||||
|
.nullable()
|
||||||
|
.required('Warehouse wajib diisi!')
|
||||||
|
.min(1, 'Warehouse wajib diisi!'),
|
||||||
|
|
||||||
transaction_type: Yup.string()
|
transaction_type: Yup.string()
|
||||||
.oneOf(['increase', 'decrease'], 'Tipe transaksi tidak valid')
|
.oneOf(['increase', 'decrease'], 'Tipe transaksi tidak valid')
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import SelectInput, { OptionType } from '@/components/input/SelectInput';
|
|||||||
import TextInput from '@/components/input/TextInput';
|
import TextInput from '@/components/input/TextInput';
|
||||||
import { RadioGroup } from '@/components/input/RadioInput';
|
import { RadioGroup } from '@/components/input/RadioInput';
|
||||||
import TextArea from '@/components/input/TextArea';
|
import TextArea from '@/components/input/TextArea';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
|
||||||
interface InventoryAdjustmentFormProps {
|
interface InventoryAdjustmentFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -245,6 +247,9 @@ const InventoryAdjustmentForm = ({
|
|||||||
return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
|
return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -266,7 +271,7 @@ const InventoryAdjustmentForm = ({
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
className='w-full mt-8 flex flex-col gap-6'
|
className='w-full mt-8 flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
@@ -390,6 +395,7 @@ const InventoryAdjustmentForm = ({
|
|||||||
readOnly={type === 'detail'}
|
readOnly={type === 'detail'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
<div className='flex flex-row justify-between gap-2 flex-wrap'>
|
<div className='flex flex-row justify-between gap-2 flex-wrap'>
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
<div className='flex flex-row justify-end gap-2'>
|
<div className='flex flex-row justify-end gap-2'>
|
||||||
@@ -405,11 +411,7 @@ const InventoryAdjustmentForm = ({
|
|||||||
type='submit'
|
type='submit'
|
||||||
color='primary'
|
color='primary'
|
||||||
isLoading={formik.isSubmitting}
|
isLoading={formik.isSubmitting}
|
||||||
disabled={
|
disabled={formik.isSubmitting}
|
||||||
!formik.isValid ||
|
|
||||||
formik.isSubmitting ||
|
|
||||||
formik.values.product == undefined
|
|
||||||
}
|
|
||||||
className='px-4'
|
className='px-4'
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ import DeliveryOrderProductForm from '@/components/pages/marketing/form/repeater
|
|||||||
import { SalesOrderProductFormValues } from '@/components/pages/marketing/form/repeater/sales-order/SalesOrderProduct.schema';
|
import { SalesOrderProductFormValues } from '@/components/pages/marketing/form/repeater/sales-order/SalesOrderProduct.schema';
|
||||||
import { DeliveryOrderProductFormValues } from '@/components/pages/marketing/form/repeater/delivery-order/DeliverOrderProduct.schema';
|
import { DeliveryOrderProductFormValues } from '@/components/pages/marketing/form/repeater/delivery-order/DeliverOrderProduct.schema';
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
import { getUniqueFormikErrors } from '@/lib/formik-helper';
|
|
||||||
import AlertErrorList from '@/components/helper/form/FormErrors';
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
const MemoizedSalesOrderProductTable = memo(SalesOrderProductTable);
|
const MemoizedSalesOrderProductTable = memo(SalesOrderProductTable);
|
||||||
const MemoizedSalesOrderProductForm = memo(SalesOrderProductForm);
|
const MemoizedSalesOrderProductForm = memo(SalesOrderProductForm);
|
||||||
@@ -219,7 +219,6 @@ const MarketingForm = ({
|
|||||||
const [deliveryFormState, setDeliveryFormState] = useState<'add' | 'edit'>(
|
const [deliveryFormState, setDeliveryFormState] = useState<'add' | 'edit'>(
|
||||||
'add'
|
'add'
|
||||||
);
|
);
|
||||||
const [formErrorList, setFormErrorList] = useState<string[]>([]);
|
|
||||||
const [deliveryOrderValues, setDeliveryOrderValues] = useState<
|
const [deliveryOrderValues, setDeliveryOrderValues] = useState<
|
||||||
DeliveryOrderProductFormValues[]
|
DeliveryOrderProductFormValues[]
|
||||||
>(
|
>(
|
||||||
@@ -561,22 +560,8 @@ const MarketingForm = ({
|
|||||||
);
|
);
|
||||||
}, [memoSalesOrder]);
|
}, [memoSalesOrder]);
|
||||||
|
|
||||||
const handleValidateForm = async () => {
|
// ===== Formik Error List =====
|
||||||
const errors = await formik.validateForm();
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
if (Object.keys(errors).length > 0) {
|
|
||||||
// Parse and display errors
|
|
||||||
const errorMessages = getUniqueFormikErrors(errors);
|
|
||||||
setFormErrorList(errorMessages);
|
|
||||||
return; // Stop submission
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
|
||||||
e.preventDefault();
|
|
||||||
handleValidateForm();
|
|
||||||
formik.handleSubmit();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -686,13 +671,7 @@ const MarketingForm = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Error List Alert */}
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
{formErrorList.length > 0 && (
|
|
||||||
<AlertErrorList
|
|
||||||
formErrorList={formErrorList}
|
|
||||||
onClose={() => setFormErrorList([])}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Form Actions */}
|
{/* Form Actions */}
|
||||||
<div className='flex flex-row items-start justify-center gap-2 mt-4'>
|
<div className='flex flex-row items-start justify-center gap-2 mt-4'>
|
||||||
|
|||||||
+4
-23
@@ -16,8 +16,8 @@ import Badge from '@/components/Badge';
|
|||||||
import { SalesProductToFieldValues } from '@/components/pages/marketing/form/MarketingForm';
|
import { SalesProductToFieldValues } from '@/components/pages/marketing/form/MarketingForm';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import { isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { getUniqueFormikErrors } from '@/lib/formik-helper';
|
|
||||||
import AlertErrorList from '@/components/helper/form/FormErrors';
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
const DeliveryOrderProductForm = ({
|
const DeliveryOrderProductForm = ({
|
||||||
formState,
|
formState,
|
||||||
@@ -42,7 +42,6 @@ const DeliveryOrderProductForm = ({
|
|||||||
null
|
null
|
||||||
);
|
);
|
||||||
const [currentInput, setCurrentInput] = useState<string>('');
|
const [currentInput, setCurrentInput] = useState<string>('');
|
||||||
const [formErrorList, setFormErrorList] = useState<string[]>([]);
|
|
||||||
|
|
||||||
const salesOrder = salesOrders.find(
|
const salesOrder = salesOrders.find(
|
||||||
(item) => item.id === initialValues?.marketing_product_id
|
(item) => item.id === initialValues?.marketing_product_id
|
||||||
@@ -168,21 +167,8 @@ const DeliveryOrderProductForm = ({
|
|||||||
}
|
}
|
||||||
}, [initialValues]);
|
}, [initialValues]);
|
||||||
|
|
||||||
const handleValidateForm = () => {
|
// ===== Formik Error List =====
|
||||||
formik.validateForm();
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
const formErrorList = getUniqueFormikErrors(formik.errors);
|
|
||||||
setFormErrorList(formErrorList);
|
|
||||||
if (formErrorList.length > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
|
||||||
e.preventDefault();
|
|
||||||
handleBlurField(currentInput);
|
|
||||||
handleValidateForm();
|
|
||||||
formik.handleSubmit(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -388,12 +374,7 @@ const DeliveryOrderProductForm = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{formErrorList.length > 0 && (
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
<AlertErrorList
|
|
||||||
formErrorList={formErrorList}
|
|
||||||
onClose={() => setFormErrorList([])}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className='flex flex-row justify-end gap-3 mt-4'>
|
<div className='flex flex-row justify-end gap-3 mt-4'>
|
||||||
<Button type='reset' color='warning'>
|
<Button type='reset' color='warning'>
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ import {
|
|||||||
} from '@/lib/helper';
|
} from '@/lib/helper';
|
||||||
import PatternInput from '@/components/input/PatternInput';
|
import PatternInput from '@/components/input/PatternInput';
|
||||||
import Alert from '@/components/Alert';
|
import Alert from '@/components/Alert';
|
||||||
import { getUniqueFormikErrors } from '@/lib/formik-helper';
|
|
||||||
import AlertErrorList from '@/components/helper/form/FormErrors';
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
const SalesOrderProductForm = ({
|
const SalesOrderProductForm = ({
|
||||||
initialValues,
|
initialValues,
|
||||||
@@ -39,7 +39,6 @@ const SalesOrderProductForm = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const [formErrorMessage, setFormErrorMessage] = useState('');
|
const [formErrorMessage, setFormErrorMessage] = useState('');
|
||||||
const [currentInput, setCurrentInput] = useState<string>('');
|
const [currentInput, setCurrentInput] = useState<string>('');
|
||||||
const [formErrorList, setFormErrorList] = useState<string[]>([]);
|
|
||||||
|
|
||||||
// ============ Formik ============
|
// ============ Formik ============
|
||||||
const formik = useFormik<SalesOrderProductFormValues>({
|
const formik = useFormik<SalesOrderProductFormValues>({
|
||||||
@@ -172,23 +171,8 @@ const SalesOrderProductForm = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleValidateForm = async () => {
|
// ===== Formik Error List =====
|
||||||
const errors = await formik.validateForm();
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
if (Object.keys(errors).length > 0) {
|
|
||||||
// Parse and display errors
|
|
||||||
const errorMessages = getUniqueFormikErrors(errors);
|
|
||||||
setFormErrorList(errorMessages);
|
|
||||||
return; // Stop submission
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
|
||||||
e.preventDefault();
|
|
||||||
handleBlurField(currentInput);
|
|
||||||
handleValidateForm();
|
|
||||||
formik.handleSubmit(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -356,13 +340,7 @@ const SalesOrderProductForm = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Error List Alert */}
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
{formErrorList.length > 0 && (
|
|
||||||
<AlertErrorList
|
|
||||||
formErrorList={formErrorList}
|
|
||||||
onClose={() => setFormErrorList([])}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className='flex flex-row justify-end gap-3 mt-4'>
|
<div className='flex flex-row justify-end gap-3 mt-4'>
|
||||||
<Button type='reset' color='warning' onClick={handleResetForm}>
|
<Button type='reset' color='warning' onClick={handleResetForm}>
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import {
|
|||||||
} from '@/types/api/master-data/area';
|
} from '@/types/api/master-data/area';
|
||||||
import { AreaApi } from '@/services/api/master-data';
|
import { AreaApi } from '@/services/api/master-data';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
interface AreaFormProps {
|
interface AreaFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -118,6 +120,9 @@ const AreaForm = ({ type = 'add', initialValues }: AreaFormProps) => {
|
|||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
}, [formikSetValues, formikInitialValues]);
|
}, [formikSetValues, formikInitialValues]);
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className='w-full max-w-xl'>
|
<section className='w-full max-w-xl'>
|
||||||
@@ -139,7 +144,7 @@ const AreaForm = ({ type = 'add', initialValues }: AreaFormProps) => {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
className='w-full mt-8 flex flex-col gap-6'
|
className='w-full mt-8 flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
@@ -199,6 +204,8 @@ const AreaForm = ({ type = 'add', initialValues }: AreaFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
|
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
<div
|
<div
|
||||||
className={cn('flex flex-row justify-end gap-2', {
|
className={cn('flex flex-row justify-end gap-2', {
|
||||||
@@ -213,7 +220,7 @@ const AreaForm = ({ type = 'add', initialValues }: AreaFormProps) => {
|
|||||||
type='submit'
|
type='submit'
|
||||||
color='primary'
|
color='primary'
|
||||||
isLoading={formik.isSubmitting}
|
isLoading={formik.isSubmitting}
|
||||||
disabled={!formik.isValid || formik.isSubmitting}
|
disabled={formik.isSubmitting}
|
||||||
className='px-4'
|
className='px-4'
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import {
|
|||||||
} from '@/types/api/master-data/bank';
|
} from '@/types/api/master-data/bank';
|
||||||
import { BankApi } from '@/services/api/master-data';
|
import { BankApi } from '@/services/api/master-data';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
interface BankFormProps {
|
interface BankFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -124,6 +126,9 @@ const BankForm = ({ type = 'add', initialValues }: BankFormProps) => {
|
|||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
}, [formikSetValues, formikInitialValues]);
|
}, [formikSetValues, formikInitialValues]);
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className='w-full max-w-xl'>
|
<section className='w-full max-w-xl'>
|
||||||
@@ -145,7 +150,7 @@ const BankForm = ({ type = 'add', initialValues }: BankFormProps) => {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
className='w-full mt-8 flex flex-col gap-6'
|
className='w-full mt-8 flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
@@ -247,6 +252,8 @@ const BankForm = ({ type = 'add', initialValues }: BankFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
|
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
<div
|
<div
|
||||||
className={cn('flex flex-row justify-end gap-2', {
|
className={cn('flex flex-row justify-end gap-2', {
|
||||||
@@ -261,7 +268,7 @@ const BankForm = ({ type = 'add', initialValues }: BankFormProps) => {
|
|||||||
type='submit'
|
type='submit'
|
||||||
color='primary'
|
color='primary'
|
||||||
isLoading={formik.isSubmitting}
|
isLoading={formik.isSubmitting}
|
||||||
disabled={!formik.isValid || formik.isSubmitting}
|
disabled={formik.isSubmitting}
|
||||||
className='px-4'
|
className='px-4'
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ import useSWR from 'swr';
|
|||||||
import { UserApi } from '@/services/api/user';
|
import { UserApi } from '@/services/api/user';
|
||||||
import { TYPE_OPTIONS } from '@/config/constant';
|
import { TYPE_OPTIONS } from '@/config/constant';
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
|
||||||
interface CustomerFormProps {
|
interface CustomerFormProps {
|
||||||
formType?: 'add' | 'edit' | 'detail';
|
formType?: 'add' | 'edit' | 'detail';
|
||||||
@@ -191,6 +193,9 @@ const CustomerForm = ({
|
|||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
}, [formikSetValues, formikInitialValues]);
|
}, [formikSetValues, formikInitialValues]);
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -213,7 +218,7 @@ const CustomerForm = ({
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
className='w-full mt-8 flex flex-col gap-6'
|
className='w-full mt-8 flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
@@ -358,6 +363,8 @@ const CustomerForm = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
|
|
||||||
{formType !== 'detail' && (
|
{formType !== 'detail' && (
|
||||||
<div
|
<div
|
||||||
className={cn('flex flex-row justify-end gap-2', {
|
className={cn('flex flex-row justify-end gap-2', {
|
||||||
@@ -372,7 +379,7 @@ const CustomerForm = ({
|
|||||||
type='submit'
|
type='submit'
|
||||||
color='primary'
|
color='primary'
|
||||||
isLoading={formik.isSubmitting}
|
isLoading={formik.isSubmitting}
|
||||||
disabled={!formik.isValid || formik.isSubmitting}
|
disabled={formik.isSubmitting}
|
||||||
className='px-4'
|
className='px-4'
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import {
|
|||||||
} from '@/types/api/master-data/fcr';
|
} from '@/types/api/master-data/fcr';
|
||||||
import { FcrApi } from '@/services/api/master-data';
|
import { FcrApi } from '@/services/api/master-data';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
interface FcrFormProps {
|
interface FcrFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -158,6 +160,9 @@ const FcrForm = ({ type = 'add', initialValues }: FcrFormProps) => {
|
|||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
}, [formikSetValues, formikInitialValues]);
|
}, [formikSetValues, formikInitialValues]);
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className='w-full max-w-5xl'>
|
<section className='w-full max-w-5xl'>
|
||||||
@@ -179,7 +184,7 @@ const FcrForm = ({ type = 'add', initialValues }: FcrFormProps) => {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
className='w-full mt-8 flex flex-col gap-6'
|
className='w-full mt-8 flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
@@ -294,6 +299,8 @@ const FcrForm = ({ type = 'add', initialValues }: FcrFormProps) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
|
|
||||||
<div className='flex flex-row justify-between gap-2 flex-wrap'>
|
<div className='flex flex-row justify-between gap-2 flex-wrap'>
|
||||||
{type !== 'add' && (
|
{type !== 'add' && (
|
||||||
<div className='flex flex-row justify-start gap-2'>
|
<div className='flex flex-row justify-start gap-2'>
|
||||||
@@ -349,7 +356,7 @@ const FcrForm = ({ type = 'add', initialValues }: FcrFormProps) => {
|
|||||||
type='submit'
|
type='submit'
|
||||||
color='primary'
|
color='primary'
|
||||||
isLoading={formik.isSubmitting}
|
isLoading={formik.isSubmitting}
|
||||||
disabled={!formik.isValid || formik.isSubmitting}
|
disabled={formik.isSubmitting}
|
||||||
className='px-4'
|
className='px-4'
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import TextInput from '@/components/input/TextInput';
|
|||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
interface FlockCustomProps {
|
interface FlockCustomProps {
|
||||||
formType?: 'add' | 'edit' | 'detail';
|
formType?: 'add' | 'edit' | 'detail';
|
||||||
@@ -86,6 +88,9 @@ const FlockForm = ({ formType = 'add', initialValues }: FlockCustomProps) => {
|
|||||||
formikSetValues(formikInitialValue);
|
formikSetValues(formikInitialValue);
|
||||||
}, [formikSetValues, formikInitialValue]);
|
}, [formikSetValues, formikInitialValue]);
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -107,7 +112,7 @@ const FlockForm = ({ formType = 'add', initialValues }: FlockCustomProps) => {
|
|||||||
</h1>
|
</h1>
|
||||||
</header>
|
</header>
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
className='w-full mt-8 flex flex-col gap-6'
|
className='w-full mt-8 flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
@@ -168,6 +173,8 @@ const FlockForm = ({ formType = 'add', initialValues }: FlockCustomProps) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
|
|
||||||
{formType !== 'detail' && (
|
{formType !== 'detail' && (
|
||||||
<div
|
<div
|
||||||
className={cn('flex flex-row justify-end gap-2', {
|
className={cn('flex flex-row justify-end gap-2', {
|
||||||
@@ -182,7 +189,7 @@ const FlockForm = ({ formType = 'add', initialValues }: FlockCustomProps) => {
|
|||||||
type='submit'
|
type='submit'
|
||||||
color='primary'
|
color='primary'
|
||||||
isLoading={formik.isSubmitting}
|
isLoading={formik.isSubmitting}
|
||||||
disabled={!formik.isValid || formik.isSubmitting}
|
disabled={formik.isSubmitting}
|
||||||
className='px-4'
|
className='px-4'
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import { LocationApi, KandangApi } from '@/services/api/master-data';
|
|||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
import { UserApi } from '@/services/api/user';
|
import { UserApi } from '@/services/api/user';
|
||||||
import NumberInput from '@/components/input/NumberInput';
|
import NumberInput from '@/components/input/NumberInput';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
|
||||||
interface KandangFormProps {
|
interface KandangFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -198,6 +200,9 @@ const KandangForm = ({ type = 'add', initialValues }: KandangFormProps) => {
|
|||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
}, [formikSetValues, formikInitialValues]);
|
}, [formikSetValues, formikInitialValues]);
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className='w-full max-w-xl'>
|
<section className='w-full max-w-xl'>
|
||||||
@@ -219,7 +224,7 @@ const KandangForm = ({ type = 'add', initialValues }: KandangFormProps) => {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
className='w-full mt-8 flex flex-col gap-6'
|
className='w-full mt-8 flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
@@ -324,6 +329,8 @@ const KandangForm = ({ type = 'add', initialValues }: KandangFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
|
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
<div
|
<div
|
||||||
className={cn('flex flex-row justify-end gap-2', {
|
className={cn('flex flex-row justify-end gap-2', {
|
||||||
@@ -338,7 +345,7 @@ const KandangForm = ({ type = 'add', initialValues }: KandangFormProps) => {
|
|||||||
type='submit'
|
type='submit'
|
||||||
color='primary'
|
color='primary'
|
||||||
isLoading={formik.isSubmitting}
|
isLoading={formik.isSubmitting}
|
||||||
disabled={!formik.isValid || formik.isSubmitting}
|
disabled={formik.isSubmitting}
|
||||||
className='px-4'
|
className='px-4'
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import {
|
|||||||
} from '@/types/api/master-data/location';
|
} from '@/types/api/master-data/location';
|
||||||
import { AreaApi, LocationApi } from '@/services/api/master-data';
|
import { AreaApi, LocationApi } from '@/services/api/master-data';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
|
||||||
interface LocationFormProps {
|
interface LocationFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -160,6 +162,9 @@ const LocationForm = ({ type = 'add', initialValues }: LocationFormProps) => {
|
|||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
}, [formikSetValues, formikInitialValues]);
|
}, [formikSetValues, formikInitialValues]);
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className='w-full max-w-xl'>
|
<section className='w-full max-w-xl'>
|
||||||
@@ -181,7 +186,7 @@ const LocationForm = ({ type = 'add', initialValues }: LocationFormProps) => {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
className='w-full mt-8 flex flex-col gap-6'
|
className='w-full mt-8 flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
@@ -268,6 +273,8 @@ const LocationForm = ({ type = 'add', initialValues }: LocationFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
|
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
<div
|
<div
|
||||||
className={cn('flex flex-row justify-end gap-2', {
|
className={cn('flex flex-row justify-end gap-2', {
|
||||||
@@ -282,7 +289,7 @@ const LocationForm = ({ type = 'add', initialValues }: LocationFormProps) => {
|
|||||||
type='submit'
|
type='submit'
|
||||||
color='primary'
|
color='primary'
|
||||||
isLoading={formik.isSubmitting}
|
isLoading={formik.isSubmitting}
|
||||||
disabled={!formik.isValid || formik.isSubmitting}
|
disabled={formik.isSubmitting}
|
||||||
className='px-4'
|
className='px-4'
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import { NonstockApi, SupplierApi, UomApi } from '@/services/api/master-data';
|
|||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
import { flags } from '@/types/api/api-general';
|
import { flags } from '@/types/api/api-general';
|
||||||
import { SUPPLIER_FLAG_OPTIONS } from '@/config/constant';
|
import { SUPPLIER_FLAG_OPTIONS } from '@/config/constant';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
|
||||||
interface NonstockFormProps {
|
interface NonstockFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -213,6 +215,9 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => {
|
|||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
}, [formikSetValues, formikInitialValues]);
|
}, [formikSetValues, formikInitialValues]);
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className='w-full max-w-xl'>
|
<section className='w-full max-w-xl'>
|
||||||
@@ -234,7 +239,7 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
className='w-full mt-8 flex flex-col gap-6'
|
className='w-full mt-8 flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
@@ -337,6 +342,8 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
|
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
<div
|
<div
|
||||||
className={cn('flex flex-row justify-end gap-2', {
|
className={cn('flex flex-row justify-end gap-2', {
|
||||||
@@ -351,7 +358,7 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => {
|
|||||||
type='submit'
|
type='submit'
|
||||||
color='primary'
|
color='primary'
|
||||||
isLoading={formik.isSubmitting}
|
isLoading={formik.isSubmitting}
|
||||||
disabled={!formik.isValid || formik.isSubmitting}
|
disabled={formik.isSubmitting}
|
||||||
className='px-4'
|
className='px-4'
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import TextInput from '@/components/input/TextInput';
|
|||||||
import { useModal } from '@/components/Modal';
|
import { useModal } from '@/components/Modal';
|
||||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
import { getUniqueFormikErrors } from '@/lib/formik-helper';
|
|
||||||
import AlertErrorList from '@/components/helper/form/FormErrors';
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -27,6 +26,7 @@ import {
|
|||||||
} from '@/types/api/master-data/product-category';
|
} from '@/types/api/master-data/product-category';
|
||||||
import { ProductCategoryApi } from '@/services/api/master-data';
|
import { ProductCategoryApi } from '@/services/api/master-data';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
interface ProductCategoryFormProps {
|
interface ProductCategoryFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -41,7 +41,6 @@ const ProductCategoryForm = ({
|
|||||||
const deleteModal = useModal();
|
const deleteModal = useModal();
|
||||||
|
|
||||||
const [formErrorMessage, setFormErrorMessage] = useState('');
|
const [formErrorMessage, setFormErrorMessage] = useState('');
|
||||||
const [formErrorList, setFormErrorList] = useState<string[]>([]);
|
|
||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
|
|
||||||
const createProductCategoryHandler = useCallback(
|
const createProductCategoryHandler = useCallback(
|
||||||
@@ -132,21 +131,8 @@ const ProductCategoryForm = ({
|
|||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
}, [formikSetValues, formikInitialValues]);
|
}, [formikSetValues, formikInitialValues]);
|
||||||
|
|
||||||
const handleValidateForm = async () => {
|
// ===== Formik Error List =====
|
||||||
const errors = await formik.validateForm();
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -184,13 +170,7 @@ const ProductCategoryForm = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Error List Alert */}
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
{formErrorList.length > 0 && (
|
|
||||||
<AlertErrorList
|
|
||||||
formErrorList={formErrorList}
|
|
||||||
onClose={() => setFormErrorList([])}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className='flex flex-col gap-4'>
|
<div className='flex flex-col gap-4'>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import {
|
|||||||
} from '@/services/api/master-data';
|
} from '@/services/api/master-data';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
import { PRODUCT_FLAG_OPTIONS } from '@/config/constant';
|
import { PRODUCT_FLAG_OPTIONS } from '@/config/constant';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
interface ProductFormProps {
|
interface ProductFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -50,7 +51,6 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
|||||||
const deleteModal = useModal();
|
const deleteModal = useModal();
|
||||||
|
|
||||||
const [productFormErrorMessage, setProductFormErrorMessage] = useState('');
|
const [productFormErrorMessage, setProductFormErrorMessage] = useState('');
|
||||||
const [formErrorList, setFormErrorList] = useState<string[]>([]);
|
|
||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
|
|
||||||
const createProductHandler = useCallback(
|
const createProductHandler = useCallback(
|
||||||
@@ -204,21 +204,8 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
|||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
}, [formikSetValues, formikInitialValues]);
|
}, [formikSetValues, formikInitialValues]);
|
||||||
|
|
||||||
const handleValidateForm = async () => {
|
// ===== Formik Error List =====
|
||||||
const errors = await formik.validateForm();
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -254,13 +241,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Error List Alert */}
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
{formErrorList.length > 0 && (
|
|
||||||
<AlertErrorList
|
|
||||||
formErrorList={formErrorList}
|
|
||||||
onClose={() => setFormErrorList([])}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className='grid grid-cols-1 gap-4'>
|
<div className='grid grid-cols-1 gap-4'>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
|||||||
+24
-15
@@ -9,6 +9,7 @@ import {
|
|||||||
ProductionStandardRepeaterFormSchemaValues,
|
ProductionStandardRepeaterFormSchemaValues,
|
||||||
ProductionStandardFormValues,
|
ProductionStandardFormValues,
|
||||||
createProductionStandardRepeaterFormSchema,
|
createProductionStandardRepeaterFormSchema,
|
||||||
|
ProductionStandardFormSchema,
|
||||||
} from '@/components/pages/master-data/production-standard/form/ProductionStandardForm.schema';
|
} from '@/components/pages/master-data/production-standard/form/ProductionStandardForm.schema';
|
||||||
import Table, { TABLE_DEFAULT_STYLING } from '@/components/Table';
|
import Table, { TABLE_DEFAULT_STYLING } from '@/components/Table';
|
||||||
import { FLOCK_CATEGORY_OPTIONS } from '@/config/constant';
|
import { FLOCK_CATEGORY_OPTIONS } from '@/config/constant';
|
||||||
@@ -31,6 +32,8 @@ import { useModal } from '@/components/Modal';
|
|||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
import Tooltip from '@/components/Tooltip';
|
import Tooltip from '@/components/Tooltip';
|
||||||
import Alert from '@/components/Alert';
|
import Alert from '@/components/Alert';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
|
||||||
type TableRowsType = {
|
type TableRowsType = {
|
||||||
customRow: boolean;
|
customRow: boolean;
|
||||||
@@ -207,6 +210,7 @@ const ProductionStandardForm = ({
|
|||||||
initialValues: formikInitialValues as ProductionStandardFormValues,
|
initialValues: formikInitialValues as ProductionStandardFormValues,
|
||||||
// Only enable reinitialize for edit/detail mode, not add mode
|
// Only enable reinitialize for edit/detail mode, not add mode
|
||||||
enableReinitialize: formType !== 'add',
|
enableReinitialize: formType !== 'add',
|
||||||
|
validationSchema: ProductionStandardFormSchema,
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
switch (formType) {
|
switch (formType) {
|
||||||
case 'add':
|
case 'add':
|
||||||
@@ -723,7 +727,8 @@ const ProductionStandardForm = ({
|
|||||||
router.push('/master-data/production-standard');
|
router.push('/master-data/production-standard');
|
||||||
};
|
};
|
||||||
|
|
||||||
// ===== Function =====
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -1210,9 +1215,26 @@ const ProductionStandardForm = ({
|
|||||||
return null;
|
return null;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
|
|
||||||
|
{productionStandardFormErrorMessage && (
|
||||||
|
<Alert color='error' className='w-full'>
|
||||||
|
<div className='flex items-center gap-2 stretch'>
|
||||||
|
<Icon icon='mdi:alert' />
|
||||||
|
<span>{productionStandardFormErrorMessage}</span>
|
||||||
|
</div>
|
||||||
|
<Icon
|
||||||
|
icon='mdi:close'
|
||||||
|
onClick={() => setProductionStandardFormErrorMessage('')}
|
||||||
|
className='ms-auto'
|
||||||
|
/>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
<form
|
<form
|
||||||
className='flex justify-between mt-6 gap-2 flex-wrap'
|
className='flex justify-between mt-6 gap-2 flex-wrap'
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
>
|
>
|
||||||
{formType === 'detail' && (
|
{formType === 'detail' && (
|
||||||
<div className='gap-2 flex items-center'>
|
<div className='gap-2 flex items-center'>
|
||||||
@@ -1293,19 +1315,6 @@ const ProductionStandardForm = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
{productionStandardFormErrorMessage && (
|
|
||||||
<Alert color='error' className='w-full'>
|
|
||||||
<div className='flex items-center gap-2 stretch'>
|
|
||||||
<Icon icon='mdi:alert' />
|
|
||||||
<span>{productionStandardFormErrorMessage}</span>
|
|
||||||
</div>
|
|
||||||
<Icon
|
|
||||||
icon='mdi:close'
|
|
||||||
onClick={() => setProductionStandardFormErrorMessage('')}
|
|
||||||
className='ms-auto'
|
|
||||||
/>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import TextArea from '@/components/input/TextArea';
|
|||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
|
||||||
interface SupplierCustomProps {
|
interface SupplierCustomProps {
|
||||||
formType?: 'add' | 'edit' | 'detail';
|
formType?: 'add' | 'edit' | 'detail';
|
||||||
@@ -199,6 +201,9 @@ const SupplierForm = ({
|
|||||||
formik.setFieldValue('category', val);
|
formik.setFieldValue('category', val);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -221,7 +226,7 @@ const SupplierForm = ({
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
className='w-full mt-8 flex flex-col gap-6'
|
className='w-full mt-8 flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
@@ -444,6 +449,8 @@ const SupplierForm = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
|
|
||||||
{formType !== 'detail' && (
|
{formType !== 'detail' && (
|
||||||
<div
|
<div
|
||||||
className={cn('flex flex-row justify-end gap-2', {
|
className={cn('flex flex-row justify-end gap-2', {
|
||||||
@@ -458,7 +465,7 @@ const SupplierForm = ({
|
|||||||
type='submit'
|
type='submit'
|
||||||
color='primary'
|
color='primary'
|
||||||
isLoading={formik.isSubmitting}
|
isLoading={formik.isSubmitting}
|
||||||
disabled={!formik.isValid || formik.isSubmitting}
|
disabled={formik.isSubmitting}
|
||||||
className='px-4'
|
className='px-4'
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import {
|
|||||||
} from '@/types/api/master-data/uom';
|
} from '@/types/api/master-data/uom';
|
||||||
import { UomApi } from '@/services/api/master-data';
|
import { UomApi } from '@/services/api/master-data';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
|
||||||
interface UomFormProps {
|
interface UomFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -118,6 +120,9 @@ const UomForm = ({ type = 'add', initialValues }: UomFormProps) => {
|
|||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
}, [formikSetValues, formikInitialValues]);
|
}, [formikSetValues, formikInitialValues]);
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className='w-full max-w-xl'>
|
<section className='w-full max-w-xl'>
|
||||||
@@ -139,7 +144,7 @@ const UomForm = ({ type = 'add', initialValues }: UomFormProps) => {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
className='w-full mt-8 flex flex-col gap-6'
|
className='w-full mt-8 flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
@@ -199,6 +204,8 @@ const UomForm = ({ type = 'add', initialValues }: UomFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
|
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
<div
|
<div
|
||||||
className={cn('flex flex-row justify-end gap-2', {
|
className={cn('flex flex-row justify-end gap-2', {
|
||||||
@@ -213,7 +220,7 @@ const UomForm = ({ type = 'add', initialValues }: UomFormProps) => {
|
|||||||
type='submit'
|
type='submit'
|
||||||
color='primary'
|
color='primary'
|
||||||
isLoading={formik.isSubmitting}
|
isLoading={formik.isSubmitting}
|
||||||
disabled={!formik.isValid || formik.isSubmitting}
|
disabled={formik.isSubmitting}
|
||||||
className='px-4'
|
className='px-4'
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ import {
|
|||||||
} from '@/services/api/master-data';
|
} from '@/services/api/master-data';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
import { WAREHOUSE_TYPE_OPTIONS } from '@/config/constant';
|
import { WAREHOUSE_TYPE_OPTIONS } from '@/config/constant';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
|
|
||||||
interface WarehouseFormProps {
|
interface WarehouseFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -323,6 +325,9 @@ const WarehouseForm = ({ type = 'add', initialValues }: WarehouseFormProps) => {
|
|||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
}, [formikSetValues, formikInitialValues]);
|
}, [formikSetValues, formikInitialValues]);
|
||||||
|
|
||||||
|
// ===== Formik Error List =====
|
||||||
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className='w-full max-w-xl'>
|
<section className='w-full max-w-xl'>
|
||||||
@@ -344,7 +349,7 @@ const WarehouseForm = ({ type = 'add', initialValues }: WarehouseFormProps) => {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
className='w-full mt-8 flex flex-col gap-6'
|
className='w-full mt-8 flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
@@ -474,6 +479,8 @@ const WarehouseForm = ({ type = 'add', initialValues }: WarehouseFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
|
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
<div
|
<div
|
||||||
className={cn('flex flex-row justify-end gap-2', {
|
className={cn('flex flex-row justify-end gap-2', {
|
||||||
@@ -488,7 +495,7 @@ const WarehouseForm = ({ type = 'add', initialValues }: WarehouseFormProps) => {
|
|||||||
type='submit'
|
type='submit'
|
||||||
color='primary'
|
color='primary'
|
||||||
isLoading={formik.isSubmitting}
|
isLoading={formik.isSubmitting}
|
||||||
disabled={!formik.isValid || formik.isSubmitting}
|
disabled={formik.isSubmitting}
|
||||||
className='px-4'
|
className='px-4'
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -209,20 +209,6 @@ const ProjectFlockDetail = ({
|
|||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <div className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2'>
|
|
||||||
<Icon width={14} height={14} icon={'mdi:clock'} /> History
|
|
||||||
</div>
|
|
||||||
<div className='col-span-2'>
|
|
||||||
<Button variant='outline' className='py-1 text-sm'>
|
|
||||||
See History{' '}
|
|
||||||
<Icon
|
|
||||||
icon='mdi:arrow-top-right-thin'
|
|
||||||
width={11}
|
|
||||||
height={11}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</div> */}
|
|
||||||
|
|
||||||
{/* BARIS 1 */}
|
{/* BARIS 1 */}
|
||||||
<div
|
<div
|
||||||
className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2
|
className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2
|
||||||
@@ -252,6 +238,18 @@ const ProjectFlockDetail = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className='col-span-2'>{projectFlock?.fcr?.name}</div>
|
<div className='col-span-2'>{projectFlock?.fcr?.name}</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2
|
||||||
|
relative
|
||||||
|
before:content-[""] before:absolute before:left-[5px] before:top-[90%] before:bottom-[-100%] before:w-[1px] before:border-1 before:border-dashed before:border-gray-400'
|
||||||
|
>
|
||||||
|
<Icon width={14} height={14} icon='mdi:circle-slice-8' />{' '}
|
||||||
|
Standard
|
||||||
|
</div>
|
||||||
|
<div className='col-span-2'>
|
||||||
|
{projectFlock?.production_standard?.name ?? '-'}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* BARIS 3 (Terakhir - TIDAK PERLU garis di bawahnya) */}
|
{/* BARIS 3 (Terakhir - TIDAK PERLU garis di bawahnya) */}
|
||||||
<div className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2'>
|
<div className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2'>
|
||||||
<Icon width={14} height={14} icon='mdi:circle-slice-8' />{' '}
|
<Icon width={14} height={14} icon='mdi:circle-slice-8' />{' '}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import SelectInput, {
|
|||||||
useSelect,
|
useSelect,
|
||||||
} from '@/components/input/SelectInput';
|
} from '@/components/input/SelectInput';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { getUniqueFormikErrors } from '@/lib/formik-helper';
|
|
||||||
import AlertErrorList from '@/components/helper/form/FormErrors';
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||||
import {
|
import {
|
||||||
AreaApi,
|
AreaApi,
|
||||||
@@ -47,6 +46,7 @@ import { Nonstock } from '@/types/api/master-data/nonstock';
|
|||||||
import { useUiStore } from '@/stores/ui/ui.store';
|
import { useUiStore } from '@/stores/ui/ui.store';
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
import DrawerHeader from '@/components/helper/drawer/DrawerHeader';
|
import DrawerHeader from '@/components/helper/drawer/DrawerHeader';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
interface ProjectFlockFormProps {
|
interface ProjectFlockFormProps {
|
||||||
formType?: 'add' | 'edit' | 'detail';
|
formType?: 'add' | 'edit' | 'detail';
|
||||||
@@ -66,7 +66,6 @@ const ProjectFlockForm = ({
|
|||||||
|
|
||||||
const [projectFlockFormErrorMessage, setProjectFlockFormErrorMessage] =
|
const [projectFlockFormErrorMessage, setProjectFlockFormErrorMessage] =
|
||||||
useState('');
|
useState('');
|
||||||
const [formErrorList, setFormErrorList] = useState<string[]>([]);
|
|
||||||
const [selectedArea, setSelectedArea] = useState('');
|
const [selectedArea, setSelectedArea] = useState('');
|
||||||
const [selectedLocation, setSelectedLocation] = useState('');
|
const [selectedLocation, setSelectedLocation] = useState('');
|
||||||
const [selectedCategory, setSelectedCategory] = useState('');
|
const [selectedCategory, setSelectedCategory] = useState('');
|
||||||
@@ -642,16 +641,8 @@ const ProjectFlockForm = ({
|
|||||||
return !isNonstockAlreadyInBudgets;
|
return !isNonstockAlreadyInBudgets;
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleValidateForm = async () => {
|
// ===== Formik Error List =====
|
||||||
const errors = await formik.validateForm();
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
||||||
|
|
||||||
if (Object.keys(errors).length > 0) {
|
|
||||||
// Parse and display errors
|
|
||||||
const errorMessages = getUniqueFormikErrors(errors);
|
|
||||||
setFormErrorList(errorMessages);
|
|
||||||
return; // Stop submission
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -712,11 +703,7 @@ const ProjectFlockForm = ({
|
|||||||
|
|
||||||
<form
|
<form
|
||||||
className='w-auto h-auto'
|
className='w-auto h-auto'
|
||||||
onSubmit={(e) => {
|
onSubmit={handleFormSubmit}
|
||||||
e.preventDefault();
|
|
||||||
handleValidateForm();
|
|
||||||
formik.handleSubmit(e);
|
|
||||||
}}
|
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
>
|
>
|
||||||
{/* Form Informasi Umum */}
|
{/* Form Informasi Umum */}
|
||||||
@@ -1082,13 +1069,7 @@ const ProjectFlockForm = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Error List Alert */}
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
{formErrorList.length > 0 && (
|
|
||||||
<AlertErrorList
|
|
||||||
formErrorList={formErrorList}
|
|
||||||
onClose={() => setFormErrorList([])}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className='flex flex-row justify-center gap-2 flex-wrap my-6 px-4'>
|
<div className='flex flex-row justify-center gap-2 flex-wrap my-6 px-4'>
|
||||||
{formType !== 'detail' && (
|
{formType !== 'detail' && (
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import { getUniqueFormikErrors } from '@/lib/formik-helper';
|
||||||
|
import { FormikProps } from 'formik';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
interface UseFormikErrorListOptions {
|
||||||
|
onBeforeSubmit?: (e: React.FormEvent<HTMLFormElement>) => boolean | void;
|
||||||
|
onAfterValidation?: () => void | Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useFormikErrorList = <T>(
|
||||||
|
formik: FormikProps<T>,
|
||||||
|
options?: UseFormikErrorListOptions
|
||||||
|
) => {
|
||||||
|
const [formErrorList, setFormErrorList] = useState<string[]>([]);
|
||||||
|
|
||||||
|
const handleValidateForm = async () => {
|
||||||
|
const errors = await formik.validateForm();
|
||||||
|
|
||||||
|
if (Object.keys(errors).length > 0) {
|
||||||
|
const errorMessages = getUniqueFormikErrors(errors);
|
||||||
|
setFormErrorList(errorMessages);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFormSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// Call onBeforeSubmit callback
|
||||||
|
if (options?.onBeforeSubmit) {
|
||||||
|
const shouldContinue = options.onBeforeSubmit(e);
|
||||||
|
if (shouldContinue === false) {
|
||||||
|
return; // Cancel submit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate form
|
||||||
|
const isValid = await handleValidateForm();
|
||||||
|
|
||||||
|
// Call onAfterValidation callback if validation passed
|
||||||
|
if (options?.onAfterValidation) {
|
||||||
|
await options.onAfterValidation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Submit form
|
||||||
|
formik.handleSubmit();
|
||||||
|
};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
setFormErrorList([]);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
formErrorList,
|
||||||
|
setFormErrorList,
|
||||||
|
close,
|
||||||
|
handleValidateForm,
|
||||||
|
handleFormSubmit,
|
||||||
|
};
|
||||||
|
};
|
||||||
Vendored
+1
@@ -63,6 +63,7 @@ export type BaseClosing = {
|
|||||||
location_id: number;
|
location_id: number;
|
||||||
location_name: string;
|
location_name: string;
|
||||||
project_category: 'GROWING' | 'LAYING';
|
project_category: 'GROWING' | 'LAYING';
|
||||||
|
project_type?: 'GROWING' | 'LAYING'; // berubah dari BE?
|
||||||
period: number;
|
period: number;
|
||||||
closing_date?: string;
|
closing_date?: string;
|
||||||
shed_label: string;
|
shed_label: string;
|
||||||
|
|||||||
+1
@@ -5,6 +5,7 @@ import { Kandang } from '@/types/api/master-data/kandang';
|
|||||||
import { Location } from '@/types/api/master-data/location';
|
import { Location } from '@/types/api/master-data/location';
|
||||||
import { BaseApproval, BaseMetadata } from '@/types/api/api-general';
|
import { BaseApproval, BaseMetadata } from '@/types/api/api-general';
|
||||||
import { Nonstock } from '@/types/api/master-data/nonstock';
|
import { Nonstock } from '@/types/api/master-data/nonstock';
|
||||||
|
import { ProductionStandard } from '@/types/api/master-data/production-standard';
|
||||||
|
|
||||||
export type BaseProjectFlock = {
|
export type BaseProjectFlock = {
|
||||||
id: number;
|
id: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user