mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-30 02:58:12 +00:00
- Added useLocalized hook to provide a stable function for retrieving bilingual values based on the current language. - Updated various components across the portal and backoffice to utilize the new useLocalized hook for consistent bilingual label rendering. - Refactored localized function in licensing.helpers to handle empty Amharic strings correctly. - Enhanced localization handling in LicenseApplicationPage, ProfilePage, and other components to ensure proper language switching.
72 lines
2.8 KiB
TypeScript
72 lines
2.8 KiB
TypeScript
import { STATUS_LABELS, localized, type LicenseApplication } from '@ema-platform/api';
|
||
import { dateDisplayer } from '@ema-platform/shared';
|
||
import { computeSla } from './sla';
|
||
|
||
/**
|
||
* Escapes one CSV field.
|
||
*
|
||
* Company names routinely contain commas, and remarks contain quotes and
|
||
* newlines — unescaped, either one shifts every later column on the row.
|
||
*/
|
||
function csvCell(value: unknown): string {
|
||
if (value === null || value === undefined) return '';
|
||
const text = String(value);
|
||
return /[",\n\r]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
|
||
}
|
||
|
||
const COLUMNS: Array<{
|
||
header: string;
|
||
value: (app: LicenseApplication, locale: string) => unknown;
|
||
}> = [
|
||
{ header: 'Application #', value: (a) => a.applicationNumber },
|
||
{ header: 'Company', value: (a) => a.companyName },
|
||
{ header: 'Trade name', value: (a) => a.tradeName },
|
||
{ header: 'TIN', value: (a) => a.tinNumber },
|
||
{ header: 'Licence type', value: (a, locale) => localized(a.licenseType?.name, locale) || a.licenseTypeId },
|
||
{ header: 'Status', value: (a) => STATUS_LABELS[a.status] },
|
||
{ header: 'Kind', value: (a) => a.kind },
|
||
{ header: 'Assigned officer', value: (a) => a.assignedOfficerId },
|
||
{
|
||
header: 'Submitted',
|
||
value: (a, locale) => (a.submittedAt ? dateDisplayer(a.submittedAt, locale) : ''),
|
||
},
|
||
{
|
||
header: 'Decided',
|
||
value: (a, locale) => (a.decidedAt ? dateDisplayer(a.decidedAt, locale) : ''),
|
||
},
|
||
{ header: 'SLA', value: (a, locale) => computeSla(a, undefined, locale).label },
|
||
{ header: 'Adjustment rounds', value: (a) => a.adjustmentRound },
|
||
{ header: 'Declared capital', value: (a) => a.capitalAmountDeclared },
|
||
{ header: 'Verified capital', value: (a) => a.capitalAmountVerified },
|
||
];
|
||
|
||
/**
|
||
* Exports exactly the rows passed in.
|
||
*
|
||
* Takes the already-filtered, already-paged list rather than re-querying, so
|
||
* what lands in the file is what the officer was looking at. Note this means
|
||
* an export covers the current page — exporting a whole filtered result set
|
||
* would need a server-side export endpoint, which does not exist.
|
||
*/
|
||
export function exportApplicationsCsv(
|
||
applications: LicenseApplication[],
|
||
locale: string,
|
||
filename = `licence-applications-${new Date().toISOString().slice(0, 10)}.csv`,
|
||
): void {
|
||
const header = COLUMNS.map((column) => csvCell(column.header)).join(',');
|
||
const rows = applications.map((app) =>
|
||
COLUMNS.map((column) => csvCell(column.value(app, locale))).join(','),
|
||
);
|
||
// BOM so Excel opens Amharic and other non-ASCII content as UTF-8.
|
||
const blob = new Blob(['', [header, ...rows].join('\r\n')], {
|
||
type: 'text/csv;charset=utf-8;',
|
||
});
|
||
|
||
const url = URL.createObjectURL(blob);
|
||
const link = document.createElement('a');
|
||
link.href = url;
|
||
link.download = filename;
|
||
link.click();
|
||
URL.revokeObjectURL(url);
|
||
}
|