mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 21:41:57 +00:00
c9a5a91970
DeliveryOrderFormModal
809 lines
28 KiB
TypeScript
809 lines
28 KiB
TypeScript
'use client';
|
|
|
|
import AlertErrorList from '@/components/helper/form/FormErrors';
|
|
import { OptionType } from '@/components/input/SelectInput';
|
|
import Modal, { useModal } from '@/components/Modal';
|
|
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
|
import { DeliveryOrderProductFormValues } from '@/components/pages/marketing/form/repeater/delivery-order/DeliverOrderProduct.schema';
|
|
import { isResponseSuccess, isResponseError } from '@/lib/api-helper';
|
|
import { formatCurrency, formatDate, formatTitleCase } from '@/lib/helper';
|
|
import {
|
|
DeliveryOrderApi,
|
|
MarketingApi,
|
|
SalesOrderApi,
|
|
} from '@/services/api/marketing/marketing';
|
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
|
import { BaseApproval } from '@/types/api/api-general';
|
|
import {
|
|
CreateDeliveryOrderPayload,
|
|
Marketing,
|
|
UpdateDeliveryOrderPayload,
|
|
} from '@/types/api/marketing/marketing';
|
|
import { useFormik } from 'formik';
|
|
import { Icon } from '@iconify/react';
|
|
import { useRouter, useSearchParams } from 'next/navigation';
|
|
import { useState, useRef, useMemo, useCallback, useEffect } from 'react';
|
|
import toast from 'react-hot-toast';
|
|
import useSWR, { useSWRConfig } from 'swr';
|
|
import Button from '@/components/Button';
|
|
import { memo } from 'react';
|
|
import SalesOrderExport from '@/components/pages/marketing/pdf/SalesOrderExport';
|
|
import ApprovalStepsV2 from '@/components/helper/ApprovalStepsV2';
|
|
import { useApprovalSteps } from '@/components/pages/ApprovalSteps';
|
|
import { MARKETING_APPROVAL_LINE } from '@/config/approval-line';
|
|
import DeliveryOrderProductForm from '@/components/pages/marketing/form/repeater/delivery-order/DeliverOrderProduct';
|
|
import DeliveryOrderProductTable from '@/components/pages/marketing/form/table-view/DeliveryOrderProductTable';
|
|
import {
|
|
DeliveryOrderFormValues,
|
|
DeliveryOrderSchema,
|
|
getFilledMarketingFormInitialValues,
|
|
SalesOrderFormValues,
|
|
mergeSOwithDO,
|
|
SalesProductToFieldValues,
|
|
DeliveryProductToFieldValues,
|
|
} from '@/components/pages/marketing/form/MarketingForm.schema';
|
|
import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
|
|
import RequirePermission from '@/components/helper/RequirePermission';
|
|
|
|
const MemoizedDeliveryOrderProductTable = memo(DeliveryOrderProductTable);
|
|
const MemoizedDeliveryOrderProductForm = memo(DeliveryOrderProductForm);
|
|
|
|
const DeliveryOrderFormModal = ({
|
|
initialValues,
|
|
}: {
|
|
initialValues?: Marketing;
|
|
}) => {
|
|
const router = useRouter();
|
|
const searchParams = useSearchParams();
|
|
|
|
const modalAction = searchParams.get('action');
|
|
const marketingId = searchParams.get('id');
|
|
|
|
const isModalActionForForm =
|
|
modalAction === 'add_delivery' ||
|
|
modalAction === 'edit_delivery' ||
|
|
modalAction === 'detail';
|
|
|
|
const { mutate } = useSWRConfig();
|
|
|
|
const refreshMarketing = () => {
|
|
mutate(
|
|
(key) => typeof key === 'string' && key.includes(MarketingApi.basePath)
|
|
);
|
|
};
|
|
|
|
const { data: marketing, isLoading: isLoadingMarketing } = useSWR(
|
|
isModalActionForForm && marketingId
|
|
? `detail-marketing-${marketingId}`
|
|
: undefined,
|
|
() => MarketingApi.getSingle(Number(marketingId))
|
|
);
|
|
|
|
const {
|
|
approvals,
|
|
rawDataApprovals,
|
|
isLoading: isLoadingApproval,
|
|
refresh: refreshApproval,
|
|
} = useApprovalSteps({
|
|
latestApproval: isResponseSuccess(marketing)
|
|
? marketing?.data.latest_approval
|
|
: undefined,
|
|
approvalLines: MARKETING_APPROVAL_LINE,
|
|
moduleName: 'MARKETINGS',
|
|
moduleId: marketingId as string,
|
|
params: {
|
|
group_step_number: false,
|
|
order_by_date: 'ASC',
|
|
},
|
|
});
|
|
|
|
/**
|
|
* Step 1: View Details
|
|
* Step 2: Edit Delivery
|
|
*/
|
|
const [step, setStep] = useState(1);
|
|
|
|
const formModal = useModal();
|
|
const successModal = useModal();
|
|
const rejectModal = useModal();
|
|
const deleteModal = useModal();
|
|
const formRef = useRef<HTMLFormElement>(null);
|
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
|
|
|
const [formErrorMessage, setFormErrorMessage] = useState<string | null>(null);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [selectedDeliveryProduct, setSelectedDeliveryProduct] =
|
|
useState<DeliveryOrderProductFormValues | null>(null);
|
|
const [deliveryOrderValues, setDeliveryOrderValues] = useState<
|
|
DeliveryOrderProductFormValues[]
|
|
>(
|
|
isResponseSuccess(marketing)
|
|
? mergeSOwithDO(
|
|
marketing?.data.sales_order?.map(SalesProductToFieldValues) ?? [],
|
|
marketing?.data.delivery_order?.flatMap((delivery) =>
|
|
DeliveryProductToFieldValues(marketing.data.sales_order, delivery)
|
|
) ?? [],
|
|
true
|
|
)
|
|
: []
|
|
);
|
|
|
|
// ================== SETUP FORMIK ==================
|
|
const formikInitialValues = useMemo<
|
|
SalesOrderFormValues & DeliveryOrderFormValues
|
|
>(() => {
|
|
if (!isResponseSuccess(marketing))
|
|
return {} as SalesOrderFormValues & DeliveryOrderFormValues;
|
|
const deliveryValues = mergeSOwithDO(
|
|
marketing?.data.sales_order?.map(SalesProductToFieldValues) ?? [],
|
|
marketing?.data.delivery_order?.flatMap((delivery) =>
|
|
DeliveryProductToFieldValues(marketing.data.sales_order, delivery)
|
|
) ?? [],
|
|
true
|
|
);
|
|
|
|
setDeliveryOrderValues(deliveryValues);
|
|
|
|
return {
|
|
so_date: marketing?.data?.so_date || undefined,
|
|
notes: marketing?.data?.notes || undefined,
|
|
customer_id: marketing?.data?.customer?.id || undefined,
|
|
sales_person_id: marketing?.data?.sales_person?.id || undefined,
|
|
sales_person: marketing?.data?.sales_person
|
|
? {
|
|
value: marketing?.data.sales_person.id,
|
|
label: marketing?.data.sales_person.name,
|
|
}
|
|
: null,
|
|
customer: marketing?.data?.customer
|
|
? {
|
|
value: marketing?.data.customer.id,
|
|
label: marketing?.data.customer.name,
|
|
}
|
|
: null,
|
|
sales_order:
|
|
marketing?.data?.sales_order?.map((product) =>
|
|
SalesProductToFieldValues(product)
|
|
) ?? [],
|
|
delivery_order: deliveryValues,
|
|
};
|
|
}, [marketing]);
|
|
|
|
const formik = useFormik<SalesOrderFormValues & DeliveryOrderFormValues>({
|
|
enableReinitialize: true,
|
|
initialValues: formikInitialValues,
|
|
validationSchema: DeliveryOrderSchema,
|
|
validateOnMount: true,
|
|
onSubmit: async (values) => {
|
|
const payload = {
|
|
marketing_id: Number(marketingId),
|
|
delivery_products: values.delivery_order
|
|
.map((product) => {
|
|
if (Boolean(product.delivery_date)) {
|
|
return {
|
|
marketing_product_id: product.marketing_product_id as number,
|
|
unit_price: parseFloat(product.unit_price as string),
|
|
total_weight: parseFloat(product.total_weight as string),
|
|
qty: parseFloat(product.qty as string),
|
|
avg_weight: parseFloat(product.avg_weight as string),
|
|
total_price: parseFloat(product.total_price as string),
|
|
delivery_date: formatDate(
|
|
product.delivery_date as string,
|
|
'yyyy-MM-DD'
|
|
),
|
|
vehicle_number: product.vehicle_number,
|
|
};
|
|
}
|
|
})
|
|
.filter((item) => Boolean(item)),
|
|
} as UpdateDeliveryOrderPayload;
|
|
switch (modalAction) {
|
|
case 'add_delivery':
|
|
await createDeliveryHandler(payload as CreateDeliveryOrderPayload);
|
|
break;
|
|
case 'edit_delivery':
|
|
await updateDeliveryHandler(payload as UpdateDeliveryOrderPayload);
|
|
break;
|
|
case 'detail':
|
|
const dataMarketing = isResponseSuccess(marketing)
|
|
? marketing.data
|
|
: null;
|
|
if (!dataMarketing) break;
|
|
if (
|
|
dataMarketing.delivery_order &&
|
|
dataMarketing.delivery_order.length > 0
|
|
) {
|
|
await updateDeliveryHandler(payload as UpdateDeliveryOrderPayload);
|
|
break;
|
|
} else {
|
|
await createDeliveryHandler(payload as CreateDeliveryOrderPayload);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
},
|
|
});
|
|
|
|
// ===== Formik Error List =====
|
|
const { formErrorList, setFormErrorList, close, handleFormSubmit } =
|
|
useFormikErrorList(formik);
|
|
|
|
// ================== FORM HANDLER ==================
|
|
const createDeliveryHandler = async (values: CreateDeliveryOrderPayload) => {
|
|
setIsLoading(true);
|
|
const createDeliveryRes = await DeliveryOrderApi.create(values);
|
|
if (isResponseSuccess(createDeliveryRes)) {
|
|
toast.success(createDeliveryRes?.message as string);
|
|
setDeliveryOrderValues(
|
|
createDeliveryRes.data?.delivery_order?.flatMap((delivery) =>
|
|
DeliveryProductToFieldValues(
|
|
createDeliveryRes.data?.sales_order,
|
|
delivery
|
|
)
|
|
) ?? []
|
|
);
|
|
closeModalHandler(false);
|
|
successModal.openModal();
|
|
}
|
|
if (isResponseError(createDeliveryRes)) {
|
|
setFormErrorMessage(createDeliveryRes?.message as string);
|
|
}
|
|
setIsLoading(false);
|
|
};
|
|
const updateDeliveryHandler = async (values: UpdateDeliveryOrderPayload) => {
|
|
setIsLoading(true);
|
|
const updateDeliveryRes = await DeliveryOrderApi.update(
|
|
Number(marketingId),
|
|
values
|
|
);
|
|
if (isResponseSuccess(updateDeliveryRes)) {
|
|
toast.success(updateDeliveryRes?.message as string);
|
|
setDeliveryOrderValues(
|
|
mergeSOwithDO(
|
|
formik.values.sales_order,
|
|
updateDeliveryRes.data?.delivery_order?.flatMap((delivery) =>
|
|
DeliveryProductToFieldValues(
|
|
updateDeliveryRes.data?.sales_order,
|
|
delivery
|
|
)
|
|
) ?? []
|
|
)
|
|
);
|
|
closeModalHandler(false);
|
|
successModal.openModal();
|
|
}
|
|
if (isResponseError(updateDeliveryRes)) {
|
|
setFormErrorMessage(updateDeliveryRes?.message as string);
|
|
}
|
|
setIsLoading(false);
|
|
};
|
|
|
|
const memoSalesOrder = formik.values.sales_order;
|
|
|
|
// ================== HANDLER ==================
|
|
const nextButtonHandler = () => {
|
|
setStep(step + 1);
|
|
};
|
|
const prevButtonHandler = () => {
|
|
setStep(step - 1);
|
|
};
|
|
const handleChangeCustomer = useCallback(
|
|
(val: OptionType | OptionType[] | null) => {
|
|
formik.setFieldValue('customer_id', (val as OptionType)?.value);
|
|
formik.setFieldValue('customer', val as OptionType);
|
|
},
|
|
[]
|
|
);
|
|
const handleChangeSalesPerson = useCallback(
|
|
(val: OptionType | OptionType[] | null) => {
|
|
formik.setFieldValue('sales_person_id', (val as OptionType)?.value);
|
|
formik.setFieldValue('sales_person', val as OptionType);
|
|
},
|
|
[]
|
|
);
|
|
const rejectMarketingHandler = async (notes: string) => {
|
|
if (!marketingId) {
|
|
toast.error(`Tidak ada data yang valid untuk di reject.`);
|
|
rejectModal.closeModal();
|
|
return;
|
|
}
|
|
|
|
const rejectMarketingRes = await SalesOrderApi.singleApproval(
|
|
Number(marketingId),
|
|
'REJECTED',
|
|
notes
|
|
);
|
|
|
|
if (isResponseSuccess(rejectMarketingRes)) {
|
|
rejectModal.closeModal();
|
|
toast.success(rejectMarketingRes?.message as string);
|
|
closeModalHandler();
|
|
router.push('/marketing');
|
|
}
|
|
if (isResponseError(rejectMarketingRes)) {
|
|
rejectModal.closeModal();
|
|
toast.error(rejectMarketingRes?.message as string);
|
|
}
|
|
refreshMarketing();
|
|
refreshApproval();
|
|
};
|
|
|
|
const deleteClickHandler = () => {
|
|
deleteModal.openModal();
|
|
};
|
|
|
|
const confirmationModalDeleteClickHandler = async () => {
|
|
if (!marketingId) {
|
|
toast.error(`Tidak ada data yang valid untuk di hapus.`);
|
|
deleteModal.closeModal();
|
|
return;
|
|
}
|
|
setIsLoading(true);
|
|
const res = await MarketingApi.delete(Number(marketingId));
|
|
deleteModal.closeModal();
|
|
toast.success(res?.message as string);
|
|
setIsLoading(false);
|
|
router.replace('/marketing');
|
|
};
|
|
|
|
// ================== DELIVERY ORDER HANDLER ==================
|
|
const handleEditDO = useCallback(
|
|
(id: number, values?: DeliveryOrderProductFormValues) => {
|
|
const currentProducts = deliveryOrderValues?.find(
|
|
(product) => product.id == id
|
|
);
|
|
setSelectedDeliveryProduct(values ?? currentProducts ?? null);
|
|
if (id) {
|
|
setStep(2);
|
|
}
|
|
},
|
|
[deliveryOrderValues, setSelectedDeliveryProduct, setStep]
|
|
);
|
|
const handleAddDOClick = useCallback(() => {
|
|
setSelectedDeliveryProduct(null);
|
|
}, []);
|
|
const handleAddSubmitDO = useCallback(
|
|
async (values: DeliveryOrderProductFormValues) => {
|
|
const newValues = {
|
|
...values,
|
|
id: values.id ?? Date.now(),
|
|
};
|
|
|
|
setDeliveryOrderValues((prev) => [...prev, newValues]);
|
|
setSelectedDeliveryProduct(null);
|
|
prevButtonHandler();
|
|
},
|
|
[prevButtonHandler]
|
|
);
|
|
const handleUpdateDO = useCallback(
|
|
async (id: number, values: DeliveryOrderProductFormValues) => {
|
|
setDeliveryOrderValues((prev) =>
|
|
prev.map((product) =>
|
|
product.id === id ? { ...product, ...values } : product
|
|
)
|
|
);
|
|
setSelectedDeliveryProduct(null);
|
|
prevButtonHandler();
|
|
},
|
|
[prevButtonHandler]
|
|
);
|
|
const handleDeleteDO = useCallback(async (id: number) => {
|
|
setDeliveryOrderValues((prev) =>
|
|
prev.map((product) =>
|
|
product.id === id
|
|
? {
|
|
...product,
|
|
...{
|
|
delivery_date: '',
|
|
},
|
|
}
|
|
: product
|
|
)
|
|
);
|
|
setSelectedDeliveryProduct(null);
|
|
}, []);
|
|
|
|
// ================== MEMOIZED ==================
|
|
const isNextButtonDisabled = useMemo(() => {
|
|
if (step === 1) {
|
|
return Boolean(
|
|
!formik.values.customer_id ||
|
|
!formik.values.sales_person_id ||
|
|
!formik.values.so_date ||
|
|
!formik.values.notes
|
|
);
|
|
}
|
|
|
|
return true;
|
|
}, [step, formik.values]);
|
|
const deliveryRejected = useMemo(() => {
|
|
return (
|
|
isResponseSuccess(marketing) &&
|
|
((marketing.data.latest_approval.step_number === 3 &&
|
|
marketing.data.latest_approval.action === 'REJECTED') ||
|
|
(marketing.data.latest_approval.step_number === 2 &&
|
|
marketing.data.latest_approval.action === 'REJECTED'))
|
|
);
|
|
}, [marketing]);
|
|
|
|
const isPending = useMemo(() => {
|
|
return (
|
|
isResponseSuccess(marketing) &&
|
|
marketing.data.latest_approval.step_number === 1
|
|
);
|
|
}, [marketing]);
|
|
|
|
// ================== EFFECT ==================
|
|
useEffect(() => {
|
|
if (
|
|
modalAction === 'add_delivery' ||
|
|
modalAction === 'edit_delivery' ||
|
|
modalAction === 'detail'
|
|
) {
|
|
formModal.openModal();
|
|
}
|
|
}, [modalAction]);
|
|
|
|
const closeModalHandler = (shouldPushToRoute: boolean = true) => {
|
|
refreshMarketing();
|
|
|
|
if (shouldPushToRoute) {
|
|
formik.resetForm();
|
|
textareaRef.current?.setAttribute('value', '');
|
|
successModal.closeModal();
|
|
router.push('/marketing');
|
|
}
|
|
|
|
setStep(1);
|
|
setFormErrorMessage('');
|
|
formModal.closeModal();
|
|
};
|
|
|
|
useEffect(() => {
|
|
const getFilledInitialValues = async () => {
|
|
if (marketingId && isResponseSuccess(marketing)) {
|
|
const filledInitialValues = await getFilledMarketingFormInitialValues(
|
|
marketing.data
|
|
);
|
|
|
|
formik.setValues(filledInitialValues);
|
|
setStep(1);
|
|
}
|
|
|
|
if (isResponseError(marketing)) {
|
|
router.push('/marketing');
|
|
closeModalHandler();
|
|
toast.error(marketing.message);
|
|
}
|
|
};
|
|
|
|
getFilledInitialValues();
|
|
}, [marketingId, marketing]);
|
|
|
|
// Reset error message when step changes
|
|
useEffect(() => {
|
|
setFormErrorList([]);
|
|
setFormErrorMessage('');
|
|
}, [step]);
|
|
|
|
// sync delivery order values to formik
|
|
useEffect(() => {
|
|
formik.setFieldValue('delivery_order', deliveryOrderValues);
|
|
}, [deliveryOrderValues]);
|
|
|
|
const grandTotal = useMemo(() => {
|
|
return deliveryOrderValues.reduce(
|
|
(total, product) =>
|
|
total + parseFloat((product.total_price as string) || '0'),
|
|
0
|
|
);
|
|
}, [deliveryOrderValues]);
|
|
|
|
return (
|
|
<>
|
|
<Modal
|
|
ref={formModal.ref}
|
|
position='end'
|
|
className={{
|
|
modalBox: 'w-full sm:w-fit p-3 rounded-xl bg-transparent shadow-none',
|
|
}}
|
|
>
|
|
<div
|
|
onSubmit={(e) => {
|
|
e.preventDefault();
|
|
}}
|
|
className='w-full min-h-full flex flex-col sm:flex-row items-stretch bg-base-100 rounded-xl overflow-y-auto'
|
|
>
|
|
{step <= 2 && isResponseSuccess(marketing) && (
|
|
<>
|
|
<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'>
|
|
View Details
|
|
</h4>
|
|
</div>
|
|
<form
|
|
className='w-full p-4 gap-3 flex flex-col border-b border-base-content/10'
|
|
ref={formRef}
|
|
onSubmit={handleFormSubmit}
|
|
>
|
|
<h4 className='text-base font-medium text-base-content/50 font-roboto'>
|
|
Informasi Penjualan
|
|
</h4>
|
|
<div className='rounded-lg border border-tools-table-outline border-base-content/5'>
|
|
<table
|
|
style={{
|
|
borderRadius: '0.5rem',
|
|
}}
|
|
className='border-none w-full'
|
|
>
|
|
<tbody className='w-full'>
|
|
<tr className='border-b border-tools-table-outline border-base-content/5'>
|
|
<th className='w-1/3 text-start not-first:font-medium text-base-content/50 text-sm px-4 py-3'>
|
|
Label
|
|
</th>
|
|
<th className='text-start font-medium text-base-content/50 text-sm px-4 py-3'>
|
|
<div className='flex w-full flex-row gap-1 items-center justify-between h-full mt-2'>
|
|
<div>Value</div>
|
|
</div>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<td className='text-sm px-4 py-3'>No. Order</td>
|
|
<td className='text-sm px-4 py-3'>
|
|
{marketing.data.do_number
|
|
? marketing.data.do_number
|
|
: marketing.data.so_number}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td className='text-sm px-4 py-3'>Nama Pelanggan</td>
|
|
<td className='text-sm px-4 py-3'>
|
|
{marketing.data.customer.name}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td className='text-sm px-4 py-3'>Status</td>
|
|
<td className='text-sm px-4 py-3'>
|
|
{formatTitleCase(
|
|
marketing.data.latest_approval.step_name
|
|
)}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td className='text-sm px-4 py-3'>
|
|
Tanggal Penjualan
|
|
</td>
|
|
<td className='text-sm px-4 py-3'>
|
|
{formatDate(marketing.data.so_date, 'DD MMM yyyy')}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td className='text-sm px-4 py-3'>Total Penjualan</td>
|
|
<td className='text-sm px-4 py-3'>
|
|
{formatCurrency(grandTotal || 0)}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td className='text-sm px-4 py-3'>
|
|
Dokumen Penjualan
|
|
</td>
|
|
<td className='text-sm px-4 py-3'>
|
|
<SalesOrderExport data={marketing.data} />
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div className='w-full min-h-full flex flex-col 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'>
|
|
<div className='w-full flex flex-row items-stretch gap-3'>
|
|
{step === 2 && (
|
|
<>
|
|
<Button
|
|
type='button'
|
|
variant='ghost'
|
|
color='none'
|
|
onClick={() => {
|
|
setStep(1);
|
|
}}
|
|
className='p-0 text-black hover:text-base-content'
|
|
>
|
|
<Icon
|
|
icon='heroicons:chevron-left'
|
|
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'>
|
|
Informasi
|
|
</h4>
|
|
</div>
|
|
{step === 1 && (
|
|
<RequirePermission permissions='lti.marketing.sales_order.delete'>
|
|
<Button
|
|
type='button'
|
|
variant='ghost'
|
|
color='none'
|
|
onClick={() => {
|
|
deleteClickHandler();
|
|
}}
|
|
className='p-0 text-error hover:text-base-content'
|
|
>
|
|
<Icon icon='heroicons:trash' width={20} height={20} />
|
|
</Button>
|
|
</RequirePermission>
|
|
)}
|
|
</div>
|
|
{step === 1 && (
|
|
<ApprovalStepsV2
|
|
approvals={rawDataApprovals as BaseApproval[]}
|
|
steps={MARKETING_APPROVAL_LINE}
|
|
/>
|
|
)}
|
|
<div className='w-full gap-3 flex flex-col'>
|
|
<h4 className='px-4 pt-4 text-base font-medium text-base-content/50 font-roboto'>
|
|
{step == 2 && 'Ubah '} Informasi{' '}
|
|
{step == 2 ? 'Delivery' : 'Produk'}
|
|
</h4>
|
|
{step === 1 && (
|
|
<div className='px-4'>
|
|
<MemoizedDeliveryOrderProductTable
|
|
marketing={marketing.data}
|
|
formType={
|
|
deliveryRejected
|
|
? 'rejected'
|
|
: isPending
|
|
? 'pending'
|
|
: modalAction
|
|
}
|
|
data={deliveryOrderValues}
|
|
onEdit={handleEditDO}
|
|
onDelete={handleDeleteDO}
|
|
onAddProductClick={handleAddDOClick}
|
|
/>
|
|
</div>
|
|
)}
|
|
{step === 2 && (
|
|
<MemoizedDeliveryOrderProductForm
|
|
formState={'edit'}
|
|
salesOrders={marketing?.data?.sales_order ?? []}
|
|
exisitingValues={deliveryOrderValues}
|
|
onSubmitForm={handleAddSubmitDO}
|
|
initialValues={selectedDeliveryProduct ?? undefined}
|
|
onUpdateForm={handleUpdateDO}
|
|
/>
|
|
)}
|
|
</div>
|
|
{formErrorMessage && (
|
|
<div className='px-4 pb-4'>
|
|
<AlertErrorList
|
|
className={{
|
|
alert: 'w-full',
|
|
}}
|
|
formErrorList={[formErrorMessage]}
|
|
onClose={() => setFormErrorMessage('')}
|
|
/>
|
|
</div>
|
|
)}
|
|
{formErrorList && (
|
|
<div className='px-4 pb-4 '>
|
|
<AlertErrorList
|
|
className={{
|
|
alert: 'w-full',
|
|
}}
|
|
formErrorList={formErrorList}
|
|
onClose={close}
|
|
title={`Terdapat ${formErrorList.length} error pada ${formErrorMessage ? 'server' : 'form'}:`}
|
|
/>
|
|
</div>
|
|
)}
|
|
{step === 1 && (
|
|
<div className='w-full px-4 py-3 grid grid-cols-2 items-center justify-between gap-3 border-t border-base-content/10'>
|
|
<Button
|
|
type='button'
|
|
variant='outline'
|
|
color='none'
|
|
onClick={() => rejectModal.openModal()}
|
|
disabled={deliveryRejected || isPending}
|
|
className='p-3 border-base-content/10 shadow-button-soft rounded-lg text-sm text-base-content/50 font-semibold'
|
|
>
|
|
Reject
|
|
</Button>
|
|
<Button
|
|
type='button'
|
|
color='primary'
|
|
onClick={() => {
|
|
formRef.current?.requestSubmit();
|
|
}}
|
|
className='p-3 shadow-button-soft text-base-100 rounded-lg text-sm font-semibold'
|
|
disabled={deliveryRejected || isPending}
|
|
>
|
|
Approve
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
</Modal>
|
|
<ConfirmationModal
|
|
ref={successModal.ref}
|
|
iconPosition='left'
|
|
type='success'
|
|
text={`${modalAction === 'add' ? 'Data Berhasil Disimpan' : 'Data Berhasil Diubah'}`}
|
|
subtitleText={`${modalAction === 'add' ? 'Data delivery order telah berhasil disimpan.' : 'Data delivery order telah berhasil diubah.'}`}
|
|
primaryButton={{
|
|
text: 'Oke',
|
|
color: 'primary',
|
|
className: 'rounded-lg',
|
|
onClick: (e) => {
|
|
closeModalHandler();
|
|
},
|
|
}}
|
|
>
|
|
<MemoizedDeliveryOrderProductTable
|
|
marketing={isResponseSuccess(marketing) ? marketing.data : undefined}
|
|
formType={'success'}
|
|
data={deliveryOrderValues}
|
|
onDelete={handleDeleteDO}
|
|
onEdit={handleEditDO}
|
|
onAddProductClick={handleAddDOClick}
|
|
/>
|
|
</ConfirmationModal>
|
|
|
|
<ConfirmationModalWithNotes
|
|
ref={rejectModal.ref}
|
|
type={'error'}
|
|
text={`Apakah anda yakin ingin reject data penjualan?`}
|
|
secondaryButton={{
|
|
text: 'Tidak',
|
|
onClick: rejectModal.closeModal,
|
|
}}
|
|
primaryButton={{
|
|
text: 'Ya',
|
|
color: 'error',
|
|
onClick: rejectMarketingHandler,
|
|
}}
|
|
/>
|
|
|
|
<ConfirmationModal
|
|
ref={deleteModal.ref}
|
|
type='error'
|
|
text={`Apakah anda yakin ingin menghapus data penjualan ini?`}
|
|
secondaryButton={{
|
|
text: 'Tidak',
|
|
}}
|
|
primaryButton={{
|
|
text: 'Ya',
|
|
color: 'error',
|
|
isLoading: isLoading,
|
|
onClick: confirmationModalDeleteClickHandler,
|
|
}}
|
|
/>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default DeliveryOrderFormModal;
|