From 8f6597e7df1a0e2968377186717afe3ae22c2712 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 27 Jan 2026 18:58:03 +0700 Subject: [PATCH 1/2] feat: add exportToExcel method --- .../api/production/transfer-to-laying.ts | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/src/services/api/production/transfer-to-laying.ts b/src/services/api/production/transfer-to-laying.ts index db3d815c..27c88536 100644 --- a/src/services/api/production/transfer-to-laying.ts +++ b/src/services/api/production/transfer-to-laying.ts @@ -1,3 +1,4 @@ +import * as XLSX from 'xlsx'; import axios from 'axios'; import { BaseApiService } from '@/services/api/base'; import { @@ -11,12 +12,14 @@ import { TransferToLaying, UpdateTransferToLayingPayload, } from '@/types/api/production/transfer-to-laying'; -import { httpClient } from '@/services/http/client'; +import { httpClient, httpClientFetcher } from '@/services/http/client'; import { ProjectFlockAvailableQuantity, ProjectFlockMaxQuantity, } from '@/types/api/production/project-flock'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; +import toast from 'react-hot-toast'; +import { formatDate } from '@/lib/helper'; export class TransferToLayingService extends BaseApiService< TransferToLaying, @@ -221,6 +224,60 @@ export class TransferToLayingService extends BaseApiService< } } + async exportToExcel(initialQueryString: string) { + const params = new URLSearchParams(initialQueryString); + + params.set('limit', '9999999'); + + const queryString = `?${params.toString()}`; + + try { + const transferToLayings = await httpClientFetcher< + BaseApiResponse + >(`${this.basePath}${queryString}`); + + if (isResponseError(transferToLayings)) { + toast.error('Gagal melakukan export transfer to laying! Coba lagi.'); + return; + } + + const rows = transferToLayings.data; + + const formattedRows = []; + + for (let i = 0; i < rows.length; i++) { + formattedRows.push({ + id: rows[i].id, + transfer_number: rows[i].transfer_number, + transfer_date: formatDate(rows[i].transfer_date, 'DD-MM-YYYY'), + project_flock_source: rows[i].from_project_flock.flock_name, + project_flock_target: rows[i].to_project_flock.flock_name, + pending_usage_qty: rows[i].pending_usage_qty, + usage_qty: rows[i].usage_qty, + project_flock_source_kandang: rows[i].sources + .map((item) => item.source_project_flock_kandang.kandang.name) + .join(', '), + project_flock_target_kandang: rows[i].targets + .map((item) => item.target_project_flock_kandang.kandang.name) + .join(', '), + created_user: rows[i].created_user.name, + created_at: formatDate(rows[i].created_at, 'DD-MM-YYYY'), + updated_at: formatDate(rows[i].updated_at, 'DD-MM-YYYY'), + notes: rows[i].notes, + }); + } + + const ws = XLSX.utils.json_to_sheet(formattedRows); + const wb = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(wb, ws, 'transfer-ke-laying'); + + // triggers download in browser + XLSX.writeFile(wb, 'transfer-ke-laying.xlsx'); + } catch (error) { + toast.error('Gagal melakukan export transfer to laying! Coba lagi.'); + } + } + async getApprovalHistory( transferToLayingId: number, group: boolean = true, From 5fe0236686366b0dfcebcbb3d638a7ba3d4e77bc Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 27 Jan 2026 18:58:47 +0700 Subject: [PATCH 2/2] feat: implement export to excel --- .../transfer-to-laying/TransferToLayingsTable.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/components/pages/production/transfer-to-laying/TransferToLayingsTable.tsx b/src/components/pages/production/transfer-to-laying/TransferToLayingsTable.tsx index 7817c427..438c529c 100644 --- a/src/components/pages/production/transfer-to-laying/TransferToLayingsTable.tsx +++ b/src/components/pages/production/transfer-to-laying/TransferToLayingsTable.tsx @@ -183,6 +183,9 @@ const TransferToLayingsTable = () => { const isFilterActive = filterCount > 0; + const [isLoadingExportingToExcel, setIsLoadingExportingToExcel] = + useState(false); + // Modal hooks const filterModal = useModal(); const deleteModal = useModal(); @@ -453,9 +456,12 @@ const TransferToLayingsTable = () => { updateFilter('status', ''); }; - // TODO: add export to excel functionality - const exportToExcelHandler = () => { - toast.error('Not implemented yet'); + const exportToExcelHandler = async () => { + setIsLoadingExportingToExcel(true); + + await TransferToLayingApi.exportToExcel(getTableFilterQueryString()); + + setIsLoadingExportingToExcel(false); }; useEffect(() => { @@ -615,6 +621,7 @@ const TransferToLayingsTable = () => { variant='ghost' color='none' onClick={exportToExcelHandler} + isLoading={isLoadingExportingToExcel} className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap' >