feat: add export to excel feature

This commit is contained in:
ValdiANS
2026-05-21 14:43:08 +07:00
parent 7e1fab9a69
commit 027668a1bf
2 changed files with 87 additions and 1 deletions
+62 -1
View File
@@ -29,7 +29,7 @@ import {
FINANCE_TRANSACTION_TYPE_OPTIONS,
} from '@/config/constant';
import { FinanceApi } from '@/services/api/finance';
import { isResponseSuccess } from '@/lib/api-helper';
import { getErrorMessage, isResponseSuccess } from '@/lib/api-helper';
import { BankApi, CustomerApi, SupplierApi } from '@/services/api/master-data';
import { Bank } from '@/types/api/master-data/bank';
import Modal, { useModal } from '@/components/Modal';
@@ -39,6 +39,7 @@ import ConfirmationModal from '@/components/modal/ConfirmationModal';
import toast from 'react-hot-toast';
import RequirePermission from '@/components/helper/RequirePermission';
import ButtonFilter from '@/components/helper/ButtonFilter';
import Dropdown from '@/components/dropdown/Dropdown';
import {
FinanceTableFilterSchema,
FinanceTableFilterValues,
@@ -233,6 +234,7 @@ const FinanceTable = () => {
const [selectedSortBy, setSelectedSortBy] = useState<OptionType | null>(null);
const [selectedFinance, setSelectedFinance] = useState<Finance | null>(null);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const [isExportLoading, setIsExportLoading] = useState(false);
const [dateErrorShown, setDateErrorShown] = useState(false);
const [hasDateError, setHasDateError] = useState(false);
@@ -552,6 +554,20 @@ const FinanceTable = () => {
filterModal.openModal();
};
const exportToExcel = async () => {
setIsExportLoading(true);
try {
await FinanceApi.exportToExcel(getTableFilterQueryString());
toast.success('Excel berhasil dibuat dan diunduh.');
} catch (error) {
toast.error(
await getErrorMessage(error, 'Gagal mengekspor data finance.')
);
} finally {
setIsExportLoading(false);
}
};
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
@@ -759,6 +775,51 @@ const FinanceTable = () => {
onClick={handleFilterModalOpen}
className='px-3 py-2.5'
/>
<Dropdown
align='end'
direction='bottom'
className={{
content:
'mt-1 rounded-xl border border-base-content/5 shadow-sm overflow-hidden',
}}
trigger={
<Button
variant='outline'
color='none'
className='px-3 py-2.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft'
>
<div className='flex flex-row items-center gap-1.5'>
<Icon
icon='heroicons:cloud-arrow-down'
width={20}
height={20}
/>
<span>Ekspor</span>
<div className='w-px self-stretch bg-base-content/10' />
<Icon
icon='heroicons:chevron-down'
width={14}
height={14}
/>
</div>
</Button>
}
>
<Button
variant='ghost'
color='none'
onClick={exportToExcel}
isLoading={isExportLoading}
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} />
Ekspor ke Excel
</Button>
</Dropdown>
</div>
</div>
+25
View File
@@ -2,6 +2,7 @@ import axios from 'axios';
import { BaseApiService } from '@/services/api/base';
import { BaseApiResponse } from '@/types/api/api-general';
import { httpClient, httpClientFetcher } from '@/services/http/client';
import { formatDate } from '@/lib/helper';
import {
CreateFinancePayment,
CreateInitialBalance,
@@ -174,6 +175,30 @@ export class FinanceApiService extends BaseApiService<
}
}
async exportToExcel(initialQueryString: string) {
const params = new URLSearchParams(initialQueryString);
params.set('export', 'excel');
params.set('page', '1');
params.set('limit', '99999999999');
const res = await httpClient<Blob>(
`${this.basePath}/transactions?${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',
`finance-${formatDate(Date.now(), 'DD-MM-YYYY')}.xlsx`
);
document.body.appendChild(link);
link.click();
link.remove();
}
async delete(id: number) {
try {
const deletePath = `${this.basePath}/transactions/${id}`;