feat: add server-side Excel export to PurchasesPerSupplierTab

Add exportToExcelSupplierPerSheet and exportToExcelGeneral methods to
LogisticApiService, hitting the existing purchase-supplier endpoint with
export=excel / export=excel-all query params and downloading the server
blob response. Replace the client-side Excel generation in
PurchasesPerSupplierTab with calls to these two service methods, and
split the single Export to Excel button into Export to Excel - Supplier
Per Sheet and Export to Excel - General.
This commit is contained in:
ValdiANS
2026-05-25 11:28:41 +07:00
parent 13eb0594a8
commit 7e6f250864
2 changed files with 160 additions and 16 deletions
@@ -16,7 +16,6 @@ import {
LogisticPurchasePerSupplierReport, LogisticPurchasePerSupplierReport,
LogisticPurchasePerSupplierSummary, LogisticPurchasePerSupplierSummary,
} from '@/types/api/report/logistic-stock'; } from '@/types/api/report/logistic-stock';
import { generatePurchasesPerSupplierExcel } from '@/components/pages/report/logistic-stock/export/PurchasesPerSupplierExportXLSX';
import { generatePurchasesPerSupplierPDF } from '@/components/pages/report/logistic-stock/export/PurchasesPerSupplierExportPDF'; import { generatePurchasesPerSupplierPDF } from '@/components/pages/report/logistic-stock/export/PurchasesPerSupplierExportPDF';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { ColumnDef } from '@tanstack/react-table'; import { ColumnDef } from '@tanstack/react-table';
@@ -53,7 +52,10 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
// ===== STATE MANAGEMENT ===== // ===== STATE MANAGEMENT =====
const [isPdfExportLoading, setIsPdfExportLoading] = useState(false); const [isPdfExportLoading, setIsPdfExportLoading] = useState(false);
const [isExcelExportLoading, setIsExcelExportLoading] = useState(false); const [isExcelExportLoading, setIsExcelExportLoading] = useState(false);
const isAnyExportLoading = isPdfExportLoading || isExcelExportLoading; const [isExcelGeneralExportLoading, setIsExcelGeneralExportLoading] =
useState(false);
const isAnyExportLoading =
isPdfExportLoading || isExcelExportLoading || isExcelGeneralExportLoading;
// ===== PAGINATION STATE ===== // ===== PAGINATION STATE =====
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
@@ -360,25 +362,44 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
const handleExportExcel = useCallback(async () => { const handleExportExcel = useCallback(async () => {
setIsExcelExportLoading(true); setIsExcelExportLoading(true);
try { try {
const allDataForExport = await logisticPurchasePerSupplierExport(); await LogisticApi.exportToExcelSupplierPerSheet(
filterParams.area_id,
if ( filterParams.supplier_id,
!allDataForExport || filterParams.product_id,
!Array.isArray(allDataForExport) || filterParams.product_category_id,
allDataForExport.length === 0 filterParams.start_date,
) { filterParams.end_date,
toast.error('Tidak ada data untuk diekspor.'); filterParams.sort_by,
return; filterParams.filter_by
} );
await generatePurchasesPerSupplierExcel({ data: allDataForExport });
toast.success('Excel berhasil dibuat dan diunduh.'); toast.success('Excel berhasil dibuat dan diunduh.');
} catch { } catch {
toast.error('Gagal membuat Excel. Silakan coba lagi.'); toast.error('Gagal membuat Excel. Silakan coba lagi.');
} finally { } finally {
setIsExcelExportLoading(false); setIsExcelExportLoading(false);
} }
}, [logisticPurchasePerSupplierExport]); }, [filterParams]);
const handleExportExcelGeneral = useCallback(async () => {
setIsExcelGeneralExportLoading(true);
try {
await LogisticApi.exportToExcelGeneral(
filterParams.area_id,
filterParams.supplier_id,
filterParams.product_id,
filterParams.product_category_id,
filterParams.start_date,
filterParams.end_date,
filterParams.sort_by,
filterParams.filter_by
);
toast.success('Excel General berhasil dibuat dan diunduh.');
} catch {
toast.error('Gagal membuat Excel General. Silakan coba lagi.');
} finally {
setIsExcelGeneralExportLoading(false);
}
}, [filterParams]);
const handleExportPdf = useCallback(async () => { const handleExportPdf = useCallback(async () => {
setIsPdfExportLoading(true); setIsPdfExportLoading(true);
@@ -523,7 +544,17 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap' className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
> >
<Icon icon='heroicons:table-cells' width={20} height={20} /> <Icon icon='heroicons:table-cells' width={20} height={20} />
Export to Excel Export to Excel - Supplier Per Sheet
</Button>
<Button
variant='ghost'
color='none'
onClick={handleExportExcelGeneral}
isLoading={isExcelGeneralExportLoading}
className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
>
<Icon icon='heroicons:table-cells' width={20} height={20} />
Export to Excel - General
</Button> </Button>
<Button <Button
variant='ghost' variant='ghost'
@@ -553,8 +584,10 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
filterParams, filterParams,
isAnyExportLoading, isAnyExportLoading,
handleExportExcel, handleExportExcel,
handleExportExcelGeneral,
handleExportPdf, handleExportPdf,
isExcelExportLoading, isExcelExportLoading,
isExcelGeneralExportLoading,
isPdfExportLoading, isPdfExportLoading,
]); ]);
+111
View File
@@ -1,4 +1,6 @@
import { BaseApiService } from '@/services/api/base'; import { BaseApiService } from '@/services/api/base';
import { httpClient } from '@/services/http/client';
import { formatDate } from '@/lib/helper';
import { BaseApiResponse } from '@/types/api/api-general'; import { BaseApiResponse } from '@/types/api/api-general';
import { LogisticPurchasePerSupplierReport } from '@/types/api/report/logistic-stock'; import { LogisticPurchasePerSupplierReport } from '@/types/api/report/logistic-stock';
@@ -11,6 +13,115 @@ export class LogisticApiService extends BaseApiService<
super(basePath); super(basePath);
} }
private buildPurchaseSupplierParams(
area_id?: string,
supplier_id?: string,
product_id?: string,
product_category_id?: string,
start_date?: string,
end_date?: string,
sort_by?: string,
filter_by?: string
): URLSearchParams {
const params = new URLSearchParams();
if (area_id) params.set('area_id', area_id);
if (supplier_id) params.set('supplier_id', supplier_id);
if (product_id) params.set('product_id', product_id);
if (product_category_id)
params.set('product_category_id', product_category_id);
if (filter_by === 'received_date' && start_date)
params.set('received_date', start_date);
if (filter_by === 'po_date' && start_date)
params.set('po_date', start_date);
if (start_date) params.set('start_date', start_date);
if (end_date) params.set('end_date', end_date);
if (sort_by) params.set('sort_by', sort_by);
if (filter_by) params.set('filter_by', filter_by);
return params;
}
async exportToExcelSupplierPerSheet(
area_id?: string,
supplier_id?: string,
product_id?: string,
product_category_id?: string,
start_date?: string,
end_date?: string,
sort_by?: string,
filter_by?: string
) {
const params = this.buildPurchaseSupplierParams(
area_id,
supplier_id,
product_id,
product_category_id,
start_date,
end_date,
sort_by,
filter_by
);
params.set('export', 'excel');
params.set('page', '1');
params.set('limit', '99999999999');
const res = await httpClient<Blob>(
`${this.basePath.replace(/\/$/, '')}/purchase-supplier?${params.toString()}`,
{ method: 'GET', responseType: 'blob' }
);
const url = window.URL.createObjectURL(new Blob([res]));
const link = document.createElement('a');
link.href = url;
link.setAttribute(
'download',
`laporan-pembelian-per-supplier-per-sheet-${formatDate(Date.now(), 'DD-MM-YYYY')}.xlsx`
);
document.body.appendChild(link);
link.click();
link.remove();
}
async exportToExcelGeneral(
area_id?: string,
supplier_id?: string,
product_id?: string,
product_category_id?: string,
start_date?: string,
end_date?: string,
sort_by?: string,
filter_by?: string
) {
const params = this.buildPurchaseSupplierParams(
area_id,
supplier_id,
product_id,
product_category_id,
start_date,
end_date,
sort_by,
filter_by
);
params.set('export', 'excel-all');
params.set('page', '1');
params.set('limit', '99999999999');
const res = await httpClient<Blob>(
`${this.basePath.replace(/\/$/, '')}/purchase-supplier?${params.toString()}`,
{ method: 'GET', responseType: 'blob' }
);
const url = window.URL.createObjectURL(new Blob([res]));
const link = document.createElement('a');
link.href = url;
link.setAttribute(
'download',
`laporan-pembelian-per-supplier-general-${formatDate(Date.now(), 'DD-MM-YYYY')}.xlsx`
);
document.body.appendChild(link);
link.click();
link.remove();
}
async getLogisticPurchasePerSupplierReport( async getLogisticPurchasePerSupplierReport(
area_id?: string, area_id?: string,
supplier_id?: string, supplier_id?: string,