feat(FE-208): add confirmation modal for manager approval with notes functionality

This commit is contained in:
rstubryan
2025-11-14 10:52:36 +07:00
parent 3d49947c1e
commit 00e0202be2
@@ -1,6 +1,6 @@
'use client'; 'use client';
import { useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { ColumnDef } from '@tanstack/react-table'; import { ColumnDef } from '@tanstack/react-table';
import ApprovalSteps, { import ApprovalSteps, {
@@ -11,13 +11,18 @@ import Button from '@/components/Button';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { useModal } from '@/components/Modal'; import { useModal } from '@/components/Modal';
import Modal from '@/components/Modal'; import Modal from '@/components/Modal';
import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
import PurchaseOrderStaffApprovalForm from '@/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm'; import PurchaseOrderStaffApprovalForm from '@/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm';
import PurchaseOrderAcceptApprovalForm from '@/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm'; import PurchaseOrderAcceptApprovalForm from '@/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm';
import { BaseGroupedApproval } from '@/types/api/api-general'; import { BaseGroupedApproval } from '@/types/api/api-general';
import { PURCHASE_ORDER_APPROVAL_LINE } from '@/config/approval-line'; import { PURCHASE_ORDER_APPROVAL_LINE } from '@/config/approval-line';
import Card from '@/components/Card'; import Card from '@/components/Card';
import { Purchase, PurchaseItem } from '@/types/api/purchase/purchase'; import {
CreateManagerApprovalRequisitionsPayload,
Purchase,
PurchaseItem,
} from '@/types/api/purchase/purchase';
import { import {
createdUser, createdUser,
dummyAreas, dummyAreas,
@@ -25,6 +30,10 @@ import {
dummyProductWarehouses, dummyProductWarehouses,
dummyWarehouses, dummyWarehouses,
} from '@/dummy/marketing.dummy'; } from '@/dummy/marketing.dummy';
import { ManagerApprovalApi } from '@/services/api/purchase';
import { isResponseError } from '@/lib/api-helper';
import { toast } from 'react-hot-toast';
import { useSearchParams } from 'next/navigation';
interface PurchaseOrderDetailProps { interface PurchaseOrderDetailProps {
type?: 'detail' | 'edit'; type?: 'detail' | 'edit';
@@ -290,6 +299,8 @@ const PurchaseOrderDetail = ({
data, data,
}: PurchaseOrderDetailProps) => { }: PurchaseOrderDetailProps) => {
// ===== MODAL HOOKS ===== // ===== MODAL HOOKS =====
const searchParams = useSearchParams();
const confirmationModalWithNotes = useModal();
const staffApprovalModal = useModal(); const staffApprovalModal = useModal();
const acceptApprovalModal = useModal(); const acceptApprovalModal = useModal();
@@ -301,6 +312,32 @@ const PurchaseOrderDetail = ({
const latestApproval = const latestApproval =
groupedApprovals[groupedApprovals.length - 1]?.approvals[0]; groupedApprovals[groupedApprovals.length - 1]?.approvals[0];
// ===== SUBMISSION HANDLER =====
const createManagerApprovalHandler = useCallback(
async (payload: CreateManagerApprovalRequisitionsPayload) => {
const purchaseRequisitionId = searchParams.get('purchaseId')
? parseInt(searchParams.get('purchaseId')!)
: purchaseData?.id || 1;
if (!purchaseRequisitionId) {
toast.error('Purchase Requisition ID is required');
return;
}
const res = await ManagerApprovalApi.createManagerApproval(
purchaseRequisitionId,
payload
);
if (isResponseError(res)) {
toast.error(res.message);
return;
}
toast.success(res?.message as string);
},
[purchaseData?.id, searchParams]
);
// ===== COMPUTED VALUES ===== // ===== COMPUTED VALUES =====
const approvalSteps = useMemo(() => { const approvalSteps = useMemo(() => {
if (!groupedApprovals.length || !latestApproval) return []; if (!groupedApprovals.length || !latestApproval) return [];
@@ -470,6 +507,16 @@ const PurchaseOrderDetail = ({
<section className='w-full'> <section className='w-full'>
{/* Approval Action Buttons */} {/* Approval Action Buttons */}
<div className='flex flex-wrap gap-3 my-6'> <div className='flex flex-wrap gap-3 my-6'>
<Button
onClick={() => confirmationModalWithNotes.openModal()}
variant='outline'
color='warning'
className='w-full sm:w-fit'
>
<Icon icon='mdi:note-edit-outline' width={20} height={20} />
Approve
</Button>
<Button <Button
onClick={() => staffApprovalModal.openModal()} onClick={() => staffApprovalModal.openModal()}
variant='outline' variant='outline'
@@ -516,7 +563,7 @@ const PurchaseOrderDetail = ({
}} }}
> >
{/* Order Information */} {/* Order Information */}
<div className='bg-gray-50 rounded-lg p-6 mb-8'> <div className='my-8'>
<h3 className='text-lg font-semibold text-gray-800 mb-6 pb-3 border-b border-gray-200'> <h3 className='text-lg font-semibold text-gray-800 mb-6 pb-3 border-b border-gray-200'>
Informasi Pesanan Informasi Pesanan
</h3> </h3>
@@ -713,6 +760,31 @@ const PurchaseOrderDetail = ({
</div> </div>
</Card> </Card>
{/* Confirmation Modal with Notes */}
<ConfirmationModalWithNotes
ref={confirmationModalWithNotes.ref}
type='success'
text='Apakah Anda yakin ingin melanjutkan approval ini?'
placeholder='(Opsional) Tambahkan catatan untuk approval ini...'
rows={4}
closeOnBackdrop
primaryButton={{
text: 'Ya, Lanjutkan',
color: 'success',
onClick: async (notes) => {
const payload: CreateManagerApprovalRequisitionsPayload = {
notes: notes || null,
};
await createManagerApprovalHandler(payload);
confirmationModalWithNotes.closeModal();
},
}}
secondaryButton={{
text: 'Batal',
}}
/>
{/* Staff Approval Modal */} {/* Staff Approval Modal */}
<Modal <Modal
ref={staffApprovalModal.ref} ref={staffApprovalModal.ref}