mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-23 23:05:46 +00:00
feat(FE-149): integrate TransferToLayingForm to API
This commit is contained in:
+404
-187
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { toast } from 'react-hot-toast';
|
import { toast } from 'react-hot-toast';
|
||||||
@@ -8,16 +8,23 @@ import useSWR from 'swr';
|
|||||||
|
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import TextInput from '@/components/input/TextInput';
|
|
||||||
import SelectInput, {
|
import SelectInput, {
|
||||||
OptionType,
|
OptionType,
|
||||||
// useSelect,
|
useSelect,
|
||||||
} from '@/components/input/SelectInput';
|
} from '@/components/input/SelectInput';
|
||||||
import TextArea from '@/components/input/TextArea';
|
import TextArea from '@/components/input/TextArea';
|
||||||
import { useModal } from '@/components/Modal';
|
import { useModal } from '@/components/Modal';
|
||||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
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 {
|
import {
|
||||||
|
getFilledTransferToLayingFormInitialValues,
|
||||||
|
getTransferToLayingFormInitialValues,
|
||||||
TransferToLayingFormSchema,
|
TransferToLayingFormSchema,
|
||||||
TransferToLayingFormValues,
|
TransferToLayingFormValues,
|
||||||
UpdateTransferToLayingFormSchema,
|
UpdateTransferToLayingFormSchema,
|
||||||
@@ -31,6 +38,8 @@ import {
|
|||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
|
|
||||||
import { TransferToLayingApi } from '@/services/api/production/transfer-to-laying';
|
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';
|
||||||
|
|
||||||
interface TransferToLayingFormProps {
|
interface TransferToLayingFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -55,11 +64,23 @@ const TransferToLayingForm = ({
|
|||||||
const [isApproveLoading, setIsApproveLoading] = useState(false);
|
const [isApproveLoading, setIsApproveLoading] = useState(false);
|
||||||
const [isRejectLoading, setIsRejectLoading] = 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(
|
const createTransferToLayingHandler = useCallback(
|
||||||
async (payload: CreateTransferToLayingPayload) => {
|
async (payload: CreateTransferToLayingPayload) => {
|
||||||
console.log('Create transfer to laying:', { payload });
|
const createTransferToLayingRes =
|
||||||
|
await TransferToLayingApi.create(payload);
|
||||||
|
|
||||||
toast.success('Berhasil menambahkan data transfer ke laying!');
|
if (isResponseError(createTransferToLayingRes)) {
|
||||||
|
setFormErrorMessage(createTransferToLayingRes.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.success(createTransferToLayingRes?.message as string);
|
||||||
|
router.push('/production/transfer-to-laying');
|
||||||
},
|
},
|
||||||
[router]
|
[router]
|
||||||
);
|
);
|
||||||
@@ -69,46 +90,30 @@ const TransferToLayingForm = ({
|
|||||||
transferToLayingId: number,
|
transferToLayingId: number,
|
||||||
payload: UpdateTransferToLayingPayload
|
payload: UpdateTransferToLayingPayload
|
||||||
) => {
|
) => {
|
||||||
console.log(
|
const updateKandangRes = await TransferToLayingApi.update(
|
||||||
`Update transfer to laying with ID of ${transferToLayingId}:`,
|
transferToLayingId,
|
||||||
{ payload }
|
payload
|
||||||
);
|
);
|
||||||
|
|
||||||
toast.success('Berhasil mengubah data transfer ke laying!');
|
if (updateKandangRes?.status === 'error') {
|
||||||
|
setFormErrorMessage(updateKandangRes.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.success(updateKandangRes?.message as string);
|
||||||
|
router.refresh();
|
||||||
|
router.push('/production/transfer-to-laying');
|
||||||
},
|
},
|
||||||
[router]
|
[router]
|
||||||
);
|
);
|
||||||
|
|
||||||
const formikInitialValues = useMemo<TransferToLayingFormValues>(() => {
|
// const formikInitialValues = useMemo<TransferToLayingFormValues>(() => {
|
||||||
return {
|
// return getTransferToLayingFormInitialValues(initialValues);
|
||||||
transfer_date: initialValues?.transfer_date ?? '',
|
// }, [initialValues]);
|
||||||
flockSource: initialValues?.flock_source
|
|
||||||
? {
|
|
||||||
value: initialValues?.flock_source.id,
|
|
||||||
label: initialValues?.flock_source.name,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
flockDestination: initialValues?.flock_destination
|
|
||||||
? {
|
|
||||||
value: initialValues?.flock_destination.id,
|
|
||||||
label: initialValues?.flock_destination.name,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
totalQuantity: initialValues?.quantity ?? undefined,
|
|
||||||
|
|
||||||
kandangs: initialValues?.kandangs
|
const [formikInitialValues, setFormikInitialValues] = useState(
|
||||||
? initialValues.kandangs.map((kandang) => ({
|
getTransferToLayingFormInitialValues()
|
||||||
kandang: {
|
);
|
||||||
value: kandang.kandang.id,
|
|
||||||
label: kandang.kandang.name,
|
|
||||||
},
|
|
||||||
quantity: kandang.quantity,
|
|
||||||
}))
|
|
||||||
: [],
|
|
||||||
|
|
||||||
reason: initialValues?.reason ?? undefined,
|
|
||||||
};
|
|
||||||
}, [initialValues]);
|
|
||||||
|
|
||||||
const formik = useFormik<TransferToLayingFormValues>({
|
const formik = useFormik<TransferToLayingFormValues>({
|
||||||
initialValues: formikInitialValues,
|
initialValues: formikInitialValues,
|
||||||
@@ -117,23 +122,23 @@ const TransferToLayingForm = ({
|
|||||||
? UpdateTransferToLayingFormSchema
|
? UpdateTransferToLayingFormSchema
|
||||||
: TransferToLayingFormSchema,
|
: TransferToLayingFormSchema,
|
||||||
onSubmit: async (values) => {
|
onSubmit: async (values) => {
|
||||||
console.log({ values });
|
|
||||||
|
|
||||||
setFormErrorMessage('');
|
setFormErrorMessage('');
|
||||||
|
|
||||||
const transferToLayingPayload: CreateTransferToLayingPayload = {
|
const transferToLayingPayload: CreateTransferToLayingPayload = {
|
||||||
transfer_date: values.transfer_date as string,
|
transfer_date: values.transfer_date as string,
|
||||||
flock_source_id: values.flockSource?.value as number,
|
source_project_flock_id: values.flockSource?.value as number,
|
||||||
flock_destination_id: values.flockDestination?.value as number,
|
target_project_flock_id: values.flockDestination?.value as number,
|
||||||
totalQuantity: values.totalQuantity as number,
|
totalQuantity: values.totalQuantity as number,
|
||||||
|
|
||||||
kandangs: values.kandangs?.map((kandang) => ({
|
source_kandangs: values.flockSourceKandangs?.map((kandang) => ({
|
||||||
kandang_id: kandang.kandang.value,
|
project_flock_kandang_id: kandang.kandang.value,
|
||||||
quantity: kandang.quantity,
|
quantity: parseFloat(kandang.quantity as string),
|
||||||
})) as {
|
})) as CreateTransferToLayingPayload['source_kandangs'],
|
||||||
kandang_id: number;
|
|
||||||
quantity: number;
|
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,
|
reason: values.reason as string,
|
||||||
};
|
};
|
||||||
@@ -154,7 +159,11 @@ const TransferToLayingForm = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { setValues: formikSetValues, values: formikValues } = formik;
|
const { setValues: formikSetValues, values: formikValues } = formik;
|
||||||
const { kandangs: kandangsValue } = formikValues;
|
const {
|
||||||
|
flockSourceKandangs: flockSourceKandangsValue,
|
||||||
|
flockDestinationKandangs: flockDestinationKandangsValue,
|
||||||
|
totalQuantity,
|
||||||
|
} = formikValues;
|
||||||
|
|
||||||
const deleteTransferToLayingClickHandler = () => {
|
const deleteTransferToLayingClickHandler = () => {
|
||||||
deleteModal.openModal();
|
deleteModal.openModal();
|
||||||
@@ -172,24 +181,32 @@ const TransferToLayingForm = ({
|
|||||||
const confirmationModalDeleteClickHandler = async () => {
|
const confirmationModalDeleteClickHandler = async () => {
|
||||||
setIsDeleteLoading(true);
|
setIsDeleteLoading(true);
|
||||||
|
|
||||||
// TODO: delete data and integrate to real API
|
try {
|
||||||
deleteModal.closeModal();
|
await TransferToLayingApi.delete(initialValues?.id as number);
|
||||||
toast.success('Berhasil menghapus data transfer ke laying!');
|
|
||||||
|
|
||||||
setIsDeleteLoading(false);
|
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 () => {
|
const confirmationModalApproveClickHandler = async (notes: string) => {
|
||||||
setIsApproveLoading(true);
|
setIsApproveLoading(true);
|
||||||
|
|
||||||
const approveResponse = await TransferToLayingApi.approve(
|
const approveResponse = await TransferToLayingApi.approve(
|
||||||
initialValues?.id as number
|
initialValues?.id as number,
|
||||||
|
notes
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isResponseSuccess(approveResponse)) {
|
if (isResponseSuccess(approveResponse)) {
|
||||||
approveModal.closeModal();
|
approveModal.closeModal();
|
||||||
|
|
||||||
toast.success('Berhasil approve data transfer ke laying!');
|
toast.success('Berhasil approve data transfer ke laying!');
|
||||||
|
router.push('/production/transfer-to-laying');
|
||||||
} else {
|
} else {
|
||||||
approveModal.closeModal();
|
approveModal.closeModal();
|
||||||
|
|
||||||
@@ -199,17 +216,19 @@ const TransferToLayingForm = ({
|
|||||||
setIsApproveLoading(false);
|
setIsApproveLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const confirmationModalRejectClickHandler = async () => {
|
const confirmationModalRejectClickHandler = async (notes: string) => {
|
||||||
setIsRejectLoading(true);
|
setIsRejectLoading(true);
|
||||||
|
|
||||||
const rejectResponse = await TransferToLayingApi.reject(
|
const rejectResponse = await TransferToLayingApi.reject(
|
||||||
initialValues?.id as number
|
initialValues?.id as number,
|
||||||
|
notes
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isResponseSuccess(rejectResponse)) {
|
if (isResponseSuccess(rejectResponse)) {
|
||||||
rejectModal.closeModal();
|
rejectModal.closeModal();
|
||||||
|
|
||||||
toast.success('Berhasil reject data transfer ke laying!');
|
toast.success('Berhasil reject data transfer ke laying!');
|
||||||
|
router.push('/production/transfer-to-laying');
|
||||||
} else {
|
} else {
|
||||||
rejectModal.closeModal();
|
rejectModal.closeModal();
|
||||||
|
|
||||||
@@ -219,49 +238,47 @@ const TransferToLayingForm = ({
|
|||||||
setIsRejectLoading(false);
|
setIsRejectLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const isRepeaterInputError = (
|
// flock source
|
||||||
column: keyof TransferToLayingFormValues['kandangs'][0],
|
const isFlockSourceKandangsRepeaterInputError = (
|
||||||
|
column: keyof TransferToLayingFormValues['flockSourceKandangs'][0],
|
||||||
idx: number
|
idx: number
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
formik.touched.kandangs?.[idx]?.[column] &&
|
formik.touched.flockSourceKandangs?.[idx]?.[column] &&
|
||||||
Boolean(
|
Boolean(
|
||||||
formik.errors.kandangs?.[idx] instanceof Object &&
|
formik.errors.flockSourceKandangs?.[idx] instanceof Object &&
|
||||||
formik.errors.kandangs?.[idx]?.[column]
|
formik.errors.flockSourceKandangs?.[idx]?.[column]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const repeaterInputErrorMessage = (
|
const flockSourceKandangsRepeaterInputErrorMessage = (
|
||||||
column: keyof TransferToLayingFormValues['kandangs'][0],
|
column: keyof TransferToLayingFormValues['flockSourceKandangs'][0],
|
||||||
idx: number
|
idx: number
|
||||||
) => {
|
) => {
|
||||||
return (formik.errors.kandangs?.[idx] as Record<string, string>)?.[column];
|
return (
|
||||||
|
formik.errors.flockSourceKandangs?.[idx] as Record<string, string>
|
||||||
|
)?.[column];
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: remove dummy data and use real data
|
const {
|
||||||
// Flock Source
|
setInputValue: setFlockSourceInputValue,
|
||||||
// const {
|
options: flockSourceOptions,
|
||||||
// inputValue: flockSourceInputValue,
|
isLoadingOptions: isLoadingFlockSourceOptions,
|
||||||
// setInputValue: setFlockSourceInputValue,
|
rawData: flockSources,
|
||||||
// options: flockSourceOptions,
|
} = useSelect<ProjectFlock>(
|
||||||
// isLoadingOptions: isLoadingFlockSourceOptions,
|
'/production/project-flocks',
|
||||||
// } = useSelect<FlockWithKandangs>('/transfer-to-laying/production/get-flock-source', 'id', 'name');
|
'id',
|
||||||
|
'flock_name',
|
||||||
// TODO: remove this dummy data
|
'search',
|
||||||
const { data: flockSources, isLoading: isLoadingFlockSourceOptions } = useSWR(
|
{
|
||||||
'test',
|
category: 'GROWING',
|
||||||
() => TransferToLayingApi.getFlockSource()
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const flockSourceOptions = isResponseSuccess(flockSources)
|
const flockSourceChangeHandler = async (
|
||||||
? flockSources?.data.map((flockSource) => ({
|
val: OptionType | OptionType[] | null
|
||||||
value: flockSource.id,
|
) => {
|
||||||
label: flockSource.name,
|
|
||||||
}))
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const flockSourceChangeHandler = (val: OptionType | OptionType[] | null) => {
|
|
||||||
// Get flock source data for total quantity and kandang
|
// Get flock source data for total quantity and kandang
|
||||||
const flockSource =
|
const flockSource =
|
||||||
isResponseSuccess(flockSources) && val !== null
|
isResponseSuccess(flockSources) && val !== null
|
||||||
@@ -272,21 +289,38 @@ const TransferToLayingForm = ({
|
|||||||
|
|
||||||
// Set total quantity and kandangs
|
// Set total quantity and kandangs
|
||||||
if (flockSource) {
|
if (flockSource) {
|
||||||
|
const mappedFlockKandangsAvailableQty =
|
||||||
|
await TransferToLayingApi.getMappedFlockKandangsAvailability(
|
||||||
|
flockSource.id
|
||||||
|
);
|
||||||
|
|
||||||
const formattedKandangs = flockSource.kandangs.map((item) => ({
|
const formattedKandangs = flockSource.kandangs.map((item) => ({
|
||||||
kandang: {
|
kandang: {
|
||||||
value: item.kandang.id,
|
value: item.project_flock_kandang_id,
|
||||||
label: item.kandang.name,
|
label: item.name,
|
||||||
},
|
},
|
||||||
quantity: '',
|
quantity: '',
|
||||||
maxQuantity: item.quantity,
|
maxQuantity:
|
||||||
|
(mappedFlockKandangsAvailableQty &&
|
||||||
|
mappedFlockKandangsAvailableQty[item.project_flock_kandang_id]
|
||||||
|
.available_qty) ??
|
||||||
|
0,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
formik.setFieldValue('totalQuantity', flockSource.totalQuantity);
|
let maxTotalQuantity = 0;
|
||||||
formik.setFieldValue('maxTotalQuantity', flockSource.totalQuantity);
|
// flockSource.kandangs.forEach((item) => {
|
||||||
formik.setFieldValue('kandangs', formattedKandangs);
|
// maxTotalQuantity += item.capacity;
|
||||||
|
// });
|
||||||
|
formattedKandangs.forEach((item) => {
|
||||||
|
maxTotalQuantity += item.maxQuantity;
|
||||||
|
});
|
||||||
|
|
||||||
|
formik.setFieldValue('totalQuantity', '');
|
||||||
|
formik.setFieldValue('maxTotalQuantity', maxTotalQuantity);
|
||||||
|
formik.setFieldValue('flockSourceKandangs', formattedKandangs);
|
||||||
} else {
|
} else {
|
||||||
formik.setFieldValue('totalQuantity', undefined);
|
formik.setFieldValue('totalQuantity', undefined);
|
||||||
formik.setFieldValue('kandangs', undefined);
|
formik.setFieldValue('flockSourceKandangs', undefined);
|
||||||
formik.setFieldValue('reason', '');
|
formik.setFieldValue('reason', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,52 +328,137 @@ const TransferToLayingForm = ({
|
|||||||
formik.setFieldValue('flockSource', val);
|
formik.setFieldValue('flockSource', val);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: remove dummy data and use real data
|
// flock destination
|
||||||
// Flock Destination
|
const isFlockDestinationKandangsRepeaterInputError = (
|
||||||
// const {
|
column: keyof TransferToLayingFormValues['flockDestinationKandangs'][0],
|
||||||
// inputValue: flockDestinationInputValue,
|
idx: number
|
||||||
// setInputValue: setFlockDestinationInputValue,
|
) => {
|
||||||
// options: flockDestinationOptions,
|
return (
|
||||||
// isLoadingOptions: isLoadingFlockDestinationOptions,
|
formik.touched.flockDestinationKandangs?.[idx]?.[column] &&
|
||||||
// } = useSelect<FlockWithKandangs>('/transfer-to-laying/production/get-flock-destination', 'id', 'name');
|
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];
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: remove this dummy data
|
|
||||||
const {
|
const {
|
||||||
data: flockDestinations,
|
setInputValue: setFlockDestinationInputValue,
|
||||||
isLoading: isLoadingFlockDestinationOptions,
|
options: flockDestinationOptions,
|
||||||
} = useSWR('test', () => TransferToLayingApi.getFlockSource());
|
isLoadingOptions: isLoadingFlockDestinationOptions,
|
||||||
|
rawData: flockDestinations,
|
||||||
const flockDestinationOptions = isResponseSuccess(flockDestinations)
|
} = useSelect<ProjectFlock>(
|
||||||
? flockDestinations?.data.map((flockDestination) => ({
|
'/production/project-flocks',
|
||||||
value: flockDestination.id,
|
'id',
|
||||||
label: flockDestination.name,
|
'flock_name',
|
||||||
}))
|
'search',
|
||||||
: [];
|
{
|
||||||
|
category: 'LAYING',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const flockDestinationChangeHandler = (
|
const flockDestinationChangeHandler = (
|
||||||
val: OptionType | OptionType[] | null
|
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.setFieldTouched('flockDestination', true);
|
||||||
formik.setFieldValue('flockDestination', val);
|
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(() => {
|
useEffect(() => {
|
||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
}, [formikSetValues, formikInitialValues]);
|
}, [formikSetValues, formikInitialValues]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// calculate total quantity if kandangs quantity change
|
// calculate total quantity if kandangs quantity change
|
||||||
if (kandangsValue && kandangsValue.length > 0) {
|
if (flockSourceKandangsValue && flockSourceKandangsValue.length > 0) {
|
||||||
let newTotalQuantity = 0;
|
let newTotalQuantity = 0;
|
||||||
|
|
||||||
kandangsValue.forEach((item) => {
|
flockSourceKandangsValue.forEach((item) => {
|
||||||
newTotalQuantity += item.quantity as number;
|
newTotalQuantity += parseFloat(item.quantity as string);
|
||||||
});
|
});
|
||||||
|
|
||||||
formik.setFieldValue('totalQuantity', newTotalQuantity);
|
formik.setFieldValue('totalQuantity', newTotalQuantity);
|
||||||
formik.validateField('totalQuantity');
|
formik.validateField('totalQuantity');
|
||||||
}
|
}
|
||||||
}, [formikSetValues, kandangsValue]);
|
}, [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 (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -361,30 +480,56 @@ const TransferToLayingForm = ({
|
|||||||
</h1>
|
</h1>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className='w-full my-4 flex flex-row justify-end gap-2'>
|
{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' && (
|
{type === 'detail' && (
|
||||||
<>
|
<>
|
||||||
<Button
|
{isShowApproveRejectButton && (
|
||||||
variant='outline'
|
<div className='w-full flex flex-row justify-end gap-2'>
|
||||||
color='success'
|
{/* TODO: apply RBAC */}
|
||||||
onClick={approveClickHandler}
|
<Button
|
||||||
// disabled={selectedRowIds.length === 0}
|
variant='outline'
|
||||||
className='w-full sm:w-fit'
|
color='success'
|
||||||
>
|
onClick={approveClickHandler}
|
||||||
<Icon icon='material-symbols:check' width={24} height={24} />
|
className='w-full sm:w-fit'
|
||||||
Approve
|
>
|
||||||
</Button>
|
<Icon
|
||||||
|
icon='material-symbols:check'
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
/>
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant='outline'
|
variant='outline'
|
||||||
color='error'
|
color='error'
|
||||||
onClick={rejectClickHandler}
|
onClick={rejectClickHandler}
|
||||||
// disabled={selectedRowIds.length === 0}
|
className='w-full sm:w-fit'
|
||||||
className='w-full sm:w-fit'
|
>
|
||||||
>
|
<Icon
|
||||||
<Icon icon='material-symbols:close' width={24} height={24} />
|
icon='material-symbols:close'
|
||||||
Reject
|
width={24}
|
||||||
</Button>
|
height={24}
|
||||||
|
/>
|
||||||
|
Reject
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -395,13 +540,12 @@ const TransferToLayingForm = ({
|
|||||||
className='w-full flex flex-col gap-6'
|
className='w-full flex flex-col gap-6'
|
||||||
>
|
>
|
||||||
<div className='flex flex-col gap-4'>
|
<div className='flex flex-col gap-4'>
|
||||||
<TextInput
|
<DateInput
|
||||||
required
|
required
|
||||||
type='date'
|
|
||||||
label='Tanggal Transfer'
|
label='Tanggal Transfer'
|
||||||
name='transfer_date'
|
name='transfer_date'
|
||||||
placeholder='Masukkan tanggal transfer'
|
placeholder='Masukkan tanggal transfer'
|
||||||
value={formik.values.transfer_date}
|
value={formik.values.transfer_date ?? ''}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
onBlur={formik.handleBlur}
|
onBlur={formik.handleBlur}
|
||||||
isError={
|
isError={
|
||||||
@@ -421,7 +565,7 @@ const TransferToLayingForm = ({
|
|||||||
options={flockSourceOptions}
|
options={flockSourceOptions}
|
||||||
onChange={flockSourceChangeHandler}
|
onChange={flockSourceChangeHandler}
|
||||||
isLoading={isLoadingFlockSourceOptions}
|
isLoading={isLoadingFlockSourceOptions}
|
||||||
// onInputChange={setFlockSourceInputValue}
|
onInputChange={setFlockSourceInputValue}
|
||||||
isError={
|
isError={
|
||||||
formik.touched.flockSource &&
|
formik.touched.flockSource &&
|
||||||
Boolean(typeof formik.errors.flockSource === 'string')
|
Boolean(typeof formik.errors.flockSource === 'string')
|
||||||
@@ -439,7 +583,7 @@ const TransferToLayingForm = ({
|
|||||||
options={flockDestinationOptions}
|
options={flockDestinationOptions}
|
||||||
onChange={flockDestinationChangeHandler}
|
onChange={flockDestinationChangeHandler}
|
||||||
isLoading={isLoadingFlockDestinationOptions}
|
isLoading={isLoadingFlockDestinationOptions}
|
||||||
// onInputChange={setFlockDestinationInputValue}
|
onInputChange={setFlockDestinationInputValue}
|
||||||
isError={
|
isError={
|
||||||
formik.touched.flockDestination &&
|
formik.touched.flockDestination &&
|
||||||
Boolean(typeof formik.errors.flockDestination === 'string')
|
Boolean(typeof formik.errors.flockDestination === 'string')
|
||||||
@@ -450,9 +594,8 @@ const TransferToLayingForm = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TextInput
|
<NumberInput
|
||||||
required
|
required
|
||||||
type='number'
|
|
||||||
name='totalQuantity'
|
name='totalQuantity'
|
||||||
label='Jumlah Transfer'
|
label='Jumlah Transfer'
|
||||||
bottomLabel={
|
bottomLabel={
|
||||||
@@ -461,7 +604,9 @@ const TransferToLayingForm = ({
|
|||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
placeholder='Masukkan jumlah transfer'
|
placeholder='Masukkan jumlah transfer'
|
||||||
value={formik.values.totalQuantity ?? ''}
|
value={
|
||||||
|
formik.values.totalQuantity ? formik.values.totalQuantity : ''
|
||||||
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
onBlur={formik.handleBlur}
|
onBlur={formik.handleBlur}
|
||||||
isError={
|
isError={
|
||||||
@@ -469,24 +614,22 @@ const TransferToLayingForm = ({
|
|||||||
Boolean(formik.errors.totalQuantity)
|
Boolean(formik.errors.totalQuantity)
|
||||||
}
|
}
|
||||||
errorMessage={formik.errors.totalQuantity}
|
errorMessage={formik.errors.totalQuantity}
|
||||||
// readOnly={type === 'detail'}
|
|
||||||
// disabled={Boolean(formik.errors.flockSource)}
|
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div>
|
<div className='flex flex-col gap-4'>
|
||||||
<div className='overflow-x-auto'>
|
<div className='overflow-x-auto'>
|
||||||
<table className='table'>
|
<table className='table'>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Kandang</th>
|
<th>Kandang Flock Asal</th>
|
||||||
<th>Kuantitas</th>
|
<th>Kuantitas</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
{(!formik.values.kandangs ||
|
{(!formik.values.flockSourceKandangs ||
|
||||||
formik.values.kandangs.length === 0) && (
|
formik.values.flockSourceKandangs.length === 0) && (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={2}>
|
<td colSpan={2}>
|
||||||
<p className='w-full text-center text-gray-400'>
|
<p className='w-full text-center text-gray-400'>
|
||||||
@@ -496,8 +639,8 @@ const TransferToLayingForm = ({
|
|||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{formik.values.kandangs &&
|
{formik.values.flockSourceKandangs &&
|
||||||
formik.values.kandangs.map((kandang, idx) => (
|
formik.values.flockSourceKandangs.map((kandang, idx) => (
|
||||||
<tr key={idx}>
|
<tr key={idx}>
|
||||||
<td>
|
<td>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
@@ -511,10 +654,9 @@ const TransferToLayingForm = ({
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<NumberInput
|
||||||
required
|
required
|
||||||
type='number'
|
name={`flockSourceKandangs[${idx}].quantity`}
|
||||||
name={`kandangs[${idx}].quantity`}
|
|
||||||
bottomLabel={
|
bottomLabel={
|
||||||
kandang.maxQuantity
|
kandang.maxQuantity
|
||||||
? `Max: ${kandang.maxQuantity}`
|
? `Max: ${kandang.maxQuantity}`
|
||||||
@@ -524,8 +666,11 @@ const TransferToLayingForm = ({
|
|||||||
value={kandang.quantity}
|
value={kandang.quantity}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
onBlur={formik.handleBlur}
|
onBlur={formik.handleBlur}
|
||||||
isError={isRepeaterInputError('quantity', idx)}
|
isError={isFlockSourceKandangsRepeaterInputError(
|
||||||
errorMessage={repeaterInputErrorMessage(
|
'quantity',
|
||||||
|
idx
|
||||||
|
)}
|
||||||
|
errorMessage={flockSourceKandangsRepeaterInputErrorMessage(
|
||||||
'quantity',
|
'quantity',
|
||||||
idx
|
idx
|
||||||
)}
|
)}
|
||||||
@@ -540,6 +685,76 @@ const TransferToLayingForm = ({
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
|
|
||||||
<TextArea
|
<TextArea
|
||||||
@@ -558,25 +773,38 @@ const TransferToLayingForm = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{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'>
|
<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'>
|
||||||
<Button
|
{isShowDeleteButton && (
|
||||||
type='button'
|
<Button
|
||||||
color='error'
|
type='button'
|
||||||
onClick={deleteTransferToLayingClickHandler}
|
color='error'
|
||||||
className='px-4'
|
onClick={deleteTransferToLayingClickHandler}
|
||||||
>
|
className='px-4'
|
||||||
<Icon
|
>
|
||||||
icon='material-symbols:delete-outline-rounded'
|
<Icon
|
||||||
width={24}
|
icon='material-symbols:delete-outline-rounded'
|
||||||
height={24}
|
width={24}
|
||||||
className='justify-start text-sm'
|
height={24}
|
||||||
/>
|
className='justify-start text-sm'
|
||||||
Delete
|
/>
|
||||||
</Button>
|
Delete
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
{type !== 'edit' && (
|
{type !== 'edit' && isShowEditButton && (
|
||||||
<Button
|
<Button
|
||||||
type='button'
|
type='button'
|
||||||
color='warning'
|
color='warning'
|
||||||
@@ -617,17 +845,6 @@ const TransferToLayingForm = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{formErrorMessage && (
|
|
||||||
<div role='alert' className='alert alert-error'>
|
|
||||||
<Icon
|
|
||||||
icon='material-symbols:error-outline'
|
|
||||||
width={24}
|
|
||||||
height={24}
|
|
||||||
/>
|
|
||||||
<span>{formErrorMessage}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -650,7 +867,7 @@ const TransferToLayingForm = ({
|
|||||||
|
|
||||||
{type === 'detail' && (
|
{type === 'detail' && (
|
||||||
<>
|
<>
|
||||||
<ConfirmationModal
|
<ConfirmationModalWithNotes
|
||||||
ref={approveModal.ref}
|
ref={approveModal.ref}
|
||||||
type='success'
|
type='success'
|
||||||
text='Apakah anda yakin ingin approve data transfer ke laying ini?'
|
text='Apakah anda yakin ingin approve data transfer ke laying ini?'
|
||||||
@@ -665,7 +882,7 @@ const TransferToLayingForm = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ConfirmationModal
|
<ConfirmationModalWithNotes
|
||||||
ref={rejectModal.ref}
|
ref={rejectModal.ref}
|
||||||
type='error'
|
type='error'
|
||||||
text='Apakah anda yakin ingin reject data transfer ke laying ini?'
|
text='Apakah anda yakin ingin reject data transfer ke laying ini?'
|
||||||
|
|||||||
Reference in New Issue
Block a user