mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 15:25:46 +00:00
refactor: delete unnecessary page and component
This commit is contained in:
@@ -1,11 +0,0 @@
|
|||||||
import TransferToLayingForm from '@/components/pages/production/transfer-to-laying/form/TransferToLayingForm';
|
|
||||||
|
|
||||||
const AddTransferToLaying = () => {
|
|
||||||
return (
|
|
||||||
<div className='w-full p-4 flex flex-row justify-center'>
|
|
||||||
<TransferToLayingForm />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AddTransferToLaying;
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { useRouter, useSearchParams } from 'next/navigation';
|
|
||||||
import useSWR from 'swr';
|
|
||||||
|
|
||||||
import TransferToLayingForm from '@/components/pages/production/transfer-to-laying/form/TransferToLayingForm';
|
|
||||||
|
|
||||||
import { TransferToLayingApi } from '@/services/api/production/transfer-to-laying';
|
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
|
||||||
|
|
||||||
const TransferToLayingEdit = () => {
|
|
||||||
const router = useRouter();
|
|
||||||
const searchParams = useSearchParams();
|
|
||||||
|
|
||||||
const transferToLayingId = searchParams.get('transferToLayingId');
|
|
||||||
|
|
||||||
const { data: transferToLaying, isLoading: isLoadingTransferToLaying } =
|
|
||||||
useSWR(transferToLayingId, (id: number) =>
|
|
||||||
TransferToLayingApi.getSingle(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!transferToLayingId) {
|
|
||||||
router.back();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='w-full flex flex-row justify-center items-center p-4'>
|
|
||||||
<span className='loading loading-spinner loading-xl' />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!isLoadingTransferToLaying &&
|
|
||||||
(!transferToLaying || isResponseError(transferToLaying))
|
|
||||||
) {
|
|
||||||
router.replace('/404');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
isResponseSuccess(transferToLaying) &&
|
|
||||||
transferToLaying.data.approval.step_number === 2
|
|
||||||
) {
|
|
||||||
router.replace('/production/transfer-to-laying');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='w-full p-4 flex flex-row justify-center'>
|
|
||||||
{isLoadingTransferToLaying && (
|
|
||||||
<span className='loading loading-spinner loading-xl' />
|
|
||||||
)}
|
|
||||||
{!isLoadingTransferToLaying && isResponseSuccess(transferToLaying) && (
|
|
||||||
<TransferToLayingForm
|
|
||||||
type='edit'
|
|
||||||
initialValues={transferToLaying.data}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TransferToLayingEdit;
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import SuspenseHelper from '@/components/helper/SuspenseHelper';
|
|
||||||
|
|
||||||
const Layout = ({
|
|
||||||
children,
|
|
||||||
}: Readonly<{
|
|
||||||
children: React.ReactNode;
|
|
||||||
}>) => {
|
|
||||||
return <SuspenseHelper>{children}</SuspenseHelper>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Layout;
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { useRouter, useSearchParams } from 'next/navigation';
|
|
||||||
import useSWR from 'swr';
|
|
||||||
|
|
||||||
import TransferToLayingForm from '@/components/pages/production/transfer-to-laying/form/TransferToLayingForm';
|
|
||||||
|
|
||||||
import { TransferToLayingApi } from '@/services/api/production/transfer-to-laying';
|
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
|
||||||
|
|
||||||
const TransferToLayingDetail = () => {
|
|
||||||
const router = useRouter();
|
|
||||||
const searchParams = useSearchParams();
|
|
||||||
|
|
||||||
const transferToLayingId = searchParams.get('transferToLayingId');
|
|
||||||
|
|
||||||
const { data: transferToLaying, isLoading: isLoadingTransferToLaying } =
|
|
||||||
useSWR(transferToLayingId, (id: number) =>
|
|
||||||
TransferToLayingApi.getSingle(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!transferToLayingId) {
|
|
||||||
router.back();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='w-full flex flex-row justify-center items-center p-4'>
|
|
||||||
<span className='loading loading-spinner loading-xl' />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!isLoadingTransferToLaying &&
|
|
||||||
(!transferToLaying || isResponseError(transferToLaying))
|
|
||||||
) {
|
|
||||||
router.replace('/404');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='w-full p-4 flex flex-row justify-center'>
|
|
||||||
{isLoadingTransferToLaying && (
|
|
||||||
<span className='loading loading-spinner loading-xl' />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!isLoadingTransferToLaying && isResponseSuccess(transferToLaying) && (
|
|
||||||
<TransferToLayingForm
|
|
||||||
type='detail'
|
|
||||||
initialValues={transferToLaying.data}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TransferToLayingDetail;
|
|
||||||
@@ -1,932 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
|
||||||
import { useRouter } from 'next/navigation';
|
|
||||||
import { useFormik } from 'formik';
|
|
||||||
import { toast } from 'react-hot-toast';
|
|
||||||
import useSWR from 'swr';
|
|
||||||
|
|
||||||
import { Icon } from '@iconify/react';
|
|
||||||
import Button from '@/components/Button';
|
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
|
||||||
import SelectInput, {
|
|
||||||
OptionType,
|
|
||||||
useSelect,
|
|
||||||
} from '@/components/input/SelectInput';
|
|
||||||
import TextArea from '@/components/input/TextArea';
|
|
||||||
import { useModal } from '@/components/Modal';
|
|
||||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
|
||||||
import DateInput from '@/components/input/DateInput';
|
|
||||||
import NumberInput from '@/components/input/NumberInput';
|
|
||||||
import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
|
|
||||||
import ApprovalSteps, {
|
|
||||||
formatGroupedApprovalsToApprovalSteps,
|
|
||||||
} from '@/components/pages/ApprovalSteps';
|
|
||||||
|
|
||||||
import {
|
|
||||||
getFilledTransferToLayingFormInitialValues,
|
|
||||||
getTransferToLayingFormInitialValues,
|
|
||||||
TransferToLayingFormSchema,
|
|
||||||
TransferToLayingFormValues,
|
|
||||||
UpdateTransferToLayingFormSchema,
|
|
||||||
} from '@/components/pages/production/transfer-to-laying/form/TransferToLayingForm.schema';
|
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
|
||||||
import {
|
|
||||||
TransferToLaying,
|
|
||||||
CreateTransferToLayingPayload,
|
|
||||||
UpdateTransferToLayingPayload,
|
|
||||||
} from '@/types/api/production/transfer-to-laying';
|
|
||||||
import { cn } from '@/lib/helper';
|
|
||||||
|
|
||||||
import { TransferToLayingApi } from '@/services/api/production/transfer-to-laying';
|
|
||||||
import { ProjectFlock } from '@/types/api/production/project-flock';
|
|
||||||
import { TRANSFER_TO_LAYING_APPROVAL_LINE } from '@/config/approval-line';
|
|
||||||
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
|
||||||
import AlertErrorList from '@/components/helper/form/FormErrors';
|
|
||||||
|
|
||||||
interface TransferToLayingFormProps {
|
|
||||||
type?: 'add' | 'edit' | 'detail';
|
|
||||||
initialValues?: TransferToLaying;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TransferToLayingForm = ({
|
|
||||||
type = 'add',
|
|
||||||
initialValues,
|
|
||||||
}: TransferToLayingFormProps) => {
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
// Modal hooks
|
|
||||||
const deleteModal = useModal();
|
|
||||||
const approveModal = useModal();
|
|
||||||
const rejectModal = useModal();
|
|
||||||
|
|
||||||
const [formErrorMessage, setFormErrorMessage] = useState('');
|
|
||||||
|
|
||||||
// Modal loading state
|
|
||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
|
||||||
const [isApproveLoading, setIsApproveLoading] = useState(false);
|
|
||||||
const [isRejectLoading, setIsRejectLoading] = useState(false);
|
|
||||||
|
|
||||||
const { data: approvalHistory, isLoading: isLoadingApprovalHistory } = useSWR(
|
|
||||||
type === 'detail' && initialValues ? [String(initialValues.id)] : null,
|
|
||||||
([id]: string[]) => TransferToLayingApi.getApprovalHistory(Number(id))
|
|
||||||
);
|
|
||||||
|
|
||||||
const createTransferToLayingHandler = useCallback(
|
|
||||||
async (payload: CreateTransferToLayingPayload) => {
|
|
||||||
const createTransferToLayingRes =
|
|
||||||
await TransferToLayingApi.create(payload);
|
|
||||||
|
|
||||||
if (isResponseError(createTransferToLayingRes)) {
|
|
||||||
setFormErrorMessage(createTransferToLayingRes.message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
toast.success(createTransferToLayingRes?.message as string);
|
|
||||||
router.push('/production/transfer-to-laying');
|
|
||||||
},
|
|
||||||
[router]
|
|
||||||
);
|
|
||||||
|
|
||||||
const updateTransferToLayingHandler = useCallback(
|
|
||||||
async (
|
|
||||||
transferToLayingId: number,
|
|
||||||
payload: UpdateTransferToLayingPayload
|
|
||||||
) => {
|
|
||||||
const updateKandangRes = await TransferToLayingApi.update(
|
|
||||||
transferToLayingId,
|
|
||||||
payload
|
|
||||||
);
|
|
||||||
|
|
||||||
if (updateKandangRes?.status === 'error') {
|
|
||||||
setFormErrorMessage(updateKandangRes.message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
toast.success(updateKandangRes?.message as string);
|
|
||||||
router.refresh();
|
|
||||||
router.push('/production/transfer-to-laying');
|
|
||||||
},
|
|
||||||
[router]
|
|
||||||
);
|
|
||||||
|
|
||||||
// const formikInitialValues = useMemo<TransferToLayingFormValues>(() => {
|
|
||||||
// return getTransferToLayingFormInitialValues(initialValues);
|
|
||||||
// }, [initialValues]);
|
|
||||||
|
|
||||||
const [formikInitialValues, setFormikInitialValues] = useState(
|
|
||||||
getTransferToLayingFormInitialValues()
|
|
||||||
);
|
|
||||||
|
|
||||||
const formik = useFormik<TransferToLayingFormValues>({
|
|
||||||
initialValues: formikInitialValues,
|
|
||||||
validationSchema:
|
|
||||||
type === 'edit'
|
|
||||||
? UpdateTransferToLayingFormSchema
|
|
||||||
: TransferToLayingFormSchema,
|
|
||||||
onSubmit: async (values) => {
|
|
||||||
setFormErrorMessage('');
|
|
||||||
|
|
||||||
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 (type) {
|
|
||||||
case 'add':
|
|
||||||
await createTransferToLayingHandler(transferToLayingPayload);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'edit':
|
|
||||||
await updateTransferToLayingHandler(
|
|
||||||
initialValues?.id as number,
|
|
||||||
transferToLayingPayload
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const { setValues: formikSetValues, values: formikValues } = formik;
|
|
||||||
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);
|
|
||||||
const {
|
|
||||||
flockSourceKandangs: flockSourceKandangsValue,
|
|
||||||
flockDestinationKandangs: flockDestinationKandangsValue,
|
|
||||||
totalQuantity,
|
|
||||||
} = formikValues;
|
|
||||||
|
|
||||||
const deleteTransferToLayingClickHandler = () => {
|
|
||||||
deleteModal.openModal();
|
|
||||||
};
|
|
||||||
|
|
||||||
const approveClickHandler = () => {
|
|
||||||
approveModal.openModal();
|
|
||||||
};
|
|
||||||
|
|
||||||
const rejectClickHandler = () => {
|
|
||||||
rejectModal.openModal();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Modal confirm click handler
|
|
||||||
const confirmationModalDeleteClickHandler = async () => {
|
|
||||||
setIsDeleteLoading(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await TransferToLayingApi.delete(initialValues?.id as number);
|
|
||||||
|
|
||||||
toast.success('Berhasil menghapus data transfer ke laying!');
|
|
||||||
router.push('/production/transfer-to-laying');
|
|
||||||
} catch (error) {
|
|
||||||
toast.success('Gagal menghapus data transfer ke laying!');
|
|
||||||
} finally {
|
|
||||||
deleteModal.closeModal();
|
|
||||||
setIsDeleteLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const confirmationModalApproveClickHandler = async (notes: string) => {
|
|
||||||
setIsApproveLoading(true);
|
|
||||||
|
|
||||||
const approveResponse = await TransferToLayingApi.approve(
|
|
||||||
initialValues?.id as number,
|
|
||||||
notes
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isResponseSuccess(approveResponse)) {
|
|
||||||
approveModal.closeModal();
|
|
||||||
|
|
||||||
toast.success('Berhasil approve data transfer ke laying!');
|
|
||||||
router.push('/production/transfer-to-laying');
|
|
||||||
} else {
|
|
||||||
approveModal.closeModal();
|
|
||||||
|
|
||||||
toast.error('Gagal approve data transfer ke laying!');
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsApproveLoading(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const confirmationModalRejectClickHandler = async (notes: string) => {
|
|
||||||
setIsRejectLoading(true);
|
|
||||||
|
|
||||||
const rejectResponse = await TransferToLayingApi.reject(
|
|
||||||
initialValues?.id as number,
|
|
||||||
notes
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isResponseSuccess(rejectResponse)) {
|
|
||||||
rejectModal.closeModal();
|
|
||||||
|
|
||||||
toast.success('Berhasil reject data transfer ke laying!');
|
|
||||||
router.push('/production/transfer-to-laying');
|
|
||||||
} else {
|
|
||||||
rejectModal.closeModal();
|
|
||||||
|
|
||||||
toast.error('Gagal reject data transfer ke laying!');
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsRejectLoading(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// flock source
|
|
||||||
const isFlockSourceKandangsRepeaterInputError = (
|
|
||||||
column: keyof TransferToLayingFormValues['flockSourceKandangs'][0],
|
|
||||||
idx: number
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
formik.touched.flockSourceKandangs?.[idx]?.[column] &&
|
|
||||||
Boolean(
|
|
||||||
formik.errors.flockSourceKandangs?.[idx] instanceof Object &&
|
|
||||||
formik.errors.flockSourceKandangs?.[idx]?.[column]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const flockSourceKandangsRepeaterInputErrorMessage = (
|
|
||||||
column: keyof TransferToLayingFormValues['flockSourceKandangs'][0],
|
|
||||||
idx: number
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
formik.errors.flockSourceKandangs?.[idx] as Record<string, string>
|
|
||||||
)?.[column];
|
|
||||||
};
|
|
||||||
|
|
||||||
const {
|
|
||||||
setInputValue: setFlockSourceInputValue,
|
|
||||||
options: flockSourceOptions,
|
|
||||||
isLoadingOptions: isLoadingFlockSourceOptions,
|
|
||||||
rawData: flockSources,
|
|
||||||
loadMore: loadMoreFlockSource,
|
|
||||||
hasMore: hasMoreFlockSource,
|
|
||||||
} = useSelect<ProjectFlock>(
|
|
||||||
'/production/project-flocks',
|
|
||||||
'id',
|
|
||||||
'flock_name',
|
|
||||||
'search',
|
|
||||||
{
|
|
||||||
category: 'GROWING',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const flockSourceChangeHandler = async (
|
|
||||||
val: OptionType | OptionType[] | null
|
|
||||||
) => {
|
|
||||||
// Get flock source data for total quantity and kandang
|
|
||||||
const flockSource =
|
|
||||||
isResponseSuccess(flockSources) && val !== null
|
|
||||||
? flockSources.data.find(
|
|
||||||
(item) => item.id === (val as OptionType).value
|
|
||||||
)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
// Set total quantity and kandangs
|
|
||||||
if (flockSource) {
|
|
||||||
const mappedFlockKandangsAvailableQty =
|
|
||||||
await TransferToLayingApi.getMappedFlockKandangsAvailability(
|
|
||||||
flockSource.id
|
|
||||||
);
|
|
||||||
|
|
||||||
const formattedKandangs = flockSource.kandangs.map((item) => ({
|
|
||||||
kandang: {
|
|
||||||
value: item.project_flock_kandang_id,
|
|
||||||
label: item.name,
|
|
||||||
},
|
|
||||||
quantity: '',
|
|
||||||
maxQuantity:
|
|
||||||
(mappedFlockKandangsAvailableQty &&
|
|
||||||
mappedFlockKandangsAvailableQty[item.project_flock_kandang_id]
|
|
||||||
.available_qty) ??
|
|
||||||
0,
|
|
||||||
}));
|
|
||||||
|
|
||||||
let maxTotalQuantity = 0;
|
|
||||||
// flockSource.kandangs.forEach((item) => {
|
|
||||||
// maxTotalQuantity += item.capacity;
|
|
||||||
// });
|
|
||||||
formattedKandangs.forEach((item) => {
|
|
||||||
maxTotalQuantity += item.maxQuantity;
|
|
||||||
});
|
|
||||||
|
|
||||||
formik.setFieldValue('totalQuantity', '');
|
|
||||||
formik.setFieldValue('maxTotalQuantity', maxTotalQuantity);
|
|
||||||
formik.setFieldValue('flockSourceKandangs', formattedKandangs);
|
|
||||||
} else {
|
|
||||||
formik.setFieldValue('totalQuantity', undefined);
|
|
||||||
formik.setFieldValue('flockSourceKandangs', undefined);
|
|
||||||
formik.setFieldValue('reason', '');
|
|
||||||
}
|
|
||||||
|
|
||||||
formik.setFieldTouched('flockSource', true);
|
|
||||||
formik.setFieldValue('flockSource', val);
|
|
||||||
};
|
|
||||||
|
|
||||||
// flock destination
|
|
||||||
const isFlockDestinationKandangsRepeaterInputError = (
|
|
||||||
column: keyof TransferToLayingFormValues['flockDestinationKandangs'][0],
|
|
||||||
idx: number
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
formik.touched.flockDestinationKandangs?.[idx]?.[column] &&
|
|
||||||
Boolean(
|
|
||||||
formik.errors.flockDestinationKandangs?.[idx] instanceof Object &&
|
|
||||||
formik.errors.flockDestinationKandangs?.[idx]?.[column]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const flockDestinationKandangsRepeaterInputErrorMessage = (
|
|
||||||
column: keyof TransferToLayingFormValues['flockDestinationKandangs'][0],
|
|
||||||
idx: number
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
formik.errors.flockDestinationKandangs?.[idx] as Record<string, string>
|
|
||||||
)?.[column];
|
|
||||||
};
|
|
||||||
|
|
||||||
const {
|
|
||||||
setInputValue: setFlockDestinationInputValue,
|
|
||||||
options: flockDestinationOptions,
|
|
||||||
isLoadingOptions: isLoadingFlockDestinationOptions,
|
|
||||||
rawData: flockDestinations,
|
|
||||||
loadMore: loadMoreFlockDestination,
|
|
||||||
hasMore: hasMoreFlockDestination,
|
|
||||||
} = useSelect<ProjectFlock>(
|
|
||||||
'/production/project-flocks',
|
|
||||||
'id',
|
|
||||||
'flock_name',
|
|
||||||
'search',
|
|
||||||
{
|
|
||||||
category: 'LAYING',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const flockDestinationChangeHandler = (
|
|
||||||
val: OptionType | OptionType[] | null
|
|
||||||
) => {
|
|
||||||
// Get flock destination data for total quantity and kandang
|
|
||||||
const flockDestination =
|
|
||||||
isResponseSuccess(flockDestinations) && val !== null
|
|
||||||
? flockDestinations.data.find(
|
|
||||||
(item) => item.id === (val as OptionType).value
|
|
||||||
)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
// Set total quantity and kandangs
|
|
||||||
if (flockDestination) {
|
|
||||||
const formattedKandangs = flockDestination.kandangs.map((item) => ({
|
|
||||||
kandang: {
|
|
||||||
value: item.project_flock_kandang_id,
|
|
||||||
label: item.name,
|
|
||||||
},
|
|
||||||
quantity: '',
|
|
||||||
|
|
||||||
// TODO: integrate this later to real kandang capacity API
|
|
||||||
// maxQuantity: item.capacity ?? 0,
|
|
||||||
maxQuantity: item.capacity ?? Infinity,
|
|
||||||
}));
|
|
||||||
|
|
||||||
formik.setFieldValue('flockDestinationKandangs', formattedKandangs);
|
|
||||||
}
|
|
||||||
|
|
||||||
formik.setFieldTouched('flockDestination', true);
|
|
||||||
formik.setFieldValue('flockDestination', val);
|
|
||||||
};
|
|
||||||
|
|
||||||
const isShowApproveRejectButton =
|
|
||||||
initialValues &&
|
|
||||||
initialValues?.approval?.step_number === 1 &&
|
|
||||||
initialValues?.approval.action !== 'REJECTED';
|
|
||||||
|
|
||||||
const isShowDeleteButton =
|
|
||||||
initialValues &&
|
|
||||||
initialValues?.approval.action !== 'REJECTED' &&
|
|
||||||
initialValues?.approval.action !== 'APPROVED';
|
|
||||||
|
|
||||||
const isShowEditButton = isShowDeleteButton;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const getFilledInitialValues = async () => {
|
|
||||||
if (initialValues) {
|
|
||||||
const filledInitialValues =
|
|
||||||
await getFilledTransferToLayingFormInitialValues(initialValues);
|
|
||||||
|
|
||||||
setFormikInitialValues(filledInitialValues);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
getFilledInitialValues();
|
|
||||||
}, [initialValues, setFormikInitialValues]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
formikSetValues(formikInitialValues);
|
|
||||||
}, [formikSetValues, formikInitialValues]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// calculate total quantity if kandangs quantity change
|
|
||||||
if (flockSourceKandangsValue && flockSourceKandangsValue.length > 0) {
|
|
||||||
let newTotalQuantity = 0;
|
|
||||||
|
|
||||||
flockSourceKandangsValue.forEach((item) => {
|
|
||||||
newTotalQuantity += parseFloat(item.quantity as string);
|
|
||||||
});
|
|
||||||
|
|
||||||
formik.setFieldValue('totalQuantity', newTotalQuantity);
|
|
||||||
formik.validateField('totalQuantity');
|
|
||||||
}
|
|
||||||
}, [formikSetValues, flockSourceKandangsValue]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// calculate total quantity if kandangs quantity change
|
|
||||||
if (
|
|
||||||
flockDestinationKandangsValue &&
|
|
||||||
flockDestinationKandangsValue.length > 0
|
|
||||||
) {
|
|
||||||
let destinationKandangsTotalQuantity = 0;
|
|
||||||
|
|
||||||
flockDestinationKandangsValue.forEach((item) => {
|
|
||||||
destinationKandangsTotalQuantity += parseFloat(item.quantity as string);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (
|
|
||||||
destinationKandangsTotalQuantity > parseFloat(String(totalQuantity))
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [formikSetValues, flockDestinationKandangsValue]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<section className='w-full max-w-3xl'>
|
|
||||||
<header className='flex flex-col gap-4'>
|
|
||||||
<Button
|
|
||||||
href='/production/transfer-to-laying'
|
|
||||||
variant='link'
|
|
||||||
className='w-fit p-0 text-primary'
|
|
||||||
>
|
|
||||||
<Icon icon='uil:arrow-left' width={24} height={24} />
|
|
||||||
Kembali
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<h1 className='text-2xl font-bold text-center'>
|
|
||||||
{type === 'add' && 'Tambah Transfer ke Laying'}
|
|
||||||
{type === 'edit' && 'Edit Transfer ke Laying'}
|
|
||||||
{type === 'detail' && 'Detail Transfer ke Laying'}
|
|
||||||
</h1>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{type === 'detail' &&
|
|
||||||
initialValues &&
|
|
||||||
!isLoadingApprovalHistory &&
|
|
||||||
isResponseSuccess(approvalHistory) && (
|
|
||||||
<div className='w-full my-4'>
|
|
||||||
<ApprovalSteps
|
|
||||||
approvals={formatGroupedApprovalsToApprovalSteps(
|
|
||||||
TRANSFER_TO_LAYING_APPROVAL_LINE,
|
|
||||||
approvalHistory.data,
|
|
||||||
initialValues.approval
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className='w-full my-4 flex flex-row justify-between gap-2'>
|
|
||||||
{type === 'detail' && (
|
|
||||||
<>
|
|
||||||
{isShowApproveRejectButton && (
|
|
||||||
<div className='w-full flex flex-row justify-end gap-2'>
|
|
||||||
<RequirePermission permissions='lti.production.transfer_to_laying.approve'>
|
|
||||||
<Button
|
|
||||||
variant='outline'
|
|
||||||
color='success'
|
|
||||||
onClick={approveClickHandler}
|
|
||||||
className='w-full sm:w-fit'
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
icon='material-symbols:check'
|
|
||||||
width={24}
|
|
||||||
height={24}
|
|
||||||
/>
|
|
||||||
Approve
|
|
||||||
</Button>
|
|
||||||
</RequirePermission>
|
|
||||||
|
|
||||||
<RequirePermission permissions='lti.production.transfer_to_laying.approve'>
|
|
||||||
<Button
|
|
||||||
variant='outline'
|
|
||||||
color='error'
|
|
||||||
onClick={rejectClickHandler}
|
|
||||||
className='w-full sm:w-fit'
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
icon='material-symbols:close'
|
|
||||||
width={24}
|
|
||||||
height={24}
|
|
||||||
/>
|
|
||||||
Reject
|
|
||||||
</Button>
|
|
||||||
</RequirePermission>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form
|
|
||||||
onSubmit={handleFormSubmit}
|
|
||||||
onReset={formik.handleReset}
|
|
||||||
className='w-full flex flex-col gap-6'
|
|
||||||
>
|
|
||||||
<div className='flex flex-col gap-4'>
|
|
||||||
<DateInput
|
|
||||||
required
|
|
||||||
label='Tanggal Transfer'
|
|
||||||
name='transfer_date'
|
|
||||||
placeholder='Masukkan tanggal transfer'
|
|
||||||
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}
|
|
||||||
readOnly={type === 'detail'}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className='flex flex-col sm:flex-row gap-4'>
|
|
||||||
<SelectInput
|
|
||||||
required
|
|
||||||
label='Flock Asal'
|
|
||||||
placeholder='Flock asal'
|
|
||||||
value={formik.values.flockSource as OptionType}
|
|
||||||
options={flockSourceOptions}
|
|
||||||
onChange={flockSourceChangeHandler}
|
|
||||||
isLoading={isLoadingFlockSourceOptions}
|
|
||||||
onInputChange={setFlockSourceInputValue}
|
|
||||||
onMenuScrollToBottom={loadMoreFlockSource}
|
|
||||||
isError={
|
|
||||||
formik.touched.flockSource &&
|
|
||||||
Boolean(typeof formik.errors.flockSource === 'string')
|
|
||||||
}
|
|
||||||
errorMessage={formik.errors.flockSource as string}
|
|
||||||
isDisabled={type === 'detail'}
|
|
||||||
isClearable
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SelectInput
|
|
||||||
required
|
|
||||||
label='Flock Tujuan'
|
|
||||||
placeholder='Flock tujuan'
|
|
||||||
value={formik.values.flockDestination as OptionType}
|
|
||||||
options={flockDestinationOptions}
|
|
||||||
onChange={flockDestinationChangeHandler}
|
|
||||||
isLoading={isLoadingFlockDestinationOptions}
|
|
||||||
onInputChange={setFlockDestinationInputValue}
|
|
||||||
onMenuScrollToBottom={loadMoreFlockDestination}
|
|
||||||
isError={
|
|
||||||
formik.touched.flockDestination &&
|
|
||||||
Boolean(typeof formik.errors.flockDestination === 'string')
|
|
||||||
}
|
|
||||||
errorMessage={formik.errors.flockDestination as string}
|
|
||||||
isDisabled={type === 'detail'}
|
|
||||||
isClearable
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<NumberInput
|
|
||||||
required
|
|
||||||
name='totalQuantity'
|
|
||||||
label='Jumlah Transfer'
|
|
||||||
bottomLabel={
|
|
||||||
formikValues.maxTotalQuantity
|
|
||||||
? `Max: ${formikValues.maxTotalQuantity}`
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
placeholder='Masukkan jumlah transfer'
|
|
||||||
value={
|
|
||||||
formik.values.totalQuantity ? formik.values.totalQuantity : ''
|
|
||||||
}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
onBlur={formik.handleBlur}
|
|
||||||
isError={
|
|
||||||
formik.touched.totalQuantity &&
|
|
||||||
Boolean(formik.errors.totalQuantity)
|
|
||||||
}
|
|
||||||
errorMessage={formik.errors.totalQuantity}
|
|
||||||
disabled
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className='flex flex-col gap-4'>
|
|
||||||
<div className='overflow-x-auto'>
|
|
||||||
<table className='table'>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Kandang Flock Asal</th>
|
|
||||||
<th>Kuantitas</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
{(!formik.values.flockSourceKandangs ||
|
|
||||||
formik.values.flockSourceKandangs.length === 0) && (
|
|
||||||
<tr>
|
|
||||||
<td colSpan={2}>
|
|
||||||
<p className='w-full text-center text-gray-400'>
|
|
||||||
Pilih flock asal terlebih dahulu!
|
|
||||||
</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{formik.values.flockSourceKandangs &&
|
|
||||||
formik.values.flockSourceKandangs.map((kandang, idx) => (
|
|
||||||
<tr key={idx}>
|
|
||||||
<td>
|
|
||||||
<SelectInput
|
|
||||||
value={kandang.kandang}
|
|
||||||
options={[]}
|
|
||||||
isDisabled
|
|
||||||
className={{
|
|
||||||
wrapper: 'min-w-52',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td>
|
|
||||||
<NumberInput
|
|
||||||
required
|
|
||||||
name={`flockSourceKandangs[${idx}].quantity`}
|
|
||||||
bottomLabel={
|
|
||||||
kandang.maxQuantity
|
|
||||||
? `Max: ${kandang.maxQuantity}`
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
placeholder='Masukkan kuantitas'
|
|
||||||
value={kandang.quantity}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
onBlur={formik.handleBlur}
|
|
||||||
isError={isFlockSourceKandangsRepeaterInputError(
|
|
||||||
'quantity',
|
|
||||||
idx
|
|
||||||
)}
|
|
||||||
errorMessage={flockSourceKandangsRepeaterInputErrorMessage(
|
|
||||||
'quantity',
|
|
||||||
idx
|
|
||||||
)}
|
|
||||||
readOnly={type === 'detail'}
|
|
||||||
className={{
|
|
||||||
wrapper: 'min-w-52',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='overflow-x-auto'>
|
|
||||||
<table className='table'>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Kandang Flock Tujuan</th>
|
|
||||||
<th>Kuantitas</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
{(!formik.values.flockDestinationKandangs ||
|
|
||||||
formik.values.flockDestinationKandangs.length === 0) && (
|
|
||||||
<tr>
|
|
||||||
<td colSpan={2}>
|
|
||||||
<p className='w-full text-center text-gray-400'>
|
|
||||||
Pilih flock tujuan terlebih dahulu!
|
|
||||||
</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{formik.values.flockDestinationKandangs &&
|
|
||||||
formik.values.flockDestinationKandangs.map(
|
|
||||||
(kandang, idx) => (
|
|
||||||
<tr key={idx}>
|
|
||||||
<td>
|
|
||||||
<SelectInput
|
|
||||||
value={kandang.kandang}
|
|
||||||
options={[]}
|
|
||||||
isDisabled
|
|
||||||
className={{
|
|
||||||
wrapper: 'min-w-52',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td>
|
|
||||||
<NumberInput
|
|
||||||
required
|
|
||||||
name={`flockDestinationKandangs[${idx}].quantity`}
|
|
||||||
bottomLabel={
|
|
||||||
kandang.maxQuantity
|
|
||||||
? `Max: ${kandang.maxQuantity}`
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
placeholder='Masukkan kuantitas'
|
|
||||||
value={kandang.quantity}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
onBlur={formik.handleBlur}
|
|
||||||
isError={isFlockDestinationKandangsRepeaterInputError(
|
|
||||||
'quantity',
|
|
||||||
idx
|
|
||||||
)}
|
|
||||||
errorMessage={flockDestinationKandangsRepeaterInputErrorMessage(
|
|
||||||
'quantity',
|
|
||||||
idx
|
|
||||||
)}
|
|
||||||
readOnly={type === 'detail'}
|
|
||||||
className={{
|
|
||||||
wrapper: 'min-w-52',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<TextArea
|
|
||||||
required
|
|
||||||
rows={5}
|
|
||||||
name='reason'
|
|
||||||
label='Alasan Transfer'
|
|
||||||
placeholder='Alasan transfer'
|
|
||||||
value={formik.values.reason}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
onBlur={formik.handleBlur}
|
|
||||||
isError={formik.touched.reason && Boolean(formik.errors.reason)}
|
|
||||||
errorMessage={formik.errors.reason}
|
|
||||||
readOnly={type === 'detail'}
|
|
||||||
disabled={Boolean(formik.errors.flockSource)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
|
||||||
|
|
||||||
{formErrorMessage && (
|
|
||||||
<div role='alert' className='alert alert-error w-full'>
|
|
||||||
<Icon
|
|
||||||
icon='material-symbols:error-outline'
|
|
||||||
width={24}
|
|
||||||
height={24}
|
|
||||||
/>
|
|
||||||
<span>{formErrorMessage}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className='flex flex-row justify-between gap-2 flex-wrap'>
|
|
||||||
{type !== 'add' && (
|
|
||||||
<div className='flex flex-row justify-start gap-2'>
|
|
||||||
{isShowDeleteButton && (
|
|
||||||
<RequirePermission permissions='lti.production.transfer_to_laying.delete'>
|
|
||||||
<Button
|
|
||||||
type='button'
|
|
||||||
color='error'
|
|
||||||
onClick={deleteTransferToLayingClickHandler}
|
|
||||||
className='px-4'
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
icon='material-symbols:delete-outline-rounded'
|
|
||||||
width={24}
|
|
||||||
height={24}
|
|
||||||
className='justify-start text-sm'
|
|
||||||
/>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
</RequirePermission>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{type !== 'edit' && isShowEditButton && (
|
|
||||||
<RequirePermission permissions='lti.production.transfer_to_laying.update'>
|
|
||||||
<Button
|
|
||||||
type='button'
|
|
||||||
color='warning'
|
|
||||||
href={`/production/transfer-to-laying/detail/edit/?transferToLayingId=${initialValues?.id}`}
|
|
||||||
className='px-4'
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
icon='material-symbols:edit-outline'
|
|
||||||
width={24}
|
|
||||||
height={24}
|
|
||||||
className='justify-start text-sm'
|
|
||||||
/>
|
|
||||||
Edit
|
|
||||||
</Button>
|
|
||||||
</RequirePermission>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{type !== 'detail' && (
|
|
||||||
<div
|
|
||||||
className={cn('flex flex-row justify-end gap-2', {
|
|
||||||
'w-full': type === 'add',
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Button type='reset' color='warning' className='px-4'>
|
|
||||||
Reset
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<RequirePermission
|
|
||||||
permissions={
|
|
||||||
type === 'add'
|
|
||||||
? 'lti.production.transfer_to_laying.create'
|
|
||||||
: 'lti.production.transfer_to_laying.update'
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
type='submit'
|
|
||||||
color='primary'
|
|
||||||
isLoading={formik.isSubmitting}
|
|
||||||
disabled={formik.isSubmitting}
|
|
||||||
className='px-4'
|
|
||||||
>
|
|
||||||
Submit
|
|
||||||
</Button>
|
|
||||||
</RequirePermission>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{type !== 'add' && (
|
|
||||||
<ConfirmationModal
|
|
||||||
ref={deleteModal.ref}
|
|
||||||
type='error'
|
|
||||||
text='Apakah anda yakin ingin menghapus data transfer ke laying ini?'
|
|
||||||
secondaryButton={{
|
|
||||||
text: 'Tidak',
|
|
||||||
}}
|
|
||||||
primaryButton={{
|
|
||||||
text: 'Ya',
|
|
||||||
color: 'error',
|
|
||||||
isLoading: isDeleteLoading,
|
|
||||||
onClick: confirmationModalDeleteClickHandler,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{type === 'detail' && (
|
|
||||||
<>
|
|
||||||
<ConfirmationModalWithNotes
|
|
||||||
ref={approveModal.ref}
|
|
||||||
type='success'
|
|
||||||
text='Apakah anda yakin ingin approve data transfer ke laying ini?'
|
|
||||||
secondaryButton={{
|
|
||||||
text: 'Tidak',
|
|
||||||
}}
|
|
||||||
primaryButton={{
|
|
||||||
text: 'Ya',
|
|
||||||
color: 'success',
|
|
||||||
isLoading: isApproveLoading,
|
|
||||||
onClick: confirmationModalApproveClickHandler,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ConfirmationModalWithNotes
|
|
||||||
ref={rejectModal.ref}
|
|
||||||
type='error'
|
|
||||||
text='Apakah anda yakin ingin reject data transfer ke laying ini?'
|
|
||||||
secondaryButton={{
|
|
||||||
text: 'Tidak',
|
|
||||||
}}
|
|
||||||
primaryButton={{
|
|
||||||
text: 'Ya',
|
|
||||||
color: 'error',
|
|
||||||
isLoading: isRejectLoading,
|
|
||||||
onClick: confirmationModalRejectClickHandler,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TransferToLayingForm;
|
|
||||||
Reference in New Issue
Block a user