Initial commit
Some checks failed
CI / test (push) Has been cancelled
CI / security (push) Has been cancelled
CI / build (push) Has been cancelled

This commit is contained in:
defiQUG
2025-12-12 15:02:56 -08:00
commit 849e6a8357
891 changed files with 167728 additions and 0 deletions

View File

@@ -0,0 +1,184 @@
// Export utilities for CSV and PDF
export interface ExportData {
headers: string[];
rows: (string | number)[][];
title?: string;
}
/**
* Export data to CSV
*/
export function exportToCSV(data: ExportData, filename: string = 'export.csv'): void {
const { headers, rows } = data;
// Create CSV content
const csvContent = [
headers.join(','),
...rows.map((row) => row.map((cell) => `"${cell}"`).join(',')),
].join('\n');
// Create blob and download
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
/**
* Export table data to CSV
*/
export function exportTableToCSV(
tableId: string,
filename: string = 'table-export.csv'
): void {
const table = document.getElementById(tableId) as HTMLTableElement;
if (!table) {
console.error('Table not found:', tableId);
return;
}
const headers: string[] = [];
const rows: (string | number)[][] = [];
// Get headers
const headerRow = table.querySelector('thead tr');
if (headerRow) {
headerRow.querySelectorAll('th').forEach((th) => {
headers.push(th.textContent?.trim() || '');
});
}
// Get rows
table.querySelectorAll('tbody tr').forEach((tr) => {
const row: (string | number)[] = [];
tr.querySelectorAll('td').forEach((td) => {
row.push(td.textContent?.trim() || '');
});
if (row.length > 0) {
rows.push(row);
}
});
exportToCSV({ headers, rows }, filename);
}
/**
* Export data to JSON
*/
export function exportToJSON(data: any, filename: string = 'export.json'): void {
const jsonContent = JSON.stringify(data, null, 2);
const blob = new Blob([jsonContent], { type: 'application/json;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
/**
* Generate PDF using browser print (simple approach)
* For more advanced PDF generation, consider using libraries like jsPDF or pdfmake
*/
export function exportToPDF(
elementId: string,
filename: string = 'export.pdf',
title?: string
): void {
const element = document.getElementById(elementId);
if (!element) {
console.error('Element not found:', elementId);
return;
}
// Create a new window for printing
const printWindow = window.open('', '_blank');
if (!printWindow) {
console.error('Could not open print window');
return;
}
printWindow.document.write(`
<html>
<head>
<title>${title || 'Export'}</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
font-weight: bold;
}
</style>
</head>
<body>
${element.innerHTML}
</body>
</html>
`);
printWindow.document.close();
printWindow.focus();
// Wait for content to load, then print
setTimeout(() => {
printWindow.print();
// Optionally close after printing
// printWindow.close();
}, 250);
}
/**
* Format data for export from DataTable component
*/
export function formatDataForExport<T extends Record<string, any>>(
data: T[],
columns: Array<{ key: string; header: string; render?: (row: T) => any }>
): ExportData {
const headers = columns.map((col) => col.header);
const rows = data.map((row) =>
columns.map((col) => {
if (col.render) {
// For rendered cells, try to extract meaningful text
const rendered = col.render(row);
if (typeof rendered === 'string' || typeof rendered === 'number') {
return rendered;
}
// For React elements, fall back to raw value
return String(row[col.key] || '');
}
const value = row[col.key];
if (value === null || value === undefined) {
return '';
}
return String(value);
})
);
return { headers, rows };
}

View File

@@ -0,0 +1,29 @@
// Formatting utilities
export function formatCurrency(value: number, currency: string = 'USD'): string {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(value);
}
export function formatNumber(value: number, decimals: number = 2): string {
return new Intl.NumberFormat('en-US', {
minimumFractionDigits: decimals,
maximumFractionDigits: decimals,
}).format(value);
}
export function formatPercentage(value: number, decimals: number = 2): string {
return `${formatNumber(value, decimals)}%`;
}
export function formatBytes(bytes: number): string {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
}