155 lines
3.9 KiB
TypeScript
155 lines
3.9 KiB
TypeScript
import { csvCell } from './csv-cell';
|
|
/**
|
|
* Client-side export utilities
|
|
*/
|
|
|
|
import * as XLSX from 'xlsx';
|
|
import { saveAs } from 'file-saver';
|
|
import { Booking } from '@/types/booking';
|
|
|
|
export interface ExportField {
|
|
key: string;
|
|
label: string;
|
|
formatter?: (value: any) => string;
|
|
}
|
|
|
|
const DEFAULT_BOOKING_FIELDS: ExportField[] = [
|
|
{ key: 'bookingNumber', label: 'Booking Number' },
|
|
{ key: 'status', label: 'Status' },
|
|
{ key: 'rateQuote.carrierName', label: 'Carrier' },
|
|
{ key: 'rateQuote.origin', label: 'Origin' },
|
|
{ key: 'rateQuote.destination', label: 'Destination' },
|
|
{ key: 'shipper.name', label: 'Shipper' },
|
|
{ key: 'consignee.name', label: 'Consignee' },
|
|
{
|
|
key: 'rateQuote.etd',
|
|
label: 'ETD',
|
|
formatter: value => (value ? new Date(value).toLocaleDateString() : ''),
|
|
},
|
|
{
|
|
key: 'rateQuote.eta',
|
|
label: 'ETA',
|
|
formatter: value => (value ? new Date(value).toLocaleDateString() : ''),
|
|
},
|
|
{
|
|
key: 'containers',
|
|
label: 'Containers',
|
|
formatter: value => (Array.isArray(value) ? value.length.toString() : '0'),
|
|
},
|
|
{
|
|
key: 'createdAt',
|
|
label: 'Created',
|
|
formatter: value => new Date(value).toLocaleDateString(),
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Get nested object value by key path
|
|
*/
|
|
function getNestedValue(obj: any, path: string): any {
|
|
return path.split('.').reduce((current, key) => current?.[key], obj);
|
|
}
|
|
|
|
/**
|
|
* Export bookings to CSV
|
|
*/
|
|
export function exportToCSV(
|
|
data: Booking[],
|
|
fields: ExportField[] = DEFAULT_BOOKING_FIELDS,
|
|
filename: string = 'bookings-export.csv'
|
|
): void {
|
|
// Create CSV header
|
|
const header = fields.map(f => csvCell(f.label)).join(',');
|
|
|
|
// Create CSV rows
|
|
const rows = data.map(booking => {
|
|
return fields
|
|
.map(field => {
|
|
const value = getNestedValue(booking, field.key);
|
|
const formatted = field.formatter ? field.formatter(value) : value;
|
|
// Escape quotes and wrap in quotes if contains comma
|
|
return csvCell(formatted);
|
|
})
|
|
.join(',');
|
|
});
|
|
|
|
// Combine header and rows
|
|
const csv = [header, ...rows].join('\n');
|
|
|
|
// Create blob and download
|
|
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
|
|
saveAs(blob, filename);
|
|
}
|
|
|
|
/**
|
|
* Export bookings to Excel
|
|
*/
|
|
export function exportToExcel(
|
|
data: Booking[],
|
|
fields: ExportField[] = DEFAULT_BOOKING_FIELDS,
|
|
filename: string = 'bookings-export.xlsx'
|
|
): void {
|
|
// Create worksheet data
|
|
const wsData = [
|
|
// Header row
|
|
fields.map(f => f.label),
|
|
// Data rows
|
|
...data.map(booking =>
|
|
fields.map(field => {
|
|
const value = getNestedValue(booking, field.key);
|
|
return field.formatter ? field.formatter(value) : value || '';
|
|
})
|
|
),
|
|
];
|
|
|
|
// Create worksheet
|
|
const ws = XLSX.utils.aoa_to_sheet(wsData);
|
|
|
|
// Set column widths
|
|
ws['!cols'] = fields.map(() => ({ wch: 20 }));
|
|
|
|
// Create workbook
|
|
const wb = XLSX.utils.book_new();
|
|
XLSX.utils.book_append_sheet(wb, ws, 'Bookings');
|
|
|
|
// Generate Excel file
|
|
const excelBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
|
|
const blob = new Blob([excelBuffer], {
|
|
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
});
|
|
saveAs(blob, filename);
|
|
}
|
|
|
|
/**
|
|
* Export bookings to JSON
|
|
*/
|
|
export function exportToJSON(data: Booking[], filename: string = 'bookings-export.json'): void {
|
|
const json = JSON.stringify(data, null, 2);
|
|
const blob = new Blob([json], { type: 'application/json;charset=utf-8;' });
|
|
saveAs(blob, filename);
|
|
}
|
|
|
|
/**
|
|
* Export bookings based on format
|
|
*/
|
|
export function exportBookings(
|
|
data: Booking[],
|
|
format: 'csv' | 'excel' | 'json',
|
|
fields?: ExportField[],
|
|
filename?: string
|
|
): void {
|
|
switch (format) {
|
|
case 'csv':
|
|
exportToCSV(data, fields, filename);
|
|
break;
|
|
case 'excel':
|
|
exportToExcel(data, fields, filename);
|
|
break;
|
|
case 'json':
|
|
exportToJSON(data, filename);
|
|
break;
|
|
default:
|
|
throw new Error(`Unsupported export format: ${format}`);
|
|
}
|
|
}
|