@rolatech/angular-onboarding 20.3.0-beta.2

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.
Files changed (35) hide show
  1. package/README.md +55 -0
  2. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-detail-page-DKJQX3cs.mjs +224 -0
  3. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-detail-page-DKJQX3cs.mjs.map +1 -0
  4. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-index-page-BO4pC_NU.mjs +206 -0
  5. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-index-page-BO4pC_NU.mjs.map +1 -0
  6. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-review-page-BERcLBeQ.mjs +419 -0
  7. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-review-page-BERcLBeQ.mjs.map +1 -0
  8. package/fesm2022/rolatech-angular-onboarding-agent-apply-banking-page-VYNfR4fy.mjs +133 -0
  9. package/fesm2022/rolatech-angular-onboarding-agent-apply-banking-page-VYNfR4fy.mjs.map +1 -0
  10. package/fesm2022/rolatech-angular-onboarding-agent-apply-financial-page-Ck3Rowke.mjs +132 -0
  11. package/fesm2022/rolatech-angular-onboarding-agent-apply-financial-page-Ck3Rowke.mjs.map +1 -0
  12. package/fesm2022/rolatech-angular-onboarding-agent-apply-profile-page-DNepDxHu.mjs +122 -0
  13. package/fesm2022/rolatech-angular-onboarding-agent-apply-profile-page-DNepDxHu.mjs.map +1 -0
  14. package/fesm2022/rolatech-angular-onboarding-agent-apply-qualification-page-CSwupuKt.mjs +108 -0
  15. package/fesm2022/rolatech-angular-onboarding-agent-apply-qualification-page-CSwupuKt.mjs.map +1 -0
  16. package/fesm2022/rolatech-angular-onboarding-agent-apply-review-page-DugCjfvK.mjs +182 -0
  17. package/fesm2022/rolatech-angular-onboarding-agent-apply-review-page-DugCjfvK.mjs.map +1 -0
  18. package/fesm2022/rolatech-angular-onboarding-agent-apply-shell-page-DibWYeD1.mjs +150 -0
  19. package/fesm2022/rolatech-angular-onboarding-agent-apply-shell-page-DibWYeD1.mjs.map +1 -0
  20. package/fesm2022/rolatech-angular-onboarding-agent-apply-start-page-DC7gyOnS.mjs +144 -0
  21. package/fesm2022/rolatech-angular-onboarding-agent-apply-start-page-DC7gyOnS.mjs.map +1 -0
  22. package/fesm2022/rolatech-angular-onboarding-agent-apply-submitted-page-BMkV2V8K.mjs +55 -0
  23. package/fesm2022/rolatech-angular-onboarding-agent-apply-submitted-page-BMkV2V8K.mjs.map +1 -0
  24. package/fesm2022/rolatech-angular-onboarding-agent-onboarding-documents-page-DWBGTj5J.mjs +99 -0
  25. package/fesm2022/rolatech-angular-onboarding-agent-onboarding-documents-page-DWBGTj5J.mjs.map +1 -0
  26. package/fesm2022/rolatech-angular-onboarding-agent-onboarding-issues-page-CSVgCJ7t.mjs +28 -0
  27. package/fesm2022/rolatech-angular-onboarding-agent-onboarding-issues-page-CSVgCJ7t.mjs.map +1 -0
  28. package/fesm2022/rolatech-angular-onboarding-agent-onboarding-overview-page-8sTSvFZ7.mjs +67 -0
  29. package/fesm2022/rolatech-angular-onboarding-agent-onboarding-overview-page-8sTSvFZ7.mjs.map +1 -0
  30. package/fesm2022/rolatech-angular-onboarding-agent-onboarding-shell-page-B6ffcJ5A.mjs +125 -0
  31. package/fesm2022/rolatech-angular-onboarding-agent-onboarding-shell-page-B6ffcJ5A.mjs.map +1 -0
  32. package/fesm2022/rolatech-angular-onboarding.mjs +1495 -0
  33. package/fesm2022/rolatech-angular-onboarding.mjs.map +1 -0
  34. package/package.json +35 -0
  35. package/types/rolatech-angular-onboarding.d.ts +244 -0
@@ -0,0 +1,1495 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, computed, Injectable, input, ViewEncapsulation, ChangeDetectionStrategy, Component, output } from '@angular/core';
3
+ import { Router, RouterLink } from '@angular/router';
4
+ import { FormBuilder, Validators } from '@angular/forms';
5
+ import { OnboardingApplicantService, OnboardingAdminService, onboardingStatusLabel, onboardingIssueTypeLabel, onboardingDocumentTypeLabel } from '@rolatech/angular-services';
6
+ import { firstValueFrom } from 'rxjs';
7
+ import { HttpClient } from '@angular/common/http';
8
+ import { NgClass, DatePipe } from '@angular/common';
9
+
10
+ const applicationIdGuard = (route) => Boolean(route.paramMap.get('applicationId'));
11
+
12
+ const INDIVIDUAL_REQUIRED_DOCUMENTS = [
13
+ { type: 'PASSPORT', label: 'Passport' },
14
+ { type: 'PROOF_OF_ADDRESS', label: 'Proof of address' },
15
+ ];
16
+ const COMPANY_REQUIRED_DOCUMENTS = [
17
+ { type: 'PASSPORT', label: 'Passport' },
18
+ { type: 'CERTIFICATE_OF_INCORPORATION', label: 'Certificate of incorporation' },
19
+ { type: 'INDUSTRY_CERTIFICATE', label: 'Industry certificate' },
20
+ ];
21
+ class AgentApplyFacade {
22
+ onboardingService = inject(OnboardingApplicantService);
23
+ fb = inject(FormBuilder);
24
+ http = inject(HttpClient);
25
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
26
+ saving = signal(false, ...(ngDevMode ? [{ debugName: "saving" }] : []));
27
+ submitting = signal(false, ...(ngDevMode ? [{ debugName: "submitting" }] : []));
28
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
29
+ application = signal(null, ...(ngDevMode ? [{ debugName: "application" }] : []));
30
+ detail = signal(null, ...(ngDevMode ? [{ debugName: "detail" }] : []));
31
+ loadedApplicationId = signal(null, ...(ngDevMode ? [{ debugName: "loadedApplicationId" }] : []));
32
+ applicationId = computed(() => this.detail()?.id ?? this.application()?.id ?? null, ...(ngDevMode ? [{ debugName: "applicationId" }] : []));
33
+ status = computed(() => this.detail()?.status ?? this.application()?.status ?? null, ...(ngDevMode ? [{ debugName: "status" }] : []));
34
+ documents = computed(() => this.detail()?.documents ?? [], ...(ngDevMode ? [{ debugName: "documents" }] : []));
35
+ issues = computed(() => this.detail()?.issues ?? [], ...(ngDevMode ? [{ debugName: "issues" }] : []));
36
+ timeline = computed(() => this.detail()?.timeline ?? [], ...(ngDevMode ? [{ debugName: "timeline" }] : []));
37
+ requiredDocuments = computed(() => {
38
+ const applicantType = this.detail()?.applicantType ?? this.application()?.applicantType;
39
+ return applicantType === 'COMPANY' ? COMPANY_REQUIRED_DOCUMENTS : INDIVIDUAL_REQUIRED_DOCUMENTS;
40
+ }, ...(ngDevMode ? [{ debugName: "requiredDocuments" }] : []));
41
+ completion = computed(() => {
42
+ const detail = this.detail();
43
+ if (!detail) {
44
+ return {
45
+ profile: false,
46
+ qualification: false,
47
+ financial: false,
48
+ banking: false,
49
+ };
50
+ }
51
+ if (detail.progress) {
52
+ return {
53
+ profile: detail.progress.profileCompleted,
54
+ qualification: detail.progress.qualificationCompleted,
55
+ financial: detail.progress.financialCompleted,
56
+ banking: detail.progress.bankingCompleted,
57
+ };
58
+ }
59
+ return {
60
+ profile: this.isProfileComplete(detail),
61
+ qualification: this.isQualificationComplete(detail),
62
+ financial: this.isFinancialComplete(detail),
63
+ banking: this.isBankingComplete(detail),
64
+ };
65
+ }, ...(ngDevMode ? [{ debugName: "completion" }] : []));
66
+ profileForm = this.fb.nonNullable.group({
67
+ organizationName: ['', [Validators.required, Validators.maxLength(255)]],
68
+ contactName: ['', [Validators.required, Validators.maxLength(255)]],
69
+ contactEmail: ['', [Validators.required, Validators.email]],
70
+ contactPhone: ['', [Validators.required, Validators.maxLength(64)]],
71
+ countryCode: ['GB', [Validators.required, Validators.maxLength(8)]],
72
+ });
73
+ financialForm = this.fb.nonNullable.group({
74
+ vatMode: ['NON_VAT_REGISTERED', [Validators.required]],
75
+ vatNumber: [''],
76
+ });
77
+ bankingForm = this.fb.nonNullable.group({
78
+ bankName: ['', [Validators.required, Validators.maxLength(255)]],
79
+ accountHolderName: ['', [Validators.required, Validators.maxLength(255)]],
80
+ sortCode: ['', [Validators.required, Validators.maxLength(16)]],
81
+ accountNumber: ['', [Validators.required, Validators.maxLength(32)]],
82
+ });
83
+ async start(request) {
84
+ this.loading.set(true);
85
+ this.error.set(null);
86
+ try {
87
+ const response = await firstValueFrom(this.onboardingService.createApplication(request));
88
+ this.application.set(response);
89
+ this.detail.set(null);
90
+ this.loadedApplicationId.set(null);
91
+ return response;
92
+ }
93
+ catch (error) {
94
+ this.error.set(this.toErrorMessage(error));
95
+ return null;
96
+ }
97
+ finally {
98
+ this.loading.set(false);
99
+ }
100
+ }
101
+ async ensureLoaded(applicationId, force = false) {
102
+ if (!applicationId) {
103
+ return;
104
+ }
105
+ if (!force && this.loadedApplicationId() === applicationId && this.detail()) {
106
+ return;
107
+ }
108
+ this.loading.set(true);
109
+ this.error.set(null);
110
+ try {
111
+ const response = await firstValueFrom(this.onboardingService.getApplication(applicationId));
112
+ this.detail.set(response);
113
+ this.loadedApplicationId.set(response.id);
114
+ this.patchForms(response);
115
+ }
116
+ catch (error) {
117
+ this.error.set(this.toErrorMessage(error));
118
+ }
119
+ finally {
120
+ this.loading.set(false);
121
+ }
122
+ }
123
+ async saveProfile() {
124
+ const applicationId = this.applicationId();
125
+ if (!applicationId) {
126
+ return false;
127
+ }
128
+ if (this.profileForm.invalid) {
129
+ this.profileForm.markAllAsTouched();
130
+ return false;
131
+ }
132
+ this.saving.set(true);
133
+ this.error.set(null);
134
+ try {
135
+ const payload = this.profileForm.getRawValue();
136
+ const response = await firstValueFrom(this.onboardingService.saveProfile(applicationId, payload));
137
+ this.application.set(response);
138
+ await this.ensureLoaded(applicationId, true);
139
+ return true;
140
+ }
141
+ catch (error) {
142
+ this.error.set(this.toErrorMessage(error));
143
+ return false;
144
+ }
145
+ finally {
146
+ this.saving.set(false);
147
+ }
148
+ }
149
+ async saveFinancial() {
150
+ const applicationId = this.applicationId();
151
+ if (!applicationId) {
152
+ return false;
153
+ }
154
+ if (this.financialForm.invalid) {
155
+ this.financialForm.markAllAsTouched();
156
+ return false;
157
+ }
158
+ this.saving.set(true);
159
+ this.error.set(null);
160
+ try {
161
+ const rawValue = this.financialForm.getRawValue();
162
+ const payload = {
163
+ vatMode: rawValue.vatMode,
164
+ vatNumber: rawValue.vatNumber || undefined,
165
+ };
166
+ const response = await firstValueFrom(this.onboardingService.saveFinancial(applicationId, payload));
167
+ this.application.set(response);
168
+ await this.ensureLoaded(applicationId, true);
169
+ return true;
170
+ }
171
+ catch (error) {
172
+ this.error.set(this.toErrorMessage(error));
173
+ return false;
174
+ }
175
+ finally {
176
+ this.saving.set(false);
177
+ }
178
+ }
179
+ async saveBanking() {
180
+ const applicationId = this.applicationId();
181
+ if (!applicationId) {
182
+ return false;
183
+ }
184
+ if (this.bankingForm.invalid) {
185
+ this.bankingForm.markAllAsTouched();
186
+ return false;
187
+ }
188
+ this.saving.set(true);
189
+ this.error.set(null);
190
+ try {
191
+ const payload = this.bankingForm.getRawValue();
192
+ const response = await firstValueFrom(this.onboardingService.saveBanking(applicationId, payload));
193
+ this.application.set(response);
194
+ await this.ensureLoaded(applicationId, true);
195
+ return true;
196
+ }
197
+ catch (error) {
198
+ this.error.set(this.toErrorMessage(error));
199
+ return false;
200
+ }
201
+ finally {
202
+ this.saving.set(false);
203
+ }
204
+ }
205
+ async uploadDocument(documentType, file, replacedDocumentId) {
206
+ const applicationId = this.applicationId();
207
+ if (!applicationId) {
208
+ return false;
209
+ }
210
+ this.saving.set(true);
211
+ this.error.set(null);
212
+ try {
213
+ const uploadRequest = {
214
+ documentType,
215
+ filename: file.name,
216
+ contentType: file.type,
217
+ fileSize: file.size,
218
+ replacedDocumentId: replacedDocumentId ?? undefined,
219
+ };
220
+ const uploadUrl = await firstValueFrom(this.onboardingService.requestUploadUrl(applicationId, uploadRequest));
221
+ // const uploadResponse1 = await fetch(uploadUrl.uploadUrl, {
222
+ // method: 'PUT',
223
+ // body: file,
224
+ // headers: {
225
+ // 'Content-Type': file.type || 'application/octet-stream',
226
+ // },
227
+ // mode: 'cors',
228
+ // });
229
+ // const uploadResponse = await firstValueFrom(
230
+ // this.http.put(uploadUrl.uploadUrl, file, {
231
+ // headers: {
232
+ // 'Content-Type': file.type || 'application/octet-stream',
233
+ // },
234
+ // }),
235
+ // );
236
+ // console.log(uploadResponse);
237
+ // if (!uploadResponse .ok) {
238
+ // throw new Error(`Document upload failed with status ${uploadResponse.status}`);
239
+ // }
240
+ const confirmRequest = {
241
+ documentType,
242
+ storageType: uploadUrl.storageType,
243
+ objectKey: uploadUrl.objectKey,
244
+ objectUrl: uploadUrl.uploadUrl,
245
+ originalFilename: file.name,
246
+ contentType: file.type,
247
+ fileSize: file.size,
248
+ replacedDocumentId: replacedDocumentId ?? undefined,
249
+ };
250
+ const detail = await firstValueFrom(this.onboardingService.confirmDocumentUpload(applicationId, confirmRequest));
251
+ this.detail.set(detail);
252
+ this.loadedApplicationId.set(detail.id);
253
+ return true;
254
+ }
255
+ catch (error) {
256
+ this.error.set(this.toErrorMessage(error));
257
+ return false;
258
+ }
259
+ finally {
260
+ this.saving.set(false);
261
+ }
262
+ }
263
+ async submit() {
264
+ const applicationId = this.applicationId();
265
+ if (!applicationId) {
266
+ return false;
267
+ }
268
+ this.submitting.set(true);
269
+ this.error.set(null);
270
+ try {
271
+ const response = await firstValueFrom(this.onboardingService.submit(applicationId));
272
+ this.application.set(response);
273
+ await this.ensureLoaded(applicationId, true);
274
+ return true;
275
+ }
276
+ catch (error) {
277
+ this.error.set(this.toErrorMessage(error));
278
+ return false;
279
+ }
280
+ finally {
281
+ this.submitting.set(false);
282
+ }
283
+ }
284
+ getDocument(documentType) {
285
+ return this.documents().find((item) => item.documentType === documentType) ?? null;
286
+ }
287
+ getIssueComment(documentType) {
288
+ return this.issues().find((item) => item.documentType === documentType)?.comment ?? null;
289
+ }
290
+ canAccessStep(step) {
291
+ const completion = this.completion();
292
+ switch (step) {
293
+ case 'profile':
294
+ return true;
295
+ case 'qualification':
296
+ return completion.profile;
297
+ case 'financial':
298
+ return completion.profile && completion.qualification;
299
+ case 'banking':
300
+ return completion.profile && completion.qualification && completion.financial;
301
+ case 'review':
302
+ return completion.profile && completion.qualification && completion.financial && completion.banking;
303
+ case 'submitted': {
304
+ const status = this.status();
305
+ return status === 'SUBMITTED' || status === 'IN_REVIEW' || status === 'APPROVED' || status === 'FAILED';
306
+ }
307
+ default:
308
+ return false;
309
+ }
310
+ }
311
+ firstIncompleteStep() {
312
+ const completion = this.completion();
313
+ if (!completion.profile) {
314
+ return 'profile';
315
+ }
316
+ if (!completion.qualification) {
317
+ return 'qualification';
318
+ }
319
+ if (!completion.financial) {
320
+ return 'financial';
321
+ }
322
+ if (!completion.banking) {
323
+ return 'banking';
324
+ }
325
+ return 'review';
326
+ }
327
+ patchForms(detail) {
328
+ this.profileForm.patchValue({
329
+ organizationName: detail.organizationName ?? '',
330
+ contactName: detail.contactName ?? '',
331
+ contactEmail: detail.contactEmail ?? '',
332
+ contactPhone: detail.contactPhone ?? '',
333
+ countryCode: detail.countryCode ?? 'GB',
334
+ });
335
+ this.financialForm.patchValue({
336
+ vatMode: detail.vatMode ?? 'NON_VAT_REGISTERED',
337
+ vatNumber: detail.vatNumber ?? '',
338
+ });
339
+ this.bankingForm.patchValue({
340
+ bankName: detail.bankName ?? '',
341
+ accountHolderName: detail.accountHolderName ?? '',
342
+ sortCode: detail.sortCode ?? '',
343
+ accountNumber: detail.accountNumber ?? '',
344
+ });
345
+ }
346
+ isProfileComplete(detail) {
347
+ return Boolean(detail.organizationName && detail.contactName && detail.contactEmail && detail.contactPhone && detail.countryCode);
348
+ }
349
+ isQualificationComplete(detail) {
350
+ const uploadedTypes = new Set(detail.documents.map((item) => item.documentType));
351
+ const required = detail.applicantType === 'COMPANY' ? COMPANY_REQUIRED_DOCUMENTS : INDIVIDUAL_REQUIRED_DOCUMENTS;
352
+ return required.every((item) => uploadedTypes.has(item.type));
353
+ }
354
+ isFinancialComplete(detail) {
355
+ if (!detail.vatMode) {
356
+ return false;
357
+ }
358
+ if (detail.vatMode === 'VAT_REGISTERED') {
359
+ return Boolean(detail.vatNumber);
360
+ }
361
+ return true;
362
+ }
363
+ isBankingComplete(detail) {
364
+ return Boolean(detail.bankName && detail.accountHolderName && detail.sortCode && detail.accountNumber);
365
+ }
366
+ toErrorMessage(error) {
367
+ if (error instanceof Error && error.message) {
368
+ return error.message;
369
+ }
370
+ return 'Unable to complete the onboarding action.';
371
+ }
372
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AgentApplyFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
373
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AgentApplyFacade });
374
+ }
375
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AgentApplyFacade, decorators: [{
376
+ type: Injectable
377
+ }] });
378
+
379
+ const applyStepGuard = async (childRoute) => {
380
+ const facade = inject(AgentApplyFacade);
381
+ const router = inject(Router);
382
+ const applicationId = childRoute.parent?.paramMap.get('applicationId') ?? childRoute.paramMap.get('applicationId');
383
+ if (!applicationId) {
384
+ return false;
385
+ }
386
+ await facade.ensureLoaded(applicationId);
387
+ const requiredStep = childRoute.data['requiredStep'];
388
+ if (!requiredStep || facade.canAccessStep(requiredStep)) {
389
+ return true;
390
+ }
391
+ const fallbackStep = facade.firstIncompleteStep();
392
+ const fallbackSegments = buildFallbackSegments(childRoute, fallbackStep);
393
+ if (fallbackSegments.length === 0) {
394
+ return false;
395
+ }
396
+ return router.createUrlTree(['/', ...fallbackSegments]);
397
+ };
398
+ function buildFallbackSegments(route, fallbackStep) {
399
+ const segments = route.pathFromRoot.flatMap((item) => item.url.map((segment) => segment.path)).filter(Boolean);
400
+ if (segments.length === 0) {
401
+ return [];
402
+ }
403
+ segments[segments.length - 1] = fallbackStep;
404
+ return segments;
405
+ }
406
+
407
+ const AGENT_APPLY_ROUTES = [
408
+ {
409
+ path: '',
410
+ loadComponent: () => import('./rolatech-angular-onboarding-agent-apply-start-page-DC7gyOnS.mjs').then((m) => m.AgentApplyStartPage),
411
+ },
412
+ {
413
+ path: ':applicationId',
414
+ canActivate: [applicationIdGuard],
415
+ canActivateChild: [applyStepGuard],
416
+ providers: [AgentApplyFacade],
417
+ loadComponent: () => import('./rolatech-angular-onboarding-agent-apply-shell-page-DibWYeD1.mjs').then((m) => m.AgentApplyShellPage),
418
+ children: [
419
+ {
420
+ path: '',
421
+ pathMatch: 'full',
422
+ redirectTo: 'profile',
423
+ },
424
+ {
425
+ path: 'profile',
426
+ data: {
427
+ requiredStep: 'profile',
428
+ },
429
+ loadComponent: () => import('./rolatech-angular-onboarding-agent-apply-profile-page-DNepDxHu.mjs').then((m) => m.AgentApplyProfilePage),
430
+ },
431
+ {
432
+ path: 'qualification',
433
+ data: {
434
+ requiredStep: 'qualification',
435
+ },
436
+ loadComponent: () => import('./rolatech-angular-onboarding-agent-apply-qualification-page-CSwupuKt.mjs').then((m) => m.AgentApplyQualificationPage),
437
+ },
438
+ {
439
+ path: 'financial',
440
+ data: {
441
+ requiredStep: 'financial',
442
+ },
443
+ loadComponent: () => import('./rolatech-angular-onboarding-agent-apply-financial-page-Ck3Rowke.mjs').then((m) => m.AgentApplyFinancialPage),
444
+ },
445
+ {
446
+ path: 'banking',
447
+ data: {
448
+ requiredStep: 'banking',
449
+ },
450
+ loadComponent: () => import('./rolatech-angular-onboarding-agent-apply-banking-page-VYNfR4fy.mjs').then((m) => m.AgentApplyBankingPage),
451
+ },
452
+ {
453
+ path: 'review',
454
+ data: {
455
+ requiredStep: 'review',
456
+ },
457
+ loadComponent: () => import('./rolatech-angular-onboarding-agent-apply-review-page-DugCjfvK.mjs').then((m) => m.AgentApplyReviewPage),
458
+ },
459
+ {
460
+ path: 'submitted',
461
+ data: {
462
+ requiredStep: 'submitted',
463
+ },
464
+ loadComponent: () => import('./rolatech-angular-onboarding-agent-apply-submitted-page-BMkV2V8K.mjs').then((m) => m.AgentApplySubmittedPage),
465
+ },
466
+ ],
467
+ },
468
+ ];
469
+
470
+ class AgentOnboardingFacade {
471
+ onboardingService = inject(OnboardingApplicantService);
472
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
473
+ saving = signal(false, ...(ngDevMode ? [{ debugName: "saving" }] : []));
474
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
475
+ detail = signal(null, ...(ngDevMode ? [{ debugName: "detail" }] : []));
476
+ loadedApplicationId = signal(null, ...(ngDevMode ? [{ debugName: "loadedApplicationId" }] : []));
477
+ status = computed(() => this.detail()?.status ?? null, ...(ngDevMode ? [{ debugName: "status" }] : []));
478
+ issues = computed(() => this.detail()?.issues ?? [], ...(ngDevMode ? [{ debugName: "issues" }] : []));
479
+ documents = computed(() => this.detail()?.documents ?? [], ...(ngDevMode ? [{ debugName: "documents" }] : []));
480
+ timeline = computed(() => this.detail()?.timeline ?? [], ...(ngDevMode ? [{ debugName: "timeline" }] : []));
481
+ applicationId = computed(() => this.detail()?.id ?? null, ...(ngDevMode ? [{ debugName: "applicationId" }] : []));
482
+ async ensureLoaded(applicationId, force = false) {
483
+ if (!applicationId) {
484
+ return;
485
+ }
486
+ if (!force && this.loadedApplicationId() === applicationId && this.detail()) {
487
+ return;
488
+ }
489
+ this.loading.set(true);
490
+ this.error.set(null);
491
+ try {
492
+ const detail = await firstValueFrom(this.onboardingService.getApplication(applicationId));
493
+ this.detail.set(detail);
494
+ this.loadedApplicationId.set(detail.id);
495
+ }
496
+ catch (error) {
497
+ this.error.set(this.toErrorMessage(error));
498
+ }
499
+ finally {
500
+ this.loading.set(false);
501
+ }
502
+ }
503
+ async reuploadDocument(documentType, file, replacedDocumentId) {
504
+ const applicationId = this.applicationId();
505
+ if (!applicationId) {
506
+ return false;
507
+ }
508
+ this.saving.set(true);
509
+ this.error.set(null);
510
+ try {
511
+ const uploadRequest = {
512
+ documentType,
513
+ filename: file.name,
514
+ contentType: file.type,
515
+ fileSize: file.size,
516
+ replacedDocumentId,
517
+ };
518
+ const uploadUrl = await firstValueFrom(this.onboardingService.requestUploadUrl(applicationId, uploadRequest));
519
+ const uploadResponse = await fetch(uploadUrl.uploadUrl, {
520
+ method: 'PUT',
521
+ body: file,
522
+ headers: {
523
+ 'Content-Type': file.type,
524
+ },
525
+ });
526
+ if (!uploadResponse.ok) {
527
+ throw new Error(`Document upload failed with status ${uploadResponse.status}`);
528
+ }
529
+ const confirmRequest = {
530
+ documentType,
531
+ storageType: uploadUrl.storageType,
532
+ objectKey: uploadUrl.objectKey,
533
+ objectUrl: uploadUrl.uploadUrl,
534
+ originalFilename: file.name,
535
+ contentType: file.type,
536
+ fileSize: file.size,
537
+ replacedDocumentId,
538
+ };
539
+ const detail = await firstValueFrom(this.onboardingService.confirmDocumentUpload(applicationId, confirmRequest));
540
+ this.detail.set(detail);
541
+ this.loadedApplicationId.set(detail.id);
542
+ return true;
543
+ }
544
+ catch (error) {
545
+ this.error.set(this.toErrorMessage(error));
546
+ return false;
547
+ }
548
+ finally {
549
+ this.saving.set(false);
550
+ }
551
+ }
552
+ async resubmit() {
553
+ const applicationId = this.applicationId();
554
+ if (!applicationId) {
555
+ return false;
556
+ }
557
+ this.saving.set(true);
558
+ this.error.set(null);
559
+ try {
560
+ await firstValueFrom(this.onboardingService.submit(applicationId));
561
+ await this.ensureLoaded(applicationId, true);
562
+ return true;
563
+ }
564
+ catch (error) {
565
+ this.error.set(this.toErrorMessage(error));
566
+ return false;
567
+ }
568
+ finally {
569
+ this.saving.set(false);
570
+ }
571
+ }
572
+ toErrorMessage(error) {
573
+ if (error instanceof Error && error.message) {
574
+ return error.message;
575
+ }
576
+ return 'Unable to load onboarding information.';
577
+ }
578
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AgentOnboardingFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
579
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AgentOnboardingFacade });
580
+ }
581
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AgentOnboardingFacade, decorators: [{
582
+ type: Injectable
583
+ }] });
584
+
585
+ const AGENT_ONBOARDING_ROUTES = [
586
+ {
587
+ path: ':applicationId',
588
+ canActivate: [applicationIdGuard],
589
+ providers: [AgentOnboardingFacade],
590
+ loadComponent: () => import('./rolatech-angular-onboarding-agent-onboarding-shell-page-B6ffcJ5A.mjs').then((m) => m.AgentOnboardingShellPage),
591
+ children: [
592
+ {
593
+ path: '',
594
+ pathMatch: 'full',
595
+ loadComponent: () => import('./rolatech-angular-onboarding-agent-onboarding-overview-page-8sTSvFZ7.mjs').then((m) => m.AgentOnboardingOverviewPage),
596
+ },
597
+ {
598
+ path: 'documents',
599
+ loadComponent: () => import('./rolatech-angular-onboarding-agent-onboarding-documents-page-DWBGTj5J.mjs').then((m) => m.AgentOnboardingDocumentsPage),
600
+ },
601
+ {
602
+ path: 'issues',
603
+ loadComponent: () => import('./rolatech-angular-onboarding-agent-onboarding-issues-page-CSVgCJ7t.mjs').then((m) => m.AgentOnboardingIssuesPage),
604
+ },
605
+ ],
606
+ },
607
+ ];
608
+
609
+ const ADMIN_ONBOARDING_ROUTES = [
610
+ {
611
+ path: '',
612
+ loadComponent: () => import('./rolatech-angular-onboarding-admin-onboarding-index-page-BO4pC_NU.mjs').then((m) => m.AdminOnboardingIndexPage),
613
+ },
614
+ {
615
+ path: ':applicationId',
616
+ canActivate: [applicationIdGuard],
617
+ loadComponent: () => import('./rolatech-angular-onboarding-admin-onboarding-detail-page-DKJQX3cs.mjs').then((m) => m.AdminOnboardingDetailPage),
618
+ },
619
+ {
620
+ path: ':applicationId/review',
621
+ canActivate: [applicationIdGuard],
622
+ loadComponent: () => import('./rolatech-angular-onboarding-admin-onboarding-review-page-BERcLBeQ.mjs').then((m) => m.AdminOnboardingReviewPage),
623
+ },
624
+ ];
625
+
626
+ class AdminOnboardingListFacade {
627
+ onboardingAdminService = inject(OnboardingAdminService);
628
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
629
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
630
+ filters = signal({
631
+ status: undefined,
632
+ search: '',
633
+ }, ...(ngDevMode ? [{ debugName: "filters" }] : []));
634
+ items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : []));
635
+ groupedCounts = computed(() => {
636
+ const result = {
637
+ DRAFT: 0,
638
+ IN_PROGRESS: 0,
639
+ SUBMITTED: 0,
640
+ IN_REVIEW: 0,
641
+ NEED_MORE_INFO: 0,
642
+ APPROVED: 0,
643
+ FAILED: 0,
644
+ };
645
+ for (const item of this.items()) {
646
+ result[item.status] += 1;
647
+ }
648
+ return result;
649
+ }, ...(ngDevMode ? [{ debugName: "groupedCounts" }] : []));
650
+ async load(query) {
651
+ if (query) {
652
+ this.filters.update((current) => ({
653
+ ...current,
654
+ ...query,
655
+ }));
656
+ }
657
+ this.loading.set(true);
658
+ this.error.set(null);
659
+ try {
660
+ const payload = this.filters();
661
+ const items = await firstValueFrom(this.onboardingAdminService.list(payload));
662
+ this.items.set(items);
663
+ }
664
+ catch (error) {
665
+ this.error.set(this.toErrorMessage(error));
666
+ }
667
+ finally {
668
+ this.loading.set(false);
669
+ }
670
+ }
671
+ setStatus(status) {
672
+ this.filters.update((current) => ({
673
+ ...current,
674
+ status,
675
+ }));
676
+ }
677
+ setSearch(search) {
678
+ this.filters.update((current) => ({
679
+ ...current,
680
+ search,
681
+ }));
682
+ }
683
+ toErrorMessage(error) {
684
+ if (error instanceof Error && error.message) {
685
+ return error.message;
686
+ }
687
+ return 'Unable to load onboarding applications.';
688
+ }
689
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AdminOnboardingListFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
690
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AdminOnboardingListFacade });
691
+ }
692
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AdminOnboardingListFacade, decorators: [{
693
+ type: Injectable
694
+ }] });
695
+
696
+ class AdminOnboardingDetailFacade {
697
+ onboardingAdminService = inject(OnboardingAdminService);
698
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
699
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
700
+ detail = signal(null, ...(ngDevMode ? [{ debugName: "detail" }] : []));
701
+ async load(applicationId) {
702
+ if (!applicationId) {
703
+ return;
704
+ }
705
+ this.loading.set(true);
706
+ this.error.set(null);
707
+ try {
708
+ const detail = await firstValueFrom(this.onboardingAdminService.getApplication(applicationId));
709
+ this.detail.set(detail);
710
+ }
711
+ catch (error) {
712
+ this.error.set(this.toErrorMessage(error));
713
+ }
714
+ finally {
715
+ this.loading.set(false);
716
+ }
717
+ }
718
+ toErrorMessage(error) {
719
+ if (error instanceof Error && error.message) {
720
+ return error.message;
721
+ }
722
+ return 'Unable to load onboarding application details.';
723
+ }
724
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AdminOnboardingDetailFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
725
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AdminOnboardingDetailFacade });
726
+ }
727
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AdminOnboardingDetailFacade, decorators: [{
728
+ type: Injectable
729
+ }] });
730
+
731
+ class AdminOnboardingReviewFacade {
732
+ onboardingAdminService = inject(OnboardingAdminService);
733
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
734
+ saving = signal(false, ...(ngDevMode ? [{ debugName: "saving" }] : []));
735
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
736
+ detail = signal(null, ...(ngDevMode ? [{ debugName: "detail" }] : []));
737
+ reviewComment = signal('', ...(ngDevMode ? [{ debugName: "reviewComment" }] : []));
738
+ issueDrafts = signal([], ...(ngDevMode ? [{ debugName: "issueDrafts" }] : []));
739
+ async load(applicationId) {
740
+ if (!applicationId) {
741
+ return;
742
+ }
743
+ this.loading.set(true);
744
+ this.error.set(null);
745
+ try {
746
+ const detail = await firstValueFrom(this.onboardingAdminService.getApplication(applicationId));
747
+ this.detail.set(detail);
748
+ }
749
+ catch (error) {
750
+ this.error.set(this.toErrorMessage(error));
751
+ }
752
+ finally {
753
+ this.loading.set(false);
754
+ }
755
+ }
756
+ addFieldIssue(fieldKey, comment) {
757
+ this.issueDrafts.update((items) => [
758
+ ...items,
759
+ {
760
+ issueType: 'FIELD',
761
+ fieldKey,
762
+ comment,
763
+ },
764
+ ]);
765
+ }
766
+ addDocumentIssue(documentType, comment) {
767
+ this.issueDrafts.update((items) => [
768
+ ...items,
769
+ {
770
+ issueType: 'DOCUMENT',
771
+ documentType,
772
+ comment,
773
+ },
774
+ ]);
775
+ }
776
+ removeIssue(index) {
777
+ this.issueDrafts.update((items) => items.filter((_, currentIndex) => currentIndex !== index));
778
+ }
779
+ setComment(value) {
780
+ this.reviewComment.set(value);
781
+ }
782
+ async startReview(applicationId) {
783
+ return this.runAction(async () => {
784
+ const detail = await firstValueFrom(this.onboardingAdminService.startReview(applicationId));
785
+ this.detail.set(detail);
786
+ });
787
+ }
788
+ async requestMoreInfo(applicationId) {
789
+ const payload = {
790
+ comment: this.reviewComment(),
791
+ issues: this.issueDrafts(),
792
+ };
793
+ return this.runAction(async () => {
794
+ const detail = await firstValueFrom(this.onboardingAdminService.needMoreInfo(applicationId, payload));
795
+ this.detail.set(detail);
796
+ this.reviewComment.set('');
797
+ this.issueDrafts.set([]);
798
+ });
799
+ }
800
+ async approve(applicationId) {
801
+ const payload = {
802
+ comment: this.reviewComment(),
803
+ };
804
+ return this.runAction(async () => {
805
+ const detail = await firstValueFrom(this.onboardingAdminService.approve(applicationId, payload));
806
+ this.detail.set(detail);
807
+ this.reviewComment.set('');
808
+ });
809
+ }
810
+ async fail(applicationId) {
811
+ const payload = {
812
+ comment: this.reviewComment(),
813
+ };
814
+ return this.runAction(async () => {
815
+ const detail = await firstValueFrom(this.onboardingAdminService.fail(applicationId, payload));
816
+ this.detail.set(detail);
817
+ this.reviewComment.set('');
818
+ });
819
+ }
820
+ async runAction(action) {
821
+ this.saving.set(true);
822
+ this.error.set(null);
823
+ try {
824
+ await action();
825
+ return true;
826
+ }
827
+ catch (error) {
828
+ this.error.set(this.toErrorMessage(error));
829
+ return false;
830
+ }
831
+ finally {
832
+ this.saving.set(false);
833
+ }
834
+ }
835
+ toErrorMessage(error) {
836
+ if (error instanceof Error && error.message) {
837
+ return error.message;
838
+ }
839
+ return 'Unable to complete the onboarding review action.';
840
+ }
841
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AdminOnboardingReviewFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
842
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AdminOnboardingReviewFacade });
843
+ }
844
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AdminOnboardingReviewFacade, decorators: [{
845
+ type: Injectable
846
+ }] });
847
+
848
+ class OnboardingPageShell {
849
+ title = input.required(...(ngDevMode ? [{ debugName: "title" }] : []));
850
+ subtitle = input('', ...(ngDevMode ? [{ debugName: "subtitle" }] : []));
851
+ kicker = input('', ...(ngDevMode ? [{ debugName: "kicker" }] : []));
852
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingPageShell, deps: [], target: i0.ɵɵFactoryTarget.Component });
853
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: OnboardingPageShell, isStandalone: true, selector: "rolatech-onboarding-page-shell", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, kicker: { classPropertyName: "kicker", publicName: "kicker", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, ngImport: i0, template: `
854
+ <section class="rt-onboarding-theme mx-auto w-full max-w-6xl space-y-6 bg-(--rt-base-background) px-4 py-6 text-(--rt-text-primary) sm:px-6 lg:px-8">
855
+ <header class="relative overflow-hidden rounded-3xl border border-(--rt-border-color) bg-(--rt-base-background) p-6 shadow-sm sm:p-8">
856
+ <div class="pointer-events-none absolute -right-10 -top-10 h-36 w-36 rounded-full bg-(--rt-10-percent-layer) blur-2xl"></div>
857
+ <div class="pointer-events-none absolute -bottom-16 left-12 h-36 w-36 rounded-full bg-(--rt-10-percent-layer) blur-2xl"></div>
858
+
859
+ <div class="relative flex flex-wrap items-start justify-between gap-4">
860
+ <div class="flex min-w-0 items-start gap-3">
861
+ <div class="rt-onboarding-header-leading">
862
+ <ng-content select="[header-leading]"></ng-content>
863
+ </div>
864
+
865
+ <div>
866
+ @if (kicker()) {
867
+ <p class="text-xs font-semibold uppercase tracking-[0.2em] text-(--rt-text-secondary)">{{ kicker() }}</p>
868
+ }
869
+ <h1 class="mt-1 text-2xl font-semibold tracking-tight text-(--rt-text-primary) sm:text-3xl">{{ title() }}</h1>
870
+ @if (subtitle()) {
871
+ <p class="mt-3 max-w-3xl text-sm text-(--rt-text-secondary) sm:text-base">{{ subtitle() }}</p>
872
+ }
873
+ </div>
874
+ </div>
875
+ <div class="shrink-0">
876
+ <ng-content select="[header-actions]"></ng-content>
877
+ </div>
878
+ </div>
879
+ </header>
880
+
881
+ <ng-content select="[floating]"></ng-content>
882
+
883
+ <div class="space-y-6">
884
+ <ng-content></ng-content>
885
+ </div>
886
+ </section>
887
+ `, isInline: true, styles: [".rt-onboarding-theme{color-scheme:light dark;background-color:var(--rt-base-background);color:var(--rt-text-primary)}.rt-onboarding-header-leading:empty{display:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
888
+ }
889
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingPageShell, decorators: [{
890
+ type: Component,
891
+ args: [{ selector: 'rolatech-onboarding-page-shell', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'block' }, template: `
892
+ <section class="rt-onboarding-theme mx-auto w-full max-w-6xl space-y-6 bg-(--rt-base-background) px-4 py-6 text-(--rt-text-primary) sm:px-6 lg:px-8">
893
+ <header class="relative overflow-hidden rounded-3xl border border-(--rt-border-color) bg-(--rt-base-background) p-6 shadow-sm sm:p-8">
894
+ <div class="pointer-events-none absolute -right-10 -top-10 h-36 w-36 rounded-full bg-(--rt-10-percent-layer) blur-2xl"></div>
895
+ <div class="pointer-events-none absolute -bottom-16 left-12 h-36 w-36 rounded-full bg-(--rt-10-percent-layer) blur-2xl"></div>
896
+
897
+ <div class="relative flex flex-wrap items-start justify-between gap-4">
898
+ <div class="flex min-w-0 items-start gap-3">
899
+ <div class="rt-onboarding-header-leading">
900
+ <ng-content select="[header-leading]"></ng-content>
901
+ </div>
902
+
903
+ <div>
904
+ @if (kicker()) {
905
+ <p class="text-xs font-semibold uppercase tracking-[0.2em] text-(--rt-text-secondary)">{{ kicker() }}</p>
906
+ }
907
+ <h1 class="mt-1 text-2xl font-semibold tracking-tight text-(--rt-text-primary) sm:text-3xl">{{ title() }}</h1>
908
+ @if (subtitle()) {
909
+ <p class="mt-3 max-w-3xl text-sm text-(--rt-text-secondary) sm:text-base">{{ subtitle() }}</p>
910
+ }
911
+ </div>
912
+ </div>
913
+ <div class="shrink-0">
914
+ <ng-content select="[header-actions]"></ng-content>
915
+ </div>
916
+ </div>
917
+ </header>
918
+
919
+ <ng-content select="[floating]"></ng-content>
920
+
921
+ <div class="space-y-6">
922
+ <ng-content></ng-content>
923
+ </div>
924
+ </section>
925
+ `, styles: [".rt-onboarding-theme{color-scheme:light dark;background-color:var(--rt-base-background);color:var(--rt-text-primary)}.rt-onboarding-header-leading:empty{display:none}\n"] }]
926
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], kicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "kicker", required: false }] }] } });
927
+
928
+ class OnboardingStatusBadge {
929
+ status = input(null, ...(ngDevMode ? [{ debugName: "status" }] : []));
930
+ label = computed(() => {
931
+ return onboardingStatusLabel(this.status());
932
+ }, ...(ngDevMode ? [{ debugName: "label" }] : []));
933
+ badgeClass = computed(() => {
934
+ switch (this.status()) {
935
+ case 'APPROVED':
936
+ return 'border-emerald-200 bg-emerald-50 text-emerald-700';
937
+ case 'FAILED':
938
+ return 'border-rose-200 bg-rose-50 text-rose-700';
939
+ case 'NEED_MORE_INFO':
940
+ return 'border-amber-200 bg-amber-50 text-amber-700';
941
+ case 'SUBMITTED':
942
+ case 'IN_REVIEW':
943
+ return 'border-sky-200 bg-sky-50 text-sky-700';
944
+ case 'IN_PROGRESS':
945
+ case 'DRAFT':
946
+ return 'border-(--rt-border-color) bg-(--rt-raised-background) text-(--rt-text-secondary)';
947
+ default:
948
+ return 'border-(--rt-border-color) bg-(--rt-raised-background) text-(--rt-text-secondary)';
949
+ }
950
+ }, ...(ngDevMode ? [{ debugName: "badgeClass" }] : []));
951
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingStatusBadge, deps: [], target: i0.ɵɵFactoryTarget.Component });
952
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.1", type: OnboardingStatusBadge, isStandalone: true, selector: "rolatech-onboarding-status-badge", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, ngImport: i0, template: `
953
+ <span
954
+ class="inline-flex items-center rounded-full border border-(--rt-border-color) px-3 py-1 text-xs font-semibold uppercase tracking-wide"
955
+ [class]="badgeClass()"
956
+ >
957
+ {{ label() }}
958
+ </span>
959
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
960
+ }
961
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingStatusBadge, decorators: [{
962
+ type: Component,
963
+ args: [{
964
+ selector: 'rolatech-onboarding-status-badge',
965
+ standalone: true,
966
+ changeDetection: ChangeDetectionStrategy.OnPush,
967
+ encapsulation: ViewEncapsulation.None,
968
+ host: { class: 'block' },
969
+ template: `
970
+ <span
971
+ class="inline-flex items-center rounded-full border border-(--rt-border-color) px-3 py-1 text-xs font-semibold uppercase tracking-wide"
972
+ [class]="badgeClass()"
973
+ >
974
+ {{ label() }}
975
+ </span>
976
+ `,
977
+ }]
978
+ }], propDecorators: { status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }] } });
979
+
980
+ class OnboardingStepNav {
981
+ steps = input([], ...(ngDevMode ? [{ debugName: "steps" }] : []));
982
+ activeStep = input('', ...(ngDevMode ? [{ debugName: "activeStep" }] : []));
983
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingStepNav, deps: [], target: i0.ɵɵFactoryTarget.Component });
984
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: OnboardingStepNav, isStandalone: true, selector: "rolatech-onboarding-step-nav", inputs: { steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null }, activeStep: { classPropertyName: "activeStep", publicName: "activeStep", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, ngImport: i0, template: `
985
+ <nav class="grid gap-2 sm:grid-cols-2 lg:grid-cols-6" aria-label="Onboarding steps">
986
+ @for (step of steps(); track step.step) {
987
+ <a
988
+ [routerLink]="step.accessible ? step.link : null"
989
+ class="group rounded-2xl border border-(--rt-border-color) px-3 py-3 text-left transition cursor-pointer"
990
+ [ngClass]="
991
+ step.step === activeStep()
992
+ ? 'border-(--rt-brand-color) bg-(--rt-brand-color) text-(--rt-text-primary-inverse) shadow-sm'
993
+ : 'border-(--rt-border-color) bg-(--rt-raised-background) text-(--rt-text-primary) hover:bg-(--rt-raised-background)'
994
+ "
995
+ [class.cursor-not-allowed]="!step.accessible"
996
+ [class.opacity-60]="!step.accessible"
997
+ >
998
+ <div class="flex items-center justify-between gap-2">
999
+ <span class="text-sm font-medium">{{ step.label }}</span>
1000
+ @if (step.completed) {
1001
+ <span class="text-xs font-semibold text-emerald-700">Done</span>
1002
+ } @else if (!step.accessible) {
1003
+ <span class="text-xs font-semibold text-(--rt-text-secondary)">Locked</span>
1004
+ }
1005
+ </div>
1006
+ </a>
1007
+ }
1008
+ </nav>
1009
+ `, isInline: true, dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1010
+ }
1011
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingStepNav, decorators: [{
1012
+ type: Component,
1013
+ args: [{
1014
+ selector: 'rolatech-onboarding-step-nav',
1015
+ standalone: true,
1016
+ imports: [RouterLink, NgClass],
1017
+ changeDetection: ChangeDetectionStrategy.OnPush,
1018
+ encapsulation: ViewEncapsulation.None,
1019
+ host: { class: 'block' },
1020
+ template: `
1021
+ <nav class="grid gap-2 sm:grid-cols-2 lg:grid-cols-6" aria-label="Onboarding steps">
1022
+ @for (step of steps(); track step.step) {
1023
+ <a
1024
+ [routerLink]="step.accessible ? step.link : null"
1025
+ class="group rounded-2xl border border-(--rt-border-color) px-3 py-3 text-left transition cursor-pointer"
1026
+ [ngClass]="
1027
+ step.step === activeStep()
1028
+ ? 'border-(--rt-brand-color) bg-(--rt-brand-color) text-(--rt-text-primary-inverse) shadow-sm'
1029
+ : 'border-(--rt-border-color) bg-(--rt-raised-background) text-(--rt-text-primary) hover:bg-(--rt-raised-background)'
1030
+ "
1031
+ [class.cursor-not-allowed]="!step.accessible"
1032
+ [class.opacity-60]="!step.accessible"
1033
+ >
1034
+ <div class="flex items-center justify-between gap-2">
1035
+ <span class="text-sm font-medium">{{ step.label }}</span>
1036
+ @if (step.completed) {
1037
+ <span class="text-xs font-semibold text-emerald-700">Done</span>
1038
+ } @else if (!step.accessible) {
1039
+ <span class="text-xs font-semibold text-(--rt-text-secondary)">Locked</span>
1040
+ }
1041
+ </div>
1042
+ </a>
1043
+ }
1044
+ </nav>
1045
+ `,
1046
+ }]
1047
+ }], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: false }] }], activeStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeStep", required: false }] }] } });
1048
+
1049
+ class OnboardingDocumentUploader {
1050
+ label = input.required(...(ngDevMode ? [{ debugName: "label" }] : []));
1051
+ helperText = input('Upload a clear and readable file.', ...(ngDevMode ? [{ debugName: "helperText" }] : []));
1052
+ documentType = input.required(...(ngDevMode ? [{ debugName: "documentType" }] : []));
1053
+ document = input(null, ...(ngDevMode ? [{ debugName: "document" }] : []));
1054
+ comment = input(null, ...(ngDevMode ? [{ debugName: "comment" }] : []));
1055
+ busy = input(false, ...(ngDevMode ? [{ debugName: "busy" }] : []));
1056
+ acceptedTypes = input('image/*,application/pdf', ...(ngDevMode ? [{ debugName: "acceptedTypes" }] : []));
1057
+ fileSelected = output();
1058
+ onFileChange(event) {
1059
+ const target = event.target;
1060
+ const file = target.files?.[0];
1061
+ if (!file) {
1062
+ return;
1063
+ }
1064
+ this.fileSelected.emit({
1065
+ documentType: this.documentType(),
1066
+ file,
1067
+ replacedDocumentId: this.document()?.id ?? undefined,
1068
+ });
1069
+ target.value = '';
1070
+ }
1071
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingDocumentUploader, deps: [], target: i0.ɵɵFactoryTarget.Component });
1072
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: OnboardingDocumentUploader, isStandalone: true, selector: "rolatech-onboarding-document-uploader", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, documentType: { classPropertyName: "documentType", publicName: "documentType", isSignal: true, isRequired: true, transformFunction: null }, document: { classPropertyName: "document", publicName: "document", isSignal: true, isRequired: false, transformFunction: null }, comment: { classPropertyName: "comment", publicName: "comment", isSignal: true, isRequired: false, transformFunction: null }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null }, acceptedTypes: { classPropertyName: "acceptedTypes", publicName: "acceptedTypes", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fileSelected: "fileSelected" }, host: { classAttribute: "block" }, ngImport: i0, template: `
1073
+ <section class="rounded-2xl border border-(--rt-border-color) bg-(--rt-base-background) p-4 shadow-sm">
1074
+ <div class="flex flex-wrap items-start justify-between gap-4">
1075
+ <div>
1076
+ <h3 class="text-sm font-semibold text-(--rt-text-primary)">{{ label() }}</h3>
1077
+ <p class="mt-1 text-xs text-(--rt-text-secondary)">{{ helperText() }}</p>
1078
+
1079
+ @if (document(); as existing) {
1080
+ <p class="mt-2 text-sm text-(--rt-text-primary)">
1081
+ {{ existing.originalFilename }}
1082
+ <span class="text-(--rt-text-secondary)">(v{{ existing.version }})</span>
1083
+ </p>
1084
+ }
1085
+ </div>
1086
+
1087
+ <label
1088
+ class="inline-flex cursor-pointer items-center rounded-xl border border-(--rt-border-color) px-3 py-2 text-sm font-medium text-(--rt-text-primary) transition hover:bg-(--rt-raised-background)"
1089
+ [class.pointer-events-none]="busy()"
1090
+ [class.opacity-60]="busy()"
1091
+ >
1092
+ {{ document() ? 'Replace' : 'Upload' }}
1093
+ <input
1094
+ type="file"
1095
+ class="hidden"
1096
+ [accept]="acceptedTypes()"
1097
+ [disabled]="busy()"
1098
+ (change)="onFileChange($event)"
1099
+ />
1100
+ </label>
1101
+ </div>
1102
+
1103
+ @if (comment()) {
1104
+ <div class="mt-3 rounded-xl border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-800">
1105
+ {{ comment() }}
1106
+ </div>
1107
+ }
1108
+ </section>
1109
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1110
+ }
1111
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingDocumentUploader, decorators: [{
1112
+ type: Component,
1113
+ args: [{
1114
+ selector: 'rolatech-onboarding-document-uploader',
1115
+ standalone: true,
1116
+ changeDetection: ChangeDetectionStrategy.OnPush,
1117
+ encapsulation: ViewEncapsulation.None,
1118
+ host: { class: 'block' },
1119
+ template: `
1120
+ <section class="rounded-2xl border border-(--rt-border-color) bg-(--rt-base-background) p-4 shadow-sm">
1121
+ <div class="flex flex-wrap items-start justify-between gap-4">
1122
+ <div>
1123
+ <h3 class="text-sm font-semibold text-(--rt-text-primary)">{{ label() }}</h3>
1124
+ <p class="mt-1 text-xs text-(--rt-text-secondary)">{{ helperText() }}</p>
1125
+
1126
+ @if (document(); as existing) {
1127
+ <p class="mt-2 text-sm text-(--rt-text-primary)">
1128
+ {{ existing.originalFilename }}
1129
+ <span class="text-(--rt-text-secondary)">(v{{ existing.version }})</span>
1130
+ </p>
1131
+ }
1132
+ </div>
1133
+
1134
+ <label
1135
+ class="inline-flex cursor-pointer items-center rounded-xl border border-(--rt-border-color) px-3 py-2 text-sm font-medium text-(--rt-text-primary) transition hover:bg-(--rt-raised-background)"
1136
+ [class.pointer-events-none]="busy()"
1137
+ [class.opacity-60]="busy()"
1138
+ >
1139
+ {{ document() ? 'Replace' : 'Upload' }}
1140
+ <input
1141
+ type="file"
1142
+ class="hidden"
1143
+ [accept]="acceptedTypes()"
1144
+ [disabled]="busy()"
1145
+ (change)="onFileChange($event)"
1146
+ />
1147
+ </label>
1148
+ </div>
1149
+
1150
+ @if (comment()) {
1151
+ <div class="mt-3 rounded-xl border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-800">
1152
+ {{ comment() }}
1153
+ </div>
1154
+ }
1155
+ </section>
1156
+ `,
1157
+ }]
1158
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], documentType: [{ type: i0.Input, args: [{ isSignal: true, alias: "documentType", required: true }] }], document: [{ type: i0.Input, args: [{ isSignal: true, alias: "document", required: false }] }], comment: [{ type: i0.Input, args: [{ isSignal: true, alias: "comment", required: false }] }], busy: [{ type: i0.Input, args: [{ isSignal: true, alias: "busy", required: false }] }], acceptedTypes: [{ type: i0.Input, args: [{ isSignal: true, alias: "acceptedTypes", required: false }] }], fileSelected: [{ type: i0.Output, args: ["fileSelected"] }] } });
1159
+
1160
+ class OnboardingIssueList {
1161
+ issues = input([], ...(ngDevMode ? [{ debugName: "issues" }] : []));
1162
+ issueTypeLabel = onboardingIssueTypeLabel;
1163
+ documentTypeLabel = onboardingDocumentTypeLabel;
1164
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingIssueList, deps: [], target: i0.ɵɵFactoryTarget.Component });
1165
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: OnboardingIssueList, isStandalone: true, selector: "rolatech-onboarding-issue-list", inputs: { issues: { classPropertyName: "issues", publicName: "issues", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, ngImport: i0, template: `
1166
+ <section class="rounded-2xl border border-(--rt-border-color) bg-(--rt-base-background) p-5 shadow-sm">
1167
+ <div class="mb-4 flex items-center justify-between gap-3">
1168
+ <h3 class="text-base font-semibold text-(--rt-text-primary)">Reviewer Issues</h3>
1169
+ <span class="rounded-full bg-(--rt-raised-background) px-2 py-1 text-xs font-semibold text-(--rt-text-secondary)">
1170
+ {{ issues().length }}
1171
+ </span>
1172
+ </div>
1173
+
1174
+ @if (issues().length === 0) {
1175
+ <p class="text-sm text-(--rt-text-secondary)">No issues raised for this application.</p>
1176
+ } @else {
1177
+ <div class="space-y-3">
1178
+ @for (issue of issues(); track issue.id) {
1179
+ <article class="rounded-xl border border-amber-200 bg-amber-50 p-3">
1180
+ <div class="flex flex-wrap items-center justify-between gap-2">
1181
+ <p class="text-xs font-semibold uppercase tracking-wide text-amber-800">{{ issueTypeLabel(issue.issueType) }}</p>
1182
+ @if (issue.resolved) {
1183
+ <span class="rounded-full border border-emerald-200 bg-emerald-50 px-2 py-0.5 text-xs font-semibold text-emerald-700">
1184
+ Resolved
1185
+ </span>
1186
+ }
1187
+ </div>
1188
+
1189
+ @if (issue.fieldKey) {
1190
+ <p class="mt-2 text-xs text-(--rt-text-secondary)">Field: {{ issue.fieldKey }}</p>
1191
+ }
1192
+
1193
+ @if (issue.documentType) {
1194
+ <p class="mt-2 text-xs text-(--rt-text-secondary)">Document: {{ documentTypeLabel(issue.documentType) }}</p>
1195
+ }
1196
+
1197
+ <p class="mt-2 text-sm text-(--rt-text-primary)">{{ issue.comment }}</p>
1198
+ </article>
1199
+ }
1200
+ </div>
1201
+ }
1202
+ </section>
1203
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1204
+ }
1205
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingIssueList, decorators: [{
1206
+ type: Component,
1207
+ args: [{
1208
+ selector: 'rolatech-onboarding-issue-list',
1209
+ standalone: true,
1210
+ changeDetection: ChangeDetectionStrategy.OnPush,
1211
+ encapsulation: ViewEncapsulation.None,
1212
+ host: { class: 'block' },
1213
+ template: `
1214
+ <section class="rounded-2xl border border-(--rt-border-color) bg-(--rt-base-background) p-5 shadow-sm">
1215
+ <div class="mb-4 flex items-center justify-between gap-3">
1216
+ <h3 class="text-base font-semibold text-(--rt-text-primary)">Reviewer Issues</h3>
1217
+ <span class="rounded-full bg-(--rt-raised-background) px-2 py-1 text-xs font-semibold text-(--rt-text-secondary)">
1218
+ {{ issues().length }}
1219
+ </span>
1220
+ </div>
1221
+
1222
+ @if (issues().length === 0) {
1223
+ <p class="text-sm text-(--rt-text-secondary)">No issues raised for this application.</p>
1224
+ } @else {
1225
+ <div class="space-y-3">
1226
+ @for (issue of issues(); track issue.id) {
1227
+ <article class="rounded-xl border border-amber-200 bg-amber-50 p-3">
1228
+ <div class="flex flex-wrap items-center justify-between gap-2">
1229
+ <p class="text-xs font-semibold uppercase tracking-wide text-amber-800">{{ issueTypeLabel(issue.issueType) }}</p>
1230
+ @if (issue.resolved) {
1231
+ <span class="rounded-full border border-emerald-200 bg-emerald-50 px-2 py-0.5 text-xs font-semibold text-emerald-700">
1232
+ Resolved
1233
+ </span>
1234
+ }
1235
+ </div>
1236
+
1237
+ @if (issue.fieldKey) {
1238
+ <p class="mt-2 text-xs text-(--rt-text-secondary)">Field: {{ issue.fieldKey }}</p>
1239
+ }
1240
+
1241
+ @if (issue.documentType) {
1242
+ <p class="mt-2 text-xs text-(--rt-text-secondary)">Document: {{ documentTypeLabel(issue.documentType) }}</p>
1243
+ }
1244
+
1245
+ <p class="mt-2 text-sm text-(--rt-text-primary)">{{ issue.comment }}</p>
1246
+ </article>
1247
+ }
1248
+ </div>
1249
+ }
1250
+ </section>
1251
+ `,
1252
+ }]
1253
+ }], propDecorators: { issues: [{ type: i0.Input, args: [{ isSignal: true, alias: "issues", required: false }] }] } });
1254
+
1255
+ class OnboardingSummaryCard {
1256
+ title = input.required(...(ngDevMode ? [{ debugName: "title" }] : []));
1257
+ items = input([], ...(ngDevMode ? [{ debugName: "items" }] : []));
1258
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingSummaryCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
1259
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: OnboardingSummaryCard, isStandalone: true, selector: "rolatech-onboarding-summary-card", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, ngImport: i0, template: `
1260
+ <section class="rounded-2xl border border-(--rt-border-color) bg-(--rt-base-background) p-5 shadow-sm">
1261
+ <h3 class="text-base font-semibold text-(--rt-text-primary)">{{ title() }}</h3>
1262
+
1263
+ <div class="mt-4 grid gap-4 md:grid-cols-2">
1264
+ @for (item of items(); track item.label) {
1265
+ <div class="rounded-xl border border-(--rt-border-color) bg-(--rt-raised-background) p-3">
1266
+ <p class="text-xs font-medium uppercase tracking-wide text-(--rt-text-secondary)">{{ item.label }}</p>
1267
+ <p class="mt-1 text-sm font-medium text-(--rt-text-primary)">{{ item.value || '-' }}</p>
1268
+ </div>
1269
+ }
1270
+ </div>
1271
+ </section>
1272
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1273
+ }
1274
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingSummaryCard, decorators: [{
1275
+ type: Component,
1276
+ args: [{
1277
+ selector: 'rolatech-onboarding-summary-card',
1278
+ standalone: true,
1279
+ changeDetection: ChangeDetectionStrategy.OnPush,
1280
+ encapsulation: ViewEncapsulation.None,
1281
+ host: { class: 'block' },
1282
+ template: `
1283
+ <section class="rounded-2xl border border-(--rt-border-color) bg-(--rt-base-background) p-5 shadow-sm">
1284
+ <h3 class="text-base font-semibold text-(--rt-text-primary)">{{ title() }}</h3>
1285
+
1286
+ <div class="mt-4 grid gap-4 md:grid-cols-2">
1287
+ @for (item of items(); track item.label) {
1288
+ <div class="rounded-xl border border-(--rt-border-color) bg-(--rt-raised-background) p-3">
1289
+ <p class="text-xs font-medium uppercase tracking-wide text-(--rt-text-secondary)">{{ item.label }}</p>
1290
+ <p class="mt-1 text-sm font-medium text-(--rt-text-primary)">{{ item.value || '-' }}</p>
1291
+ </div>
1292
+ }
1293
+ </div>
1294
+ </section>
1295
+ `,
1296
+ }]
1297
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }] } });
1298
+
1299
+ class OnboardingTimeline {
1300
+ items = input([], ...(ngDevMode ? [{ debugName: "items" }] : []));
1301
+ collapsible = input(false, ...(ngDevMode ? [{ debugName: "collapsible" }] : []));
1302
+ collapseThreshold = input(6, ...(ngDevMode ? [{ debugName: "collapseThreshold" }] : []));
1303
+ expanded = signal(true, ...(ngDevMode ? [{ debugName: "expanded" }] : []));
1304
+ canCollapse = computed(() => this.collapsible() && this.items().length >= this.collapseThreshold(), ...(ngDevMode ? [{ debugName: "canCollapse" }] : []));
1305
+ panelOpen = computed(() => !this.canCollapse() || this.expanded(), ...(ngDevMode ? [{ debugName: "panelOpen" }] : []));
1306
+ toggle() {
1307
+ this.expanded.update((value) => !value);
1308
+ }
1309
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingTimeline, deps: [], target: i0.ɵɵFactoryTarget.Component });
1310
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: OnboardingTimeline, isStandalone: true, selector: "rolatech-onboarding-timeline", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, collapseThreshold: { classPropertyName: "collapseThreshold", publicName: "collapseThreshold", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, ngImport: i0, template: `
1311
+ <section class="rounded-2xl border border-(--rt-border-color) bg-(--rt-base-background) p-5 shadow-sm">
1312
+ <div class="flex items-center justify-between gap-3">
1313
+ <h3 class="text-base font-semibold text-(--rt-text-primary)">Timeline</h3>
1314
+ @if (canCollapse()) {
1315
+ <button
1316
+ type="button"
1317
+ class="rounded-lg border border-(--rt-border-color) px-3 py-1.5 text-xs font-semibold uppercase tracking-wide text-(--rt-text-secondary) transition hover:bg-(--rt-raised-background)"
1318
+ (click)="toggle()"
1319
+ >
1320
+ {{ panelOpen() ? 'Collapse' : 'Expand' }}
1321
+ </button>
1322
+ }
1323
+ </div>
1324
+
1325
+ @if (items().length === 0) {
1326
+ <p class="mt-4 text-sm text-(--rt-text-secondary)">No timeline events yet.</p>
1327
+ } @else {
1328
+ <div
1329
+ class="mt-4 transform transition-all duration-300 ease-out"
1330
+ [style.maxHeight]="panelOpen() ? '1400px' : '0px'"
1331
+ [style.opacity]="panelOpen() ? '1' : '0'"
1332
+ [style.transform]="panelOpen() ? 'translateX(0)' : 'translateX(24px)'"
1333
+ [style.overflow]="panelOpen() ? 'visible' : 'hidden'"
1334
+ >
1335
+ <ol class="space-y-3">
1336
+ @for (item of items(); track item.id) {
1337
+ <li class="rounded-xl border border-(--rt-border-color) p-3">
1338
+ <div class="flex flex-wrap items-start justify-between gap-2">
1339
+ <p class="text-sm font-semibold text-(--rt-text-primary)">{{ item.title || item.type }}</p>
1340
+ <p class="text-xs text-(--rt-text-secondary)">{{ item.createdAt | date: 'medium' }}</p>
1341
+ </div>
1342
+ @if (item.description) {
1343
+ <p class="mt-2 text-sm text-(--rt-text-secondary)">{{ item.description }}</p>
1344
+ }
1345
+ </li>
1346
+ }
1347
+ </ol>
1348
+ </div>
1349
+ }
1350
+ </section>
1351
+ `, isInline: true, dependencies: [{ kind: "pipe", type: DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1352
+ }
1353
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingTimeline, decorators: [{
1354
+ type: Component,
1355
+ args: [{
1356
+ selector: 'rolatech-onboarding-timeline',
1357
+ standalone: true,
1358
+ imports: [DatePipe],
1359
+ changeDetection: ChangeDetectionStrategy.OnPush,
1360
+ encapsulation: ViewEncapsulation.None,
1361
+ host: { class: 'block' },
1362
+ template: `
1363
+ <section class="rounded-2xl border border-(--rt-border-color) bg-(--rt-base-background) p-5 shadow-sm">
1364
+ <div class="flex items-center justify-between gap-3">
1365
+ <h3 class="text-base font-semibold text-(--rt-text-primary)">Timeline</h3>
1366
+ @if (canCollapse()) {
1367
+ <button
1368
+ type="button"
1369
+ class="rounded-lg border border-(--rt-border-color) px-3 py-1.5 text-xs font-semibold uppercase tracking-wide text-(--rt-text-secondary) transition hover:bg-(--rt-raised-background)"
1370
+ (click)="toggle()"
1371
+ >
1372
+ {{ panelOpen() ? 'Collapse' : 'Expand' }}
1373
+ </button>
1374
+ }
1375
+ </div>
1376
+
1377
+ @if (items().length === 0) {
1378
+ <p class="mt-4 text-sm text-(--rt-text-secondary)">No timeline events yet.</p>
1379
+ } @else {
1380
+ <div
1381
+ class="mt-4 transform transition-all duration-300 ease-out"
1382
+ [style.maxHeight]="panelOpen() ? '1400px' : '0px'"
1383
+ [style.opacity]="panelOpen() ? '1' : '0'"
1384
+ [style.transform]="panelOpen() ? 'translateX(0)' : 'translateX(24px)'"
1385
+ [style.overflow]="panelOpen() ? 'visible' : 'hidden'"
1386
+ >
1387
+ <ol class="space-y-3">
1388
+ @for (item of items(); track item.id) {
1389
+ <li class="rounded-xl border border-(--rt-border-color) p-3">
1390
+ <div class="flex flex-wrap items-start justify-between gap-2">
1391
+ <p class="text-sm font-semibold text-(--rt-text-primary)">{{ item.title || item.type }}</p>
1392
+ <p class="text-xs text-(--rt-text-secondary)">{{ item.createdAt | date: 'medium' }}</p>
1393
+ </div>
1394
+ @if (item.description) {
1395
+ <p class="mt-2 text-sm text-(--rt-text-secondary)">{{ item.description }}</p>
1396
+ }
1397
+ </li>
1398
+ }
1399
+ </ol>
1400
+ </div>
1401
+ }
1402
+ </section>
1403
+ `,
1404
+ }]
1405
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], collapseThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseThreshold", required: false }] }] } });
1406
+
1407
+ class OnboardingTimelineDrawer {
1408
+ open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
1409
+ title = input('Application Timeline', ...(ngDevMode ? [{ debugName: "title" }] : []));
1410
+ items = input([], ...(ngDevMode ? [{ debugName: "items" }] : []));
1411
+ zIndex = input(9100, ...(ngDevMode ? [{ debugName: "zIndex" }] : []));
1412
+ closeRequested = output();
1413
+ requestClose() {
1414
+ this.closeRequested.emit();
1415
+ }
1416
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingTimelineDrawer, deps: [], target: i0.ɵɵFactoryTarget.Component });
1417
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.1", type: OnboardingTimelineDrawer, isStandalone: true, selector: "rolatech-onboarding-timeline-drawer", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closeRequested: "closeRequested" }, host: { classAttribute: "block" }, ngImport: i0, template: `
1418
+ <div
1419
+ class="fixed inset-0 transition-opacity duration-300 ease-out"
1420
+ [style.opacity]="open() ? '1' : '0'"
1421
+ [style.pointer-events]="open() ? 'auto' : 'none'"
1422
+ [style.zIndex]="zIndex()"
1423
+ >
1424
+ <div class="absolute inset-0 bg-black/20" (click)="requestClose()"></div>
1425
+
1426
+ <aside
1427
+ class="absolute right-0 top-0 h-full w-full max-w-2xl border-l border-(--rt-border-color) bg-(--rt-base-background) p-5 shadow-2xl transition-transform duration-300 ease-out"
1428
+ [style.transform]="open() ? 'translateX(0)' : 'translateX(100%)'"
1429
+ >
1430
+ <div class="mb-4 flex items-center justify-between gap-3">
1431
+ <h3 class="text-base font-semibold text-(--rt-text-primary)">{{ title() }}</h3>
1432
+ <button
1433
+ type="button"
1434
+ class="rounded-lg border border-(--rt-border-color) px-3 py-1.5 text-xs font-semibold uppercase tracking-wide text-(--rt-text-secondary) transition hover:bg-(--rt-raised-background)"
1435
+ (click)="requestClose()"
1436
+ >
1437
+ Close
1438
+ </button>
1439
+ </div>
1440
+
1441
+ <div class="h-[calc(100vh-6rem)] overflow-auto pr-1">
1442
+ <rolatech-onboarding-timeline [items]="items()" />
1443
+ </div>
1444
+ </aside>
1445
+ </div>
1446
+ `, isInline: true, dependencies: [{ kind: "component", type: OnboardingTimeline, selector: "rolatech-onboarding-timeline", inputs: ["items", "collapsible", "collapseThreshold"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1447
+ }
1448
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: OnboardingTimelineDrawer, decorators: [{
1449
+ type: Component,
1450
+ args: [{
1451
+ selector: 'rolatech-onboarding-timeline-drawer',
1452
+ standalone: true,
1453
+ imports: [OnboardingTimeline],
1454
+ changeDetection: ChangeDetectionStrategy.OnPush,
1455
+ encapsulation: ViewEncapsulation.None,
1456
+ host: { class: 'block' },
1457
+ template: `
1458
+ <div
1459
+ class="fixed inset-0 transition-opacity duration-300 ease-out"
1460
+ [style.opacity]="open() ? '1' : '0'"
1461
+ [style.pointer-events]="open() ? 'auto' : 'none'"
1462
+ [style.zIndex]="zIndex()"
1463
+ >
1464
+ <div class="absolute inset-0 bg-black/20" (click)="requestClose()"></div>
1465
+
1466
+ <aside
1467
+ class="absolute right-0 top-0 h-full w-full max-w-2xl border-l border-(--rt-border-color) bg-(--rt-base-background) p-5 shadow-2xl transition-transform duration-300 ease-out"
1468
+ [style.transform]="open() ? 'translateX(0)' : 'translateX(100%)'"
1469
+ >
1470
+ <div class="mb-4 flex items-center justify-between gap-3">
1471
+ <h3 class="text-base font-semibold text-(--rt-text-primary)">{{ title() }}</h3>
1472
+ <button
1473
+ type="button"
1474
+ class="rounded-lg border border-(--rt-border-color) px-3 py-1.5 text-xs font-semibold uppercase tracking-wide text-(--rt-text-secondary) transition hover:bg-(--rt-raised-background)"
1475
+ (click)="requestClose()"
1476
+ >
1477
+ Close
1478
+ </button>
1479
+ </div>
1480
+
1481
+ <div class="h-[calc(100vh-6rem)] overflow-auto pr-1">
1482
+ <rolatech-onboarding-timeline [items]="items()" />
1483
+ </div>
1484
+ </aside>
1485
+ </div>
1486
+ `,
1487
+ }]
1488
+ }], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], closeRequested: [{ type: i0.Output, args: ["closeRequested"] }] } });
1489
+
1490
+ /**
1491
+ * Generated bundle index. Do not edit.
1492
+ */
1493
+
1494
+ export { ADMIN_ONBOARDING_ROUTES, AGENT_APPLY_ROUTES, AGENT_ONBOARDING_ROUTES, AdminOnboardingDetailFacade, AdminOnboardingListFacade, AdminOnboardingReviewFacade, AgentApplyFacade, AgentOnboardingFacade, OnboardingDocumentUploader, OnboardingIssueList, OnboardingPageShell, OnboardingStatusBadge, OnboardingStepNav, OnboardingSummaryCard, OnboardingTimeline, OnboardingTimelineDrawer, applicationIdGuard, applyStepGuard };
1495
+ //# sourceMappingURL=rolatech-angular-onboarding.mjs.map