@platform-modules/civil-aviation-authority 2.3.279 → 2.3.281

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,327 +1,5 @@
1
- import catalog from './workflow-chat-i18n.json';
2
-
3
- export type BilingualText = { en: string; ar: string };
4
-
5
- type WorkflowChatI18nCatalog = {
6
- workflowTemplates: Record<string, BilingualText>;
7
- chatTemplates: Record<string, BilingualText>;
8
- workflowStatusLabels: Record<string, string>;
9
- chatStatusLabels: Record<string, string>;
10
- };
11
-
12
- const WORKFLOW_TEMPLATES = catalog.workflowTemplates as Record<string, BilingualText>;
13
- const CHAT_TEMPLATES = catalog.chatTemplates as Record<string, BilingualText>;
14
- const WORKFLOW_STATUS_LABELS = catalog.workflowStatusLabels as Record<string, string>;
15
- const CHAT_STATUS_LABELS = catalog.chatStatusLabels as Record<string, string>;
16
-
17
- /** Read-only view of the shared workflow/chat translation catalog. */
18
- export function getWorkflowChatI18nCatalog(): WorkflowChatI18nCatalog {
19
- return catalog as WorkflowChatI18nCatalog;
20
- }
21
-
22
- function interpolate(template: string, params: Record<string, string> = {}): string {
23
- return template.replace(/\{\{(\w+)\}\}/g, (_, key: string) => params[key] ?? '');
24
- }
25
-
26
- export function buildBilingualFromTemplate(
27
- templateCatalog: Record<string, BilingualText>,
28
- key: string,
29
- params: Record<string, string> = {},
30
- arParams?: Record<string, string>,
31
- ): BilingualText {
32
- const tpl = templateCatalog[key];
33
- if (!tpl) {
34
- return { en: key, ar: key };
35
- }
36
- const arabicParams = arParams ?? params;
37
- return {
38
- en: interpolate(tpl.en, params),
39
- ar: interpolate(tpl.ar, arabicParams),
40
- };
41
- }
42
-
43
- export function workflowTemplate(
44
- key: string,
45
- params: Record<string, string> = {},
46
- arParams?: Record<string, string>,
47
- ): BilingualText {
48
- return buildBilingualFromTemplate(WORKFLOW_TEMPLATES, key, params, arParams);
49
- }
50
-
51
- export function chatTemplate(
52
- key: string,
53
- params: Record<string, string> = {},
54
- arParams?: Record<string, string>,
55
- ): BilingualText {
56
- return buildBilingualFromTemplate(CHAT_TEMPLATES, key, params, arParams);
57
- }
58
-
59
- export function resolveWorkflowStatusAr(status: string | null | undefined): string | null {
60
- if (status == null || status === '') return null;
61
- return WORKFLOW_STATUS_LABELS[status] ?? status;
62
- }
63
-
64
- export function resolveChatStatusAr(status: string | null | undefined): string | null {
65
- if (status == null || status === '') return null;
66
- return CHAT_STATUS_LABELS[status] ?? status;
67
- }
68
-
69
- /** Arabic DB value when present; otherwise English so AR text stays structurally complete. */
70
- export function resolveBilingualName(
71
- englishName?: string | null,
72
- arabicName?: string | null,
73
- ): string {
74
- const ar = arabicName?.trim();
75
- if (ar) return ar;
76
- return englishName?.trim() || '';
77
- }
78
-
79
- export function pickArabicName(arabicName?: string | null, fallback = ''): string {
80
- return arabicName?.trim() || fallback;
81
- }
82
-
83
- export function pickLocalizedName(
84
- englishName?: string | null,
85
- arabicName?: string | null,
86
- fallback = ''
87
- ): string {
88
- const ar = arabicName?.trim();
89
- if (ar) return ar;
90
- const en = englishName?.trim();
91
- if (en) return en;
92
- return fallback;
93
- }
94
-
95
- function joinDeptSectionLabels(
96
- dept?: string | null,
97
- section?: string | null,
98
- ): string {
99
- return [dept, section].map((s) => s?.trim()).filter(Boolean).join(' - ');
100
- }
101
-
102
- /** Parallel EN/AR dept-section labels (Arabic columns preferred; English fallback per field). */
103
- export function joinDeptSectionBilingualLabels(
104
- deptEn?: string | null,
105
- deptAr?: string | null,
106
- sectEn?: string | null,
107
- sectAr?: string | null,
108
- ): { en: string; ar: string } {
109
- const en = joinDeptSectionLabels(deptEn, sectEn);
110
- const ar = joinDeptSectionLabels(
111
- resolveBilingualName(deptEn, deptAr),
112
- resolveBilingualName(sectEn, sectAr),
113
- );
114
- return { en, ar };
115
- }
116
-
117
- /** @deprecated Use joinDeptSectionBilingualLabels */
118
- export function joinDeptSectionArabicLabels(
119
- deptArabic?: string | null,
120
- sectionArabic?: string | null,
121
- ): string {
122
- return joinDeptSectionLabels(deptArabic, sectionArabic);
123
- }
124
-
125
- function formatWorkflowCommentSuffix(comment?: string | null): string {
126
- const text = comment?.trim();
127
- return text ? `: ${text}` : '';
128
- }
129
-
130
- function formatChatCommentSuffix(comment?: string | null): string {
131
- const text = comment?.trim();
132
- return text ? ` - ${text}` : '';
133
- }
134
-
135
- function buildWorkflowApprovalByName(
136
- templateKey: 'request_approved_by' | 'request_rejected_by' | 'request_returned_for_modification_by',
137
- nameEn: string,
138
- nameAr: string,
139
- comment?: string | null,
140
- ): BilingualText {
141
- const commentSuffix = formatWorkflowCommentSuffix(comment);
142
- return workflowTemplate(
143
- templateKey,
144
- { name: nameEn, comment: commentSuffix },
145
- { name: nameAr, comment: commentSuffix },
146
- );
147
- }
148
-
149
- function buildWorkflowApprovalWithoutName(
150
- templateKey: 'request_approved' | 'request_rejected' | 'request_returned_for_modification',
151
- comment?: string | null,
152
- ): BilingualText {
153
- const commentSuffix = formatWorkflowCommentSuffix(comment);
154
- return workflowTemplate(
155
- templateKey,
156
- { comment: commentSuffix },
157
- { comment: commentSuffix },
158
- );
159
- }
160
-
161
- export function buildApprovalWorkflowContent(params: {
162
- status: 'Approved' | 'Rejected' | 'Returned for Modification' | 'Pending' | string;
163
- roleName?: string | null;
164
- roleArabicName?: string | null;
165
- comment?: string | null;
166
- }): BilingualText {
167
- const nameEn = params.roleName?.trim() || '';
168
- const nameAr = resolveBilingualName(nameEn, params.roleArabicName);
169
-
170
- if (params.status === 'Approved') {
171
- return nameEn
172
- ? buildWorkflowApprovalByName('request_approved_by', nameEn, nameAr, params.comment)
173
- : buildWorkflowApprovalWithoutName('request_approved', params.comment);
174
- }
175
-
176
- if (params.status === 'Rejected') {
177
- return nameEn
178
- ? buildWorkflowApprovalByName('request_rejected_by', nameEn, nameAr, params.comment)
179
- : buildWorkflowApprovalWithoutName('request_rejected', params.comment);
180
- }
181
-
182
- if (params.status === 'Returned for Modification') {
183
- return nameEn
184
- ? buildWorkflowApprovalByName('request_returned_for_modification_by', nameEn, nameAr, params.comment)
185
- : buildWorkflowApprovalWithoutName('request_returned_for_modification', params.comment);
186
- }
187
-
188
- const commentSuffix = formatWorkflowCommentSuffix(params.comment);
189
- if (nameEn) {
190
- return workflowTemplate(
191
- 'request_approval_pending_from',
192
- { name: nameEn, comment: commentSuffix },
193
- { name: nameAr, comment: commentSuffix },
194
- );
195
- }
196
-
197
- return workflowTemplate(
198
- 'request_approval_pending',
199
- { comment: commentSuffix },
200
- { comment: commentSuffix },
201
- );
202
- }
203
-
204
- export function buildHumanApprovalWorkflowContent(params: {
205
- isFirst: boolean;
206
- roleName?: string | null;
207
- roleArabicName?: string | null;
208
- deptName?: string | null;
209
- deptArabicName?: string | null;
210
- sectionName?: string | null;
211
- sectionArabicName?: string | null;
212
- }): BilingualText {
213
- const key = params.isFirst ? 'request_approval_in_progress_from' : 'request_approval_pending_from';
214
-
215
- if (params.roleName?.trim()) {
216
- const nameEn = params.roleName.trim();
217
- const nameAr = resolveBilingualName(nameEn, params.roleArabicName);
218
- return workflowTemplate(key, { name: nameEn }, { name: nameAr });
219
- }
220
-
221
- const { en, ar } = joinDeptSectionBilingualLabels(
222
- params.deptName,
223
- params.deptArabicName,
224
- params.sectionName,
225
- params.sectionArabicName,
226
- );
227
- if (en) {
228
- return workflowTemplate(key, { name: en }, { name: ar });
229
- }
230
-
231
- return params.isFirst
232
- ? workflowTemplate('request_approval_in_progress')
233
- : workflowTemplate('request_approval_pending');
234
- }
235
-
236
- export function buildApprovalChatMessage(params: {
237
- status: 'Approved' | 'Rejected' | 'Returned for Modification' | string;
238
- roleName?: string | null;
239
- roleArabicName?: string | null;
240
- comment?: string | null;
241
- }): BilingualText {
242
- const roleEn = params.roleName?.trim() || 'Unknown Role';
243
- const roleAr = resolveBilingualName(roleEn, params.roleArabicName);
244
- const commentSuffix = formatChatCommentSuffix(params.comment);
245
-
246
- let key: string;
247
- if (params.status === 'Approved') {
248
- key = 'request_approved_by_role';
249
- } else if (params.status === 'Rejected') {
250
- key = 'request_rejected_by_role';
251
- } else if (params.status === 'Returned for Modification') {
252
- key = 'request_returned_for_modification_by_role';
253
- } else {
254
- key = 'request_approved_by_role';
255
- }
256
-
257
- return chatTemplate(
258
- key,
259
- { roleName: roleEn, comment: commentSuffix },
260
- { roleName: roleAr, comment: commentSuffix },
261
- );
262
- }
263
-
264
- /** Resolve Arabic workflow content from a stored English content string (legacy rows). */
265
- export function resolveWorkflowContentAr(content: string | null | undefined): string | null {
266
- if (content == null || content.trim() === '') return null;
267
- const normalized = content.trim();
268
-
269
- for (const tpl of Object.values(WORKFLOW_TEMPLATES)) {
270
- if (tpl.en === normalized) return tpl.ar;
271
- }
272
-
273
- const commentIdx = normalized.indexOf(': ');
274
- if (commentIdx > 0) {
275
- const baseEn = normalized.slice(0, commentIdx).trim();
276
- const commentText = normalized.slice(commentIdx + 2).trim();
277
- const commentSuffix = formatWorkflowCommentSuffix(commentText);
278
-
279
- for (const tpl of Object.values(WORKFLOW_TEMPLATES)) {
280
- if (!tpl.en.includes('{{comment}}')) continue;
281
- const withoutComment = tpl.en.replace('{{comment}}', '');
282
- if (withoutComment.includes('{{name}}')) {
283
- const staticPrefix = withoutComment.replace('{{name}}', '').trim();
284
- if (baseEn.startsWith(staticPrefix)) {
285
- const namePart = baseEn.slice(staticPrefix.length).trim();
286
- return interpolate(tpl.ar, { name: namePart, comment: commentSuffix });
287
- }
288
- } else if (withoutComment.trim() === baseEn) {
289
- return interpolate(tpl.ar, { comment: commentSuffix });
290
- }
291
- }
292
- }
293
-
294
- return null;
295
- }
296
-
297
- /** Resolve Arabic chat message from a stored English message string (legacy rows). */
298
- export function resolveChatMessageAr(message: string | null | undefined): string | null {
299
- if (message == null || message.trim() === '') return null;
300
- const normalized = message.trim();
301
-
302
- for (const tpl of Object.values(CHAT_TEMPLATES)) {
303
- if (tpl.en === normalized) return tpl.ar;
304
- }
305
-
306
- return null;
307
- }
308
-
309
- export function enrichCancellationWorkflowLog(log: Record<string, unknown>): Record<string, unknown> {
310
- const status = log.status != null ? String(log.status) : null;
311
- const content = log.content != null ? String(log.content) : null;
312
- return {
313
- ...log,
314
- content_ar: log.content_ar ?? resolveWorkflowContentAr(content),
315
- status_ar: log.status_ar ?? resolveWorkflowStatusAr(status),
316
- };
317
- }
318
-
319
- export function enrichCancellationChatMessage(chat: Record<string, unknown>): Record<string, unknown> {
320
- const status = chat.status != null ? String(chat.status) : null;
321
- const message = chat.message != null ? String(chat.message) : null;
322
- return {
323
- ...chat,
324
- message_ar: chat.message_ar ?? resolveChatMessageAr(message),
325
- status_ar: chat.status_ar ?? resolveChatStatusAr(status),
326
- };
327
- }
1
+ /**
2
+ * Re-exports the CAA standard bilingual message builder.
3
+ * Import from '@platform-modules/civil-aviation-authority' in all services.
4
+ */
5
+ export * from './workflow-chat-message.builder';