@edvak99/voice-receptionist-widget 1.1.21 → 1.1.23

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 (63) hide show
  1. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-D16UQWsH.mjs +539 -0
  2. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-D16UQWsH.mjs.map +1 -0
  3. package/fesm2022/{edvak99-voice-receptionist-widget-analytics-page.component-CmImX5FN.mjs → edvak99-voice-receptionist-widget-analytics-page.component-DEXdD1mB.mjs} +2 -2
  4. package/fesm2022/{edvak99-voice-receptionist-widget-analytics-page.component-CmImX5FN.mjs.map → edvak99-voice-receptionist-widget-analytics-page.component-DEXdD1mB.mjs.map} +1 -1
  5. package/fesm2022/edvak99-voice-receptionist-widget-audit-page.component-D-uAGYwd.mjs +89 -0
  6. package/fesm2022/edvak99-voice-receptionist-widget-audit-page.component-D-uAGYwd.mjs.map +1 -0
  7. package/fesm2022/{edvak99-voice-receptionist-widget-call-history-detail-page.component-BT4clUO-.mjs → edvak99-voice-receptionist-widget-call-history-detail-page.component-D3GAw7pk.mjs} +45 -15
  8. package/fesm2022/edvak99-voice-receptionist-widget-call-history-detail-page.component-D3GAw7pk.mjs.map +1 -0
  9. package/fesm2022/edvak99-voice-receptionist-widget-call-history-page.component-krL6GnMf.mjs +254 -0
  10. package/fesm2022/edvak99-voice-receptionist-widget-call-history-page.component-krL6GnMf.mjs.map +1 -0
  11. package/fesm2022/{edvak99-voice-receptionist-widget-call-recording-player.component-4fL-zUWy.mjs → edvak99-voice-receptionist-widget-call-recording-player.component-C-iLpJhH.mjs} +2 -2
  12. package/fesm2022/{edvak99-voice-receptionist-widget-call-recording-player.component-4fL-zUWy.mjs.map → edvak99-voice-receptionist-widget-call-recording-player.component-C-iLpJhH.mjs.map} +1 -1
  13. package/fesm2022/{edvak99-voice-receptionist-widget-call-review.service-BhbCmB1S.mjs → edvak99-voice-receptionist-widget-call-review.service-DmvSPr-I.mjs} +2 -2
  14. package/fesm2022/{edvak99-voice-receptionist-widget-call-review.service-BhbCmB1S.mjs.map → edvak99-voice-receptionist-widget-call-review.service-DmvSPr-I.mjs.map} +1 -1
  15. package/fesm2022/edvak99-voice-receptionist-widget-dashboard-page.component-CcphzJ4N.mjs +311 -0
  16. package/fesm2022/edvak99-voice-receptionist-widget-dashboard-page.component-CcphzJ4N.mjs.map +1 -0
  17. package/fesm2022/{edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-DDS7VdnD.mjs → edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CGbyYMbi.mjs} +54 -25
  18. package/fesm2022/edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CGbyYMbi.mjs.map +1 -0
  19. package/fesm2022/{edvak99-voice-receptionist-widget-live-calls-page.component-4LtgT4lS.mjs → edvak99-voice-receptionist-widget-live-calls-page.component-gTy7IynR.mjs} +4 -4
  20. package/fesm2022/edvak99-voice-receptionist-widget-live-calls-page.component-gTy7IynR.mjs.map +1 -0
  21. package/fesm2022/{edvak99-voice-receptionist-widget-live-monitor-page.component-B1lKfw-j.mjs → edvak99-voice-receptionist-widget-live-monitor-page.component-C-sDCE3S.mjs} +10 -7
  22. package/fesm2022/edvak99-voice-receptionist-widget-live-monitor-page.component-C-sDCE3S.mjs.map +1 -0
  23. package/fesm2022/edvak99-voice-receptionist-widget-outbound-purposes-page.component-87FxvbsK.mjs +273 -0
  24. package/fesm2022/edvak99-voice-receptionist-widget-outbound-purposes-page.component-87FxvbsK.mjs.map +1 -0
  25. package/fesm2022/{edvak99-voice-receptionist-widget-task-detail-drawer.component-aDTKTV79.mjs → edvak99-voice-receptionist-widget-task-detail-drawer.component-BNbjcoA2.mjs} +14 -6
  26. package/fesm2022/edvak99-voice-receptionist-widget-task-detail-drawer.component-BNbjcoA2.mjs.map +1 -0
  27. package/fesm2022/{edvak99-voice-receptionist-widget-tasks-page.component-Dj1nWx6V.mjs → edvak99-voice-receptionist-widget-tasks-page.component-OP77Shm4.mjs} +11 -7
  28. package/fesm2022/edvak99-voice-receptionist-widget-tasks-page.component-OP77Shm4.mjs.map +1 -0
  29. package/fesm2022/{edvak99-voice-receptionist-widget-wizard-page.component-CQttbEzW.mjs → edvak99-voice-receptionist-widget-wizard-page.component-CefGWtVL.mjs} +2 -2
  30. package/fesm2022/{edvak99-voice-receptionist-widget-wizard-page.component-CQttbEzW.mjs.map → edvak99-voice-receptionist-widget-wizard-page.component-CefGWtVL.mjs.map} +1 -1
  31. package/fesm2022/edvak99-voice-receptionist-widget.mjs +1 -1
  32. package/lib/components/call-tasks-panel/call-tasks-panel.component.d.ts +7 -3
  33. package/lib/components/patient-profile-drawer/patient-profile-drawer.component.d.ts +3 -0
  34. package/lib/components/task-detail-drawer/task-detail-drawer.component.d.ts +3 -0
  35. package/lib/pages/activities-page/activities-page.component.d.ts +6 -2
  36. package/lib/pages/audit-page/audit-page.component.d.ts +2 -1
  37. package/lib/pages/call-history-detail-page/call-history-detail-page.component.d.ts +2 -0
  38. package/lib/pages/call-history-page/call-history-page.component.d.ts +1 -0
  39. package/lib/pages/dashboard-page/dashboard-page.component.d.ts +4 -0
  40. package/lib/pages/live-monitor-page/live-monitor-page.component.d.ts +2 -0
  41. package/lib/pages/outbound-purposes-page/outbound-purposes-page.component.d.ts +3 -0
  42. package/lib/pages/settings-page/settings-page.component.d.ts +1 -0
  43. package/lib/pages/tasks-page/tasks-page.component.d.ts +2 -0
  44. package/lib/services/ai-receptionist-api.service.d.ts +1 -0
  45. package/package.json +1 -1
  46. package/src/assets/css/_tables.scss +12 -0
  47. package/styles/embed.scss +65 -0
  48. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-CpXa1J9-.mjs +0 -510
  49. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-CpXa1J9-.mjs.map +0 -1
  50. package/fesm2022/edvak99-voice-receptionist-widget-audit-page.component-DTAB2WTX.mjs +0 -78
  51. package/fesm2022/edvak99-voice-receptionist-widget-audit-page.component-DTAB2WTX.mjs.map +0 -1
  52. package/fesm2022/edvak99-voice-receptionist-widget-call-history-detail-page.component-BT4clUO-.mjs.map +0 -1
  53. package/fesm2022/edvak99-voice-receptionist-widget-call-history-page.component-BACON4uq.mjs +0 -247
  54. package/fesm2022/edvak99-voice-receptionist-widget-call-history-page.component-BACON4uq.mjs.map +0 -1
  55. package/fesm2022/edvak99-voice-receptionist-widget-dashboard-page.component-CxNYLBbg.mjs +0 -291
  56. package/fesm2022/edvak99-voice-receptionist-widget-dashboard-page.component-CxNYLBbg.mjs.map +0 -1
  57. package/fesm2022/edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-DDS7VdnD.mjs.map +0 -1
  58. package/fesm2022/edvak99-voice-receptionist-widget-live-calls-page.component-4LtgT4lS.mjs.map +0 -1
  59. package/fesm2022/edvak99-voice-receptionist-widget-live-monitor-page.component-B1lKfw-j.mjs.map +0 -1
  60. package/fesm2022/edvak99-voice-receptionist-widget-outbound-purposes-page.component-BkIHblSu.mjs +0 -269
  61. package/fesm2022/edvak99-voice-receptionist-widget-outbound-purposes-page.component-BkIHblSu.mjs.map +0 -1
  62. package/fesm2022/edvak99-voice-receptionist-widget-task-detail-drawer.component-aDTKTV79.mjs.map +0 -1
  63. package/fesm2022/edvak99-voice-receptionist-widget-tasks-page.component-Dj1nWx6V.mjs.map +0 -1
@@ -0,0 +1,311 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, computed, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { Router, ActivatedRoute } from '@angular/router';
4
+ import { DatePipe } from '@angular/common';
5
+ import { A as AiReceptionistApiService, L as LiveCallsListService, a as AgentOnlineService, T as ToastService, h as historyResolution, t as triggerBlobDownload, i as isUnknownCaller, c as callerMetaLine, b as ageFromDob, d as historyResultChips, r as resultChipIcon, e as historyResolutionLabel, E as EdAvatarComponent, f as EdButtonComponent, I as IconComponent, g as EdSkeletonComponent } from './edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CGbyYMbi.mjs';
6
+ import { s as sentimentIconSrc, a as sentimentLabel, E as EdsElapsedPipe } from './edvak99-voice-receptionist-widget-eds-elapsed.pipe-Dra7e7xN.mjs';
7
+ import { i as isNeedsReview } from './edvak99-voice-receptionist-widget-call-review.util-rWIPxDtQ.mjs';
8
+ import { S as SmartTooltipDirective } from './edvak99-voice-receptionist-widget-smart-tooltip.directive-ChEdIem3.mjs';
9
+ import { T as TABLE_SKELETON_ROWS } from './edvak99-voice-receptionist-widget-table-skeleton.constants-C1Dg9Z_2.mjs';
10
+ import { E as EdsPulseDotComponent } from './edvak99-voice-receptionist-widget-eds-pulse-dot.component-B8yxY-7p.mjs';
11
+
12
+ class DashboardPageComponent {
13
+ constructor() {
14
+ this.api = inject(AiReceptionistApiService);
15
+ this.liveCallsList = inject(LiveCallsListService);
16
+ this.agentOnline = inject(AgentOnlineService);
17
+ this.router = inject(Router);
18
+ this.route = inject(ActivatedRoute);
19
+ this.toast = inject(ToastService);
20
+ this.data = signal(null);
21
+ this.loading = signal(true);
22
+ this.kpiSkeletonRows = [0, 1, 2, 3];
23
+ this.listSkeletonRows = [0, 1, 2];
24
+ this.skeletonRows = TABLE_SKELETON_ROWS;
25
+ this.liveCalls = this.liveCallsList.calls;
26
+ this.liveCallsLoading = this.liveCallsList.loading;
27
+ this.liveCallsError = this.liveCallsList.error;
28
+ this.agentOffline = computed(() => this.agentOnline.online() === false);
29
+ this.kpiCards = computed(() => {
30
+ const stats = this.data()?.stats;
31
+ if (!stats)
32
+ return [];
33
+ const calls = stats.answeredToday;
34
+ const resolvedCount = Math.round((stats.completionRate / 100) * Math.max(calls, 1));
35
+ return [
36
+ {
37
+ id: 'calls',
38
+ label: 'Calls handled',
39
+ value: String(calls),
40
+ meta: 'Today',
41
+ link: '../history',
42
+ },
43
+ {
44
+ id: 'appointments',
45
+ label: 'Appointments booked',
46
+ value: String(stats.appointmentsBooked),
47
+ meta: 'Created by AI',
48
+ link: '../activities',
49
+ queryParams: { tab: 'appointments' },
50
+ },
51
+ {
52
+ id: 'tasks',
53
+ label: 'Tasks created',
54
+ value: String(stats.tasksCreated),
55
+ meta: 'Created by AI',
56
+ link: '../activities',
57
+ },
58
+ {
59
+ id: 'resolved',
60
+ label: 'Resolved without staff',
61
+ value: `${stats.completionRate}%`,
62
+ meta: calls > 0 ? `${resolvedCount} of ${calls} calls` : 'AI handled',
63
+ link: '../history',
64
+ },
65
+ ];
66
+ });
67
+ this.liveCallRows = computed(() => this.liveCalls().map((call) => this.toLiveCallRow(call)));
68
+ this.liveCallCount = computed(() => this.liveCallRows().length);
69
+ this.attentionRows = computed(() => {
70
+ const fromLive = this.liveCalls()
71
+ .filter((c) => this.isAssistanceStatus(c.status) || c.sentiment === 'frustrated' || c.sentiment === 'urgent')
72
+ .map((c) => this.toAttentionFromLive(c));
73
+ const fromHistory = (this.data()?.recentHistory ?? [])
74
+ .filter((row) => historyResolution({
75
+ outcome: row.outcome,
76
+ resolution: row.resolution,
77
+ risk: row.risk,
78
+ }) === 'needs_attention')
79
+ .map((row) => this.toAttentionFromHistory(row));
80
+ const seen = new Set();
81
+ const merged = [];
82
+ for (const item of [...fromLive, ...fromHistory]) {
83
+ if (seen.has(item.callId))
84
+ continue;
85
+ seen.add(item.callId);
86
+ merged.push(item);
87
+ if (merged.length >= 6)
88
+ break;
89
+ }
90
+ return merged;
91
+ });
92
+ this.attentionCount = computed(() => this.attentionRows().length);
93
+ this.recentHistoryRows = computed(() => (this.data()?.recentHistory ?? []).map((row) => this.toRecentHistoryRow(row)));
94
+ this.recentHistoryCount = computed(() => this.recentHistoryRows().length);
95
+ }
96
+ ngOnInit() {
97
+ this.liveCallsList.start();
98
+ this.api.getDashboard().subscribe(({ data }) => {
99
+ this.data.set(data);
100
+ this.loading.set(false);
101
+ });
102
+ }
103
+ ngOnDestroy() {
104
+ this.liveCallsList.stop();
105
+ }
106
+ exportCsv() {
107
+ this.api.exportHistoryCsv().subscribe({
108
+ next: ({ blob, filename }) => {
109
+ triggerBlobDownload(blob, filename);
110
+ this.toast.show('Export downloaded', 'success');
111
+ },
112
+ error: (err) => {
113
+ this.toast.show(err.message ?? 'Failed to export CSV', 'error');
114
+ },
115
+ });
116
+ }
117
+ openKpi(tile) {
118
+ if (!tile.link)
119
+ return;
120
+ void this.router.navigate([tile.link], {
121
+ relativeTo: this.route,
122
+ queryParams: tile.queryParams ?? undefined,
123
+ });
124
+ }
125
+ goTo(path) {
126
+ void this.router.navigate([path], { relativeTo: this.route });
127
+ }
128
+ openHistoryDetail(id) {
129
+ void this.router.navigate(['../history', id], { relativeTo: this.route });
130
+ }
131
+ openLiveCall(id) {
132
+ void this.router.navigate(['../live', id], { relativeTo: this.route });
133
+ }
134
+ openAttention(item) {
135
+ const live = this.liveCalls().some((c) => c.id === item.callId);
136
+ void this.router.navigate(live ? ['../live', item.callId] : ['../history', item.callId], {
137
+ relativeTo: this.route,
138
+ });
139
+ }
140
+ toLiveCallRow(call) {
141
+ const unknown = isUnknownCaller(call.name, call.matched);
142
+ const needsAssistance = this.isAssistanceStatus(call.status);
143
+ const staffHandling = call.status === 'takeover' || call.controlMode === 'takeover';
144
+ const lastTool = call.tools[call.tools.length - 1];
145
+ return {
146
+ id: call.id,
147
+ name: unknown ? 'Unknown Caller' : call.name.trim() || 'Unknown Caller',
148
+ initials: unknown ? '?' : call.initials || '?',
149
+ avatarTone: unknown ? 'gray' : 'warm',
150
+ metaLine: callerMetaLine({
151
+ name: call.name,
152
+ matched: call.matched,
153
+ phone: call.phone,
154
+ dob: call.dob,
155
+ age: call.age ?? ageFromDob(call.dob),
156
+ gender: call.gender,
157
+ }),
158
+ sentiment: call.sentiment,
159
+ sentimentLabel: sentimentLabel(call.sentiment),
160
+ sentimentIconSrc: sentimentIconSrc(call.sentiment),
161
+ direction: call.direction,
162
+ directionIcon: call.direction === 'inbound' ? 'call_received' : 'call_made',
163
+ directionTitle: call.direction === 'inbound' ? 'Incoming call' : 'Outgoing call',
164
+ goal: call.reason || call.goal || '—',
165
+ statusSubtitle: lastTool?.result || call.goal || 'In progress…',
166
+ handlingLabel: needsAssistance
167
+ ? 'NEED ASSISTANCE'
168
+ : staffHandling
169
+ ? 'STAFF HANDLING'
170
+ : 'AI HANDLING',
171
+ handlingVariant: needsAssistance ? 'danger' : staffHandling ? 'success' : 'opened',
172
+ needsAssistance,
173
+ started: call.started,
174
+ };
175
+ }
176
+ toAttentionFromLive(call) {
177
+ const unknown = isUnknownCaller(call.name, call.matched);
178
+ return {
179
+ id: `live-${call.id}`,
180
+ callId: call.id,
181
+ name: unknown ? 'Unknown Caller' : call.name.trim() || 'Unknown Caller',
182
+ initials: unknown ? '?' : call.initials || '?',
183
+ avatarTone: unknown ? 'gray' : 'violet',
184
+ metaLine: callerMetaLine({
185
+ name: call.name,
186
+ matched: call.matched,
187
+ phone: call.phone,
188
+ dob: call.dob,
189
+ age: call.age ?? ageFromDob(call.dob),
190
+ gender: call.gender,
191
+ }),
192
+ badge: this.attentionBadgeFromLive(call),
193
+ detail: call.goal || call.reason || 'Needs staff follow-up.',
194
+ timeLabel: 'Just now',
195
+ direction: call.direction,
196
+ directionIcon: call.direction === 'inbound' ? 'call_received' : 'call_made',
197
+ directionTitle: call.direction === 'inbound' ? 'Incoming call' : 'Outgoing call',
198
+ };
199
+ }
200
+ toAttentionFromHistory(row) {
201
+ const unknown = isUnknownCaller(row.name);
202
+ const inbound = row.direction === 'inbound';
203
+ return {
204
+ id: `hist-${row.id}`,
205
+ callId: row.id,
206
+ name: unknown ? 'Unknown Caller' : row.name.trim() || 'Unknown Caller',
207
+ initials: unknown || !row.initials ? '?' : row.initials,
208
+ avatarTone: unknown || row.initials === '?' ? 'gray' : 'violet',
209
+ metaLine: callerMetaLine({
210
+ dob: row.dob,
211
+ age: row.age,
212
+ gender: row.gender,
213
+ phone: row.phone,
214
+ name: row.name,
215
+ }),
216
+ badge: this.attentionBadgeFromHistory(row),
217
+ detail: row.reason || row.outcome || 'Needs review.',
218
+ timeLabel: row.whenLabel || 'Recently',
219
+ direction: row.direction,
220
+ directionIcon: inbound ? 'call_received' : 'call_made',
221
+ directionTitle: inbound ? 'Incoming call' : 'Outgoing call',
222
+ };
223
+ }
224
+ toRecentHistoryRow(row) {
225
+ const unknown = isUnknownCaller(row.name);
226
+ const resolution = historyResolution({
227
+ outcome: row.outcome,
228
+ resolution: row.resolution,
229
+ risk: row.risk,
230
+ });
231
+ const handledByStaff = row.handledBy === 'staff';
232
+ const inbound = row.direction === 'inbound';
233
+ const chips = historyResultChips(row.results, row.outcome);
234
+ return {
235
+ id: row.id,
236
+ name: row.name || 'Unknown Caller',
237
+ initials: row.initials || '?',
238
+ avatarTone: unknown || row.initials === '?' ? 'gray' : 'brand',
239
+ metaLine: callerMetaLine({
240
+ dob: row.dob,
241
+ age: row.age,
242
+ gender: row.gender,
243
+ phone: row.phone,
244
+ name: row.name,
245
+ }),
246
+ direction: row.direction,
247
+ directionIcon: inbound ? 'call_received' : 'call_made',
248
+ directionTitle: inbound ? 'Incoming call' : 'Outgoing call',
249
+ reason: row.reason || '—',
250
+ handledByLabel: handledByStaff ? 'STAFF' : 'AI',
251
+ handledByVariant: handledByStaff ? 'primary' : 'opened',
252
+ resolution,
253
+ resolutionLabel: historyResolutionLabel(resolution),
254
+ resolutionVariant: resolution === 'resolved' ? 'success' : 'warning',
255
+ resultChips: chips.map((label) => ({ label, icon: resultChipIcon(label) })),
256
+ durationLabel: row.durationLabel ?? this.formatDuration(row.duration),
257
+ started: row.started || null,
258
+ whenLabel: row.whenLabel || '—',
259
+ needsReview: isNeedsReview(row.review),
260
+ reviewed: row.review === 'reviewed',
261
+ };
262
+ }
263
+ isAssistanceStatus(status) {
264
+ return status === 'needs-help' || status === 'human-requested' || status === 'urgent';
265
+ }
266
+ attentionBadgeFromLive(call) {
267
+ if (call.status === 'urgent')
268
+ return 'SAFETY ESCALATION';
269
+ if (call.status === 'human-requested')
270
+ return 'HUMAN REQUESTED';
271
+ if (call.verification === 'failed' || call.verification === 'unknown')
272
+ return 'IDENTITY UNRESOLVED';
273
+ if (call.status === 'needs-help')
274
+ return 'NEED ASSISTANCE';
275
+ return 'NEEDS REVIEW';
276
+ }
277
+ attentionBadgeFromHistory(row) {
278
+ const o = (row.outcome || row.reason || '').toLowerCase();
279
+ if (o.includes('book') || o.includes('appoint'))
280
+ return 'BOOKING FAILURE';
281
+ if (o.includes('ident') || row.verification === 'failed' || row.verification === 'unknown') {
282
+ return 'IDENTITY UNRESOLVED';
283
+ }
284
+ if (row.risk === 'urgent')
285
+ return 'SAFETY ESCALATION';
286
+ return 'NEEDS REVIEW';
287
+ }
288
+ formatDuration(sec) {
289
+ const m = Math.floor(sec / 60);
290
+ const s = sec % 60;
291
+ return `${m}:${s.toString().padStart(2, '0')}`;
292
+ }
293
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: DashboardPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
294
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: DashboardPageComponent, isStandalone: true, selector: "eds-dashboard-page", host: { classAttribute: "block h-full min-h-0" }, ngImport: i0, template: "<div class=\"flex h-full flex-col overflow-auto bg-lighter p-base dashboard-page\">\n <header class=\"mb-base flex shrink-0 items-start justify-between gap-base\">\n <div class=\"flex flex-col gap-2xs\">\n <h3>Dashboard</h3>\n <p class=\"fs-sm text-light\">Monitor AI receptionist activity and follow up where needed</p>\n </div>\n <ed-button\n class=\"shrink-0\"\n variant=\"default\"\n size=\"sm\"\n (click$)=\"exportCsv()\">\n <ed-icon slot=\"prefix\" name=\"download\" [size]=\"16\" />\n Export CSV\n </ed-button>\n </header>\n\n <div class=\"flex flex-1 flex-col gap-base \">\n @if (loading()) {\n <section class=\"grid grid-cols-1 gap-base sm:grid-cols-2 xl:grid-cols-4\" aria-label=\"Overview KPIs\" aria-busy=\"true\">\n @for (_ of kpiSkeletonRows; track _) {\n <article class=\"flex flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-base\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-6 w-14\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n </article>\n }\n </section>\n\n <section\n class=\"grid grid-cols-1 items-stretch gap-base xl:grid-cols-2\"\n aria-label=\"Live calls and needs attention\"\n aria-busy=\"true\"\n >\n <article class=\"flex h-full min-h-64 flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex shrink-0 items-center justify-between gap-sm\">\n <div class=\"flex items-center gap-sm\">\n <h4>Live Calls</h4>\n <ed-skeleton class=\"h-5 w-16 !rounded-full\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n </header>\n <ul class=\"m-0 grid max-h-64 list-none content-start gap-xs overflow-x-hidden overflow-y-auto p-0\">\n @for (_ of listSkeletonRows; track _) {\n <li>\n <div class=\"flex w-full items-center gap-base rounded-md border border-light bg-white p-sm\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs xl:max-w-xs\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 flex-1 gap-2xs\">\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n </div>\n </div>\n <div class=\"hidden min-w-0 flex-1 items-center gap-xs xl:flex\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 gap-2xs\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n </div>\n </div>\n <div class=\"grid shrink-0 justify-items-end gap-2xs self-stretch\">\n <ed-skeleton class=\"h-5 w-24 !rounded-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-12\"></ed-skeleton>\n </div>\n </div>\n </li>\n }\n </ul>\n </article>\n\n <article class=\"flex h-full min-h-64 flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex shrink-0 items-center justify-between gap-sm\">\n <div class=\"flex items-center gap-sm\">\n <h4>Needs Attention</h4>\n <ed-skeleton class=\"h-5 w-8 !rounded-full\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n </header>\n <ul class=\"m-0 grid max-h-64 list-none content-start gap-xs overflow-x-hidden overflow-y-auto p-0\">\n @for (_ of listSkeletonRows; track _) {\n <li>\n <div class=\"flex w-full flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-sm\">\n <div class=\"flex w-full min-w-0 items-center gap-xs\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"flex min-w-0 flex-1 flex-col gap-2xs\">\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-36\"></ed-skeleton>\n </div>\n </div>\n <ed-skeleton class=\"h-5 w-28 shrink-0 !rounded-full\"></ed-skeleton>\n </div>\n <div class=\"flex w-full min-w-0 items-center gap-sm\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs\">\n <ed-skeleton class=\"h-8 w-8 shrink-0 !rounded-md\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-full max-w-xs\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-3 w-14 shrink-0\"></ed-skeleton>\n </div>\n </div>\n </li>\n }\n </ul>\n </article>\n </section>\n\n <article class=\"flex flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\" aria-busy=\"true\">\n <header class=\"flex items-center justify-between gap-xs\">\n <div class=\"flex items-center gap-sm\">\n <h4>Recent Calls</h4>\n <ed-skeleton class=\"h-5 w-8 !rounded-full\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n </header>\n <div class=\"overflow-x-auto bg-white rounded-md\">\n <table class=\"table-default eds-centered-table relative min-w-5xl w-full\" aria-label=\"Recent calls\">\n <thead>\n <tr>\n <th>Time</th>\n <th>Patient / Caller</th>\n <th class=\"w-16 text-center\" aria-label=\"Direction\">\n <span class=\"inline-flex items-center justify-center gap-2xs\">\n <ed-icon name=\"call_received\" [size]=\"12\" class=\"text-success\" color=\"currentColor\" />\n <span class=\"text-light\">/</span>\n <ed-icon name=\"call_made\" [size]=\"12\" class=\"text-primary\" color=\"currentColor\" />\n </span>\n </th>\n <th>Goal</th>\n <th>Review</th>\n <th>Resolution</th>\n <th>Result</th>\n <th>Duration</th>\n </tr>\n </thead>\n <tbody>\n @for (_ of skeletonRows; track _) {\n <tr>\n <td>\n <div class=\"grid gap-2xs py-2xs\">\n <ed-skeleton class=\"h-3 w-12\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-20\"></ed-skeleton>\n </div>\n </td>\n <td>\n <div class=\"flex items-center gap-xs py-2xs\">\n <ed-skeleton class=\"h-8 w-8 !rounded-md\"></ed-skeleton>\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-36\"></ed-skeleton>\n </div>\n </div>\n </td>\n <td class=\"text-center\">\n <div class=\"flex justify-center py-2xs\">\n <ed-skeleton class=\"h-5 w-5 !rounded\"></ed-skeleton>\n </div>\n </td>\n <td><ed-skeleton class=\"h-3 w-32\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-5 w-12 !rounded-full\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-5 w-28 !rounded\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-10\"></ed-skeleton></td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </article>\n } @else if (data()) {\n <section class=\"grid grid-cols-1 gap-base sm:grid-cols-2 xl:grid-cols-4\" aria-label=\"Overview KPIs\">\n @for (tile of kpiCards(); track tile.id) {\n @if (tile.link) {\n <button\n type=\"button\"\n class=\"flex flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-base text-left text-inherit transition-colors hover:bg-primary-100 hover:shadow-sm\"\n (click)=\"openKpi(tile)\">\n <span class=\"fs-xs font-semibold uppercase tracking-wide text-light\">{{ tile.label }}</span>\n <h3>{{ tile.value }}</h3>\n <span class=\"fs-xs text-light\">{{ tile.meta }}</span>\n </button>\n } @else {\n <article class=\"flex flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-base\">\n <span class=\"fs-xs font-semibold uppercase tracking-wide text-light\">{{ tile.label }}</span>\n <h3>{{ tile.value }}</h3>\n <span class=\"fs-sm text-light\">{{ tile.meta }}</span>\n </article>\n }\n }\n </section>\n\n <section\n class=\"grid grid-cols-1 items-stretch gap-base xl:grid-cols-2\"\n aria-label=\"Live calls and needs attention\">\n <article class=\"flex h-full min-h-64 flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex shrink-0 items-center justify-between gap-sm\">\n <div class=\"flex items-center gap-sm\">\n <h4>Live Calls</h4>\n @if (agentOffline()) {\n <span class=\"inline-flex items-center gap-2xs fs-sm font-semibold text-danger\">\n <ed-icon name=\"phone_disabled\" [size]=\"18\" />\n Offline\n </span>\n } @else {\n <ed-badge-2 variant=\"success\" pill uppercase>\n {{ liveCallCount() }} LIVE\n </ed-badge-2>\n }\n </div>\n <button type=\"button\" class=\"eds-plain-nav fs-sm font-medium text-primary\" (click)=\"goTo('../live')\">\n View All\n <ed-icon name=\"chevron_right\" [size]=\"16\" color=\"currentColor\" />\n </button>\n </header>\n\n <ul class=\"m-0 grid max-h-64 list-none content-start gap-xs overflow-x-hidden overflow-y-auto p-0\">\n @if (liveCallsError()) {\n <li class=\"fs-sm text-light\" role=\"alert\">{{ liveCallsError() }}</li>\n }\n @if (liveCallsLoading() && liveCallRows().length === 0) {\n @for (_ of listSkeletonRows; track _) {\n <li>\n <div class=\"flex w-full items-center gap-base rounded-md border border-light bg-white p-sm\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs xl:max-w-xs\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 flex-1 gap-2xs\">\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n </div>\n </div>\n <div class=\"hidden min-w-0 flex-1 items-center gap-xs xl:flex\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 gap-2xs\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n </div>\n </div>\n <div class=\"grid shrink-0 justify-items-end gap-2xs self-stretch\">\n <ed-skeleton class=\"h-5 w-24 !rounded-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-12\"></ed-skeleton>\n </div>\n </div>\n </li>\n }\n }\n @for (call of liveCallRows(); track call.id) {\n <li>\n <button\n type=\"button\"\n class=\"flex w-full cursor-pointer items-center gap-base rounded-md border border-light bg-white p-sm text-left transition-colors hover:bg-lighter hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary\"\n [class.border-danger]=\"call.needsAssistance\"\n [class.bg-danger-50]=\"call.needsAssistance\"\n (click)=\"openLiveCall(call.id)\"\n >\n <div class=\"flex min-w-0 flex-1 items-center gap-xs xl:max-w-xs\">\n <ed-avatar\n shape=\"box\"\n size=\"base\"\n [initials]=\"call.initials\"\n [tone]=\"call.avatarTone\"\n />\n <div class=\"grid min-w-0 flex-1 gap-2xs\">\n <div class=\"flex min-w-0 flex-wrap items-center gap-sm\">\n <span class=\"fs-sm font-semibold text-dark\">{{ call.name }}</span>\n <span class=\"vr-sentiment\" [attr.data-sentiment]=\"call.sentiment\">\n <span class=\"vr-sentiment__icon\" aria-hidden=\"true\">\n <img [src]=\"call.sentimentIconSrc\" alt=\"\" width=\"16\" height=\"16\" />\n </span>\n <span>{{ call.sentimentLabel }}</span>\n </span>\n </div>\n <span class=\"fs-sm whitespace-nowrap text-light\">{{ call.metaLine }}</span>\n </div>\n </div>\n\n <div class=\"hidden min-w-0 flex-1 items-center gap-xs xl:flex\">\n <span\n class=\"inline-flex size-9 shrink-0 items-center justify-center rounded-md\"\n [class.bg-success-50]=\"call.direction === 'inbound'\"\n [class.text-success]=\"call.direction === 'inbound'\"\n [class.bg-primary-50]=\"call.direction === 'outbound'\"\n [class.text-primary]=\"call.direction === 'outbound'\"\n [smartTooltip]=\"call.directionTitle\"\n >\n <ed-icon [name]=\"call.directionIcon\" [size]=\"18\" color=\"currentColor\" />\n </span>\n <div class=\"grid min-w-0 gap-2xs whitespace-nowrap\">\n <span class=\"fs-sm font-medium text-dark\">{{ call.goal }}</span>\n <span class=\"fs-xs text-light\">{{ call.statusSubtitle }}</span>\n </div>\n </div>\n\n <div class=\"grid shrink-0 justify-items-end gap-2xs self-stretch\">\n <ed-badge-2 [attr.variant]=\"call.handlingVariant\" pill uppercase>\n {{ call.handlingLabel }}\n </ed-badge-2>\n <strong\n class=\"inline-flex items-center gap-2xs fs-2xs text-primary\"\n [class.text-danger]=\"call.needsAssistance\"\n [class.text-light]=\"!call.needsAssistance\"\n >\n @if (!call.needsAssistance) {\n <eds-pulse-dot />\n }\n {{ call.started | edsElapsed }}\n </strong>\n </div>\n </button>\n </li>\n } @empty {\n @if (!liveCallsLoading()) {\n <li class=\"fs-sm text-light\">No active calls right now.</li>\n }\n }\n </ul>\n </article>\n\n <article class=\"flex h-full min-h-64 flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex shrink-0 items-center justify-between gap-sm\">\n <div class=\"flex items-center gap-sm\">\n <h4>Needs Attention</h4>\n <ed-badge-2 variant=\"warning\" pill>\n {{ attentionCount() }}\n </ed-badge-2>\n </div>\n <button type=\"button\" class=\"eds-plain-nav fs-sm font-medium text-primary\" (click)=\"goTo('../history')\">\n View All\n <ed-icon name=\"chevron_right\" [size]=\"16\" color=\"currentColor\" />\n </button>\n </header>\n\n <ul class=\"m-0 grid max-h-64 list-none content-start gap-xs overflow-x-hidden overflow-y-auto p-0\">\n @for (item of attentionRows(); track item.id) {\n <li>\n <div\n role=\"button\"\n tabindex=\"0\"\n class=\"flex w-full cursor-pointer flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-sm text-left transition-colors hover:bg-lighter hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary\"\n [attr.aria-label]=\"'Open attention item for ' + item.name\"\n (click)=\"openAttention(item)\"\n (keyup.enter)=\"openAttention(item)\"\n >\n <div class=\"flex w-full min-w-0 items-center gap-xs\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs\">\n <ed-avatar\n shape=\"box\"\n size=\"base\"\n [initials]=\"item.initials\"\n [tone]=\"item.avatarTone\"\n />\n <div class=\"flex min-w-0 flex-1 flex-col gap-2xs\">\n <div class=\"flex min-w-0 items-center gap-2xs\">\n <span class=\"truncate fs-sm font-semibold text-dark\">{{ item.name }}</span>\n <!-- <span class=\"inline-flex shrink-0 text-light\">\n <ed-icon name=\"TagSimple\" [size]=\"14\" color=\"currentColor\" />\n </span> -->\n </div>\n <span class=\"truncate fs-sm text-light\">{{ item.metaLine }}</span>\n </div>\n </div>\n <ed-badge-2 class=\"shrink-0\" variant=\"light\" pill uppercase>\n {{ item.badge }}\n </ed-badge-2>\n </div>\n <div class=\"flex w-full min-w-0 items-center gap-sm\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs\">\n <span\n class=\"inline-flex size-8 shrink-0 items-center justify-center rounded-md\"\n [class.bg-success-50]=\"item.direction === 'inbound'\"\n [class.text-success]=\"item.direction === 'inbound'\"\n [class.bg-primary-50]=\"item.direction === 'outbound'\"\n [class.text-primary]=\"item.direction === 'outbound'\"\n [smartTooltip]=\"item.directionTitle\"\n >\n <ed-icon [name]=\"item.directionIcon\" [size]=\"16\" color=\"currentColor\" />\n </span>\n <span class=\"min-w-0 flex-1 truncate fs-sm text-light\">{{ item.detail }}</span>\n </div>\n <span class=\"shrink-0 whitespace-nowrap fs-xs text-light\">{{ item.timeLabel }}</span>\n </div>\n </div>\n </li>\n } @empty {\n <li class=\"fs-sm text-light\">Nothing needs attention right now.</li>\n }\n </ul>\n </article>\n </section>\n\n <article class=\"flex flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex items-center justify-between gap-xs\">\n <div class=\"flex items-center gap-sm\">\n <h4>Recent Calls</h4>\n <ed-badge-2\n variant=\"light\"\n pill\n [attr.aria-label]=\"'Recent calls count ' + recentHistoryCount()\"\n >\n {{ recentHistoryCount() }}\n </ed-badge-2>\n </div>\n <button type=\"button\" class=\"eds-plain-nav fs-sm font-medium text-primary\" (click)=\"goTo('../history')\">\n View All\n <ed-icon name=\"chevron_right\" [size]=\"16\" color=\"currentColor\" />\n </button>\n </header>\n\n <div class=\"overflow-x-auto bg-white rounded-md\">\n <table class=\"table-default eds-centered-table relative min-w-5xl w-full\" aria-label=\"Recent calls\">\n <thead>\n <tr>\n <th>Time</th>\n <th>Patient / Caller</th>\n <th class=\"w-16 text-center\" aria-label=\"Direction\">\n <span class=\"inline-flex items-center justify-center gap-2xs\">\n <ed-icon name=\"call_received\" [size]=\"12\" class=\"text-success\" color=\"currentColor\" />\n <span class=\"text-light\">/</span>\n <ed-icon name=\"call_made\" [size]=\"12\" class=\"text-primary\" color=\"currentColor\" />\n </span>\n </th>\n <th>Goal</th>\n <th>Review</th>\n <th>Resolution</th>\n <th>Result</th>\n <th>Duration</th>\n </tr>\n </thead>\n <tbody>\n @for (row of recentHistoryRows(); track row.id) {\n <tr\n class=\"focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'View call details for ' + row.name\"\n (click)=\"openHistoryDetail(row.id)\"\n (keyup.enter)=\"openHistoryDetail(row.id)\"\n >\n <td>\n <div class=\"flex flex-col gap-2xs whitespace-nowrap\">\n @if (row.started) {\n <span class=\"fs-xs font-medium text-light\">{{ row.started | date: 'shortTime' }}</span>\n <span class=\"fs-xs text-light\">{{ row.started | date: 'MMM d, y' }}</span>\n } @else {\n <span class=\"fs-xs font-medium text-light\">{{ row.whenLabel }}</span>\n }\n </div>\n </td>\n\n <td>\n <div class=\"eds-caller-cell\">\n <ed-avatar\n shape=\"box\"\n size=\"base\"\n [initials]=\"row.initials\"\n [tone]=\"row.avatarTone\"\n />\n <div class=\"eds-caller-cell__text\">\n <span\n class=\"eds-caller-cell__name fs-sm font-semibold text-dark\"\n [smartTooltip]=\"row.name\"\n >{{ row.name }}</span>\n <span\n class=\"eds-caller-cell__meta fs-xs text-light\"\n [smartTooltip]=\"row.metaLine\"\n >{{ row.metaLine }}</span>\n </div>\n </div>\n </td>\n\n <td class=\"text-center\">\n <span\n class=\"inline-flex size-5 items-center justify-center rounded\"\n [class.bg-success-50]=\"row.direction === 'inbound'\"\n [class.text-success]=\"row.direction === 'inbound'\"\n [class.bg-primary-50]=\"row.direction === 'outbound'\"\n [class.text-primary]=\"row.direction === 'outbound'\"\n [smartTooltip]=\"row.directionTitle\"\n >\n <ed-icon [name]=\"row.directionIcon\" [size]=\"12\" color=\"currentColor\" />\n </span>\n </td>\n\n <td>\n <span\n class=\"inline-block min-w-0 max-w-56 truncate fs-sm font-medium text-light\"\n [smartTooltip]=\"row.reason\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ row.reason }}</span>\n </td>\n\n <td>\n <ed-badge-2 [attr.variant]=\"row.reviewed ? 'success' : 'warning'\" pill uppercase>\n {{ row.reviewed ? 'Reviewed' : 'Needs review' }}\n </ed-badge-2>\n </td>\n\n <td>\n @if (row.resolution) {\n <ed-badge-2 [attr.variant]=\"row.resolutionVariant\" pill uppercase>\n {{ row.resolutionLabel }}\n </ed-badge-2>\n }\n </td>\n\n <td>\n <div class=\"flex min-w-0 max-w-80 flex-wrap gap-2xs\">\n @for (chip of row.resultChips; track chip.label) {\n <span\n class=\"inline-flex h-5 max-w-48 min-w-0 items-center gap-2xs rounded bg-light px-2xs fs-xs font-medium text-dark\"\n >\n <ed-icon [name]=\"chip.icon\" [size]=\"12\" color=\"currentColor\" />\n <span\n class=\"min-w-0 truncate\"\n [smartTooltip]=\"chip.label\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ chip.label }}</span>\n </span>\n } @empty {\n <span class=\"fs-sm text-light\">\u2014</span>\n }\n </div>\n </td>\n\n <td class=\"whitespace-nowrap tabular-nums fs-xs font-medium text-light\">\n {{ row.durationLabel }}\n </td>\n </tr>\n } @empty {\n <tr class=\"table-no-data\">\n <td colspan=\"8\" class=\"py-base text-center fs-sm text-light\">No recent calls.</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </article>\n }\n </div>\n</div>\n", styles: [".vr-sentiment{display:inline-flex;align-items:center;justify-content:center;gap:4px;height:20px;padding:2px 4px;border-radius:6px;font-size:11px;font-weight:500;line-height:16px;white-space:nowrap}.vr-sentiment__icon{display:block;width:16px;height:16px;flex-shrink:0;overflow:hidden}.vr-sentiment__icon img{display:block;width:100%;height:100%;max-width:none}.vr-sentiment[data-sentiment=calm]{background:#3681f41a;color:#2162f0}.vr-sentiment[data-sentiment=neutral]{background:#f0f2f5;color:#41464c}.vr-sentiment[data-sentiment=urgent]{background:#f26b0d1a;color:#e94e0c}.vr-sentiment[data-sentiment=frustrated]{background:#f037401a;color:#db0c15}.eds-caller-cell{display:flex;width:13.5rem;max-width:13.5rem;align-items:center;gap:.5rem;margin-inline:auto;text-align:left}.eds-caller-cell__text{min-width:0;flex:1}.eds-caller-cell__name,.eds-caller-cell__meta{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.eds-plain-nav{display:inline-flex;align-items:center;gap:.25rem;margin:0;padding:0;border:none;background:transparent;cursor:pointer;font:inherit;color:inherit}\n"], dependencies: [{ kind: "pipe", type: DatePipe, name: "date" }, { kind: "component", type: EdAvatarComponent, selector: "ed-avatar", inputs: ["initials", "tone", "shape", "size", "gradient"] }, { kind: "component", type: EdButtonComponent, selector: "ed-button", inputs: ["variant", "size", "disabled", "ghost", "outline", "subtle", "fill", "loading", "block", "elevated", "shape", "type", "href", "routerLink", "rel", "target", "download", "ariaLabel"], outputs: ["click$"] }, { kind: "component", type: IconComponent, selector: "ed-icon", inputs: ["name", "size", "color", "cssClass", "decorative", "ariaHidden", "ariaLabel", "title", "desc", "focusable", "tabIndex"] }, { kind: "component", type: EdsPulseDotComponent, selector: "eds-pulse-dot" }, { kind: "pipe", type: EdsElapsedPipe, name: "edsElapsed" }, { kind: "directive", type: SmartTooltipDirective, selector: "[smartTooltip]", inputs: ["smartTooltip", "tooltipAllowHtml", "tooltipTemplate", "tooltipTemplateContext", "tooltipPlacement", "tooltipTrigger", "tooltipDelayShow", "tooltipDelayHide", "tooltipOffset", "tooltipMaxWidth", "tooltipZIndex", "tooltipClass", "tooltipDisabled", "tooltipArrow", "tooltipHoverIntentMs", "tooltipHoverIntentRadius", "tooltipId", "tooltipRole", "tooltipAnimEnterMs", "tooltipAnimExitMs", "tooltipAnimEasing", "tooltipHoverable", "tooltipHandoffMs", "tooltipOpen", "tooltipOnlyWhenTruncated"] }, { kind: "component", type: EdSkeletonComponent, selector: "ed-skeleton", inputs: ["class"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
295
+ }
296
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: DashboardPageComponent, decorators: [{
297
+ type: Component,
298
+ args: [{ selector: 'eds-dashboard-page', imports: [
299
+ DatePipe,
300
+ EdAvatarComponent,
301
+ EdButtonComponent,
302
+ IconComponent,
303
+ EdsPulseDotComponent,
304
+ EdsElapsedPipe,
305
+ SmartTooltipDirective,
306
+ EdSkeletonComponent,
307
+ ], changeDetection: ChangeDetectionStrategy.OnPush, schemas: [CUSTOM_ELEMENTS_SCHEMA], host: { class: 'block h-full min-h-0' }, template: "<div class=\"flex h-full flex-col overflow-auto bg-lighter p-base dashboard-page\">\n <header class=\"mb-base flex shrink-0 items-start justify-between gap-base\">\n <div class=\"flex flex-col gap-2xs\">\n <h3>Dashboard</h3>\n <p class=\"fs-sm text-light\">Monitor AI receptionist activity and follow up where needed</p>\n </div>\n <ed-button\n class=\"shrink-0\"\n variant=\"default\"\n size=\"sm\"\n (click$)=\"exportCsv()\">\n <ed-icon slot=\"prefix\" name=\"download\" [size]=\"16\" />\n Export CSV\n </ed-button>\n </header>\n\n <div class=\"flex flex-1 flex-col gap-base \">\n @if (loading()) {\n <section class=\"grid grid-cols-1 gap-base sm:grid-cols-2 xl:grid-cols-4\" aria-label=\"Overview KPIs\" aria-busy=\"true\">\n @for (_ of kpiSkeletonRows; track _) {\n <article class=\"flex flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-base\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-6 w-14\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n </article>\n }\n </section>\n\n <section\n class=\"grid grid-cols-1 items-stretch gap-base xl:grid-cols-2\"\n aria-label=\"Live calls and needs attention\"\n aria-busy=\"true\"\n >\n <article class=\"flex h-full min-h-64 flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex shrink-0 items-center justify-between gap-sm\">\n <div class=\"flex items-center gap-sm\">\n <h4>Live Calls</h4>\n <ed-skeleton class=\"h-5 w-16 !rounded-full\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n </header>\n <ul class=\"m-0 grid max-h-64 list-none content-start gap-xs overflow-x-hidden overflow-y-auto p-0\">\n @for (_ of listSkeletonRows; track _) {\n <li>\n <div class=\"flex w-full items-center gap-base rounded-md border border-light bg-white p-sm\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs xl:max-w-xs\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 flex-1 gap-2xs\">\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n </div>\n </div>\n <div class=\"hidden min-w-0 flex-1 items-center gap-xs xl:flex\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 gap-2xs\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n </div>\n </div>\n <div class=\"grid shrink-0 justify-items-end gap-2xs self-stretch\">\n <ed-skeleton class=\"h-5 w-24 !rounded-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-12\"></ed-skeleton>\n </div>\n </div>\n </li>\n }\n </ul>\n </article>\n\n <article class=\"flex h-full min-h-64 flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex shrink-0 items-center justify-between gap-sm\">\n <div class=\"flex items-center gap-sm\">\n <h4>Needs Attention</h4>\n <ed-skeleton class=\"h-5 w-8 !rounded-full\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n </header>\n <ul class=\"m-0 grid max-h-64 list-none content-start gap-xs overflow-x-hidden overflow-y-auto p-0\">\n @for (_ of listSkeletonRows; track _) {\n <li>\n <div class=\"flex w-full flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-sm\">\n <div class=\"flex w-full min-w-0 items-center gap-xs\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"flex min-w-0 flex-1 flex-col gap-2xs\">\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-36\"></ed-skeleton>\n </div>\n </div>\n <ed-skeleton class=\"h-5 w-28 shrink-0 !rounded-full\"></ed-skeleton>\n </div>\n <div class=\"flex w-full min-w-0 items-center gap-sm\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs\">\n <ed-skeleton class=\"h-8 w-8 shrink-0 !rounded-md\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-full max-w-xs\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-3 w-14 shrink-0\"></ed-skeleton>\n </div>\n </div>\n </li>\n }\n </ul>\n </article>\n </section>\n\n <article class=\"flex flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\" aria-busy=\"true\">\n <header class=\"flex items-center justify-between gap-xs\">\n <div class=\"flex items-center gap-sm\">\n <h4>Recent Calls</h4>\n <ed-skeleton class=\"h-5 w-8 !rounded-full\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n </header>\n <div class=\"overflow-x-auto bg-white rounded-md\">\n <table class=\"table-default eds-centered-table relative min-w-5xl w-full\" aria-label=\"Recent calls\">\n <thead>\n <tr>\n <th>Time</th>\n <th>Patient / Caller</th>\n <th class=\"w-16 text-center\" aria-label=\"Direction\">\n <span class=\"inline-flex items-center justify-center gap-2xs\">\n <ed-icon name=\"call_received\" [size]=\"12\" class=\"text-success\" color=\"currentColor\" />\n <span class=\"text-light\">/</span>\n <ed-icon name=\"call_made\" [size]=\"12\" class=\"text-primary\" color=\"currentColor\" />\n </span>\n </th>\n <th>Goal</th>\n <th>Review</th>\n <th>Resolution</th>\n <th>Result</th>\n <th>Duration</th>\n </tr>\n </thead>\n <tbody>\n @for (_ of skeletonRows; track _) {\n <tr>\n <td>\n <div class=\"grid gap-2xs py-2xs\">\n <ed-skeleton class=\"h-3 w-12\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-20\"></ed-skeleton>\n </div>\n </td>\n <td>\n <div class=\"flex items-center gap-xs py-2xs\">\n <ed-skeleton class=\"h-8 w-8 !rounded-md\"></ed-skeleton>\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-36\"></ed-skeleton>\n </div>\n </div>\n </td>\n <td class=\"text-center\">\n <div class=\"flex justify-center py-2xs\">\n <ed-skeleton class=\"h-5 w-5 !rounded\"></ed-skeleton>\n </div>\n </td>\n <td><ed-skeleton class=\"h-3 w-32\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-5 w-12 !rounded-full\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-5 w-28 !rounded\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-10\"></ed-skeleton></td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </article>\n } @else if (data()) {\n <section class=\"grid grid-cols-1 gap-base sm:grid-cols-2 xl:grid-cols-4\" aria-label=\"Overview KPIs\">\n @for (tile of kpiCards(); track tile.id) {\n @if (tile.link) {\n <button\n type=\"button\"\n class=\"flex flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-base text-left text-inherit transition-colors hover:bg-primary-100 hover:shadow-sm\"\n (click)=\"openKpi(tile)\">\n <span class=\"fs-xs font-semibold uppercase tracking-wide text-light\">{{ tile.label }}</span>\n <h3>{{ tile.value }}</h3>\n <span class=\"fs-xs text-light\">{{ tile.meta }}</span>\n </button>\n } @else {\n <article class=\"flex flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-base\">\n <span class=\"fs-xs font-semibold uppercase tracking-wide text-light\">{{ tile.label }}</span>\n <h3>{{ tile.value }}</h3>\n <span class=\"fs-sm text-light\">{{ tile.meta }}</span>\n </article>\n }\n }\n </section>\n\n <section\n class=\"grid grid-cols-1 items-stretch gap-base xl:grid-cols-2\"\n aria-label=\"Live calls and needs attention\">\n <article class=\"flex h-full min-h-64 flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex shrink-0 items-center justify-between gap-sm\">\n <div class=\"flex items-center gap-sm\">\n <h4>Live Calls</h4>\n @if (agentOffline()) {\n <span class=\"inline-flex items-center gap-2xs fs-sm font-semibold text-danger\">\n <ed-icon name=\"phone_disabled\" [size]=\"18\" />\n Offline\n </span>\n } @else {\n <ed-badge-2 variant=\"success\" pill uppercase>\n {{ liveCallCount() }} LIVE\n </ed-badge-2>\n }\n </div>\n <button type=\"button\" class=\"eds-plain-nav fs-sm font-medium text-primary\" (click)=\"goTo('../live')\">\n View All\n <ed-icon name=\"chevron_right\" [size]=\"16\" color=\"currentColor\" />\n </button>\n </header>\n\n <ul class=\"m-0 grid max-h-64 list-none content-start gap-xs overflow-x-hidden overflow-y-auto p-0\">\n @if (liveCallsError()) {\n <li class=\"fs-sm text-light\" role=\"alert\">{{ liveCallsError() }}</li>\n }\n @if (liveCallsLoading() && liveCallRows().length === 0) {\n @for (_ of listSkeletonRows; track _) {\n <li>\n <div class=\"flex w-full items-center gap-base rounded-md border border-light bg-white p-sm\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs xl:max-w-xs\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 flex-1 gap-2xs\">\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n </div>\n </div>\n <div class=\"hidden min-w-0 flex-1 items-center gap-xs xl:flex\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 gap-2xs\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n </div>\n </div>\n <div class=\"grid shrink-0 justify-items-end gap-2xs self-stretch\">\n <ed-skeleton class=\"h-5 w-24 !rounded-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-12\"></ed-skeleton>\n </div>\n </div>\n </li>\n }\n }\n @for (call of liveCallRows(); track call.id) {\n <li>\n <button\n type=\"button\"\n class=\"flex w-full cursor-pointer items-center gap-base rounded-md border border-light bg-white p-sm text-left transition-colors hover:bg-lighter hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary\"\n [class.border-danger]=\"call.needsAssistance\"\n [class.bg-danger-50]=\"call.needsAssistance\"\n (click)=\"openLiveCall(call.id)\"\n >\n <div class=\"flex min-w-0 flex-1 items-center gap-xs xl:max-w-xs\">\n <ed-avatar\n shape=\"box\"\n size=\"base\"\n [initials]=\"call.initials\"\n [tone]=\"call.avatarTone\"\n />\n <div class=\"grid min-w-0 flex-1 gap-2xs\">\n <div class=\"flex min-w-0 flex-wrap items-center gap-sm\">\n <span class=\"fs-sm font-semibold text-dark\">{{ call.name }}</span>\n <span class=\"vr-sentiment\" [attr.data-sentiment]=\"call.sentiment\">\n <span class=\"vr-sentiment__icon\" aria-hidden=\"true\">\n <img [src]=\"call.sentimentIconSrc\" alt=\"\" width=\"16\" height=\"16\" />\n </span>\n <span>{{ call.sentimentLabel }}</span>\n </span>\n </div>\n <span class=\"fs-sm whitespace-nowrap text-light\">{{ call.metaLine }}</span>\n </div>\n </div>\n\n <div class=\"hidden min-w-0 flex-1 items-center gap-xs xl:flex\">\n <span\n class=\"inline-flex size-9 shrink-0 items-center justify-center rounded-md\"\n [class.bg-success-50]=\"call.direction === 'inbound'\"\n [class.text-success]=\"call.direction === 'inbound'\"\n [class.bg-primary-50]=\"call.direction === 'outbound'\"\n [class.text-primary]=\"call.direction === 'outbound'\"\n [smartTooltip]=\"call.directionTitle\"\n >\n <ed-icon [name]=\"call.directionIcon\" [size]=\"18\" color=\"currentColor\" />\n </span>\n <div class=\"grid min-w-0 gap-2xs whitespace-nowrap\">\n <span class=\"fs-sm font-medium text-dark\">{{ call.goal }}</span>\n <span class=\"fs-xs text-light\">{{ call.statusSubtitle }}</span>\n </div>\n </div>\n\n <div class=\"grid shrink-0 justify-items-end gap-2xs self-stretch\">\n <ed-badge-2 [attr.variant]=\"call.handlingVariant\" pill uppercase>\n {{ call.handlingLabel }}\n </ed-badge-2>\n <strong\n class=\"inline-flex items-center gap-2xs fs-2xs text-primary\"\n [class.text-danger]=\"call.needsAssistance\"\n [class.text-light]=\"!call.needsAssistance\"\n >\n @if (!call.needsAssistance) {\n <eds-pulse-dot />\n }\n {{ call.started | edsElapsed }}\n </strong>\n </div>\n </button>\n </li>\n } @empty {\n @if (!liveCallsLoading()) {\n <li class=\"fs-sm text-light\">No active calls right now.</li>\n }\n }\n </ul>\n </article>\n\n <article class=\"flex h-full min-h-64 flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex shrink-0 items-center justify-between gap-sm\">\n <div class=\"flex items-center gap-sm\">\n <h4>Needs Attention</h4>\n <ed-badge-2 variant=\"warning\" pill>\n {{ attentionCount() }}\n </ed-badge-2>\n </div>\n <button type=\"button\" class=\"eds-plain-nav fs-sm font-medium text-primary\" (click)=\"goTo('../history')\">\n View All\n <ed-icon name=\"chevron_right\" [size]=\"16\" color=\"currentColor\" />\n </button>\n </header>\n\n <ul class=\"m-0 grid max-h-64 list-none content-start gap-xs overflow-x-hidden overflow-y-auto p-0\">\n @for (item of attentionRows(); track item.id) {\n <li>\n <div\n role=\"button\"\n tabindex=\"0\"\n class=\"flex w-full cursor-pointer flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-sm text-left transition-colors hover:bg-lighter hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary\"\n [attr.aria-label]=\"'Open attention item for ' + item.name\"\n (click)=\"openAttention(item)\"\n (keyup.enter)=\"openAttention(item)\"\n >\n <div class=\"flex w-full min-w-0 items-center gap-xs\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs\">\n <ed-avatar\n shape=\"box\"\n size=\"base\"\n [initials]=\"item.initials\"\n [tone]=\"item.avatarTone\"\n />\n <div class=\"flex min-w-0 flex-1 flex-col gap-2xs\">\n <div class=\"flex min-w-0 items-center gap-2xs\">\n <span class=\"truncate fs-sm font-semibold text-dark\">{{ item.name }}</span>\n <!-- <span class=\"inline-flex shrink-0 text-light\">\n <ed-icon name=\"TagSimple\" [size]=\"14\" color=\"currentColor\" />\n </span> -->\n </div>\n <span class=\"truncate fs-sm text-light\">{{ item.metaLine }}</span>\n </div>\n </div>\n <ed-badge-2 class=\"shrink-0\" variant=\"light\" pill uppercase>\n {{ item.badge }}\n </ed-badge-2>\n </div>\n <div class=\"flex w-full min-w-0 items-center gap-sm\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs\">\n <span\n class=\"inline-flex size-8 shrink-0 items-center justify-center rounded-md\"\n [class.bg-success-50]=\"item.direction === 'inbound'\"\n [class.text-success]=\"item.direction === 'inbound'\"\n [class.bg-primary-50]=\"item.direction === 'outbound'\"\n [class.text-primary]=\"item.direction === 'outbound'\"\n [smartTooltip]=\"item.directionTitle\"\n >\n <ed-icon [name]=\"item.directionIcon\" [size]=\"16\" color=\"currentColor\" />\n </span>\n <span class=\"min-w-0 flex-1 truncate fs-sm text-light\">{{ item.detail }}</span>\n </div>\n <span class=\"shrink-0 whitespace-nowrap fs-xs text-light\">{{ item.timeLabel }}</span>\n </div>\n </div>\n </li>\n } @empty {\n <li class=\"fs-sm text-light\">Nothing needs attention right now.</li>\n }\n </ul>\n </article>\n </section>\n\n <article class=\"flex flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex items-center justify-between gap-xs\">\n <div class=\"flex items-center gap-sm\">\n <h4>Recent Calls</h4>\n <ed-badge-2\n variant=\"light\"\n pill\n [attr.aria-label]=\"'Recent calls count ' + recentHistoryCount()\"\n >\n {{ recentHistoryCount() }}\n </ed-badge-2>\n </div>\n <button type=\"button\" class=\"eds-plain-nav fs-sm font-medium text-primary\" (click)=\"goTo('../history')\">\n View All\n <ed-icon name=\"chevron_right\" [size]=\"16\" color=\"currentColor\" />\n </button>\n </header>\n\n <div class=\"overflow-x-auto bg-white rounded-md\">\n <table class=\"table-default eds-centered-table relative min-w-5xl w-full\" aria-label=\"Recent calls\">\n <thead>\n <tr>\n <th>Time</th>\n <th>Patient / Caller</th>\n <th class=\"w-16 text-center\" aria-label=\"Direction\">\n <span class=\"inline-flex items-center justify-center gap-2xs\">\n <ed-icon name=\"call_received\" [size]=\"12\" class=\"text-success\" color=\"currentColor\" />\n <span class=\"text-light\">/</span>\n <ed-icon name=\"call_made\" [size]=\"12\" class=\"text-primary\" color=\"currentColor\" />\n </span>\n </th>\n <th>Goal</th>\n <th>Review</th>\n <th>Resolution</th>\n <th>Result</th>\n <th>Duration</th>\n </tr>\n </thead>\n <tbody>\n @for (row of recentHistoryRows(); track row.id) {\n <tr\n class=\"focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'View call details for ' + row.name\"\n (click)=\"openHistoryDetail(row.id)\"\n (keyup.enter)=\"openHistoryDetail(row.id)\"\n >\n <td>\n <div class=\"flex flex-col gap-2xs whitespace-nowrap\">\n @if (row.started) {\n <span class=\"fs-xs font-medium text-light\">{{ row.started | date: 'shortTime' }}</span>\n <span class=\"fs-xs text-light\">{{ row.started | date: 'MMM d, y' }}</span>\n } @else {\n <span class=\"fs-xs font-medium text-light\">{{ row.whenLabel }}</span>\n }\n </div>\n </td>\n\n <td>\n <div class=\"eds-caller-cell\">\n <ed-avatar\n shape=\"box\"\n size=\"base\"\n [initials]=\"row.initials\"\n [tone]=\"row.avatarTone\"\n />\n <div class=\"eds-caller-cell__text\">\n <span\n class=\"eds-caller-cell__name fs-sm font-semibold text-dark\"\n [smartTooltip]=\"row.name\"\n >{{ row.name }}</span>\n <span\n class=\"eds-caller-cell__meta fs-xs text-light\"\n [smartTooltip]=\"row.metaLine\"\n >{{ row.metaLine }}</span>\n </div>\n </div>\n </td>\n\n <td class=\"text-center\">\n <span\n class=\"inline-flex size-5 items-center justify-center rounded\"\n [class.bg-success-50]=\"row.direction === 'inbound'\"\n [class.text-success]=\"row.direction === 'inbound'\"\n [class.bg-primary-50]=\"row.direction === 'outbound'\"\n [class.text-primary]=\"row.direction === 'outbound'\"\n [smartTooltip]=\"row.directionTitle\"\n >\n <ed-icon [name]=\"row.directionIcon\" [size]=\"12\" color=\"currentColor\" />\n </span>\n </td>\n\n <td>\n <span\n class=\"inline-block min-w-0 max-w-56 truncate fs-sm font-medium text-light\"\n [smartTooltip]=\"row.reason\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ row.reason }}</span>\n </td>\n\n <td>\n <ed-badge-2 [attr.variant]=\"row.reviewed ? 'success' : 'warning'\" pill uppercase>\n {{ row.reviewed ? 'Reviewed' : 'Needs review' }}\n </ed-badge-2>\n </td>\n\n <td>\n @if (row.resolution) {\n <ed-badge-2 [attr.variant]=\"row.resolutionVariant\" pill uppercase>\n {{ row.resolutionLabel }}\n </ed-badge-2>\n }\n </td>\n\n <td>\n <div class=\"flex min-w-0 max-w-80 flex-wrap gap-2xs\">\n @for (chip of row.resultChips; track chip.label) {\n <span\n class=\"inline-flex h-5 max-w-48 min-w-0 items-center gap-2xs rounded bg-light px-2xs fs-xs font-medium text-dark\"\n >\n <ed-icon [name]=\"chip.icon\" [size]=\"12\" color=\"currentColor\" />\n <span\n class=\"min-w-0 truncate\"\n [smartTooltip]=\"chip.label\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ chip.label }}</span>\n </span>\n } @empty {\n <span class=\"fs-sm text-light\">\u2014</span>\n }\n </div>\n </td>\n\n <td class=\"whitespace-nowrap tabular-nums fs-xs font-medium text-light\">\n {{ row.durationLabel }}\n </td>\n </tr>\n } @empty {\n <tr class=\"table-no-data\">\n <td colspan=\"8\" class=\"py-base text-center fs-sm text-light\">No recent calls.</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </article>\n }\n </div>\n</div>\n", styles: [".vr-sentiment{display:inline-flex;align-items:center;justify-content:center;gap:4px;height:20px;padding:2px 4px;border-radius:6px;font-size:11px;font-weight:500;line-height:16px;white-space:nowrap}.vr-sentiment__icon{display:block;width:16px;height:16px;flex-shrink:0;overflow:hidden}.vr-sentiment__icon img{display:block;width:100%;height:100%;max-width:none}.vr-sentiment[data-sentiment=calm]{background:#3681f41a;color:#2162f0}.vr-sentiment[data-sentiment=neutral]{background:#f0f2f5;color:#41464c}.vr-sentiment[data-sentiment=urgent]{background:#f26b0d1a;color:#e94e0c}.vr-sentiment[data-sentiment=frustrated]{background:#f037401a;color:#db0c15}.eds-caller-cell{display:flex;width:13.5rem;max-width:13.5rem;align-items:center;gap:.5rem;margin-inline:auto;text-align:left}.eds-caller-cell__text{min-width:0;flex:1}.eds-caller-cell__name,.eds-caller-cell__meta{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.eds-plain-nav{display:inline-flex;align-items:center;gap:.25rem;margin:0;padding:0;border:none;background:transparent;cursor:pointer;font:inherit;color:inherit}\n"] }]
308
+ }] });
309
+
310
+ export { DashboardPageComponent };
311
+ //# sourceMappingURL=edvak99-voice-receptionist-widget-dashboard-page.component-CcphzJ4N.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edvak99-voice-receptionist-widget-dashboard-page.component-CcphzJ4N.mjs","sources":["../../../src/lib/pages/dashboard-page/dashboard-page.component.ts","../../../src/lib/pages/dashboard-page/dashboard-page.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n CUSTOM_ELEMENTS_SCHEMA,\n inject,\n OnDestroy,\n OnInit,\n signal,\n} from '@angular/core';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { DatePipe } from '@angular/common';\nimport { ToastService } from '../../shared/toast.service';\nimport { triggerBlobDownload } from '../../utils/csv-download.util';\n\nimport {\n CallStatus,\n DashboardData,\n HistoryCall,\n LiveCall,\n Sentiment,\n} from '../../models/ai-receptionist.types';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport { AgentOnlineService } from '../../services/agent-online.service';\nimport { LiveCallsListService } from '../../services/live-calls-list.service';\nimport {\n ageFromDob,\n callerMetaLine,\n historyResolution,\n historyResolutionLabel,\n historyResultChips,\n HistoryResolution,\n isUnknownCaller,\n resultChipIcon,\n} from '../../utils/call-history-display.util';\nimport { sentimentIconSrc, sentimentLabel } from '../../utils/sentiment-display.util';\nimport { isNeedsReview } from '../../utils/call-review.util';\nimport { EdButtonComponent } from '../../ui/ed-button.component';\nimport { EdSkeletonComponent } from '../../ui/ed-skeleton.component';\n\nimport { SmartTooltipDirective } from '../../shared/smart-tooltip.directive';\nimport { TABLE_SKELETON_ROWS } from '../../shared/table-skeleton.constants';\nimport { EdAvatarComponent } from '../../ui/ed-avatar.component';\nimport { IconComponent } from '../../ui/ed-icon.component';\nimport { EdsPulseDotComponent } from '../../ui/eds-pulse-dot.component';\nimport { EdsElapsedPipe } from '../../pipes/eds-elapsed.pipe';\n\ninterface KpiCardVm {\n id: string;\n label: string;\n value: string;\n meta: string;\n link?: string;\n queryParams?: Record<string, string>;\n}\n\ninterface LiveCallRowVm {\n id: string;\n name: string;\n initials: string;\n avatarTone: 'gray' | 'brand' | 'warm';\n metaLine: string;\n sentiment: Sentiment;\n sentimentLabel: string;\n sentimentIconSrc: string;\n direction: 'inbound' | 'outbound';\n directionIcon: string;\n directionTitle: string;\n goal: string;\n statusSubtitle: string;\n handlingLabel: string;\n handlingVariant: 'opened' | 'danger' | 'success';\n needsAssistance: boolean;\n started: number;\n}\n\ninterface AttentionRowVm {\n id: string;\n callId: string;\n name: string;\n initials: string;\n avatarTone: 'gray' | 'brand' | 'violet';\n metaLine: string;\n badge: string;\n detail: string;\n timeLabel: string;\n direction: 'inbound' | 'outbound';\n directionIcon: string;\n directionTitle: string;\n}\n\ninterface RecentHistoryRowVm {\n id: string;\n name: string;\n initials: string;\n avatarTone: 'gray' | 'brand';\n metaLine: string;\n direction: 'inbound' | 'outbound';\n directionIcon: string;\n directionTitle: string;\n reason: string;\n handledByLabel: string;\n handledByVariant: 'opened' | 'primary';\n resolution: HistoryResolution | null;\n resolutionLabel: string;\n resolutionVariant: 'success' | 'warning';\n resultChips: { label: string; icon: string }[];\n durationLabel: string;\n started: number | null;\n whenLabel: string;\n needsReview: boolean;\n reviewed: boolean;\n}\n\n@Component({\n selector: 'eds-dashboard-page',\n imports: [\n DatePipe,\n EdAvatarComponent,\n EdButtonComponent,\n IconComponent,\n EdsPulseDotComponent,\n EdsElapsedPipe,\n SmartTooltipDirective,\n EdSkeletonComponent,\n ],\n templateUrl: './dashboard-page.component.html',\n styleUrl: './dashboard-page.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n host: { class: 'block h-full min-h-0' },\n})\nexport class DashboardPageComponent implements OnInit, OnDestroy {\n private readonly api = inject(AiReceptionistApiService);\n private readonly liveCallsList = inject(LiveCallsListService);\n private readonly agentOnline = inject(AgentOnlineService);\n private readonly router = inject(Router);\n private readonly route = inject(ActivatedRoute);\n private readonly toast = inject(ToastService);\n\n protected readonly data = signal<DashboardData | null>(null);\n protected readonly loading = signal(true);\n protected readonly kpiSkeletonRows = [0, 1, 2, 3] as const;\n protected readonly listSkeletonRows = [0, 1, 2] as const;\n protected readonly skeletonRows = TABLE_SKELETON_ROWS;\n\n protected readonly liveCalls = this.liveCallsList.calls;\n protected readonly liveCallsLoading = this.liveCallsList.loading;\n protected readonly liveCallsError = this.liveCallsList.error;\n protected readonly agentOffline = computed(() => this.agentOnline.online() === false);\n\n protected readonly kpiCards = computed((): KpiCardVm[] => {\n const stats = this.data()?.stats;\n if (!stats) return [];\n const calls = stats.answeredToday;\n const resolvedCount = Math.round((stats.completionRate / 100) * Math.max(calls, 1));\n return [\n {\n id: 'calls',\n label: 'Calls handled',\n value: String(calls),\n meta: 'Today',\n link: '../history',\n },\n {\n id: 'appointments',\n label: 'Appointments booked',\n value: String(stats.appointmentsBooked),\n meta: 'Created by AI',\n link: '../activities',\n queryParams: { tab: 'appointments' },\n },\n {\n id: 'tasks',\n label: 'Tasks created',\n value: String(stats.tasksCreated),\n meta: 'Created by AI',\n link: '../activities',\n },\n {\n id: 'resolved',\n label: 'Resolved without staff',\n value: `${stats.completionRate}%`,\n meta: calls > 0 ? `${resolvedCount} of ${calls} calls` : 'AI handled',\n link: '../history',\n },\n ];\n });\n\n protected readonly liveCallRows = computed(() =>\n this.liveCalls().map((call) => this.toLiveCallRow(call)),\n );\n\n protected readonly liveCallCount = computed(() => this.liveCallRows().length);\n\n protected readonly attentionRows = computed((): AttentionRowVm[] => {\n const fromLive = this.liveCalls()\n .filter((c) => this.isAssistanceStatus(c.status) || c.sentiment === 'frustrated' || c.sentiment === 'urgent')\n .map((c) => this.toAttentionFromLive(c));\n\n const fromHistory = (this.data()?.recentHistory ?? [])\n .filter(\n (row) =>\n historyResolution({\n outcome: row.outcome,\n resolution: row.resolution,\n risk: row.risk,\n }) === 'needs_attention',\n )\n .map((row) => this.toAttentionFromHistory(row));\n\n const seen = new Set<string>();\n const merged: AttentionRowVm[] = [];\n for (const item of [...fromLive, ...fromHistory]) {\n if (seen.has(item.callId)) continue;\n seen.add(item.callId);\n merged.push(item);\n if (merged.length >= 6) break;\n }\n return merged;\n });\n\n protected readonly attentionCount = computed(() => this.attentionRows().length);\n\n protected readonly recentHistoryRows = computed(() =>\n (this.data()?.recentHistory ?? []).map((row) => this.toRecentHistoryRow(row)),\n );\n\n protected readonly recentHistoryCount = computed(() => this.recentHistoryRows().length);\n\n ngOnInit(): void {\n this.liveCallsList.start();\n this.api.getDashboard().subscribe(({ data }) => {\n this.data.set(data);\n this.loading.set(false);\n });\n }\n\n ngOnDestroy(): void {\n this.liveCallsList.stop();\n }\n\n protected exportCsv(): void {\n this.api.exportHistoryCsv().subscribe({\n next: ({ blob, filename }) => {\n triggerBlobDownload(blob, filename);\n this.toast.show('Export downloaded', 'success');\n },\n error: (err: { message?: string }) => {\n this.toast.show(err.message ?? 'Failed to export CSV', 'error');\n },\n });\n }\n\n protected openKpi(tile: KpiCardVm): void {\n if (!tile.link) return;\n void this.router.navigate([tile.link], {\n relativeTo: this.route,\n queryParams: tile.queryParams ?? undefined,\n });\n }\n\n protected goTo(path: string): void {\n void this.router.navigate([path], { relativeTo: this.route });\n }\n\n protected openHistoryDetail(id: string): void {\n void this.router.navigate(['../history', id], { relativeTo: this.route });\n }\n\n protected openLiveCall(id: string): void {\n void this.router.navigate(['../live', id], { relativeTo: this.route });\n }\n\n protected openAttention(item: AttentionRowVm): void {\n const live = this.liveCalls().some((c) => c.id === item.callId);\n void this.router.navigate(live ? ['../live', item.callId] : ['../history', item.callId], {\n relativeTo: this.route,\n });\n }\n\n private toLiveCallRow(call: LiveCall): LiveCallRowVm {\n const unknown = isUnknownCaller(call.name, call.matched);\n const needsAssistance = this.isAssistanceStatus(call.status);\n const staffHandling = call.status === 'takeover' || call.controlMode === 'takeover';\n const lastTool = call.tools[call.tools.length - 1];\n\n return {\n id: call.id,\n name: unknown ? 'Unknown Caller' : call.name.trim() || 'Unknown Caller',\n initials: unknown ? '?' : call.initials || '?',\n avatarTone: unknown ? 'gray' : 'warm',\n metaLine: callerMetaLine({\n name: call.name,\n matched: call.matched,\n phone: call.phone,\n dob: call.dob,\n age: call.age ?? ageFromDob(call.dob),\n gender: call.gender,\n }),\n sentiment: call.sentiment,\n sentimentLabel: sentimentLabel(call.sentiment),\n sentimentIconSrc: sentimentIconSrc(call.sentiment),\n direction: call.direction,\n directionIcon: call.direction === 'inbound' ? 'call_received' : 'call_made',\n directionTitle: call.direction === 'inbound' ? 'Incoming call' : 'Outgoing call',\n goal: call.reason || call.goal || '—',\n statusSubtitle: lastTool?.result || call.goal || 'In progress…',\n handlingLabel: needsAssistance\n ? 'NEED ASSISTANCE'\n : staffHandling\n ? 'STAFF HANDLING'\n : 'AI HANDLING',\n handlingVariant: needsAssistance ? 'danger' : staffHandling ? 'success' : 'opened',\n needsAssistance,\n started: call.started,\n };\n }\n\n private toAttentionFromLive(call: LiveCall): AttentionRowVm {\n const unknown = isUnknownCaller(call.name, call.matched);\n return {\n id: `live-${call.id}`,\n callId: call.id,\n name: unknown ? 'Unknown Caller' : call.name.trim() || 'Unknown Caller',\n initials: unknown ? '?' : call.initials || '?',\n avatarTone: unknown ? 'gray' : 'violet',\n metaLine: callerMetaLine({\n name: call.name,\n matched: call.matched,\n phone: call.phone,\n dob: call.dob,\n age: call.age ?? ageFromDob(call.dob),\n gender: call.gender,\n }),\n badge: this.attentionBadgeFromLive(call),\n detail: call.goal || call.reason || 'Needs staff follow-up.',\n timeLabel: 'Just now',\n direction: call.direction,\n directionIcon: call.direction === 'inbound' ? 'call_received' : 'call_made',\n directionTitle: call.direction === 'inbound' ? 'Incoming call' : 'Outgoing call',\n };\n }\n\n private toAttentionFromHistory(row: HistoryCall): AttentionRowVm {\n const unknown = isUnknownCaller(row.name);\n const inbound = row.direction === 'inbound';\n return {\n id: `hist-${row.id}`,\n callId: row.id,\n name: unknown ? 'Unknown Caller' : row.name.trim() || 'Unknown Caller',\n initials: unknown || !row.initials ? '?' : row.initials,\n avatarTone: unknown || row.initials === '?' ? 'gray' : 'violet',\n metaLine: callerMetaLine({\n dob: row.dob,\n age: row.age,\n gender: row.gender,\n phone: row.phone,\n name: row.name,\n }),\n badge: this.attentionBadgeFromHistory(row),\n detail: row.reason || row.outcome || 'Needs review.',\n timeLabel: row.whenLabel || 'Recently',\n direction: row.direction,\n directionIcon: inbound ? 'call_received' : 'call_made',\n directionTitle: inbound ? 'Incoming call' : 'Outgoing call',\n };\n }\n\n private toRecentHistoryRow(row: HistoryCall): RecentHistoryRowVm {\n const unknown = isUnknownCaller(row.name);\n const resolution = historyResolution({\n outcome: row.outcome,\n resolution: row.resolution,\n risk: row.risk,\n });\n const handledByStaff = row.handledBy === 'staff';\n const inbound = row.direction === 'inbound';\n const chips = historyResultChips(row.results, row.outcome);\n\n return {\n id: row.id,\n name: row.name || 'Unknown Caller',\n initials: row.initials || '?',\n avatarTone: unknown || row.initials === '?' ? 'gray' : 'brand',\n metaLine: callerMetaLine({\n dob: row.dob,\n age: row.age,\n gender: row.gender,\n phone: row.phone,\n name: row.name,\n }),\n direction: row.direction,\n directionIcon: inbound ? 'call_received' : 'call_made',\n directionTitle: inbound ? 'Incoming call' : 'Outgoing call',\n reason: row.reason || '—',\n handledByLabel: handledByStaff ? 'STAFF' : 'AI',\n handledByVariant: handledByStaff ? 'primary' : 'opened',\n resolution,\n resolutionLabel: historyResolutionLabel(resolution),\n resolutionVariant: resolution === 'resolved' ? 'success' : 'warning',\n resultChips: chips.map((label) => ({ label, icon: resultChipIcon(label) })),\n durationLabel: row.durationLabel ?? this.formatDuration(row.duration),\n started: row.started || null,\n whenLabel: row.whenLabel || '—',\n needsReview: isNeedsReview(row.review),\n reviewed: row.review === 'reviewed',\n };\n }\n\n private isAssistanceStatus(status: CallStatus): boolean {\n return status === 'needs-help' || status === 'human-requested' || status === 'urgent';\n }\n\n private attentionBadgeFromLive(call: LiveCall): string {\n if (call.status === 'urgent') return 'SAFETY ESCALATION';\n if (call.status === 'human-requested') return 'HUMAN REQUESTED';\n if (call.verification === 'failed' || call.verification === 'unknown') return 'IDENTITY UNRESOLVED';\n if (call.status === 'needs-help') return 'NEED ASSISTANCE';\n return 'NEEDS REVIEW';\n }\n\n private attentionBadgeFromHistory(row: HistoryCall): string {\n const o = (row.outcome || row.reason || '').toLowerCase();\n if (o.includes('book') || o.includes('appoint')) return 'BOOKING FAILURE';\n if (o.includes('ident') || row.verification === 'failed' || row.verification === 'unknown') {\n return 'IDENTITY UNRESOLVED';\n }\n if (row.risk === 'urgent') return 'SAFETY ESCALATION';\n return 'NEEDS REVIEW';\n }\n\n private formatDuration(sec: number): string {\n const m = Math.floor(sec / 60);\n const s = sec % 60;\n return `${m}:${s.toString().padStart(2, '0')}`;\n }\n}\n","<div class=\"flex h-full flex-col overflow-auto bg-lighter p-base dashboard-page\">\n <header class=\"mb-base flex shrink-0 items-start justify-between gap-base\">\n <div class=\"flex flex-col gap-2xs\">\n <h3>Dashboard</h3>\n <p class=\"fs-sm text-light\">Monitor AI receptionist activity and follow up where needed</p>\n </div>\n <ed-button\n class=\"shrink-0\"\n variant=\"default\"\n size=\"sm\"\n (click$)=\"exportCsv()\">\n <ed-icon slot=\"prefix\" name=\"download\" [size]=\"16\" />\n Export CSV\n </ed-button>\n </header>\n\n <div class=\"flex flex-1 flex-col gap-base \">\n @if (loading()) {\n <section class=\"grid grid-cols-1 gap-base sm:grid-cols-2 xl:grid-cols-4\" aria-label=\"Overview KPIs\" aria-busy=\"true\">\n @for (_ of kpiSkeletonRows; track _) {\n <article class=\"flex flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-base\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-6 w-14\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n </article>\n }\n </section>\n\n <section\n class=\"grid grid-cols-1 items-stretch gap-base xl:grid-cols-2\"\n aria-label=\"Live calls and needs attention\"\n aria-busy=\"true\"\n >\n <article class=\"flex h-full min-h-64 flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex shrink-0 items-center justify-between gap-sm\">\n <div class=\"flex items-center gap-sm\">\n <h4>Live Calls</h4>\n <ed-skeleton class=\"h-5 w-16 !rounded-full\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n </header>\n <ul class=\"m-0 grid max-h-64 list-none content-start gap-xs overflow-x-hidden overflow-y-auto p-0\">\n @for (_ of listSkeletonRows; track _) {\n <li>\n <div class=\"flex w-full items-center gap-base rounded-md border border-light bg-white p-sm\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs xl:max-w-xs\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 flex-1 gap-2xs\">\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n </div>\n </div>\n <div class=\"hidden min-w-0 flex-1 items-center gap-xs xl:flex\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 gap-2xs\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n </div>\n </div>\n <div class=\"grid shrink-0 justify-items-end gap-2xs self-stretch\">\n <ed-skeleton class=\"h-5 w-24 !rounded-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-12\"></ed-skeleton>\n </div>\n </div>\n </li>\n }\n </ul>\n </article>\n\n <article class=\"flex h-full min-h-64 flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex shrink-0 items-center justify-between gap-sm\">\n <div class=\"flex items-center gap-sm\">\n <h4>Needs Attention</h4>\n <ed-skeleton class=\"h-5 w-8 !rounded-full\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n </header>\n <ul class=\"m-0 grid max-h-64 list-none content-start gap-xs overflow-x-hidden overflow-y-auto p-0\">\n @for (_ of listSkeletonRows; track _) {\n <li>\n <div class=\"flex w-full flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-sm\">\n <div class=\"flex w-full min-w-0 items-center gap-xs\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"flex min-w-0 flex-1 flex-col gap-2xs\">\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-36\"></ed-skeleton>\n </div>\n </div>\n <ed-skeleton class=\"h-5 w-28 shrink-0 !rounded-full\"></ed-skeleton>\n </div>\n <div class=\"flex w-full min-w-0 items-center gap-sm\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs\">\n <ed-skeleton class=\"h-8 w-8 shrink-0 !rounded-md\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-full max-w-xs\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-3 w-14 shrink-0\"></ed-skeleton>\n </div>\n </div>\n </li>\n }\n </ul>\n </article>\n </section>\n\n <article class=\"flex flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\" aria-busy=\"true\">\n <header class=\"flex items-center justify-between gap-xs\">\n <div class=\"flex items-center gap-sm\">\n <h4>Recent Calls</h4>\n <ed-skeleton class=\"h-5 w-8 !rounded-full\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n </header>\n <div class=\"overflow-x-auto bg-white rounded-md\">\n <table class=\"table-default eds-centered-table relative min-w-5xl w-full\" aria-label=\"Recent calls\">\n <thead>\n <tr>\n <th>Time</th>\n <th>Patient / Caller</th>\n <th class=\"w-16 text-center\" aria-label=\"Direction\">\n <span class=\"inline-flex items-center justify-center gap-2xs\">\n <ed-icon name=\"call_received\" [size]=\"12\" class=\"text-success\" color=\"currentColor\" />\n <span class=\"text-light\">/</span>\n <ed-icon name=\"call_made\" [size]=\"12\" class=\"text-primary\" color=\"currentColor\" />\n </span>\n </th>\n <th>Goal</th>\n <th>Review</th>\n <th>Resolution</th>\n <th>Result</th>\n <th>Duration</th>\n </tr>\n </thead>\n <tbody>\n @for (_ of skeletonRows; track _) {\n <tr>\n <td>\n <div class=\"grid gap-2xs py-2xs\">\n <ed-skeleton class=\"h-3 w-12\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-20\"></ed-skeleton>\n </div>\n </td>\n <td>\n <div class=\"flex items-center gap-xs py-2xs\">\n <ed-skeleton class=\"h-8 w-8 !rounded-md\"></ed-skeleton>\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-36\"></ed-skeleton>\n </div>\n </div>\n </td>\n <td class=\"text-center\">\n <div class=\"flex justify-center py-2xs\">\n <ed-skeleton class=\"h-5 w-5 !rounded\"></ed-skeleton>\n </div>\n </td>\n <td><ed-skeleton class=\"h-3 w-32\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-5 w-12 !rounded-full\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-5 w-28 !rounded\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-10\"></ed-skeleton></td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </article>\n } @else if (data()) {\n <section class=\"grid grid-cols-1 gap-base sm:grid-cols-2 xl:grid-cols-4\" aria-label=\"Overview KPIs\">\n @for (tile of kpiCards(); track tile.id) {\n @if (tile.link) {\n <button\n type=\"button\"\n class=\"flex flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-base text-left text-inherit transition-colors hover:bg-primary-100 hover:shadow-sm\"\n (click)=\"openKpi(tile)\">\n <span class=\"fs-xs font-semibold uppercase tracking-wide text-light\">{{ tile.label }}</span>\n <h3>{{ tile.value }}</h3>\n <span class=\"fs-xs text-light\">{{ tile.meta }}</span>\n </button>\n } @else {\n <article class=\"flex flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-base\">\n <span class=\"fs-xs font-semibold uppercase tracking-wide text-light\">{{ tile.label }}</span>\n <h3>{{ tile.value }}</h3>\n <span class=\"fs-sm text-light\">{{ tile.meta }}</span>\n </article>\n }\n }\n </section>\n\n <section\n class=\"grid grid-cols-1 items-stretch gap-base xl:grid-cols-2\"\n aria-label=\"Live calls and needs attention\">\n <article class=\"flex h-full min-h-64 flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex shrink-0 items-center justify-between gap-sm\">\n <div class=\"flex items-center gap-sm\">\n <h4>Live Calls</h4>\n @if (agentOffline()) {\n <span class=\"inline-flex items-center gap-2xs fs-sm font-semibold text-danger\">\n <ed-icon name=\"phone_disabled\" [size]=\"18\" />\n Offline\n </span>\n } @else {\n <ed-badge-2 variant=\"success\" pill uppercase>\n {{ liveCallCount() }} LIVE\n </ed-badge-2>\n }\n </div>\n <button type=\"button\" class=\"eds-plain-nav fs-sm font-medium text-primary\" (click)=\"goTo('../live')\">\n View All\n <ed-icon name=\"chevron_right\" [size]=\"16\" color=\"currentColor\" />\n </button>\n </header>\n\n <ul class=\"m-0 grid max-h-64 list-none content-start gap-xs overflow-x-hidden overflow-y-auto p-0\">\n @if (liveCallsError()) {\n <li class=\"fs-sm text-light\" role=\"alert\">{{ liveCallsError() }}</li>\n }\n @if (liveCallsLoading() && liveCallRows().length === 0) {\n @for (_ of listSkeletonRows; track _) {\n <li>\n <div class=\"flex w-full items-center gap-base rounded-md border border-light bg-white p-sm\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs xl:max-w-xs\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 flex-1 gap-2xs\">\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n </div>\n </div>\n <div class=\"hidden min-w-0 flex-1 items-center gap-xs xl:flex\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 gap-2xs\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n </div>\n </div>\n <div class=\"grid shrink-0 justify-items-end gap-2xs self-stretch\">\n <ed-skeleton class=\"h-5 w-24 !rounded-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-12\"></ed-skeleton>\n </div>\n </div>\n </li>\n }\n }\n @for (call of liveCallRows(); track call.id) {\n <li>\n <button\n type=\"button\"\n class=\"flex w-full cursor-pointer items-center gap-base rounded-md border border-light bg-white p-sm text-left transition-colors hover:bg-lighter hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary\"\n [class.border-danger]=\"call.needsAssistance\"\n [class.bg-danger-50]=\"call.needsAssistance\"\n (click)=\"openLiveCall(call.id)\"\n >\n <div class=\"flex min-w-0 flex-1 items-center gap-xs xl:max-w-xs\">\n <ed-avatar\n shape=\"box\"\n size=\"base\"\n [initials]=\"call.initials\"\n [tone]=\"call.avatarTone\"\n />\n <div class=\"grid min-w-0 flex-1 gap-2xs\">\n <div class=\"flex min-w-0 flex-wrap items-center gap-sm\">\n <span class=\"fs-sm font-semibold text-dark\">{{ call.name }}</span>\n <span class=\"vr-sentiment\" [attr.data-sentiment]=\"call.sentiment\">\n <span class=\"vr-sentiment__icon\" aria-hidden=\"true\">\n <img [src]=\"call.sentimentIconSrc\" alt=\"\" width=\"16\" height=\"16\" />\n </span>\n <span>{{ call.sentimentLabel }}</span>\n </span>\n </div>\n <span class=\"fs-sm whitespace-nowrap text-light\">{{ call.metaLine }}</span>\n </div>\n </div>\n\n <div class=\"hidden min-w-0 flex-1 items-center gap-xs xl:flex\">\n <span\n class=\"inline-flex size-9 shrink-0 items-center justify-center rounded-md\"\n [class.bg-success-50]=\"call.direction === 'inbound'\"\n [class.text-success]=\"call.direction === 'inbound'\"\n [class.bg-primary-50]=\"call.direction === 'outbound'\"\n [class.text-primary]=\"call.direction === 'outbound'\"\n [smartTooltip]=\"call.directionTitle\"\n >\n <ed-icon [name]=\"call.directionIcon\" [size]=\"18\" color=\"currentColor\" />\n </span>\n <div class=\"grid min-w-0 gap-2xs whitespace-nowrap\">\n <span class=\"fs-sm font-medium text-dark\">{{ call.goal }}</span>\n <span class=\"fs-xs text-light\">{{ call.statusSubtitle }}</span>\n </div>\n </div>\n\n <div class=\"grid shrink-0 justify-items-end gap-2xs self-stretch\">\n <ed-badge-2 [attr.variant]=\"call.handlingVariant\" pill uppercase>\n {{ call.handlingLabel }}\n </ed-badge-2>\n <strong\n class=\"inline-flex items-center gap-2xs fs-2xs text-primary\"\n [class.text-danger]=\"call.needsAssistance\"\n [class.text-light]=\"!call.needsAssistance\"\n >\n @if (!call.needsAssistance) {\n <eds-pulse-dot />\n }\n {{ call.started | edsElapsed }}\n </strong>\n </div>\n </button>\n </li>\n } @empty {\n @if (!liveCallsLoading()) {\n <li class=\"fs-sm text-light\">No active calls right now.</li>\n }\n }\n </ul>\n </article>\n\n <article class=\"flex h-full min-h-64 flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex shrink-0 items-center justify-between gap-sm\">\n <div class=\"flex items-center gap-sm\">\n <h4>Needs Attention</h4>\n <ed-badge-2 variant=\"warning\" pill>\n {{ attentionCount() }}\n </ed-badge-2>\n </div>\n <button type=\"button\" class=\"eds-plain-nav fs-sm font-medium text-primary\" (click)=\"goTo('../history')\">\n View All\n <ed-icon name=\"chevron_right\" [size]=\"16\" color=\"currentColor\" />\n </button>\n </header>\n\n <ul class=\"m-0 grid max-h-64 list-none content-start gap-xs overflow-x-hidden overflow-y-auto p-0\">\n @for (item of attentionRows(); track item.id) {\n <li>\n <div\n role=\"button\"\n tabindex=\"0\"\n class=\"flex w-full cursor-pointer flex-col gap-xs overflow-hidden rounded-md border border-light bg-white p-sm text-left transition-colors hover:bg-lighter hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary\"\n [attr.aria-label]=\"'Open attention item for ' + item.name\"\n (click)=\"openAttention(item)\"\n (keyup.enter)=\"openAttention(item)\"\n >\n <div class=\"flex w-full min-w-0 items-center gap-xs\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs\">\n <ed-avatar\n shape=\"box\"\n size=\"base\"\n [initials]=\"item.initials\"\n [tone]=\"item.avatarTone\"\n />\n <div class=\"flex min-w-0 flex-1 flex-col gap-2xs\">\n <div class=\"flex min-w-0 items-center gap-2xs\">\n <span class=\"truncate fs-sm font-semibold text-dark\">{{ item.name }}</span>\n <!-- <span class=\"inline-flex shrink-0 text-light\">\n <ed-icon name=\"TagSimple\" [size]=\"14\" color=\"currentColor\" />\n </span> -->\n </div>\n <span class=\"truncate fs-sm text-light\">{{ item.metaLine }}</span>\n </div>\n </div>\n <ed-badge-2 class=\"shrink-0\" variant=\"light\" pill uppercase>\n {{ item.badge }}\n </ed-badge-2>\n </div>\n <div class=\"flex w-full min-w-0 items-center gap-sm\">\n <div class=\"flex min-w-0 flex-1 items-center gap-xs\">\n <span\n class=\"inline-flex size-8 shrink-0 items-center justify-center rounded-md\"\n [class.bg-success-50]=\"item.direction === 'inbound'\"\n [class.text-success]=\"item.direction === 'inbound'\"\n [class.bg-primary-50]=\"item.direction === 'outbound'\"\n [class.text-primary]=\"item.direction === 'outbound'\"\n [smartTooltip]=\"item.directionTitle\"\n >\n <ed-icon [name]=\"item.directionIcon\" [size]=\"16\" color=\"currentColor\" />\n </span>\n <span class=\"min-w-0 flex-1 truncate fs-sm text-light\">{{ item.detail }}</span>\n </div>\n <span class=\"shrink-0 whitespace-nowrap fs-xs text-light\">{{ item.timeLabel }}</span>\n </div>\n </div>\n </li>\n } @empty {\n <li class=\"fs-sm text-light\">Nothing needs attention right now.</li>\n }\n </ul>\n </article>\n </section>\n\n <article class=\"flex flex-col gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <header class=\"flex items-center justify-between gap-xs\">\n <div class=\"flex items-center gap-sm\">\n <h4>Recent Calls</h4>\n <ed-badge-2\n variant=\"light\"\n pill\n [attr.aria-label]=\"'Recent calls count ' + recentHistoryCount()\"\n >\n {{ recentHistoryCount() }}\n </ed-badge-2>\n </div>\n <button type=\"button\" class=\"eds-plain-nav fs-sm font-medium text-primary\" (click)=\"goTo('../history')\">\n View All\n <ed-icon name=\"chevron_right\" [size]=\"16\" color=\"currentColor\" />\n </button>\n </header>\n\n <div class=\"overflow-x-auto bg-white rounded-md\">\n <table class=\"table-default eds-centered-table relative min-w-5xl w-full\" aria-label=\"Recent calls\">\n <thead>\n <tr>\n <th>Time</th>\n <th>Patient / Caller</th>\n <th class=\"w-16 text-center\" aria-label=\"Direction\">\n <span class=\"inline-flex items-center justify-center gap-2xs\">\n <ed-icon name=\"call_received\" [size]=\"12\" class=\"text-success\" color=\"currentColor\" />\n <span class=\"text-light\">/</span>\n <ed-icon name=\"call_made\" [size]=\"12\" class=\"text-primary\" color=\"currentColor\" />\n </span>\n </th>\n <th>Goal</th>\n <th>Review</th>\n <th>Resolution</th>\n <th>Result</th>\n <th>Duration</th>\n </tr>\n </thead>\n <tbody>\n @for (row of recentHistoryRows(); track row.id) {\n <tr\n class=\"focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'View call details for ' + row.name\"\n (click)=\"openHistoryDetail(row.id)\"\n (keyup.enter)=\"openHistoryDetail(row.id)\"\n >\n <td>\n <div class=\"flex flex-col gap-2xs whitespace-nowrap\">\n @if (row.started) {\n <span class=\"fs-xs font-medium text-light\">{{ row.started | date: 'shortTime' }}</span>\n <span class=\"fs-xs text-light\">{{ row.started | date: 'MMM d, y' }}</span>\n } @else {\n <span class=\"fs-xs font-medium text-light\">{{ row.whenLabel }}</span>\n }\n </div>\n </td>\n\n <td>\n <div class=\"eds-caller-cell\">\n <ed-avatar\n shape=\"box\"\n size=\"base\"\n [initials]=\"row.initials\"\n [tone]=\"row.avatarTone\"\n />\n <div class=\"eds-caller-cell__text\">\n <span\n class=\"eds-caller-cell__name fs-sm font-semibold text-dark\"\n [smartTooltip]=\"row.name\"\n >{{ row.name }}</span>\n <span\n class=\"eds-caller-cell__meta fs-xs text-light\"\n [smartTooltip]=\"row.metaLine\"\n >{{ row.metaLine }}</span>\n </div>\n </div>\n </td>\n\n <td class=\"text-center\">\n <span\n class=\"inline-flex size-5 items-center justify-center rounded\"\n [class.bg-success-50]=\"row.direction === 'inbound'\"\n [class.text-success]=\"row.direction === 'inbound'\"\n [class.bg-primary-50]=\"row.direction === 'outbound'\"\n [class.text-primary]=\"row.direction === 'outbound'\"\n [smartTooltip]=\"row.directionTitle\"\n >\n <ed-icon [name]=\"row.directionIcon\" [size]=\"12\" color=\"currentColor\" />\n </span>\n </td>\n\n <td>\n <span\n class=\"inline-block min-w-0 max-w-56 truncate fs-sm font-medium text-light\"\n [smartTooltip]=\"row.reason\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ row.reason }}</span>\n </td>\n\n <td>\n <ed-badge-2 [attr.variant]=\"row.reviewed ? 'success' : 'warning'\" pill uppercase>\n {{ row.reviewed ? 'Reviewed' : 'Needs review' }}\n </ed-badge-2>\n </td>\n\n <td>\n @if (row.resolution) {\n <ed-badge-2 [attr.variant]=\"row.resolutionVariant\" pill uppercase>\n {{ row.resolutionLabel }}\n </ed-badge-2>\n }\n </td>\n\n <td>\n <div class=\"flex min-w-0 max-w-80 flex-wrap gap-2xs\">\n @for (chip of row.resultChips; track chip.label) {\n <span\n class=\"inline-flex h-5 max-w-48 min-w-0 items-center gap-2xs rounded bg-light px-2xs fs-xs font-medium text-dark\"\n >\n <ed-icon [name]=\"chip.icon\" [size]=\"12\" color=\"currentColor\" />\n <span\n class=\"min-w-0 truncate\"\n [smartTooltip]=\"chip.label\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ chip.label }}</span>\n </span>\n } @empty {\n <span class=\"fs-sm text-light\">—</span>\n }\n </div>\n </td>\n\n <td class=\"whitespace-nowrap tabular-nums fs-xs font-medium text-light\">\n {{ row.durationLabel }}\n </td>\n </tr>\n } @empty {\n <tr class=\"table-no-data\">\n <td colspan=\"8\" class=\"py-base text-center fs-sm text-light\">No recent calls.</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </article>\n }\n </div>\n</div>\n"],"names":[],"mappings":"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"}