Files
emaui/apps/backoffice/src/app/features/license-review/export.ts
estifanos 31c52c02e0 feat: introduce useLocalized hook for bilingual value retrieval.(localization round 2)
- 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.
2026-08-12 11:31:20 +00:00

72 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}