From 283c2b2a440e90020e8d82c193d8fba914c98b18 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Mon, 17 Nov 2025 13:21:43 +0700 Subject: [PATCH] feat(FE-208,212): implement bulk delete functionality for purchase order items with confirmation modal --- .../purchase/order/PurchaseOrderDetail.tsx | 113 ++++++++++++++++-- 1 file changed, 104 insertions(+), 9 deletions(-) diff --git a/src/components/pages/purchase/order/PurchaseOrderDetail.tsx b/src/components/pages/purchase/order/PurchaseOrderDetail.tsx index acbf6660..225a079e 100644 --- a/src/components/pages/purchase/order/PurchaseOrderDetail.tsx +++ b/src/components/pages/purchase/order/PurchaseOrderDetail.tsx @@ -175,6 +175,67 @@ const dummyPurchaseData: Purchase = { vehicle_number: null, warehouse: dummyWarehouses[0], }, + { + id: 2, + purchase_id: 2, + product: { + id: 1, + name: 'CP Vaksin', + brand: '', + sku: '', + product_price: 0, + selling_price: 0, + tax: 0, + expiry_period: 0, + uom: { + id: 1, + name: 'Ekor', + created_user: { + id: 1, + id_user: 1, + email: 'hello@gmail.com', + name: 'Admin', + }, + created_at: '2025-01-01T00:00:00Z', + updated_at: '2025-01-01T00:00:00Z', + }, + product_category: { + id: 1, + code: 'DOC', + name: 'DOC', + created_user: { + id: 1, + id_user: 1, + email: 'hello@gmail.com', + name: 'Admin', + }, + created_at: '2025-01-01T00:00:00Z', + updated_at: '2025-01-01T00:00:00Z', + }, + suppliers: [], + flags: [], + created_user: { + id: 1, + id_user: 1, + email: 'hello@gmail.com', + name: 'Admin', + }, + created_at: '2025-01-01T00:00:00Z', + updated_at: '2025-01-01T00:00:00Z', + }, + product_warehouse: dummyProductWarehouses[0], + quantity: 10000, + sub_qty: 10000, + total_qty: 10000, + total_used: 0, + price: 6500, + total_price: 65000000, + received_date: null, + travel_number: null, + travel_number_docs: null, + vehicle_number: null, + warehouse: dummyWarehouses[0], + }, ], created_at: '2025-01-10T00:00:00Z', updated_at: '2025-01-10T00:00:00Z', @@ -184,7 +245,6 @@ const dummyPurchaseData: Purchase = { warehouse: dummyWarehouses[0], }; -// Goods Receipt data - using items from PurchaseItem with received data const dummyGoodsReceiptItems: PurchaseItem[] = [ { id: 1, @@ -356,6 +416,10 @@ const PurchaseOrderDetail = ({ const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [selectedItem, setSelectedItem] = useState(null); + const selectedRowIds = Object.keys(rowSelection).map((item) => + parseInt(item) + ); + // ===== STATIC DATA ===== const purchaseData = data || dummyPurchaseData; const purchaseOrderItems = useMemo( @@ -394,7 +458,7 @@ const PurchaseOrderDetail = ({ ); // ===== DELETE HANDLER ===== - const deleteItemHandler = useCallback(async () => { + const deleteItemsHandler = useCallback(async () => { const purchaseRequestId = searchParams.get('purchaseId') ? parseInt(searchParams.get('purchaseId')!) : purchaseData?.id || 1; @@ -404,8 +468,10 @@ const PurchaseOrderDetail = ({ return; } - if (!selectedItem) { - toast.error('Item tidak valid'); + const itemIdsToDelete = selectedItem ? [selectedItem.id] : selectedRowIds; + + if (itemIdsToDelete.length === 0) { + toast.error('Pilih minimal 1 item untuk dihapus'); return; } @@ -413,7 +479,7 @@ const PurchaseOrderDetail = ({ try { const res = await PurchaseDeleteItemsApi.deleteItems(purchaseRequestId, { - item_ids: [selectedItem.id], + item_ids: itemIdsToDelete, }); if (isResponseError(res)) { @@ -421,16 +487,21 @@ const PurchaseOrderDetail = ({ return; } - toast.success('Berhasil menghapus item pembelian'); + const successMessage = selectedItem + ? 'Berhasil menghapus item pembelian' + : `Berhasil menghapus ${itemIdsToDelete.length} item pembelian`; + + toast.success(successMessage); deleteModal.closeModal(); setSelectedItem(null); + setRowSelection({}); } catch (error) { toast.error('Terjadi kesalahan saat menghapus item pembelian'); } finally { setIsDeleteLoading(false); } - }, [purchaseData?.id, searchParams, selectedItem]); + }, [purchaseData?.id, searchParams, selectedItem, selectedRowIds]); // ===== COMPUTED VALUES ===== const approvalSteps = useMemo(() => { @@ -522,6 +593,7 @@ const PurchaseOrderDetail = ({ cell: (props) => { const deleteClickHandler = () => { setSelectedItem(props.row.original); + setRowSelection({}); // Clear row selection when doing single delete deleteModal.openModal(); }; @@ -857,6 +929,25 @@ const PurchaseOrderDetail = ({ /> + {/* Bulk Action Buttons */} + {selectedRowIds.length > 0 && ( +
+ +
+ )} + {/* Bottom Section - Catatan dan Total */}
{/* Catatan Section */} @@ -1024,14 +1115,18 @@ const PurchaseOrderDetail = ({ { - await deleteItemHandler(); + await deleteItemsHandler(); }, }} secondaryButton={{