fix(FE): fixing pixel perfect marketing table

This commit is contained in:
randy-ar
2026-01-30 15:53:51 +07:00
parent 8bf0f067bb
commit 73319bbdfa
5 changed files with 694 additions and 459 deletions
+78 -4
View File
@@ -1,5 +1,6 @@
import { isResponseError } from '@/lib/api-helper';
import { BaseApiService } from '@/services/api/base';
import { httpClient } from '@/services/http/client';
import { httpClient, httpClientFetcher } from '@/services/http/client';
import { BaseApiResponse } from '@/types/api/api-general';
import {
Marketing,
@@ -8,6 +9,9 @@ import {
CreateDeliveryOrderPayload,
UpdateDeliveryOrderPayload,
} from '@/types/api/marketing/marketing';
import toast from 'react-hot-toast';
import * as XLSX from 'xlsx';
import { formatCurrency, formatDate, formatTitleCase } from '@/lib/helper';
/**
* 💡 Helper untuk membuat respons dummy
@@ -97,6 +101,78 @@ export class SalesOrderService extends BaseApiService<
}
}
}
class MarketingExportService extends BaseApiService<
Marketing,
unknown,
unknown
> {
constructor(basePath: string = '/marketing') {
super(basePath);
}
/**
* Export to Excel
*/
async exportToExcel(initialQueryString: string) {
const params = new URLSearchParams(initialQueryString);
const queryString = `?${params.toString()}`;
try {
const marketingData = await httpClientFetcher<
BaseApiResponse<Marketing[]>
>(`${this.basePath}${queryString}`);
if (isResponseError(marketingData)) {
toast.error('Gagal melakukan export marketing! Coba lagi.');
return;
}
const rows = marketingData.data;
const formattedRows = [];
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
const approval = row.latest_approval;
const isRejected = approval?.action === 'REJECTED';
// Calculate grand total from sales_order products
const grandTotal =
row.sales_order
?.map((product) => product.total_price)
.reduce((a, b) => a + b, 0) ?? 0;
// Get product names
const products =
row.sales_order
?.map((product) => product.product_warehouse?.product?.name)
.filter(Boolean)
.join(', ') ?? '';
formattedRows.push({
'No. Order': row.so_number,
Tanggal: formatDate(row.so_date, 'DD-MM-YYYY'),
Status: isRejected
? 'Ditolak'
: formatTitleCase(approval?.step_name || ''),
Customer: row.customer?.name || '',
'Grand Total': formatCurrency(grandTotal),
Products: products,
Notes: row.notes || '',
});
}
const ws = XLSX.utils.json_to_sheet(formattedRows);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, 'marketing');
// triggers download in browser
XLSX.writeFile(wb, 'marketing.xlsx');
} catch (error) {
toast.error('Gagal melakukan export marketing! Coba lagi.');
}
}
}
export const SalesOrderApi = new SalesOrderService('/marketing/sales-orders');
export const DeliveryOrderApi = new BaseApiService<
@@ -104,6 +180,4 @@ export const DeliveryOrderApi = new BaseApiService<
CreateDeliveryOrderPayload,
UpdateDeliveryOrderPayload
>('/marketing/delivery-orders');
export const MarketingApi = new BaseApiService<Marketing, unknown, unknown>(
'/marketing'
);
export const MarketingApi = new MarketingExportService('/marketing');