@edvak99/voice-receptionist-widget 1.1.20 → 1.1.21

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 (42) hide show
  1. package/fesm2022/{edvak99-voice-receptionist-widget-activities-page.component-CLpNIrcb.mjs → edvak99-voice-receptionist-widget-activities-page.component-CpXa1J9-.mjs} +3 -3
  2. package/fesm2022/{edvak99-voice-receptionist-widget-activities-page.component-CLpNIrcb.mjs.map → edvak99-voice-receptionist-widget-activities-page.component-CpXa1J9-.mjs.map} +1 -1
  3. package/fesm2022/edvak99-voice-receptionist-widget-analytics-page.component-CmImX5FN.mjs +435 -0
  4. package/fesm2022/edvak99-voice-receptionist-widget-analytics-page.component-CmImX5FN.mjs.map +1 -0
  5. package/fesm2022/{edvak99-voice-receptionist-widget-audit-page.component-DwHRYqNe.mjs → edvak99-voice-receptionist-widget-audit-page.component-DTAB2WTX.mjs} +2 -2
  6. package/fesm2022/{edvak99-voice-receptionist-widget-audit-page.component-DwHRYqNe.mjs.map → edvak99-voice-receptionist-widget-audit-page.component-DTAB2WTX.mjs.map} +1 -1
  7. package/fesm2022/{edvak99-voice-receptionist-widget-call-history-detail-page.component-gdOpQsoM.mjs → edvak99-voice-receptionist-widget-call-history-detail-page.component-BT4clUO-.mjs} +4 -4
  8. package/fesm2022/{edvak99-voice-receptionist-widget-call-history-detail-page.component-gdOpQsoM.mjs.map → edvak99-voice-receptionist-widget-call-history-detail-page.component-BT4clUO-.mjs.map} +1 -1
  9. package/fesm2022/{edvak99-voice-receptionist-widget-call-history-page.component-CDOyFwGI.mjs → edvak99-voice-receptionist-widget-call-history-page.component-BACON4uq.mjs} +3 -3
  10. package/fesm2022/{edvak99-voice-receptionist-widget-call-history-page.component-CDOyFwGI.mjs.map → edvak99-voice-receptionist-widget-call-history-page.component-BACON4uq.mjs.map} +1 -1
  11. package/fesm2022/{edvak99-voice-receptionist-widget-call-recording-player.component-o0bttL-m.mjs → edvak99-voice-receptionist-widget-call-recording-player.component-4fL-zUWy.mjs} +2 -2
  12. package/fesm2022/{edvak99-voice-receptionist-widget-call-recording-player.component-o0bttL-m.mjs.map → edvak99-voice-receptionist-widget-call-recording-player.component-4fL-zUWy.mjs.map} +1 -1
  13. package/fesm2022/{edvak99-voice-receptionist-widget-call-review.service-B3y421d_.mjs → edvak99-voice-receptionist-widget-call-review.service-BhbCmB1S.mjs} +2 -2
  14. package/fesm2022/{edvak99-voice-receptionist-widget-call-review.service-B3y421d_.mjs.map → edvak99-voice-receptionist-widget-call-review.service-BhbCmB1S.mjs.map} +1 -1
  15. package/fesm2022/{edvak99-voice-receptionist-widget-dashboard-page.component-CWAsroOR.mjs → edvak99-voice-receptionist-widget-dashboard-page.component-CxNYLBbg.mjs} +2 -2
  16. package/fesm2022/{edvak99-voice-receptionist-widget-dashboard-page.component-CWAsroOR.mjs.map → edvak99-voice-receptionist-widget-dashboard-page.component-CxNYLBbg.mjs.map} +1 -1
  17. package/fesm2022/{edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-BEyM4U02.mjs → edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-DDS7VdnD.mjs} +26 -19
  18. package/fesm2022/edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-DDS7VdnD.mjs.map +1 -0
  19. package/fesm2022/{edvak99-voice-receptionist-widget-live-calls-page.component-BEhbKM1c.mjs → edvak99-voice-receptionist-widget-live-calls-page.component-4LtgT4lS.mjs} +2 -2
  20. package/fesm2022/{edvak99-voice-receptionist-widget-live-calls-page.component-BEhbKM1c.mjs.map → edvak99-voice-receptionist-widget-live-calls-page.component-4LtgT4lS.mjs.map} +1 -1
  21. package/fesm2022/{edvak99-voice-receptionist-widget-live-monitor-page.component-DrqhaEEw.mjs → edvak99-voice-receptionist-widget-live-monitor-page.component-B1lKfw-j.mjs} +8 -29
  22. package/fesm2022/edvak99-voice-receptionist-widget-live-monitor-page.component-B1lKfw-j.mjs.map +1 -0
  23. package/fesm2022/{edvak99-voice-receptionist-widget-outbound-purposes-page.component-DTqLwtvb.mjs → edvak99-voice-receptionist-widget-outbound-purposes-page.component-BkIHblSu.mjs} +2 -2
  24. package/fesm2022/{edvak99-voice-receptionist-widget-outbound-purposes-page.component-DTqLwtvb.mjs.map → edvak99-voice-receptionist-widget-outbound-purposes-page.component-BkIHblSu.mjs.map} +1 -1
  25. package/fesm2022/{edvak99-voice-receptionist-widget-task-detail-drawer.component-lW-CQ71m.mjs → edvak99-voice-receptionist-widget-task-detail-drawer.component-aDTKTV79.mjs} +2 -2
  26. package/fesm2022/{edvak99-voice-receptionist-widget-task-detail-drawer.component-lW-CQ71m.mjs.map → edvak99-voice-receptionist-widget-task-detail-drawer.component-aDTKTV79.mjs.map} +1 -1
  27. package/fesm2022/{edvak99-voice-receptionist-widget-tasks-page.component-MBm-mLFO.mjs → edvak99-voice-receptionist-widget-tasks-page.component-Dj1nWx6V.mjs} +3 -3
  28. package/fesm2022/{edvak99-voice-receptionist-widget-tasks-page.component-MBm-mLFO.mjs.map → edvak99-voice-receptionist-widget-tasks-page.component-Dj1nWx6V.mjs.map} +1 -1
  29. package/fesm2022/{edvak99-voice-receptionist-widget-wizard-page.component-CgK05X9O.mjs → edvak99-voice-receptionist-widget-wizard-page.component-CQttbEzW.mjs} +2 -2
  30. package/fesm2022/{edvak99-voice-receptionist-widget-wizard-page.component-CgK05X9O.mjs.map → edvak99-voice-receptionist-widget-wizard-page.component-CQttbEzW.mjs.map} +1 -1
  31. package/fesm2022/edvak99-voice-receptionist-widget.mjs +1 -1
  32. package/lib/components/live-transcript-panel/live-transcript-panel.component.d.ts +1 -5
  33. package/lib/models/ai-receptionist.types.d.ts +2 -0
  34. package/lib/pages/analytics-page/analytics-page.component.d.ts +17 -8
  35. package/lib/pages/live-monitor-page/live-monitor-page.component.d.ts +0 -2
  36. package/lib/services/ai-receptionist-api.service.d.ts +1 -0
  37. package/package.json +1 -1
  38. package/styles/embed.scss +2 -1
  39. package/fesm2022/edvak99-voice-receptionist-widget-analytics-page.component-D5ze9OdJ.mjs +0 -416
  40. package/fesm2022/edvak99-voice-receptionist-widget-analytics-page.component-D5ze9OdJ.mjs.map +0 -1
  41. package/fesm2022/edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-BEyM4U02.mjs.map +0 -1
  42. package/fesm2022/edvak99-voice-receptionist-widget-live-monitor-page.component-DrqhaEEw.mjs.map +0 -1
@@ -5,9 +5,9 @@ import { ActivatedRoute, RouterLink } from '@angular/router';
5
5
  import * as i1 from '@angular/forms';
6
6
  import { FormsModule } from '@angular/forms';
7
7
  import { firstValueFrom } from 'rxjs';
8
- import { j as resolveToolKey, k as resolveToolDisplayName, D as DashboardSocketService, V as VOICE_RECEPTIONIST_CONFIG, i as isUnknownCaller, I as IconComponent, A as AiReceptionistApiService, T as ToastService, l as toolEventTrackKey, c as callerMetaLine, b as ageFromDob, E as EdAvatarComponent, f as EdButtonComponent, g as EdSkeletonComponent } from './edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-BEyM4U02.mjs';
8
+ import { j as resolveToolKey, k as resolveToolDisplayName, D as DashboardSocketService, V as VOICE_RECEPTIONIST_CONFIG, i as isUnknownCaller, I as IconComponent, A as AiReceptionistApiService, T as ToastService, l as toolEventTrackKey, c as callerMetaLine, b as ageFromDob, E as EdAvatarComponent, f as EdButtonComponent, g as EdSkeletonComponent } from './edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-DDS7VdnD.mjs';
9
9
  import { E as EdsElapsedPipe, a as sentimentLabel, s as sentimentIconSrc } from './edvak99-voice-receptionist-widget-eds-elapsed.pipe-Dra7e7xN.mjs';
10
- import { C as CallRecordingPlayerComponent } from './edvak99-voice-receptionist-widget-call-recording-player.component-o0bttL-m.mjs';
10
+ import { C as CallRecordingPlayerComponent } from './edvak99-voice-receptionist-widget-call-recording-player.component-4fL-zUWy.mjs';
11
11
  import { Track, Room, RoomEvent, ConnectionState } from 'livekit-client';
12
12
 
13
13
  function mapChunkToLine(chunk) {
@@ -291,8 +291,6 @@ class LiveTranscriptPanelComponent {
291
291
  this.paused = input(false);
292
292
  this.humanTakeover = input(false);
293
293
  this.showStaffInput = input(false);
294
- /** Co-Pilot chips + purple send control (Figma live monitor). */
295
- this.showCopilot = input(false);
296
294
  /** Call start ms for the Recording timer pill. */
297
295
  this.callStarted = input(null);
298
296
  this.staffMessage = input('');
@@ -315,12 +313,6 @@ class LiveTranscriptPanelComponent {
315
313
  return 'Unknown Caller';
316
314
  return name || 'Unknown Caller';
317
315
  });
318
- this.copilotChips = [
319
- 'Ask for MRN',
320
- 'Create Task: Follow Up',
321
- 'Ask for full Name & DOB',
322
- 'Verify Phone Number',
323
- ];
324
316
  this.shouldScroll = false;
325
317
  effect(() => {
326
318
  this.lines();
@@ -371,9 +363,6 @@ class LiveTranscriptPanelComponent {
371
363
  onStaffInput(value) {
372
364
  this.staffMessageChange.emit(value);
373
365
  }
374
- onChipClick(chip) {
375
- this.staffMessageChange.emit(chip);
376
- }
377
366
  onSend() {
378
367
  this.sendMessage.emit();
379
368
  }
@@ -381,13 +370,13 @@ class LiveTranscriptPanelComponent {
381
370
  this.shouldScroll = true;
382
371
  }
383
372
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: LiveTranscriptPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
384
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: LiveTranscriptPanelComponent, isStandalone: true, selector: "eds-live-transcript-panel", inputs: { live: { classPropertyName: "live", publicName: "live", isSignal: true, isRequired: false, transformFunction: null }, paused: { classPropertyName: "paused", publicName: "paused", isSignal: true, isRequired: false, transformFunction: null }, humanTakeover: { classPropertyName: "humanTakeover", publicName: "humanTakeover", isSignal: true, isRequired: false, transformFunction: null }, showStaffInput: { classPropertyName: "showStaffInput", publicName: "showStaffInput", isSignal: true, isRequired: false, transformFunction: null }, showCopilot: { classPropertyName: "showCopilot", publicName: "showCopilot", isSignal: true, isRequired: false, transformFunction: null }, callStarted: { classPropertyName: "callStarted", publicName: "callStarted", isSignal: true, isRequired: false, transformFunction: null }, staffMessage: { classPropertyName: "staffMessage", publicName: "staffMessage", isSignal: true, isRequired: false, transformFunction: null }, callerName: { classPropertyName: "callerName", publicName: "callerName", isSignal: true, isRequired: false, transformFunction: null }, callerMatched: { classPropertyName: "callerMatched", publicName: "callerMatched", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { staffMessageChange: "staffMessageChange", sendMessage: "sendMessage" }, host: { classAttribute: "flex h-full min-h-0 flex-1 flex-col max-[900px]:h-auto max-[900px]:max-h-none max-[900px]:min-h-[360px]" }, viewQueries: [{ propertyName: "scrollHost", first: true, predicate: ["scrollHost"], descendants: true }], ngImport: i0, template: "<section\n class=\"flex h-full min-h-0 flex-1 flex-col overflow-hidden rounded-xl bg-white p-4 max-[900px]:h-auto max-[900px]:max-h-none max-[900px]:min-h-[360px]\"\n aria-labelledby=\"live-transcript-title\"\n>\n <header class=\"mb-4 flex shrink-0 items-center justify-between gap-3\">\n <div class=\"flex min-w-0 items-center gap-2\">\n <h4 id=\"live-transcript-title\" class=\"m-0\">Live Transcript</h4>\n @if (live() && !paused()) {\n <span class=\"live-transcript-panel__recording inline-flex h-5 items-center gap-1 rounded px-1 text-red-600\">\n <span class=\"h-1.5 w-1.5 rounded-full bg-red-600\" aria-hidden=\"true\"></span>\n Recording\n </span>\n }\n </div>\n @if (callStarted()) {\n <span class=\"live-transcript-panel__timer inline-flex items-center gap-0.5 rounded-full bg-green-500/10 px-1 py-0.5 text-green-700\">\n <span class=\"h-1.5 w-1.5 rounded-full bg-green-600\" aria-hidden=\"true\"></span>\n <span class=\"font-mono uppercase tracking-wide\">{{ callStarted() | edsElapsed }}</span>\n </span>\n }\n </header>\n\n <div #scrollHost class=\"chat-thread live-transcript-panel__thread\" role=\"log\" aria-live=\"polite\">\n @for (line of lines(); track $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.border-emerald-200]=\"line.flag === 'verify'\"\n [class.bg-emerald-50]=\"line.flag === 'verify'\"\n [class.text-emerald-700]=\"line.flag === 'verify'\"\n [class.border-amber-200]=\"line.flag === 'fail' || line.flag === 'escalate'\"\n [class.bg-amber-50]=\"line.flag === 'fail' || line.flag === 'escalate'\"\n [class.text-amber-700]=\"line.flag === 'fail' || line.flag === 'escalate'\"\n >\n <ed-icon [name]=\"systemIcon(line.flag)\" [size]=\"14\" />\n <span>{{ line.text }}</span>\n </div>\n </div>\n } @else {\n <article\n class=\"chat-row\"\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 >\n <div class=\"chat-meta\">\n <span [class.live-transcript-panel__meta--ai]=\"line.who === 'ai'\">{{ roleLabel(line.who) }}</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.live-transcript-panel__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 >\n <p class=\"chat-content\">{{ line.text }}</p>\n </div>\n </div>\n </article>\n }\n }\n\n @if (patientInterim(); as interim) {\n <article class=\"chat-row chat-row--caller\">\n <div class=\"chat-meta\">\n <span>{{ callerLabel() }}</span>\n </div>\n <div class=\"chat-bubble-row\">\n <div class=\"chat-avatar chat-avatar--caller\">\n <ed-icon name=\"person\" [size]=\"16\" />\n </div>\n <div class=\"chat-bubble chat-bubble--caller chat-bubble--interim live-transcript-panel__typing\">\n <span class=\"live-transcript-panel__dot\" aria-hidden=\"true\"></span>\n <span class=\"live-transcript-panel__dot\" aria-hidden=\"true\"></span>\n <span class=\"live-transcript-panel__dot\" aria-hidden=\"true\"></span>\n <span class=\"sr-only\">{{ interim }}</span>\n </div>\n </div>\n </article>\n }\n\n @if (staffInterim(); as interim) {\n <article class=\"chat-row chat-row--staff\">\n <div class=\"chat-meta\"><span>Staff</span></div>\n <div class=\"chat-bubble-row\">\n <div class=\"chat-avatar chat-avatar--staff\">\n <ed-icon name=\"Robot\" [size]=\"16\" />\n </div>\n <div class=\"chat-bubble chat-bubble--staff chat-bubble--interim\">\n <p class=\"chat-content\">{{ interim }}</p>\n </div>\n </div>\n </article>\n }\n\n @if (aiInterim(); as interim) {\n <article class=\"chat-row chat-row--ai\">\n <div class=\"chat-meta\">\n <span class=\"live-transcript-panel__meta--ai\">AI Receptionist</span>\n </div>\n <div class=\"chat-bubble-row\">\n <div class=\"chat-avatar chat-avatar--ai live-transcript-panel__avatar--ai\">\n <ed-icon name=\"graph_new\" [size]=\"16\" />\n </div>\n <div class=\"chat-bubble chat-bubble--ai chat-bubble--interim\">\n <p class=\"chat-content\">\n {{ interim }}<span class=\"live-transcript-panel__caret\" aria-hidden=\"true\"></span>\n </p>\n </div>\n </div>\n </article>\n }\n\n @if (lines().length === 0 && !patientInterim() && !aiInterim() && !staffInterim()) {\n <p class=\"m-0 px-3 py-8 text-center text-zinc-500\">Waiting for conversation\u2026</p>\n }\n </div>\n\n @if (showCopilot() || showStaffInput()) {\n <footer class=\"mt-4 flex shrink-0 flex-col gap-4\">\n @if (showCopilot()) {\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"inline-flex items-center justify-center rounded-md bg-purple-500/10 p-1 text-purple-700\">\n <ed-icon name=\"sparkle\" [size]=\"12\" />\n </span>\n @for (chip of copilotChips; track chip) {\n <button\n type=\"button\"\n class=\"live-transcript-panel__chip inline-flex h-5 items-center rounded border border-zinc-200 bg-white px-1 text-zinc-700\"\n (click)=\"onChipClick(chip)\"\n >\n {{ chip }}\n </button>\n }\n </div>\n }\n\n <div class=\"flex items-center gap-2 rounded-lg border border-zinc-200 p-2\">\n <input\n type=\"text\"\n class=\"h-8 min-w-0 flex-1 border-0 bg-transparent px-1 text-zinc-900 outline-none placeholder:text-zinc-400\"\n [placeholder]=\"showCopilot() ? 'Tell the AI what it should know or do next\u2026' : 'Type to speak as staff\u2026'\"\n [ngModel]=\"staffMessage()\"\n (ngModelChange)=\"onStaffInput($event)\"\n (keyup.enter)=\"onSend()\"\n autocomplete=\"off\"\n />\n @if (showCopilot()) {\n <button\n type=\"button\"\n class=\"live-transcript-panel__copilot-btn inline-flex h-8 shrink-0 items-center gap-0.5 rounded-md bg-purple-600 px-2 text-white\"\n (click)=\"onSend()\"\n >\n Co-Pilot\n <ed-icon name=\"sparkle\" [size]=\"14\" />\n </button>\n }\n </div>\n </footer>\n }\n</section>\n", styles: ["@charset \"UTF-8\";.chat-thread{display:flex;flex-direction:column;gap:0;flex:1 1 auto;min-height:0;overflow:auto;padding:1rem 1.5rem;background:#fff;scroll-behavior:smooth}.chat-row{display:flex;flex-direction:column;width:100%;margin-bottom:1rem}.chat-row--caller,.chat-row--user,.chat-row--patient{align-items:flex-start}.chat-row--agent,.chat-row--ai,.chat-row--staff{align-items:flex-end}.chat-row--tool,.chat-row--system{align-items:center}.chat-meta{display:flex;align-items:center;gap:.5rem;margin-bottom:.25rem;font-size:.875rem;color:var(--color-text-light, #6b7280)}.chat-row--agent .chat-meta,.chat-row--ai .chat-meta,.chat-row--staff .chat-meta{justify-content:flex-end;padding-right:2.75rem}.chat-bubble-row{display:flex;align-items:flex-start;gap:.5rem;max-width:min(72%,40rem)}.chat-row--agent .chat-bubble-row,.chat-row--ai .chat-bubble-row,.chat-row--staff .chat-bubble-row{flex-direction:row-reverse}.chat-avatar{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border-radius:9999px}.chat-avatar--ai{background:#ad46ff1f;color:#8200db}.chat-avatar--staff{border:1px solid #ddd6fe;background:#f5f3ff;color:#6d28d9}.chat-avatar--caller{background:#e5e7eb;color:#4b5563}.chat-bubble{max-width:100%;padding:.75rem 1rem;font-size:.875rem;line-height:1.5;word-break:break-word;white-space:pre-wrap}.chat-bubble--caller,.chat-bubble--user,.chat-bubble--patient{border:1px solid var(--color-border-light, #e5e7eb);border-radius:0 .5rem .5rem;background:#fff;color:var(--color-text-dark, #111827)}.chat-bubble--agent,.chat-bubble--ai{border:none;border-radius:.5rem;background:#ad46ff1a;color:var(--color-text-dark, #53575c)}.chat-bubble--staff{border:1px solid #ddd6fe;border-radius:.5rem 0 .5rem .5rem;background:#f5f3ff;color:#4c1d95}.chat-bubble--tool,.chat-bubble--system{max-width:min(90%,40rem);padding:.5rem .75rem;border:1px solid var(--color-border-light, #e5e7eb);border-radius:9999px;background:#f9fafb;color:#6b7280;font-size:.75rem;text-align:center}.chat-bubble--interim{opacity:.9;font-style:italic}.chat-content{margin:0}.chat-time{font-size:.75rem;color:#9ca3af}.live-transcript-panel__thread.chat-thread{background:#f7f9fa;border-radius:.75rem;padding:1rem;min-height:0}@media(max-width:900px){.live-transcript-panel__thread.chat-thread{max-height:min(60vh,36rem)}}.live-transcript-panel__avatar--ai{background:#ad46ff1f;color:#8200db}.live-transcript-panel__meta--ai{color:#8200db}.live-transcript-panel__caret{display:inline-block;width:7px;height:14px;margin-left:2px;vertical-align:text-bottom;background:#8200db;animation:eds-caret 1s step-end infinite}.live-transcript-panel__typing{display:inline-flex;align-items:center;gap:4px;min-width:2.5rem;min-height:1.25rem}.live-transcript-panel__chip{cursor:pointer}.live-transcript-panel__chip:hover{background:#f7f9fa}.live-transcript-panel__copilot-btn{cursor:pointer;border:0}.live-transcript-panel__dot{width:6px;height:6px;border-radius:9999px;background:#a2a4a6;animation:eds-typing 1.2s ease-in-out infinite}.live-transcript-panel__dot:nth-child(2){animation-delay:.15s}.live-transcript-panel__dot:nth-child(3){animation-delay:.3s}@keyframes eds-caret{50%{opacity:0}}@keyframes eds-typing{0%,80%,to{opacity:.35;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IconComponent, selector: "ed-icon", inputs: ["name", "size", "color", "cssClass", "decorative", "ariaHidden", "ariaLabel", "title", "desc", "focusable", "tabIndex"] }, { kind: "pipe", type: EdsElapsedPipe, name: "edsElapsed" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
373
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: LiveTranscriptPanelComponent, isStandalone: true, selector: "eds-live-transcript-panel", inputs: { live: { classPropertyName: "live", publicName: "live", isSignal: true, isRequired: false, transformFunction: null }, paused: { classPropertyName: "paused", publicName: "paused", isSignal: true, isRequired: false, transformFunction: null }, humanTakeover: { classPropertyName: "humanTakeover", publicName: "humanTakeover", isSignal: true, isRequired: false, transformFunction: null }, showStaffInput: { classPropertyName: "showStaffInput", publicName: "showStaffInput", isSignal: true, isRequired: false, transformFunction: null }, callStarted: { classPropertyName: "callStarted", publicName: "callStarted", isSignal: true, isRequired: false, transformFunction: null }, staffMessage: { classPropertyName: "staffMessage", publicName: "staffMessage", isSignal: true, isRequired: false, transformFunction: null }, callerName: { classPropertyName: "callerName", publicName: "callerName", isSignal: true, isRequired: false, transformFunction: null }, callerMatched: { classPropertyName: "callerMatched", publicName: "callerMatched", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { staffMessageChange: "staffMessageChange", sendMessage: "sendMessage" }, host: { classAttribute: "flex h-full min-h-0 flex-1 flex-col overflow-hidden" }, viewQueries: [{ propertyName: "scrollHost", first: true, predicate: ["scrollHost"], descendants: true }], ngImport: i0, template: "<section\n class=\"flex h-full min-h-0 flex-1 flex-col overflow-hidden rounded-xl bg-white p-4\"\n aria-labelledby=\"live-transcript-title\"\n>\n <header class=\"mb-4 flex shrink-0 items-center justify-between gap-3\">\n <div class=\"flex min-w-0 items-center gap-2\">\n <h4 id=\"live-transcript-title\" class=\"m-0\">Live Transcript</h4>\n @if (live() && !paused()) {\n <span class=\"live-transcript-panel__recording inline-flex h-5 items-center gap-1 rounded px-1 text-red-600\">\n <span class=\"h-1.5 w-1.5 rounded-full bg-red-600\" aria-hidden=\"true\"></span>\n Recording\n </span>\n }\n </div>\n @if (callStarted()) {\n <span class=\"live-transcript-panel__timer inline-flex items-center gap-0.5 rounded-full bg-green-500/10 px-1 py-0.5 text-green-700\">\n <span class=\"h-1.5 w-1.5 rounded-full bg-green-600\" aria-hidden=\"true\"></span>\n <span class=\"font-mono uppercase tracking-wide\">{{ callStarted() | edsElapsed }}</span>\n </span>\n }\n </header>\n\n <div #scrollHost class=\"chat-thread live-transcript-panel__thread\" role=\"log\" aria-live=\"polite\">\n @for (line of lines(); track $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.border-emerald-200]=\"line.flag === 'verify'\"\n [class.bg-emerald-50]=\"line.flag === 'verify'\"\n [class.text-emerald-700]=\"line.flag === 'verify'\"\n [class.border-amber-200]=\"line.flag === 'fail' || line.flag === 'escalate'\"\n [class.bg-amber-50]=\"line.flag === 'fail' || line.flag === 'escalate'\"\n [class.text-amber-700]=\"line.flag === 'fail' || line.flag === 'escalate'\"\n >\n <ed-icon [name]=\"systemIcon(line.flag)\" [size]=\"14\" />\n <span>{{ line.text }}</span>\n </div>\n </div>\n } @else {\n <article\n class=\"chat-row\"\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 >\n <div class=\"chat-meta\">\n <span [class.live-transcript-panel__meta--ai]=\"line.who === 'ai'\">{{ roleLabel(line.who) }}</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.live-transcript-panel__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 >\n <p class=\"chat-content\">{{ line.text }}</p>\n </div>\n </div>\n </article>\n }\n }\n\n @if (patientInterim(); as interim) {\n <article class=\"chat-row chat-row--caller\">\n <div class=\"chat-meta\">\n <span>{{ callerLabel() }}</span>\n </div>\n <div class=\"chat-bubble-row\">\n <div class=\"chat-avatar chat-avatar--caller\">\n <ed-icon name=\"person\" [size]=\"16\" />\n </div>\n <div class=\"chat-bubble chat-bubble--caller chat-bubble--interim live-transcript-panel__typing\">\n <span class=\"live-transcript-panel__dot\" aria-hidden=\"true\"></span>\n <span class=\"live-transcript-panel__dot\" aria-hidden=\"true\"></span>\n <span class=\"live-transcript-panel__dot\" aria-hidden=\"true\"></span>\n <span class=\"sr-only\">{{ interim }}</span>\n </div>\n </div>\n </article>\n }\n\n @if (staffInterim(); as interim) {\n <article class=\"chat-row chat-row--staff\">\n <div class=\"chat-meta\"><span>Staff</span></div>\n <div class=\"chat-bubble-row\">\n <div class=\"chat-avatar chat-avatar--staff\">\n <ed-icon name=\"Robot\" [size]=\"16\" />\n </div>\n <div class=\"chat-bubble chat-bubble--staff chat-bubble--interim\">\n <p class=\"chat-content\">{{ interim }}</p>\n </div>\n </div>\n </article>\n }\n\n @if (aiInterim(); as interim) {\n <article class=\"chat-row chat-row--ai\">\n <div class=\"chat-meta\">\n <span class=\"live-transcript-panel__meta--ai\">AI Receptionist</span>\n </div>\n <div class=\"chat-bubble-row\">\n <div class=\"chat-avatar chat-avatar--ai live-transcript-panel__avatar--ai\">\n <ed-icon name=\"graph_new\" [size]=\"16\" />\n </div>\n <div class=\"chat-bubble chat-bubble--ai chat-bubble--interim\">\n <p class=\"chat-content\">\n {{ interim }}<span class=\"live-transcript-panel__caret\" aria-hidden=\"true\"></span>\n </p>\n </div>\n </div>\n </article>\n }\n\n @if (lines().length === 0 && !patientInterim() && !aiInterim() && !staffInterim()) {\n <p class=\"m-0 px-3 py-8 text-center text-zinc-500\">Waiting for conversation\u2026</p>\n }\n </div>\n\n @if (showStaffInput()) {\n <footer class=\"mt-4 flex shrink-0 flex-col gap-4\">\n <div class=\"flex items-center gap-2 rounded-lg border border-zinc-200 p-2\">\n <input\n type=\"text\"\n class=\"h-8 min-w-0 flex-1 border-0 bg-transparent px-1 text-zinc-900 outline-none placeholder:text-zinc-400\"\n placeholder=\"Type to speak as staff\u2026\"\n [ngModel]=\"staffMessage()\"\n (ngModelChange)=\"onStaffInput($event)\"\n (keyup.enter)=\"onSend()\"\n autocomplete=\"off\"\n />\n </div>\n </footer>\n }\n</section>\n", styles: ["@charset \"UTF-8\";.chat-thread{display:flex;flex-direction:column;gap:0;flex:1 1 auto;min-height:0;overflow:auto;padding:1rem 1.5rem;background:#fff;scroll-behavior:smooth}.chat-row{display:flex;flex-direction:column;width:100%;margin-bottom:1rem}.chat-row--caller,.chat-row--user,.chat-row--patient{align-items:flex-start}.chat-row--agent,.chat-row--ai,.chat-row--staff{align-items:flex-end}.chat-row--tool,.chat-row--system{align-items:center}.chat-meta{display:flex;align-items:center;gap:.5rem;margin-bottom:.25rem;font-size:.875rem;color:var(--color-text-light, #6b7280)}.chat-row--agent .chat-meta,.chat-row--ai .chat-meta,.chat-row--staff .chat-meta{justify-content:flex-end;padding-right:2.75rem}.chat-bubble-row{display:flex;align-items:flex-start;gap:.5rem;max-width:min(72%,40rem)}.chat-row--agent .chat-bubble-row,.chat-row--ai .chat-bubble-row,.chat-row--staff .chat-bubble-row{flex-direction:row-reverse}.chat-avatar{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border-radius:9999px}.chat-avatar--ai{background:#ad46ff1f;color:#8200db}.chat-avatar--staff{border:1px solid #ddd6fe;background:#f5f3ff;color:#6d28d9}.chat-avatar--caller{background:#e5e7eb;color:#4b5563}.chat-bubble{max-width:100%;padding:.75rem 1rem;font-size:.875rem;line-height:1.5;word-break:break-word;white-space:pre-wrap}.chat-bubble--caller,.chat-bubble--user,.chat-bubble--patient{border:1px solid var(--color-border-light, #e5e7eb);border-radius:0 .5rem .5rem;background:#fff;color:var(--color-text-dark, #111827)}.chat-bubble--agent,.chat-bubble--ai{border:none;border-radius:.5rem;background:#ad46ff1a;color:var(--color-text-dark, #53575c)}.chat-bubble--staff{border:1px solid #ddd6fe;border-radius:.5rem 0 .5rem .5rem;background:#f5f3ff;color:#4c1d95}.chat-bubble--tool,.chat-bubble--system{max-width:min(90%,40rem);padding:.5rem .75rem;border:1px solid var(--color-border-light, #e5e7eb);border-radius:9999px;background:#f9fafb;color:#6b7280;font-size:.75rem;text-align:center}.chat-bubble--interim{opacity:.9;font-style:italic}.chat-content{margin:0}.chat-time{font-size:.75rem;color:#9ca3af}.live-transcript-panel__thread.chat-thread{flex:1 1 auto;min-height:0;overflow:auto;background:#f7f9fa;border-radius:.75rem;padding:1rem}.live-transcript-panel__avatar--ai{background:#ad46ff1f;color:#8200db}.live-transcript-panel__meta--ai{color:#8200db}.live-transcript-panel__caret{display:inline-block;width:7px;height:14px;margin-left:2px;vertical-align:text-bottom;background:#8200db;animation:eds-caret 1s step-end infinite}.live-transcript-panel__typing{display:inline-flex;align-items:center;gap:4px;min-width:2.5rem;min-height:1.25rem}.live-transcript-panel__dot{width:6px;height:6px;border-radius:9999px;background:#a2a4a6;animation:eds-typing 1.2s ease-in-out infinite}.live-transcript-panel__dot:nth-child(2){animation-delay:.15s}.live-transcript-panel__dot:nth-child(3){animation-delay:.3s}@keyframes eds-caret{50%{opacity:0}}@keyframes eds-typing{0%,80%,to{opacity:.35;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IconComponent, selector: "ed-icon", inputs: ["name", "size", "color", "cssClass", "decorative", "ariaHidden", "ariaLabel", "title", "desc", "focusable", "tabIndex"] }, { kind: "pipe", type: EdsElapsedPipe, name: "edsElapsed" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
385
374
  }
386
375
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: LiveTranscriptPanelComponent, decorators: [{
387
376
  type: Component,
388
377
  args: [{ selector: 'eds-live-transcript-panel', imports: [FormsModule, IconComponent, EdsElapsedPipe], changeDetection: ChangeDetectionStrategy.OnPush, host: {
389
- class: 'flex h-full min-h-0 flex-1 flex-col max-[900px]:h-auto max-[900px]:max-h-none max-[900px]:min-h-[360px]',
390
- }, template: "<section\n class=\"flex h-full min-h-0 flex-1 flex-col overflow-hidden rounded-xl bg-white p-4 max-[900px]:h-auto max-[900px]:max-h-none max-[900px]:min-h-[360px]\"\n aria-labelledby=\"live-transcript-title\"\n>\n <header class=\"mb-4 flex shrink-0 items-center justify-between gap-3\">\n <div class=\"flex min-w-0 items-center gap-2\">\n <h4 id=\"live-transcript-title\" class=\"m-0\">Live Transcript</h4>\n @if (live() && !paused()) {\n <span class=\"live-transcript-panel__recording inline-flex h-5 items-center gap-1 rounded px-1 text-red-600\">\n <span class=\"h-1.5 w-1.5 rounded-full bg-red-600\" aria-hidden=\"true\"></span>\n Recording\n </span>\n }\n </div>\n @if (callStarted()) {\n <span class=\"live-transcript-panel__timer inline-flex items-center gap-0.5 rounded-full bg-green-500/10 px-1 py-0.5 text-green-700\">\n <span class=\"h-1.5 w-1.5 rounded-full bg-green-600\" aria-hidden=\"true\"></span>\n <span class=\"font-mono uppercase tracking-wide\">{{ callStarted() | edsElapsed }}</span>\n </span>\n }\n </header>\n\n <div #scrollHost class=\"chat-thread live-transcript-panel__thread\" role=\"log\" aria-live=\"polite\">\n @for (line of lines(); track $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.border-emerald-200]=\"line.flag === 'verify'\"\n [class.bg-emerald-50]=\"line.flag === 'verify'\"\n [class.text-emerald-700]=\"line.flag === 'verify'\"\n [class.border-amber-200]=\"line.flag === 'fail' || line.flag === 'escalate'\"\n [class.bg-amber-50]=\"line.flag === 'fail' || line.flag === 'escalate'\"\n [class.text-amber-700]=\"line.flag === 'fail' || line.flag === 'escalate'\"\n >\n <ed-icon [name]=\"systemIcon(line.flag)\" [size]=\"14\" />\n <span>{{ line.text }}</span>\n </div>\n </div>\n } @else {\n <article\n class=\"chat-row\"\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 >\n <div class=\"chat-meta\">\n <span [class.live-transcript-panel__meta--ai]=\"line.who === 'ai'\">{{ roleLabel(line.who) }}</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.live-transcript-panel__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 >\n <p class=\"chat-content\">{{ line.text }}</p>\n </div>\n </div>\n </article>\n }\n }\n\n @if (patientInterim(); as interim) {\n <article class=\"chat-row chat-row--caller\">\n <div class=\"chat-meta\">\n <span>{{ callerLabel() }}</span>\n </div>\n <div class=\"chat-bubble-row\">\n <div class=\"chat-avatar chat-avatar--caller\">\n <ed-icon name=\"person\" [size]=\"16\" />\n </div>\n <div class=\"chat-bubble chat-bubble--caller chat-bubble--interim live-transcript-panel__typing\">\n <span class=\"live-transcript-panel__dot\" aria-hidden=\"true\"></span>\n <span class=\"live-transcript-panel__dot\" aria-hidden=\"true\"></span>\n <span class=\"live-transcript-panel__dot\" aria-hidden=\"true\"></span>\n <span class=\"sr-only\">{{ interim }}</span>\n </div>\n </div>\n </article>\n }\n\n @if (staffInterim(); as interim) {\n <article class=\"chat-row chat-row--staff\">\n <div class=\"chat-meta\"><span>Staff</span></div>\n <div class=\"chat-bubble-row\">\n <div class=\"chat-avatar chat-avatar--staff\">\n <ed-icon name=\"Robot\" [size]=\"16\" />\n </div>\n <div class=\"chat-bubble chat-bubble--staff chat-bubble--interim\">\n <p class=\"chat-content\">{{ interim }}</p>\n </div>\n </div>\n </article>\n }\n\n @if (aiInterim(); as interim) {\n <article class=\"chat-row chat-row--ai\">\n <div class=\"chat-meta\">\n <span class=\"live-transcript-panel__meta--ai\">AI Receptionist</span>\n </div>\n <div class=\"chat-bubble-row\">\n <div class=\"chat-avatar chat-avatar--ai live-transcript-panel__avatar--ai\">\n <ed-icon name=\"graph_new\" [size]=\"16\" />\n </div>\n <div class=\"chat-bubble chat-bubble--ai chat-bubble--interim\">\n <p class=\"chat-content\">\n {{ interim }}<span class=\"live-transcript-panel__caret\" aria-hidden=\"true\"></span>\n </p>\n </div>\n </div>\n </article>\n }\n\n @if (lines().length === 0 && !patientInterim() && !aiInterim() && !staffInterim()) {\n <p class=\"m-0 px-3 py-8 text-center text-zinc-500\">Waiting for conversation\u2026</p>\n }\n </div>\n\n @if (showCopilot() || showStaffInput()) {\n <footer class=\"mt-4 flex shrink-0 flex-col gap-4\">\n @if (showCopilot()) {\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"inline-flex items-center justify-center rounded-md bg-purple-500/10 p-1 text-purple-700\">\n <ed-icon name=\"sparkle\" [size]=\"12\" />\n </span>\n @for (chip of copilotChips; track chip) {\n <button\n type=\"button\"\n class=\"live-transcript-panel__chip inline-flex h-5 items-center rounded border border-zinc-200 bg-white px-1 text-zinc-700\"\n (click)=\"onChipClick(chip)\"\n >\n {{ chip }}\n </button>\n }\n </div>\n }\n\n <div class=\"flex items-center gap-2 rounded-lg border border-zinc-200 p-2\">\n <input\n type=\"text\"\n class=\"h-8 min-w-0 flex-1 border-0 bg-transparent px-1 text-zinc-900 outline-none placeholder:text-zinc-400\"\n [placeholder]=\"showCopilot() ? 'Tell the AI what it should know or do next\u2026' : 'Type to speak as staff\u2026'\"\n [ngModel]=\"staffMessage()\"\n (ngModelChange)=\"onStaffInput($event)\"\n (keyup.enter)=\"onSend()\"\n autocomplete=\"off\"\n />\n @if (showCopilot()) {\n <button\n type=\"button\"\n class=\"live-transcript-panel__copilot-btn inline-flex h-8 shrink-0 items-center gap-0.5 rounded-md bg-purple-600 px-2 text-white\"\n (click)=\"onSend()\"\n >\n Co-Pilot\n <ed-icon name=\"sparkle\" [size]=\"14\" />\n </button>\n }\n </div>\n </footer>\n }\n</section>\n", styles: ["@charset \"UTF-8\";.chat-thread{display:flex;flex-direction:column;gap:0;flex:1 1 auto;min-height:0;overflow:auto;padding:1rem 1.5rem;background:#fff;scroll-behavior:smooth}.chat-row{display:flex;flex-direction:column;width:100%;margin-bottom:1rem}.chat-row--caller,.chat-row--user,.chat-row--patient{align-items:flex-start}.chat-row--agent,.chat-row--ai,.chat-row--staff{align-items:flex-end}.chat-row--tool,.chat-row--system{align-items:center}.chat-meta{display:flex;align-items:center;gap:.5rem;margin-bottom:.25rem;font-size:.875rem;color:var(--color-text-light, #6b7280)}.chat-row--agent .chat-meta,.chat-row--ai .chat-meta,.chat-row--staff .chat-meta{justify-content:flex-end;padding-right:2.75rem}.chat-bubble-row{display:flex;align-items:flex-start;gap:.5rem;max-width:min(72%,40rem)}.chat-row--agent .chat-bubble-row,.chat-row--ai .chat-bubble-row,.chat-row--staff .chat-bubble-row{flex-direction:row-reverse}.chat-avatar{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border-radius:9999px}.chat-avatar--ai{background:#ad46ff1f;color:#8200db}.chat-avatar--staff{border:1px solid #ddd6fe;background:#f5f3ff;color:#6d28d9}.chat-avatar--caller{background:#e5e7eb;color:#4b5563}.chat-bubble{max-width:100%;padding:.75rem 1rem;font-size:.875rem;line-height:1.5;word-break:break-word;white-space:pre-wrap}.chat-bubble--caller,.chat-bubble--user,.chat-bubble--patient{border:1px solid var(--color-border-light, #e5e7eb);border-radius:0 .5rem .5rem;background:#fff;color:var(--color-text-dark, #111827)}.chat-bubble--agent,.chat-bubble--ai{border:none;border-radius:.5rem;background:#ad46ff1a;color:var(--color-text-dark, #53575c)}.chat-bubble--staff{border:1px solid #ddd6fe;border-radius:.5rem 0 .5rem .5rem;background:#f5f3ff;color:#4c1d95}.chat-bubble--tool,.chat-bubble--system{max-width:min(90%,40rem);padding:.5rem .75rem;border:1px solid var(--color-border-light, #e5e7eb);border-radius:9999px;background:#f9fafb;color:#6b7280;font-size:.75rem;text-align:center}.chat-bubble--interim{opacity:.9;font-style:italic}.chat-content{margin:0}.chat-time{font-size:.75rem;color:#9ca3af}.live-transcript-panel__thread.chat-thread{background:#f7f9fa;border-radius:.75rem;padding:1rem;min-height:0}@media(max-width:900px){.live-transcript-panel__thread.chat-thread{max-height:min(60vh,36rem)}}.live-transcript-panel__avatar--ai{background:#ad46ff1f;color:#8200db}.live-transcript-panel__meta--ai{color:#8200db}.live-transcript-panel__caret{display:inline-block;width:7px;height:14px;margin-left:2px;vertical-align:text-bottom;background:#8200db;animation:eds-caret 1s step-end infinite}.live-transcript-panel__typing{display:inline-flex;align-items:center;gap:4px;min-width:2.5rem;min-height:1.25rem}.live-transcript-panel__chip{cursor:pointer}.live-transcript-panel__chip:hover{background:#f7f9fa}.live-transcript-panel__copilot-btn{cursor:pointer;border:0}.live-transcript-panel__dot{width:6px;height:6px;border-radius:9999px;background:#a2a4a6;animation:eds-typing 1.2s ease-in-out infinite}.live-transcript-panel__dot:nth-child(2){animation-delay:.15s}.live-transcript-panel__dot:nth-child(3){animation-delay:.3s}@keyframes eds-caret{50%{opacity:0}}@keyframes eds-typing{0%,80%,to{opacity:.35;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}\n"] }]
378
+ class: 'flex h-full min-h-0 flex-1 flex-col overflow-hidden',
379
+ }, template: "<section\n class=\"flex h-full min-h-0 flex-1 flex-col overflow-hidden rounded-xl bg-white p-4\"\n aria-labelledby=\"live-transcript-title\"\n>\n <header class=\"mb-4 flex shrink-0 items-center justify-between gap-3\">\n <div class=\"flex min-w-0 items-center gap-2\">\n <h4 id=\"live-transcript-title\" class=\"m-0\">Live Transcript</h4>\n @if (live() && !paused()) {\n <span class=\"live-transcript-panel__recording inline-flex h-5 items-center gap-1 rounded px-1 text-red-600\">\n <span class=\"h-1.5 w-1.5 rounded-full bg-red-600\" aria-hidden=\"true\"></span>\n Recording\n </span>\n }\n </div>\n @if (callStarted()) {\n <span class=\"live-transcript-panel__timer inline-flex items-center gap-0.5 rounded-full bg-green-500/10 px-1 py-0.5 text-green-700\">\n <span class=\"h-1.5 w-1.5 rounded-full bg-green-600\" aria-hidden=\"true\"></span>\n <span class=\"font-mono uppercase tracking-wide\">{{ callStarted() | edsElapsed }}</span>\n </span>\n }\n </header>\n\n <div #scrollHost class=\"chat-thread live-transcript-panel__thread\" role=\"log\" aria-live=\"polite\">\n @for (line of lines(); track $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.border-emerald-200]=\"line.flag === 'verify'\"\n [class.bg-emerald-50]=\"line.flag === 'verify'\"\n [class.text-emerald-700]=\"line.flag === 'verify'\"\n [class.border-amber-200]=\"line.flag === 'fail' || line.flag === 'escalate'\"\n [class.bg-amber-50]=\"line.flag === 'fail' || line.flag === 'escalate'\"\n [class.text-amber-700]=\"line.flag === 'fail' || line.flag === 'escalate'\"\n >\n <ed-icon [name]=\"systemIcon(line.flag)\" [size]=\"14\" />\n <span>{{ line.text }}</span>\n </div>\n </div>\n } @else {\n <article\n class=\"chat-row\"\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 >\n <div class=\"chat-meta\">\n <span [class.live-transcript-panel__meta--ai]=\"line.who === 'ai'\">{{ roleLabel(line.who) }}</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.live-transcript-panel__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 >\n <p class=\"chat-content\">{{ line.text }}</p>\n </div>\n </div>\n </article>\n }\n }\n\n @if (patientInterim(); as interim) {\n <article class=\"chat-row chat-row--caller\">\n <div class=\"chat-meta\">\n <span>{{ callerLabel() }}</span>\n </div>\n <div class=\"chat-bubble-row\">\n <div class=\"chat-avatar chat-avatar--caller\">\n <ed-icon name=\"person\" [size]=\"16\" />\n </div>\n <div class=\"chat-bubble chat-bubble--caller chat-bubble--interim live-transcript-panel__typing\">\n <span class=\"live-transcript-panel__dot\" aria-hidden=\"true\"></span>\n <span class=\"live-transcript-panel__dot\" aria-hidden=\"true\"></span>\n <span class=\"live-transcript-panel__dot\" aria-hidden=\"true\"></span>\n <span class=\"sr-only\">{{ interim }}</span>\n </div>\n </div>\n </article>\n }\n\n @if (staffInterim(); as interim) {\n <article class=\"chat-row chat-row--staff\">\n <div class=\"chat-meta\"><span>Staff</span></div>\n <div class=\"chat-bubble-row\">\n <div class=\"chat-avatar chat-avatar--staff\">\n <ed-icon name=\"Robot\" [size]=\"16\" />\n </div>\n <div class=\"chat-bubble chat-bubble--staff chat-bubble--interim\">\n <p class=\"chat-content\">{{ interim }}</p>\n </div>\n </div>\n </article>\n }\n\n @if (aiInterim(); as interim) {\n <article class=\"chat-row chat-row--ai\">\n <div class=\"chat-meta\">\n <span class=\"live-transcript-panel__meta--ai\">AI Receptionist</span>\n </div>\n <div class=\"chat-bubble-row\">\n <div class=\"chat-avatar chat-avatar--ai live-transcript-panel__avatar--ai\">\n <ed-icon name=\"graph_new\" [size]=\"16\" />\n </div>\n <div class=\"chat-bubble chat-bubble--ai chat-bubble--interim\">\n <p class=\"chat-content\">\n {{ interim }}<span class=\"live-transcript-panel__caret\" aria-hidden=\"true\"></span>\n </p>\n </div>\n </div>\n </article>\n }\n\n @if (lines().length === 0 && !patientInterim() && !aiInterim() && !staffInterim()) {\n <p class=\"m-0 px-3 py-8 text-center text-zinc-500\">Waiting for conversation\u2026</p>\n }\n </div>\n\n @if (showStaffInput()) {\n <footer class=\"mt-4 flex shrink-0 flex-col gap-4\">\n <div class=\"flex items-center gap-2 rounded-lg border border-zinc-200 p-2\">\n <input\n type=\"text\"\n class=\"h-8 min-w-0 flex-1 border-0 bg-transparent px-1 text-zinc-900 outline-none placeholder:text-zinc-400\"\n placeholder=\"Type to speak as staff\u2026\"\n [ngModel]=\"staffMessage()\"\n (ngModelChange)=\"onStaffInput($event)\"\n (keyup.enter)=\"onSend()\"\n autocomplete=\"off\"\n />\n </div>\n </footer>\n }\n</section>\n", styles: ["@charset \"UTF-8\";.chat-thread{display:flex;flex-direction:column;gap:0;flex:1 1 auto;min-height:0;overflow:auto;padding:1rem 1.5rem;background:#fff;scroll-behavior:smooth}.chat-row{display:flex;flex-direction:column;width:100%;margin-bottom:1rem}.chat-row--caller,.chat-row--user,.chat-row--patient{align-items:flex-start}.chat-row--agent,.chat-row--ai,.chat-row--staff{align-items:flex-end}.chat-row--tool,.chat-row--system{align-items:center}.chat-meta{display:flex;align-items:center;gap:.5rem;margin-bottom:.25rem;font-size:.875rem;color:var(--color-text-light, #6b7280)}.chat-row--agent .chat-meta,.chat-row--ai .chat-meta,.chat-row--staff .chat-meta{justify-content:flex-end;padding-right:2.75rem}.chat-bubble-row{display:flex;align-items:flex-start;gap:.5rem;max-width:min(72%,40rem)}.chat-row--agent .chat-bubble-row,.chat-row--ai .chat-bubble-row,.chat-row--staff .chat-bubble-row{flex-direction:row-reverse}.chat-avatar{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border-radius:9999px}.chat-avatar--ai{background:#ad46ff1f;color:#8200db}.chat-avatar--staff{border:1px solid #ddd6fe;background:#f5f3ff;color:#6d28d9}.chat-avatar--caller{background:#e5e7eb;color:#4b5563}.chat-bubble{max-width:100%;padding:.75rem 1rem;font-size:.875rem;line-height:1.5;word-break:break-word;white-space:pre-wrap}.chat-bubble--caller,.chat-bubble--user,.chat-bubble--patient{border:1px solid var(--color-border-light, #e5e7eb);border-radius:0 .5rem .5rem;background:#fff;color:var(--color-text-dark, #111827)}.chat-bubble--agent,.chat-bubble--ai{border:none;border-radius:.5rem;background:#ad46ff1a;color:var(--color-text-dark, #53575c)}.chat-bubble--staff{border:1px solid #ddd6fe;border-radius:.5rem 0 .5rem .5rem;background:#f5f3ff;color:#4c1d95}.chat-bubble--tool,.chat-bubble--system{max-width:min(90%,40rem);padding:.5rem .75rem;border:1px solid var(--color-border-light, #e5e7eb);border-radius:9999px;background:#f9fafb;color:#6b7280;font-size:.75rem;text-align:center}.chat-bubble--interim{opacity:.9;font-style:italic}.chat-content{margin:0}.chat-time{font-size:.75rem;color:#9ca3af}.live-transcript-panel__thread.chat-thread{flex:1 1 auto;min-height:0;overflow:auto;background:#f7f9fa;border-radius:.75rem;padding:1rem}.live-transcript-panel__avatar--ai{background:#ad46ff1f;color:#8200db}.live-transcript-panel__meta--ai{color:#8200db}.live-transcript-panel__caret{display:inline-block;width:7px;height:14px;margin-left:2px;vertical-align:text-bottom;background:#8200db;animation:eds-caret 1s step-end infinite}.live-transcript-panel__typing{display:inline-flex;align-items:center;gap:4px;min-width:2.5rem;min-height:1.25rem}.live-transcript-panel__dot{width:6px;height:6px;border-radius:9999px;background:#a2a4a6;animation:eds-typing 1.2s ease-in-out infinite}.live-transcript-panel__dot:nth-child(2){animation-delay:.15s}.live-transcript-panel__dot:nth-child(3){animation-delay:.3s}@keyframes eds-caret{50%{opacity:0}}@keyframes eds-typing{0%,80%,to{opacity:.35;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}\n"] }]
391
380
  }], ctorParameters: () => [], propDecorators: { scrollHost: [{
392
381
  type: ViewChild,
393
382
  args: ['scrollHost']
@@ -720,7 +709,6 @@ class LiveMonitorPageComponent {
720
709
  this.toast = inject(ToastService);
721
710
  this.destroyRef = inject(DestroyRef);
722
711
  this.call = signal(null);
723
- this.staffMessage = signal('');
724
712
  this.loading = signal(true);
725
713
  this.callId = signal('');
726
714
  this.summary = signal(null);
@@ -953,15 +941,6 @@ class LiveMonitorPageComponent {
953
941
  });
954
942
  });
955
943
  }
956
- sendMessage() {
957
- const text = this.staffMessage().trim();
958
- if (!text)
959
- return;
960
- this.api.postMessage(this.callId(), text).subscribe(() => {
961
- this.staffMessage.set('');
962
- this.refreshMetadata();
963
- });
964
- }
965
944
  enableSound() {
966
945
  void this.staffMedia.startAudioPlayback();
967
946
  }
@@ -1114,7 +1093,7 @@ class LiveMonitorPageComponent {
1114
1093
  });
1115
1094
  }
1116
1095
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: LiveMonitorPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1117
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: LiveMonitorPageComponent, isStandalone: true, selector: "eds-live-monitor-page", host: { classAttribute: "block h-full min-h-0" }, ngImport: i0, template: "<div class=\"live-monitor-page box-border flex h-full min-h-0 flex-col overflow-hidden bg-lighter p-base text-zinc-900\">\n @if (loading()) {\n <div class=\"flex min-h-0 flex-1 flex-col gap-4\" aria-busy=\"true\">\n <header class=\"flex shrink-0 items-center justify-between gap-3 rounded-lg bg-white p-3\">\n <div class=\"flex min-w-0 flex-1 items-center gap-4\">\n <ed-skeleton class=\"h-5 w-5 !rounded-sm\"></ed-skeleton>\n <div class=\"flex min-w-0 items-center gap-2\">\n <ed-skeleton class=\"h-9 w-9 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 gap-2xs\">\n <ed-skeleton class=\"h-4 w-40\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n </div>\n </div>\n </div>\n <div class=\"flex shrink-0 items-center gap-3\">\n <ed-skeleton class=\"h-8 w-24 !rounded-md\"></ed-skeleton>\n <ed-skeleton class=\"h-8 w-28 !rounded-md\"></ed-skeleton>\n </div>\n </header>\n <div class=\"grid min-h-0 flex-1 grid-cols-[minmax(0,1fr)_minmax(280px,447px)] items-stretch gap-4 max-[1100px]:grid-cols-1\">\n <div class=\"flex min-h-0 flex-col rounded-xl bg-white p-4\">\n <ed-skeleton class=\"mb-4 h-5 w-36\"></ed-skeleton>\n @for (_ of transcriptSkeletonRows; track _) {\n <div class=\"mb-4 flex flex-col gap-2\">\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n <ed-skeleton class=\"h-16 w-full max-w-xl !rounded-lg\"></ed-skeleton>\n </div>\n }\n </div>\n <aside class=\"flex min-h-0 flex-col gap-4\">\n <ed-skeleton class=\"h-40 w-full !rounded-lg\"></ed-skeleton>\n <ed-skeleton class=\"min-h-48 w-full flex-1 !rounded-lg\"></ed-skeleton>\n <ed-skeleton class=\"h-48 w-full !rounded-lg\"></ed-skeleton>\n </aside>\n </div>\n </div>\n } @else {\n @if (call(); as c) {\n <header class=\"live-monitor-page__header mb-4 flex shrink-0 flex-wrap items-center justify-between gap-3 rounded-lg bg-white p-3\">\n <div class=\"flex min-w-0 flex-1 items-center gap-4\">\n <a\n routerLink=\"..\"\n class=\"live-monitor-page__back inline-flex h-5 w-5 shrink-0 items-center justify-center text-zinc-600 no-underline\"\n aria-label=\"Back to live calls\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"14\" />\n </a>\n\n <div class=\"live-monitor-page__profile flex min-w-0 items-center gap-2\">\n <ed-avatar\n class=\"shrink-0\"\n shape=\"box\"\n size=\"md\"\n [initials]=\"profileInitials(c)\"\n [tone]=\"isUnknownCaller(c) ? 'gray' : 'warm'\"\n />\n\n <div class=\"min-w-0\">\n <div class=\"flex flex-wrap items-center gap-3\">\n <h4 class=\"m-0\">{{ displayName(c) }}</h4>\n @if (isUnknownCaller(c)) {\n <ed-badge-2 variant=\"primary\" pill uppercase>Unknown</ed-badge-2>\n } @else {\n @if (goalBadge(c); as badge) {\n <ed-badge-2 variant=\"primary\" pill uppercase>{{ badge }}</ed-badge-2>\n }\n }\n </div>\n <p class=\"m-0 mt-0.5 text-zinc-500\">{{ c.phone || profileMeta(c) }}</p>\n </div>\n </div>\n </div>\n\n <div class=\"live-monitor-page__header-actions flex flex-wrap items-center gap-3\">\n @if (!callEnded()) {\n @if (mediaState() === 'connected' && isMediaForThisCall() && !audioPlaybackAllowed()) {\n <ed-button variant=\"secondary\" outline size=\"sm\" (click$)=\"enableSound()\">\n <ed-icon slot=\"prefix\" name=\"mic\" [size]=\"16\" />\n Enable sound\n </ed-button>\n }\n @if (isMediaForThisCall() && (mediaState() === 'connected' || mediaState() === 'connecting')) {\n <span\n class=\"live-monitor-page__media-pill inline-flex h-7 items-center rounded-full border border-zinc-200 bg-zinc-50 px-3 text-zinc-600\"\n [attr.data-mode]=\"mediaMode() || 'idle'\"\n [attr.data-state]=\"mediaState()\"\n >\n @if (mediaState() === 'connecting') {\n Connecting\u2026\n } @else if (mediaMode() === 'takeover') {\n {{ micEnabled() ? 'On call \u00B7 mic on' : 'On call \u00B7 mic off' }}\n } @else {\n Joined\n }\n </span>\n }\n <ed-button\n variant=\"danger\"\n outline\n size=\"sm\"\n [disabled]=\"mediaBusy()\"\n (click$)=\"endCall()\"\n >\n <ed-icon slot=\"prefix\" name=\"call_end\" [size]=\"16\" />\n End Call\n </ed-button>\n @if (isTakeover()) {\n @if (mediaState() === 'connected' && isMediaForThisCall()) {\n <ed-button variant=\"secondary\" outline size=\"sm\" (click$)=\"toggleMic()\">\n <ed-icon slot=\"prefix\" [name]=\"micEnabled() ? 'mic' : 'mic_off'\" [size]=\"16\" />\n {{ micEnabled() ? 'Mute' : 'Unmute' }}\n </ed-button>\n }\n } @else {\n <ed-button\n variant=\"primary\"\n fill\n size=\"sm\"\n [disabled]=\"mediaBusy()\"\n (click$)=\"takeover()\"\n >\n <ed-icon slot=\"prefix\" name=\"phone_call\" [size]=\"16\" />\n Take Over\n </ed-button>\n }\n } @else {\n <span class=\"inline-flex items-center gap-2 font-mono text-zinc-900\">\n <span class=\"h-2 w-2 rounded-full bg-green-500 ring-4 ring-green-500/15\" aria-hidden=\"true\"></span>\n {{ c.started | edsElapsed }}\n </span>\n }\n </div>\n </header>\n\n @if (callEnded()) {\n <div class=\"mb-4 flex items-center gap-2 rounded-lg bg-green-50 px-4 py-3 text-green-700\" role=\"status\">\n <ed-icon name=\"check_circle\" [size]=\"18\" />\n Call ended\n </div>\n }\n\n <div\n class=\"live-monitor-page__grid grid min-h-0 flex-1 grid-cols-[minmax(0,1fr)_minmax(280px,447px)] items-stretch gap-4 max-[1100px]:grid-cols-1 max-[1100px]:overflow-auto\"\n >\n <div class=\"live-monitor-page__main flex h-full min-h-0 flex-col gap-4 max-[1100px]:min-h-[420px]\">\n <eds-live-transcript-panel\n [live]=\"isLive()\"\n [paused]=\"isPaused()\"\n [humanTakeover]=\"isTakeover()\"\n [showStaffInput]=\"false\"\n [showCopilot]=\"isLive() && !isTakeover()\"\n [callStarted]=\"c.started\"\n [staffMessage]=\"staffMessage()\"\n [callerName]=\"c.name\"\n [callerMatched]=\"c.matched\"\n (staffMessageChange)=\"staffMessage.set($event)\"\n (sendMessage)=\"sendMessage()\"\n />\n\n @if (callEnded()) {\n <section class=\"live-monitor-page__post-call flex flex-col gap-4\">\n <div class=\"rounded-lg border border-zinc-200 bg-white p-4 text-zinc-600\">\n <h4 class=\"mb-3 m-0\">Call summary</h4>\n @if (summaryLoading()) {\n <div class=\"grid gap-2xs\" aria-busy=\"true\">\n <ed-skeleton class=\"h-3 w-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-5/6\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-3/4\"></ed-skeleton>\n </div>\n } @else if (summary()) {\n <p class=\"m-0\">{{ summary() }}</p>\n } @else {\n <p class=\"m-0 text-zinc-500\">Summary will appear when processing completes.</p>\n }\n </div>\n <eds-call-recording-player [callId]=\"callId()\" />\n </section>\n }\n </div>\n\n <aside class=\"live-monitor-page__sidebar flex h-full min-h-0 flex-col gap-4 overflow-auto\">\n @if (!callEnded()) {\n <section class=\"flex flex-col gap-4 rounded-lg bg-white p-4\" aria-labelledby=\"live-call-state-title\">\n <header class=\"flex items-center gap-3\">\n <span class=\"inline-flex items-center justify-center rounded-md bg-fuchsia-500/10 p-1 text-fuchsia-600\">\n <ed-icon name=\"phone_call\" [size]=\"16\" />\n </span>\n <h4 id=\"live-call-state-title\" class=\"m-0\">Call State</h4>\n </header>\n\n <div class=\"flex flex-col gap-2\">\n <div class=\"flex items-center justify-between gap-2 text-zinc-600\">\n <span class=\"live-monitor-page__eyebrow\">Agent confidence</span>\n <span class=\"live-monitor-page__eyebrow\">{{ c.confidence }}%</span>\n </div>\n <div class=\"live-monitor-page__confidence-track\">\n <span\n class=\"live-monitor-page__confidence-fill\"\n [style.width.%]=\"c.confidence\"\n [attr.data-level]=\"confidenceLevel(c.confidence)\"\n ></span>\n </div>\n <div class=\"flex items-center gap-2 text-zinc-600\">\n <ed-icon\n [name]=\"confidenceLevel(c.confidence) === 'low' ? 'trend_down' : 'info'\"\n [size]=\"16\"\n />\n <span>{{ confidenceHint(c.confidence) }}</span>\n </div>\n </div>\n\n <div class=\"flex items-center justify-between gap-3\">\n <span class=\"live-monitor-page__eyebrow\">Patient sentiment</span>\n <span class=\"vr-sentiment\" [attr.data-sentiment]=\"c.sentiment\">\n <span class=\"vr-sentiment__icon\" aria-hidden=\"true\">\n <img [src]=\"sentimentIcon(c.sentiment)\" alt=\"\" width=\"16\" height=\"16\" />\n </span>\n <span>{{ sentimentLabel(c.sentiment) }}</span>\n </span>\n </div>\n </section>\n }\n\n <section\n class=\"live-monitor-page__sidebar-block flex min-h-0 flex-1 flex-col gap-4 rounded-lg bg-white p-4\"\n aria-labelledby=\"live-goal-timeline-title\"\n >\n <header class=\"flex items-center gap-3\">\n <span class=\"inline-flex items-center justify-center rounded-md bg-blue-500/10 p-1 text-blue-600\">\n <ed-icon name=\"flag\" [size]=\"16\" />\n </span>\n <h4 id=\"live-goal-timeline-title\" class=\"m-0\">Goal Timeline</h4>\n </header>\n\n <div class=\"live-monitor-page__goal-panel flex min-h-0 flex-1 flex-col rounded-lg bg-zinc-50 p-2\">\n @if (c.goal) {\n <p class=\"live-monitor-page__eyebrow mb-3 m-0 text-zinc-900\">{{ c.goal }}</p>\n } @else {\n <p class=\"live-monitor-page__eyebrow mb-3 m-0 text-zinc-900\">No Goal identified yet</p>\n }\n\n <ul class=\"live-monitor-page__tools m-0 flex min-h-0 flex-1 list-none flex-col gap-4 overflow-auto p-0\">\n @for (tool of liveTools(); track toolTrackKey(tool, $index)) {\n <li class=\"flex flex-col gap-1\" [class]=\"toolStateClass(tool.state)\">\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"text-zinc-900\">{{ tool.name }}</span>\n <ed-badge-2 [attr.variant]=\"toolBadgeTone(tool.state)\" pill uppercase>\n {{ toolBadgeLabel(tool.state) }}\n </ed-badge-2>\n </div>\n @if (tool.result) {\n <p class=\"m-0 text-zinc-500\">{{ tool.result }}</p>\n }\n </li>\n } @empty {\n @for (step of goalPlaceholderSteps; track step.title) {\n <li class=\"flex flex-col gap-1\">\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"text-zinc-900\">{{ step.title }}</span>\n <ed-badge-2 [attr.variant]=\"step.tone\" pill uppercase>{{ step.label }}</ed-badge-2>\n </div>\n <p class=\"m-0 text-zinc-500\">{{ step.detail }}</p>\n </li>\n }\n }\n </ul>\n </div>\n </section>\n\n <section class=\"flex flex-col gap-2.5 rounded-lg bg-white p-4\" aria-labelledby=\"live-patient-context-title\">\n <header class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-3\">\n <span class=\"inline-flex items-center justify-center rounded-md bg-green-500/10 p-1 text-green-700\">\n <ed-icon name=\"person\" [size]=\"16\" />\n </span>\n <h4 id=\"live-patient-context-title\" class=\"m-0\">Patient Context</h4>\n </div>\n @if (isUnknownCaller(c) || !c.matched) {\n <ed-badge-2 variant=\"primary\" pill uppercase>Asking details\u2026</ed-badge-2>\n }\n </header>\n\n @if (isUnknownCaller(c) || !c.matched) {\n <div\n class=\"flex flex-1 flex-col justify-center gap-6 rounded-lg border border-dashed border-zinc-200 bg-zinc-50 p-4\"\n aria-busy=\"true\"\n >\n <div class=\"flex flex-col gap-2\">\n <ed-skeleton class=\"h-3 w-full !rounded-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-3/4 !rounded-full\"></ed-skeleton>\n </div>\n <div class=\"flex flex-col gap-2\">\n <ed-skeleton class=\"h-3 w-full !rounded-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-3/4 !rounded-full\"></ed-skeleton>\n </div>\n </div>\n } @else {\n <div class=\"rounded-lg border border-zinc-200 bg-zinc-50 p-4\">\n <p class=\"m-0 text-zinc-900\">{{ displayName(c) }}</p>\n <p class=\"m-0 mt-1 text-zinc-500\">{{ profileMeta(c) }}</p>\n @if (c.phone) {\n <p class=\"m-0 mt-1 text-zinc-500\">{{ c.phone }}</p>\n }\n </div>\n }\n </section>\n </aside>\n </div>\n } @else {\n <div class=\"flex flex-col items-start gap-3\">\n <a\n routerLink=\"..\"\n class=\"live-monitor-page__back inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md border border-zinc-200 bg-white text-zinc-600 no-underline\"\n aria-label=\"Back to live calls\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"19\" />\n </a>\n <p class=\"m-0 text-zinc-500\">Call ended or not found.</p>\n </div>\n }\n }\n</div>\n", styles: [".vr-sentiment{display:inline-flex;align-items:center;justify-content:center;gap:4px;height:20px;padding:2px 4px;border-radius:6px;font-size:11px;font-weight:500;line-height:16px;white-space:nowrap}.vr-sentiment__icon{display:block;width:16px;height:16px;flex-shrink:0;overflow:hidden}.vr-sentiment__icon img{display:block;width:100%;height:100%;max-width:none}.vr-sentiment[data-sentiment=calm]{background:#3681f41a;color:#2162f0}.vr-sentiment[data-sentiment=neutral]{background:#f0f2f5;color:#41464c}.vr-sentiment[data-sentiment=urgent]{background:#f26b0d1a;color:#e94e0c}.vr-sentiment[data-sentiment=frustrated]{background:#f037401a;color:#db0c15}.live-monitor-page__eyebrow{font-size:10px;font-weight:600;letter-spacing:1px;line-height:1;text-transform:uppercase}.live-monitor-page__confidence-track{height:8px;overflow:hidden;border-radius:9999px;background:linear-gradient(90deg,#7d34fb1a,#e76b171a)}.live-monitor-page__confidence-fill{display:block;height:100%;border-radius:9999px;background:linear-gradient(90deg,#7d34fb,#e76b17)}.live-monitor-page__tools li{position:relative;padding-left:1.25rem}.live-monitor-page__tools li:before{content:\"\";position:absolute;top:.35rem;left:0;width:.5rem;height:.5rem;border-radius:9999px;background:#a2a4a6}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: EdAvatarComponent, selector: "ed-avatar", inputs: ["initials", "tone", "shape", "size", "gradient"] }, { 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: "pipe", type: EdsElapsedPipe, name: "edsElapsed" }, { kind: "component", type: LiveTranscriptPanelComponent, selector: "eds-live-transcript-panel", inputs: ["live", "paused", "humanTakeover", "showStaffInput", "showCopilot", "callStarted", "staffMessage", "callerName", "callerMatched"], outputs: ["staffMessageChange", "sendMessage"] }, { kind: "component", type: CallRecordingPlayerComponent, selector: "eds-call-recording-player", inputs: ["callId"], outputs: ["currentTimeChange", "durationChange"] }, { kind: "component", type: EdSkeletonComponent, selector: "ed-skeleton", inputs: ["class"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1096
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: LiveMonitorPageComponent, isStandalone: true, selector: "eds-live-monitor-page", host: { classAttribute: "block h-full min-h-0" }, ngImport: i0, template: "<div class=\"live-monitor-page box-border flex h-full min-h-0 flex-col overflow-hidden bg-lighter p-base text-zinc-900\">\n @if (loading()) {\n <div class=\"flex min-h-0 flex-1 flex-col gap-4\" aria-busy=\"true\">\n <header class=\"flex shrink-0 items-center justify-between gap-3 rounded-lg bg-white p-3\">\n <div class=\"flex min-w-0 flex-1 items-center gap-4\">\n <ed-skeleton class=\"h-5 w-5 !rounded-sm\"></ed-skeleton>\n <div class=\"flex min-w-0 items-center gap-2\">\n <ed-skeleton class=\"h-9 w-9 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 gap-2xs\">\n <ed-skeleton class=\"h-4 w-40\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n </div>\n </div>\n </div>\n <div class=\"flex shrink-0 items-center gap-3\">\n <ed-skeleton class=\"h-8 w-24 !rounded-md\"></ed-skeleton>\n <ed-skeleton class=\"h-8 w-28 !rounded-md\"></ed-skeleton>\n </div>\n </header>\n <div class=\"grid min-h-0 flex-1 grid-cols-[minmax(0,1fr)_minmax(280px,447px)] items-stretch gap-4 max-[1100px]:grid-cols-1\">\n <div class=\"flex min-h-0 flex-col rounded-xl bg-white p-4\">\n <ed-skeleton class=\"mb-4 h-5 w-36\"></ed-skeleton>\n @for (_ of transcriptSkeletonRows; track _) {\n <div class=\"mb-4 flex flex-col gap-2\">\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n <ed-skeleton class=\"h-16 w-full max-w-xl !rounded-lg\"></ed-skeleton>\n </div>\n }\n </div>\n <aside class=\"flex min-h-0 flex-col gap-4\">\n <ed-skeleton class=\"h-40 w-full !rounded-lg\"></ed-skeleton>\n <ed-skeleton class=\"min-h-48 w-full flex-1 !rounded-lg\"></ed-skeleton>\n <ed-skeleton class=\"h-48 w-full !rounded-lg\"></ed-skeleton>\n </aside>\n </div>\n </div>\n } @else {\n @if (call(); as c) {\n <header class=\"live-monitor-page__header mb-4 flex shrink-0 flex-wrap items-center justify-between gap-3 rounded-lg bg-white p-3\">\n <div class=\"flex min-w-0 flex-1 items-center gap-4\">\n <a\n routerLink=\"..\"\n class=\"live-monitor-page__back inline-flex h-5 w-5 shrink-0 items-center justify-center text-zinc-600 no-underline\"\n aria-label=\"Back to live calls\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"14\" />\n </a>\n\n <div class=\"live-monitor-page__profile flex min-w-0 items-center gap-2\">\n <ed-avatar\n class=\"shrink-0\"\n shape=\"box\"\n size=\"md\"\n [initials]=\"profileInitials(c)\"\n [tone]=\"isUnknownCaller(c) ? 'gray' : 'warm'\"\n />\n\n <div class=\"min-w-0\">\n <div class=\"flex flex-wrap items-center gap-3\">\n <h4 class=\"m-0\">{{ displayName(c) }}</h4>\n @if (isUnknownCaller(c)) {\n <ed-badge-2 variant=\"primary\" pill uppercase>Unknown</ed-badge-2>\n } @else {\n @if (goalBadge(c); as badge) {\n <ed-badge-2 variant=\"primary\" pill uppercase>{{ badge }}</ed-badge-2>\n }\n }\n </div>\n <p class=\"m-0 mt-0.5 text-zinc-500\">{{ c.phone || profileMeta(c) }}</p>\n </div>\n </div>\n </div>\n\n <div class=\"live-monitor-page__header-actions flex flex-wrap items-center gap-3\">\n @if (!callEnded()) {\n @if (mediaState() === 'connected' && isMediaForThisCall() && !audioPlaybackAllowed()) {\n <ed-button variant=\"secondary\" outline size=\"sm\" (click$)=\"enableSound()\">\n <ed-icon slot=\"prefix\" name=\"mic\" [size]=\"16\" />\n Enable sound\n </ed-button>\n }\n @if (isMediaForThisCall() && (mediaState() === 'connected' || mediaState() === 'connecting')) {\n <span\n class=\"live-monitor-page__media-pill inline-flex h-7 items-center rounded-full border border-zinc-200 bg-zinc-50 px-3 text-zinc-600\"\n [attr.data-mode]=\"mediaMode() || 'idle'\"\n [attr.data-state]=\"mediaState()\"\n >\n @if (mediaState() === 'connecting') {\n Connecting\u2026\n } @else if (mediaMode() === 'takeover') {\n {{ micEnabled() ? 'On call \u00B7 mic on' : 'On call \u00B7 mic off' }}\n } @else {\n Joined\n }\n </span>\n }\n <ed-button\n variant=\"danger\"\n outline\n size=\"sm\"\n [disabled]=\"mediaBusy()\"\n (click$)=\"endCall()\"\n >\n <ed-icon slot=\"prefix\" name=\"call_end\" [size]=\"16\" />\n End Call\n </ed-button>\n @if (isTakeover()) {\n @if (mediaState() === 'connected' && isMediaForThisCall()) {\n <ed-button variant=\"secondary\" outline size=\"sm\" (click$)=\"toggleMic()\">\n <ed-icon slot=\"prefix\" [name]=\"micEnabled() ? 'mic' : 'mic_off'\" [size]=\"16\" />\n {{ micEnabled() ? 'Mute' : 'Unmute' }}\n </ed-button>\n }\n } @else {\n <ed-button\n variant=\"primary\"\n fill\n size=\"sm\"\n [disabled]=\"mediaBusy()\"\n (click$)=\"takeover()\"\n >\n <ed-icon slot=\"prefix\" name=\"phone_call\" [size]=\"16\" />\n Take Over\n </ed-button>\n }\n } @else {\n <span class=\"inline-flex items-center gap-2 font-mono text-zinc-900\">\n <span class=\"h-2 w-2 rounded-full bg-green-500 ring-4 ring-green-500/15\" aria-hidden=\"true\"></span>\n {{ c.started | edsElapsed }}\n </span>\n }\n </div>\n </header>\n\n @if (callEnded()) {\n <div class=\"mb-4 flex items-center gap-2 rounded-lg bg-green-50 px-4 py-3 text-green-700\" role=\"status\">\n <ed-icon name=\"check_circle\" [size]=\"18\" />\n Call ended\n </div>\n }\n\n <div\n class=\"live-monitor-page__grid grid min-h-0 flex-1 grid-cols-[minmax(0,1fr)_360px] items-stretch gap-4 max-[1100px]:grid-cols-1 max-[1100px]:overflow-auto\"\n >\n <div class=\"live-monitor-page__main flex h-full min-h-0 flex-col overflow-hidden\">\n <eds-live-transcript-panel\n [live]=\"isLive()\"\n [paused]=\"isPaused()\"\n [humanTakeover]=\"isTakeover()\"\n [callStarted]=\"c.started\"\n [callerName]=\"c.name\"\n [callerMatched]=\"c.matched\"\n />\n\n @if (callEnded()) {\n <section class=\"live-monitor-page__post-call flex flex-col gap-4\">\n <div class=\"rounded-lg border border-zinc-200 bg-white p-4 text-zinc-600\">\n <h4 class=\"mb-3 m-0\">Call summary</h4>\n @if (summaryLoading()) {\n <div class=\"grid gap-2xs\" aria-busy=\"true\">\n <ed-skeleton class=\"h-3 w-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-5/6\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-3/4\"></ed-skeleton>\n </div>\n } @else if (summary()) {\n <p class=\"m-0\">{{ summary() }}</p>\n } @else {\n <p class=\"m-0 text-zinc-500\">Summary will appear when processing completes.</p>\n }\n </div>\n <eds-call-recording-player [callId]=\"callId()\" />\n </section>\n }\n </div>\n\n <aside class=\"live-monitor-page__sidebar flex h-full min-h-0 flex-col gap-4 overflow-hidden\">\n @if (!callEnded()) {\n <section class=\"flex shrink-0 flex-col gap-4 rounded-lg bg-white p-4\" aria-labelledby=\"live-call-state-title\">\n <header class=\"flex items-center gap-3\">\n <span class=\"inline-flex items-center justify-center rounded-md bg-fuchsia-500/10 p-1 text-fuchsia-600\">\n <ed-icon name=\"phone_call\" [size]=\"16\" />\n </span>\n <h4 id=\"live-call-state-title\" class=\"m-0\">Call State</h4>\n </header>\n\n <div class=\"flex flex-col gap-2\">\n <div class=\"flex items-center justify-between gap-2 text-zinc-600\">\n <span class=\"live-monitor-page__eyebrow\">Agent confidence</span>\n <span class=\"live-monitor-page__eyebrow\">{{ c.confidence }}%</span>\n </div>\n <div class=\"live-monitor-page__confidence-track\">\n <span\n class=\"live-monitor-page__confidence-fill\"\n [style.width.%]=\"c.confidence\"\n [attr.data-level]=\"confidenceLevel(c.confidence)\"\n ></span>\n </div>\n <div class=\"flex items-center gap-2 text-zinc-600\">\n <ed-icon\n [name]=\"confidenceLevel(c.confidence) === 'low' ? 'trend_down' : 'info'\"\n [size]=\"16\"\n />\n <span>{{ confidenceHint(c.confidence) }}</span>\n </div>\n </div>\n\n <div class=\"flex items-center justify-between gap-3\">\n <span class=\"live-monitor-page__eyebrow\">Patient sentiment</span>\n <span class=\"vr-sentiment\" [attr.data-sentiment]=\"c.sentiment\">\n <span class=\"vr-sentiment__icon\" aria-hidden=\"true\">\n <img [src]=\"sentimentIcon(c.sentiment)\" alt=\"\" width=\"16\" height=\"16\" />\n </span>\n <span>{{ sentimentLabel(c.sentiment) }}</span>\n </span>\n </div>\n </section>\n }\n\n <section\n class=\"live-monitor-page__sidebar-block flex min-h-[16rem] flex-1 flex-col gap-4 overflow-hidden rounded-lg bg-white p-4\"\n aria-labelledby=\"live-goal-timeline-title\"\n >\n <header class=\"flex items-center gap-3\">\n <span class=\"inline-flex items-center justify-center rounded-md bg-blue-500/10 p-1 text-blue-600\">\n <ed-icon name=\"flag\" [size]=\"16\" />\n </span>\n <h4 id=\"live-goal-timeline-title\" class=\"m-0\">Goal Timeline</h4>\n </header>\n\n <div class=\"live-monitor-page__goal-panel flex min-h-0 flex-1 flex-col rounded-lg bg-zinc-50 p-2\">\n @if (c.goal) {\n <p class=\"live-monitor-page__eyebrow mb-3 m-0 text-zinc-900\">{{ c.goal }}</p>\n } @else {\n <p class=\"live-monitor-page__eyebrow mb-3 m-0 text-zinc-900\">No Goal identified yet</p>\n }\n\n <ul class=\"live-monitor-page__tools m-0 flex min-h-0 flex-1 list-none flex-col gap-4 overflow-auto p-0\">\n @for (tool of liveTools(); track toolTrackKey(tool, $index)) {\n <li class=\"flex flex-col gap-1\" [class]=\"toolStateClass(tool.state)\">\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"text-zinc-900\">{{ tool.name }}</span>\n <ed-badge-2 [attr.variant]=\"toolBadgeTone(tool.state)\" pill uppercase>\n {{ toolBadgeLabel(tool.state) }}\n </ed-badge-2>\n </div>\n @if (tool.result) {\n <p class=\"m-0 text-zinc-500\">{{ tool.result }}</p>\n }\n </li>\n } @empty {\n @for (step of goalPlaceholderSteps; track step.title) {\n <li class=\"flex flex-col gap-1\">\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"text-zinc-900\">{{ step.title }}</span>\n <ed-badge-2 [attr.variant]=\"step.tone\" pill uppercase>{{ step.label }}</ed-badge-2>\n </div>\n <p class=\"m-0 text-zinc-500\">{{ step.detail }}</p>\n </li>\n }\n }\n </ul>\n </div>\n </section>\n </aside>\n </div>\n } @else {\n <div class=\"flex flex-col items-start gap-3\">\n <a\n routerLink=\"..\"\n class=\"live-monitor-page__back inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md border border-zinc-200 bg-white text-zinc-600 no-underline\"\n aria-label=\"Back to live calls\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"19\" />\n </a>\n <p class=\"m-0 text-zinc-500\">Call ended or not found.</p>\n </div>\n }\n }\n</div>\n", styles: [".vr-sentiment{display:inline-flex;align-items:center;justify-content:center;gap:4px;height:20px;padding:2px 4px;border-radius:6px;font-size:11px;font-weight:500;line-height:16px;white-space:nowrap}.vr-sentiment__icon{display:block;width:16px;height:16px;flex-shrink:0;overflow:hidden}.vr-sentiment__icon img{display:block;width:100%;height:100%;max-width:none}.vr-sentiment[data-sentiment=calm]{background:#3681f41a;color:#2162f0}.vr-sentiment[data-sentiment=neutral]{background:#f0f2f5;color:#41464c}.vr-sentiment[data-sentiment=urgent]{background:#f26b0d1a;color:#e94e0c}.vr-sentiment[data-sentiment=frustrated]{background:#f037401a;color:#db0c15}.live-monitor-page__eyebrow{font-size:10px;font-weight:600;letter-spacing:1px;line-height:1;text-transform:uppercase}.live-monitor-page__confidence-track{height:8px;overflow:hidden;border-radius:9999px;background:linear-gradient(90deg,#7d34fb1a,#e76b171a)}.live-monitor-page__confidence-fill{display:block;height:100%;border-radius:9999px;background:linear-gradient(90deg,#7d34fb,#e76b17)}.live-monitor-page__sidebar-block{min-height:16rem}.live-monitor-page__tools li{position:relative;padding-left:1.25rem}.live-monitor-page__tools li:before{content:\"\";position:absolute;top:.35rem;left:0;width:.5rem;height:.5rem;border-radius:9999px;background:#a2a4a6}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: EdAvatarComponent, selector: "ed-avatar", inputs: ["initials", "tone", "shape", "size", "gradient"] }, { 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: "pipe", type: EdsElapsedPipe, name: "edsElapsed" }, { kind: "component", type: LiveTranscriptPanelComponent, selector: "eds-live-transcript-panel", inputs: ["live", "paused", "humanTakeover", "showStaffInput", "callStarted", "staffMessage", "callerName", "callerMatched"], outputs: ["staffMessageChange", "sendMessage"] }, { kind: "component", type: CallRecordingPlayerComponent, selector: "eds-call-recording-player", inputs: ["callId"], outputs: ["currentTimeChange", "durationChange"] }, { kind: "component", type: EdSkeletonComponent, selector: "ed-skeleton", inputs: ["class"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1118
1097
  }
1119
1098
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: LiveMonitorPageComponent, decorators: [{
1120
1099
  type: Component,
@@ -1128,8 +1107,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
1128
1107
  LiveTranscriptPanelComponent,
1129
1108
  CallRecordingPlayerComponent,
1130
1109
  EdSkeletonComponent,
1131
- ], changeDetection: ChangeDetectionStrategy.OnPush, schemas: [CUSTOM_ELEMENTS_SCHEMA], host: { class: 'block h-full min-h-0' }, template: "<div class=\"live-monitor-page box-border flex h-full min-h-0 flex-col overflow-hidden bg-lighter p-base text-zinc-900\">\n @if (loading()) {\n <div class=\"flex min-h-0 flex-1 flex-col gap-4\" aria-busy=\"true\">\n <header class=\"flex shrink-0 items-center justify-between gap-3 rounded-lg bg-white p-3\">\n <div class=\"flex min-w-0 flex-1 items-center gap-4\">\n <ed-skeleton class=\"h-5 w-5 !rounded-sm\"></ed-skeleton>\n <div class=\"flex min-w-0 items-center gap-2\">\n <ed-skeleton class=\"h-9 w-9 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 gap-2xs\">\n <ed-skeleton class=\"h-4 w-40\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n </div>\n </div>\n </div>\n <div class=\"flex shrink-0 items-center gap-3\">\n <ed-skeleton class=\"h-8 w-24 !rounded-md\"></ed-skeleton>\n <ed-skeleton class=\"h-8 w-28 !rounded-md\"></ed-skeleton>\n </div>\n </header>\n <div class=\"grid min-h-0 flex-1 grid-cols-[minmax(0,1fr)_minmax(280px,447px)] items-stretch gap-4 max-[1100px]:grid-cols-1\">\n <div class=\"flex min-h-0 flex-col rounded-xl bg-white p-4\">\n <ed-skeleton class=\"mb-4 h-5 w-36\"></ed-skeleton>\n @for (_ of transcriptSkeletonRows; track _) {\n <div class=\"mb-4 flex flex-col gap-2\">\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n <ed-skeleton class=\"h-16 w-full max-w-xl !rounded-lg\"></ed-skeleton>\n </div>\n }\n </div>\n <aside class=\"flex min-h-0 flex-col gap-4\">\n <ed-skeleton class=\"h-40 w-full !rounded-lg\"></ed-skeleton>\n <ed-skeleton class=\"min-h-48 w-full flex-1 !rounded-lg\"></ed-skeleton>\n <ed-skeleton class=\"h-48 w-full !rounded-lg\"></ed-skeleton>\n </aside>\n </div>\n </div>\n } @else {\n @if (call(); as c) {\n <header class=\"live-monitor-page__header mb-4 flex shrink-0 flex-wrap items-center justify-between gap-3 rounded-lg bg-white p-3\">\n <div class=\"flex min-w-0 flex-1 items-center gap-4\">\n <a\n routerLink=\"..\"\n class=\"live-monitor-page__back inline-flex h-5 w-5 shrink-0 items-center justify-center text-zinc-600 no-underline\"\n aria-label=\"Back to live calls\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"14\" />\n </a>\n\n <div class=\"live-monitor-page__profile flex min-w-0 items-center gap-2\">\n <ed-avatar\n class=\"shrink-0\"\n shape=\"box\"\n size=\"md\"\n [initials]=\"profileInitials(c)\"\n [tone]=\"isUnknownCaller(c) ? 'gray' : 'warm'\"\n />\n\n <div class=\"min-w-0\">\n <div class=\"flex flex-wrap items-center gap-3\">\n <h4 class=\"m-0\">{{ displayName(c) }}</h4>\n @if (isUnknownCaller(c)) {\n <ed-badge-2 variant=\"primary\" pill uppercase>Unknown</ed-badge-2>\n } @else {\n @if (goalBadge(c); as badge) {\n <ed-badge-2 variant=\"primary\" pill uppercase>{{ badge }}</ed-badge-2>\n }\n }\n </div>\n <p class=\"m-0 mt-0.5 text-zinc-500\">{{ c.phone || profileMeta(c) }}</p>\n </div>\n </div>\n </div>\n\n <div class=\"live-monitor-page__header-actions flex flex-wrap items-center gap-3\">\n @if (!callEnded()) {\n @if (mediaState() === 'connected' && isMediaForThisCall() && !audioPlaybackAllowed()) {\n <ed-button variant=\"secondary\" outline size=\"sm\" (click$)=\"enableSound()\">\n <ed-icon slot=\"prefix\" name=\"mic\" [size]=\"16\" />\n Enable sound\n </ed-button>\n }\n @if (isMediaForThisCall() && (mediaState() === 'connected' || mediaState() === 'connecting')) {\n <span\n class=\"live-monitor-page__media-pill inline-flex h-7 items-center rounded-full border border-zinc-200 bg-zinc-50 px-3 text-zinc-600\"\n [attr.data-mode]=\"mediaMode() || 'idle'\"\n [attr.data-state]=\"mediaState()\"\n >\n @if (mediaState() === 'connecting') {\n Connecting\u2026\n } @else if (mediaMode() === 'takeover') {\n {{ micEnabled() ? 'On call \u00B7 mic on' : 'On call \u00B7 mic off' }}\n } @else {\n Joined\n }\n </span>\n }\n <ed-button\n variant=\"danger\"\n outline\n size=\"sm\"\n [disabled]=\"mediaBusy()\"\n (click$)=\"endCall()\"\n >\n <ed-icon slot=\"prefix\" name=\"call_end\" [size]=\"16\" />\n End Call\n </ed-button>\n @if (isTakeover()) {\n @if (mediaState() === 'connected' && isMediaForThisCall()) {\n <ed-button variant=\"secondary\" outline size=\"sm\" (click$)=\"toggleMic()\">\n <ed-icon slot=\"prefix\" [name]=\"micEnabled() ? 'mic' : 'mic_off'\" [size]=\"16\" />\n {{ micEnabled() ? 'Mute' : 'Unmute' }}\n </ed-button>\n }\n } @else {\n <ed-button\n variant=\"primary\"\n fill\n size=\"sm\"\n [disabled]=\"mediaBusy()\"\n (click$)=\"takeover()\"\n >\n <ed-icon slot=\"prefix\" name=\"phone_call\" [size]=\"16\" />\n Take Over\n </ed-button>\n }\n } @else {\n <span class=\"inline-flex items-center gap-2 font-mono text-zinc-900\">\n <span class=\"h-2 w-2 rounded-full bg-green-500 ring-4 ring-green-500/15\" aria-hidden=\"true\"></span>\n {{ c.started | edsElapsed }}\n </span>\n }\n </div>\n </header>\n\n @if (callEnded()) {\n <div class=\"mb-4 flex items-center gap-2 rounded-lg bg-green-50 px-4 py-3 text-green-700\" role=\"status\">\n <ed-icon name=\"check_circle\" [size]=\"18\" />\n Call ended\n </div>\n }\n\n <div\n class=\"live-monitor-page__grid grid min-h-0 flex-1 grid-cols-[minmax(0,1fr)_minmax(280px,447px)] items-stretch gap-4 max-[1100px]:grid-cols-1 max-[1100px]:overflow-auto\"\n >\n <div class=\"live-monitor-page__main flex h-full min-h-0 flex-col gap-4 max-[1100px]:min-h-[420px]\">\n <eds-live-transcript-panel\n [live]=\"isLive()\"\n [paused]=\"isPaused()\"\n [humanTakeover]=\"isTakeover()\"\n [showStaffInput]=\"false\"\n [showCopilot]=\"isLive() && !isTakeover()\"\n [callStarted]=\"c.started\"\n [staffMessage]=\"staffMessage()\"\n [callerName]=\"c.name\"\n [callerMatched]=\"c.matched\"\n (staffMessageChange)=\"staffMessage.set($event)\"\n (sendMessage)=\"sendMessage()\"\n />\n\n @if (callEnded()) {\n <section class=\"live-monitor-page__post-call flex flex-col gap-4\">\n <div class=\"rounded-lg border border-zinc-200 bg-white p-4 text-zinc-600\">\n <h4 class=\"mb-3 m-0\">Call summary</h4>\n @if (summaryLoading()) {\n <div class=\"grid gap-2xs\" aria-busy=\"true\">\n <ed-skeleton class=\"h-3 w-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-5/6\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-3/4\"></ed-skeleton>\n </div>\n } @else if (summary()) {\n <p class=\"m-0\">{{ summary() }}</p>\n } @else {\n <p class=\"m-0 text-zinc-500\">Summary will appear when processing completes.</p>\n }\n </div>\n <eds-call-recording-player [callId]=\"callId()\" />\n </section>\n }\n </div>\n\n <aside class=\"live-monitor-page__sidebar flex h-full min-h-0 flex-col gap-4 overflow-auto\">\n @if (!callEnded()) {\n <section class=\"flex flex-col gap-4 rounded-lg bg-white p-4\" aria-labelledby=\"live-call-state-title\">\n <header class=\"flex items-center gap-3\">\n <span class=\"inline-flex items-center justify-center rounded-md bg-fuchsia-500/10 p-1 text-fuchsia-600\">\n <ed-icon name=\"phone_call\" [size]=\"16\" />\n </span>\n <h4 id=\"live-call-state-title\" class=\"m-0\">Call State</h4>\n </header>\n\n <div class=\"flex flex-col gap-2\">\n <div class=\"flex items-center justify-between gap-2 text-zinc-600\">\n <span class=\"live-monitor-page__eyebrow\">Agent confidence</span>\n <span class=\"live-monitor-page__eyebrow\">{{ c.confidence }}%</span>\n </div>\n <div class=\"live-monitor-page__confidence-track\">\n <span\n class=\"live-monitor-page__confidence-fill\"\n [style.width.%]=\"c.confidence\"\n [attr.data-level]=\"confidenceLevel(c.confidence)\"\n ></span>\n </div>\n <div class=\"flex items-center gap-2 text-zinc-600\">\n <ed-icon\n [name]=\"confidenceLevel(c.confidence) === 'low' ? 'trend_down' : 'info'\"\n [size]=\"16\"\n />\n <span>{{ confidenceHint(c.confidence) }}</span>\n </div>\n </div>\n\n <div class=\"flex items-center justify-between gap-3\">\n <span class=\"live-monitor-page__eyebrow\">Patient sentiment</span>\n <span class=\"vr-sentiment\" [attr.data-sentiment]=\"c.sentiment\">\n <span class=\"vr-sentiment__icon\" aria-hidden=\"true\">\n <img [src]=\"sentimentIcon(c.sentiment)\" alt=\"\" width=\"16\" height=\"16\" />\n </span>\n <span>{{ sentimentLabel(c.sentiment) }}</span>\n </span>\n </div>\n </section>\n }\n\n <section\n class=\"live-monitor-page__sidebar-block flex min-h-0 flex-1 flex-col gap-4 rounded-lg bg-white p-4\"\n aria-labelledby=\"live-goal-timeline-title\"\n >\n <header class=\"flex items-center gap-3\">\n <span class=\"inline-flex items-center justify-center rounded-md bg-blue-500/10 p-1 text-blue-600\">\n <ed-icon name=\"flag\" [size]=\"16\" />\n </span>\n <h4 id=\"live-goal-timeline-title\" class=\"m-0\">Goal Timeline</h4>\n </header>\n\n <div class=\"live-monitor-page__goal-panel flex min-h-0 flex-1 flex-col rounded-lg bg-zinc-50 p-2\">\n @if (c.goal) {\n <p class=\"live-monitor-page__eyebrow mb-3 m-0 text-zinc-900\">{{ c.goal }}</p>\n } @else {\n <p class=\"live-monitor-page__eyebrow mb-3 m-0 text-zinc-900\">No Goal identified yet</p>\n }\n\n <ul class=\"live-monitor-page__tools m-0 flex min-h-0 flex-1 list-none flex-col gap-4 overflow-auto p-0\">\n @for (tool of liveTools(); track toolTrackKey(tool, $index)) {\n <li class=\"flex flex-col gap-1\" [class]=\"toolStateClass(tool.state)\">\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"text-zinc-900\">{{ tool.name }}</span>\n <ed-badge-2 [attr.variant]=\"toolBadgeTone(tool.state)\" pill uppercase>\n {{ toolBadgeLabel(tool.state) }}\n </ed-badge-2>\n </div>\n @if (tool.result) {\n <p class=\"m-0 text-zinc-500\">{{ tool.result }}</p>\n }\n </li>\n } @empty {\n @for (step of goalPlaceholderSteps; track step.title) {\n <li class=\"flex flex-col gap-1\">\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"text-zinc-900\">{{ step.title }}</span>\n <ed-badge-2 [attr.variant]=\"step.tone\" pill uppercase>{{ step.label }}</ed-badge-2>\n </div>\n <p class=\"m-0 text-zinc-500\">{{ step.detail }}</p>\n </li>\n }\n }\n </ul>\n </div>\n </section>\n\n <section class=\"flex flex-col gap-2.5 rounded-lg bg-white p-4\" aria-labelledby=\"live-patient-context-title\">\n <header class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-3\">\n <span class=\"inline-flex items-center justify-center rounded-md bg-green-500/10 p-1 text-green-700\">\n <ed-icon name=\"person\" [size]=\"16\" />\n </span>\n <h4 id=\"live-patient-context-title\" class=\"m-0\">Patient Context</h4>\n </div>\n @if (isUnknownCaller(c) || !c.matched) {\n <ed-badge-2 variant=\"primary\" pill uppercase>Asking details\u2026</ed-badge-2>\n }\n </header>\n\n @if (isUnknownCaller(c) || !c.matched) {\n <div\n class=\"flex flex-1 flex-col justify-center gap-6 rounded-lg border border-dashed border-zinc-200 bg-zinc-50 p-4\"\n aria-busy=\"true\"\n >\n <div class=\"flex flex-col gap-2\">\n <ed-skeleton class=\"h-3 w-full !rounded-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-3/4 !rounded-full\"></ed-skeleton>\n </div>\n <div class=\"flex flex-col gap-2\">\n <ed-skeleton class=\"h-3 w-full !rounded-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-3/4 !rounded-full\"></ed-skeleton>\n </div>\n </div>\n } @else {\n <div class=\"rounded-lg border border-zinc-200 bg-zinc-50 p-4\">\n <p class=\"m-0 text-zinc-900\">{{ displayName(c) }}</p>\n <p class=\"m-0 mt-1 text-zinc-500\">{{ profileMeta(c) }}</p>\n @if (c.phone) {\n <p class=\"m-0 mt-1 text-zinc-500\">{{ c.phone }}</p>\n }\n </div>\n }\n </section>\n </aside>\n </div>\n } @else {\n <div class=\"flex flex-col items-start gap-3\">\n <a\n routerLink=\"..\"\n class=\"live-monitor-page__back inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md border border-zinc-200 bg-white text-zinc-600 no-underline\"\n aria-label=\"Back to live calls\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"19\" />\n </a>\n <p class=\"m-0 text-zinc-500\">Call ended or not found.</p>\n </div>\n }\n }\n</div>\n", styles: [".vr-sentiment{display:inline-flex;align-items:center;justify-content:center;gap:4px;height:20px;padding:2px 4px;border-radius:6px;font-size:11px;font-weight:500;line-height:16px;white-space:nowrap}.vr-sentiment__icon{display:block;width:16px;height:16px;flex-shrink:0;overflow:hidden}.vr-sentiment__icon img{display:block;width:100%;height:100%;max-width:none}.vr-sentiment[data-sentiment=calm]{background:#3681f41a;color:#2162f0}.vr-sentiment[data-sentiment=neutral]{background:#f0f2f5;color:#41464c}.vr-sentiment[data-sentiment=urgent]{background:#f26b0d1a;color:#e94e0c}.vr-sentiment[data-sentiment=frustrated]{background:#f037401a;color:#db0c15}.live-monitor-page__eyebrow{font-size:10px;font-weight:600;letter-spacing:1px;line-height:1;text-transform:uppercase}.live-monitor-page__confidence-track{height:8px;overflow:hidden;border-radius:9999px;background:linear-gradient(90deg,#7d34fb1a,#e76b171a)}.live-monitor-page__confidence-fill{display:block;height:100%;border-radius:9999px;background:linear-gradient(90deg,#7d34fb,#e76b17)}.live-monitor-page__tools li{position:relative;padding-left:1.25rem}.live-monitor-page__tools li:before{content:\"\";position:absolute;top:.35rem;left:0;width:.5rem;height:.5rem;border-radius:9999px;background:#a2a4a6}\n"] }]
1110
+ ], changeDetection: ChangeDetectionStrategy.OnPush, schemas: [CUSTOM_ELEMENTS_SCHEMA], host: { class: 'block h-full min-h-0' }, template: "<div class=\"live-monitor-page box-border flex h-full min-h-0 flex-col overflow-hidden bg-lighter p-base text-zinc-900\">\n @if (loading()) {\n <div class=\"flex min-h-0 flex-1 flex-col gap-4\" aria-busy=\"true\">\n <header class=\"flex shrink-0 items-center justify-between gap-3 rounded-lg bg-white p-3\">\n <div class=\"flex min-w-0 flex-1 items-center gap-4\">\n <ed-skeleton class=\"h-5 w-5 !rounded-sm\"></ed-skeleton>\n <div class=\"flex min-w-0 items-center gap-2\">\n <ed-skeleton class=\"h-9 w-9 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 gap-2xs\">\n <ed-skeleton class=\"h-4 w-40\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n </div>\n </div>\n </div>\n <div class=\"flex shrink-0 items-center gap-3\">\n <ed-skeleton class=\"h-8 w-24 !rounded-md\"></ed-skeleton>\n <ed-skeleton class=\"h-8 w-28 !rounded-md\"></ed-skeleton>\n </div>\n </header>\n <div class=\"grid min-h-0 flex-1 grid-cols-[minmax(0,1fr)_minmax(280px,447px)] items-stretch gap-4 max-[1100px]:grid-cols-1\">\n <div class=\"flex min-h-0 flex-col rounded-xl bg-white p-4\">\n <ed-skeleton class=\"mb-4 h-5 w-36\"></ed-skeleton>\n @for (_ of transcriptSkeletonRows; track _) {\n <div class=\"mb-4 flex flex-col gap-2\">\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n <ed-skeleton class=\"h-16 w-full max-w-xl !rounded-lg\"></ed-skeleton>\n </div>\n }\n </div>\n <aside class=\"flex min-h-0 flex-col gap-4\">\n <ed-skeleton class=\"h-40 w-full !rounded-lg\"></ed-skeleton>\n <ed-skeleton class=\"min-h-48 w-full flex-1 !rounded-lg\"></ed-skeleton>\n <ed-skeleton class=\"h-48 w-full !rounded-lg\"></ed-skeleton>\n </aside>\n </div>\n </div>\n } @else {\n @if (call(); as c) {\n <header class=\"live-monitor-page__header mb-4 flex shrink-0 flex-wrap items-center justify-between gap-3 rounded-lg bg-white p-3\">\n <div class=\"flex min-w-0 flex-1 items-center gap-4\">\n <a\n routerLink=\"..\"\n class=\"live-monitor-page__back inline-flex h-5 w-5 shrink-0 items-center justify-center text-zinc-600 no-underline\"\n aria-label=\"Back to live calls\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"14\" />\n </a>\n\n <div class=\"live-monitor-page__profile flex min-w-0 items-center gap-2\">\n <ed-avatar\n class=\"shrink-0\"\n shape=\"box\"\n size=\"md\"\n [initials]=\"profileInitials(c)\"\n [tone]=\"isUnknownCaller(c) ? 'gray' : 'warm'\"\n />\n\n <div class=\"min-w-0\">\n <div class=\"flex flex-wrap items-center gap-3\">\n <h4 class=\"m-0\">{{ displayName(c) }}</h4>\n @if (isUnknownCaller(c)) {\n <ed-badge-2 variant=\"primary\" pill uppercase>Unknown</ed-badge-2>\n } @else {\n @if (goalBadge(c); as badge) {\n <ed-badge-2 variant=\"primary\" pill uppercase>{{ badge }}</ed-badge-2>\n }\n }\n </div>\n <p class=\"m-0 mt-0.5 text-zinc-500\">{{ c.phone || profileMeta(c) }}</p>\n </div>\n </div>\n </div>\n\n <div class=\"live-monitor-page__header-actions flex flex-wrap items-center gap-3\">\n @if (!callEnded()) {\n @if (mediaState() === 'connected' && isMediaForThisCall() && !audioPlaybackAllowed()) {\n <ed-button variant=\"secondary\" outline size=\"sm\" (click$)=\"enableSound()\">\n <ed-icon slot=\"prefix\" name=\"mic\" [size]=\"16\" />\n Enable sound\n </ed-button>\n }\n @if (isMediaForThisCall() && (mediaState() === 'connected' || mediaState() === 'connecting')) {\n <span\n class=\"live-monitor-page__media-pill inline-flex h-7 items-center rounded-full border border-zinc-200 bg-zinc-50 px-3 text-zinc-600\"\n [attr.data-mode]=\"mediaMode() || 'idle'\"\n [attr.data-state]=\"mediaState()\"\n >\n @if (mediaState() === 'connecting') {\n Connecting\u2026\n } @else if (mediaMode() === 'takeover') {\n {{ micEnabled() ? 'On call \u00B7 mic on' : 'On call \u00B7 mic off' }}\n } @else {\n Joined\n }\n </span>\n }\n <ed-button\n variant=\"danger\"\n outline\n size=\"sm\"\n [disabled]=\"mediaBusy()\"\n (click$)=\"endCall()\"\n >\n <ed-icon slot=\"prefix\" name=\"call_end\" [size]=\"16\" />\n End Call\n </ed-button>\n @if (isTakeover()) {\n @if (mediaState() === 'connected' && isMediaForThisCall()) {\n <ed-button variant=\"secondary\" outline size=\"sm\" (click$)=\"toggleMic()\">\n <ed-icon slot=\"prefix\" [name]=\"micEnabled() ? 'mic' : 'mic_off'\" [size]=\"16\" />\n {{ micEnabled() ? 'Mute' : 'Unmute' }}\n </ed-button>\n }\n } @else {\n <ed-button\n variant=\"primary\"\n fill\n size=\"sm\"\n [disabled]=\"mediaBusy()\"\n (click$)=\"takeover()\"\n >\n <ed-icon slot=\"prefix\" name=\"phone_call\" [size]=\"16\" />\n Take Over\n </ed-button>\n }\n } @else {\n <span class=\"inline-flex items-center gap-2 font-mono text-zinc-900\">\n <span class=\"h-2 w-2 rounded-full bg-green-500 ring-4 ring-green-500/15\" aria-hidden=\"true\"></span>\n {{ c.started | edsElapsed }}\n </span>\n }\n </div>\n </header>\n\n @if (callEnded()) {\n <div class=\"mb-4 flex items-center gap-2 rounded-lg bg-green-50 px-4 py-3 text-green-700\" role=\"status\">\n <ed-icon name=\"check_circle\" [size]=\"18\" />\n Call ended\n </div>\n }\n\n <div\n class=\"live-monitor-page__grid grid min-h-0 flex-1 grid-cols-[minmax(0,1fr)_360px] items-stretch gap-4 max-[1100px]:grid-cols-1 max-[1100px]:overflow-auto\"\n >\n <div class=\"live-monitor-page__main flex h-full min-h-0 flex-col overflow-hidden\">\n <eds-live-transcript-panel\n [live]=\"isLive()\"\n [paused]=\"isPaused()\"\n [humanTakeover]=\"isTakeover()\"\n [callStarted]=\"c.started\"\n [callerName]=\"c.name\"\n [callerMatched]=\"c.matched\"\n />\n\n @if (callEnded()) {\n <section class=\"live-monitor-page__post-call flex flex-col gap-4\">\n <div class=\"rounded-lg border border-zinc-200 bg-white p-4 text-zinc-600\">\n <h4 class=\"mb-3 m-0\">Call summary</h4>\n @if (summaryLoading()) {\n <div class=\"grid gap-2xs\" aria-busy=\"true\">\n <ed-skeleton class=\"h-3 w-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-5/6\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-3/4\"></ed-skeleton>\n </div>\n } @else if (summary()) {\n <p class=\"m-0\">{{ summary() }}</p>\n } @else {\n <p class=\"m-0 text-zinc-500\">Summary will appear when processing completes.</p>\n }\n </div>\n <eds-call-recording-player [callId]=\"callId()\" />\n </section>\n }\n </div>\n\n <aside class=\"live-monitor-page__sidebar flex h-full min-h-0 flex-col gap-4 overflow-hidden\">\n @if (!callEnded()) {\n <section class=\"flex shrink-0 flex-col gap-4 rounded-lg bg-white p-4\" aria-labelledby=\"live-call-state-title\">\n <header class=\"flex items-center gap-3\">\n <span class=\"inline-flex items-center justify-center rounded-md bg-fuchsia-500/10 p-1 text-fuchsia-600\">\n <ed-icon name=\"phone_call\" [size]=\"16\" />\n </span>\n <h4 id=\"live-call-state-title\" class=\"m-0\">Call State</h4>\n </header>\n\n <div class=\"flex flex-col gap-2\">\n <div class=\"flex items-center justify-between gap-2 text-zinc-600\">\n <span class=\"live-monitor-page__eyebrow\">Agent confidence</span>\n <span class=\"live-monitor-page__eyebrow\">{{ c.confidence }}%</span>\n </div>\n <div class=\"live-monitor-page__confidence-track\">\n <span\n class=\"live-monitor-page__confidence-fill\"\n [style.width.%]=\"c.confidence\"\n [attr.data-level]=\"confidenceLevel(c.confidence)\"\n ></span>\n </div>\n <div class=\"flex items-center gap-2 text-zinc-600\">\n <ed-icon\n [name]=\"confidenceLevel(c.confidence) === 'low' ? 'trend_down' : 'info'\"\n [size]=\"16\"\n />\n <span>{{ confidenceHint(c.confidence) }}</span>\n </div>\n </div>\n\n <div class=\"flex items-center justify-between gap-3\">\n <span class=\"live-monitor-page__eyebrow\">Patient sentiment</span>\n <span class=\"vr-sentiment\" [attr.data-sentiment]=\"c.sentiment\">\n <span class=\"vr-sentiment__icon\" aria-hidden=\"true\">\n <img [src]=\"sentimentIcon(c.sentiment)\" alt=\"\" width=\"16\" height=\"16\" />\n </span>\n <span>{{ sentimentLabel(c.sentiment) }}</span>\n </span>\n </div>\n </section>\n }\n\n <section\n class=\"live-monitor-page__sidebar-block flex min-h-[16rem] flex-1 flex-col gap-4 overflow-hidden rounded-lg bg-white p-4\"\n aria-labelledby=\"live-goal-timeline-title\"\n >\n <header class=\"flex items-center gap-3\">\n <span class=\"inline-flex items-center justify-center rounded-md bg-blue-500/10 p-1 text-blue-600\">\n <ed-icon name=\"flag\" [size]=\"16\" />\n </span>\n <h4 id=\"live-goal-timeline-title\" class=\"m-0\">Goal Timeline</h4>\n </header>\n\n <div class=\"live-monitor-page__goal-panel flex min-h-0 flex-1 flex-col rounded-lg bg-zinc-50 p-2\">\n @if (c.goal) {\n <p class=\"live-monitor-page__eyebrow mb-3 m-0 text-zinc-900\">{{ c.goal }}</p>\n } @else {\n <p class=\"live-monitor-page__eyebrow mb-3 m-0 text-zinc-900\">No Goal identified yet</p>\n }\n\n <ul class=\"live-monitor-page__tools m-0 flex min-h-0 flex-1 list-none flex-col gap-4 overflow-auto p-0\">\n @for (tool of liveTools(); track toolTrackKey(tool, $index)) {\n <li class=\"flex flex-col gap-1\" [class]=\"toolStateClass(tool.state)\">\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"text-zinc-900\">{{ tool.name }}</span>\n <ed-badge-2 [attr.variant]=\"toolBadgeTone(tool.state)\" pill uppercase>\n {{ toolBadgeLabel(tool.state) }}\n </ed-badge-2>\n </div>\n @if (tool.result) {\n <p class=\"m-0 text-zinc-500\">{{ tool.result }}</p>\n }\n </li>\n } @empty {\n @for (step of goalPlaceholderSteps; track step.title) {\n <li class=\"flex flex-col gap-1\">\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"text-zinc-900\">{{ step.title }}</span>\n <ed-badge-2 [attr.variant]=\"step.tone\" pill uppercase>{{ step.label }}</ed-badge-2>\n </div>\n <p class=\"m-0 text-zinc-500\">{{ step.detail }}</p>\n </li>\n }\n }\n </ul>\n </div>\n </section>\n </aside>\n </div>\n } @else {\n <div class=\"flex flex-col items-start gap-3\">\n <a\n routerLink=\"..\"\n class=\"live-monitor-page__back inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md border border-zinc-200 bg-white text-zinc-600 no-underline\"\n aria-label=\"Back to live calls\"\n >\n <ed-icon name=\"arrow_back\" [size]=\"19\" />\n </a>\n <p class=\"m-0 text-zinc-500\">Call ended or not found.</p>\n </div>\n }\n }\n</div>\n", styles: [".vr-sentiment{display:inline-flex;align-items:center;justify-content:center;gap:4px;height:20px;padding:2px 4px;border-radius:6px;font-size:11px;font-weight:500;line-height:16px;white-space:nowrap}.vr-sentiment__icon{display:block;width:16px;height:16px;flex-shrink:0;overflow:hidden}.vr-sentiment__icon img{display:block;width:100%;height:100%;max-width:none}.vr-sentiment[data-sentiment=calm]{background:#3681f41a;color:#2162f0}.vr-sentiment[data-sentiment=neutral]{background:#f0f2f5;color:#41464c}.vr-sentiment[data-sentiment=urgent]{background:#f26b0d1a;color:#e94e0c}.vr-sentiment[data-sentiment=frustrated]{background:#f037401a;color:#db0c15}.live-monitor-page__eyebrow{font-size:10px;font-weight:600;letter-spacing:1px;line-height:1;text-transform:uppercase}.live-monitor-page__confidence-track{height:8px;overflow:hidden;border-radius:9999px;background:linear-gradient(90deg,#7d34fb1a,#e76b171a)}.live-monitor-page__confidence-fill{display:block;height:100%;border-radius:9999px;background:linear-gradient(90deg,#7d34fb,#e76b17)}.live-monitor-page__sidebar-block{min-height:16rem}.live-monitor-page__tools li{position:relative;padding-left:1.25rem}.live-monitor-page__tools li:before{content:\"\";position:absolute;top:.35rem;left:0;width:.5rem;height:.5rem;border-radius:9999px;background:#a2a4a6}\n"] }]
1132
1111
  }], ctorParameters: () => [] });
1133
1112
 
1134
1113
  export { LiveMonitorPageComponent };
1135
- //# sourceMappingURL=edvak99-voice-receptionist-widget-live-monitor-page.component-DrqhaEEw.mjs.map
1114
+ //# sourceMappingURL=edvak99-voice-receptionist-widget-live-monitor-page.component-B1lKfw-j.mjs.map