@edvak99/voice-receptionist-widget 1.1.8 → 1.1.9

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 (21) hide show
  1. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-DTSc452x.mjs +388 -0
  2. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-DTSc452x.mjs.map +1 -0
  3. package/fesm2022/{edvak99-voice-receptionist-widget-call-history-detail-page.component-BuNyPmhn.mjs → edvak99-voice-receptionist-widget-call-history-detail-page.component-BkT3Qfsk.mjs} +3 -3
  4. package/fesm2022/{edvak99-voice-receptionist-widget-call-history-detail-page.component-BuNyPmhn.mjs.map → edvak99-voice-receptionist-widget-call-history-detail-page.component-BkT3Qfsk.mjs.map} +1 -1
  5. package/fesm2022/edvak99-voice-receptionist-widget-settings-page.component-9qSZL9mc.mjs +1059 -0
  6. package/fesm2022/edvak99-voice-receptionist-widget-settings-page.component-9qSZL9mc.mjs.map +1 -0
  7. package/fesm2022/edvak99-voice-receptionist-widget-task-detail-drawer.component-B3KmFJNH.mjs +194 -0
  8. package/fesm2022/edvak99-voice-receptionist-widget-task-detail-drawer.component-B3KmFJNH.mjs.map +1 -0
  9. package/fesm2022/{edvak99-voice-receptionist-widget-tasks-page.component-Dfz-_0Jz.mjs → edvak99-voice-receptionist-widget-tasks-page.component-D4bWKglj.mjs} +5 -181
  10. package/fesm2022/edvak99-voice-receptionist-widget-tasks-page.component-D4bWKglj.mjs.map +1 -0
  11. package/fesm2022/edvak99-voice-receptionist-widget.mjs +5 -5
  12. package/lib/components/task-detail-drawer/task-detail-drawer.component.d.ts +1 -0
  13. package/lib/pages/activities-page/activities-page.component.d.ts +6 -0
  14. package/lib/pages/settings-page/settings-page.component.d.ts +11 -2
  15. package/lib/pages/settings-page/tts-voice-presets.d.ts +2 -0
  16. package/package.json +1 -1
  17. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-CtaPoY1k.mjs +0 -344
  18. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-CtaPoY1k.mjs.map +0 -1
  19. package/fesm2022/edvak99-voice-receptionist-widget-settings-page.component-CspheAr8.mjs +0 -992
  20. package/fesm2022/edvak99-voice-receptionist-widget-settings-page.component-CspheAr8.mjs.map +0 -1
  21. package/fesm2022/edvak99-voice-receptionist-widget-tasks-page.component-Dfz-_0Jz.mjs.map +0 -1
@@ -0,0 +1,388 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { ActivatedRoute, Router } from '@angular/router';
4
+ import { T as TaskDetailDrawerComponent } from './edvak99-voice-receptionist-widget-task-detail-drawer.component-B3KmFJNH.mjs';
5
+ import { A as AiReceptionistApiService, D as DEFAULT_PAGE_SIZE, j as totalPages, d as ageFromDob, l as initialsFromName } from './edvak99-voice-receptionist-widget-ai-receptionist-api.service-CK6tM862.mjs';
6
+ import { E as EdsAvatarComponent } from './edvak99-voice-receptionist-widget-eds-avatar.component-BJs_TH8X.mjs';
7
+ import { EdsButtonComponent, EdsIconComponent } from './edvak99-voice-receptionist-widget.mjs';
8
+
9
+ const TABS = [
10
+ { id: 'task_created', label: 'Tasks' },
11
+ { id: 'appointment_booked', label: 'Appointments' },
12
+ { id: 'patient_created', label: 'Registrations' },
13
+ ];
14
+ const AVATAR_TONES = ['green', 'amber', 'brand', 'violet', 'rose'];
15
+ class ActivitiesPageComponent {
16
+ constructor() {
17
+ this.api = inject(AiReceptionistApiService);
18
+ this.route = inject(ActivatedRoute);
19
+ this.router = inject(Router);
20
+ this.tabs = TABS;
21
+ this.pageSize = DEFAULT_PAGE_SIZE;
22
+ this.items = signal([]);
23
+ this.total = signal(0);
24
+ this.page = signal(1);
25
+ this.activeTab = signal('appointment_booked');
26
+ this.callIdFilter = signal(null);
27
+ this.loading = signal(true);
28
+ this.loadError = signal(null);
29
+ this.selectedTask = signal(null);
30
+ }
31
+ ngOnInit() {
32
+ const callId = this.route.snapshot.queryParamMap.get('callId')?.trim() || null;
33
+ if (callId)
34
+ this.callIdFilter.set(callId);
35
+ const tabParam = (this.route.snapshot.queryParamMap.get('tab') || '').trim().toLowerCase();
36
+ const tabFromQuery = this.tabFromQuery(tabParam);
37
+ if (tabFromQuery)
38
+ this.activeTab.set(tabFromQuery);
39
+ this.load();
40
+ }
41
+ setTab(tab) {
42
+ if (this.activeTab() === tab)
43
+ return;
44
+ this.activeTab.set(tab);
45
+ this.page.set(1);
46
+ void this.router.navigate([], {
47
+ relativeTo: this.route,
48
+ queryParams: { tab: this.tabQueryValue(tab) },
49
+ queryParamsHandling: 'merge',
50
+ replaceUrl: true,
51
+ });
52
+ this.load();
53
+ }
54
+ tabFromQuery(raw) {
55
+ switch (raw) {
56
+ case 'tasks':
57
+ case 'task':
58
+ case 'task_created':
59
+ return 'task_created';
60
+ case 'appointments':
61
+ case 'appointment':
62
+ case 'appointment_booked':
63
+ return 'appointment_booked';
64
+ case 'registrations':
65
+ case 'registration':
66
+ case 'patient_created':
67
+ return 'patient_created';
68
+ default:
69
+ return null;
70
+ }
71
+ }
72
+ tabQueryValue(tab) {
73
+ switch (tab) {
74
+ case 'task_created':
75
+ return 'tasks';
76
+ case 'patient_created':
77
+ return 'registrations';
78
+ default:
79
+ return 'appointments';
80
+ }
81
+ }
82
+ clearCallFilter() {
83
+ this.callIdFilter.set(null);
84
+ this.page.set(1);
85
+ this.load();
86
+ }
87
+ load() {
88
+ this.loading.set(true);
89
+ this.loadError.set(null);
90
+ const tab = this.activeTab();
91
+ this.api
92
+ .getActivities({
93
+ page: this.page(),
94
+ limit: DEFAULT_PAGE_SIZE,
95
+ types: tab,
96
+ callId: this.callIdFilter() || undefined,
97
+ })
98
+ .subscribe({
99
+ next: ({ items, total, page }) => {
100
+ this.items.set(items);
101
+ this.total.set(total);
102
+ this.page.set(page);
103
+ this.loading.set(false);
104
+ },
105
+ error: () => {
106
+ this.loading.set(false);
107
+ this.items.set([]);
108
+ this.total.set(0);
109
+ this.loadError.set('Activities feed is unavailable. Confirm GET /api/ai-receptionist/activities is deployed.');
110
+ },
111
+ });
112
+ }
113
+ totalPages() {
114
+ return totalPages(this.total(), DEFAULT_PAGE_SIZE);
115
+ }
116
+ prevPage() {
117
+ if (this.page() <= 1)
118
+ return;
119
+ this.page.update((p) => p - 1);
120
+ this.load();
121
+ }
122
+ nextPage() {
123
+ if (this.page() >= this.totalPages())
124
+ return;
125
+ this.page.update((p) => p + 1);
126
+ this.load();
127
+ }
128
+ historyLink(callId) {
129
+ return callId ? ['../history', callId] : null;
130
+ }
131
+ openCallHistory(callId, ev) {
132
+ if (!callId)
133
+ return;
134
+ if (ev && ev.target.closest('a,button'))
135
+ return;
136
+ void this.router.navigate(['../history', callId], { relativeTo: this.route });
137
+ }
138
+ openTask(item) {
139
+ this.selectedTask.set(this.activityToTask(item));
140
+ }
141
+ closeTaskDrawer() {
142
+ this.selectedTask.set(null);
143
+ }
144
+ onTaskStatusChange(status) {
145
+ const task = this.selectedTask();
146
+ if (!task)
147
+ return;
148
+ this.api.patchTask(task.id, status).subscribe({
149
+ next: ({ data }) => {
150
+ if (data) {
151
+ this.selectedTask.set(data);
152
+ }
153
+ else {
154
+ this.selectedTask.set({ ...task, status });
155
+ }
156
+ },
157
+ error: () => {
158
+ // Optimistic local update if patch fails (activity-sourced ids may not exist).
159
+ this.selectedTask.set({ ...task, status });
160
+ },
161
+ });
162
+ }
163
+ activityToTask(item) {
164
+ const priority = item.priority === 'urgent' || item.priority === 'high' ? 'urgent' : 'normal';
165
+ const created = this.parseDate(item.occurredAt)?.getTime() ?? Date.now();
166
+ return {
167
+ id: item.taskId || item.id,
168
+ created,
169
+ title: this.taskTitle(item),
170
+ type: 'task',
171
+ description: item.detail || '',
172
+ patient: item.patientName || 'Unknown caller',
173
+ priority,
174
+ status: 'open',
175
+ source: 'voice',
176
+ assignee: 'AI Receptionist',
177
+ callId: item.callId || undefined,
178
+ };
179
+ }
180
+ displayMrn(item) {
181
+ return item.patientMrn?.trim() || '—';
182
+ }
183
+ providerSpecialtyLabel(item) {
184
+ const s = item.providerSpecialty?.trim();
185
+ if (!s)
186
+ return null;
187
+ // Hide stray numeric IDs that sometimes land in specialty.
188
+ if (/^\d+(\.\d+)?$/.test(s))
189
+ return null;
190
+ return s;
191
+ }
192
+ /** Day-anchored stamp — a bare clock time gave no idea which day a row belonged to. */
193
+ timestampLabel(item) {
194
+ const start = this.parseDate(item.startAt || item.occurredAt);
195
+ if (!start)
196
+ return '—';
197
+ const stamp = `${this.formatDay(start)}, ${this.formatClock(start)}`;
198
+ const end = this.parseDate(item.endAt);
199
+ if (end && end.getTime() > start.getTime()) {
200
+ return `${stamp} – ${this.formatClock(end)}`;
201
+ }
202
+ return stamp;
203
+ }
204
+ durationLabel(item) {
205
+ const mins = item.durationMinutes;
206
+ if (mins == null || mins <= 0) {
207
+ if (item.startAt && item.endAt) {
208
+ const ms = Date.parse(item.endAt) - Date.parse(item.startAt);
209
+ if (Number.isFinite(ms) && ms > 0) {
210
+ return `${Math.round(ms / 60000)} MIN`;
211
+ }
212
+ }
213
+ return null;
214
+ }
215
+ return `${mins} MIN`;
216
+ }
217
+ categoryLabel(item) {
218
+ if (item.visitType)
219
+ return item.visitType;
220
+ switch (item.type) {
221
+ case 'appointment_booked':
222
+ return 'Appointment';
223
+ case 'patient_created':
224
+ return 'Registration';
225
+ case 'task_created':
226
+ return item.title && !/^task created$/i.test(item.title) ? item.title : 'Task';
227
+ default:
228
+ return item.title || 'Activity';
229
+ }
230
+ }
231
+ patientMeta(item) {
232
+ const parts = [];
233
+ const dob = item.patientDob;
234
+ const age = item.patientAge ?? (dob ? ageFromDob(dob) : null);
235
+ if (dob && age != null)
236
+ parts.push(`DOB: ${this.formatDob(dob)} · ${age}Y`);
237
+ else if (dob)
238
+ parts.push(`DOB: ${this.formatDob(dob)}`);
239
+ else if (age != null)
240
+ parts.push(`${age}Y`);
241
+ if (item.patientGender)
242
+ parts.push(item.patientGender);
243
+ return parts.length ? parts.join(' | ') : null;
244
+ }
245
+ patientInitials(item) {
246
+ return item.patientInitials || initialsFromName(item.patientName) || '?';
247
+ }
248
+ providerInitials(item) {
249
+ return item.providerInitials || initialsFromName(item.providerName) || '?';
250
+ }
251
+ avatarTone(key, salt) {
252
+ const raw = `${key || 'x'}:${salt}`;
253
+ let hash = 0;
254
+ for (let i = 0; i < raw.length; i++)
255
+ hash = (hash + raw.charCodeAt(i) * (i + 1)) % 997;
256
+ return AVATAR_TONES[hash % AVATAR_TONES.length];
257
+ }
258
+ insuranceState(item) {
259
+ if (item.hasInsurance === true)
260
+ return 'covered';
261
+ if (item.hasInsurance === false)
262
+ return 'none';
263
+ return 'unknown';
264
+ }
265
+ insuranceIcon(item) {
266
+ switch (this.insuranceState(item)) {
267
+ case 'covered':
268
+ return 'verified_user';
269
+ case 'none':
270
+ return 'gpp_bad';
271
+ default:
272
+ return 'gpp_maybe';
273
+ }
274
+ }
275
+ insuranceLabel(item) {
276
+ switch (this.insuranceState(item)) {
277
+ case 'covered':
278
+ return 'Insured';
279
+ case 'none':
280
+ return 'No insurance';
281
+ default:
282
+ return 'Unverified';
283
+ }
284
+ }
285
+ insuranceTitle(item) {
286
+ switch (this.insuranceState(item)) {
287
+ case 'covered':
288
+ return item.insuranceName ? `Insured — ${item.insuranceName}` : 'Insured';
289
+ case 'none':
290
+ return 'No insurance on file';
291
+ default:
292
+ return 'Insurance not verified';
293
+ }
294
+ }
295
+ isTaskRow(item) {
296
+ return item.type === 'task_created';
297
+ }
298
+ taskTitle(item) {
299
+ const title = (item.title || '').trim();
300
+ if (title && !/^task created$/i.test(title))
301
+ return title;
302
+ return item.visitType || 'Task';
303
+ }
304
+ priorityLabel(item) {
305
+ switch (item.priority) {
306
+ case 'urgent':
307
+ return 'Urgent';
308
+ case 'high':
309
+ return 'High';
310
+ case 'low':
311
+ return 'Low';
312
+ case 'medium':
313
+ case 'normal':
314
+ default:
315
+ return 'Medium';
316
+ }
317
+ }
318
+ priorityTone(item) {
319
+ switch (item.priority) {
320
+ case 'urgent':
321
+ return 'urgent';
322
+ case 'high':
323
+ return 'high';
324
+ case 'low':
325
+ return 'low';
326
+ default:
327
+ return 'medium';
328
+ }
329
+ }
330
+ isRegistrationTab() {
331
+ return this.activeTab() === 'patient_created';
332
+ }
333
+ emptyLabel() {
334
+ if (this.callIdFilter())
335
+ return 'No activities found for this call.';
336
+ switch (this.activeTab()) {
337
+ case 'task_created':
338
+ return 'No tasks created by the AI yet.';
339
+ case 'patient_created':
340
+ return 'No patient registrations yet.';
341
+ default:
342
+ return 'No appointments booked by the AI yet.';
343
+ }
344
+ }
345
+ parseDate(iso) {
346
+ if (!iso)
347
+ return null;
348
+ const d = new Date(iso);
349
+ return Number.isNaN(d.getTime()) ? null : d;
350
+ }
351
+ formatDay(d) {
352
+ const midnight = (x) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();
353
+ const now = new Date();
354
+ const days = Math.round((midnight(d) - midnight(now)) / 86_400_000);
355
+ if (days === 0)
356
+ return 'Today';
357
+ if (days === 1)
358
+ return 'Tomorrow';
359
+ if (days === -1)
360
+ return 'Yesterday';
361
+ return d.toLocaleDateString(undefined, d.getFullYear() === now.getFullYear()
362
+ ? { weekday: 'short', month: 'short', day: 'numeric' }
363
+ : { month: 'short', day: 'numeric', year: 'numeric' });
364
+ }
365
+ formatClock(d) {
366
+ return d.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
367
+ }
368
+ formatDob(iso) {
369
+ const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(iso.trim());
370
+ if (m)
371
+ return `${m[2]}-${m[3]}-${m[1]}`;
372
+ const d = new Date(iso);
373
+ if (Number.isNaN(d.getTime()))
374
+ return iso;
375
+ const mm = String(d.getMonth() + 1).padStart(2, '0');
376
+ const dd = String(d.getDate()).padStart(2, '0');
377
+ return `${mm}-${dd}-${d.getFullYear()}`;
378
+ }
379
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: ActivitiesPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
380
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: ActivitiesPageComponent, isStandalone: true, selector: "eds-activities-page", ngImport: i0, template: "<div class=\"eds-page activities-page\">\n <header class=\"mb-5\">\n <div>\n <h1 class=\"eds-h1\">Activities</h1>\n <p class=\"eds-body-sm\">Review all the activities done by the AI at one place</p>\n </div>\n </header>\n\n @if (callIdFilter(); as callId) {\n <div\n class=\"mb-4 flex flex-wrap items-center justify-between gap-3 rounded-lg bg-blue-50 px-4 py-3 text-sm font-normal leading-snug text-zinc-600\"\n role=\"status\"\n >\n <span>Showing activities for call <strong class=\"font-medium text-zinc-700\">{{ callId }}</strong></span>\n <button\n type=\"button\"\n class=\"cursor-pointer border-none bg-transparent px-0 py-1 text-sm font-medium text-blue-600 hover:underline\"\n (click)=\"clearCallFilter()\"\n >\n Clear filter\n </button>\n </div>\n }\n\n <nav class=\"mb-5 flex flex-wrap gap-2\" aria-label=\"Activity type\">\n @for (tab of tabs; track tab.id) {\n <button\n type=\"button\"\n [class]=\"\n activeTab() === tab.id\n ? 'cursor-pointer rounded-full border-none bg-blue-50 px-4 py-2 text-sm font-medium text-blue-600 transition-colors'\n : 'cursor-pointer rounded-full border-none bg-transparent px-4 py-2 text-sm font-medium text-zinc-500 transition-colors hover:bg-white hover:text-zinc-700'\n \"\n (click)=\"setTab(tab.id)\"\n >\n {{ tab.label }}\n </button>\n }\n </nav>\n\n @if (loading()) {\n <p class=\"eds-body-sm\">Loading activities\u2026</p>\n } @else if (loadError()) {\n <p class=\"text-sm text-red-700\" role=\"alert\">{{ loadError() }}</p>\n } @else {\n @if (activeTab() === 'task_created') {\n <div\n class=\"activities-page__col-head activities-page__col-head--tasks grid gap-x-7 gap-y-4 pb-2 text-sm font-semibold leading-tight text-zinc-600 max-lg:hidden\"\n aria-hidden=\"true\"\n >\n <span>Priority</span>\n <span>Task</span>\n <span>Patient / Caller</span>\n </div>\n } @else if (activeTab() === 'appointment_booked') {\n <div\n class=\"activities-page__col-head activities-page__col-head--appointments grid gap-x-7 gap-y-4 pb-2 text-sm font-semibold leading-tight text-zinc-600 max-lg:hidden\"\n aria-hidden=\"true\"\n >\n <span>When</span>\n <span>Patient</span>\n <span>Provider</span>\n <span class=\"justify-self-end text-right\">Insurance</span>\n </div>\n } @else if (activeTab() === 'patient_created') {\n <div\n class=\"activities-page__col-head activities-page__col-head--registration grid gap-x-7 gap-y-4 pb-2 text-sm font-semibold leading-tight text-zinc-600 max-lg:hidden\"\n aria-hidden=\"true\"\n >\n <span>When</span>\n <span>Patient</span>\n <span>MRN</span>\n <span class=\"justify-self-end text-right\">Insurance</span>\n </div>\n }\n\n <ul class=\"m-0 flex list-none flex-col gap-3 p-0\">\n @for (item of items(); track item.id; let i = $index) {\n @if (isTaskRow(item)) {\n <li\n class=\"activities-page__card activities-page__card--task grid cursor-pointer items-center gap-x-7 gap-y-4 rounded-xl border border-zinc-200 bg-white px-4 py-4 max-lg:gap-x-4 max-lg:gap-y-4 hover:border-blue-200 hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'View task: ' + taskTitle(item)\"\n (click)=\"openTask(item)\"\n (keyup.enter)=\"openTask(item)\"\n >\n <div class=\"inline-flex items-center gap-2 text-sm font-medium leading-snug text-zinc-700\" [attr.data-tone]=\"priorityTone(item)\">\n <span class=\"activities-page__priority-mark h-2.5 w-2.5 shrink-0 rotate-45 rounded-sm\" aria-hidden=\"true\"></span>\n <span class=\"capitalize\">{{ priorityLabel(item) }}</span>\n </div>\n\n <div class=\"text-sm font-medium leading-snug text-zinc-700 max-lg:col-span-full\">{{ taskTitle(item) }}</div>\n\n <div class=\"flex min-w-0 items-center gap-3 max-lg:col-span-full\">\n <eds-avatar\n shape=\"box\"\n [initials]=\"patientInitials(item)\"\n [tone]=\"avatarTone(item.patientId || item.patientName || item.id, i)\"\n />\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"truncate text-sm font-medium leading-snug text-zinc-700\">{{ item.patientName || 'Unknown caller' }}</span>\n @if (patientMeta(item); as meta) {\n <span class=\"truncate text-xs leading-snug text-zinc-500\">{{ meta }}</span>\n }\n </div>\n </div>\n </li>\n } @else if (isRegistrationTab()) {\n <li\n class=\"activities-page__card activities-page__card--registration grid items-center gap-x-7 gap-y-4 rounded-xl border border-zinc-200 bg-white px-4 py-4 max-lg:gap-x-4 max-lg:gap-y-4\"\n >\n <div class=\"min-w-0\">\n <div class=\"mb-1 flex flex-wrap items-center gap-2\">\n <span class=\"whitespace-nowrap text-base font-medium leading-snug text-zinc-700 max-md:whitespace-normal\">{{ timestampLabel(item) }}</span>\n </div>\n <p class=\"m-0 text-sm leading-snug text-zinc-500\">{{ categoryLabel(item) }}</p>\n </div>\n\n <div class=\"flex min-w-0 items-center gap-3 max-lg:col-span-full\">\n <eds-avatar\n shape=\"box\"\n [initials]=\"patientInitials(item)\"\n [tone]=\"avatarTone(item.patientId || item.patientName || item.id, i)\"\n />\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"truncate text-sm font-medium leading-snug text-zinc-700\">{{ item.patientName || 'Unknown patient' }}</span>\n @if (patientMeta(item); as meta) {\n <span class=\"truncate text-xs leading-snug text-zinc-500\">{{ meta }}</span>\n }\n </div>\n </div>\n\n <div class=\"text-sm font-normal leading-snug text-zinc-600\">{{ displayMrn(item) }}</div>\n\n <div class=\"flex items-center justify-end gap-2.5\">\n <span\n class=\"activities-page__insurance inline-flex h-8 w-8 items-center justify-center rounded-full border border-transparent max-md:px-1.5\"\n [attr.data-state]=\"insuranceState(item)\"\n [title]=\"insuranceTitle(item)\"\n [attr.aria-label]=\"insuranceLabel(item)\"\n >\n <eds-icon [name]=\"insuranceIcon(item)\" [size]=\"18\" />\n </span>\n </div>\n </li>\n } @else {\n <li\n [class]=\"\n 'activities-page__card grid items-center gap-x-7 gap-y-4 rounded-xl border border-zinc-200 bg-white px-4 py-4 max-lg:gap-x-4 max-lg:gap-y-4' +\n (item.callId\n ? ' cursor-pointer hover:border-blue-200 hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600'\n : '')\n \"\n [attr.role]=\"item.callId ? 'link' : null\"\n [attr.tabindex]=\"item.callId ? 0 : null\"\n (click)=\"openCallHistory(item.callId, $event)\"\n (keyup.enter)=\"openCallHistory(item.callId)\"\n >\n <div class=\"min-w-0\">\n <div class=\"mb-1 flex flex-wrap items-center gap-2\">\n <span class=\"whitespace-nowrap text-base font-medium leading-snug text-zinc-700 max-md:whitespace-normal\">{{ timestampLabel(item) }}</span>\n </div>\n <p class=\"m-0 text-sm leading-snug text-zinc-500\">{{ categoryLabel(item) }}</p>\n </div>\n\n <div class=\"flex min-w-0 items-center gap-3 max-lg:col-span-full\">\n <eds-avatar\n shape=\"box\"\n [initials]=\"patientInitials(item)\"\n [tone]=\"avatarTone(item.patientId || item.patientName || item.id, i)\"\n />\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"truncate text-sm font-medium leading-snug text-zinc-700\">{{ item.patientName || 'Unknown patient' }}</span>\n @if (patientMeta(item); as meta) {\n <span class=\"truncate text-xs leading-snug text-zinc-500\">{{ meta }}</span>\n }\n </div>\n </div>\n\n <div class=\"flex min-w-0 items-center gap-3 max-lg:col-span-full\">\n @if (item.providerName) {\n <eds-avatar\n shape=\"circle\"\n [initials]=\"providerInitials(item)\"\n [tone]=\"avatarTone(item.providerId || item.providerName, i + 3)\"\n />\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"truncate text-sm font-medium leading-snug text-zinc-700\">{{ item.providerName }}</span>\n @if (providerSpecialtyLabel(item); as specialty) {\n <span class=\"truncate text-xs leading-snug text-zinc-500\">{{ specialty }}</span>\n }\n </div>\n } @else {\n <div class=\"flex min-h-9 items-center\">\n <span class=\"truncate text-xs leading-snug text-zinc-500\">No provider assigned</span>\n </div>\n }\n </div>\n\n <div class=\"flex items-center justify-end gap-3\">\n <span\n class=\"activities-page__insurance inline-flex h-8 w-8 items-center justify-center rounded-full border border-transparent max-md:px-2\"\n [attr.data-state]=\"insuranceState(item)\"\n [title]=\"insuranceTitle(item)\"\n [attr.aria-label]=\"insuranceLabel(item)\"\n >\n <eds-icon [name]=\"insuranceIcon(item)\" [size]=\"18\" />\n </span>\n </div>\n </li>\n }\n } @empty {\n <li class=\"rounded-xl border border-dashed border-zinc-200 bg-white px-4 py-10 text-center text-sm leading-snug text-zinc-500\">\n {{ emptyLabel() }}\n </li>\n }\n </ul>\n\n @if (total() > pageSize) {\n <footer class=\"mt-4 flex flex-wrap items-center justify-between gap-3\">\n <span class=\"eds-body-sm\">\n Page {{ page() }} of {{ totalPages() }} \u00B7 {{ total() }} total\n </span>\n <div class=\"flex gap-2\">\n <eds-button variant=\"secondary\" [disabled]=\"page() <= 1\" (click)=\"prevPage()\">Previous</eds-button>\n <eds-button variant=\"secondary\" [disabled]=\"page() >= totalPages()\" (click)=\"nextPage()\">Next</eds-button>\n </div>\n </footer>\n }\n }\n</div>\n\n@if (selectedTask(); as task) {\n <eds-task-detail-drawer\n [task]=\"task\"\n (closed)=\"closeTaskDrawer()\"\n (statusChange)=\"onTaskStatusChange($event)\"\n />\n}\n", styles: [".activities-page__card{grid-template-columns:minmax(180px,1.1fr) minmax(200px,1.2fr) minmax(200px,1.2fr) auto}.activities-page__card--task{grid-template-columns:minmax(120px,.7fr) minmax(220px,1.4fr) minmax(240px,1.3fr)}.activities-page__card--registration{grid-template-columns:minmax(180px,1.1fr) minmax(240px,1.4fr) minmax(120px,.8fr) auto}.activities-page__col-head{box-sizing:border-box;border:1px solid transparent;padding-left:1rem;padding-right:1rem;padding-bottom:.5rem;column-gap:1.75rem}.activities-page__col-head--tasks{grid-template-columns:minmax(120px,.7fr) minmax(220px,1.4fr) minmax(240px,1.3fr)}.activities-page__col-head--appointments{grid-template-columns:minmax(180px,1.1fr) minmax(200px,1.2fr) minmax(200px,1.2fr) auto}.activities-page__col-head--registration{grid-template-columns:minmax(180px,1.1fr) minmax(240px,1.4fr) minmax(120px,.8fr) auto}.activities-page__priority-mark{background:#f59e0b}[data-tone=urgent] .activities-page__priority-mark{background:#dc2626}[data-tone=high] .activities-page__priority-mark{background:#ea580c}[data-tone=medium] .activities-page__priority-mark{background:#f59e0b}[data-tone=low] .activities-page__priority-mark{background:#94a3b8}.activities-page__insurance[data-state=covered]{background:#ecfdf5;border-color:#bbf7d0;color:#15803d}.activities-page__insurance[data-state=none]{background:#fef2f2;border-color:#fecaca;color:#b91c1c}.activities-page__insurance[data-state=unknown]{background:#f4f4f5;border-color:#e4e4e7;color:#71717a}@media(max-width:1023px){.activities-page__card,.activities-page__card--task{grid-template-columns:1fr auto}}\n"], dependencies: [{ kind: "component", type: EdsAvatarComponent, selector: "eds-avatar", inputs: ["initials", "tone", "shape", "gradient"] }, { kind: "component", type: EdsButtonComponent, selector: "eds-button", inputs: ["variant", "type", "disabled"] }, { kind: "component", type: EdsIconComponent, selector: "eds-icon", inputs: ["name", "size", "fill", "weight"] }, { kind: "component", type: TaskDetailDrawerComponent, selector: "eds-task-detail-drawer", inputs: ["task"], outputs: ["closed", "statusChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
381
+ }
382
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: ActivitiesPageComponent, decorators: [{
383
+ type: Component,
384
+ args: [{ selector: 'eds-activities-page', imports: [EdsAvatarComponent, EdsButtonComponent, EdsIconComponent, TaskDetailDrawerComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"eds-page activities-page\">\n <header class=\"mb-5\">\n <div>\n <h1 class=\"eds-h1\">Activities</h1>\n <p class=\"eds-body-sm\">Review all the activities done by the AI at one place</p>\n </div>\n </header>\n\n @if (callIdFilter(); as callId) {\n <div\n class=\"mb-4 flex flex-wrap items-center justify-between gap-3 rounded-lg bg-blue-50 px-4 py-3 text-sm font-normal leading-snug text-zinc-600\"\n role=\"status\"\n >\n <span>Showing activities for call <strong class=\"font-medium text-zinc-700\">{{ callId }}</strong></span>\n <button\n type=\"button\"\n class=\"cursor-pointer border-none bg-transparent px-0 py-1 text-sm font-medium text-blue-600 hover:underline\"\n (click)=\"clearCallFilter()\"\n >\n Clear filter\n </button>\n </div>\n }\n\n <nav class=\"mb-5 flex flex-wrap gap-2\" aria-label=\"Activity type\">\n @for (tab of tabs; track tab.id) {\n <button\n type=\"button\"\n [class]=\"\n activeTab() === tab.id\n ? 'cursor-pointer rounded-full border-none bg-blue-50 px-4 py-2 text-sm font-medium text-blue-600 transition-colors'\n : 'cursor-pointer rounded-full border-none bg-transparent px-4 py-2 text-sm font-medium text-zinc-500 transition-colors hover:bg-white hover:text-zinc-700'\n \"\n (click)=\"setTab(tab.id)\"\n >\n {{ tab.label }}\n </button>\n }\n </nav>\n\n @if (loading()) {\n <p class=\"eds-body-sm\">Loading activities\u2026</p>\n } @else if (loadError()) {\n <p class=\"text-sm text-red-700\" role=\"alert\">{{ loadError() }}</p>\n } @else {\n @if (activeTab() === 'task_created') {\n <div\n class=\"activities-page__col-head activities-page__col-head--tasks grid gap-x-7 gap-y-4 pb-2 text-sm font-semibold leading-tight text-zinc-600 max-lg:hidden\"\n aria-hidden=\"true\"\n >\n <span>Priority</span>\n <span>Task</span>\n <span>Patient / Caller</span>\n </div>\n } @else if (activeTab() === 'appointment_booked') {\n <div\n class=\"activities-page__col-head activities-page__col-head--appointments grid gap-x-7 gap-y-4 pb-2 text-sm font-semibold leading-tight text-zinc-600 max-lg:hidden\"\n aria-hidden=\"true\"\n >\n <span>When</span>\n <span>Patient</span>\n <span>Provider</span>\n <span class=\"justify-self-end text-right\">Insurance</span>\n </div>\n } @else if (activeTab() === 'patient_created') {\n <div\n class=\"activities-page__col-head activities-page__col-head--registration grid gap-x-7 gap-y-4 pb-2 text-sm font-semibold leading-tight text-zinc-600 max-lg:hidden\"\n aria-hidden=\"true\"\n >\n <span>When</span>\n <span>Patient</span>\n <span>MRN</span>\n <span class=\"justify-self-end text-right\">Insurance</span>\n </div>\n }\n\n <ul class=\"m-0 flex list-none flex-col gap-3 p-0\">\n @for (item of items(); track item.id; let i = $index) {\n @if (isTaskRow(item)) {\n <li\n class=\"activities-page__card activities-page__card--task grid cursor-pointer items-center gap-x-7 gap-y-4 rounded-xl border border-zinc-200 bg-white px-4 py-4 max-lg:gap-x-4 max-lg:gap-y-4 hover:border-blue-200 hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'View task: ' + taskTitle(item)\"\n (click)=\"openTask(item)\"\n (keyup.enter)=\"openTask(item)\"\n >\n <div class=\"inline-flex items-center gap-2 text-sm font-medium leading-snug text-zinc-700\" [attr.data-tone]=\"priorityTone(item)\">\n <span class=\"activities-page__priority-mark h-2.5 w-2.5 shrink-0 rotate-45 rounded-sm\" aria-hidden=\"true\"></span>\n <span class=\"capitalize\">{{ priorityLabel(item) }}</span>\n </div>\n\n <div class=\"text-sm font-medium leading-snug text-zinc-700 max-lg:col-span-full\">{{ taskTitle(item) }}</div>\n\n <div class=\"flex min-w-0 items-center gap-3 max-lg:col-span-full\">\n <eds-avatar\n shape=\"box\"\n [initials]=\"patientInitials(item)\"\n [tone]=\"avatarTone(item.patientId || item.patientName || item.id, i)\"\n />\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"truncate text-sm font-medium leading-snug text-zinc-700\">{{ item.patientName || 'Unknown caller' }}</span>\n @if (patientMeta(item); as meta) {\n <span class=\"truncate text-xs leading-snug text-zinc-500\">{{ meta }}</span>\n }\n </div>\n </div>\n </li>\n } @else if (isRegistrationTab()) {\n <li\n class=\"activities-page__card activities-page__card--registration grid items-center gap-x-7 gap-y-4 rounded-xl border border-zinc-200 bg-white px-4 py-4 max-lg:gap-x-4 max-lg:gap-y-4\"\n >\n <div class=\"min-w-0\">\n <div class=\"mb-1 flex flex-wrap items-center gap-2\">\n <span class=\"whitespace-nowrap text-base font-medium leading-snug text-zinc-700 max-md:whitespace-normal\">{{ timestampLabel(item) }}</span>\n </div>\n <p class=\"m-0 text-sm leading-snug text-zinc-500\">{{ categoryLabel(item) }}</p>\n </div>\n\n <div class=\"flex min-w-0 items-center gap-3 max-lg:col-span-full\">\n <eds-avatar\n shape=\"box\"\n [initials]=\"patientInitials(item)\"\n [tone]=\"avatarTone(item.patientId || item.patientName || item.id, i)\"\n />\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"truncate text-sm font-medium leading-snug text-zinc-700\">{{ item.patientName || 'Unknown patient' }}</span>\n @if (patientMeta(item); as meta) {\n <span class=\"truncate text-xs leading-snug text-zinc-500\">{{ meta }}</span>\n }\n </div>\n </div>\n\n <div class=\"text-sm font-normal leading-snug text-zinc-600\">{{ displayMrn(item) }}</div>\n\n <div class=\"flex items-center justify-end gap-2.5\">\n <span\n class=\"activities-page__insurance inline-flex h-8 w-8 items-center justify-center rounded-full border border-transparent max-md:px-1.5\"\n [attr.data-state]=\"insuranceState(item)\"\n [title]=\"insuranceTitle(item)\"\n [attr.aria-label]=\"insuranceLabel(item)\"\n >\n <eds-icon [name]=\"insuranceIcon(item)\" [size]=\"18\" />\n </span>\n </div>\n </li>\n } @else {\n <li\n [class]=\"\n 'activities-page__card grid items-center gap-x-7 gap-y-4 rounded-xl border border-zinc-200 bg-white px-4 py-4 max-lg:gap-x-4 max-lg:gap-y-4' +\n (item.callId\n ? ' cursor-pointer hover:border-blue-200 hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600'\n : '')\n \"\n [attr.role]=\"item.callId ? 'link' : null\"\n [attr.tabindex]=\"item.callId ? 0 : null\"\n (click)=\"openCallHistory(item.callId, $event)\"\n (keyup.enter)=\"openCallHistory(item.callId)\"\n >\n <div class=\"min-w-0\">\n <div class=\"mb-1 flex flex-wrap items-center gap-2\">\n <span class=\"whitespace-nowrap text-base font-medium leading-snug text-zinc-700 max-md:whitespace-normal\">{{ timestampLabel(item) }}</span>\n </div>\n <p class=\"m-0 text-sm leading-snug text-zinc-500\">{{ categoryLabel(item) }}</p>\n </div>\n\n <div class=\"flex min-w-0 items-center gap-3 max-lg:col-span-full\">\n <eds-avatar\n shape=\"box\"\n [initials]=\"patientInitials(item)\"\n [tone]=\"avatarTone(item.patientId || item.patientName || item.id, i)\"\n />\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"truncate text-sm font-medium leading-snug text-zinc-700\">{{ item.patientName || 'Unknown patient' }}</span>\n @if (patientMeta(item); as meta) {\n <span class=\"truncate text-xs leading-snug text-zinc-500\">{{ meta }}</span>\n }\n </div>\n </div>\n\n <div class=\"flex min-w-0 items-center gap-3 max-lg:col-span-full\">\n @if (item.providerName) {\n <eds-avatar\n shape=\"circle\"\n [initials]=\"providerInitials(item)\"\n [tone]=\"avatarTone(item.providerId || item.providerName, i + 3)\"\n />\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"truncate text-sm font-medium leading-snug text-zinc-700\">{{ item.providerName }}</span>\n @if (providerSpecialtyLabel(item); as specialty) {\n <span class=\"truncate text-xs leading-snug text-zinc-500\">{{ specialty }}</span>\n }\n </div>\n } @else {\n <div class=\"flex min-h-9 items-center\">\n <span class=\"truncate text-xs leading-snug text-zinc-500\">No provider assigned</span>\n </div>\n }\n </div>\n\n <div class=\"flex items-center justify-end gap-3\">\n <span\n class=\"activities-page__insurance inline-flex h-8 w-8 items-center justify-center rounded-full border border-transparent max-md:px-2\"\n [attr.data-state]=\"insuranceState(item)\"\n [title]=\"insuranceTitle(item)\"\n [attr.aria-label]=\"insuranceLabel(item)\"\n >\n <eds-icon [name]=\"insuranceIcon(item)\" [size]=\"18\" />\n </span>\n </div>\n </li>\n }\n } @empty {\n <li class=\"rounded-xl border border-dashed border-zinc-200 bg-white px-4 py-10 text-center text-sm leading-snug text-zinc-500\">\n {{ emptyLabel() }}\n </li>\n }\n </ul>\n\n @if (total() > pageSize) {\n <footer class=\"mt-4 flex flex-wrap items-center justify-between gap-3\">\n <span class=\"eds-body-sm\">\n Page {{ page() }} of {{ totalPages() }} \u00B7 {{ total() }} total\n </span>\n <div class=\"flex gap-2\">\n <eds-button variant=\"secondary\" [disabled]=\"page() <= 1\" (click)=\"prevPage()\">Previous</eds-button>\n <eds-button variant=\"secondary\" [disabled]=\"page() >= totalPages()\" (click)=\"nextPage()\">Next</eds-button>\n </div>\n </footer>\n }\n }\n</div>\n\n@if (selectedTask(); as task) {\n <eds-task-detail-drawer\n [task]=\"task\"\n (closed)=\"closeTaskDrawer()\"\n (statusChange)=\"onTaskStatusChange($event)\"\n />\n}\n", styles: [".activities-page__card{grid-template-columns:minmax(180px,1.1fr) minmax(200px,1.2fr) minmax(200px,1.2fr) auto}.activities-page__card--task{grid-template-columns:minmax(120px,.7fr) minmax(220px,1.4fr) minmax(240px,1.3fr)}.activities-page__card--registration{grid-template-columns:minmax(180px,1.1fr) minmax(240px,1.4fr) minmax(120px,.8fr) auto}.activities-page__col-head{box-sizing:border-box;border:1px solid transparent;padding-left:1rem;padding-right:1rem;padding-bottom:.5rem;column-gap:1.75rem}.activities-page__col-head--tasks{grid-template-columns:minmax(120px,.7fr) minmax(220px,1.4fr) minmax(240px,1.3fr)}.activities-page__col-head--appointments{grid-template-columns:minmax(180px,1.1fr) minmax(200px,1.2fr) minmax(200px,1.2fr) auto}.activities-page__col-head--registration{grid-template-columns:minmax(180px,1.1fr) minmax(240px,1.4fr) minmax(120px,.8fr) auto}.activities-page__priority-mark{background:#f59e0b}[data-tone=urgent] .activities-page__priority-mark{background:#dc2626}[data-tone=high] .activities-page__priority-mark{background:#ea580c}[data-tone=medium] .activities-page__priority-mark{background:#f59e0b}[data-tone=low] .activities-page__priority-mark{background:#94a3b8}.activities-page__insurance[data-state=covered]{background:#ecfdf5;border-color:#bbf7d0;color:#15803d}.activities-page__insurance[data-state=none]{background:#fef2f2;border-color:#fecaca;color:#b91c1c}.activities-page__insurance[data-state=unknown]{background:#f4f4f5;border-color:#e4e4e7;color:#71717a}@media(max-width:1023px){.activities-page__card,.activities-page__card--task{grid-template-columns:1fr auto}}\n"] }]
385
+ }] });
386
+
387
+ export { ActivitiesPageComponent };
388
+ //# sourceMappingURL=edvak99-voice-receptionist-widget-activities-page.component-DTSc452x.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edvak99-voice-receptionist-widget-activities-page.component-DTSc452x.mjs","sources":["../../../projects/voice-receptionist-widget/src/lib/pages/activities-page/activities-page.component.ts","../../../projects/voice-receptionist-widget/src/lib/pages/activities-page/activities-page.component.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, OnInit, inject, signal } from '@angular/core';\nimport { ActivatedRoute, Router } from '@angular/router';\n\nimport { TaskDetailDrawerComponent } from '../../components/task-detail-drawer/task-detail-drawer.component';\nimport {\n ActivitiesTab,\n AgentActivity,\n initialsFromName,\n} from '../../models/agent-activity.types';\nimport { TaskItem, TaskStatus } from '../../models/ai-receptionist.types';\nimport { DEFAULT_PAGE_SIZE, totalPages as calcTotalPages } from '../../models/pagination';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport { ageFromDob } from '../../utils/call-history-display.util';\nimport { EdsAvatarComponent } from '../../ui/eds-avatar.component';\nimport { EdsButtonComponent } from '../../ui/eds-button.component';\nimport { EdsIconComponent } from '../../ui/eds-icon.component';\n\ntype TabId = ActivitiesTab;\n\nconst TABS: { id: TabId; label: string }[] = [\n { id: 'task_created', label: 'Tasks' },\n { id: 'appointment_booked', label: 'Appointments' },\n { id: 'patient_created', label: 'Registrations' },\n];\n\nconst AVATAR_TONES = ['green', 'amber', 'brand', 'violet', 'rose'] as const;\n\n@Component({\n selector: 'eds-activities-page',\n imports: [EdsAvatarComponent, EdsButtonComponent, EdsIconComponent, TaskDetailDrawerComponent],\n templateUrl: './activities-page.component.html',\n styleUrl: './activities-page.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ActivitiesPageComponent implements OnInit {\n private readonly api = inject(AiReceptionistApiService);\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n\n protected readonly tabs = TABS;\n protected readonly pageSize = DEFAULT_PAGE_SIZE;\n protected readonly items = signal<AgentActivity[]>([]);\n protected readonly total = signal(0);\n protected readonly page = signal(1);\n protected readonly activeTab = signal<TabId>('appointment_booked');\n protected readonly callIdFilter = signal<string | null>(null);\n protected readonly loading = signal(true);\n protected readonly loadError = signal<string | null>(null);\n protected readonly selectedTask = signal<TaskItem | null>(null);\n\n ngOnInit(): void {\n const callId = this.route.snapshot.queryParamMap.get('callId')?.trim() || null;\n if (callId) this.callIdFilter.set(callId);\n\n const tabParam = (this.route.snapshot.queryParamMap.get('tab') || '').trim().toLowerCase();\n const tabFromQuery = this.tabFromQuery(tabParam);\n if (tabFromQuery) this.activeTab.set(tabFromQuery);\n\n this.load();\n }\n\n protected setTab(tab: TabId): void {\n if (this.activeTab() === tab) return;\n this.activeTab.set(tab);\n this.page.set(1);\n void this.router.navigate([], {\n relativeTo: this.route,\n queryParams: { tab: this.tabQueryValue(tab) },\n queryParamsHandling: 'merge',\n replaceUrl: true,\n });\n this.load();\n }\n\n private tabFromQuery(raw: string): TabId | null {\n switch (raw) {\n case 'tasks':\n case 'task':\n case 'task_created':\n return 'task_created';\n case 'appointments':\n case 'appointment':\n case 'appointment_booked':\n return 'appointment_booked';\n case 'registrations':\n case 'registration':\n case 'patient_created':\n return 'patient_created';\n default:\n return null;\n }\n }\n\n private tabQueryValue(tab: TabId): string {\n switch (tab) {\n case 'task_created':\n return 'tasks';\n case 'patient_created':\n return 'registrations';\n default:\n return 'appointments';\n }\n }\n\n protected clearCallFilter(): void {\n this.callIdFilter.set(null);\n this.page.set(1);\n this.load();\n }\n\n protected load(): void {\n this.loading.set(true);\n this.loadError.set(null);\n const tab = this.activeTab();\n this.api\n .getActivities({\n page: this.page(),\n limit: DEFAULT_PAGE_SIZE,\n types: tab,\n callId: this.callIdFilter() || undefined,\n })\n .subscribe({\n next: ({ items, total, page }) => {\n this.items.set(items);\n this.total.set(total);\n this.page.set(page);\n this.loading.set(false);\n },\n error: () => {\n this.loading.set(false);\n this.items.set([]);\n this.total.set(0);\n this.loadError.set(\n 'Activities feed is unavailable. Confirm GET /api/ai-receptionist/activities is deployed.',\n );\n },\n });\n }\n\n protected totalPages(): number {\n return calcTotalPages(this.total(), DEFAULT_PAGE_SIZE);\n }\n\n protected prevPage(): void {\n if (this.page() <= 1) return;\n this.page.update((p) => p - 1);\n this.load();\n }\n\n protected nextPage(): void {\n if (this.page() >= this.totalPages()) return;\n this.page.update((p) => p + 1);\n this.load();\n }\n\n protected historyLink(callId: string | null | undefined): string[] | null {\n return callId ? ['../history', callId] : null;\n }\n\n protected openCallHistory(callId: string | null | undefined, ev?: Event): void {\n if (!callId) return;\n if (ev && (ev.target as HTMLElement).closest('a,button')) return;\n void this.router.navigate(['../history', callId], { relativeTo: this.route });\n }\n\n protected openTask(item: AgentActivity): void {\n this.selectedTask.set(this.activityToTask(item));\n }\n\n protected closeTaskDrawer(): void {\n this.selectedTask.set(null);\n }\n\n protected onTaskStatusChange(status: TaskStatus): void {\n const task = this.selectedTask();\n if (!task) return;\n this.api.patchTask(task.id, status).subscribe({\n next: ({ data }) => {\n if (data) {\n this.selectedTask.set(data);\n } else {\n this.selectedTask.set({ ...task, status });\n }\n },\n error: () => {\n // Optimistic local update if patch fails (activity-sourced ids may not exist).\n this.selectedTask.set({ ...task, status });\n },\n });\n }\n\n private activityToTask(item: AgentActivity): TaskItem {\n const priority =\n item.priority === 'urgent' || item.priority === 'high' ? 'urgent' : 'normal';\n const created = this.parseDate(item.occurredAt)?.getTime() ?? Date.now();\n return {\n id: item.taskId || item.id,\n created,\n title: this.taskTitle(item),\n type: 'task',\n description: item.detail || '',\n patient: item.patientName || 'Unknown caller',\n priority,\n status: 'open',\n source: 'voice',\n assignee: 'AI Receptionist',\n callId: item.callId || undefined,\n };\n }\n\n protected displayMrn(item: AgentActivity): string {\n return item.patientMrn?.trim() || '—';\n }\n\n protected providerSpecialtyLabel(item: AgentActivity): string | null {\n const s = item.providerSpecialty?.trim();\n if (!s) return null;\n // Hide stray numeric IDs that sometimes land in specialty.\n if (/^\\d+(\\.\\d+)?$/.test(s)) return null;\n return s;\n }\n\n /** Day-anchored stamp — a bare clock time gave no idea which day a row belonged to. */\n protected timestampLabel(item: AgentActivity): string {\n const start = this.parseDate(item.startAt || item.occurredAt);\n if (!start) return '—';\n const stamp = `${this.formatDay(start)}, ${this.formatClock(start)}`;\n const end = this.parseDate(item.endAt);\n if (end && end.getTime() > start.getTime()) {\n return `${stamp} – ${this.formatClock(end)}`;\n }\n return stamp;\n }\n\n protected durationLabel(item: AgentActivity): string | null {\n const mins = item.durationMinutes;\n if (mins == null || mins <= 0) {\n if (item.startAt && item.endAt) {\n const ms = Date.parse(item.endAt) - Date.parse(item.startAt);\n if (Number.isFinite(ms) && ms > 0) {\n return `${Math.round(ms / 60000)} MIN`;\n }\n }\n return null;\n }\n return `${mins} MIN`;\n }\n\n protected categoryLabel(item: AgentActivity): string {\n if (item.visitType) return item.visitType;\n switch (item.type) {\n case 'appointment_booked':\n return 'Appointment';\n case 'patient_created':\n return 'Registration';\n case 'task_created':\n return item.title && !/^task created$/i.test(item.title) ? item.title : 'Task';\n default:\n return item.title || 'Activity';\n }\n }\n\n protected patientMeta(item: AgentActivity): string | null {\n const parts: string[] = [];\n const dob = item.patientDob;\n const age = item.patientAge ?? (dob ? ageFromDob(dob) : null);\n if (dob && age != null) parts.push(`DOB: ${this.formatDob(dob)} · ${age}Y`);\n else if (dob) parts.push(`DOB: ${this.formatDob(dob)}`);\n else if (age != null) parts.push(`${age}Y`);\n if (item.patientGender) parts.push(item.patientGender);\n return parts.length ? parts.join(' | ') : null;\n }\n\n protected patientInitials(item: AgentActivity): string {\n return item.patientInitials || initialsFromName(item.patientName) || '?';\n }\n\n protected providerInitials(item: AgentActivity): string {\n return item.providerInitials || initialsFromName(item.providerName) || '?';\n }\n\n protected avatarTone(key: string | null | undefined, salt: number): string {\n const raw = `${key || 'x'}:${salt}`;\n let hash = 0;\n for (let i = 0; i < raw.length; i++) hash = (hash + raw.charCodeAt(i) * (i + 1)) % 997;\n return AVATAR_TONES[hash % AVATAR_TONES.length];\n }\n\n protected insuranceState(item: AgentActivity): 'covered' | 'none' | 'unknown' {\n if (item.hasInsurance === true) return 'covered';\n if (item.hasInsurance === false) return 'none';\n return 'unknown';\n }\n\n protected insuranceIcon(item: AgentActivity): string {\n switch (this.insuranceState(item)) {\n case 'covered':\n return 'verified_user';\n case 'none':\n return 'gpp_bad';\n default:\n return 'gpp_maybe';\n }\n }\n\n protected insuranceLabel(item: AgentActivity): string {\n switch (this.insuranceState(item)) {\n case 'covered':\n return 'Insured';\n case 'none':\n return 'No insurance';\n default:\n return 'Unverified';\n }\n }\n\n protected insuranceTitle(item: AgentActivity): string {\n switch (this.insuranceState(item)) {\n case 'covered':\n return item.insuranceName ? `Insured — ${item.insuranceName}` : 'Insured';\n case 'none':\n return 'No insurance on file';\n default:\n return 'Insurance not verified';\n }\n }\n\n protected isTaskRow(item: AgentActivity): boolean {\n return item.type === 'task_created';\n }\n\n protected taskTitle(item: AgentActivity): string {\n const title = (item.title || '').trim();\n if (title && !/^task created$/i.test(title)) return title;\n return item.visitType || 'Task';\n }\n\n protected priorityLabel(item: AgentActivity): string {\n switch (item.priority) {\n case 'urgent':\n return 'Urgent';\n case 'high':\n return 'High';\n case 'low':\n return 'Low';\n case 'medium':\n case 'normal':\n default:\n return 'Medium';\n }\n }\n\n protected priorityTone(item: AgentActivity): string {\n switch (item.priority) {\n case 'urgent':\n return 'urgent';\n case 'high':\n return 'high';\n case 'low':\n return 'low';\n default:\n return 'medium';\n }\n }\n\n protected isRegistrationTab(): boolean {\n return this.activeTab() === 'patient_created';\n }\n\n protected emptyLabel(): string {\n if (this.callIdFilter()) return 'No activities found for this call.';\n switch (this.activeTab()) {\n case 'task_created':\n return 'No tasks created by the AI yet.';\n case 'patient_created':\n return 'No patient registrations yet.';\n default:\n return 'No appointments booked by the AI yet.';\n }\n }\n\n private parseDate(iso: string | null | undefined): Date | null {\n if (!iso) return null;\n const d = new Date(iso);\n return Number.isNaN(d.getTime()) ? null : d;\n }\n\n private formatDay(d: Date): string {\n const midnight = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();\n const now = new Date();\n const days = Math.round((midnight(d) - midnight(now)) / 86_400_000);\n if (days === 0) return 'Today';\n if (days === 1) return 'Tomorrow';\n if (days === -1) return 'Yesterday';\n return d.toLocaleDateString(\n undefined,\n d.getFullYear() === now.getFullYear()\n ? { weekday: 'short', month: 'short', day: 'numeric' }\n : { month: 'short', day: 'numeric', year: 'numeric' },\n );\n }\n\n private formatClock(d: Date): string {\n return d.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });\n }\n\n private formatDob(iso: string): string {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(iso.trim());\n if (m) return `${m[2]}-${m[3]}-${m[1]}`;\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n const mm = String(d.getMonth() + 1).padStart(2, '0');\n const dd = String(d.getDate()).padStart(2, '0');\n return `${mm}-${dd}-${d.getFullYear()}`;\n }\n}\n","<div class=\"eds-page activities-page\">\n <header class=\"mb-5\">\n <div>\n <h1 class=\"eds-h1\">Activities</h1>\n <p class=\"eds-body-sm\">Review all the activities done by the AI at one place</p>\n </div>\n </header>\n\n @if (callIdFilter(); as callId) {\n <div\n class=\"mb-4 flex flex-wrap items-center justify-between gap-3 rounded-lg bg-blue-50 px-4 py-3 text-sm font-normal leading-snug text-zinc-600\"\n role=\"status\"\n >\n <span>Showing activities for call <strong class=\"font-medium text-zinc-700\">{{ callId }}</strong></span>\n <button\n type=\"button\"\n class=\"cursor-pointer border-none bg-transparent px-0 py-1 text-sm font-medium text-blue-600 hover:underline\"\n (click)=\"clearCallFilter()\"\n >\n Clear filter\n </button>\n </div>\n }\n\n <nav class=\"mb-5 flex flex-wrap gap-2\" aria-label=\"Activity type\">\n @for (tab of tabs; track tab.id) {\n <button\n type=\"button\"\n [class]=\"\n activeTab() === tab.id\n ? 'cursor-pointer rounded-full border-none bg-blue-50 px-4 py-2 text-sm font-medium text-blue-600 transition-colors'\n : 'cursor-pointer rounded-full border-none bg-transparent px-4 py-2 text-sm font-medium text-zinc-500 transition-colors hover:bg-white hover:text-zinc-700'\n \"\n (click)=\"setTab(tab.id)\"\n >\n {{ tab.label }}\n </button>\n }\n </nav>\n\n @if (loading()) {\n <p class=\"eds-body-sm\">Loading activities…</p>\n } @else if (loadError()) {\n <p class=\"text-sm text-red-700\" role=\"alert\">{{ loadError() }}</p>\n } @else {\n @if (activeTab() === 'task_created') {\n <div\n class=\"activities-page__col-head activities-page__col-head--tasks grid gap-x-7 gap-y-4 pb-2 text-sm font-semibold leading-tight text-zinc-600 max-lg:hidden\"\n aria-hidden=\"true\"\n >\n <span>Priority</span>\n <span>Task</span>\n <span>Patient / Caller</span>\n </div>\n } @else if (activeTab() === 'appointment_booked') {\n <div\n class=\"activities-page__col-head activities-page__col-head--appointments grid gap-x-7 gap-y-4 pb-2 text-sm font-semibold leading-tight text-zinc-600 max-lg:hidden\"\n aria-hidden=\"true\"\n >\n <span>When</span>\n <span>Patient</span>\n <span>Provider</span>\n <span class=\"justify-self-end text-right\">Insurance</span>\n </div>\n } @else if (activeTab() === 'patient_created') {\n <div\n class=\"activities-page__col-head activities-page__col-head--registration grid gap-x-7 gap-y-4 pb-2 text-sm font-semibold leading-tight text-zinc-600 max-lg:hidden\"\n aria-hidden=\"true\"\n >\n <span>When</span>\n <span>Patient</span>\n <span>MRN</span>\n <span class=\"justify-self-end text-right\">Insurance</span>\n </div>\n }\n\n <ul class=\"m-0 flex list-none flex-col gap-3 p-0\">\n @for (item of items(); track item.id; let i = $index) {\n @if (isTaskRow(item)) {\n <li\n class=\"activities-page__card activities-page__card--task grid cursor-pointer items-center gap-x-7 gap-y-4 rounded-xl border border-zinc-200 bg-white px-4 py-4 max-lg:gap-x-4 max-lg:gap-y-4 hover:border-blue-200 hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'View task: ' + taskTitle(item)\"\n (click)=\"openTask(item)\"\n (keyup.enter)=\"openTask(item)\"\n >\n <div class=\"inline-flex items-center gap-2 text-sm font-medium leading-snug text-zinc-700\" [attr.data-tone]=\"priorityTone(item)\">\n <span class=\"activities-page__priority-mark h-2.5 w-2.5 shrink-0 rotate-45 rounded-sm\" aria-hidden=\"true\"></span>\n <span class=\"capitalize\">{{ priorityLabel(item) }}</span>\n </div>\n\n <div class=\"text-sm font-medium leading-snug text-zinc-700 max-lg:col-span-full\">{{ taskTitle(item) }}</div>\n\n <div class=\"flex min-w-0 items-center gap-3 max-lg:col-span-full\">\n <eds-avatar\n shape=\"box\"\n [initials]=\"patientInitials(item)\"\n [tone]=\"avatarTone(item.patientId || item.patientName || item.id, i)\"\n />\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"truncate text-sm font-medium leading-snug text-zinc-700\">{{ item.patientName || 'Unknown caller' }}</span>\n @if (patientMeta(item); as meta) {\n <span class=\"truncate text-xs leading-snug text-zinc-500\">{{ meta }}</span>\n }\n </div>\n </div>\n </li>\n } @else if (isRegistrationTab()) {\n <li\n class=\"activities-page__card activities-page__card--registration grid items-center gap-x-7 gap-y-4 rounded-xl border border-zinc-200 bg-white px-4 py-4 max-lg:gap-x-4 max-lg:gap-y-4\"\n >\n <div class=\"min-w-0\">\n <div class=\"mb-1 flex flex-wrap items-center gap-2\">\n <span class=\"whitespace-nowrap text-base font-medium leading-snug text-zinc-700 max-md:whitespace-normal\">{{ timestampLabel(item) }}</span>\n </div>\n <p class=\"m-0 text-sm leading-snug text-zinc-500\">{{ categoryLabel(item) }}</p>\n </div>\n\n <div class=\"flex min-w-0 items-center gap-3 max-lg:col-span-full\">\n <eds-avatar\n shape=\"box\"\n [initials]=\"patientInitials(item)\"\n [tone]=\"avatarTone(item.patientId || item.patientName || item.id, i)\"\n />\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"truncate text-sm font-medium leading-snug text-zinc-700\">{{ item.patientName || 'Unknown patient' }}</span>\n @if (patientMeta(item); as meta) {\n <span class=\"truncate text-xs leading-snug text-zinc-500\">{{ meta }}</span>\n }\n </div>\n </div>\n\n <div class=\"text-sm font-normal leading-snug text-zinc-600\">{{ displayMrn(item) }}</div>\n\n <div class=\"flex items-center justify-end gap-2.5\">\n <span\n class=\"activities-page__insurance inline-flex h-8 w-8 items-center justify-center rounded-full border border-transparent max-md:px-1.5\"\n [attr.data-state]=\"insuranceState(item)\"\n [title]=\"insuranceTitle(item)\"\n [attr.aria-label]=\"insuranceLabel(item)\"\n >\n <eds-icon [name]=\"insuranceIcon(item)\" [size]=\"18\" />\n </span>\n </div>\n </li>\n } @else {\n <li\n [class]=\"\n 'activities-page__card grid items-center gap-x-7 gap-y-4 rounded-xl border border-zinc-200 bg-white px-4 py-4 max-lg:gap-x-4 max-lg:gap-y-4' +\n (item.callId\n ? ' cursor-pointer hover:border-blue-200 hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600'\n : '')\n \"\n [attr.role]=\"item.callId ? 'link' : null\"\n [attr.tabindex]=\"item.callId ? 0 : null\"\n (click)=\"openCallHistory(item.callId, $event)\"\n (keyup.enter)=\"openCallHistory(item.callId)\"\n >\n <div class=\"min-w-0\">\n <div class=\"mb-1 flex flex-wrap items-center gap-2\">\n <span class=\"whitespace-nowrap text-base font-medium leading-snug text-zinc-700 max-md:whitespace-normal\">{{ timestampLabel(item) }}</span>\n </div>\n <p class=\"m-0 text-sm leading-snug text-zinc-500\">{{ categoryLabel(item) }}</p>\n </div>\n\n <div class=\"flex min-w-0 items-center gap-3 max-lg:col-span-full\">\n <eds-avatar\n shape=\"box\"\n [initials]=\"patientInitials(item)\"\n [tone]=\"avatarTone(item.patientId || item.patientName || item.id, i)\"\n />\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"truncate text-sm font-medium leading-snug text-zinc-700\">{{ item.patientName || 'Unknown patient' }}</span>\n @if (patientMeta(item); as meta) {\n <span class=\"truncate text-xs leading-snug text-zinc-500\">{{ meta }}</span>\n }\n </div>\n </div>\n\n <div class=\"flex min-w-0 items-center gap-3 max-lg:col-span-full\">\n @if (item.providerName) {\n <eds-avatar\n shape=\"circle\"\n [initials]=\"providerInitials(item)\"\n [tone]=\"avatarTone(item.providerId || item.providerName, i + 3)\"\n />\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"truncate text-sm font-medium leading-snug text-zinc-700\">{{ item.providerName }}</span>\n @if (providerSpecialtyLabel(item); as specialty) {\n <span class=\"truncate text-xs leading-snug text-zinc-500\">{{ specialty }}</span>\n }\n </div>\n } @else {\n <div class=\"flex min-h-9 items-center\">\n <span class=\"truncate text-xs leading-snug text-zinc-500\">No provider assigned</span>\n </div>\n }\n </div>\n\n <div class=\"flex items-center justify-end gap-3\">\n <span\n class=\"activities-page__insurance inline-flex h-8 w-8 items-center justify-center rounded-full border border-transparent max-md:px-2\"\n [attr.data-state]=\"insuranceState(item)\"\n [title]=\"insuranceTitle(item)\"\n [attr.aria-label]=\"insuranceLabel(item)\"\n >\n <eds-icon [name]=\"insuranceIcon(item)\" [size]=\"18\" />\n </span>\n </div>\n </li>\n }\n } @empty {\n <li class=\"rounded-xl border border-dashed border-zinc-200 bg-white px-4 py-10 text-center text-sm leading-snug text-zinc-500\">\n {{ emptyLabel() }}\n </li>\n }\n </ul>\n\n @if (total() > pageSize) {\n <footer class=\"mt-4 flex flex-wrap items-center justify-between gap-3\">\n <span class=\"eds-body-sm\">\n Page {{ page() }} of {{ totalPages() }} · {{ total() }} total\n </span>\n <div class=\"flex gap-2\">\n <eds-button variant=\"secondary\" [disabled]=\"page() <= 1\" (click)=\"prevPage()\">Previous</eds-button>\n <eds-button variant=\"secondary\" [disabled]=\"page() >= totalPages()\" (click)=\"nextPage()\">Next</eds-button>\n </div>\n </footer>\n }\n }\n</div>\n\n@if (selectedTask(); as task) {\n <eds-task-detail-drawer\n [task]=\"task\"\n (closed)=\"closeTaskDrawer()\"\n (statusChange)=\"onTaskStatusChange($event)\"\n />\n}\n"],"names":["calcTotalPages"],"mappings":"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"}
@@ -401,7 +401,7 @@ class CallHistoryDetailPageComponent {
401
401
  return `${m}:${s.toString().padStart(2, '0')}`;
402
402
  }
403
403
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CallHistoryDetailPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
404
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: CallHistoryDetailPageComponent, isStandalone: true, selector: "eds-call-history-detail-page", ngImport: i0, template: "<div class=\"eds-page call-history-detail-page\">\n <a\n class=\"call-history-detail-page__back eds-body-sm mb-4 inline-flex items-center gap-1 no-underline\"\n [routerLink]=\"historyListLink\"\n [relativeTo]=\"historyListRelativeTo\"\n >\n <eds-icon name=\"arrow_back\" [size]=\"18\" /> Back to history\n </a>\n\n @if (loading()) {\n <p class=\"eds-body-sm\">Loading call detail\u2026</p>\n } @else if (detail()) {\n <header class=\"mb-4 flex flex-wrap items-start justify-between gap-4\">\n <div>\n <h1 class=\"eds-h1\">{{ detail()!.name }}</h1>\n <p class=\"eds-body-sm\">{{ detail()!.phone }} \u00B7 {{ detail()!.reason }}</p>\n </div>\n @if (isNeedsReview(detail()!.review)) {\n <eds-button\n variant=\"primary\"\n [disabled]=\"markingReview()\"\n (click)=\"markReviewed()\"\n >\n <eds-icon name=\"check_circle\" [size]=\"18\" />\n {{ markingReview() ? 'Saving\u2026' : 'Mark as reviewed' }}\n </eds-button>\n }\n </header>\n\n <dl class=\"call-history-detail-page__meta mx-0 mt-0 mb-5 grid grid-cols-4 gap-4\">\n <div><dt class=\"eds-label\">Outcome</dt><dd>\n <eds-badge [tone]=\"outcomeTone(detail()!.outcome)\">\n {{ outcomeLabel(detail()!.outcome) }}\n </eds-badge>\n </dd></div>\n <div><dt class=\"eds-label\">Duration</dt><dd>{{ detail()!.durationLabel ?? formatDuration(detail()!.duration) }}</dd></div>\n <div><dt class=\"eds-label\">Location</dt><dd>{{ detail()!.location }}</dd></div>\n <div><dt class=\"eds-label\">When</dt><dd>{{ detail()!.whenLabel ?? '\u2014' }}</dd></div>\n </dl>\n\n <eds-call-conversation-panel\n [callId]=\"detail()!.id\"\n [summary]=\"detail()!.summary\"\n [transcript]=\"detail()!.transcript\"\n [tools]=\"detail()!.tools\"\n [callDurationSec]=\"detail()!.duration\"\n [callerName]=\"detail()!.name\"\n [callerMatched]=\"!isUnknownName(detail()!.name)\"\n (summaryRegenerated)=\"refreshCallDetail()\"\n >\n <eds-call-tasks-panel\n summary-side\n [callId]=\"detail()!.id\"\n [compact]=\"true\"\n />\n </eds-call-conversation-panel>\n } @else {\n <p class=\"eds-body-sm\">Call not found.</p>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.call-history-detail-page__back{color:var(--eds-text-secondary)}.call-history-detail-page__badges{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.call-history-detail-page__meta dd{margin:4px 0 0;font-size:14px}.call-history-detail-page__tabs{display:flex;gap:4px;margin-bottom:16px;border-bottom:1px solid var(--eds-border-default)}.call-history-detail-page__tab{padding:10px 16px;border:none;background:none;font-size:14px;font-weight:500;color:var(--eds-text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}.call-history-detail-page__tab--active{color:var(--eds-text-brand);border-bottom-color:var(--eds-brand-500)}.call-history-detail-page__panel{padding:20px}@media(max-width:800px){.call-history-detail-page__meta{grid-template-columns:repeat(2,1fr)}}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: EdsBadgeComponent, selector: "eds-badge", inputs: ["tone"] }, { kind: "component", type: EdsButtonComponent, selector: "eds-button", inputs: ["variant", "type", "disabled"] }, { kind: "component", type: EdsIconComponent, selector: "eds-icon", inputs: ["name", "size", "fill", "weight"] }, { kind: "component", type: CallConversationPanelComponent, selector: "eds-call-conversation-panel", inputs: ["callId", "summary", "transcript", "tools", "callDurationSec", "allowRegenerate", "callerName", "callerMatched"], outputs: ["summaryRegenerated"] }, { kind: "component", type: CallTasksPanelComponent, selector: "eds-call-tasks-panel", inputs: ["callId", "compact"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
404
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: CallHistoryDetailPageComponent, isStandalone: true, selector: "eds-call-history-detail-page", ngImport: i0, template: "<div class=\"eds-page call-history-detail-page\">\n <a\n class=\"call-history-detail-page__back eds-body-sm mb-4 inline-flex items-center gap-1 no-underline\"\n [routerLink]=\"historyListLink\"\n [relativeTo]=\"historyListRelativeTo\"\n >\n <eds-icon name=\"arrow_back\" [size]=\"18\" /> Back to history\n </a>\n\n @if (loading()) {\n <p class=\"eds-body-sm\">Loading call detail\u2026</p>\n } @else if (detail()) {\n <header class=\"mb-4 flex flex-wrap items-start justify-between gap-4\">\n <div>\n <h1 class=\"eds-h1\">{{ detail()!.name }}</h1>\n <p class=\"eds-body-sm\">{{ detail()!.phone }} \u00B7 {{ detail()!.reason }}</p>\n </div>\n @if (isNeedsReview(detail()!.review)) {\n <eds-button\n variant=\"primary\"\n [disabled]=\"markingReview()\"\n (click)=\"markReviewed()\"\n >\n <eds-icon name=\"check_circle\" [size]=\"18\" />\n {{ markingReview() ? 'Saving\u2026' : 'Mark as reviewed' }}\n </eds-button>\n }\n </header>\n\n <dl class=\"call-history-detail-page__meta mx-0 mt-0 mb-5 grid grid-cols-2 gap-4 sm:grid-cols-2\">\n <div><dt class=\"eds-label\">Outcome</dt><dd>\n <eds-badge [tone]=\"outcomeTone(detail()!.outcome)\">\n {{ outcomeLabel(detail()!.outcome) }}\n </eds-badge>\n </dd></div>\n <div><dt class=\"eds-label\">Duration</dt><dd>{{ detail()!.durationLabel ?? formatDuration(detail()!.duration) }}</dd></div>\n </dl>\n\n <eds-call-conversation-panel\n [callId]=\"detail()!.id\"\n [summary]=\"detail()!.summary\"\n [transcript]=\"detail()!.transcript\"\n [tools]=\"detail()!.tools\"\n [callDurationSec]=\"detail()!.duration\"\n [callerName]=\"detail()!.name\"\n [callerMatched]=\"!isUnknownName(detail()!.name)\"\n (summaryRegenerated)=\"refreshCallDetail()\"\n >\n <eds-call-tasks-panel\n summary-side\n [callId]=\"detail()!.id\"\n [compact]=\"true\"\n />\n </eds-call-conversation-panel>\n } @else {\n <p class=\"eds-body-sm\">Call not found.</p>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.call-history-detail-page__back{color:var(--eds-text-secondary)}.call-history-detail-page__badges{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.call-history-detail-page__meta dd{margin:4px 0 0;font-size:14px}.call-history-detail-page__tabs{display:flex;gap:4px;margin-bottom:16px;border-bottom:1px solid var(--eds-border-default)}.call-history-detail-page__tab{padding:10px 16px;border:none;background:none;font-size:14px;font-weight:500;color:var(--eds-text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}.call-history-detail-page__tab--active{color:var(--eds-text-brand);border-bottom-color:var(--eds-brand-500)}.call-history-detail-page__panel{padding:20px}@media(max-width:800px){.call-history-detail-page__meta{grid-template-columns:repeat(2,1fr)}}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: EdsBadgeComponent, selector: "eds-badge", inputs: ["tone"] }, { kind: "component", type: EdsButtonComponent, selector: "eds-button", inputs: ["variant", "type", "disabled"] }, { kind: "component", type: EdsIconComponent, selector: "eds-icon", inputs: ["name", "size", "fill", "weight"] }, { kind: "component", type: CallConversationPanelComponent, selector: "eds-call-conversation-panel", inputs: ["callId", "summary", "transcript", "tools", "callDurationSec", "allowRegenerate", "callerName", "callerMatched"], outputs: ["summaryRegenerated"] }, { kind: "component", type: CallTasksPanelComponent, selector: "eds-call-tasks-panel", inputs: ["callId", "compact"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
405
405
  }
406
406
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CallHistoryDetailPageComponent, decorators: [{
407
407
  type: Component,
@@ -412,8 +412,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
412
412
  EdsIconComponent,
413
413
  CallConversationPanelComponent,
414
414
  CallTasksPanelComponent,
415
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"eds-page call-history-detail-page\">\n <a\n class=\"call-history-detail-page__back eds-body-sm mb-4 inline-flex items-center gap-1 no-underline\"\n [routerLink]=\"historyListLink\"\n [relativeTo]=\"historyListRelativeTo\"\n >\n <eds-icon name=\"arrow_back\" [size]=\"18\" /> Back to history\n </a>\n\n @if (loading()) {\n <p class=\"eds-body-sm\">Loading call detail\u2026</p>\n } @else if (detail()) {\n <header class=\"mb-4 flex flex-wrap items-start justify-between gap-4\">\n <div>\n <h1 class=\"eds-h1\">{{ detail()!.name }}</h1>\n <p class=\"eds-body-sm\">{{ detail()!.phone }} \u00B7 {{ detail()!.reason }}</p>\n </div>\n @if (isNeedsReview(detail()!.review)) {\n <eds-button\n variant=\"primary\"\n [disabled]=\"markingReview()\"\n (click)=\"markReviewed()\"\n >\n <eds-icon name=\"check_circle\" [size]=\"18\" />\n {{ markingReview() ? 'Saving\u2026' : 'Mark as reviewed' }}\n </eds-button>\n }\n </header>\n\n <dl class=\"call-history-detail-page__meta mx-0 mt-0 mb-5 grid grid-cols-4 gap-4\">\n <div><dt class=\"eds-label\">Outcome</dt><dd>\n <eds-badge [tone]=\"outcomeTone(detail()!.outcome)\">\n {{ outcomeLabel(detail()!.outcome) }}\n </eds-badge>\n </dd></div>\n <div><dt class=\"eds-label\">Duration</dt><dd>{{ detail()!.durationLabel ?? formatDuration(detail()!.duration) }}</dd></div>\n <div><dt class=\"eds-label\">Location</dt><dd>{{ detail()!.location }}</dd></div>\n <div><dt class=\"eds-label\">When</dt><dd>{{ detail()!.whenLabel ?? '\u2014' }}</dd></div>\n </dl>\n\n <eds-call-conversation-panel\n [callId]=\"detail()!.id\"\n [summary]=\"detail()!.summary\"\n [transcript]=\"detail()!.transcript\"\n [tools]=\"detail()!.tools\"\n [callDurationSec]=\"detail()!.duration\"\n [callerName]=\"detail()!.name\"\n [callerMatched]=\"!isUnknownName(detail()!.name)\"\n (summaryRegenerated)=\"refreshCallDetail()\"\n >\n <eds-call-tasks-panel\n summary-side\n [callId]=\"detail()!.id\"\n [compact]=\"true\"\n />\n </eds-call-conversation-panel>\n } @else {\n <p class=\"eds-body-sm\">Call not found.</p>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.call-history-detail-page__back{color:var(--eds-text-secondary)}.call-history-detail-page__badges{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.call-history-detail-page__meta dd{margin:4px 0 0;font-size:14px}.call-history-detail-page__tabs{display:flex;gap:4px;margin-bottom:16px;border-bottom:1px solid var(--eds-border-default)}.call-history-detail-page__tab{padding:10px 16px;border:none;background:none;font-size:14px;font-weight:500;color:var(--eds-text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}.call-history-detail-page__tab--active{color:var(--eds-text-brand);border-bottom-color:var(--eds-brand-500)}.call-history-detail-page__panel{padding:20px}@media(max-width:800px){.call-history-detail-page__meta{grid-template-columns:repeat(2,1fr)}}\n"] }]
415
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"eds-page call-history-detail-page\">\n <a\n class=\"call-history-detail-page__back eds-body-sm mb-4 inline-flex items-center gap-1 no-underline\"\n [routerLink]=\"historyListLink\"\n [relativeTo]=\"historyListRelativeTo\"\n >\n <eds-icon name=\"arrow_back\" [size]=\"18\" /> Back to history\n </a>\n\n @if (loading()) {\n <p class=\"eds-body-sm\">Loading call detail\u2026</p>\n } @else if (detail()) {\n <header class=\"mb-4 flex flex-wrap items-start justify-between gap-4\">\n <div>\n <h1 class=\"eds-h1\">{{ detail()!.name }}</h1>\n <p class=\"eds-body-sm\">{{ detail()!.phone }} \u00B7 {{ detail()!.reason }}</p>\n </div>\n @if (isNeedsReview(detail()!.review)) {\n <eds-button\n variant=\"primary\"\n [disabled]=\"markingReview()\"\n (click)=\"markReviewed()\"\n >\n <eds-icon name=\"check_circle\" [size]=\"18\" />\n {{ markingReview() ? 'Saving\u2026' : 'Mark as reviewed' }}\n </eds-button>\n }\n </header>\n\n <dl class=\"call-history-detail-page__meta mx-0 mt-0 mb-5 grid grid-cols-2 gap-4 sm:grid-cols-2\">\n <div><dt class=\"eds-label\">Outcome</dt><dd>\n <eds-badge [tone]=\"outcomeTone(detail()!.outcome)\">\n {{ outcomeLabel(detail()!.outcome) }}\n </eds-badge>\n </dd></div>\n <div><dt class=\"eds-label\">Duration</dt><dd>{{ detail()!.durationLabel ?? formatDuration(detail()!.duration) }}</dd></div>\n </dl>\n\n <eds-call-conversation-panel\n [callId]=\"detail()!.id\"\n [summary]=\"detail()!.summary\"\n [transcript]=\"detail()!.transcript\"\n [tools]=\"detail()!.tools\"\n [callDurationSec]=\"detail()!.duration\"\n [callerName]=\"detail()!.name\"\n [callerMatched]=\"!isUnknownName(detail()!.name)\"\n (summaryRegenerated)=\"refreshCallDetail()\"\n >\n <eds-call-tasks-panel\n summary-side\n [callId]=\"detail()!.id\"\n [compact]=\"true\"\n />\n </eds-call-conversation-panel>\n } @else {\n <p class=\"eds-body-sm\">Call not found.</p>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.call-history-detail-page__back{color:var(--eds-text-secondary)}.call-history-detail-page__badges{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.call-history-detail-page__meta dd{margin:4px 0 0;font-size:14px}.call-history-detail-page__tabs{display:flex;gap:4px;margin-bottom:16px;border-bottom:1px solid var(--eds-border-default)}.call-history-detail-page__tab{padding:10px 16px;border:none;background:none;font-size:14px;font-weight:500;color:var(--eds-text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}.call-history-detail-page__tab--active{color:var(--eds-text-brand);border-bottom-color:var(--eds-brand-500)}.call-history-detail-page__panel{padding:20px}@media(max-width:800px){.call-history-detail-page__meta{grid-template-columns:repeat(2,1fr)}}\n"] }]
416
416
  }] });
417
417
 
418
418
  export { CallHistoryDetailPageComponent };
419
- //# sourceMappingURL=edvak99-voice-receptionist-widget-call-history-detail-page.component-BuNyPmhn.mjs.map
419
+ //# sourceMappingURL=edvak99-voice-receptionist-widget-call-history-detail-page.component-BkT3Qfsk.mjs.map