diff --git a/src/components/pages/purchase/order/PurchaseOrderDetail.tsx b/src/components/pages/purchase/order/PurchaseOrderDetail.tsx index 778b2071..acbf6660 100644 --- a/src/components/pages/purchase/order/PurchaseOrderDetail.tsx +++ b/src/components/pages/purchase/order/PurchaseOrderDetail.tsx @@ -1,7 +1,7 @@ 'use client'; -import { useCallback, useMemo } from 'react'; -import { ColumnDef } from '@tanstack/react-table'; +import { useCallback, useMemo, useState } from 'react'; +import { ColumnDef, SortingState } from '@tanstack/react-table'; import ApprovalSteps, { formatGroupedApprovalsToApprovalSteps, @@ -10,8 +10,10 @@ import Table from '@/components/Table'; import Button from '@/components/Button'; import { Icon } from '@iconify/react'; import { useModal } from '@/components/Modal'; +import CheckboxInput from '@/components/input/CheckboxInput'; import Modal from '@/components/Modal'; import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; import RowDropdownOptions from '@/components/table/RowDropdownOptions'; import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper'; import PurchaseOrderStaffApprovalForm from '@/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm'; @@ -33,10 +35,14 @@ import { dummyProductWarehouses, dummyWarehouses, } from '@/dummy/marketing.dummy'; -import { ManagerApprovalApi } from '@/services/api/purchase'; +import { + ManagerApprovalApi, + PurchaseDeleteItemsApi, +} from '@/services/api/purchase'; import { isResponseError } from '@/lib/api-helper'; import { toast } from 'react-hot-toast'; import { useSearchParams } from 'next/navigation'; +import { formatCurrency, formatNumber, formatDate } from '@/lib/helper'; const ItemPembelianDropdown = ({ onEdit }: { onEdit: () => void }) => { return ( @@ -342,10 +348,20 @@ const PurchaseOrderDetail = ({ const acceptApprovalModal = useModal(); const editModal = useModal(); const penerimaanBarangModal = useModal(); + const deleteModal = useModal(); + + // ===== STATE MANAGEMENT ===== + const [sorting, setSorting] = useState([]); + const [rowSelection, setRowSelection] = useState>({}); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + const [selectedItem, setSelectedItem] = useState(null); // ===== STATIC DATA ===== const purchaseData = data || dummyPurchaseData; - const purchaseOrderItems = purchaseData.items || []; + const purchaseOrderItems = useMemo( + () => purchaseData.items || [], + [purchaseData.items] + ); const goodsReceiptItems = dummyGoodsReceiptItems; const groupedApprovals = dummyGroupedApprovals; const latestApproval = @@ -377,6 +393,45 @@ const PurchaseOrderDetail = ({ [purchaseData?.id, searchParams] ); + // ===== DELETE HANDLER ===== + const deleteItemHandler = useCallback(async () => { + const purchaseRequestId = searchParams.get('purchaseId') + ? parseInt(searchParams.get('purchaseId')!) + : purchaseData?.id || 1; + + if (!purchaseRequestId) { + toast.error('Purchase Request ID is required'); + return; + } + + if (!selectedItem) { + toast.error('Item tidak valid'); + return; + } + + setIsDeleteLoading(true); + + try { + const res = await PurchaseDeleteItemsApi.deleteItems(purchaseRequestId, { + item_ids: [selectedItem.id], + }); + + if (isResponseError(res)) { + toast.error(res.message || 'Gagal menghapus item pembelian'); + return; + } + + toast.success('Berhasil menghapus item pembelian'); + + deleteModal.closeModal(); + setSelectedItem(null); + } catch (error) { + toast.error('Terjadi kesalahan saat menghapus item pembelian'); + } finally { + setIsDeleteLoading(false); + } + }, [purchaseData?.id, searchParams, selectedItem]); + // ===== COMPUTED VALUES ===== const approvalSteps = useMemo(() => { if (!groupedApprovals.length || !latestApproval) return []; @@ -400,19 +455,33 @@ const PurchaseOrderDetail = ({ ); }, [purchaseOrderItems]); - const formatCurrency = (value: number) => { - return new Intl.NumberFormat('id-ID', { - style: 'currency', - currency: 'IDR', - minimumFractionDigits: 2, - }).format(value); - }; - - const formatNumber = (value: number) => { - return new Intl.NumberFormat('id-ID').format(value); - }; - const purchaseOrderColumns: ColumnDef[] = [ + { + id: 'select', + header: ({ table }) => ( +
+ +
+ ), + cell: ({ row }) => { + return ( +
+ +
+ ); + }, + }, { header: 'No', cell: (props) => props.row.index + 1, @@ -448,6 +517,26 @@ const PurchaseOrderDetail = ({ header: 'Total (Rp.)', cell: (props) => formatCurrency(props.getValue() as number), }, + { + header: 'Aksi', + cell: (props) => { + const deleteClickHandler = () => { + setSelectedItem(props.row.original); + deleteModal.openModal(); + }; + + return ( + + ); + }, + }, ]; const goodsReceiptColumns: ColumnDef[] = [ @@ -456,9 +545,7 @@ const PurchaseOrderDetail = ({ header: 'Tanggal Penerimaan', cell: (props) => props.row.original.received_date - ? new Date(props.row.original.received_date).toLocaleDateString( - 'id-ID' - ) + ? formatDate(props.row.original.received_date, 'DD MMM YYYY') : '-', }, { @@ -568,7 +655,7 @@ const PurchaseOrderDetail = ({ return (
- {/* Approval Action Buttons */} + {/* Approval and Action Buttons */}
@@ -758,6 +837,11 @@ const PurchaseOrderDetail = ({ data={purchaseOrderItems} columns={purchaseOrderColumns} isLoading={false} + sorting={sorting} + setSorting={setSorting} + rowSelection={rowSelection} + setRowSelection={setRowSelection} + enableRowSelection={() => true} className={{ containerClassName: 'm-0', tableWrapperClassName: 'overflow-x-auto', @@ -823,7 +907,9 @@ const PurchaseOrderDetail = ({ Informasi Penerimaan Barang - +
@@ -933,6 +1019,25 @@ const PurchaseOrderDetail = ({ onCancel={penerimaanBarangModal.closeModal} /> + + {/* Delete Confirmation Modal */} + { + await deleteItemHandler(); + }, + }} + secondaryButton={{ + text: 'Batal', + }} + />
); };