@rolatech/angular-onboarding 20.3.0-beta.2 → 20.3.0-beta.4

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 (40) hide show
  1. package/README.md +1 -1
  2. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-detail-page-DREEMvoT.mjs +720 -0
  3. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-detail-page-DREEMvoT.mjs.map +1 -0
  4. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-index-page-DP7wffLd.mjs +313 -0
  5. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-index-page-DP7wffLd.mjs.map +1 -0
  6. package/fesm2022/rolatech-angular-onboarding-agent-apply-form-page-y02hYlN_.mjs +446 -0
  7. package/fesm2022/rolatech-angular-onboarding-agent-apply-form-page-y02hYlN_.mjs.map +1 -0
  8. package/fesm2022/rolatech-angular-onboarding-agent-apply-result-page-CEL4nWb_.mjs +141 -0
  9. package/fesm2022/rolatech-angular-onboarding-agent-apply-result-page-CEL4nWb_.mjs.map +1 -0
  10. package/fesm2022/rolatech-angular-onboarding-agent-apply-review-page-DG_D03YW.mjs +453 -0
  11. package/fesm2022/rolatech-angular-onboarding-agent-apply-review-page-DG_D03YW.mjs.map +1 -0
  12. package/fesm2022/{rolatech-angular-onboarding-agent-apply-shell-page-DibWYeD1.mjs → rolatech-angular-onboarding-agent-apply-shell-page-CaTvnFzk.mjs} +27 -40
  13. package/fesm2022/rolatech-angular-onboarding-agent-apply-shell-page-CaTvnFzk.mjs.map +1 -0
  14. package/fesm2022/{rolatech-angular-onboarding-agent-apply-start-page-DC7gyOnS.mjs → rolatech-angular-onboarding-agent-apply-start-page-BfqO2YWB.mjs} +31 -29
  15. package/fesm2022/rolatech-angular-onboarding-agent-apply-start-page-BfqO2YWB.mjs.map +1 -0
  16. package/fesm2022/{rolatech-angular-onboarding-agent-onboarding-documents-page-DWBGTj5J.mjs → rolatech-angular-onboarding-agent-onboarding-documents-page-BKDYZE0e.mjs} +79 -6
  17. package/fesm2022/rolatech-angular-onboarding-agent-onboarding-documents-page-BKDYZE0e.mjs.map +1 -0
  18. package/fesm2022/rolatech-angular-onboarding.mjs +2251 -233
  19. package/fesm2022/rolatech-angular-onboarding.mjs.map +1 -1
  20. package/package.json +1 -1
  21. package/types/rolatech-angular-onboarding.d.ts +219 -12
  22. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-detail-page-DKJQX3cs.mjs +0 -224
  23. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-detail-page-DKJQX3cs.mjs.map +0 -1
  24. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-index-page-BO4pC_NU.mjs +0 -206
  25. package/fesm2022/rolatech-angular-onboarding-admin-onboarding-index-page-BO4pC_NU.mjs.map +0 -1
  26. package/fesm2022/rolatech-angular-onboarding-agent-apply-banking-page-VYNfR4fy.mjs +0 -133
  27. package/fesm2022/rolatech-angular-onboarding-agent-apply-banking-page-VYNfR4fy.mjs.map +0 -1
  28. package/fesm2022/rolatech-angular-onboarding-agent-apply-financial-page-Ck3Rowke.mjs +0 -132
  29. package/fesm2022/rolatech-angular-onboarding-agent-apply-financial-page-Ck3Rowke.mjs.map +0 -1
  30. package/fesm2022/rolatech-angular-onboarding-agent-apply-profile-page-DNepDxHu.mjs +0 -122
  31. package/fesm2022/rolatech-angular-onboarding-agent-apply-profile-page-DNepDxHu.mjs.map +0 -1
  32. package/fesm2022/rolatech-angular-onboarding-agent-apply-qualification-page-CSwupuKt.mjs +0 -108
  33. package/fesm2022/rolatech-angular-onboarding-agent-apply-qualification-page-CSwupuKt.mjs.map +0 -1
  34. package/fesm2022/rolatech-angular-onboarding-agent-apply-review-page-DugCjfvK.mjs +0 -182
  35. package/fesm2022/rolatech-angular-onboarding-agent-apply-review-page-DugCjfvK.mjs.map +0 -1
  36. package/fesm2022/rolatech-angular-onboarding-agent-apply-shell-page-DibWYeD1.mjs.map +0 -1
  37. package/fesm2022/rolatech-angular-onboarding-agent-apply-start-page-DC7gyOnS.mjs.map +0 -1
  38. package/fesm2022/rolatech-angular-onboarding-agent-apply-submitted-page-BMkV2V8K.mjs +0 -55
  39. package/fesm2022/rolatech-angular-onboarding-agent-apply-submitted-page-BMkV2V8K.mjs.map +0 -1
  40. package/fesm2022/rolatech-angular-onboarding-agent-onboarding-documents-page-DWBGTj5J.mjs.map +0 -1
@@ -0,0 +1,720 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, computed, effect, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { toSignal } from '@angular/core/rxjs-interop';
4
+ import { ActivatedRoute, RouterLink } from '@angular/router';
5
+ import { onboardingApplicantTypeLabel, onboardingStatusLabel, onboardingVatModeLabel, onboardingDocumentTypeLabel } from '@rolatech/angular-services';
6
+ import { PlatformPageHeader, PlatformStatCard } from '@rolatech/angular-platform';
7
+ import { AdminOnboardingReviewFacade, onboardingFieldIssueOptions, onboardingDocumentIssueOptions, OnboardingStatusBadge, OnboardingIssueList, OnboardingTimelineDrawer, OnboardingReviewRow, OnboardingReviewIssuesBanner, OnboardingDocumentPreviewDialog } from './rolatech-angular-onboarding.mjs';
8
+
9
+ class AdminOnboardingDetailPage {
10
+ facade = inject(AdminOnboardingReviewFacade);
11
+ timelineOpen = signal(false, ...(ngDevMode ? [{ debugName: "timelineOpen" }] : []));
12
+ previewOpen = signal(false, ...(ngDevMode ? [{ debugName: "previewOpen" }] : []));
13
+ previewTitle = signal(null, ...(ngDevMode ? [{ debugName: "previewTitle" }] : []));
14
+ previewSubtitle = signal(null, ...(ngDevMode ? [{ debugName: "previewSubtitle" }] : []));
15
+ onboardingApplicantTypeLabel = onboardingApplicantTypeLabel;
16
+ onboardingStatusLabel = onboardingStatusLabel;
17
+ route = inject(ActivatedRoute);
18
+ paramMap = toSignal(this.route.paramMap, {
19
+ initialValue: this.route.snapshot.paramMap,
20
+ });
21
+ subtitle = computed(() => {
22
+ const detail = this.facade.detail();
23
+ if (!detail) {
24
+ return 'Inspect onboarding data and triage approvals inline.';
25
+ }
26
+ return `${detail.organizationName || detail.contactName || 'Applicant'} • ${detail.contactEmail || 'No email'}`;
27
+ }, ...(ngDevMode ? [{ debugName: "subtitle" }] : []));
28
+ title = computed(() => {
29
+ const detail = this.facade.detail();
30
+ if (!detail) {
31
+ return 'Agent Application Review';
32
+ }
33
+ return detail.organizationName || detail.contactName || 'Agent Application Review';
34
+ }, ...(ngDevMode ? [{ debugName: "title" }] : []));
35
+ documentCount = computed(() => this.facade.detail()?.documents.length ?? 0, ...(ngDevMode ? [{ debugName: "documentCount" }] : []));
36
+ timelineCount = computed(() => this.facade.detail()?.timeline.length ?? 0, ...(ngDevMode ? [{ debugName: "timelineCount" }] : []));
37
+ openIssueCount = computed(() => (this.facade.detail()?.issues ?? []).filter((issue) => !issue.resolved).length, ...(ngDevMode ? [{ debugName: "openIssueCount" }] : []));
38
+ profileItems = computed(() => {
39
+ const detail = this.facade.detail();
40
+ if (!detail) {
41
+ return [];
42
+ }
43
+ return [
44
+ ...(detail.applicantType === 'COMPANY'
45
+ ? [{ key: 'organizationName', label: 'Company legal name', value: detail.organizationName, helper: '' }]
46
+ : [{ key: 'contactName', label: 'Applicant name', value: detail.contactName, helper: '' }]),
47
+ ...(detail.applicantType === 'COMPANY'
48
+ ? [{ key: 'contactName', label: 'Primary contact', value: detail.contactName, helper: '' }]
49
+ : []),
50
+ { key: 'contactEmail', label: 'Primary email', value: detail.contactEmail, helper: '' },
51
+ { key: 'contactPhone', label: 'Phone number', value: detail.contactPhone, helper: '' },
52
+ { key: 'countryCode', label: 'Country code', value: detail.countryCode, helper: '' },
53
+ ];
54
+ }, ...(ngDevMode ? [{ debugName: "profileItems" }] : []));
55
+ complianceItems = computed(() => {
56
+ const detail = this.facade.detail();
57
+ if (!detail) {
58
+ return [];
59
+ }
60
+ return [
61
+ { key: 'vatMode', label: 'VAT mode', value: onboardingVatModeLabel(detail.vatMode ?? null), helper: '' },
62
+ { key: 'vatNumber', label: 'VAT number', value: detail.vatNumber || 'Missing', helper: '' },
63
+ { key: 'bankName', label: 'Bank name', value: detail.bankName, helper: '' },
64
+ { key: 'accountHolderName', label: 'Account holder', value: detail.accountHolderName, helper: '' },
65
+ { key: 'sortCode', label: 'Sort code', value: detail.sortCode, helper: '' },
66
+ { key: 'accountNumber', label: 'Account number', value: detail.accountNumber, helper: '' },
67
+ ];
68
+ }, ...(ngDevMode ? [{ debugName: "complianceItems" }] : []));
69
+ documentItems = computed(() => {
70
+ const detail = this.facade.detail();
71
+ if (!detail) {
72
+ return [];
73
+ }
74
+ const requiredItems = this.facade.requiredDocuments().map((spec) => {
75
+ const document = detail.documents.find((item) => item.documentType === spec.type) ?? null;
76
+ return {
77
+ documentType: spec.type,
78
+ label: spec.label,
79
+ helper: spec.helperText ?? '',
80
+ document,
81
+ value: document?.originalFilename ?? 'Missing',
82
+ };
83
+ });
84
+ const requiredTypes = new Set(requiredItems.map((item) => item.documentType));
85
+ const additionalItems = detail.documents
86
+ .filter((item) => !requiredTypes.has(item.documentType))
87
+ .map((item) => ({
88
+ documentType: item.documentType,
89
+ label: `Additional: ${onboardingDocumentTypeLabel(item.documentType)}`,
90
+ helper: 'Supporting document uploaded by the applicant.',
91
+ document: item,
92
+ value: item.originalFilename,
93
+ }));
94
+ return [...requiredItems, ...additionalItems];
95
+ }, ...(ngDevMode ? [{ debugName: "documentItems" }] : []));
96
+ constructor() {
97
+ effect(() => {
98
+ const applicationId = this.paramMap().get('applicationId');
99
+ if (!applicationId) {
100
+ return;
101
+ }
102
+ void this.facade.load(applicationId);
103
+ });
104
+ }
105
+ setComment(event) {
106
+ const target = event.target;
107
+ this.facade.setComment(target.value);
108
+ }
109
+ fieldIssueOptions(fieldKey) {
110
+ return onboardingFieldIssueOptions(fieldKey);
111
+ }
112
+ documentIssueOptions(documentType) {
113
+ return onboardingDocumentIssueOptions(documentType);
114
+ }
115
+ onFieldIssue(fieldKey, draft) {
116
+ this.facade.setFieldIssueDraft(fieldKey, draft);
117
+ }
118
+ fieldExistingIssue(fieldKey) {
119
+ const existing = this.facade.existingFieldIssues();
120
+ return Object.prototype.hasOwnProperty.call(existing, fieldKey) ? existing[fieldKey] : null;
121
+ }
122
+ onFieldPassed(fieldKey, passed) {
123
+ this.facade.toggleFieldPassed(fieldKey, passed);
124
+ }
125
+ onDocumentIssue(documentType, draft) {
126
+ this.facade.setDocumentIssueDraft(documentType, draft);
127
+ }
128
+ documentExistingIssue(documentType) {
129
+ const existing = this.facade.existingDocumentIssues();
130
+ return existing[documentType] ?? null;
131
+ }
132
+ onDocumentPassed(documentType, passed) {
133
+ this.facade.toggleDocumentPassed(documentType, passed);
134
+ }
135
+ async openDocumentPreview(item) {
136
+ if (!item.document) {
137
+ return;
138
+ }
139
+ this.previewTitle.set(item.label);
140
+ this.previewSubtitle.set(item.document.originalFilename || null);
141
+ this.previewOpen.set(true);
142
+ await this.facade.openDocumentPreview(item.document.id);
143
+ }
144
+ async startReview() {
145
+ const applicationId = this.paramMap().get('applicationId');
146
+ if (!applicationId) {
147
+ return;
148
+ }
149
+ await this.facade.startReview(applicationId);
150
+ }
151
+ async needMoreInfo() {
152
+ const applicationId = this.paramMap().get('applicationId');
153
+ if (!applicationId) {
154
+ return;
155
+ }
156
+ await this.facade.requestMoreInfo(applicationId);
157
+ }
158
+ async approve() {
159
+ const applicationId = this.paramMap().get('applicationId');
160
+ if (!applicationId) {
161
+ return;
162
+ }
163
+ await this.facade.approve(applicationId);
164
+ }
165
+ async fail() {
166
+ const applicationId = this.paramMap().get('applicationId');
167
+ if (!applicationId) {
168
+ return;
169
+ }
170
+ await this.facade.fail(applicationId);
171
+ }
172
+ openTimeline() {
173
+ this.timelineOpen.set(true);
174
+ }
175
+ closeTimeline() {
176
+ this.timelineOpen.set(false);
177
+ }
178
+ closeDocumentPreview() {
179
+ this.previewOpen.set(false);
180
+ this.previewTitle.set(null);
181
+ this.previewSubtitle.set(null);
182
+ this.facade.clearDocumentPreview();
183
+ }
184
+ countryLabel(value) {
185
+ switch ((value ?? '').toUpperCase()) {
186
+ case 'CN':
187
+ return 'China';
188
+ case 'UK':
189
+ return 'United Kingdom';
190
+ default:
191
+ return value || '—';
192
+ }
193
+ }
194
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AdminOnboardingDetailPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
195
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: AdminOnboardingDetailPage, isStandalone: true, selector: "rolatech-admin-onboarding-detail-page", host: { classAttribute: "block" }, providers: [AdminOnboardingReviewFacade], ngImport: i0, template: `
196
+ <section class="rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)">
197
+ <rolatech-platform-page-header>
198
+ <div header-left class="space-y-2">
199
+ <div class="flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
200
+ <a [routerLink]="['../']" class="hover:underline cursor-pointer">Agent Applications</a>
201
+ @if (facade.detail(); as detail) {
202
+ <span>/</span>
203
+ <span>{{ detail.organizationName || detail.contactName || detail.id }}</span>
204
+ }
205
+ </div>
206
+
207
+ <div>
208
+ <h1 class="text-2xl font-semibold tracking-tight">{{ title() }}</h1>
209
+ <p class="mt-1 text-sm text-muted-foreground">{{ subtitle() }}</p>
210
+ </div>
211
+ </div>
212
+
213
+ <div header-actions>
214
+ @if (facade.detail()?.status || null; as status) {
215
+ <rolatech-onboarding-status-badge [status]="status" />
216
+ }
217
+ <a
218
+ [routerLink]="['review']"
219
+ class="inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium hover:bg-(--rt-raised-background) cursor-pointer"
220
+ >
221
+ Review Page
222
+ </a>
223
+ <button
224
+ type="button"
225
+ class="inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium"
226
+ (click)="openTimeline()"
227
+ >
228
+ Timeline
229
+ </button>
230
+ </div>
231
+ </rolatech-platform-page-header>
232
+
233
+ <section class="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
234
+ <rolatech-platform-stat-card>
235
+ <div stat-label>Documents</div>
236
+ <div stat-value>{{ documentCount() }}</div>
237
+ </rolatech-platform-stat-card>
238
+
239
+ <rolatech-platform-stat-card>
240
+ <div stat-label>Open Issues</div>
241
+ <div stat-value>{{ openIssueCount() }}</div>
242
+ </rolatech-platform-stat-card>
243
+
244
+ <rolatech-platform-stat-card>
245
+ <div stat-label>Timeline Events</div>
246
+ <div stat-value>{{ timelineCount() }}</div>
247
+ </rolatech-platform-stat-card>
248
+
249
+ <rolatech-platform-stat-card>
250
+ <div stat-label>Draft Issues</div>
251
+ <div stat-value>{{ facade.issueDrafts().length }}</div>
252
+ </rolatech-platform-stat-card>
253
+ </section>
254
+
255
+ @if (facade.error()) {
256
+ <div class="rounded-2xl border border-rose-200 bg-rose-50 px-4 py-3 text-sm text-rose-700">{{ facade.error() }}</div>
257
+ }
258
+
259
+ @if (facade.detail(); as detail) {
260
+ <div class="space-y-4">
261
+ <section class="rounded-2xl border border-(--rt-border-color) bg-card p-5 shadow-sm">
262
+ <div class="flex flex-wrap items-center gap-3 text-sm text-muted-foreground">
263
+ <span>Application ID: <span class="font-semibold text-(--rt-text-primary)">{{ detail.id }}</span></span>
264
+ <span>•</span>
265
+ <span>{{ onboardingStatusLabel(detail.status) }}</span>
266
+ <span>•</span>
267
+ <span>{{ onboardingApplicantTypeLabel(detail.applicantType) }}</span>
268
+ <span>•</span>
269
+ <span>{{ countryLabel(detail.companyCountry) }}</span>
270
+ </div>
271
+ </section>
272
+
273
+ @if (detail.status === 'NEED_MORE_INFO') {
274
+ <rolatech-onboarding-review-issues-banner [issues]="detail.issues" [status]="detail.status" />
275
+ }
276
+
277
+ <section class="space-y-4 rounded-3xl border border-(--rt-border-color) bg-(--rt-base-background) p-6 shadow-sm">
278
+ <div class="flex flex-wrap items-start justify-between gap-4">
279
+ <div class="space-y-2">
280
+ <h2 class="text-lg font-semibold text-(--rt-text-primary)">Inline Review Workspace</h2>
281
+ <p class="max-w-2xl text-sm text-(--rt-text-secondary)">
282
+ Review the application in place. Mark a field or document as passed, or leave an issue directly beside the item that needs correction.
283
+ </p>
284
+ </div>
285
+
286
+ <span class="rounded-full border border-(--rt-border-color) bg-(--rt-raised-background) px-3 py-1 text-xs font-semibold text-(--rt-text-secondary)">
287
+ {{ facade.issueDrafts().length }} draft issues
288
+ </span>
289
+ </div>
290
+
291
+ <label class="grid gap-2">
292
+ <span class="text-sm font-medium text-(--rt-text-secondary)">Review summary</span>
293
+ <textarea
294
+ class="min-h-28 rounded-xl border border-(--rt-border-color) px-3 py-2"
295
+ [value]="facade.reviewComment()"
296
+ (input)="setComment($event)"
297
+ placeholder="Add a high-level review note or final decision context..."
298
+ ></textarea>
299
+ </label>
300
+
301
+ <div class="flex flex-wrap gap-3">
302
+ <button
303
+ type="button"
304
+ class="rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-semibold text-(--rt-text-secondary) hover:bg-(--rt-raised-background)"
305
+ [disabled]="facade.saving()"
306
+ (click)="startReview()"
307
+ >
308
+ Start Review
309
+ </button>
310
+
311
+ <button
312
+ type="button"
313
+ class="rounded-xl border border-amber-300 bg-amber-50 px-4 py-2 text-sm font-semibold text-amber-800 hover:bg-amber-100"
314
+ [disabled]="facade.saving()"
315
+ (click)="needMoreInfo()"
316
+ >
317
+ Need More Info
318
+ </button>
319
+
320
+ <button
321
+ type="button"
322
+ class="rounded-xl border border-emerald-300 bg-emerald-50 px-4 py-2 text-sm font-semibold text-emerald-800 hover:bg-emerald-100"
323
+ [disabled]="facade.saving()"
324
+ (click)="approve()"
325
+ >
326
+ Approve
327
+ </button>
328
+
329
+ <button
330
+ type="button"
331
+ class="rounded-xl border border-rose-300 bg-rose-50 px-4 py-2 text-sm font-semibold text-rose-800 hover:bg-rose-100"
332
+ [disabled]="facade.saving()"
333
+ (click)="fail()"
334
+ >
335
+ Fail
336
+ </button>
337
+ </div>
338
+ </section>
339
+
340
+ <section class="space-y-4">
341
+ <div class="space-y-1">
342
+ <h2 class="text-lg font-semibold text-(--rt-text-primary)">Applicant Profile</h2>
343
+ <p class="text-sm text-(--rt-text-secondary)">Check identity, contact, and company information.</p>
344
+ </div>
345
+
346
+ <div class="grid gap-4 lg:grid-cols-2">
347
+ @for (item of profileItems(); track item.key) {
348
+ <rolatech-onboarding-review-row
349
+ [label]="item.label"
350
+ [value]="item.value"
351
+ [helper]="item.helper"
352
+ [issueOptions]="fieldIssueOptions(item.key)"
353
+ [existingIssue]="fieldExistingIssue(item.key)"
354
+ [draftIssue]="facade.fieldDraft(item.key)"
355
+ [passed]="facade.fieldPassed(item.key)"
356
+ [busy]="facade.saving()"
357
+ (passedChange)="onFieldPassed(item.key, $event)"
358
+ (draftIssueChange)="onFieldIssue(item.key, $event)"
359
+ />
360
+ }
361
+ </div>
362
+ </section>
363
+
364
+ <section class="space-y-4">
365
+ <div class="space-y-1">
366
+ <h2 class="text-lg font-semibold text-(--rt-text-primary)">Compliance and Banking</h2>
367
+ <p class="text-sm text-(--rt-text-secondary)">Check VAT setup and settlement account details.</p>
368
+ </div>
369
+
370
+ <div class="grid gap-4 lg:grid-cols-2">
371
+ @for (item of complianceItems(); track item.key) {
372
+ <rolatech-onboarding-review-row
373
+ [label]="item.label"
374
+ [value]="item.value"
375
+ [helper]="item.helper"
376
+ [issueOptions]="fieldIssueOptions(item.key)"
377
+ [existingIssue]="fieldExistingIssue(item.key)"
378
+ [draftIssue]="facade.fieldDraft(item.key)"
379
+ [passed]="facade.fieldPassed(item.key)"
380
+ [busy]="facade.saving()"
381
+ (passedChange)="onFieldPassed(item.key, $event)"
382
+ (draftIssueChange)="onFieldIssue(item.key, $event)"
383
+ />
384
+ }
385
+ </div>
386
+ </section>
387
+
388
+ <section class="space-y-4">
389
+ <div class="space-y-1">
390
+ <h2 class="text-lg font-semibold text-(--rt-text-primary)">Documents</h2>
391
+ <p class="text-sm text-(--rt-text-secondary)">Review required documents and flag anything missing or unreadable.</p>
392
+ </div>
393
+
394
+ <div class="grid gap-4 lg:grid-cols-2">
395
+ @for (item of documentItems(); track item.documentType + item.label) {
396
+ <rolatech-onboarding-review-row
397
+ [label]="item.label"
398
+ [value]="item.value"
399
+ [helper]="item.helper"
400
+ [issueOptions]="documentIssueOptions(item.documentType)"
401
+ [existingIssue]="documentExistingIssue(item.documentType)"
402
+ [draftIssue]="facade.documentDraft(item.documentType)"
403
+ [passed]="facade.documentPassed(item.documentType)"
404
+ [busy]="facade.saving()"
405
+ [actionLabel]="item.document ? 'Preview' : null"
406
+ [actionDisabled]="!item.document"
407
+ (passedChange)="onDocumentPassed(item.documentType, $event)"
408
+ (draftIssueChange)="onDocumentIssue(item.documentType, $event)"
409
+ (actionTriggered)="openDocumentPreview(item)"
410
+ />
411
+ }
412
+ </div>
413
+ </section>
414
+
415
+ <rolatech-onboarding-issue-list [issues]="detail.issues" />
416
+ </div>
417
+ } @else {
418
+ <div class="rounded-2xl border border-(--rt-border-color) bg-(--rt-base-background) p-5 text-sm text-(--rt-text-secondary) shadow-sm">
419
+ Loading application details...
420
+ </div>
421
+ }
422
+
423
+ @if (facade.detail(); as detail) {
424
+ <rolatech-onboarding-timeline-drawer
425
+ floating
426
+ [open]="timelineOpen()"
427
+ [title]="'Application Timeline'"
428
+ [items]="detail.timeline"
429
+ [zIndex]="9100"
430
+ (closeRequested)="closeTimeline()"
431
+ />
432
+ }
433
+
434
+ <rolatech-onboarding-document-preview-dialog
435
+ [open]="previewOpen()"
436
+ [title]="previewTitle()"
437
+ [subtitle]="previewSubtitle()"
438
+ [url]="facade.previewUrl()"
439
+ [loading]="facade.previewLoading()"
440
+ [error]="facade.previewError()"
441
+ (closeRequested)="closeDocumentPreview()"
442
+ />
443
+ </section>
444
+ `, isInline: true, dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: PlatformPageHeader, selector: "rolatech-platform-page-header" }, { kind: "component", type: PlatformStatCard, selector: "rolatech-platform-stat-card" }, { kind: "component", type: OnboardingStatusBadge, selector: "rolatech-onboarding-status-badge", inputs: ["status"] }, { kind: "component", type: OnboardingIssueList, selector: "rolatech-onboarding-issue-list", inputs: ["issues"] }, { kind: "component", type: OnboardingTimelineDrawer, selector: "rolatech-onboarding-timeline-drawer", inputs: ["open", "title", "items", "zIndex"], outputs: ["closeRequested"] }, { kind: "component", type: OnboardingReviewRow, selector: "rolatech-onboarding-review-row", inputs: ["label", "value", "helper", "existingIssue", "issueOptions", "draftIssue", "passed", "busy", "actionLabel", "actionDisabled"], outputs: ["passedChange", "draftIssueChange", "actionTriggered"] }, { kind: "component", type: OnboardingReviewIssuesBanner, selector: "rolatech-onboarding-review-issues-banner", inputs: ["issues", "status"] }, { kind: "component", type: OnboardingDocumentPreviewDialog, selector: "rolatech-onboarding-document-preview-dialog", inputs: ["open", "title", "subtitle", "url", "loading", "error"], outputs: ["closeRequested"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
445
+ }
446
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AdminOnboardingDetailPage, decorators: [{
447
+ type: Component,
448
+ args: [{
449
+ selector: 'rolatech-admin-onboarding-detail-page',
450
+ standalone: true,
451
+ imports: [
452
+ RouterLink,
453
+ PlatformPageHeader,
454
+ PlatformStatCard,
455
+ OnboardingStatusBadge,
456
+ OnboardingIssueList,
457
+ OnboardingTimelineDrawer,
458
+ OnboardingReviewRow,
459
+ OnboardingReviewIssuesBanner,
460
+ OnboardingDocumentPreviewDialog,
461
+ ],
462
+ providers: [AdminOnboardingReviewFacade],
463
+ changeDetection: ChangeDetectionStrategy.OnPush,
464
+ encapsulation: ViewEncapsulation.None,
465
+ host: { class: 'block' },
466
+ template: `
467
+ <section class="rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)">
468
+ <rolatech-platform-page-header>
469
+ <div header-left class="space-y-2">
470
+ <div class="flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
471
+ <a [routerLink]="['../']" class="hover:underline cursor-pointer">Agent Applications</a>
472
+ @if (facade.detail(); as detail) {
473
+ <span>/</span>
474
+ <span>{{ detail.organizationName || detail.contactName || detail.id }}</span>
475
+ }
476
+ </div>
477
+
478
+ <div>
479
+ <h1 class="text-2xl font-semibold tracking-tight">{{ title() }}</h1>
480
+ <p class="mt-1 text-sm text-muted-foreground">{{ subtitle() }}</p>
481
+ </div>
482
+ </div>
483
+
484
+ <div header-actions>
485
+ @if (facade.detail()?.status || null; as status) {
486
+ <rolatech-onboarding-status-badge [status]="status" />
487
+ }
488
+ <a
489
+ [routerLink]="['review']"
490
+ class="inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium hover:bg-(--rt-raised-background) cursor-pointer"
491
+ >
492
+ Review Page
493
+ </a>
494
+ <button
495
+ type="button"
496
+ class="inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium"
497
+ (click)="openTimeline()"
498
+ >
499
+ Timeline
500
+ </button>
501
+ </div>
502
+ </rolatech-platform-page-header>
503
+
504
+ <section class="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
505
+ <rolatech-platform-stat-card>
506
+ <div stat-label>Documents</div>
507
+ <div stat-value>{{ documentCount() }}</div>
508
+ </rolatech-platform-stat-card>
509
+
510
+ <rolatech-platform-stat-card>
511
+ <div stat-label>Open Issues</div>
512
+ <div stat-value>{{ openIssueCount() }}</div>
513
+ </rolatech-platform-stat-card>
514
+
515
+ <rolatech-platform-stat-card>
516
+ <div stat-label>Timeline Events</div>
517
+ <div stat-value>{{ timelineCount() }}</div>
518
+ </rolatech-platform-stat-card>
519
+
520
+ <rolatech-platform-stat-card>
521
+ <div stat-label>Draft Issues</div>
522
+ <div stat-value>{{ facade.issueDrafts().length }}</div>
523
+ </rolatech-platform-stat-card>
524
+ </section>
525
+
526
+ @if (facade.error()) {
527
+ <div class="rounded-2xl border border-rose-200 bg-rose-50 px-4 py-3 text-sm text-rose-700">{{ facade.error() }}</div>
528
+ }
529
+
530
+ @if (facade.detail(); as detail) {
531
+ <div class="space-y-4">
532
+ <section class="rounded-2xl border border-(--rt-border-color) bg-card p-5 shadow-sm">
533
+ <div class="flex flex-wrap items-center gap-3 text-sm text-muted-foreground">
534
+ <span>Application ID: <span class="font-semibold text-(--rt-text-primary)">{{ detail.id }}</span></span>
535
+ <span>•</span>
536
+ <span>{{ onboardingStatusLabel(detail.status) }}</span>
537
+ <span>•</span>
538
+ <span>{{ onboardingApplicantTypeLabel(detail.applicantType) }}</span>
539
+ <span>•</span>
540
+ <span>{{ countryLabel(detail.companyCountry) }}</span>
541
+ </div>
542
+ </section>
543
+
544
+ @if (detail.status === 'NEED_MORE_INFO') {
545
+ <rolatech-onboarding-review-issues-banner [issues]="detail.issues" [status]="detail.status" />
546
+ }
547
+
548
+ <section class="space-y-4 rounded-3xl border border-(--rt-border-color) bg-(--rt-base-background) p-6 shadow-sm">
549
+ <div class="flex flex-wrap items-start justify-between gap-4">
550
+ <div class="space-y-2">
551
+ <h2 class="text-lg font-semibold text-(--rt-text-primary)">Inline Review Workspace</h2>
552
+ <p class="max-w-2xl text-sm text-(--rt-text-secondary)">
553
+ Review the application in place. Mark a field or document as passed, or leave an issue directly beside the item that needs correction.
554
+ </p>
555
+ </div>
556
+
557
+ <span class="rounded-full border border-(--rt-border-color) bg-(--rt-raised-background) px-3 py-1 text-xs font-semibold text-(--rt-text-secondary)">
558
+ {{ facade.issueDrafts().length }} draft issues
559
+ </span>
560
+ </div>
561
+
562
+ <label class="grid gap-2">
563
+ <span class="text-sm font-medium text-(--rt-text-secondary)">Review summary</span>
564
+ <textarea
565
+ class="min-h-28 rounded-xl border border-(--rt-border-color) px-3 py-2"
566
+ [value]="facade.reviewComment()"
567
+ (input)="setComment($event)"
568
+ placeholder="Add a high-level review note or final decision context..."
569
+ ></textarea>
570
+ </label>
571
+
572
+ <div class="flex flex-wrap gap-3">
573
+ <button
574
+ type="button"
575
+ class="rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-semibold text-(--rt-text-secondary) hover:bg-(--rt-raised-background)"
576
+ [disabled]="facade.saving()"
577
+ (click)="startReview()"
578
+ >
579
+ Start Review
580
+ </button>
581
+
582
+ <button
583
+ type="button"
584
+ class="rounded-xl border border-amber-300 bg-amber-50 px-4 py-2 text-sm font-semibold text-amber-800 hover:bg-amber-100"
585
+ [disabled]="facade.saving()"
586
+ (click)="needMoreInfo()"
587
+ >
588
+ Need More Info
589
+ </button>
590
+
591
+ <button
592
+ type="button"
593
+ class="rounded-xl border border-emerald-300 bg-emerald-50 px-4 py-2 text-sm font-semibold text-emerald-800 hover:bg-emerald-100"
594
+ [disabled]="facade.saving()"
595
+ (click)="approve()"
596
+ >
597
+ Approve
598
+ </button>
599
+
600
+ <button
601
+ type="button"
602
+ class="rounded-xl border border-rose-300 bg-rose-50 px-4 py-2 text-sm font-semibold text-rose-800 hover:bg-rose-100"
603
+ [disabled]="facade.saving()"
604
+ (click)="fail()"
605
+ >
606
+ Fail
607
+ </button>
608
+ </div>
609
+ </section>
610
+
611
+ <section class="space-y-4">
612
+ <div class="space-y-1">
613
+ <h2 class="text-lg font-semibold text-(--rt-text-primary)">Applicant Profile</h2>
614
+ <p class="text-sm text-(--rt-text-secondary)">Check identity, contact, and company information.</p>
615
+ </div>
616
+
617
+ <div class="grid gap-4 lg:grid-cols-2">
618
+ @for (item of profileItems(); track item.key) {
619
+ <rolatech-onboarding-review-row
620
+ [label]="item.label"
621
+ [value]="item.value"
622
+ [helper]="item.helper"
623
+ [issueOptions]="fieldIssueOptions(item.key)"
624
+ [existingIssue]="fieldExistingIssue(item.key)"
625
+ [draftIssue]="facade.fieldDraft(item.key)"
626
+ [passed]="facade.fieldPassed(item.key)"
627
+ [busy]="facade.saving()"
628
+ (passedChange)="onFieldPassed(item.key, $event)"
629
+ (draftIssueChange)="onFieldIssue(item.key, $event)"
630
+ />
631
+ }
632
+ </div>
633
+ </section>
634
+
635
+ <section class="space-y-4">
636
+ <div class="space-y-1">
637
+ <h2 class="text-lg font-semibold text-(--rt-text-primary)">Compliance and Banking</h2>
638
+ <p class="text-sm text-(--rt-text-secondary)">Check VAT setup and settlement account details.</p>
639
+ </div>
640
+
641
+ <div class="grid gap-4 lg:grid-cols-2">
642
+ @for (item of complianceItems(); track item.key) {
643
+ <rolatech-onboarding-review-row
644
+ [label]="item.label"
645
+ [value]="item.value"
646
+ [helper]="item.helper"
647
+ [issueOptions]="fieldIssueOptions(item.key)"
648
+ [existingIssue]="fieldExistingIssue(item.key)"
649
+ [draftIssue]="facade.fieldDraft(item.key)"
650
+ [passed]="facade.fieldPassed(item.key)"
651
+ [busy]="facade.saving()"
652
+ (passedChange)="onFieldPassed(item.key, $event)"
653
+ (draftIssueChange)="onFieldIssue(item.key, $event)"
654
+ />
655
+ }
656
+ </div>
657
+ </section>
658
+
659
+ <section class="space-y-4">
660
+ <div class="space-y-1">
661
+ <h2 class="text-lg font-semibold text-(--rt-text-primary)">Documents</h2>
662
+ <p class="text-sm text-(--rt-text-secondary)">Review required documents and flag anything missing or unreadable.</p>
663
+ </div>
664
+
665
+ <div class="grid gap-4 lg:grid-cols-2">
666
+ @for (item of documentItems(); track item.documentType + item.label) {
667
+ <rolatech-onboarding-review-row
668
+ [label]="item.label"
669
+ [value]="item.value"
670
+ [helper]="item.helper"
671
+ [issueOptions]="documentIssueOptions(item.documentType)"
672
+ [existingIssue]="documentExistingIssue(item.documentType)"
673
+ [draftIssue]="facade.documentDraft(item.documentType)"
674
+ [passed]="facade.documentPassed(item.documentType)"
675
+ [busy]="facade.saving()"
676
+ [actionLabel]="item.document ? 'Preview' : null"
677
+ [actionDisabled]="!item.document"
678
+ (passedChange)="onDocumentPassed(item.documentType, $event)"
679
+ (draftIssueChange)="onDocumentIssue(item.documentType, $event)"
680
+ (actionTriggered)="openDocumentPreview(item)"
681
+ />
682
+ }
683
+ </div>
684
+ </section>
685
+
686
+ <rolatech-onboarding-issue-list [issues]="detail.issues" />
687
+ </div>
688
+ } @else {
689
+ <div class="rounded-2xl border border-(--rt-border-color) bg-(--rt-base-background) p-5 text-sm text-(--rt-text-secondary) shadow-sm">
690
+ Loading application details...
691
+ </div>
692
+ }
693
+
694
+ @if (facade.detail(); as detail) {
695
+ <rolatech-onboarding-timeline-drawer
696
+ floating
697
+ [open]="timelineOpen()"
698
+ [title]="'Application Timeline'"
699
+ [items]="detail.timeline"
700
+ [zIndex]="9100"
701
+ (closeRequested)="closeTimeline()"
702
+ />
703
+ }
704
+
705
+ <rolatech-onboarding-document-preview-dialog
706
+ [open]="previewOpen()"
707
+ [title]="previewTitle()"
708
+ [subtitle]="previewSubtitle()"
709
+ [url]="facade.previewUrl()"
710
+ [loading]="facade.previewLoading()"
711
+ [error]="facade.previewError()"
712
+ (closeRequested)="closeDocumentPreview()"
713
+ />
714
+ </section>
715
+ `,
716
+ }]
717
+ }], ctorParameters: () => [] });
718
+
719
+ export { AdminOnboardingDetailPage };
720
+ //# sourceMappingURL=rolatech-angular-onboarding-admin-onboarding-detail-page-DREEMvoT.mjs.map