@edvak99/voice-receptionist-widget 1.1.21 → 1.1.22

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-dcDXT2KG.mjs +533 -0
  2. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-dcDXT2KG.mjs.map +1 -0
  3. package/fesm2022/{edvak99-voice-receptionist-widget-analytics-page.component-CmImX5FN.mjs → edvak99-voice-receptionist-widget-analytics-page.component-B25yZJZz.mjs} +2 -2
  4. package/fesm2022/{edvak99-voice-receptionist-widget-analytics-page.component-CmImX5FN.mjs.map → edvak99-voice-receptionist-widget-analytics-page.component-B25yZJZz.mjs.map} +1 -1
  5. package/fesm2022/edvak99-voice-receptionist-widget-audit-page.component-Df-dtgR3.mjs +96 -0
  6. package/fesm2022/edvak99-voice-receptionist-widget-audit-page.component-Df-dtgR3.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-BJGzgVxG.mjs} +21 -10
  8. package/fesm2022/edvak99-voice-receptionist-widget-call-history-detail-page.component-BJGzgVxG.mjs.map +1 -0
  9. package/fesm2022/edvak99-voice-receptionist-widget-call-history-page.component-CcwwO5SO.mjs +254 -0
  10. package/fesm2022/edvak99-voice-receptionist-widget-call-history-page.component-CcwwO5SO.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-BepxNLNQ.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-BepxNLNQ.mjs.map} +1 -1
  13. package/fesm2022/{edvak99-voice-receptionist-widget-call-review.service-BhbCmB1S.mjs → edvak99-voice-receptionist-widget-call-review.service-nFqc30t3.mjs} +2 -2
  14. package/fesm2022/{edvak99-voice-receptionist-widget-call-review.service-BhbCmB1S.mjs.map → edvak99-voice-receptionist-widget-call-review.service-nFqc30t3.mjs.map} +1 -1
  15. package/fesm2022/edvak99-voice-receptionist-widget-dashboard-page.component-CMgOu0aw.mjs +311 -0
  16. package/fesm2022/edvak99-voice-receptionist-widget-dashboard-page.component-CMgOu0aw.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-CJ1L6QeE.mjs} +54 -25
  18. package/fesm2022/edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CJ1L6QeE.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-MnBMu8iA.mjs} +4 -4
  20. package/fesm2022/edvak99-voice-receptionist-widget-live-calls-page.component-MnBMu8iA.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-BzvMkbC4.mjs} +10 -7
  22. package/fesm2022/edvak99-voice-receptionist-widget-live-monitor-page.component-BzvMkbC4.mjs.map +1 -0
  23. package/fesm2022/edvak99-voice-receptionist-widget-outbound-purposes-page.component-Aws6TaaE.mjs +273 -0
  24. package/fesm2022/edvak99-voice-receptionist-widget-outbound-purposes-page.component-Aws6TaaE.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-DVWdArqj.mjs} +14 -6
  26. package/fesm2022/edvak99-voice-receptionist-widget-task-detail-drawer.component-DVWdArqj.mjs.map +1 -0
  27. package/fesm2022/{edvak99-voice-receptionist-widget-tasks-page.component-Dj1nWx6V.mjs → edvak99-voice-receptionist-widget-tasks-page.component-CBDmGLol.mjs} +11 -7
  28. package/fesm2022/edvak99-voice-receptionist-widget-tasks-page.component-CBDmGLol.mjs.map +1 -0
  29. package/fesm2022/{edvak99-voice-receptionist-widget-wizard-page.component-CQttbEzW.mjs → edvak99-voice-receptionist-widget-wizard-page.component-C-hdBQIV.mjs} +2 -2
  30. package/fesm2022/{edvak99-voice-receptionist-widget-wizard-page.component-CQttbEzW.mjs.map → edvak99-voice-receptionist-widget-wizard-page.component-C-hdBQIV.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 +3 -0
  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 +5 -2
  36. package/lib/pages/audit-page/audit-page.component.d.ts +3 -0
  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 +27 -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,96 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { DatePipe } from '@angular/common';
4
+ import { FormsModule } from '@angular/forms';
5
+ import { A as AiReceptionistApiService, n as DEFAULT_PAGE_SIZE, o as totalPages, I as IconComponent, g as EdSkeletonComponent, f as EdButtonComponent } from './edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CJ1L6QeE.mjs';
6
+ import { S as SmartTooltipDirective } from './edvak99-voice-receptionist-widget-smart-tooltip.directive-ChEdIem3.mjs';
7
+ import { T as TABLE_SKELETON_ROWS } from './edvak99-voice-receptionist-widget-table-skeleton.constants-C1Dg9Z_2.mjs';
8
+ import { E as EdsSearchFieldComponent } from './edvak99-voice-receptionist-widget-eds-search-field.component-BDGCmkoP.mjs';
9
+
10
+ class AuditPageComponent {
11
+ constructor() {
12
+ this.api = inject(AiReceptionistApiService);
13
+ this.pageSize = DEFAULT_PAGE_SIZE;
14
+ this.events = signal([]);
15
+ this.total = signal(0);
16
+ this.page = signal(1);
17
+ this.search = signal('');
18
+ this.actor = signal('');
19
+ this.loading = signal(true);
20
+ this.skeletonRows = TABLE_SKELETON_ROWS;
21
+ }
22
+ ngOnInit() {
23
+ this.load();
24
+ }
25
+ load() {
26
+ this.loading.set(true);
27
+ this.api
28
+ .getAudit(this.search() || undefined, {
29
+ page: this.page(),
30
+ limit: DEFAULT_PAGE_SIZE,
31
+ actor: this.actor() || undefined,
32
+ })
33
+ .subscribe({
34
+ next: ({ items, total, page }) => {
35
+ this.events.set(items);
36
+ this.total.set(total);
37
+ this.page.set(page);
38
+ this.loading.set(false);
39
+ },
40
+ error: () => this.loading.set(false),
41
+ });
42
+ }
43
+ onSearchInput(value) {
44
+ this.search.set(value);
45
+ if (!value.trim())
46
+ this.searchSubmit();
47
+ }
48
+ onActorInput(value) {
49
+ this.actor.set(value);
50
+ if (!value.trim())
51
+ this.searchSubmit();
52
+ }
53
+ displayTarget(raw) {
54
+ const t = String(raw ?? '').trim();
55
+ if (!t || /^https?:\/\//i.test(t) || /^[0-9a-f]{8}-[0-9a-f]{4}-/i.test(t)) {
56
+ return '—';
57
+ }
58
+ return t;
59
+ }
60
+ searchSubmit() {
61
+ this.page.set(1);
62
+ this.load();
63
+ }
64
+ totalPages() {
65
+ return totalPages(this.total(), DEFAULT_PAGE_SIZE);
66
+ }
67
+ prevPage() {
68
+ if (this.page() <= 1)
69
+ return;
70
+ this.page.update((p) => p - 1);
71
+ this.load();
72
+ }
73
+ nextPage() {
74
+ if (this.page() >= this.totalPages())
75
+ return;
76
+ this.page.update((p) => p + 1);
77
+ this.load();
78
+ }
79
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: AuditPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
80
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: AuditPageComponent, isStandalone: true, selector: "eds-audit-page", host: { classAttribute: "block h-full min-h-0" }, ngImport: i0, template: "<div class=\"flex h-full min-h-0 flex-col overflow-hidden bg-lighter p-base audit-page\">\n <header class=\"relative z-10 mb-base shrink-0 bg-lighter\">\n <div>\n <h4>Audit log</h4>\n <p class=\"fs-sm text-light\">Track configuration and agent activity</p>\n </div>\n </header>\n\n <div class=\"mb-base flex shrink-0 flex-wrap items-center gap-sm rounded-md bg-white p-base\">\n <eds-search-field\n inputClass=\"form-input min-w-[180px]\"\n placeholder=\"Search action, target, detail\u2026\"\n [value]=\"search()\"\n (valueChange)=\"onSearchInput($event)\"\n (enter)=\"searchSubmit()\"\n />\n <eds-search-field\n type=\"text\"\n inputClass=\"form-input min-w-[180px]\"\n placeholder=\"Filter by actor\"\n [value]=\"actor()\"\n (valueChange)=\"onActorInput($event)\"\n (enter)=\"searchSubmit()\"\n />\n <ed-button variant=\"primary\" fill size=\"sm\" (click$)=\"searchSubmit()\">\n <ed-icon slot=\"prefix\" name=\"search\" [size]=\"16\" />\n Search\n </ed-button>\n </div>\n\n <div class=\"flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-md bg-white p-base\">\n <div class=\"eds-table-scroll min-h-0 min-w-0 flex-1\">\n <table class=\"table-default eds-sticky-table eds-centered-table w-full\" aria-label=\"Audit log\">\n <thead>\n <tr>\n <th class=\"bg-light\">Date</th>\n <th class=\"bg-light\">Actor</th>\n <th class=\"bg-light\">Action</th>\n <th class=\"bg-light\">Target</th>\n <th class=\"bg-light\">Detail</th>\n </tr>\n </thead>\n @if (loading()) {\n <tbody aria-busy=\"true\">\n @for (_ of skeletonRows; track _) {\n <tr>\n <td><ed-skeleton class=\"h-3 w-32\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-24\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-36\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-28\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-48\"></ed-skeleton></td>\n </tr>\n }\n </tbody>\n } @else {\n <tbody>\n @for (event of events(); track event.id) {\n <tr>\n <td class=\"font-['IBM_Plex_Mono'] fs-sm text-light\">{{ event.at | date: 'medium' }}</td>\n <td>\n <span\n class=\"inline-block min-w-0 max-w-48 truncate fs-sm text-dark\"\n [smartTooltip]=\"event.actor\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ event.actor }}</span>\n </td>\n <td>\n <span\n class=\"inline-block min-w-0 max-w-56 truncate fs-sm font-semibold text-dark\"\n [smartTooltip]=\"event.action\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ event.action }}</span>\n </td>\n <td>\n <span\n class=\"inline-block min-w-0 max-w-48 truncate fs-sm text-light\"\n [smartTooltip]=\"displayTarget(event.target)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ displayTarget(event.target) }}</span>\n </td>\n <td>\n <span\n class=\"inline-block min-w-0 max-w-72 truncate\"\n [smartTooltip]=\"event.detail\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ event.detail }}</span>\n </td>\n </tr>\n } @empty {\n <tr class=\"empty-row\">\n <td colspan=\"5\" class=\"py-lg text-center fs-sm text-light\">No events match your filters.</td>\n </tr>\n }\n </tbody>\n }\n </table>\n </div>\n </div>\n\n <footer class=\"mt-base flex shrink-0 items-center justify-between border-t border-light pt-sm\">\n <span class=\"fs-sm text-light\">\n Page {{ page() }} of {{ totalPages() }} \u00B7 {{ total() }} total\n </span>\n <div class=\"flex gap-2\">\n <ed-button variant=\"secondary\" outline size=\"sm\" [disabled]=\"page() <= 1\" (click$)=\"prevPage()\">Previous</ed-button>\n <ed-button variant=\"secondary\" outline size=\"sm\" [disabled]=\"page() >= totalPages()\" (click$)=\"nextPage()\">Next</ed-button>\n </div>\n </footer>\n</div>\n", dependencies: [{ kind: "pipe", type: DatePipe, name: "date" }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: IconComponent, selector: "ed-icon", inputs: ["name", "size", "color", "cssClass", "decorative", "ariaHidden", "ariaLabel", "title", "desc", "focusable", "tabIndex"] }, { kind: "component", type: EdsSearchFieldComponent, selector: "eds-search-field", inputs: ["value", "inputId", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange", "enter"] }, { 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"] }, { 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$"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
81
+ }
82
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: AuditPageComponent, decorators: [{
83
+ type: Component,
84
+ args: [{ selector: 'eds-audit-page', imports: [
85
+ DatePipe,
86
+ FormsModule,
87
+ IconComponent,
88
+ EdsSearchFieldComponent,
89
+ SmartTooltipDirective,
90
+ EdSkeletonComponent,
91
+ EdButtonComponent,
92
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'block h-full min-h-0' }, template: "<div class=\"flex h-full min-h-0 flex-col overflow-hidden bg-lighter p-base audit-page\">\n <header class=\"relative z-10 mb-base shrink-0 bg-lighter\">\n <div>\n <h4>Audit log</h4>\n <p class=\"fs-sm text-light\">Track configuration and agent activity</p>\n </div>\n </header>\n\n <div class=\"mb-base flex shrink-0 flex-wrap items-center gap-sm rounded-md bg-white p-base\">\n <eds-search-field\n inputClass=\"form-input min-w-[180px]\"\n placeholder=\"Search action, target, detail\u2026\"\n [value]=\"search()\"\n (valueChange)=\"onSearchInput($event)\"\n (enter)=\"searchSubmit()\"\n />\n <eds-search-field\n type=\"text\"\n inputClass=\"form-input min-w-[180px]\"\n placeholder=\"Filter by actor\"\n [value]=\"actor()\"\n (valueChange)=\"onActorInput($event)\"\n (enter)=\"searchSubmit()\"\n />\n <ed-button variant=\"primary\" fill size=\"sm\" (click$)=\"searchSubmit()\">\n <ed-icon slot=\"prefix\" name=\"search\" [size]=\"16\" />\n Search\n </ed-button>\n </div>\n\n <div class=\"flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-md bg-white p-base\">\n <div class=\"eds-table-scroll min-h-0 min-w-0 flex-1\">\n <table class=\"table-default eds-sticky-table eds-centered-table w-full\" aria-label=\"Audit log\">\n <thead>\n <tr>\n <th class=\"bg-light\">Date</th>\n <th class=\"bg-light\">Actor</th>\n <th class=\"bg-light\">Action</th>\n <th class=\"bg-light\">Target</th>\n <th class=\"bg-light\">Detail</th>\n </tr>\n </thead>\n @if (loading()) {\n <tbody aria-busy=\"true\">\n @for (_ of skeletonRows; track _) {\n <tr>\n <td><ed-skeleton class=\"h-3 w-32\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-24\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-36\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-28\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-48\"></ed-skeleton></td>\n </tr>\n }\n </tbody>\n } @else {\n <tbody>\n @for (event of events(); track event.id) {\n <tr>\n <td class=\"font-['IBM_Plex_Mono'] fs-sm text-light\">{{ event.at | date: 'medium' }}</td>\n <td>\n <span\n class=\"inline-block min-w-0 max-w-48 truncate fs-sm text-dark\"\n [smartTooltip]=\"event.actor\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ event.actor }}</span>\n </td>\n <td>\n <span\n class=\"inline-block min-w-0 max-w-56 truncate fs-sm font-semibold text-dark\"\n [smartTooltip]=\"event.action\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ event.action }}</span>\n </td>\n <td>\n <span\n class=\"inline-block min-w-0 max-w-48 truncate fs-sm text-light\"\n [smartTooltip]=\"displayTarget(event.target)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ displayTarget(event.target) }}</span>\n </td>\n <td>\n <span\n class=\"inline-block min-w-0 max-w-72 truncate\"\n [smartTooltip]=\"event.detail\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ event.detail }}</span>\n </td>\n </tr>\n } @empty {\n <tr class=\"empty-row\">\n <td colspan=\"5\" class=\"py-lg text-center fs-sm text-light\">No events match your filters.</td>\n </tr>\n }\n </tbody>\n }\n </table>\n </div>\n </div>\n\n <footer class=\"mt-base flex shrink-0 items-center justify-between border-t border-light pt-sm\">\n <span class=\"fs-sm text-light\">\n Page {{ page() }} of {{ totalPages() }} \u00B7 {{ total() }} total\n </span>\n <div class=\"flex gap-2\">\n <ed-button variant=\"secondary\" outline size=\"sm\" [disabled]=\"page() <= 1\" (click$)=\"prevPage()\">Previous</ed-button>\n <ed-button variant=\"secondary\" outline size=\"sm\" [disabled]=\"page() >= totalPages()\" (click$)=\"nextPage()\">Next</ed-button>\n </div>\n </footer>\n</div>\n" }]
93
+ }] });
94
+
95
+ export { AuditPageComponent };
96
+ //# sourceMappingURL=edvak99-voice-receptionist-widget-audit-page.component-Df-dtgR3.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edvak99-voice-receptionist-widget-audit-page.component-Df-dtgR3.mjs","sources":["../../../src/lib/pages/audit-page/audit-page.component.ts","../../../src/lib/pages/audit-page/audit-page.component.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, inject, OnInit, signal } from '@angular/core';\nimport { DatePipe } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\n\nimport { AuditEvent } from '../../models/ai-receptionist.types';\nimport { DEFAULT_PAGE_SIZE, totalPages as calcTotalPages } from '../../models/pagination';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\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 { IconComponent } from '../../ui/ed-icon.component';\nimport { EdsSearchFieldComponent } from '../../ui/eds-search-field.component';\n\n@Component({\n selector: 'eds-audit-page',\n imports: [\n DatePipe,\n FormsModule,\n IconComponent,\n EdsSearchFieldComponent,\n SmartTooltipDirective,\n EdSkeletonComponent,\n EdButtonComponent,\n ],\n templateUrl: './audit-page.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: { class: 'block h-full min-h-0' },\n})\nexport class AuditPageComponent implements OnInit {\n private readonly api = inject(AiReceptionistApiService);\n\n protected readonly pageSize = DEFAULT_PAGE_SIZE;\n protected readonly events = signal<AuditEvent[]>([]);\n protected readonly total = signal(0);\n protected readonly page = signal(1);\n protected readonly search = signal('');\n protected readonly actor = signal('');\n protected readonly loading = signal(true);\n protected readonly skeletonRows = TABLE_SKELETON_ROWS;\n\n ngOnInit(): void {\n this.load();\n }\n\n protected load(): void {\n this.loading.set(true);\n this.api\n .getAudit(this.search() || undefined, {\n page: this.page(),\n limit: DEFAULT_PAGE_SIZE,\n actor: this.actor() || undefined,\n })\n .subscribe({\n next: ({ items, total, page }) => {\n this.events.set(items);\n this.total.set(total);\n this.page.set(page);\n this.loading.set(false);\n },\n error: () => this.loading.set(false),\n });\n }\n\n protected onSearchInput(value: string): void {\n this.search.set(value);\n if (!value.trim()) this.searchSubmit();\n }\n\n protected onActorInput(value: string): void {\n this.actor.set(value);\n if (!value.trim()) this.searchSubmit();\n }\n\n protected displayTarget(raw: string | null | undefined): string {\n const t = String(raw ?? '').trim();\n if (!t || /^https?:\\/\\//i.test(t) || /^[0-9a-f]{8}-[0-9a-f]{4}-/i.test(t)) {\n return '—';\n }\n return t;\n }\n\n protected searchSubmit(): void {\n this.page.set(1);\n this.load();\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","<div class=\"flex h-full min-h-0 flex-col overflow-hidden bg-lighter p-base audit-page\">\n <header class=\"relative z-10 mb-base shrink-0 bg-lighter\">\n <div>\n <h4>Audit log</h4>\n <p class=\"fs-sm text-light\">Track configuration and agent activity</p>\n </div>\n </header>\n\n <div class=\"mb-base flex shrink-0 flex-wrap items-center gap-sm rounded-md bg-white p-base\">\n <eds-search-field\n inputClass=\"form-input min-w-[180px]\"\n placeholder=\"Search action, target, detail…\"\n [value]=\"search()\"\n (valueChange)=\"onSearchInput($event)\"\n (enter)=\"searchSubmit()\"\n />\n <eds-search-field\n type=\"text\"\n inputClass=\"form-input min-w-[180px]\"\n placeholder=\"Filter by actor\"\n [value]=\"actor()\"\n (valueChange)=\"onActorInput($event)\"\n (enter)=\"searchSubmit()\"\n />\n <ed-button variant=\"primary\" fill size=\"sm\" (click$)=\"searchSubmit()\">\n <ed-icon slot=\"prefix\" name=\"search\" [size]=\"16\" />\n Search\n </ed-button>\n </div>\n\n <div class=\"flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-md bg-white p-base\">\n <div class=\"eds-table-scroll min-h-0 min-w-0 flex-1\">\n <table class=\"table-default eds-sticky-table eds-centered-table w-full\" aria-label=\"Audit log\">\n <thead>\n <tr>\n <th class=\"bg-light\">Date</th>\n <th class=\"bg-light\">Actor</th>\n <th class=\"bg-light\">Action</th>\n <th class=\"bg-light\">Target</th>\n <th class=\"bg-light\">Detail</th>\n </tr>\n </thead>\n @if (loading()) {\n <tbody aria-busy=\"true\">\n @for (_ of skeletonRows; track _) {\n <tr>\n <td><ed-skeleton class=\"h-3 w-32\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-24\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-36\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-28\"></ed-skeleton></td>\n <td><ed-skeleton class=\"h-3 w-48\"></ed-skeleton></td>\n </tr>\n }\n </tbody>\n } @else {\n <tbody>\n @for (event of events(); track event.id) {\n <tr>\n <td class=\"font-['IBM_Plex_Mono'] fs-sm text-light\">{{ event.at | date: 'medium' }}</td>\n <td>\n <span\n class=\"inline-block min-w-0 max-w-48 truncate fs-sm text-dark\"\n [smartTooltip]=\"event.actor\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ event.actor }}</span>\n </td>\n <td>\n <span\n class=\"inline-block min-w-0 max-w-56 truncate fs-sm font-semibold text-dark\"\n [smartTooltip]=\"event.action\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ event.action }}</span>\n </td>\n <td>\n <span\n class=\"inline-block min-w-0 max-w-48 truncate fs-sm text-light\"\n [smartTooltip]=\"displayTarget(event.target)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ displayTarget(event.target) }}</span>\n </td>\n <td>\n <span\n class=\"inline-block min-w-0 max-w-72 truncate\"\n [smartTooltip]=\"event.detail\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ event.detail }}</span>\n </td>\n </tr>\n } @empty {\n <tr class=\"empty-row\">\n <td colspan=\"5\" class=\"py-lg text-center fs-sm text-light\">No events match your filters.</td>\n </tr>\n }\n </tbody>\n }\n </table>\n </div>\n </div>\n\n <footer class=\"mt-base flex shrink-0 items-center justify-between border-t border-light pt-sm\">\n <span class=\"fs-sm text-light\">\n Page {{ page() }} of {{ totalPages() }} · {{ total() }} total\n </span>\n <div class=\"flex gap-2\">\n <ed-button variant=\"secondary\" outline size=\"sm\" [disabled]=\"page() <= 1\" (click$)=\"prevPage()\">Previous</ed-button>\n <ed-button variant=\"secondary\" outline size=\"sm\" [disabled]=\"page() >= totalPages()\" (click$)=\"nextPage()\">Next</ed-button>\n </div>\n </footer>\n</div>\n"],"names":["calcTotalPages"],"mappings":"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"}
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, input, output, viewChild, signal, computed, effect, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import { RouterLink, ActivatedRoute } from '@angular/router';
4
- import { A as AiReceptionistApiService, T as ToastService, l as toolEventTrackKey, f as EdButtonComponent, I as IconComponent, q as activityTypeLabel, g as EdSkeletonComponent, i as isUnknownCaller } from './edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-DDS7VdnD.mjs';
3
+ import { Router, ActivatedRoute } from '@angular/router';
4
+ import { A as AiReceptionistApiService, T as ToastService, m as toolEventTrackKey, f as EdButtonComponent, I as IconComponent, q as activityTypeLabel, g as EdSkeletonComponent, i as isUnknownCaller } from './edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CJ1L6QeE.mjs';
5
5
  import { DatePipe } from '@angular/common';
6
- import { C as CallRecordingPlayerComponent } from './edvak99-voice-receptionist-widget-call-recording-player.component-4fL-zUWy.mjs';
6
+ import { C as CallRecordingPlayerComponent } from './edvak99-voice-receptionist-widget-call-recording-player.component-BepxNLNQ.mjs';
7
7
  import { S as SmartTooltipDirective } from './edvak99-voice-receptionist-widget-smart-tooltip.directive-ChEdIem3.mjs';
8
- import { C as CallReviewService } from './edvak99-voice-receptionist-widget-call-review.service-BhbCmB1S.mjs';
8
+ import { C as CallReviewService } from './edvak99-voice-receptionist-widget-call-review.service-nFqc30t3.mjs';
9
9
  import { i as isNeedsReview } from './edvak99-voice-receptionist-widget-call-review.util-rWIPxDtQ.mjs';
10
10
 
11
11
  /** Parse tool timestamp strings like "1:02" or "0:42" into seconds. */
@@ -238,6 +238,8 @@ const PREVIEW_LIMIT = 4;
238
238
  class CallTasksPanelComponent {
239
239
  constructor() {
240
240
  this.api = inject(AiReceptionistApiService);
241
+ this.router = inject(Router);
242
+ this.route = inject(ActivatedRoute);
241
243
  this.callId = input.required();
242
244
  this.compact = input(false);
243
245
  this.activities = signal([]);
@@ -248,6 +250,12 @@ class CallTasksPanelComponent {
248
250
  this.activityTypeLabel = activityTypeLabel;
249
251
  this.previewActivities = computed(() => this.activities().slice(0, PREVIEW_LIMIT));
250
252
  }
253
+ openActivities() {
254
+ void this.router.navigate(['../activities'], {
255
+ relativeTo: this.route,
256
+ queryParams: { callId: this.callId() },
257
+ });
258
+ }
251
259
  ngOnInit() {
252
260
  this.api
253
261
  .getActivities({
@@ -285,11 +293,11 @@ class CallTasksPanelComponent {
285
293
  }
286
294
  }
287
295
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CallTasksPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
288
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: CallTasksPanelComponent, isStandalone: true, selector: "eds-call-tasks-panel", inputs: { callId: { classPropertyName: "callId", publicName: "callId", isSignal: true, isRequired: true, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<section class=\"call-tasks rounded-lg border border-base bg-white px-5 py-4 mt-5 shadow-sm\" [class.call-tasks--compact]=\"compact()\">\n <header class=\"mb-4 flex items-center justify-between gap-3\">\n <h4>Activities from this call</h4>\n <a\n routerLink=\"../activities\"\n [queryParams]=\"{ callId: callId() }\"\n class=\"call-tasks__all-link fs-sm text-light\"\n >\n View all Activities\n </a>\n </header>\n\n @if (loading()) {\n <ul class=\"call-tasks__list overflow-hidden rounded-lg border border-base\" aria-busy=\"true\">\n @for (_ of listSkeletonRows; track _) {\n <li class=\"call-tasks__item border-b border-base last:border-b-0\">\n <div class=\"call-tasks__row grid w-full grid-cols-[minmax(0,1fr)_auto] items-center gap-3 px-4 py-3\">\n <div class=\"flex min-w-0 flex-col gap-1\">\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-48\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton>\n </div>\n </li>\n }\n </ul>\n } @else if (activities().length === 0) {\n <p class=\"fs-sm text-light call-tasks__empty\">No activities linked to this call.</p>\n } @else {\n <ul class=\"call-tasks__list overflow-hidden rounded-lg border border-base\">\n @for (item of previewActivities(); track item.id) {\n <li class=\"call-tasks__item border-b border-base last:border-b-0\">\n <div class=\"call-tasks__row grid w-full grid-cols-[minmax(0,1fr)_auto] items-center gap-3 border-none bg-transparent px-4 py-3 text-left font-[inherit]\">\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span\n class=\"call-tasks__title min-w-0 max-w-full overflow-hidden text-ellipsis whitespace-nowrap text-sm font-semibold\"\n [smartTooltip]=\"item.title || activityTypeLabel(item.type)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ item.title || activityTypeLabel(item.type) }}</span>\n <span\n class=\"call-tasks__sub max-w-full overflow-hidden text-ellipsis whitespace-nowrap text-xs\"\n [smartTooltip]=\"activitySubline(item)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ activitySubline(item) }}</span>\n </div>\n <ed-badge-2 [attr.variant]=\"activityTone(item.type)\">{{ activityTypeLabel(item.type) }}</ed-badge-2>\n </div>\n </li>\n }\n </ul>\n @if (total() > previewLimit) {\n <p class=\"call-tasks__more fs-sm text-light mt-3\">\n +{{ total() - previewLimit }} more \u2014\n <a routerLink=\"../activities\" [queryParams]=\"{ callId: callId() }\" class=\"call-tasks__all-link\">\n View all Activities\n </a>\n </p>\n }\n }\n</section>\n", styles: [".call-tasks--compact{margin-top:0;height:100%}.call-tasks__head .eds-h2{margin:0}.call-tasks__all-link{color:var(--eds-text-brand, #2162f0);text-decoration:none;font-weight:500}.call-tasks__all-link:hover{text-decoration:underline}.call-tasks__empty{margin:0;color:var(--eds-text-secondary, #53575c)}.call-tasks__list{list-style:none;margin:0;padding:0}.call-tasks__row--static{cursor:default}.call-tasks__title{color:var(--eds-text-primary, #41464c)}.call-tasks__sub,.call-tasks__more{color:var(--eds-text-secondary, #53575c)}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: EdSkeletonComponent, selector: "ed-skeleton", inputs: ["class"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
296
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: CallTasksPanelComponent, isStandalone: true, selector: "eds-call-tasks-panel", inputs: { callId: { classPropertyName: "callId", publicName: "callId", isSignal: true, isRequired: true, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (loading() || activities().length > 0) {\n<section class=\"call-tasks rounded-lg border border-base bg-white px-5 py-4 mt-5 shadow-sm\" [class.call-tasks--compact]=\"compact()\">\n <header class=\"mb-4 flex items-center justify-between gap-3\">\n <h4>Activities from this call</h4>\n <button\n type=\"button\"\n class=\"eds-plain-nav call-tasks__all-link fs-sm\"\n (click)=\"openActivities()\"\n >\n View all Activities\n </button>\n </header>\n\n @if (loading()) {\n <ul class=\"call-tasks__list overflow-hidden rounded-lg border border-base\" aria-busy=\"true\">\n @for (_ of listSkeletonRows; track _) {\n <li class=\"call-tasks__item border-b border-base last:border-b-0\">\n <div class=\"call-tasks__row grid w-full grid-cols-[minmax(0,1fr)_auto] items-center gap-3 px-4 py-3\">\n <div class=\"flex min-w-0 flex-col gap-1\">\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-48\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton>\n </div>\n </li>\n }\n </ul>\n } @else {\n <ul class=\"call-tasks__list overflow-hidden rounded-lg border border-base\">\n @for (item of previewActivities(); track item.id) {\n <li class=\"call-tasks__item border-b border-base last:border-b-0\">\n <div class=\"call-tasks__row grid w-full grid-cols-[minmax(0,1fr)_auto] items-center gap-3 border-none bg-transparent px-4 py-3 text-left font-[inherit]\">\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span\n class=\"call-tasks__title min-w-0 max-w-full overflow-hidden text-ellipsis whitespace-nowrap text-sm font-semibold\"\n [smartTooltip]=\"item.title || activityTypeLabel(item.type)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ item.title || activityTypeLabel(item.type) }}</span>\n <span\n class=\"call-tasks__sub max-w-full overflow-hidden text-ellipsis whitespace-nowrap text-xs\"\n [smartTooltip]=\"activitySubline(item)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ activitySubline(item) }}</span>\n </div>\n <ed-badge-2 [attr.variant]=\"activityTone(item.type)\">{{ activityTypeLabel(item.type) }}</ed-badge-2>\n </div>\n </li>\n }\n </ul>\n @if (total() > previewLimit) {\n <p class=\"call-tasks__more fs-sm text-light mt-3\">\n +{{ total() - previewLimit }} more \u2014\n <button type=\"button\" class=\"eds-plain-nav call-tasks__all-link\" (click)=\"openActivities()\">\n View all Activities\n </button>\n </p>\n }\n }\n</section>\n}\n", styles: [".call-tasks--compact{margin-top:0;height:100%}.call-tasks__head .eds-h2{margin:0}.call-tasks__all-link{color:var(--eds-text-brand, #2162f0);text-decoration:none;font-weight:500}.call-tasks__all-link:hover{text-decoration:underline}.call-tasks__empty{margin:0;color:var(--eds-text-secondary, #53575c)}.call-tasks__list{list-style:none;margin:0;padding:0}.call-tasks__row--static{cursor:default}.call-tasks__title{color:var(--eds-text-primary, #41464c)}.call-tasks__sub,.call-tasks__more{color:var(--eds-text-secondary, #53575c)}\n"], dependencies: [{ kind: "component", type: EdSkeletonComponent, selector: "ed-skeleton", inputs: ["class"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
289
297
  }
290
298
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CallTasksPanelComponent, decorators: [{
291
299
  type: Component,
292
- args: [{ selector: 'eds-call-tasks-panel', imports: [RouterLink, EdSkeletonComponent, SmartTooltipDirective], changeDetection: ChangeDetectionStrategy.OnPush, schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<section class=\"call-tasks rounded-lg border border-base bg-white px-5 py-4 mt-5 shadow-sm\" [class.call-tasks--compact]=\"compact()\">\n <header class=\"mb-4 flex items-center justify-between gap-3\">\n <h4>Activities from this call</h4>\n <a\n routerLink=\"../activities\"\n [queryParams]=\"{ callId: callId() }\"\n class=\"call-tasks__all-link fs-sm text-light\"\n >\n View all Activities\n </a>\n </header>\n\n @if (loading()) {\n <ul class=\"call-tasks__list overflow-hidden rounded-lg border border-base\" aria-busy=\"true\">\n @for (_ of listSkeletonRows; track _) {\n <li class=\"call-tasks__item border-b border-base last:border-b-0\">\n <div class=\"call-tasks__row grid w-full grid-cols-[minmax(0,1fr)_auto] items-center gap-3 px-4 py-3\">\n <div class=\"flex min-w-0 flex-col gap-1\">\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-48\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton>\n </div>\n </li>\n }\n </ul>\n } @else if (activities().length === 0) {\n <p class=\"fs-sm text-light call-tasks__empty\">No activities linked to this call.</p>\n } @else {\n <ul class=\"call-tasks__list overflow-hidden rounded-lg border border-base\">\n @for (item of previewActivities(); track item.id) {\n <li class=\"call-tasks__item border-b border-base last:border-b-0\">\n <div class=\"call-tasks__row grid w-full grid-cols-[minmax(0,1fr)_auto] items-center gap-3 border-none bg-transparent px-4 py-3 text-left font-[inherit]\">\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span\n class=\"call-tasks__title min-w-0 max-w-full overflow-hidden text-ellipsis whitespace-nowrap text-sm font-semibold\"\n [smartTooltip]=\"item.title || activityTypeLabel(item.type)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ item.title || activityTypeLabel(item.type) }}</span>\n <span\n class=\"call-tasks__sub max-w-full overflow-hidden text-ellipsis whitespace-nowrap text-xs\"\n [smartTooltip]=\"activitySubline(item)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ activitySubline(item) }}</span>\n </div>\n <ed-badge-2 [attr.variant]=\"activityTone(item.type)\">{{ activityTypeLabel(item.type) }}</ed-badge-2>\n </div>\n </li>\n }\n </ul>\n @if (total() > previewLimit) {\n <p class=\"call-tasks__more fs-sm text-light mt-3\">\n +{{ total() - previewLimit }} more \u2014\n <a routerLink=\"../activities\" [queryParams]=\"{ callId: callId() }\" class=\"call-tasks__all-link\">\n View all Activities\n </a>\n </p>\n }\n }\n</section>\n", styles: [".call-tasks--compact{margin-top:0;height:100%}.call-tasks__head .eds-h2{margin:0}.call-tasks__all-link{color:var(--eds-text-brand, #2162f0);text-decoration:none;font-weight:500}.call-tasks__all-link:hover{text-decoration:underline}.call-tasks__empty{margin:0;color:var(--eds-text-secondary, #53575c)}.call-tasks__list{list-style:none;margin:0;padding:0}.call-tasks__row--static{cursor:default}.call-tasks__title{color:var(--eds-text-primary, #41464c)}.call-tasks__sub,.call-tasks__more{color:var(--eds-text-secondary, #53575c)}\n"] }]
300
+ args: [{ selector: 'eds-call-tasks-panel', imports: [EdSkeletonComponent, SmartTooltipDirective], changeDetection: ChangeDetectionStrategy.OnPush, schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "@if (loading() || activities().length > 0) {\n<section class=\"call-tasks rounded-lg border border-base bg-white px-5 py-4 mt-5 shadow-sm\" [class.call-tasks--compact]=\"compact()\">\n <header class=\"mb-4 flex items-center justify-between gap-3\">\n <h4>Activities from this call</h4>\n <button\n type=\"button\"\n class=\"eds-plain-nav call-tasks__all-link fs-sm\"\n (click)=\"openActivities()\"\n >\n View all Activities\n </button>\n </header>\n\n @if (loading()) {\n <ul class=\"call-tasks__list overflow-hidden rounded-lg border border-base\" aria-busy=\"true\">\n @for (_ of listSkeletonRows; track _) {\n <li class=\"call-tasks__item border-b border-base last:border-b-0\">\n <div class=\"call-tasks__row grid w-full grid-cols-[minmax(0,1fr)_auto] items-center gap-3 px-4 py-3\">\n <div class=\"flex min-w-0 flex-col gap-1\">\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-48\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton>\n </div>\n </li>\n }\n </ul>\n } @else {\n <ul class=\"call-tasks__list overflow-hidden rounded-lg border border-base\">\n @for (item of previewActivities(); track item.id) {\n <li class=\"call-tasks__item border-b border-base last:border-b-0\">\n <div class=\"call-tasks__row grid w-full grid-cols-[minmax(0,1fr)_auto] items-center gap-3 border-none bg-transparent px-4 py-3 text-left font-[inherit]\">\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span\n class=\"call-tasks__title min-w-0 max-w-full overflow-hidden text-ellipsis whitespace-nowrap text-sm font-semibold\"\n [smartTooltip]=\"item.title || activityTypeLabel(item.type)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ item.title || activityTypeLabel(item.type) }}</span>\n <span\n class=\"call-tasks__sub max-w-full overflow-hidden text-ellipsis whitespace-nowrap text-xs\"\n [smartTooltip]=\"activitySubline(item)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ activitySubline(item) }}</span>\n </div>\n <ed-badge-2 [attr.variant]=\"activityTone(item.type)\">{{ activityTypeLabel(item.type) }}</ed-badge-2>\n </div>\n </li>\n }\n </ul>\n @if (total() > previewLimit) {\n <p class=\"call-tasks__more fs-sm text-light mt-3\">\n +{{ total() - previewLimit }} more \u2014\n <button type=\"button\" class=\"eds-plain-nav call-tasks__all-link\" (click)=\"openActivities()\">\n View all Activities\n </button>\n </p>\n }\n }\n</section>\n}\n", styles: [".call-tasks--compact{margin-top:0;height:100%}.call-tasks__head .eds-h2{margin:0}.call-tasks__all-link{color:var(--eds-text-brand, #2162f0);text-decoration:none;font-weight:500}.call-tasks__all-link:hover{text-decoration:underline}.call-tasks__empty{margin:0;color:var(--eds-text-secondary, #53575c)}.call-tasks__list{list-style:none;margin:0;padding:0}.call-tasks__row--static{cursor:default}.call-tasks__title{color:var(--eds-text-primary, #41464c)}.call-tasks__sub,.call-tasks__more{color:var(--eds-text-secondary, #53575c)}\n"] }]
293
301
  }] });
294
302
 
295
303
  /** Known history outcomes from GET /calls/history (HistoryCallDto.outcome). */
@@ -347,6 +355,7 @@ class CallHistoryDetailPageComponent {
347
355
  this.reviewService = inject(CallReviewService);
348
356
  this.toast = inject(ToastService);
349
357
  this.route = inject(ActivatedRoute);
358
+ this.router = inject(Router);
350
359
  /** Parent shell route — back targets sibling `history`, not `history/history`. */
351
360
  this.historyListLink = ['history'];
352
361
  this.historyListRelativeTo = this.route.parent;
@@ -397,25 +406,27 @@ class CallHistoryDetailPageComponent {
397
406
  this.detail.set(data);
398
407
  });
399
408
  }
409
+ goBack() {
410
+ void this.router.navigate(this.historyListLink, { relativeTo: this.historyListRelativeTo });
411
+ }
400
412
  formatDuration(sec) {
401
413
  const m = Math.floor(sec / 60);
402
414
  const s = sec % 60;
403
415
  return `${m}:${s.toString().padStart(2, '0')}`;
404
416
  }
405
417
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CallHistoryDetailPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
406
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: CallHistoryDetailPageComponent, isStandalone: true, selector: "eds-call-history-detail-page", host: { classAttribute: "block h-full min-h-0" }, ngImport: i0, template: "<div class=\"flex h-full min-h-0 flex-col overflow-auto bg-lighter p-base call-history-detail-page\">\n <a\n class=\"call-history-detail-page__back mb-base inline-flex shrink-0 items-center gap-1 fs-sm text-light no-underline\"\n [routerLink]=\"historyListLink\"\n [relativeTo]=\"historyListRelativeTo\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"18\" /> Go Back to histories\n </a>\n <div class=\"call-history-detail-page__body flex min-h-0 flex-1 flex-col\">\n\n @if (loading()) {\n <div class=\"flex flex-col gap-4\" aria-busy=\"true\">\n <header class=\"mb-4 flex flex-wrap items-start justify-between gap-4\">\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-6 w-48\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-64\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-9 w-36 !rounded-md\"></ed-skeleton>\n </header>\n <dl class=\"mx-0 mt-0 mb-5 grid grid-cols-2 gap-4\">\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-5 w-24 !rounded-full\"></ed-skeleton>\n </div>\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-4 w-14\"></ed-skeleton>\n </div>\n </dl>\n <div class=\"grid grid-cols-1 gap-4 lg:grid-cols-[minmax(0,1fr)_280px]\">\n <div class=\"flex flex-col gap-3 rounded-lg border border-base bg-white p-4\">\n <ed-skeleton class=\"h-4 w-28\"></ed-skeleton>\n @for (_ of detailSkeletonRows; track _) {\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-10 w-full max-w-lg !rounded-md\"></ed-skeleton>\n </div>\n }\n </div>\n <div class=\"flex flex-col gap-3 rounded-lg border border-base bg-white p-4\">\n <ed-skeleton class=\"h-4 w-36\"></ed-skeleton>\n @for (_ of listSkeletonRows; track _) {\n <div class=\"flex items-center justify-between gap-3 border-b border-base py-3 last:border-b-0\">\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 <ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton>\n </div>\n }\n </div>\n </div>\n </div>\n } @else if (detail()) {\n <header class=\"mb-4 flex shrink-0 flex-wrap items-start justify-between gap-4\">\n <div>\n <h4>{{ detail()!.name }}</h4>\n <p class=\"fs-sm text-light\">{{ detail()!.phone }} \u00B7 {{ detail()!.reason }}</p>\n </div>\n @if (isNeedsReview(detail()!.review)) {\n <ed-button\n variant=\"primary\"\n fill\n size=\"sm\"\n [disabled]=\"markingReview()\"\n (click$)=\"markReviewed()\"\n >\n <ed-icon slot=\"prefix\" name=\"check_circle\" [size]=\"16\" />\n {{ markingReview() ? 'Saving\u2026' : 'Mark as reviewed' }}\n </ed-button>\n }\n </header>\n\n <dl class=\"call-history-detail-page__meta mx-0 mt-0 mb-5 grid shrink-0 grid-cols-2 gap-4 sm:grid-cols-2\">\n <div><dt class=\"fs-sm font-semibold text-light\">Outcome</dt><dd>\n <ed-badge-2 [attr.variant]=\"outcomeTone(detail()!.outcome)\">\n {{ outcomeLabel(detail()!.outcome) }}\n </ed-badge-2>\n </dd></div>\n <div><dt class=\"fs-sm font-semibold text-light\">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=\"fs-sm text-light\">Call not found.</p>\n }\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.call-history-detail-page__back{color:var(--eds-text-secondary)}.call-history-detail-page__body eds-call-conversation-panel{display:flex;flex:1 1 auto;flex-direction:column;min-height:min(60vh,36rem)}.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: IconComponent, selector: "ed-icon", inputs: ["name", "size", "color", "cssClass", "decorative", "ariaHidden", "ariaLabel", "title", "desc", "focusable", "tabIndex"] }, { 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: 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"] }, { kind: "component", type: EdSkeletonComponent, selector: "ed-skeleton", inputs: ["class"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
418
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: CallHistoryDetailPageComponent, isStandalone: true, selector: "eds-call-history-detail-page", host: { classAttribute: "block h-full min-h-0" }, ngImport: i0, template: "<div class=\"flex h-full min-h-0 flex-col overflow-auto bg-lighter p-base call-history-detail-page\">\n <button\n type=\"button\"\n class=\"eds-plain-nav call-history-detail-page__back mb-base fs-sm text-light\"\n (click)=\"goBack()\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"18\" /> Go Back to histories\n </button>\n <div class=\"call-history-detail-page__body flex min-h-0 flex-1 flex-col\">\n\n @if (loading()) {\n <div class=\"flex flex-col gap-4\" aria-busy=\"true\">\n <header class=\"mb-4 flex flex-wrap items-start justify-between gap-4\">\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-6 w-48\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-64\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-9 w-36 !rounded-md\"></ed-skeleton>\n </header>\n <dl class=\"mx-0 mt-0 mb-5 grid grid-cols-2 gap-4\">\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-5 w-24 !rounded-full\"></ed-skeleton>\n </div>\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-4 w-14\"></ed-skeleton>\n </div>\n </dl>\n <div class=\"grid grid-cols-1 gap-4 lg:grid-cols-[minmax(0,1fr)_280px]\">\n <div class=\"flex flex-col gap-3 rounded-lg border border-base bg-white p-4\">\n <ed-skeleton class=\"h-4 w-28\"></ed-skeleton>\n @for (_ of detailSkeletonRows; track _) {\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-10 w-full max-w-lg !rounded-md\"></ed-skeleton>\n </div>\n }\n </div>\n <div class=\"flex flex-col gap-3 rounded-lg border border-base bg-white p-4\">\n <ed-skeleton class=\"h-4 w-36\"></ed-skeleton>\n @for (_ of listSkeletonRows; track _) {\n <div class=\"flex items-center justify-between gap-3 border-b border-base py-3 last:border-b-0\">\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 <ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton>\n </div>\n }\n </div>\n </div>\n </div>\n } @else if (detail()) {\n <header class=\"mb-4 flex shrink-0 flex-wrap items-start justify-between gap-4\">\n <div>\n <h4>{{ detail()!.name }}</h4>\n <p class=\"fs-sm text-light\">{{ detail()!.phone }} \u00B7 {{ detail()!.reason }}</p>\n </div>\n @if (isNeedsReview(detail()!.review)) {\n <ed-button\n variant=\"primary\"\n fill\n size=\"sm\"\n [disabled]=\"markingReview()\"\n (click$)=\"markReviewed()\"\n >\n <ed-icon slot=\"prefix\" name=\"check_circle\" [size]=\"16\" />\n {{ markingReview() ? 'Saving\u2026' : 'Mark as reviewed' }}\n </ed-button>\n } @else if (detail()!.review === 'reviewed') {\n <ed-badge-2 variant=\"success\" pill uppercase>Reviewed</ed-badge-2>\n }\n </header>\n\n <dl class=\"call-history-detail-page__meta mx-0 mt-0 mb-5 grid shrink-0 grid-cols-2 gap-4 sm:grid-cols-2\">\n <div><dt class=\"fs-sm font-semibold text-light\">Outcome</dt><dd>\n <ed-badge-2 [attr.variant]=\"outcomeTone(detail()!.outcome)\">\n {{ outcomeLabel(detail()!.outcome) }}\n </ed-badge-2>\n </dd></div>\n <div><dt class=\"fs-sm font-semibold text-light\">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=\"fs-sm text-light\">Call not found.</p>\n }\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.call-history-detail-page__back{color:var(--eds-text-secondary)}.call-history-detail-page__body eds-call-conversation-panel{display:flex;flex:1 1 auto;flex-direction:column;min-height:min(60vh,36rem)}.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: "component", type: IconComponent, selector: "ed-icon", inputs: ["name", "size", "color", "cssClass", "decorative", "ariaHidden", "ariaLabel", "title", "desc", "focusable", "tabIndex"] }, { 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: 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"] }, { kind: "component", type: EdSkeletonComponent, selector: "ed-skeleton", inputs: ["class"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
407
419
  }
408
420
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CallHistoryDetailPageComponent, decorators: [{
409
421
  type: Component,
410
422
  args: [{ selector: 'eds-call-history-detail-page', imports: [
411
- RouterLink,
412
423
  IconComponent,
413
424
  EdButtonComponent,
414
425
  CallConversationPanelComponent,
415
426
  CallTasksPanelComponent,
416
427
  EdSkeletonComponent,
417
- ], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'block h-full min-h-0' }, schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div class=\"flex h-full min-h-0 flex-col overflow-auto bg-lighter p-base call-history-detail-page\">\n <a\n class=\"call-history-detail-page__back mb-base inline-flex shrink-0 items-center gap-1 fs-sm text-light no-underline\"\n [routerLink]=\"historyListLink\"\n [relativeTo]=\"historyListRelativeTo\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"18\" /> Go Back to histories\n </a>\n <div class=\"call-history-detail-page__body flex min-h-0 flex-1 flex-col\">\n\n @if (loading()) {\n <div class=\"flex flex-col gap-4\" aria-busy=\"true\">\n <header class=\"mb-4 flex flex-wrap items-start justify-between gap-4\">\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-6 w-48\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-64\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-9 w-36 !rounded-md\"></ed-skeleton>\n </header>\n <dl class=\"mx-0 mt-0 mb-5 grid grid-cols-2 gap-4\">\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-5 w-24 !rounded-full\"></ed-skeleton>\n </div>\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-4 w-14\"></ed-skeleton>\n </div>\n </dl>\n <div class=\"grid grid-cols-1 gap-4 lg:grid-cols-[minmax(0,1fr)_280px]\">\n <div class=\"flex flex-col gap-3 rounded-lg border border-base bg-white p-4\">\n <ed-skeleton class=\"h-4 w-28\"></ed-skeleton>\n @for (_ of detailSkeletonRows; track _) {\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-10 w-full max-w-lg !rounded-md\"></ed-skeleton>\n </div>\n }\n </div>\n <div class=\"flex flex-col gap-3 rounded-lg border border-base bg-white p-4\">\n <ed-skeleton class=\"h-4 w-36\"></ed-skeleton>\n @for (_ of listSkeletonRows; track _) {\n <div class=\"flex items-center justify-between gap-3 border-b border-base py-3 last:border-b-0\">\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 <ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton>\n </div>\n }\n </div>\n </div>\n </div>\n } @else if (detail()) {\n <header class=\"mb-4 flex shrink-0 flex-wrap items-start justify-between gap-4\">\n <div>\n <h4>{{ detail()!.name }}</h4>\n <p class=\"fs-sm text-light\">{{ detail()!.phone }} \u00B7 {{ detail()!.reason }}</p>\n </div>\n @if (isNeedsReview(detail()!.review)) {\n <ed-button\n variant=\"primary\"\n fill\n size=\"sm\"\n [disabled]=\"markingReview()\"\n (click$)=\"markReviewed()\"\n >\n <ed-icon slot=\"prefix\" name=\"check_circle\" [size]=\"16\" />\n {{ markingReview() ? 'Saving\u2026' : 'Mark as reviewed' }}\n </ed-button>\n }\n </header>\n\n <dl class=\"call-history-detail-page__meta mx-0 mt-0 mb-5 grid shrink-0 grid-cols-2 gap-4 sm:grid-cols-2\">\n <div><dt class=\"fs-sm font-semibold text-light\">Outcome</dt><dd>\n <ed-badge-2 [attr.variant]=\"outcomeTone(detail()!.outcome)\">\n {{ outcomeLabel(detail()!.outcome) }}\n </ed-badge-2>\n </dd></div>\n <div><dt class=\"fs-sm font-semibold text-light\">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=\"fs-sm text-light\">Call not found.</p>\n }\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.call-history-detail-page__back{color:var(--eds-text-secondary)}.call-history-detail-page__body eds-call-conversation-panel{display:flex;flex:1 1 auto;flex-direction:column;min-height:min(60vh,36rem)}.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"] }]
428
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'block h-full min-h-0' }, schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div class=\"flex h-full min-h-0 flex-col overflow-auto bg-lighter p-base call-history-detail-page\">\n <button\n type=\"button\"\n class=\"eds-plain-nav call-history-detail-page__back mb-base fs-sm text-light\"\n (click)=\"goBack()\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"18\" /> Go Back to histories\n </button>\n <div class=\"call-history-detail-page__body flex min-h-0 flex-1 flex-col\">\n\n @if (loading()) {\n <div class=\"flex flex-col gap-4\" aria-busy=\"true\">\n <header class=\"mb-4 flex flex-wrap items-start justify-between gap-4\">\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-6 w-48\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-64\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-9 w-36 !rounded-md\"></ed-skeleton>\n </header>\n <dl class=\"mx-0 mt-0 mb-5 grid grid-cols-2 gap-4\">\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-5 w-24 !rounded-full\"></ed-skeleton>\n </div>\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-4 w-14\"></ed-skeleton>\n </div>\n </dl>\n <div class=\"grid grid-cols-1 gap-4 lg:grid-cols-[minmax(0,1fr)_280px]\">\n <div class=\"flex flex-col gap-3 rounded-lg border border-base bg-white p-4\">\n <ed-skeleton class=\"h-4 w-28\"></ed-skeleton>\n @for (_ of detailSkeletonRows; track _) {\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-10 w-full max-w-lg !rounded-md\"></ed-skeleton>\n </div>\n }\n </div>\n <div class=\"flex flex-col gap-3 rounded-lg border border-base bg-white p-4\">\n <ed-skeleton class=\"h-4 w-36\"></ed-skeleton>\n @for (_ of listSkeletonRows; track _) {\n <div class=\"flex items-center justify-between gap-3 border-b border-base py-3 last:border-b-0\">\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 <ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton>\n </div>\n }\n </div>\n </div>\n </div>\n } @else if (detail()) {\n <header class=\"mb-4 flex shrink-0 flex-wrap items-start justify-between gap-4\">\n <div>\n <h4>{{ detail()!.name }}</h4>\n <p class=\"fs-sm text-light\">{{ detail()!.phone }} \u00B7 {{ detail()!.reason }}</p>\n </div>\n @if (isNeedsReview(detail()!.review)) {\n <ed-button\n variant=\"primary\"\n fill\n size=\"sm\"\n [disabled]=\"markingReview()\"\n (click$)=\"markReviewed()\"\n >\n <ed-icon slot=\"prefix\" name=\"check_circle\" [size]=\"16\" />\n {{ markingReview() ? 'Saving\u2026' : 'Mark as reviewed' }}\n </ed-button>\n } @else if (detail()!.review === 'reviewed') {\n <ed-badge-2 variant=\"success\" pill uppercase>Reviewed</ed-badge-2>\n }\n </header>\n\n <dl class=\"call-history-detail-page__meta mx-0 mt-0 mb-5 grid shrink-0 grid-cols-2 gap-4 sm:grid-cols-2\">\n <div><dt class=\"fs-sm font-semibold text-light\">Outcome</dt><dd>\n <ed-badge-2 [attr.variant]=\"outcomeTone(detail()!.outcome)\">\n {{ outcomeLabel(detail()!.outcome) }}\n </ed-badge-2>\n </dd></div>\n <div><dt class=\"fs-sm font-semibold text-light\">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=\"fs-sm text-light\">Call not found.</p>\n }\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.call-history-detail-page__back{color:var(--eds-text-secondary)}.call-history-detail-page__body eds-call-conversation-panel{display:flex;flex:1 1 auto;flex-direction:column;min-height:min(60vh,36rem)}.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"] }]
418
429
  }] });
419
430
 
420
431
  export { CallHistoryDetailPageComponent };
421
- //# sourceMappingURL=edvak99-voice-receptionist-widget-call-history-detail-page.component-BT4clUO-.mjs.map
432
+ //# sourceMappingURL=edvak99-voice-receptionist-widget-call-history-detail-page.component-BJGzgVxG.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edvak99-voice-receptionist-widget-call-history-detail-page.component-BJGzgVxG.mjs","sources":["../../../src/lib/utils/transcript-timing.util.ts","../../../src/lib/components/call-conversation-panel/call-conversation-panel.component.ts","../../../src/lib/components/call-conversation-panel/call-conversation-panel.component.html","../../../src/lib/components/call-tasks-panel/call-tasks-panel.component.ts","../../../src/lib/components/call-tasks-panel/call-tasks-panel.component.html","../../../src/lib/utils/call-outcome.util.ts","../../../src/lib/pages/call-history-detail-page/call-history-detail-page.component.ts","../../../src/lib/pages/call-history-detail-page/call-history-detail-page.component.html"],"sourcesContent":["import { ToolEvent, TranscriptLine } from '../models/ai-receptionist.types';\n\nexport interface TimedTranscriptLine extends TranscriptLine {\n startSec: number;\n endSec: number;\n index: number;\n}\n\n/** Parse tool timestamp strings like \"1:02\" or \"0:42\" into seconds. */\nexport function parseClockTime(value: string): number | null {\n const trimmed = value?.trim();\n if (!trimmed) return null;\n const parts = trimmed.split(':').map((p) => Number(p));\n if (parts.some((n) => Number.isNaN(n))) return null;\n if (parts.length === 2) return parts[0] * 60 + parts[1];\n if (parts.length === 3) return parts[0] * 3600 + parts[1] * 60 + parts[2];\n return null;\n}\n\nfunction resolveLineStart(line: TranscriptLine): number | null {\n if (line.at != null && line.at >= 0) return line.at;\n const raw = line as TranscriptLine & { offsetSeconds?: number; startTime?: number };\n if (raw.offsetSeconds != null && raw.offsetSeconds >= 0) return raw.offsetSeconds;\n if (raw.startTime != null && raw.startTime >= 0) return raw.startTime;\n return null;\n}\n\n/**\n * Assign start/end seconds to transcript lines for audio sync.\n * Uses explicit `at` when present; otherwise estimates from call duration.\n */\nexport function buildTimedTranscript(\n lines: TranscriptLine[],\n durationSeconds: number,\n): TimedTranscriptLine[] {\n if (!lines.length) return [];\n\n const total = Math.max(durationSeconds, 1);\n const explicit = lines.map((line) => resolveLineStart(line));\n const allExplicit = explicit.every((t) => t != null);\n\n const starts: number[] = new Array(lines.length).fill(0);\n\n if (allExplicit) {\n for (let i = 0; i < lines.length; i += 1) {\n starts[i] = explicit[i]!;\n }\n } else {\n const speakableCount = lines.filter((l) => l.who !== 'system').length;\n const step = total / Math.max(speakableCount, 1);\n let speakableIdx = 0;\n\n for (let i = 0; i < lines.length; i += 1) {\n if (explicit[i] != null) {\n starts[i] = explicit[i]!;\n continue;\n }\n const line = lines[i];\n if (line.who === 'system') {\n starts[i] = i > 0 ? starts[i - 1] : 0;\n continue;\n }\n starts[i] = speakableIdx * step;\n speakableIdx += 1;\n }\n }\n\n return lines.map((line, index) => {\n const startSec = starts[index];\n const nextStart = starts.slice(index + 1).find((s) => s > startSec);\n const endSec = nextStart ?? total;\n return { ...line, startSec, endSec: Math.max(endSec, startSec + 0.5), index };\n });\n}\n\nexport function activeTranscriptIndex(lines: TimedTranscriptLine[], currentSec: number): number {\n if (!lines.length || currentSec < 0) return -1;\n for (let i = lines.length - 1; i >= 0; i -= 1) {\n if (currentSec >= lines[i].startSec) return i;\n }\n return 0;\n}\n\nexport function formatPlaybackTime(seconds: number): string {\n const s = Math.max(0, Math.floor(seconds));\n const m = Math.floor(s / 60);\n const r = s % 60;\n return `${m}:${r.toString().padStart(2, '0')}`;\n}\n\nexport function toolStateClass(state: ToolEvent['state']): string {\n const map: Record<ToolEvent['state'], string> = {\n ok: 'call-conversation__tool--ok',\n warn: 'call-conversation__tool--warn',\n error: 'call-conversation__tool--error',\n active: 'call-conversation__tool--active',\n };\n return map[state] ?? '';\n}\n\nexport function transcriptRoleLabel(\n who: TranscriptLine['who'],\n callerName?: string | null,\n callerMatched?: boolean,\n): string {\n if (who === 'patient') {\n const name = String(callerName ?? '').trim();\n if (!name || callerMatched === false || /^unknown/i.test(name) || name === '?') {\n return 'Unknown caller';\n }\n return name;\n }\n const labels: Record<Exclude<TranscriptLine['who'], 'patient'>, string> = {\n ai: 'AI receptionist',\n staff: 'Staff',\n system: 'System',\n };\n return labels[who] ?? who;\n}\n","import { DatePipe } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n CUSTOM_ELEMENTS_SCHEMA,\n computed,\n effect,\n ElementRef,\n inject,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\n\nimport { ToolEvent, TranscriptLine, TranscriptWho } from '../../models/ai-receptionist.types';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport { ToastService } from '../../shared/toast.service';\nimport {\n activeTranscriptIndex,\n buildTimedTranscript,\n formatPlaybackTime,\n TimedTranscriptLine,\n transcriptRoleLabel,\n} from '../../utils/transcript-timing.util';\nimport { toolEventTrackKey } from '../../utils/tool-labels.util';\nimport { EdButtonComponent } from '../../ui/ed-button.component';\n\nimport { CallRecordingPlayerComponent } from '../call-recording-player/call-recording-player.component';\nimport { type BadgeTone } from '../../ui/eds-badge.component';\nimport { IconComponent } from '../../ui/ed-icon.component';\n\n@Component({\n selector: 'eds-call-conversation-panel',\n imports: [\n DatePipe,\n CallRecordingPlayerComponent,\n EdButtonComponent,\n IconComponent,\n ],\n templateUrl: './call-conversation-panel.component.html',\n styleUrl: './call-conversation-panel.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n})\nexport class CallConversationPanelComponent {\n private readonly api = inject(AiReceptionistApiService);\n private readonly toast = inject(ToastService);\n\n readonly callId = input.required<string>();\n readonly summary = input.required<string>();\n readonly transcript = input.required<TranscriptLine[]>();\n readonly tools = input.required<ToolEvent[]>();\n readonly callDurationSec = input(0);\n readonly allowRegenerate = input(true);\n readonly callerName = input<string | null>(null);\n readonly callerMatched = input<boolean | null>(null);\n\n readonly summaryRegenerated = output<void>();\n\n private readonly player = viewChild(CallRecordingPlayerComponent);\n private readonly scrollHost = viewChild<ElementRef<HTMLElement>>('scrollHost');\n\n protected readonly currentTime = signal(0);\n protected readonly playbackDuration = signal(0);\n protected readonly summaryExpanded = signal(false);\n private readonly regeneratedSummary = signal<string | null>(null);\n protected readonly displaySummary = computed(\n () => this.regeneratedSummary() ?? this.summary(),\n );\n protected readonly regenerating = signal(false);\n protected readonly summaryMeta = signal<{\n model?: string;\n generatedAt?: string;\n turnCount?: number;\n } | null>(null);\n\n protected readonly timedLines = computed(() =>\n buildTimedTranscript(\n this.transcript(),\n this.playbackDuration() || this.callDurationSec() || 120,\n ),\n );\n\n protected readonly activeIndex = computed(() =>\n activeTranscriptIndex(this.timedLines(), this.currentTime()),\n );\n\n protected readonly hasExplicitTiming = computed(() =>\n this.transcript().some((line) => line.at != null),\n );\n\n protected readonly formatTime = formatPlaybackTime;\n protected readonly toolTrackKey = toolEventTrackKey;\n\n protected roleLabel(who: TranscriptLine['who']): string {\n return transcriptRoleLabel(who, this.callerName(), this.callerMatched() ?? undefined);\n }\n\n protected speakerIcon(who: TranscriptWho | string): string {\n switch (who) {\n case 'ai':\n return 'graph_new';\n case 'staff':\n return 'Robot';\n case 'patient':\n return 'person';\n default:\n return 'info';\n }\n }\n\n protected toolTone(state: string): BadgeTone {\n switch (state) {\n case 'ok':\n return 'success';\n case 'warn':\n return 'warning';\n case 'error':\n return 'danger';\n case 'active':\n return 'primary';\n default:\n return 'light';\n }\n }\n\n constructor() {\n effect(\n () => {\n this.callId();\n this.regeneratedSummary.set(null);\n },\n { allowSignalWrites: true },\n );\n\n effect(() => {\n const idx = this.activeIndex();\n const host = this.scrollHost()?.nativeElement;\n if (idx < 0 || !host) return;\n const row = host.querySelector(`[data-line-index=\"${idx}\"]`);\n if (row instanceof HTMLElement) {\n row.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n }\n });\n }\n\n protected onPlaybackTime(sec: number): void {\n this.currentTime.set(sec);\n }\n\n protected onPlaybackDuration(sec: number): void {\n this.playbackDuration.set(sec);\n }\n\n protected seekLine(line: TimedTranscriptLine): void {\n if (line.who === 'system') return;\n this.player()?.seekTo(line.startSec);\n }\n\n protected toggleSummary(): void {\n this.summaryExpanded.update((v) => !v);\n }\n\n protected regenerateSummary(): void {\n if (this.regenerating()) return;\n\n this.regenerating.set(true);\n this.api.regenerateCallSummary(this.callId()).subscribe({\n next: ({ data }) => {\n this.regenerating.set(false);\n this.regeneratedSummary.set(data.summary);\n this.summaryExpanded.set(true);\n this.summaryMeta.set({\n model: data.summaryModel,\n generatedAt: data.summaryGeneratedAt,\n turnCount: data.transcriptTurnCount,\n });\n this.summaryRegenerated.emit();\n this.toast.show('Call summary regenerated', 'success');\n },\n error: (err: { message?: string }) => {\n this.regenerating.set(false);\n this.toast.show(err.message ?? 'Failed to regenerate summary', 'error');\n },\n });\n }\n}\n","<div class=\"flex min-h-0 flex-1 flex-col gap-4\">\n <div class=\"grid shrink-0 grid-cols-1 items-stretch gap-4 lg:grid-cols-2\">\n <section class=\"rounded-lg border border-base bg-white p-4 shadow-sm\">\n <div class=\"flex items-center justify-between gap-3\">\n <button type=\"button\" class=\"flex min-w-0 flex-1 cursor-pointer items-center gap-1 border-none bg-transparent p-0 text-left\" (click)=\"toggleSummary()\">\n <ed-icon [name]=\"summaryExpanded() ? 'expand_less' : 'expand_more'\" [size]=\"20\" />\n <h4 class=\"m-0\">Call summary</h4>\n </button>\n @if (allowRegenerate()) {\n <ed-button\n variant=\"secondary\"\n outline\n size=\"sm\"\n [disabled]=\"regenerating()\"\n (click$)=\"regenerateSummary()\"\n >\n <ed-icon slot=\"prefix\" name=\"refresh\" [size]=\"16\" />\n {{ regenerating() ? 'Regenerating…' : 'Regenerate' }}\n </ed-button>\n }\n </div>\n @if (summaryExpanded() || displaySummary().length < 180) {\n <p class=\"fs-base text-dark mt-3 leading-relaxed\">{{ displaySummary() }}</p>\n } @else {\n <p class=\"fs-base text-dark mt-3 line-clamp-2 leading-relaxed\">\n {{ displaySummary() }}\n </p>\n <button\n type=\"button\"\n class=\"cursor-pointer border-none bg-transparent px-0 pt-1 text-sm text-blue-600\"\n (click)=\"toggleSummary()\"\n >\n Read full summary\n </button>\n }\n @if (summaryMeta(); as meta) {\n <p class=\"fs-sm text-light mt-3 flex flex-wrap gap-3 text-zinc-500\">\n @if (meta.model) {\n <span>Model: {{ meta.model }}</span>\n }\n @if (meta.generatedAt) {\n <span>Generated {{ meta.generatedAt | date: 'medium' }}</span>\n }\n @if (meta.turnCount != null) {\n <span>{{ meta.turnCount }} transcript turns</span>\n }\n </p>\n }\n </section>\n <ng-content select=\"[summary-side]\" />\n </div>\n\n <section class=\"shrink-0 overflow-hidden rounded-lg border border-base bg-white p-0 shadow-sm\">\n <eds-call-recording-player\n [callId]=\"callId()\"\n (currentTimeChange)=\"onPlaybackTime($event)\"\n (durationChange)=\"onPlaybackDuration($event)\"\n />\n </section>\n\n <div class=\"call-conversation-panel__split grid min-h-0 flex-1 grid-cols-1 items-stretch gap-4 lg:grid-cols-[1fr_300px]\">\n <section\n class=\"call-conversation-panel__transcript flex flex-1 flex-col rounded-lg border border-base bg-white p-4 shadow-sm\"\n aria-labelledby=\"call-transcript-title\"\n >\n <header class=\"mb-3 flex shrink-0 items-center justify-between gap-3\">\n <h4 id=\"call-transcript-title\" class=\"m-0\">Transcript</h4>\n @if (playbackDuration() > 0) {\n <span class=\"font-['IBM_Plex_Mono'] fs-sm text-light text-zinc-500\">\n {{ formatTime(currentTime()) }} / {{ formatTime(playbackDuration()) }}\n </span>\n }\n </header>\n\n <div #scrollHost class=\"chat-thread call-conversation-panel__thread flex-1 overflow-auto rounded-xl border border-zinc-200\" role=\"log\">\n @for (line of timedLines(); track line.index) {\n @if (line.who === 'system') {\n <div class=\"chat-row chat-row--system\">\n <div\n class=\"chat-bubble chat-bubble--system inline-flex items-center gap-2\"\n [class.ring-2]=\"line.index === activeIndex()\"\n [class.ring-blue-200]=\"line.index === activeIndex()\"\n [attr.data-line-index]=\"line.index\"\n >\n <ed-icon name=\"info\" [size]=\"14\" />\n <span>{{ line.text }}</span>\n </div>\n </div>\n } @else {\n <article\n class=\"chat-row cursor-pointer border-none bg-transparent p-0\"\n [class.chat-row--caller]=\"line.who === 'patient'\"\n [class.chat-row--ai]=\"line.who === 'ai'\"\n [class.chat-row--staff]=\"line.who === 'staff'\"\n [attr.data-line-index]=\"line.index\"\n [attr.data-who]=\"line.who\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-current]=\"line.index === activeIndex() ? 'true' : null\"\n (click)=\"seekLine(line)\"\n (keyup.enter)=\"seekLine(line)\"\n >\n <div class=\"chat-meta\">\n <span>{{ roleLabel(line.who) }}</span>\n <span class=\"chat-time\">{{ formatTime(line.startSec) }}</span>\n </div>\n <div class=\"chat-bubble-row\">\n <div\n class=\"chat-avatar\"\n [class.chat-avatar--ai]=\"line.who === 'ai'\"\n [class.chat-avatar--staff]=\"line.who === 'staff'\"\n [class.chat-avatar--caller]=\"line.who === 'patient'\"\n >\n <ed-icon [name]=\"speakerIcon(line.who)\" [size]=\"16\" />\n </div>\n <div\n class=\"chat-bubble\"\n [class.chat-bubble--caller]=\"line.who === 'patient'\"\n [class.chat-bubble--ai]=\"line.who === 'ai'\"\n [class.chat-bubble--staff]=\"line.who === 'staff'\"\n [class.ring-2]=\"line.index === activeIndex()\"\n [class.ring-blue-200]=\"line.index === activeIndex()\"\n >\n <p class=\"chat-content\">{{ line.text }}</p>\n </div>\n </div>\n </article>\n }\n } @empty {\n <p class=\"fs-sm text-light py-3 text-zinc-500\">No transcript available for this call.</p>\n }\n </div>\n</section>\n\n <aside class=\"flex min-h-0 flex-col overflow-hidden rounded-lg border border-base bg-white p-4 shadow-sm\" aria-labelledby=\"call-goal-timeline-title\">\n <header class=\"mb-3 flex items-center justify-between gap-3\">\n <h4 id=\"call-goal-timeline-title\" class=\"m-0\">Goal Timeline</h4>\n <span class=\"fs-sm text-light\">{{ tools().length }}</span>\n </header>\n\n <ul class=\"m-0 flex min-h-0 list-none flex-1 flex-col gap-3 overflow-auto p-0\">\n @for (tool of tools(); track toolTrackKey(tool, $index)) {\n <li\n [class]=\"\n 'grid grid-cols-[auto_1fr_auto] items-start gap-3 rounded-md border-l-4 bg-zinc-50 p-3 ' +\n (tool.state === 'ok'\n ? 'border-l-green-500'\n : tool.state === 'warn'\n ? 'border-l-amber-500'\n : tool.state === 'error'\n ? 'border-l-red-500'\n : tool.state === 'active'\n ? 'border-l-blue-600'\n : 'border-l-zinc-400')\n \"\n >\n <span class=\"font-['IBM_Plex_Mono'] fs-sm text-light whitespace-nowrap text-zinc-500\">{{ tool.t }}</span>\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span class=\"fs-sm font-semibold text-dark\">{{ tool.name }}</span>\n <span class=\"fs-sm text-light\">{{ tool.result }}</span>\n </div>\n <ed-badge-2 [attr.variant]=\"toolTone(tool.state)\">{{ tool.state }}</ed-badge-2>\n </li>\n } @empty {\n <li class=\"fs-sm text-light py-3 text-zinc-500\">No goal activity recorded.</li>\n }\n </ul>\n </aside>\n </div>\n</div>\n","import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, computed, inject, input, OnInit, signal } from '@angular/core';\nimport { ActivatedRoute, Router } from '@angular/router';\n\nimport { EdSkeletonComponent } from '../../ui/ed-skeleton.component';\n\nimport { SmartTooltipDirective } from '../../shared/smart-tooltip.directive';\nimport { BadgeTone } from '../../ui/eds-badge.component';\nimport {\n AgentActivity,\n activityTypeLabel,\n} from '../../models/agent-activity.types';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\n\nconst PREVIEW_LIMIT = 4;\n\n@Component({\n selector: 'eds-call-tasks-panel',\n imports: [EdSkeletonComponent, SmartTooltipDirective],\n templateUrl: './call-tasks-panel.component.html',\n styleUrl: './call-tasks-panel.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n})\nexport class CallTasksPanelComponent implements OnInit {\n private readonly api = inject(AiReceptionistApiService);\n private readonly router = inject(Router);\n private readonly route = inject(ActivatedRoute);\n\n readonly callId = input.required<string>();\n readonly compact = input(false);\n\n protected readonly activities = signal<AgentActivity[]>([]);\n protected readonly total = signal(0);\n protected readonly loading = signal(true);\n protected readonly listSkeletonRows = [0, 1, 2] as const;\n protected readonly previewLimit = PREVIEW_LIMIT;\n protected readonly activityTypeLabel = activityTypeLabel;\n\n protected readonly previewActivities = computed(() =>\n this.activities().slice(0, PREVIEW_LIMIT),\n );\n\n protected openActivities(): void {\n void this.router.navigate(['../activities'], {\n relativeTo: this.route,\n queryParams: { callId: this.callId() },\n });\n }\n\n ngOnInit(): void {\n this.api\n .getActivities({\n callId: this.callId(),\n page: 1,\n limit: 50,\n })\n .subscribe({\n next: ({ items, total }) => {\n this.activities.set(items);\n this.total.set(total);\n this.loading.set(false);\n },\n error: () => this.loading.set(false),\n });\n }\n\n protected activitySubline(item: AgentActivity): string {\n const bits = [\n item.patientName,\n item.visitType,\n item.providerName,\n ].filter(Boolean);\n return bits.join(' · ') || item.detail || '—';\n }\n\n protected activityTone(type: string): BadgeTone {\n switch (type) {\n case 'appointment_booked':\n return 'primary';\n case 'patient_created':\n return 'success';\n case 'task_created':\n return 'warning';\n default:\n return 'light';\n }\n }\n}\n","@if (loading() || activities().length > 0) {\n<section class=\"call-tasks rounded-lg border border-base bg-white px-5 py-4 mt-5 shadow-sm\" [class.call-tasks--compact]=\"compact()\">\n <header class=\"mb-4 flex items-center justify-between gap-3\">\n <h4>Activities from this call</h4>\n <button\n type=\"button\"\n class=\"eds-plain-nav call-tasks__all-link fs-sm\"\n (click)=\"openActivities()\"\n >\n View all Activities\n </button>\n </header>\n\n @if (loading()) {\n <ul class=\"call-tasks__list overflow-hidden rounded-lg border border-base\" aria-busy=\"true\">\n @for (_ of listSkeletonRows; track _) {\n <li class=\"call-tasks__item border-b border-base last:border-b-0\">\n <div class=\"call-tasks__row grid w-full grid-cols-[minmax(0,1fr)_auto] items-center gap-3 px-4 py-3\">\n <div class=\"flex min-w-0 flex-col gap-1\">\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-48\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton>\n </div>\n </li>\n }\n </ul>\n } @else {\n <ul class=\"call-tasks__list overflow-hidden rounded-lg border border-base\">\n @for (item of previewActivities(); track item.id) {\n <li class=\"call-tasks__item border-b border-base last:border-b-0\">\n <div class=\"call-tasks__row grid w-full grid-cols-[minmax(0,1fr)_auto] items-center gap-3 border-none bg-transparent px-4 py-3 text-left font-[inherit]\">\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span\n class=\"call-tasks__title min-w-0 max-w-full overflow-hidden text-ellipsis whitespace-nowrap text-sm font-semibold\"\n [smartTooltip]=\"item.title || activityTypeLabel(item.type)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ item.title || activityTypeLabel(item.type) }}</span>\n <span\n class=\"call-tasks__sub max-w-full overflow-hidden text-ellipsis whitespace-nowrap text-xs\"\n [smartTooltip]=\"activitySubline(item)\"\n [tooltipOnlyWhenTruncated]=\"true\"\n >{{ activitySubline(item) }}</span>\n </div>\n <ed-badge-2 [attr.variant]=\"activityTone(item.type)\">{{ activityTypeLabel(item.type) }}</ed-badge-2>\n </div>\n </li>\n }\n </ul>\n @if (total() > previewLimit) {\n <p class=\"call-tasks__more fs-sm text-light mt-3\">\n +{{ total() - previewLimit }} more —\n <button type=\"button\" class=\"eds-plain-nav call-tasks__all-link\" (click)=\"openActivities()\">\n View all Activities\n </button>\n </p>\n }\n }\n</section>\n}\n","import { BadgeTone } from '../ui/eds-badge.component';\n\n/** Known history outcomes from GET /calls/history (HistoryCallDto.outcome). */\nexport const HISTORY_OUTCOMES = [\n 'completed',\n 'failed',\n 'transferred',\n 'escalated',\n] as const;\n\nexport type HistoryOutcome = (typeof HISTORY_OUTCOMES)[number] | 'custom';\n\nexport function normalizeHistoryOutcome(outcome: string): HistoryOutcome {\n const key = outcome.trim().toLowerCase();\n if ((HISTORY_OUTCOMES as readonly string[]).includes(key)) {\n return key as HistoryOutcome;\n }\n return 'custom';\n}\n\n/** Badge tone for history table / detail — separate from lifecycle or live UI status. */\nexport function outcomeBadgeTone(outcome: string): BadgeTone {\n switch (normalizeHistoryOutcome(outcome)) {\n case 'completed':\n return 'success';\n case 'failed':\n return 'danger';\n case 'transferred':\n return 'opened';\n case 'escalated':\n return 'danger';\n default: {\n const key = outcome.trim().toLowerCase();\n if (key.includes('transfer')) return 'opened';\n if (key.includes('fail') || key.includes('escalat') || key.includes('abandon')) return 'danger';\n if (key.includes('voicemail')) return 'light';\n if (key.includes('complete') || key.includes('book') || key.includes('task')) return 'success';\n return 'primary';\n }\n }\n}\n\nexport function formatOutcomeLabel(outcome: string): string {\n const trimmed = outcome.trim();\n if (!trimmed) return 'Unknown';\n const known = normalizeHistoryOutcome(trimmed);\n if (known === 'custom') return trimmed;\n return known.charAt(0).toUpperCase() + known.slice(1);\n}\n","import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, inject, OnInit, signal } from '@angular/core';\nimport { ActivatedRoute, Router } from '@angular/router';\n\nimport { EdButtonComponent } from '../../ui/ed-button.component';\nimport { EdSkeletonComponent } from '../../ui/ed-skeleton.component';\n\nimport { CallConversationPanelComponent } from '../../components/call-conversation-panel/call-conversation-panel.component';\nimport { CallTasksPanelComponent } from '../../components/call-tasks-panel/call-tasks-panel.component';\nimport { HistoryDetail } from '../../models/ai-receptionist.types';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport { CallReviewService } from '../../services/call-review.service';\nimport { formatOutcomeLabel, outcomeBadgeTone } from '../../utils/call-outcome.util';\nimport {\n isNeedsReview,\n} from '../../utils/call-review.util';\nimport { isUnknownCaller } from '../../utils/call-history-display.util';\nimport { IconComponent } from '../../ui/ed-icon.component';\nimport { ToastService } from '../../shared/toast.service';\n\n@Component({\n selector: 'eds-call-history-detail-page',\n imports: [\n IconComponent,\n EdButtonComponent,\n CallConversationPanelComponent,\n CallTasksPanelComponent,\n EdSkeletonComponent,\n ],\n templateUrl: './call-history-detail-page.component.html',\n styleUrl: './call-history-detail-page.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: { class: 'block h-full min-h-0' },\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n})\nexport class CallHistoryDetailPageComponent implements OnInit {\n private readonly api = inject(AiReceptionistApiService);\n private readonly reviewService = inject(CallReviewService);\n private readonly toast = inject(ToastService);\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n\n /** Parent shell route — back targets sibling `history`, not `history/history`. */\n protected readonly historyListLink: string[] = ['history'];\n protected readonly historyListRelativeTo = this.route.parent;\n\n protected readonly detail = signal<HistoryDetail | null>(null);\n protected readonly loading = signal(true);\n protected readonly markingReview = signal(false);\n protected readonly detailSkeletonRows = [0, 1, 2, 3, 4] as const;\n protected readonly listSkeletonRows = [0, 1, 2] as const;\n\n protected isNeedsReview = isNeedsReview;\n protected outcomeTone = outcomeBadgeTone;\n protected outcomeLabel = formatOutcomeLabel;\n\n protected isUnknownName(name: string | null | undefined): boolean {\n return isUnknownCaller(name);\n }\n\n ngOnInit(): void {\n const id = this.route.snapshot.paramMap.get('id') ?? '';\n this.api.getCallDetail(id).subscribe(({ data }) => {\n this.detail.set(data);\n this.loading.set(false);\n });\n }\n\n protected markReviewed(): void {\n const d = this.detail();\n if (!d || !isNeedsReview(d.review) || this.markingReview()) return;\n\n this.markingReview.set(true);\n const prev = d.review;\n this.detail.update((current) =>\n current ? { ...current, review: 'reviewed' } : current,\n );\n\n this.reviewService.markReviewed(d.id).subscribe({\n next: () => {\n this.markingReview.set(false);\n this.toast.show('Call marked as reviewed', 'success');\n },\n error: () => {\n this.markingReview.set(false);\n this.detail.update((current) =>\n current ? { ...current, review: prev } : current,\n );\n this.toast.show('Failed to mark call as reviewed', 'error');\n },\n });\n }\n\n protected refreshCallDetail(): void {\n const id = this.detail()?.id;\n if (!id) return;\n this.api.getCallDetail(id).subscribe(({ data }) => {\n if (data) this.detail.set(data);\n });\n }\n\n protected goBack(): void {\n void this.router.navigate(this.historyListLink, { relativeTo: this.historyListRelativeTo });\n }\n\n protected 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 min-h-0 flex-col overflow-auto bg-lighter p-base call-history-detail-page\">\n <button\n type=\"button\"\n class=\"eds-plain-nav call-history-detail-page__back mb-base fs-sm text-light\"\n (click)=\"goBack()\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"18\" /> Go Back to histories\n </button>\n <div class=\"call-history-detail-page__body flex min-h-0 flex-1 flex-col\">\n\n @if (loading()) {\n <div class=\"flex flex-col gap-4\" aria-busy=\"true\">\n <header class=\"mb-4 flex flex-wrap items-start justify-between gap-4\">\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-6 w-48\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-64\"></ed-skeleton>\n </div>\n <ed-skeleton class=\"h-9 w-36 !rounded-md\"></ed-skeleton>\n </header>\n <dl class=\"mx-0 mt-0 mb-5 grid grid-cols-2 gap-4\">\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-5 w-24 !rounded-full\"></ed-skeleton>\n </div>\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-4 w-14\"></ed-skeleton>\n </div>\n </dl>\n <div class=\"grid grid-cols-1 gap-4 lg:grid-cols-[minmax(0,1fr)_280px]\">\n <div class=\"flex flex-col gap-3 rounded-lg border border-base bg-white p-4\">\n <ed-skeleton class=\"h-4 w-28\"></ed-skeleton>\n @for (_ of detailSkeletonRows; track _) {\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-16\"></ed-skeleton>\n <ed-skeleton class=\"h-10 w-full max-w-lg !rounded-md\"></ed-skeleton>\n </div>\n }\n </div>\n <div class=\"flex flex-col gap-3 rounded-lg border border-base bg-white p-4\">\n <ed-skeleton class=\"h-4 w-36\"></ed-skeleton>\n @for (_ of listSkeletonRows; track _) {\n <div class=\"flex items-center justify-between gap-3 border-b border-base py-3 last:border-b-0\">\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 <ed-skeleton class=\"h-5 w-20 !rounded-full\"></ed-skeleton>\n </div>\n }\n </div>\n </div>\n </div>\n } @else if (detail()) {\n <header class=\"mb-4 flex shrink-0 flex-wrap items-start justify-between gap-4\">\n <div>\n <h4>{{ detail()!.name }}</h4>\n <p class=\"fs-sm text-light\">{{ detail()!.phone }} · {{ detail()!.reason }}</p>\n </div>\n @if (isNeedsReview(detail()!.review)) {\n <ed-button\n variant=\"primary\"\n fill\n size=\"sm\"\n [disabled]=\"markingReview()\"\n (click$)=\"markReviewed()\"\n >\n <ed-icon slot=\"prefix\" name=\"check_circle\" [size]=\"16\" />\n {{ markingReview() ? 'Saving…' : 'Mark as reviewed' }}\n </ed-button>\n } @else if (detail()!.review === 'reviewed') {\n <ed-badge-2 variant=\"success\" pill uppercase>Reviewed</ed-badge-2>\n }\n </header>\n\n <dl class=\"call-history-detail-page__meta mx-0 mt-0 mb-5 grid shrink-0 grid-cols-2 gap-4 sm:grid-cols-2\">\n <div><dt class=\"fs-sm font-semibold text-light\">Outcome</dt><dd>\n <ed-badge-2 [attr.variant]=\"outcomeTone(detail()!.outcome)\">\n {{ outcomeLabel(detail()!.outcome) }}\n </ed-badge-2>\n </dd></div>\n <div><dt class=\"fs-sm font-semibold text-light\">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=\"fs-sm text-light\">Call not found.</p>\n }\n </div>\n</div>\n"],"names":[],"mappings":"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"}