- Add utils/export.ts for centralized CSV export functionality - Add EmptyState component for consistent empty state UI - Add Pagination component for reusable pagination controls - Refactor employe/gains-client to use apiFetch and EmptyState - Refactor employe/historique to use apiFetch and EmptyState - Export new components from ui/index.ts Target: reduce duplication from 13.93% to under 3% 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
81 lines
2.2 KiB
TypeScript
81 lines
2.2 KiB
TypeScript
/**
|
|
* Utility functions for data export
|
|
*/
|
|
|
|
type CsvRow = (string | number | boolean | null | undefined)[];
|
|
|
|
/**
|
|
* Export data to CSV file
|
|
*/
|
|
export const exportToCSV = (
|
|
data: CsvRow[],
|
|
filename: string,
|
|
options?: { separator?: string; includeDate?: boolean }
|
|
): void => {
|
|
const { separator = ',', includeDate = true } = options || {};
|
|
|
|
const csvContent = data
|
|
.map((row) =>
|
|
row
|
|
.map((cell) => {
|
|
if (cell === null || cell === undefined) return '';
|
|
const cellStr = String(cell);
|
|
// Escape quotes and wrap in quotes if contains separator or quotes
|
|
if (cellStr.includes(separator) || cellStr.includes('"') || cellStr.includes('\n')) {
|
|
return `"${cellStr.replace(/"/g, '""')}"`;
|
|
}
|
|
return cellStr;
|
|
})
|
|
.join(separator)
|
|
)
|
|
.join('\n');
|
|
|
|
const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' });
|
|
const link = document.createElement('a');
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
const date = includeDate ? `-${new Date().toISOString().split('T')[0]}` : '';
|
|
link.href = url;
|
|
link.download = `${filename}${date}.csv`;
|
|
link.style.display = 'none';
|
|
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
URL.revokeObjectURL(url);
|
|
};
|
|
|
|
/**
|
|
* Export data to JSON file
|
|
*/
|
|
export const exportToJSON = <T>(data: T, filename: string): 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.href = url;
|
|
link.download = `${filename}-${new Date().toISOString().split('T')[0]}.json`;
|
|
link.style.display = 'none';
|
|
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
URL.revokeObjectURL(url);
|
|
};
|
|
|
|
/**
|
|
* Format date for export
|
|
*/
|
|
export const formatDateForExport = (date: string | Date | null | undefined): string => {
|
|
if (!date) return '';
|
|
const d = new Date(date);
|
|
return d.toLocaleDateString('fr-FR', {
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
});
|
|
};
|