feat: create TransferToLayingFormModal component

This commit is contained in:
ValdiANS
2026-01-24 11:20:24 +07:00
parent db1e224c3b
commit 71a430c99c
@@ -0,0 +1,940 @@
'use client';
import {
FormEventHandler,
useCallback,
useEffect,
useMemo,
useState,
} from 'react';
import useSWR, { useSWRConfig } from 'swr';
import toast from 'react-hot-toast';
import { Icon } from '@iconify/react';
import Modal, { useModal } from '@/components/Modal';
import Button from '@/components/Button';
import DateInput from '@/components/input/DateInput';
import SelectInputRadio from '@/components/input/SelectInputRadio';
import { OptionType, useSelect } from '@/components/input/SelectInput';
import NumberInput from '@/components/input/NumberInput';
import TextArea from '@/components/input/TextArea';
import AlertErrorList from '@/components/helper/form/FormErrors';
import { useRouter, useSearchParams } from 'next/navigation';
import { ProjectFlockApi } from '@/services/api/production';
import { getIn, useFormik } from 'formik';
import {
getFilledTransferToLayingFormInitialValues,
getTransferToLayingFormInitialValues,
TransferToLayingFormSchema,
TransferToLayingFormValues,
} from '@/components/pages/production/transfer-to-laying/form/TransferToLayingForm.schema';
import { TransferToLayingApi } from '@/services/api/production/transfer-to-laying';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import StatusBadge from '@/components/helper/StatusBadge';
import CheckboxInput from '@/components/input/CheckboxInput';
import { ProjectFlock } from '@/types/api/production/project-flock';
import { cn, formatNumber } from '@/lib/helper';
import {
CreateTransferToLayingPayload,
UpdateTransferToLayingPayload,
} from '@/types/api/production/transfer-to-laying';
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
const TransferToLayingFormModal = () => {
const router = useRouter();
const searchParams = useSearchParams();
const modalAction = searchParams.get('action');
const transferToLayingId = searchParams.get('id');
const { mutate } = useSWRConfig();
const refreshTransferToLayings = () => {
mutate(
(key) =>
typeof key === 'string' && key.includes(TransferToLayingApi.basePath)
);
};
const { data: transferToLaying, isLoading: isLoadingTransferToLaying } =
useSWR(transferToLayingId ? transferToLayingId : undefined, (id: number) =>
TransferToLayingApi.getSingle(id)
);
/**
* Step 1: General Information
* Step 2: Select source and destination kandang
* Step 3: Enter transfered quantity
* Step 4: Submit
*/
const [step, setStep] = useState(1);
const formModal = useModal();
const [formErrorMessage, setFormErrorMessage] = useState<string | null>(null);
// Flock Source
const {
setInputValue: setFlockSourceInputValue,
options: flockSourceOptions,
isLoadingOptions: isLoadingFlockSourceOptions,
loadMore: loadMoreFlockSource,
rawData: flockSourceRawData,
} = useSelect<ProjectFlock>(
ProjectFlockApi.basePath,
'id',
'flock_name',
'search',
{
category: 'GROWING',
}
);
// Flock Destination
const {
setInputValue: setFlockDestinationInputValue,
options: flockDestinationOptions,
isLoadingOptions: isLoadingFlockDestinationOptions,
loadMore: loadMoreFlockDestination,
rawData: flockDestinationRawData,
} = useSelect<ProjectFlock>(
ProjectFlockApi.basePath,
'id',
'flock_name',
'search',
{
category: 'LAYING',
}
);
const closeModalHandler = (shouldPushToRoute: boolean = true) => {
if (shouldPushToRoute) {
router.push('/production/transfer-to-laying');
}
formik.resetForm();
setStep(1);
setFormErrorMessage('');
formModal.closeModal();
};
const createTransferToLayingHandler = useCallback(
async (payload: CreateTransferToLayingPayload) => {
const createTransferToLayingRes =
await TransferToLayingApi.create(payload);
if (isResponseError(createTransferToLayingRes)) {
setFormErrorMessage(createTransferToLayingRes.message);
return;
}
refreshTransferToLayings();
toast.success(createTransferToLayingRes?.message as string);
router.push('/production/transfer-to-laying');
closeModalHandler(false);
},
[router]
);
const updateTransferToLayingHandler = useCallback(
async (
transferToLayingId: number,
payload: UpdateTransferToLayingPayload
) => {
const updateKandangRes = await TransferToLayingApi.update(
transferToLayingId,
payload
);
if (updateKandangRes?.status === 'error') {
setFormErrorMessage(updateKandangRes.message);
return;
}
refreshTransferToLayings();
toast.success(updateKandangRes?.message as string);
router.push('/production/transfer-to-laying');
closeModalHandler(false);
},
[router]
);
const [formikInitialValues, setFormikInitialValues] = useState(
getTransferToLayingFormInitialValues()
);
const formik = useFormik<TransferToLayingFormValues>({
initialValues: formikInitialValues,
validationSchema: TransferToLayingFormSchema,
onSubmit: async (values) => {
const transferToLayingPayload: CreateTransferToLayingPayload = {
transfer_date: values.transfer_date as string,
source_project_flock_id: values.flockSource?.value as number,
target_project_flock_id: values.flockDestination?.value as number,
totalQuantity: values.totalQuantity as number,
source_kandangs: values.flockSourceKandangs?.map((kandang) => ({
project_flock_kandang_id: kandang.kandang.value,
quantity: parseFloat(kandang.quantity as string),
})) as CreateTransferToLayingPayload['source_kandangs'],
target_kandangs: values.flockDestinationKandangs?.map((kandang) => ({
project_flock_kandang_id: kandang.kandang.value,
quantity: parseFloat(kandang.quantity as string),
})) as CreateTransferToLayingPayload['target_kandangs'],
reason: values.reason as string,
};
switch (modalAction) {
case 'add':
await createTransferToLayingHandler(transferToLayingPayload);
break;
case 'edit':
await updateTransferToLayingHandler(
Number(transferToLayingId),
transferToLayingPayload
);
break;
}
},
});
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
const selectedFlockSourceRawData = isResponseSuccess(flockSourceRawData)
? flockSourceRawData.data.find(
(item) => item.id === formik.values.flockSource?.value
)
: undefined;
const selectedFlockDestinationRawData = isResponseSuccess(
flockDestinationRawData
)
? flockDestinationRawData.data.find(
(item) => item.id === formik.values.flockDestination?.value
)
: undefined;
const {
data: flockSourceKandangsAvailability,
isLoading: isLoadingFlockSourceKandangsAvailability,
} = useSWR(
formik.values.flockSource
? String(formik.values.flockSource.value)
: undefined,
(id: string) =>
TransferToLayingApi.getMappedFlockKandangsAvailability(Number(id))
);
const mappedFlockSourceKandangsAvailability: {
kandang_name: string;
available_qty: number;
project_flock_kandang_id: number;
}[] = useMemo(() => {
if (!flockSourceKandangsAvailability || !selectedFlockSourceRawData)
return [];
return selectedFlockSourceRawData
? selectedFlockSourceRawData.kandangs.map((kandang) => {
const availability =
flockSourceKandangsAvailability[kandang.project_flock_kandang_id]
.available_qty;
return {
kandang_name: kandang.name,
available_qty: availability,
project_flock_kandang_id: kandang.project_flock_kandang_id,
};
})
: [];
}, [flockSourceKandangsAvailability, selectedFlockSourceRawData]);
const mappedFlockSourceKandangsAvailabilityInfo: {
available: number;
unavailable: number;
} = useMemo(() => {
if (!mappedFlockSourceKandangsAvailability)
return { available: 0, unavailable: 0 };
let countAvailable = 0;
let countUnavailable = 0;
mappedFlockSourceKandangsAvailability.forEach((item) => {
if (item.available_qty > 0) {
countAvailable += 1;
} else {
countUnavailable += 1;
}
});
return { available: countAvailable, unavailable: countUnavailable };
}, [mappedFlockSourceKandangsAvailability]);
const mappedFlockDestinationKandangsAvailabilityInfo: {
available: number;
unavailable: number;
} = useMemo(() => {
if (!selectedFlockDestinationRawData)
return { available: 0, unavailable: 0 };
let countAvailable = 0;
let countUnavailable = 0;
selectedFlockDestinationRawData?.kandangs.forEach((item) => {
// TODO: change this to real available quota later
if (item.capacity > 0) {
countAvailable += 1;
} else {
countUnavailable += 1;
}
});
return { available: countAvailable, unavailable: countUnavailable };
}, [selectedFlockDestinationRawData]);
const totalEnteredChickenForTransfer =
formik.values.flockSourceKandangs.reduce(
(acc, item) => acc + Number(item.quantity),
0
);
const totalTransferedChicken = formik.values.flockDestinationKandangs.reduce(
(acc, item) => acc + Number(item.quantity),
0
);
const totalAvailableChickenForTransfer =
totalEnteredChickenForTransfer - totalTransferedChicken;
const isNextButtonDisabled = useMemo(() => {
if (step === 1) {
return Boolean(
!formik.values.transfer_date ||
!formik.values.flockSource ||
!formik.values.flockDestination
);
}
if (step === 2) {
return Boolean(
!formik.values.flockSourceKandangs.length ||
!formik.values.flockDestinationKandangs.length
);
}
return true;
}, [step, formik.values]);
const nextButtonHandler = () => {
setStep(step + 1);
};
const deleteEnteredKandangHandler = () => {
formik.setFieldValue('flockSourceKandangs', []);
formik.setFieldValue('flockDestinationKandangs', []);
formik.setFieldValue('totalQuantity', '');
formik.setFieldValue('maxTotalQuantity', '');
formik.setFieldValue('reason', '');
formik.setFieldTouched('reason', false);
setStep(2);
};
const flockSourceChangeHandler = (val: OptionType | OptionType[] | null) => {
formik.setFieldValue('flockSource', val);
formik.setFieldValue('flockSourceKandangs', []);
};
const flockDestinationChangeHandler = (
val: OptionType | OptionType[] | null
) => {
formik.setFieldValue('flockDestination', val);
formik.setFieldValue('flockDestinationKandangs', []);
};
useEffect(() => {
if (modalAction === 'add' || modalAction === 'edit') {
formModal.openModal();
}
}, [modalAction]);
useEffect(() => {
const getFilledInitialValues = async () => {
if (transferToLayingId && isResponseSuccess(transferToLaying)) {
const filledInitialValues =
await getFilledTransferToLayingFormInitialValues(
transferToLaying.data
);
formik.setValues(filledInitialValues);
setStep(3);
}
};
getFilledInitialValues();
}, [transferToLayingId, transferToLaying]);
useEffect(() => {
formik.setFieldValue('totalQuantity', totalTransferedChicken);
formik.setFieldValue('maxTotalQuantity', totalTransferedChicken);
}, [totalTransferedChicken]);
return (
<Modal
ref={formModal.ref}
position='end'
className={{
modalBox: 'w-full sm:w-fit p-3 rounded-xl bg-transparent shadow-none',
}}
>
<form
onSubmit={handleFormSubmit}
className='w-full min-h-full flex flex-col sm:flex-row items-stretch bg-base-100 rounded-xl overflow-y-auto'
>
{/* 1st Section */}
<div className='w-full sm:w-[446px]'>
<div className='w-full p-4 flex flex-row items-stretch gap-3 border-b border-base-content/10'>
<Button
type='button'
variant='ghost'
color='none'
onClick={() => closeModalHandler()}
className='p-0 text-black hover:text-base-content'
>
<Icon icon='heroicons:x-mark' width={20} height={20} />
</Button>
<div className='w-px border-none bg-base-content/10' />
<h4 className='text-sm font-medium text-base-content/50'>
Add Transfer to Laying
</h4>
</div>
<div className='w-full p-4 flex flex-col'>
<h4 className='text-base font-medium text-base-content/50 font-roboto'>
Informasi Umum
</h4>
<DateInput
name='transfer_date'
label='Tanggal'
placeholder='Tanggal'
value={formik.values.transfer_date ?? ''}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
isError={
formik.touched.transfer_date &&
Boolean(formik.errors.transfer_date)
}
errorMessage={formik.errors.transfer_date}
disabled={step > 2}
/>
<SelectInputRadio
label='Flock Asal'
placeholder='Pilih Flock Asal'
value={formik.values.flockSource}
onChange={flockSourceChangeHandler}
options={flockSourceOptions}
isLoading={isLoadingFlockSourceOptions}
onInputChange={setFlockSourceInputValue}
onMenuScrollToBottom={loadMoreFlockSource}
isDisabled={step > 2}
/>
<SelectInputRadio
label='Flock Tujuan'
placeholder='Pilih Flock Tujuan'
value={formik.values.flockDestination}
onChange={flockDestinationChangeHandler}
options={flockDestinationOptions}
isLoading={isLoadingFlockDestinationOptions}
onInputChange={setFlockDestinationInputValue}
onMenuScrollToBottom={loadMoreFlockDestination}
isDisabled={step > 2}
/>
</div>
{step >= 2 && (
<>
<div className='w-full p-4 flex flex-col gap-3 border-y border-base-content/10'>
<h4 className='text-base font-medium text-base-content/50 font-roboto'>
Pilih Kandang Asal
</h4>
<div className='w-fit flex flex-row items-stretch gap-3'>
<StatusBadge
color='info'
text={`Tersedia (${mappedFlockSourceKandangsAvailabilityInfo.available})`}
className={{ badge: 'text-nowrap' }}
/>
<div className='w-px border-none bg-base-content/10' />
<StatusBadge
color='neutral'
text={`Tidak Tersedia (${mappedFlockSourceKandangsAvailabilityInfo.unavailable})`}
className={{ badge: 'text-nowrap' }}
/>
</div>
<div className='w-full rounded-xl border border-base-content/10'>
{mappedFlockSourceKandangsAvailability.map(
(item, itemIdx) => {
const isAvailable = item.available_qty > 0;
const isChecked = formik.values.flockSourceKandangs.some(
(k) => k.kandang.value === item.project_flock_kandang_id
);
const flockSourceKandangCheckboxChangeHandler: FormEventHandler<
HTMLInputElement
> = (e) => {
const checked = (e.target as HTMLInputElement).checked;
if (checked) {
formik.setFieldValue('flockSourceKandangs', [
...formik.values.flockSourceKandangs,
{
kandang: {
value: item.project_flock_kandang_id,
label: item.kandang_name,
},
quantity: '',
maxQuantity: item.available_qty,
},
]);
} else {
formik.setFieldValue(
'flockSourceKandangs',
formik.values.flockSourceKandangs.filter(
(k) =>
k.kandang.value !==
item.project_flock_kandang_id
)
);
}
};
return (
<div
key={itemIdx}
className='w-full p-3 flex flex-row items-center justify-between'
>
<div className='flex flex-row items-center gap-3'>
<CheckboxInput
name={`flockSourceKandang.${itemIdx}.value`}
value={item.project_flock_kandang_id}
checked={isChecked}
onChange={flockSourceKandangCheckboxChangeHandler}
size='md'
disabled={!isAvailable}
classNames={{
checkbox: cn({
'bg-base-200 border border-base-content/10 opacity-100':
!isAvailable,
}),
}}
/>
<label
htmlFor={`flockSourceKandang.${itemIdx}.value`}
className={cn('text-sm text-base-content/50', {
'cursor-pointer': isAvailable,
'cursor-not-allowed': !isAvailable,
})}
>
{item.kandang_name}{' '}
<span className='text-base-content/20'>{`(Max: ${item.available_qty})`}</span>
</label>
</div>
<StatusBadge
color={isAvailable ? 'info' : 'neutral'}
text={isAvailable ? 'Tersedia' : 'Tidak Tersedia'}
className={{ badge: 'w-fit' }}
/>
</div>
);
}
)}
</div>
</div>
<div className='w-full p-4 flex flex-col gap-3'>
<div className='flex flex-row items-center justify-between'>
<h4 className='text-base font-medium text-base-content/50 font-roboto'>
Pilih Kandang Tujuan
</h4>
{formik.touched.flockDestinationKandangs &&
formik.errors.flockDestinationKandangs &&
typeof formik.errors.flockDestinationKandangs ===
'string' && (
<span className='text-xs text-error'>
{formik.errors.flockDestinationKandangs}
</span>
)}
</div>
<div className='w-fit flex flex-row items-stretch gap-3'>
<StatusBadge
color='info'
text={`Tersedia (${mappedFlockDestinationKandangsAvailabilityInfo.available})`}
className={{ badge: 'text-nowrap' }}
/>
<div className='w-px border-none bg-base-content/10' />
<StatusBadge
color='neutral'
text={`Tidak Tersedia (${mappedFlockDestinationKandangsAvailabilityInfo.unavailable})`}
className={{ badge: 'text-nowrap' }}
/>
</div>
<div className='w-full rounded-xl border border-base-content/10'>
{selectedFlockDestinationRawData?.kandangs.map(
(item, itemIdx) => {
// TODO: change this to real available quota later
const isAvailable = item.capacity > 0;
const isChecked =
formik.values.flockDestinationKandangs.some(
(k) =>
k.kandang.value === item.project_flock_kandang_id
);
const flockDestinationKandangCheckboxChangeHandler: FormEventHandler<
HTMLInputElement
> = (e) => {
const checked = (e.target as HTMLInputElement).checked;
if (checked) {
formik.setFieldValue('flockDestinationKandangs', [
...formik.values.flockDestinationKandangs,
{
kandang: {
value: item.project_flock_kandang_id,
label: item.name,
},
quantity: '',
// TODO: change this to real available quota later
maxQuantity: item.capacity,
},
]);
} else {
formik.setFieldValue(
'flockDestinationKandangs',
formik.values.flockDestinationKandangs.filter(
(k) =>
k.kandang.value !==
item.project_flock_kandang_id
)
);
}
};
return (
<div
key={itemIdx}
className='w-full p-3 flex flex-row items-center justify-between'
>
<div className='flex flex-row items-center gap-3'>
<CheckboxInput
name={`flockDestinationKandang.${itemIdx}.value`}
value={item.project_flock_kandang_id}
checked={isChecked}
onChange={
flockDestinationKandangCheckboxChangeHandler
}
size='md'
disabled={!isAvailable}
classNames={{
checkbox: cn({
'bg-base-200 border border-base-content/10 opacity-100':
!isAvailable,
}),
}}
/>
<label
htmlFor={`flockDestinationKandang.${itemIdx}.value`}
className={cn('text-sm text-base-content/50', {
'cursor-pointer': isAvailable,
'cursor-not-allowed': !isAvailable,
})}
>
{item.name}{' '}
{/* TODO: change this to real available quota later */}
<span className='text-base-content/20'>{`(Max: ${item.capacity})`}</span>
</label>
</div>
<StatusBadge
color={isAvailable ? 'info' : 'neutral'}
text={isAvailable ? 'Tersedia' : 'Tidak Tersedia'}
className={{ badge: 'w-fit' }}
/>
</div>
);
}
)}
</div>
</div>
</>
)}
<div className='w-full p-4 border-t border-base-content/10'>
{step < 3 && (
<Button
type='button'
onClick={nextButtonHandler}
disabled={isNextButtonDisabled}
className='w-full p-3 rounded-lg text-sm text-base-100'
>
Next
</Button>
)}
</div>
</div>
{/* 2nd Section */}
{step === 3 && (
<div className='w-full sm:w-[446px] border-l border-base-content/10'>
<div className='w-full p-4 flex flex-row items-center justify-between gap-3 border-b border-base-content/10'>
<h4 className='text-sm font-medium text-base-content/50'>
Tambah Kuantitas
</h4>
<Button
type='button'
variant='ghost'
color='none'
onClick={deleteEnteredKandangHandler}
className='p-0 text-error'
>
<Icon icon='heroicons:trash' width={20} height={20} />
</Button>
</div>
<div className='w-full p-4 flex flex-col'>
<h4 className='text-base font-medium text-base-content/50 font-roboto'>
Informasi Kandang
</h4>
{/* Source Kandang */}
<div className='flex flex-col'>
<span className='w-full py-2 text-xs font-semibold'>
Kandang Asal
</span>
{formik.values.flockSourceKandangs.length === 0 && (
<span className='text-sm text-base-content/50 italic'>
Belum ada kandang asal yang dipilih
</span>
)}
{formik.values.flockSourceKandangs.length > 0 && (
<div className='flex flex-col gap-3'>
{formik.values.flockSourceKandangs.map((item, index) => {
const isInvalid =
item.quantity === ''
? false
: Boolean(
getIn(
formik.errors,
`flockSourceKandangs[${index}].quantity`
)
);
const errorMessage = getIn(
formik.errors,
`flockSourceKandangs[${index}].quantity`
);
return (
<NumberInput
key={`flockSourceKandangs-${item.kandang.value}-${index}`}
name={`flockSourceKandangs.${index}.quantity`}
placeholder='Masukkan Kuantitas'
value={item.quantity}
onChange={formik.handleChange}
isError={isInvalid}
errorMessage={errorMessage}
inputPrefix={
<div className='w-full h-full py-1 flex flex-row items-stretch justify-between gap-5'>
<span
title={item.kandang.label}
className='text-sm text-base-content self-center text-nowrap truncate'
>
{item.kandang.label}
</span>
<div className='w-px bg-base-content/10' />
</div>
}
className={{
inputPrefix:
'py-0 px-0 pl-3 text-base-content/50 bg-transparent border-r-0',
inputPrefixSuffixWrapper: 'grid grid-cols-2',
inputWrapper: 'border-l-0 pl-5',
}}
/>
);
})}
</div>
)}
</div>
{/* Destination Kandang */}
<div className='mt-3 flex flex-col'>
<span className='w-fit py-2 text-xs font-semibold flex flex-row items-center gap-3'>
<span className='text-nowrap'>Kandang Tujuan</span>
<div className='w-px h-5 bg-base-content/10' />
<StatusBadge
color={
totalAvailableChickenForTransfer < 0 ? 'error' : 'neutral'
}
text={`Sisa ayam: ${formatNumber(
totalAvailableChickenForTransfer
)} ekor`}
className={{
badge: 'text-nowrap',
}}
/>
</span>
{formik.values.flockDestinationKandangs.length === 0 && (
<span className='text-sm text-base-content/50 italic'>
Belum ada kandang tujuan yang dipilih
</span>
)}
{formik.values.flockDestinationKandangs.length > 0 && (
<div className='flex flex-col gap-3'>
{formik.values.flockDestinationKandangs.map(
(item, index) => {
const isInvalid =
item.quantity === ''
? false
: Boolean(
getIn(
formik.errors,
`flockDestinationKandangs[${index}].quantity`
)
);
const errorMessage = getIn(
formik.errors,
`flockDestinationKandangs[${index}].quantity`
);
return (
<NumberInput
key={`flockDestinationKandangs-${item.kandang.value}-${index}`}
name={`flockDestinationKandangs.${index}.quantity`}
placeholder='Masukkan Kuantitas'
value={item.quantity}
onChange={formik.handleChange}
isError={isInvalid}
errorMessage={errorMessage}
inputPrefix={
<div className='w-full h-full py-1 flex flex-row items-stretch justify-between gap-5'>
<span
title={item.kandang.label}
className='text-sm text-base-content self-center text-nowrap truncate'
>
{item.kandang.label}
</span>
<div className='w-px bg-base-content/10' />
</div>
}
className={{
inputPrefix:
'py-0 px-0 pl-3 text-base-content/50 bg-transparent border-r-0',
inputPrefixSuffixWrapper: 'grid grid-cols-2',
inputWrapper: 'border-l-0 pl-5',
}}
/>
);
}
)}
</div>
)}
</div>
</div>
<div className='w-full p-4 flex flex-col border-y border-base-content/10'>
<h4 className='text-base font-medium text-base-content/50 font-roboto'>
Informasi Umum
</h4>
<NumberInput
name='totalQuantity'
label='Jumlah Transfer'
placeholder='Total Kuantitas Transfer'
value={formik.values.totalQuantity}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
isError={totalAvailableChickenForTransfer < 0}
errorMessage={
totalAvailableChickenForTransfer < 0
? 'Jumlah transfer melebihi ketersediaan'
: ''
}
disabled
/>
<TextArea
name='reason'
label='Catatan'
placeholder='Alasan Transfer'
rows={4}
value={formik.values.reason}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
isError={
Boolean(formik.touched.reason) &&
Boolean(formik.errors.reason)
}
errorMessage={formik.errors.reason}
/>
</div>
<div className='w-full p-4 self-end flex flex-col gap-3'>
{formErrorMessage && (
<div role='alert' className='alert alert-error w-full'>
<Icon
icon='material-symbols:error-outline'
width={24}
height={24}
/>
<span>{formErrorMessage}</span>
</div>
)}
<AlertErrorList formErrorList={formErrorList} onClose={close} />
<Button
type='submit'
disabled={
formik.isSubmitting || totalAvailableChickenForTransfer < 0
}
isLoading={formik.isSubmitting}
className='w-full p-3 rounded-lg text-sm text-base-100'
>
Submit
</Button>
</div>
</div>
)}
</form>
</Modal>
);
};
export default TransferToLayingFormModal;