@edvak99/voice-receptionist-widget 1.1.21 → 1.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-dcDXT2KG.mjs +533 -0
- package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-dcDXT2KG.mjs.map +1 -0
- package/fesm2022/{edvak99-voice-receptionist-widget-analytics-page.component-CmImX5FN.mjs → edvak99-voice-receptionist-widget-analytics-page.component-B25yZJZz.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-analytics-page.component-CmImX5FN.mjs.map → edvak99-voice-receptionist-widget-analytics-page.component-B25yZJZz.mjs.map} +1 -1
- package/fesm2022/edvak99-voice-receptionist-widget-audit-page.component-Df-dtgR3.mjs +96 -0
- package/fesm2022/edvak99-voice-receptionist-widget-audit-page.component-Df-dtgR3.mjs.map +1 -0
- package/fesm2022/{edvak99-voice-receptionist-widget-call-history-detail-page.component-BT4clUO-.mjs → edvak99-voice-receptionist-widget-call-history-detail-page.component-BJGzgVxG.mjs} +21 -10
- package/fesm2022/edvak99-voice-receptionist-widget-call-history-detail-page.component-BJGzgVxG.mjs.map +1 -0
- package/fesm2022/edvak99-voice-receptionist-widget-call-history-page.component-CcwwO5SO.mjs +254 -0
- package/fesm2022/edvak99-voice-receptionist-widget-call-history-page.component-CcwwO5SO.mjs.map +1 -0
- package/fesm2022/{edvak99-voice-receptionist-widget-call-recording-player.component-4fL-zUWy.mjs → edvak99-voice-receptionist-widget-call-recording-player.component-BepxNLNQ.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-call-recording-player.component-4fL-zUWy.mjs.map → edvak99-voice-receptionist-widget-call-recording-player.component-BepxNLNQ.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-call-review.service-BhbCmB1S.mjs → edvak99-voice-receptionist-widget-call-review.service-nFqc30t3.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-call-review.service-BhbCmB1S.mjs.map → edvak99-voice-receptionist-widget-call-review.service-nFqc30t3.mjs.map} +1 -1
- package/fesm2022/edvak99-voice-receptionist-widget-dashboard-page.component-CMgOu0aw.mjs +311 -0
- package/fesm2022/edvak99-voice-receptionist-widget-dashboard-page.component-CMgOu0aw.mjs.map +1 -0
- package/fesm2022/{edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-DDS7VdnD.mjs → edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CJ1L6QeE.mjs} +54 -25
- package/fesm2022/edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CJ1L6QeE.mjs.map +1 -0
- package/fesm2022/{edvak99-voice-receptionist-widget-live-calls-page.component-4LtgT4lS.mjs → edvak99-voice-receptionist-widget-live-calls-page.component-MnBMu8iA.mjs} +4 -4
- package/fesm2022/edvak99-voice-receptionist-widget-live-calls-page.component-MnBMu8iA.mjs.map +1 -0
- package/fesm2022/{edvak99-voice-receptionist-widget-live-monitor-page.component-B1lKfw-j.mjs → edvak99-voice-receptionist-widget-live-monitor-page.component-BzvMkbC4.mjs} +10 -7
- package/fesm2022/edvak99-voice-receptionist-widget-live-monitor-page.component-BzvMkbC4.mjs.map +1 -0
- package/fesm2022/edvak99-voice-receptionist-widget-outbound-purposes-page.component-Aws6TaaE.mjs +273 -0
- package/fesm2022/edvak99-voice-receptionist-widget-outbound-purposes-page.component-Aws6TaaE.mjs.map +1 -0
- package/fesm2022/{edvak99-voice-receptionist-widget-task-detail-drawer.component-aDTKTV79.mjs → edvak99-voice-receptionist-widget-task-detail-drawer.component-DVWdArqj.mjs} +14 -6
- package/fesm2022/edvak99-voice-receptionist-widget-task-detail-drawer.component-DVWdArqj.mjs.map +1 -0
- package/fesm2022/{edvak99-voice-receptionist-widget-tasks-page.component-Dj1nWx6V.mjs → edvak99-voice-receptionist-widget-tasks-page.component-CBDmGLol.mjs} +11 -7
- package/fesm2022/edvak99-voice-receptionist-widget-tasks-page.component-CBDmGLol.mjs.map +1 -0
- package/fesm2022/{edvak99-voice-receptionist-widget-wizard-page.component-CQttbEzW.mjs → edvak99-voice-receptionist-widget-wizard-page.component-C-hdBQIV.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-wizard-page.component-CQttbEzW.mjs.map → edvak99-voice-receptionist-widget-wizard-page.component-C-hdBQIV.mjs.map} +1 -1
- package/fesm2022/edvak99-voice-receptionist-widget.mjs +1 -1
- package/lib/components/call-tasks-panel/call-tasks-panel.component.d.ts +3 -0
- package/lib/components/patient-profile-drawer/patient-profile-drawer.component.d.ts +3 -0
- package/lib/components/task-detail-drawer/task-detail-drawer.component.d.ts +3 -0
- package/lib/pages/activities-page/activities-page.component.d.ts +5 -2
- package/lib/pages/audit-page/audit-page.component.d.ts +3 -0
- package/lib/pages/call-history-detail-page/call-history-detail-page.component.d.ts +2 -0
- package/lib/pages/call-history-page/call-history-page.component.d.ts +1 -0
- package/lib/pages/dashboard-page/dashboard-page.component.d.ts +4 -0
- package/lib/pages/live-monitor-page/live-monitor-page.component.d.ts +2 -0
- package/lib/pages/outbound-purposes-page/outbound-purposes-page.component.d.ts +3 -0
- package/lib/pages/settings-page/settings-page.component.d.ts +1 -0
- package/lib/pages/tasks-page/tasks-page.component.d.ts +2 -0
- package/lib/services/ai-receptionist-api.service.d.ts +1 -0
- package/package.json +1 -1
- package/src/assets/css/_tables.scss +12 -0
- package/styles/embed.scss +27 -0
- package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-CpXa1J9-.mjs +0 -510
- package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-CpXa1J9-.mjs.map +0 -1
- package/fesm2022/edvak99-voice-receptionist-widget-audit-page.component-DTAB2WTX.mjs +0 -78
- package/fesm2022/edvak99-voice-receptionist-widget-audit-page.component-DTAB2WTX.mjs.map +0 -1
- package/fesm2022/edvak99-voice-receptionist-widget-call-history-detail-page.component-BT4clUO-.mjs.map +0 -1
- package/fesm2022/edvak99-voice-receptionist-widget-call-history-page.component-BACON4uq.mjs +0 -247
- package/fesm2022/edvak99-voice-receptionist-widget-call-history-page.component-BACON4uq.mjs.map +0 -1
- package/fesm2022/edvak99-voice-receptionist-widget-dashboard-page.component-CxNYLBbg.mjs +0 -291
- package/fesm2022/edvak99-voice-receptionist-widget-dashboard-page.component-CxNYLBbg.mjs.map +0 -1
- package/fesm2022/edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-DDS7VdnD.mjs.map +0 -1
- package/fesm2022/edvak99-voice-receptionist-widget-live-calls-page.component-4LtgT4lS.mjs.map +0 -1
- package/fesm2022/edvak99-voice-receptionist-widget-live-monitor-page.component-B1lKfw-j.mjs.map +0 -1
- package/fesm2022/edvak99-voice-receptionist-widget-outbound-purposes-page.component-BkIHblSu.mjs +0 -269
- package/fesm2022/edvak99-voice-receptionist-widget-outbound-purposes-page.component-BkIHblSu.mjs.map +0 -1
- package/fesm2022/edvak99-voice-receptionist-widget-task-detail-drawer.component-aDTKTV79.mjs.map +0 -1
- package/fesm2022/edvak99-voice-receptionist-widget-tasks-page.component-Dj1nWx6V.mjs.map +0 -1
package/fesm2022/edvak99-voice-receptionist-widget-live-calls-page.component-4LtgT4lS.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"edvak99-voice-receptionist-widget-live-calls-page.component-4LtgT4lS.mjs","sources":["../../../src/lib/components/outbound-dial-modal/outbound-dial-modal.component.ts","../../../src/lib/components/outbound-dial-modal/outbound-dial-modal.component.html","../../../src/lib/pages/live-calls-page/live-calls-page.component.ts","../../../src/lib/pages/live-calls-page/live-calls-page.component.html"],"sourcesContent":["import { DatePipe } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n EventEmitter,\n Input,\n OnChanges,\n Output,\n SimpleChanges,\n inject,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { FormsModule } from '@angular/forms';\nimport { Subject, debounceTime, distinctUntilChanged, switchMap, of, catchError } from 'rxjs';\n\nimport { EdButtonComponent } from '../../ui/ed-button.component';\nimport { EdSkeletonComponent } from '../../ui/ed-skeleton.component';\n\nimport {\n OutboundAppointmentHit,\n OutboundPatientHit,\n toE164Phone,\n} from '../../models/outbound-patient.types';\nimport { OutboundPurpose } from '../../models/outbound-purpose.types';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport {\n formatOpeningDate,\n formatOpeningTime,\n isCustomScriptRequired,\n isPurposeFormValid,\n purposeShowsCustomScript,\n renderLiveOpeningPreview,\n requiredFieldLabel,\n} from '../../utils/outbound-purpose.util';\nimport { EdsSearchFieldComponent } from '../../ui/eds-search-field.component';\nimport { ModalComponent } from '../../shared/modal.component';\nimport { ToastService } from '../../shared/toast.service';\n\nconst E164_PATTERN = /^\\+[1-9]\\d{6,14}$/;\n\n@Component({\n selector: 'eds-outbound-dial-modal',\n imports: [FormsModule, ModalComponent, EdsSearchFieldComponent, DatePipe, EdButtonComponent, EdSkeletonComponent],\n templateUrl: './outbound-dial-modal.component.html',\n styleUrl: './outbound-dial-modal.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class OutboundDialModalComponent implements OnChanges {\n private readonly api = inject(AiReceptionistApiService);\n private readonly toast = inject(ToastService);\n private readonly destroyRef = inject(DestroyRef);\n\n @Input() open = false;\n @Output() readonly closed = new EventEmitter<void>();\n @Output() readonly dialed = new EventEmitter<void>();\n\n protected readonly purposes = signal<OutboundPurpose[]>([]);\n protected readonly loading = signal(true);\n protected readonly formSkeletonRows = [0, 1, 2, 3] as const;\n protected readonly appointmentSkeletonRows = [0, 1, 2] as const;\n protected readonly submitting = signal(false);\n protected readonly serverError = signal<string | null>(null);\n\n protected readonly patientHits = signal<OutboundPatientHit[]>([]);\n protected readonly searchingPatients = signal(false);\n protected readonly selectedPatient = signal<OutboundPatientHit | null>(null);\n protected readonly appointments = signal<OutboundAppointmentHit[]>([]);\n protected readonly loadingAppointments = signal(false);\n protected readonly selectedAppointmentId = signal<string | null>(null);\n protected readonly showManualEntry = signal(false);\n protected readonly practiceName = signal('');\n /** Bumps OnPush re-render when plain ngModel fields change. */\n protected readonly formEpoch = signal(0);\n\n protected readonly patientQuery = signal('');\n protected phone = '';\n protected name = '';\n protected purposeId = '';\n protected appointmentDate = '';\n protected appointmentTime = '';\n protected providerName = '';\n protected customScript = '';\n\n protected requiredFieldLabel = requiredFieldLabel;\n\n private readonly search$ = new Subject<string>();\n\n constructor() {\n this.search$\n .pipe(\n debounceTime(280),\n distinctUntilChanged(),\n switchMap((q) => {\n const query = q.trim();\n if (query.length < 2) {\n this.searchingPatients.set(false);\n this.patientHits.set([]);\n return of([] as OutboundPatientHit[]);\n }\n this.searchingPatients.set(true);\n return this.api.searchPatientsForOutbound(query, 10).pipe(\n catchError(() => of([] as OutboundPatientHit[])),\n );\n }),\n takeUntilDestroyed(this.destroyRef),\n )\n .subscribe((hits) => {\n this.searchingPatients.set(false);\n if (!this.selectedPatient()) {\n this.patientHits.set(hits);\n }\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['open']?.currentValue) {\n this.resetForm();\n this.loadPurposes();\n this.loadPracticeName();\n }\n }\n\n protected get selectedPurpose(): OutboundPurpose | null {\n return this.purposes().find((p) => p.purposeId === this.purposeId) ?? null;\n }\n\n protected get selectedAppointment(): OutboundAppointmentHit | null {\n const id = this.selectedAppointmentId();\n if (!id) return null;\n return this.appointments().find((a) => a.appointmentId === id) ?? null;\n }\n\n protected get previewText(): string {\n this.formEpoch(); // depend for CD when form fields change\n const p = this.selectedPurpose;\n if (!p) return '—';\n const appt = this.selectedAppointment;\n const dateSource = appt?.startTime || this.appointmentDate;\n const timeSource = appt?.startTime || this.appointmentTime;\n return renderLiveOpeningPreview(p, {\n patientName: this.name.trim() || this.selectedPatient()?.fullName || '',\n appointmentDate: formatOpeningDate(dateSource),\n appointmentTime: formatOpeningTime(this.appointmentTime || timeSource, appt?.startTime),\n providerName: this.providerName.trim() || appt?.providerName || '',\n practiceName: this.practiceName(),\n locationName: appt?.locationName || '',\n visitType: appt?.visitType || '',\n customScript: this.customScript.trim(),\n });\n }\n\n protected showsField(field: 'appointmentDate' | 'appointmentTime' | 'providerName'): boolean {\n return this.selectedPurpose?.requiredFields.includes(field) ?? false;\n }\n\n protected showsCustomScript(): boolean {\n const p = this.selectedPurpose;\n return p ? purposeShowsCustomScript(p) : false;\n }\n\n protected customScriptRequired(): boolean {\n const p = this.selectedPurpose;\n return p ? isCustomScriptRequired(p) : false;\n }\n\n protected canPlaceCall(): boolean {\n if (!E164_PATTERN.test(this.phone.trim())) return false;\n return isPurposeFormValid(this.selectedPurpose, {\n phone: this.phone,\n name: this.name,\n appointmentDate: this.appointmentDate,\n appointmentTime: this.appointmentTime,\n providerName: this.providerName,\n customScript: this.customScript,\n });\n }\n\n protected touchForm(): void {\n this.formEpoch.update((n) => n + 1);\n }\n\n protected onPatientQueryChange(value: string): void {\n this.patientQuery.set(value);\n if (this.selectedPatient()) return;\n this.search$.next(value);\n }\n\n protected selectPatient(patient: OutboundPatientHit): void {\n this.selectedPatient.set(patient);\n this.patientHits.set([]);\n this.patientQuery.set(patient.fullName);\n this.name = patient.fullName;\n this.phone = toE164Phone(patient.phone) || '';\n this.showManualEntry.set(!this.phone);\n this.selectedAppointmentId.set(null);\n this.clearApptDerivedFields();\n this.touchForm();\n this.loadAppointments(patient.patientId);\n }\n\n protected clearPatient(): void {\n this.selectedPatient.set(null);\n this.patientQuery.set('');\n this.patientHits.set([]);\n this.appointments.set([]);\n this.selectedAppointmentId.set(null);\n this.name = '';\n this.phone = '';\n this.clearApptDerivedFields();\n this.touchForm();\n }\n\n protected selectAppointment(appt: OutboundAppointmentHit | null): void {\n this.selectedAppointmentId.set(appt?.appointmentId ?? null);\n if (!appt) {\n this.clearApptDerivedFields();\n this.touchForm();\n return;\n }\n this.applyAppointmentFields(appt);\n this.preferAppointmentPurpose();\n this.touchForm();\n }\n\n protected onPurposeChange(): void {\n const appt = this.selectedAppointment;\n if (appt) {\n this.applyAppointmentFields(appt);\n } else {\n this.clearApptDerivedFields();\n }\n this.customScript = '';\n this.serverError.set(null);\n this.touchForm();\n }\n\n protected close(): void {\n this.closed.emit();\n }\n\n protected submit(): void {\n this.serverError.set(null);\n if (!this.canPlaceCall() || !this.selectedPurpose) return;\n\n this.submitting.set(true);\n const patient = this.selectedPatient();\n const apptId = this.selectedAppointmentId();\n const body = {\n phone: this.phone.trim(),\n name: this.name.trim(),\n purpose: this.purposeId,\n ...(this.appointmentDate ? { appointmentDate: this.appointmentDate } : {}),\n ...(this.appointmentTime ? { appointmentTime: this.appointmentTime } : {}),\n ...(this.providerName ? { providerName: this.providerName.trim() } : {}),\n ...(this.customScript ? { customScript: this.customScript.trim() } : {}),\n ...(patient?.patientId ? { patientId: patient.patientId } : {}),\n ...(apptId ? { appointmentId: apptId } : {}),\n };\n\n this.api.placeOutboundCall(body).subscribe({\n next: (res) => {\n this.submitting.set(false);\n const msg = res.message ?? 'Outbound call started.';\n this.toast.show(msg, 'success', 5000);\n this.dialed.emit();\n this.close();\n },\n error: (err: { message?: string }) => {\n this.submitting.set(false);\n const msg = err?.message ?? 'Failed to place outbound call.';\n this.serverError.set(msg);\n this.toast.show(msg, 'error', 5000);\n },\n });\n }\n\n private preferAppointmentPurpose(): void {\n const current = this.selectedPurpose;\n const needsAppt =\n !!current &&\n (current.requiredFields.includes('appointmentDate') ||\n current.requiredFields.includes('appointmentTime'));\n if (needsAppt) return;\n\n const confirm =\n this.purposes().find(\n (p) =>\n p.isActive &&\n p.requiredFields.includes('appointmentDate') &&\n p.requiredFields.includes('appointmentTime'),\n ) ??\n this.purposes().find((p) => p.isActive && /confirm/i.test(p.label + p.purposeId));\n\n if (confirm) {\n this.purposeId = confirm.purposeId;\n }\n }\n\n private applyAppointmentFields(appt: OutboundAppointmentHit): void {\n const start = appt.startTime ? new Date(appt.startTime) : null;\n if (start && !Number.isNaN(start.getTime())) {\n const y = start.getFullYear();\n const m = String(start.getMonth() + 1).padStart(2, '0');\n const d = String(start.getDate()).padStart(2, '0');\n const hh = String(start.getHours()).padStart(2, '0');\n const mm = String(start.getMinutes()).padStart(2, '0');\n this.appointmentDate = `${y}-${m}-${d}`;\n this.appointmentTime = `${hh}:${mm}`;\n }\n if (appt.providerName) {\n this.providerName = appt.providerName;\n }\n }\n\n private clearApptDerivedFields(): void {\n this.appointmentDate = '';\n this.appointmentTime = '';\n this.providerName = '';\n }\n\n private loadAppointments(patientId: string): void {\n this.loadingAppointments.set(true);\n this.appointments.set([]);\n this.api.listPatientAppointmentsForOutbound(patientId, 20).subscribe({\n next: (rows) => {\n this.appointments.set(rows);\n this.loadingAppointments.set(false);\n if (rows.length === 1) {\n this.selectAppointment(rows[0]);\n }\n },\n error: () => {\n this.loadingAppointments.set(false);\n this.appointments.set([]);\n },\n });\n }\n\n private loadPracticeName(): void {\n this.api.getSettings().subscribe({\n next: ({ data }) => {\n const name = String(data.general?.['practiceName'] ?? '').trim();\n this.practiceName.set(name || 'our office');\n },\n error: () => this.practiceName.set('our office'),\n });\n }\n\n private resetForm(): void {\n this.patientQuery.set('');\n this.phone = '';\n this.name = '';\n this.purposeId = '';\n this.appointmentDate = '';\n this.appointmentTime = '';\n this.providerName = '';\n this.customScript = '';\n this.patientHits.set([]);\n this.selectedPatient.set(null);\n this.appointments.set([]);\n this.selectedAppointmentId.set(null);\n this.searchingPatients.set(false);\n this.loadingAppointments.set(false);\n this.showManualEntry.set(false);\n this.serverError.set(null);\n this.submitting.set(false);\n this.formEpoch.set(0);\n }\n\n private loadPurposes(): void {\n this.loading.set(true);\n this.api.getOutboundPurposes(false).subscribe({\n next: ({ purposes }) => {\n this.purposes.set(purposes);\n if (purposes.length && !this.purposeId) {\n this.purposeId = purposes[0].purposeId;\n }\n this.loading.set(false);\n },\n error: () => {\n this.loading.set(false);\n this.serverError.set('Failed to load outbound purposes.');\n },\n });\n }\n}\n","@if (open) {\n <app-modal\n title=\"Outbound call\"\n subtitle=\"Search a patient, pick an appointment, then dial\"\n maxWidth=\"600px\"\n (closed)=\"close()\"\n >\n @if (!loading()) {\n <div modalStickyTop class=\"border-b border-base bg-white px-6 pb-3 pt-5\">\n <div class=\"dial-form__field dial-form__typeahead relative\">\n <label>Patient<span required>*</span></label>\n\n @if (selectedPatient(); as patient) {\n <div class=\"flex items-center justify-between gap-3 rounded-lg border border-base bg-lighter px-3 py-3\">\n <div class=\"flex min-w-0 flex-col gap-1\">\n <strong>{{ patient.fullName }}</strong>\n <span class=\"dial-form__chip-meta text-xs\">\n @if (patient.phone) {\n {{ patient.phone }}\n }\n @if (patient.dob) {\n · DOB {{ patient.dob }}\n }\n </span>\n </div>\n <button type=\"button\" class=\"dial-form__chip-clear shrink-0 cursor-pointer border-none bg-transparent p-1 text-[13px] font-[inherit]\" (click)=\"clearPatient()\">\n Change\n </button>\n </div>\n } @else {\n <eds-search-field\n inputClass=\"form-input\"\n [value]=\"patientQuery()\"\n (valueChange)=\"onPatientQueryChange($event)\"\n placeholder=\"Search by name or phone\"\n />\n @if (searchingPatients()) {\n <span class=\"dial-form__hint text-xs\">Searching…</span>\n }\n @if (patientHits().length) {\n <ul class=\"dial-form__hits absolute left-0 right-0 top-[calc(100%+4px)] z-[5] max-h-[220px] overflow-hidden overflow-y-auto rounded-lg border\" role=\"listbox\">\n @for (hit of patientHits(); track hit.patientId) {\n <li>\n <button\n type=\"button\"\n class=\"dial-form__hit flex w-full cursor-pointer flex-col items-start gap-1 border-none border-b px-3 py-3 text-left font-[inherit] last:border-b-0\"\n role=\"option\"\n (click)=\"selectPatient(hit)\"\n >\n <span class=\"font-semibold\">{{ hit.fullName }}</span>\n <span class=\"dial-form__hit-meta text-xs\">\n {{ hit.phone || 'No phone' }}\n @if (hit.dob) {\n · {{ hit.dob }}\n }\n </span>\n </button>\n </li>\n }\n </ul>\n }\n }\n </div>\n </div>\n }\n\n @if (loading()) {\n <div class=\"flex flex-col gap-3\" aria-busy=\"true\">\n @for (_ of formSkeletonRows; track _) {\n <div class=\"grid gap-2xs\">\n <ed-skeleton class=\"h-3 w-20\"></ed-skeleton>\n <ed-skeleton class=\"h-10 w-full !rounded-md\"></ed-skeleton>\n </div>\n }\n </div>\n } @else {\n <form\n id=\"outbound-dial-form\"\n class=\"flex flex-col gap-3\"\n (ngSubmit)=\"submit()\"\n novalidate\n autocomplete=\"off\"\n >\n @if (selectedPatient()) {\n <div class=\"mb-sm\">\n <label>Appointment</label>\n @if (loadingAppointments()) {\n <ul class=\"max-h-[220px] overflow-hidden overflow-y-auto rounded-lg border\" aria-busy=\"true\">\n @for (_ of appointmentSkeletonRows; track _) {\n <li class=\"flex items-start gap-3 border-b px-3 py-3 last:border-b-0\">\n <ed-skeleton class=\"mt-0.5 h-4 w-4 !rounded-full\"></ed-skeleton>\n <div class=\"grid flex-1 gap-2xs\">\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-56\"></ed-skeleton>\n </div>\n </li>\n }\n </ul>\n } @else if (!appointments().length) {\n <span class=\"dial-form__hint text-xs\">No upcoming appointments — dial without one, or enter details below.</span>\n } @else {\n <ul class=\"max-h-[220px] overflow-hidden overflow-y-auto rounded-lg border\">\n <li>\n <label class=\"dial-form__appt flex cursor-pointer items-start gap-3 border-b px-3 py-3 last:border-b-0\">\n <input\n type=\"radio\"\n name=\"appointmentId\"\n [checked]=\"!selectedAppointmentId()\"\n (change)=\"selectAppointment(null)\"\n autocomplete=\"off\"\n />\n <span>No appointment (purpose-only)</span>\n </label>\n </li>\n @for (appt of appointments(); track appt.appointmentId) {\n <li>\n <label class=\"dial-form__appt flex cursor-pointer items-start gap-3 border-b px-3 py-3 last:border-b-0\">\n <input\n type=\"radio\"\n name=\"appointmentId\"\n [checked]=\"selectedAppointmentId() === appt.appointmentId\"\n (change)=\"selectAppointment(appt)\"\n autocomplete=\"off\"\n />\n <span class=\"flex flex-col gap-1\">\n <strong>\n {{ appt.startTime ? (appt.startTime | date: 'medium') : 'TBD' }}\n </strong>\n <span class=\"dial-form__hit-meta text-xs\">\n {{ appt.providerName || 'Provider TBD' }}\n @if (appt.locationName) {\n · {{ appt.locationName }}\n }\n @if (appt.visitType) {\n · {{ appt.visitType }}\n }\n @if (appt.status) {\n · {{ appt.status }}\n }\n </span>\n </span>\n </label>\n </li>\n }\n </ul>\n }\n </div>\n }\n\n <button\n type=\"button\"\n class=\"dial-form__toggle self-start cursor-pointer border-none bg-transparent p-0 text-[13px] font-[inherit]\"\n (click)=\"showManualEntry.set(!showManualEntry())\"\n >\n {{ showManualEntry() ? 'Hide' : 'Show' }} phone / name\n @if (!selectedPatient()) {\n (required if no patient selected)\n }\n </button>\n\n @if (showManualEntry() || !selectedPatient()) {\n <div class=\"mb-sm\">\n <label>Phone<span required>*</span></label>\n <input\n class=\"form-input\"\n type=\"tel\"\n [(ngModel)]=\"phone\"\n (ngModelChange)=\"touchForm()\"\n name=\"phone\"\n placeholder=\"+14155550100\"\n autocomplete=\"off\"\n required\n />\n <span class=\"dial-form__hint text-xs\">E.164 format, e.g. +14155550100</span>\n </div>\n\n <div class=\"mb-sm\">\n <label>Patient name<span required>*</span></label>\n <input\n class=\"form-input\"\n type=\"text\"\n [(ngModel)]=\"name\"\n (ngModelChange)=\"touchForm()\"\n name=\"name\"\n placeholder=\"Maria Garcia\"\n required\n autocomplete=\"off\"\n />\n </div>\n }\n\n <div class=\"mb-sm\">\n <label>Purpose<span required>*</span></label>\n <select\n class=\"form-select\"\n [(ngModel)]=\"purposeId\"\n name=\"purposeId\"\n (ngModelChange)=\"onPurposeChange()\"\n required\n autocomplete=\"off\"\n >\n @for (p of purposes(); track p.purposeId) {\n <option [value]=\"p.purposeId\">{{ p.label }}</option>\n }\n </select>\n </div>\n\n @if (showsField('appointmentDate') && !selectedAppointmentId()) {\n <div class=\"mb-sm\">\n <label>{{ requiredFieldLabel('appointmentDate') }}<span required>*</span></label>\n <input\n class=\"form-input\"\n type=\"date\"\n [(ngModel)]=\"appointmentDate\"\n (ngModelChange)=\"touchForm()\"\n name=\"appointmentDate\"\n placeholder=\"Appointment Date\"\n required\n autocomplete=\"off\"\n />\n </div>\n }\n\n @if (showsField('appointmentTime') && !selectedAppointmentId()) {\n <div class=\"mb-sm\">\n <label>{{ requiredFieldLabel('appointmentTime') }}<span required>*</span></label>\n <input\n class=\"form-input\"\n type=\"time\"\n [(ngModel)]=\"appointmentTime\"\n (ngModelChange)=\"touchForm()\"\n name=\"appointmentTime\"\n required\n autocomplete=\"off\"\n />\n </div>\n }\n\n @if (showsField('providerName') && !selectedAppointmentId()) {\n <div class=\"mb-sm\">\n <label>{{ requiredFieldLabel('providerName') }}<span required>*</span></label>\n <input\n class=\"form-input\"\n type=\"text\"\n [(ngModel)]=\"providerName\"\n (ngModelChange)=\"touchForm()\"\n name=\"providerName\"\n placeholder=\"Dr. Patel\"\n required\n autocomplete=\"off\"\n />\n </div>\n }\n\n @if (selectedAppointmentId() && (showsField('appointmentDate') || showsField('appointmentTime') || showsField('providerName'))) {\n <p class=\"dial-form__hint text-xs\">\n Date, time, and provider are taken from the selected appointment\n @if (appointmentDate || appointmentTime || providerName) {\n ({{ appointmentDate }}\n @if (appointmentTime) {\n {{ appointmentTime }}\n }\n @if (providerName) {\n · {{ providerName }}\n })\n }.\n </p>\n }\n\n @if (showsCustomScript()) {\n <div class=\"mb-sm\">\n <label>\n Custom script\n @if (customScriptRequired()) {\n <span required>*</span>\n }\n </label>\n <textarea\n class=\"form-textarea\"\n rows=\"4\"\n [(ngModel)]=\"customScript\"\n (ngModelChange)=\"touchForm()\"\n name=\"customScript\"\n [required]=\"customScriptRequired()\"\n placeholder=\"What should the agent say or do?\"\n autocomplete=\"off\"\n ></textarea>\n </div>\n }\n </form>\n }\n\n @if (!loading()) {\n <div modalFooter class=\"border-t border-base bg-white px-6 py-4\">\n <section class=\"dial-form__preview rounded-lg border border-base bg-white p-3 shadow-sm\">\n <h3 class=\"fs-sm font-semibold text-light\">Opening preview</h3>\n <p class=\"dial-form__preview-text mt-2 whitespace-pre-wrap text-sm leading-normal\">{{ previewText }}</p>\n @if (selectedAppointmentId()) {\n <p class=\"dial-form__hint text-xs\">\n Filled from the selected appointment and purpose template. Switch purpose to change the script.\n </p>\n } @else {\n <p class=\"dial-form__hint text-xs\">\n Select an appointment to fill date, time, and provider into this message.\n </p>\n }\n </section>\n\n @if (serverError()) {\n <p class=\"mt-3 m-0 text-[13px] text-[#b91c1c]\" role=\"alert\">{{ serverError() }}</p>\n }\n\n <footer class=\"mt-3 flex justify-end gap-2\">\n <ed-button variant=\"secondary\" outline size=\"sm\" (click$)=\"close()\" [disabled]=\"submitting()\">\n Cancel\n </ed-button>\n <ed-button\n type=\"button\"\n variant=\"primary\"\n fill\n size=\"sm\"\n [disabled]=\"submitting() || !canPlaceCall()\"\n (click$)=\"submit()\"\n >\n {{ submitting() ? 'Dialing…' : 'Place call' }}\n </ed-button>\n </footer>\n </div>\n }\n </app-modal>\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n CUSTOM_ELEMENTS_SCHEMA,\n inject,\n signal,\n} from '@angular/core';\nimport { ActivatedRoute, Router } from '@angular/router';\n\nimport { EdButtonComponent } from '../../ui/ed-button.component';\nimport { EdSkeletonComponent } from '../../ui/ed-skeleton.component';\n\nimport { CallStatus, LiveCall, Sentiment } from '../../models/ai-receptionist.types';\nimport { LiveCallsListService } from '../../services/live-calls-list.service';\nimport { AgentOnlineService } from '../../services/agent-online.service';\nimport {\n ageFromDob,\n callerMetaLine,\n isUnknownCaller,\n} from '../../utils/call-history-display.util';\nimport { sentimentIconSrc, sentimentLabel } from '../../utils/sentiment-display.util';\nimport { OutboundDialModalComponent } from '../../components/outbound-dial-modal/outbound-dial-modal.component';\nimport { SmartTooltipDirective } from '../../shared/smart-tooltip.directive';\nimport { EdAvatarComponent } from '../../ui/ed-avatar.component';\nimport { IconComponent } from '../../ui/ed-icon.component';\nimport { EdsPulseDotComponent } from '../../ui/eds-pulse-dot.component';\nimport { EdsElapsedPipe } from '../../pipes/eds-elapsed.pipe';\n\ninterface LiveCallRowVm {\n id: string;\n name: string;\n initials: string;\n avatarTone: 'gray' | 'brand' | 'warm' | 'violet' | 'rose' | 'green';\n metaLine: string;\n sentiment: Sentiment;\n sentimentLabel: string;\n sentimentIconSrc: string;\n direction: 'inbound' | 'outbound';\n directionIcon: string;\n directionTitle: string;\n goal: string;\n statusSubtitle: string;\n handlingLabel: string;\n handlingVariant: 'opened' | 'danger' | 'primary';\n needsAssistance: boolean;\n started: number;\n}\n\n@Component({\n selector: 'eds-live-calls-page',\n imports: [\n EdAvatarComponent,\n IconComponent,\n EdsPulseDotComponent,\n EdsElapsedPipe,\n OutboundDialModalComponent,\n EdSkeletonComponent,\n EdButtonComponent,\n SmartTooltipDirective,\n ],\n templateUrl: './live-calls-page.component.html',\n styleUrl: './live-calls-page.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n host: { class: 'block h-full min-h-0' },\n})\nexport class LiveCallsPageComponent {\n private readonly router = inject(Router);\n private readonly route = inject(ActivatedRoute);\n private readonly liveCallsList = inject(LiveCallsListService);\n private readonly agentOnline = inject(AgentOnlineService);\n\n protected readonly calls = this.liveCallsList.calls;\n protected readonly loading = this.liveCallsList.loading;\n protected readonly error = this.liveCallsList.error;\n protected readonly agentOffline = computed(() => this.agentOnline.online() === false);\n protected readonly listSkeletonRows = [0, 1, 2, 3] as const;\n\n protected readonly outboundOpen = signal(false);\n\n protected readonly callRows = computed(() => this.calls().map((call) => this.toRow(call)));\n\n protected readonly emptyState = computed(() => {\n if (this.calls().length > 0) return null;\n if (this.agentOnline.online() === false) {\n return {\n title: 'Agent is offline',\n detail:\n 'The AI receptionist is not answering calls. Turn it on in Agent Setting → Advanced.',\n icon: 'phone_disabled',\n };\n }\n return {\n title: 'No active calls right now',\n detail:\n 'When a patient calls your practice, their conversation will appear here for real-time monitoring.',\n icon: 'phone_callback',\n };\n });\n\n protected openMonitor(id: string): void {\n void this.router.navigate([id], { relativeTo: this.route.parent ?? this.route });\n }\n\n protected openOutbound(): void {\n this.outboundOpen.set(true);\n }\n\n protected closeOutbound(): void {\n this.outboundOpen.set(false);\n }\n\n protected openTestCall(): void {\n void this.router.navigate(['../settings'], { relativeTo: this.route.parent ?? this.route });\n }\n\n private toRow(call: LiveCall): LiveCallRowVm {\n const unknown = isUnknownCaller(call.name, call.matched);\n const needsAssistance = this.isAssistanceStatus(call.status);\n const staffHandling = call.status === 'takeover' || call.controlMode === 'takeover';\n const lastTool = call.tools[call.tools.length - 1];\n\n return {\n id: call.id,\n name: unknown ? 'Unknown Caller' : call.name.trim() || 'Unknown Caller',\n initials: unknown ? '?' : call.initials || '?',\n avatarTone: unknown ? 'gray' : this.avatarToneFor(call),\n metaLine: callerMetaLine({\n name: call.name,\n matched: call.matched,\n phone: call.phone,\n dob: call.dob,\n age: call.age ?? ageFromDob(call.dob),\n gender: call.gender,\n }),\n sentiment: call.sentiment,\n sentimentLabel: sentimentLabel(call.sentiment),\n sentimentIconSrc: sentimentIconSrc(call.sentiment),\n direction: call.direction,\n directionIcon: call.direction === 'inbound' ? 'call_received' : 'call_made',\n directionTitle: call.direction === 'inbound' ? 'Incoming call' : 'Outgoing call',\n goal: call.reason || call.goal || '—',\n statusSubtitle: lastTool?.result || call.goal || 'In progress…',\n handlingLabel: needsAssistance\n ? 'NEED ASSISTANCE'\n : staffHandling\n ? 'STAFF HANDLING'\n : 'AI HANDLING',\n handlingVariant: needsAssistance ? 'danger' : staffHandling ? 'primary' : 'opened',\n needsAssistance,\n started: call.started,\n };\n }\n\n private isAssistanceStatus(status: CallStatus): boolean {\n return status === 'needs-help' || status === 'human-requested' || status === 'urgent';\n }\n\n private avatarToneFor(call: LiveCall): 'brand' | 'warm' | 'violet' | 'rose' | 'green' {\n const tones = ['brand', 'warm', 'violet', 'rose', 'green'] as const;\n const key = call.id || call.name;\n let hash = 0;\n for (let i = 0; i < key.length; i++) hash = (hash + key.charCodeAt(i) * (i + 1)) % tones.length;\n return tones[hash];\n }\n}\n","<div class=\"flex h-full min-h-0 flex-col overflow-hidden bg-lighter p-base live-calls-page\">\n <header class=\"mb-md flex shrink-0 items-start justify-between gap-base\">\n <div class=\"grid gap-2xs\">\n <div class=\"flex items-center gap-sm\">\n <h4>Live Calls</h4>\n @if (agentOffline()) {\n <span class=\"inline-flex items-center gap-2xs fs-sm font-semibold text-danger\">\n <ed-icon name=\"phone_disabled\" [size]=\"18\" />\n Offline\n </span>\n } @else {\n <eds-pulse-dot />\n }\n </div>\n <p class=\"fs-sm text-light\">Monitor active conversations and step in when needed</p>\n </div>\n <div class=\"flex shrink-0 items-center gap-sm hidden\">\n <ed-button\n variant=\"secondary\"\n outline\n size=\"sm\"\n (click$)=\"openTestCall()\"\n >\n <ed-icon slot=\"prefix\" name=\"phone_call\" [size]=\"16\" />\n Test Call\n </ed-button>\n <ed-button\n variant=\"primary\"\n fill\n size=\"sm\"\n (click$)=\"openOutbound()\"\n >\n <ed-icon slot=\"prefix\" name=\"call_made\" [size]=\"16\" />\n Outbound Call\n </ed-button>\n </div>\n </header>\n\n <div class=\"flex min-h-0 flex-1 flex-col gap-md overflow-y-auto\">\n @if (error()) {\n <p class=\"fs-sm text-danger\" role=\"alert\">{{ error() }}</p>\n }\n\n @if (loading() && callRows().length === 0) {\n <article class=\"grid gap-base overflow-hidden rounded-lg border border-light bg-white p-base\" aria-busy=\"true\">\n <ul class=\"m-0 grid list-none content-start gap-xs p-0\">\n @for (_ of listSkeletonRows; track _) {\n <li>\n <div class=\"flex w-full items-center gap-base rounded-md border border-light bg-white p-sm\">\n <div class=\"flex min-w-0 shrink-0 items-center gap-xs md:w-72\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 flex-1 gap-2xs\">\n <ed-skeleton class=\"h-3 w-32\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-40\"></ed-skeleton>\n </div>\n </div>\n <div class=\"hidden min-w-0 items-center gap-xs md:flex\">\n <ed-skeleton class=\"h-9 w-9 shrink-0 !rounded-md\"></ed-skeleton>\n <div class=\"grid min-w-0 gap-2xs\">\n <ed-skeleton class=\"h-3 w-28\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-24\"></ed-skeleton>\n </div>\n </div>\n <div class=\"ml-auto grid shrink-0 justify-items-end gap-2xs self-stretch\">\n <ed-skeleton class=\"h-5 w-24 !rounded-full\"></ed-skeleton>\n <ed-skeleton class=\"h-3 w-12\"></ed-skeleton>\n </div>\n </div>\n </li>\n }\n </ul>\n </article>\n } @else {\n <article class=\"grid gap-base overflow-hidden rounded-lg border border-light bg-white p-base\">\n <ul class=\"m-0 grid list-none content-start gap-xs p-0\">\n @for (call of callRows(); track call.id) {\n <li>\n <button\n type=\"button\"\n class=\"flex w-full cursor-pointer items-center gap-base rounded-md border border-light bg-white p-sm text-left transition-colors hover:bg-lighter hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary\"\n [class.border-danger]=\"call.needsAssistance\"\n [class.bg-danger-50]=\"call.needsAssistance\"\n (click)=\"openMonitor(call.id)\"\n >\n <div class=\"flex min-w-0 shrink-0 items-center gap-xs md:w-72\">\n <ed-avatar\n shape=\"box\"\n size=\"base\"\n [initials]=\"call.initials\"\n [tone]=\"call.avatarTone\"\n />\n <div class=\"grid min-w-0 flex-1 gap-2xs\">\n <div class=\"flex min-w-0 flex-wrap items-center gap-2xs\">\n <span class=\"fs-sm font-semibold text-dark\">{{ call.name }}</span>\n <!-- <span class=\"inline-flex text-light\">\n <ed-icon name=\"TagSimple\" [size]=\"14\" color=\"currentColor\" />\n </span> -->\n <span class=\"vr-sentiment\" [attr.data-sentiment]=\"call.sentiment\">\n <span class=\"vr-sentiment__icon\" aria-hidden=\"true\">\n <img [src]=\"call.sentimentIconSrc\" alt=\"\" width=\"16\" height=\"16\" />\n </span>\n <span>{{ call.sentimentLabel }}</span>\n </span>\n </div>\n <span class=\"fs-xs whitespace-nowrap text-light\">{{ call.metaLine }}</span>\n </div>\n </div>\n\n <div class=\"hidden min-w-0 items-center gap-xs md:flex\">\n <span\n class=\"inline-flex size-9 shrink-0 items-center justify-center rounded-md\"\n [class.bg-success-50]=\"call.direction === 'inbound'\"\n [class.text-success]=\"call.direction === 'inbound'\"\n [class.bg-primary-50]=\"call.direction === 'outbound'\"\n [class.text-primary]=\"call.direction === 'outbound'\"\n [smartTooltip]=\"call.directionTitle\"\n >\n <ed-icon [name]=\"call.directionIcon\" [size]=\"18\" color=\"currentColor\" />\n </span>\n <div class=\"grid min-w-0 gap-2xs whitespace-nowrap\">\n <span class=\"fs-sm font-medium text-dark\">{{ call.goal }}</span>\n <span class=\"fs-xs text-light\">{{ call.statusSubtitle }}</span>\n </div>\n </div>\n\n <div class=\"ml-auto grid shrink-0 justify-items-end gap-2xs self-stretch\">\n <ed-badge-2 [attr.variant]=\"call.handlingVariant\" pill uppercase>\n {{ call.handlingLabel }}\n </ed-badge-2>\n <strong\n class=\"inline-flex items-center gap-2xs text-primary fs-2xs\"\n [class.text-danger]=\"call.needsAssistance\"\n [class.text-light]=\"!call.needsAssistance\"\n >\n @if (call.needsAssistance) {\n <ed-icon name=\"schedule\" [size]=\"12\" color=\"currentColor\" />\n } @else {\n <eds-pulse-dot />\n }\n {{ call.started | edsElapsed }}\n </strong>\n </div>\n </button>\n </li>\n } @empty {\n @if (emptyState(); as state) {\n <li\n class=\"grid justify-items-center gap-xs rounded-md border border-light px-base py-xl text-center\"\n role=\"status\"\n >\n <ed-icon [name]=\"state.icon\" [size]=\"32\" />\n <p class=\"m-0 font-semibold text-dark\">{{ state.title }}</p>\n <p class=\"m-0 max-w-md fs-sm text-light\">{{ state.detail }}</p>\n </li>\n }\n }\n </ul>\n </article>\n }\n </div>\n</div>\n\n<eds-outbound-dial-modal\n [open]=\"outboundOpen()\"\n (closed)=\"closeOutbound()\"\n (dialed)=\"closeOutbound()\"\n/>\n"],"names":[],"mappings":"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"}
|
package/fesm2022/edvak99-voice-receptionist-widget-live-monitor-page.component-B1lKfw-j.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"edvak99-voice-receptionist-widget-live-monitor-page.component-B1lKfw-j.mjs","sources":["../../../src/lib/models/live-transcript.types.ts","../../../src/lib/services/live-transcript.service.ts","../../../src/lib/components/live-transcript-panel/live-transcript-panel.component.ts","../../../src/lib/components/live-transcript-panel/live-transcript-panel.component.html","../../../src/lib/services/staff-media.service.ts","../../../src/lib/pages/live-monitor-page/live-monitor-page.component.ts","../../../src/lib/pages/live-monitor-page/live-monitor-page.component.html"],"sourcesContent":["import { ToolEvent, TranscriptLine } from './ai-receptionist.types';\nimport { resolveToolDisplayName, resolveToolKey } from '../utils/tool-labels.util';\n\n/** Socket.io `new_chunk` payload from /dashboard namespace */\nexport interface TranscriptChunk {\n /** `staff` is a human agent speaking after a softphone takeover. */\n role: 'user' | 'assistant' | 'staff' | 'system';\n text: string;\n isFinal: boolean;\n timestamp: string;\n}\n\n/** Socket.io `call_event` payload — tools + lifecycle */\nexport interface CallEventStreamPayload {\n eventType: string;\n occurredAt: string;\n payload: Record<string, unknown>;\n}\n\nexport interface LiveTranscriptState {\n lines: TranscriptLine[];\n patientInterim: string | null;\n aiInterim: string | null;\n connected: boolean;\n error: string | null;\n}\n\nexport function mapChunkToLine(chunk: TranscriptChunk): TranscriptLine {\n const at = Date.parse(chunk.timestamp);\n return {\n who:\n chunk.role === 'staff'\n ? 'staff'\n : chunk.role === 'system'\n ? 'system'\n : chunk.role === 'assistant'\n ? 'ai'\n : 'patient',\n text: chunk.text,\n at: Number.isFinite(at) ? at : Date.now(),\n };\n}\n\nexport function formatEventTime(iso: string): string {\n return new Date(iso).toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n second: '2-digit',\n hour12: false,\n });\n}\n\nexport function mapCallEventToTool(event: CallEventStreamPayload): ToolEvent {\n const p = event.payload;\n const state = p['state'];\n const rawName = String(p['name'] ?? event.eventType.replace(/^tool_/, ''));\n const tech = String(p['tech'] ?? event.eventType);\n const key = resolveToolKey(\n p['key'] != null ? String(p['key']) : undefined,\n rawName,\n tech,\n );\n return {\n t: formatEventTime(event.occurredAt),\n key,\n name: resolveToolDisplayName(key, rawName),\n tech,\n result: String(p['result'] ?? ''),\n state:\n state === 'ok' || state === 'warn' || state === 'error' || state === 'active'\n ? state\n : 'ok',\n };\n}\n\nexport function mapLifecycleEventToTool(event: CallEventStreamPayload): ToolEvent {\n const p = event.payload;\n return {\n t: formatEventTime(event.occurredAt),\n name: event.eventType.replace(/_/g, ' '),\n tech: event.eventType,\n result: String(p['detail'] ?? p['message'] ?? p['result'] ?? ''),\n state: 'ok',\n };\n}\n\nexport function isDuplicateTranscriptLine(lines: TranscriptLine[], line: TranscriptLine): boolean {\n return lines.some((l) => l.who === line.who && l.text.trim() === line.text.trim());\n}\n","import { Injectable, inject, signal } from '@angular/core';\n\nimport { VOICE_RECEPTIONIST_CONFIG } from '../config';\nimport { ToolEvent, TranscriptLine } from '../models/ai-receptionist.types';\nimport {\n CallEventStreamPayload,\n isDuplicateTranscriptLine,\n mapCallEventToTool,\n mapChunkToLine,\n mapLifecycleEventToTool,\n TranscriptChunk,\n} from '../models/live-transcript.types';\nimport { DashboardSocketService } from './dashboard-socket.service';\n\n/**\n * Live call stream over shared Socket.io (`/dashboard` namespace).\n * REST seeds transcript/tools once; socket delivers `new_chunk` + `call_event`.\n */\n@Injectable({ providedIn: 'root' })\nexport class LiveTranscriptService {\n private readonly socket = inject(DashboardSocketService);\n private readonly config = inject(VOICE_RECEPTIONIST_CONFIG);\n\n readonly lines = signal<TranscriptLine[]>([]);\n readonly patientInterim = signal<string | null>(null);\n readonly aiInterim = signal<string | null>(null);\n readonly staffInterim = signal<string | null>(null);\n readonly tools = signal<ToolEvent[]>([]);\n readonly connected = this.socket.connected;\n readonly error = signal<string | null>(null);\n readonly callEnded = signal(false);\n readonly summaryRequested = signal(false);\n\n private activeCallId: string | null = null;\n private watching = false;\n private mockTimer: ReturnType<typeof setInterval> | null = null;\n private mockIndex = 0;\n\n private readonly chunkHandler = (chunk: TranscriptChunk) => this.handleChunk(chunk);\n private readonly eventHandler = (event: CallEventStreamPayload) => this.handleCallEvent(event);\n private readonly onSocketConnect = () => {\n if (this.activeCallId) {\n this.socket.emit('watch_call', { callId: this.activeCallId });\n }\n };\n\n seed(transcript: TranscriptLine[], toolEvents: ToolEvent[]): void {\n this.lines.set(transcript.map((line) => ({ ...line })));\n this.tools.set(toolEvents.map((tool) => ({ ...tool })));\n }\n\n watch(callId: string, live = true): void {\n const id = callId.trim();\n if (!id || !live) return;\n\n const switchingCall = this.activeCallId !== id;\n if (switchingCall) {\n this.unsubscribeSocketEvents();\n this.clearInterim();\n this.callEnded.set(false);\n this.summaryRequested.set(false);\n this.activeCallId = id;\n } else if (this.watching) {\n return;\n }\n\n if (this.config.useMockApi) {\n this.watching = true;\n this.startMockStream(id);\n return;\n }\n\n if (!this.watching) {\n this.socket.acquire();\n this.socket.on('new_chunk', this.chunkHandler);\n this.socket.on('call_event', this.eventHandler);\n this.socket.onConnect(this.onSocketConnect);\n this.watching = true;\n }\n\n if (this.socket.connected()) {\n this.socket.emit('watch_call', { callId: id });\n }\n }\n\n stop(): void {\n this.activeCallId = null;\n this.unsubscribeSocketEvents();\n this.resetStreamState();\n }\n\n markCompleted(): void {\n this.callEnded.set(true);\n this.unsubscribeSocketEvents();\n this.clearInterim();\n }\n\n private unsubscribeSocketEvents(): void {\n this.stopMockStream();\n if (!this.watching) return;\n\n this.socket.off('new_chunk', this.chunkHandler);\n this.socket.off('call_event', this.eventHandler);\n this.socket.offConnect(this.onSocketConnect);\n this.socket.release();\n this.watching = false;\n }\n\n private handleChunk(chunk: TranscriptChunk): void {\n if (!chunk?.text?.trim()) return;\n\n if (chunk.role === 'user') {\n if (chunk.isFinal) {\n this.patientInterim.set(null);\n this.appendLineIfNew(mapChunkToLine(chunk));\n } else {\n this.patientInterim.set(chunk.text);\n }\n return;\n }\n\n if (chunk.role === 'system') {\n this.appendLineIfNew(mapChunkToLine(chunk));\n return;\n }\n\n if (chunk.role === 'staff') {\n if (chunk.isFinal) {\n this.staffInterim.set(null);\n this.appendLineIfNew(mapChunkToLine(chunk));\n } else {\n this.staffInterim.set(chunk.text);\n }\n return;\n }\n\n if (chunk.isFinal) {\n this.aiInterim.set(null);\n this.appendLineIfNew(mapChunkToLine(chunk));\n } else {\n this.aiInterim.set(chunk.text);\n }\n }\n\n private handleCallEvent(event: CallEventStreamPayload): void {\n if (!event?.eventType) return;\n\n if (event.eventType.startsWith('tool_')) {\n this.tools.update((prev) => [...prev, mapCallEventToTool(event)]);\n return;\n }\n\n if (event.eventType === 'call_completed') {\n this.markCompleted();\n return;\n }\n\n if (event.eventType === 'summary_generated') {\n this.summaryRequested.set(true);\n return;\n }\n\n this.tools.update((prev) => [...prev, mapLifecycleEventToTool(event)]);\n }\n\n private appendLineIfNew(line: TranscriptLine): void {\n this.lines.update((prev) => {\n if (isDuplicateTranscriptLine(prev, line)) return prev;\n return [...prev, line];\n });\n }\n\n private startMockStream(callId: string): void {\n this.stopMockStream();\n this.mockIndex = 0;\n\n const mockChunks: TranscriptChunk[] = [\n {\n role: 'user',\n text: 'Hi, I need to schedule an appointment.',\n isFinal: false,\n timestamp: new Date().toISOString(),\n },\n {\n role: 'user',\n text: 'Hi, I need to schedule an appointment.',\n isFinal: true,\n timestamp: new Date().toISOString(),\n },\n {\n role: 'assistant',\n text: 'Of course — I can help with that. Which provider would you prefer?',\n isFinal: true,\n timestamp: new Date().toISOString(),\n },\n ];\n\n const mockEvents: CallEventStreamPayload[] = [\n {\n eventType: 'tool_check_doctor_availability',\n occurredAt: new Date().toISOString(),\n payload: {\n key: 'check_doctor_availability',\n name: 'Checked Doctor Availability',\n tech: 'tool_check_doctor_availability',\n result: 'Found 3 available time slots',\n state: 'ok',\n },\n },\n ];\n\n this.mockTimer = setInterval(() => {\n if (this.activeCallId !== callId) {\n this.stopMockStream();\n return;\n }\n if (this.mockIndex < mockChunks.length) {\n this.handleChunk(mockChunks[this.mockIndex]);\n this.mockIndex++;\n return;\n }\n if (this.mockIndex === mockChunks.length) {\n this.handleCallEvent(mockEvents[0]);\n this.mockIndex++;\n }\n }, 1500);\n }\n\n private stopMockStream(): void {\n if (this.mockTimer) {\n clearInterval(this.mockTimer);\n this.mockTimer = null;\n }\n }\n\n private clearInterim(): void {\n this.patientInterim.set(null);\n this.aiInterim.set(null);\n this.staffInterim.set(null);\n }\n\n private resetStreamState(): void {\n this.lines.set([]);\n this.tools.set([]);\n this.clearInterim();\n this.error.set(null);\n this.callEnded.set(false);\n this.summaryRequested.set(false);\n }\n}\n","import {\n AfterViewChecked,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewChild,\n computed,\n effect,\n inject,\n input,\n output,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimport { TranscriptWho } from '../../models/ai-receptionist.types';\nimport { LiveTranscriptService } from '../../services/live-transcript.service';\nimport { EdsElapsedPipe } from '../../pipes/eds-elapsed.pipe';\nimport { isUnknownCaller } from '../../utils/call-history-display.util';\nimport { IconComponent } from '../../ui/ed-icon.component';\n\n@Component({\n selector: 'eds-live-transcript-panel',\n imports: [FormsModule, IconComponent, EdsElapsedPipe],\n templateUrl: './live-transcript-panel.component.html',\n styleUrl: './live-transcript-panel.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'flex h-full min-h-0 flex-1 flex-col overflow-hidden',\n },\n})\nexport class LiveTranscriptPanelComponent implements AfterViewChecked {\n readonly live = input(true);\n readonly paused = input(false);\n readonly humanTakeover = input(false);\n readonly showStaffInput = input(false);\n /** Call start ms for the Recording timer pill. */\n readonly callStarted = input<number | null>(null);\n readonly staffMessage = input('');\n /** Resolved patient display name from the live call. */\n readonly callerName = input<string | null>(null);\n /** Whether the caller was matched to a patient chart. */\n readonly callerMatched = input(false);\n readonly staffMessageChange = output<string>();\n readonly sendMessage = output<void>();\n\n private readonly stream = inject(LiveTranscriptService);\n\n @ViewChild('scrollHost') private scrollHost?: ElementRef<HTMLElement>;\n\n protected readonly lines = this.stream.lines;\n protected readonly patientInterim = this.stream.patientInterim;\n protected readonly aiInterim = this.stream.aiInterim;\n protected readonly staffInterim = this.stream.staffInterim;\n protected readonly connected = this.stream.connected;\n protected readonly error = this.stream.error;\n\n protected readonly callerLabel = computed(() => {\n const name = this.callerName()?.trim() ?? '';\n if (isUnknownCaller(name, this.callerMatched())) return 'Unknown Caller';\n return name || 'Unknown Caller';\n });\n\n private shouldScroll = false;\n\n constructor() {\n effect(() => {\n this.lines();\n this.patientInterim();\n this.aiInterim();\n this.staffInterim();\n this.requestScroll();\n });\n }\n\n ngAfterViewChecked(): void {\n if (this.shouldScroll && this.scrollHost) {\n const el = this.scrollHost.nativeElement;\n el.scrollTop = el.scrollHeight;\n this.shouldScroll = false;\n }\n }\n\n protected roleLabel(who: TranscriptWho): string {\n switch (who) {\n case 'ai':\n return 'AI Receptionist';\n case 'patient':\n return this.callerLabel();\n case 'staff':\n return 'Staff';\n default:\n return 'System';\n }\n }\n\n protected speakerIcon(who: TranscriptWho): string {\n switch (who) {\n case 'ai':\n return 'graph_new';\n case 'staff':\n return 'Robot';\n case 'patient':\n return 'person';\n default:\n return 'info';\n }\n }\n\n protected systemIcon(flag?: string): string {\n if (flag === 'verify') return 'verified_user';\n if (flag === 'fail' || flag === 'escalate') return 'bolt';\n return 'info';\n }\n\n protected onStaffInput(value: string): void {\n this.staffMessageChange.emit(value);\n }\n\n protected onSend(): void {\n this.sendMessage.emit();\n }\n\n private requestScroll(): void {\n this.shouldScroll = true;\n }\n}\n","<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…</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…\"\n [ngModel]=\"staffMessage()\"\n (ngModelChange)=\"onStaffInput($event)\"\n (keyup.enter)=\"onSend()\"\n autocomplete=\"off\"\n />\n </div>\n </footer>\n }\n</section>\n","import { Injectable, signal } from '@angular/core';\nimport {\n ConnectionState,\n RemoteParticipant,\n RemoteTrack,\n RemoteTrackPublication,\n Room,\n RoomEvent,\n Track,\n} from 'livekit-client';\n\nimport { StaffMediaJoinResult, StaffMediaMode } from '../models/staff-media.types';\n\nexport type StaffMediaConnectionState =\n | 'idle'\n | 'connecting'\n | 'connected'\n | 'disconnecting'\n | 'error';\n\nconst STAFF_IDENTITY_PREFIX = 'staff-';\n\n/**\n * Browser softphone for staff Listen / Take Over via LiveKit.\n * Secrets stay on the server — FE only uses short-lived clientToken + livekitUrl.\n *\n * Root-provided on purpose: the session must survive navigating away from the\n * Live Monitor page, otherwise switching dashboard tabs would drop the call.\n */\n@Injectable({ providedIn: 'root' })\nexport class StaffMediaService {\n readonly connectionState = signal<StaffMediaConnectionState>('idle');\n readonly mode = signal<StaffMediaMode | null>(null);\n readonly micEnabled = signal(false);\n readonly error = signal<string | null>(null);\n readonly activeCallId = signal<string | null>(null);\n /** False when the browser blocks autoplay — UI should offer an \"enable sound\" action. */\n readonly audioPlaybackAllowed = signal(true);\n /** True once remote caller audio is actually attached and playing. */\n readonly remoteAudioAttached = signal(false);\n\n private room: Room | null = null;\n private audioContainer: HTMLElement | null = null;\n private readonly attached = new Map<string, HTMLMediaElement[]>();\n\n get isConnected(): boolean {\n return this.connectionState() === 'connected';\n }\n\n /** True when a softphone session is live for this call, regardless of page. */\n isConnectedTo(callId: string): boolean {\n return this.isConnected && this.activeCallId() === callId;\n }\n\n /**\n * getUserMedia only exists in a secure context (https or localhost) and, inside an\n * iframe, requires allow=\"microphone\". Returns null when capture is possible.\n */\n microphoneBlockedReason(): string | null {\n if (typeof navigator === 'undefined') return 'Microphone is not available in this environment.';\n if (!navigator.mediaDevices?.getUserMedia) {\n const secure = typeof window !== 'undefined' && window.isSecureContext;\n return secure\n ? 'Microphone access is blocked by the browser. If the dashboard is embedded, the host page must allow microphone access.'\n : 'Microphone access needs a secure connection. Open the dashboard over https (or localhost) to talk to callers.';\n }\n return null;\n }\n\n async join(join: StaffMediaJoinResult): Promise<void> {\n if (join.provider && join.provider !== 'livekit') {\n throw new Error(`Unsupported media provider: ${join.provider}`);\n }\n if (!join.livekitUrl || !join.clientToken) {\n throw new Error('Missing LiveKit URL or client token from media/join');\n }\n if (join.mode === 'takeover') {\n const blocked = this.microphoneBlockedReason();\n if (blocked) throw new Error(blocked);\n }\n\n await this.disconnect();\n\n this.connectionState.set('connecting');\n this.error.set(null);\n this.mode.set(join.mode);\n this.activeCallId.set(join.callId || null);\n this.micEnabled.set(false);\n\n const room = new Room({\n adaptiveStream: true,\n dynacast: true,\n audioCaptureDefaults: {\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n },\n });\n\n room.on(RoomEvent.Disconnected, () => {\n if (this.room !== room) return;\n void this.cleanupLocal(false);\n this.connectionState.set('idle');\n this.mode.set(null);\n this.activeCallId.set(null);\n this.micEnabled.set(false);\n });\n\n room.on(RoomEvent.ConnectionStateChanged, (state: ConnectionState) => {\n if (this.room !== room) return;\n if (state === ConnectionState.Connected) {\n this.connectionState.set('connected');\n } else if (state === ConnectionState.Connecting || state === ConnectionState.Reconnecting) {\n this.connectionState.set('connecting');\n }\n });\n\n room.on(RoomEvent.AudioPlaybackStatusChanged, () => {\n if (this.room === room) {\n this.audioPlaybackAllowed.set(room.canPlaybackAudio);\n }\n });\n\n room.on(RoomEvent.TrackSubscribed, this.onTrackSubscribed);\n room.on(RoomEvent.TrackUnsubscribed, this.onTrackUnsubscribed);\n room.on(RoomEvent.ParticipantDisconnected, this.onParticipantDisconnected);\n room.on(RoomEvent.TrackPublished, this.onTrackPublished);\n\n try {\n this.room = room;\n this.ensureAudioContainer();\n await room.connect(join.livekitUrl, join.clientToken);\n\n // Publish mic only for takeover (listen stays receive-only).\n if (join.mode === 'takeover') {\n await this.enableMicrophone(true);\n }\n\n this.attachExistingRemoteTracks(room);\n await this.startAudioPlayback();\n this.connectionState.set('connected');\n } catch (err) {\n const message = this.friendlyError(err);\n this.error.set(message);\n this.connectionState.set('error');\n await this.cleanupLocal(true);\n this.mode.set(null);\n this.activeCallId.set(null);\n throw new Error(message);\n }\n }\n\n async setMicrophoneEnabled(enabled: boolean): Promise<void> {\n if (!this.room || this.connectionState() !== 'connected') return;\n if (this.mode() !== 'takeover' && enabled) {\n // Listen mode stays muted unless upgraded to takeover.\n return;\n }\n await this.enableMicrophone(enabled);\n }\n\n async toggleMicrophone(): Promise<void> {\n await this.setMicrophoneEnabled(!this.micEnabled());\n }\n\n /** Retry blocked autoplay — must be called from a user gesture. */\n async startAudioPlayback(): Promise<void> {\n const room = this.room;\n if (!room) return;\n try {\n await room.startAudio();\n this.audioPlaybackAllowed.set(true);\n } catch {\n this.audioPlaybackAllowed.set(room.canPlaybackAudio);\n }\n for (const elements of this.attached.values()) {\n for (const el of elements) {\n void el.play().catch(() => undefined);\n }\n }\n }\n\n async disconnect(): Promise<void> {\n if (!this.room && this.connectionState() === 'idle') return;\n this.connectionState.set('disconnecting');\n await this.cleanupLocal(true);\n this.connectionState.set('idle');\n this.mode.set(null);\n this.activeCallId.set(null);\n this.micEnabled.set(false);\n this.error.set(null);\n this.audioPlaybackAllowed.set(true);\n }\n\n private readonly onTrackSubscribed = (\n track: RemoteTrack,\n publication: RemoteTrackPublication,\n participant: RemoteParticipant,\n ): void => {\n if (track.kind !== Track.Kind.Audio) return;\n\n // Never play another staff softphone back — that is a direct feedback loop\n // where the person taking over hears their own voice.\n if (this.isStaff(participant.identity)) {\n try {\n publication.setSubscribed(false);\n } catch {\n /* server may already have unsubscribed */\n }\n return;\n }\n\n const container = this.ensureAudioContainer();\n const element = track.attach();\n element.autoplay = true;\n element.setAttribute('playsinline', 'true');\n (element as HTMLAudioElement).volume = 1;\n container.appendChild(element);\n\n const key = publication.trackSid || track.sid || participant.identity;\n this.attached.set(key, [...(this.attached.get(key) ?? []), element]);\n this.remoteAudioAttached.set(true);\n void element.play().catch(() => {\n // Autoplay blocked — surfaced via the \"Enable sound\" action.\n this.audioPlaybackAllowed.set(false);\n });\n };\n\n private readonly onTrackUnsubscribed = (\n track: RemoteTrack,\n publication: RemoteTrackPublication,\n participant: RemoteParticipant,\n ): void => {\n if (track.kind !== Track.Kind.Audio) return;\n const key = publication.trackSid || track.sid || participant.identity;\n this.detachKey(key, track);\n };\n\n private readonly onParticipantDisconnected = (participant: RemoteParticipant): void => {\n for (const publication of participant.trackPublications.values()) {\n const key = publication.trackSid;\n if (key) this.detachKey(key);\n }\n };\n\n /** Staff tracks are dropped server-side as soon as they appear. */\n private readonly onTrackPublished = (\n publication: RemoteTrackPublication,\n participant: RemoteParticipant,\n ): void => {\n if (!this.isStaff(participant.identity)) return;\n try {\n publication.setSubscribed(false);\n } catch {\n /* nothing to unsubscribe */\n }\n };\n\n private attachExistingRemoteTracks(room: Room): void {\n for (const participant of room.remoteParticipants.values()) {\n for (const publication of participant.trackPublications.values()) {\n if (publication.track && publication.isSubscribed) {\n this.onTrackSubscribed(publication.track, publication, participant);\n }\n }\n }\n }\n\n private isStaff(identity?: string | null): boolean {\n return !!identity && identity.startsWith(STAFF_IDENTITY_PREFIX);\n }\n\n private detachKey(key: string, track?: RemoteTrack): void {\n const elements = this.attached.get(key);\n if (!elements) return;\n this.attached.delete(key);\n for (const el of elements) {\n try {\n track?.detach(el);\n } catch {\n /* already detached */\n }\n el.remove();\n }\n if (this.attached.size === 0) this.remoteAudioAttached.set(false);\n }\n\n private ensureAudioContainer(): HTMLElement {\n if (this.audioContainer?.isConnected) return this.audioContainer;\n const el = document.createElement('div');\n el.dataset['edsStaffAudio'] = 'true';\n el.style.position = 'fixed';\n el.style.width = '0';\n el.style.height = '0';\n el.style.overflow = 'hidden';\n document.body.appendChild(el);\n this.audioContainer = el;\n return el;\n }\n\n private async enableMicrophone(enabled: boolean): Promise<void> {\n const room = this.room;\n if (!room) return;\n await room.localParticipant.setMicrophoneEnabled(enabled);\n this.micEnabled.set(enabled);\n }\n\n private friendlyError(err: unknown): string {\n const name = (err as { name?: string } | null)?.name ?? '';\n if (name === 'NotAllowedError' || name === 'SecurityError') {\n return 'Microphone permission was denied. Allow microphone access and try again.';\n }\n if (name === 'NotFoundError' || name === 'OverconstrainedError') {\n return 'No microphone was found on this device.';\n }\n if (name === 'NotReadableError' || name === 'TrackStartError') {\n return 'Your microphone is in use by another app.';\n }\n const message = err instanceof Error ? err.message : '';\n if (message.includes('getUserMedia')) {\n return this.microphoneBlockedReason() ?? message;\n }\n return message || 'Failed to join the call audio.';\n }\n\n private async cleanupLocal(disconnectRoom: boolean): Promise<void> {\n const room = this.room;\n this.room = null;\n\n for (const key of [...this.attached.keys()]) {\n this.detachKey(key);\n }\n this.remoteAudioAttached.set(false);\n this.audioContainer?.remove();\n this.audioContainer = null;\n\n if (!room) return;\n try {\n await room.localParticipant.setMicrophoneEnabled(false);\n } catch {\n /* mic may never have been published */\n }\n try {\n if (disconnectRoom) {\n await room.disconnect(true);\n }\n room.removeAllListeners();\n } catch {\n /* already gone */\n }\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n CUSTOM_ELEMENTS_SCHEMA,\n DestroyRef,\n effect,\n inject,\n OnDestroy,\n OnInit,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ActivatedRoute, RouterLink } from '@angular/router';\nimport { FormsModule } from '@angular/forms';\nimport { firstValueFrom } from 'rxjs';\n\nimport { EdButtonComponent } from '../../ui/ed-button.component';\nimport { EdSkeletonComponent } from '../../ui/ed-skeleton.component';\n\nimport { LiveTranscriptPanelComponent } from '../../components/live-transcript-panel/live-transcript-panel.component';\nimport { CallRecordingPlayerComponent } from '../../components/call-recording-player/call-recording-player.component';\nimport {\n CallControlMode,\n LiveCall,\n Sentiment,\n} from '../../models/ai-receptionist.types';\nimport {\n CallControlChangedEvent,\n StaffMediaMode,\n} from '../../models/staff-media.types';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport { DashboardSocketService } from '../../services/dashboard-socket.service';\nimport { LiveTranscriptService } from '../../services/live-transcript.service';\nimport { StaffMediaService } from '../../services/staff-media.service';\nimport { ToastService } from '../../shared/toast.service';\nimport {\n ageFromDob,\n callerMetaLine,\n isUnknownCaller,\n} from '../../utils/call-history-display.util';\nimport {\n sentimentIconSrc,\n sentimentLabel as toSentimentLabel,\n} from '../../utils/sentiment-display.util';\nimport { toolEventTrackKey } from '../../utils/tool-labels.util';\nimport { EdsElapsedPipe } from '../../pipes/eds-elapsed.pipe';\nimport { EdAvatarComponent } from '../../ui/ed-avatar.component';\nimport { IconComponent } from '../../ui/ed-icon.component';\n\n@Component({\n selector: 'eds-live-monitor-page',\n imports: [\n RouterLink,\n FormsModule,\n EdAvatarComponent,\n IconComponent,\n EdButtonComponent,\n EdsElapsedPipe,\n LiveTranscriptPanelComponent,\n CallRecordingPlayerComponent,\n EdSkeletonComponent,\n ],\n templateUrl: './live-monitor-page.component.html',\n styleUrl: './live-monitor-page.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n host: { class: 'block h-full min-h-0' },\n})\nexport class LiveMonitorPageComponent implements OnInit, OnDestroy {\n private readonly api = inject(AiReceptionistApiService);\n private readonly route = inject(ActivatedRoute);\n private readonly stream = inject(LiveTranscriptService);\n private readonly staffMedia = inject(StaffMediaService);\n private readonly socket = inject(DashboardSocketService);\n private readonly toast = inject(ToastService);\n private readonly destroyRef = inject(DestroyRef);\n\n protected readonly call = signal<LiveCall | null>(null);\n protected readonly loading = signal(true);\n protected readonly callId = signal('');\n protected readonly summary = signal<string | null>(null);\n protected readonly summaryLoading = signal(false);\n protected readonly mediaBusy = signal(false);\n protected readonly listSkeletonRows = [0, 1, 2] as const;\n protected readonly transcriptSkeletonRows = [0, 1, 2, 3, 4] as const;\n\n protected readonly liveTools = this.stream.tools;\n protected readonly callEnded = this.stream.callEnded;\n protected readonly mediaState = this.staffMedia.connectionState;\n protected readonly mediaMode = this.staffMedia.mode;\n protected readonly micEnabled = this.staffMedia.micEnabled;\n protected readonly audioPlaybackAllowed = this.staffMedia.audioPlaybackAllowed;\n\n private summaryLoaded = false;\n private staffJoined = false;\n\n private readonly onControlChanged = (evt: CallControlChangedEvent): void => {\n if (!evt?.callId || evt.callId !== this.callId()) return;\n this.call.update((c) => {\n if (!c) return c;\n const handedOff = evt.aiHandedOff === true || c.aiHandedOff === true;\n const controlMode = (evt.controlMode as CallControlMode | null | undefined) ?? c.controlMode;\n const next: LiveCall = {\n ...c,\n controlMode,\n aiPaused: typeof evt.aiPaused === 'boolean' ? evt.aiPaused : c.aiPaused,\n aiHandedOff: handedOff,\n assigned: evt.assigned !== undefined ? evt.assigned : c.assigned,\n };\n if (controlMode === 'takeover' || handedOff) {\n next.status = 'takeover';\n } else if (controlMode === 'ai' || controlMode === 'listen') {\n if (c.status === 'takeover') next.status = 'ai';\n }\n return next;\n });\n };\n\n constructor() {\n effect(() => {\n if (this.stream.callEnded()) {\n void this.staffMedia.disconnect();\n this.staffJoined = false;\n this.loadCallMetadataOnce();\n }\n });\n\n effect(() => {\n if (this.stream.summaryRequested() && !this.summaryLoaded) {\n this.loadPostCallSummary();\n }\n });\n }\n\n ngOnInit(): void {\n this.socket.acquire();\n this.socket.on<CallControlChangedEvent>('call_control_changed', this.onControlChanged);\n\n this.route.paramMap.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => {\n const id = params.get('id') ?? '';\n this.callId.set(id);\n // The softphone lives in a root service, so a session started earlier is still\n // running when this page is re-created.\n this.staffJoined = this.staffMedia.isConnectedTo(id);\n this.loading.set(true);\n this.summary.set(null);\n this.summaryLoaded = false;\n this.stream.stop();\n this.loadCallMetadata();\n });\n }\n\n /**\n * Leaving the page must never drop the caller. The LiveKit session is owned by the\n * root StaffMediaService and keeps running until End Call or an explicit leave.\n */\n ngOnDestroy(): void {\n this.socket.off('call_control_changed', this.onControlChanged);\n this.socket.release();\n this.stream.stop();\n }\n\n /** True when this page's call is the one the softphone is connected to. */\n protected isMediaForThisCall(): boolean {\n return this.staffMedia.activeCallId() === this.callId();\n }\n\n protected isTakeover(): boolean {\n if (this.mediaMode() === 'takeover' && this.isMediaForThisCall()) return true;\n const c = this.call();\n if (!c) return false;\n if (c.aiHandedOff) return true;\n if (c.controlMode === 'listen') return false;\n return c.controlMode === 'takeover' || c.status === 'takeover' || !!c.assigned;\n }\n\n /** After takeover the AI is gone for good — no resume path is offered. */\n protected isHandedOff(): boolean {\n return this.call()?.aiHandedOff === true || this.isTakeover();\n }\n\n protected isPaused(): boolean {\n const c = this.call();\n return c?.controlMode === 'paused' || !!c?.aiPaused;\n }\n\n protected isLive(): boolean {\n return !!this.call() && !this.callEnded();\n }\n\n protected confidenceLevel(confidence: number): 'high' | 'low' | 'mid' {\n if (confidence >= 70) return 'high';\n if (confidence < 50) return 'low';\n return 'mid';\n }\n\n protected sentimentPercent(sentiment: Sentiment): number {\n const map: Record<Sentiment, number> = {\n calm: 85,\n neutral: 60,\n frustrated: 35,\n urgent: 15,\n };\n return map[sentiment];\n }\n\n protected toolStateClass(state: string): string {\n return `live-monitor-page__tool--${state}`;\n }\n\n protected readonly toolTrackKey = toolEventTrackKey;\n\n protected isUnknownCaller(call: LiveCall): boolean {\n return isUnknownCaller(call.name, call.matched);\n }\n\n protected displayName(call: LiveCall): string {\n return this.isUnknownCaller(call) ? 'Unknown Caller' : call.name.trim();\n }\n\n protected profileInitials(call: LiveCall): string {\n return this.isUnknownCaller(call) ? '?' : call.initials || '?';\n }\n\n protected profileMeta(call: LiveCall): string {\n return callerMetaLine({\n name: call.name,\n matched: call.matched,\n phone: call.phone,\n dob: call.dob,\n age: call.age ?? ageFromDob(call.dob),\n gender: call.gender,\n });\n }\n\n protected goalBadge(call: LiveCall): string | null {\n const raw = (call.goal || call.reason || '').trim();\n if (!raw) return null;\n return raw.replace(/[_-]+/g, ' ').toUpperCase();\n }\n\n protected confidenceHint(confidence: number): string {\n const level = this.confidenceLevel(confidence);\n if (level === 'low') return 'Confidence dropped after the last response';\n if (level === 'high') return 'Agent is handling the request confidently';\n return 'Agent is still clarifying the caller needs';\n }\n\n protected sentimentLabel(sentiment: Sentiment): string {\n return toSentimentLabel(sentiment);\n }\n\n protected sentimentIcon(sentiment: Sentiment): string {\n return sentimentIconSrc(sentiment);\n }\n\n protected toolBadgeTone(state: string): string {\n switch (state) {\n case 'ok':\n return 'success';\n case 'warn':\n return 'warning';\n case 'error':\n return 'danger';\n case 'active':\n return 'primary';\n default:\n return 'light';\n }\n }\n\n protected toolBadgeLabel(state: string): string {\n switch (state) {\n case 'ok':\n return 'Done';\n case 'warn':\n return 'Needs Clarification';\n case 'error':\n return 'Failed';\n case 'active':\n return 'In Progress';\n default:\n return 'Next';\n }\n }\n\n protected readonly goalPlaceholderSteps = [\n {\n title: 'Understand the request',\n label: 'Needs Clarification',\n detail:\n 'Caller mentioned something from before but did not give enough detail to determine the reason for the call.',\n tone: 'warning',\n },\n {\n title: 'Verify patient identity',\n label: 'In Progress',\n detail: 'Confirm who the caller is so the AI can safely access relevant patient context.',\n tone: 'primary',\n },\n {\n title: 'Use patient context to clarify goal',\n label: 'Next',\n detail:\n 'Check recent appointments, referrals, orders, messages, or open items to understand the caller reference.',\n tone: 'light',\n },\n ] as const;\n\n protected takeover(): void {\n void this.joinMedia('takeover');\n }\n\n protected toggleMic(): void {\n void this.staffMedia.toggleMicrophone();\n }\n\n protected transfer(): void {\n this.api.postTransfer(this.callId()).subscribe(() => this.refreshMetadata());\n }\n\n protected endCall(): void {\n const id = this.callId();\n void this.staffMedia.disconnect().then(() => {\n this.staffJoined = false;\n this.api.postEnd(id).subscribe(() => {\n this.stream.markCompleted();\n this.loadCallMetadataOnce();\n this.loadPostCallSummary();\n });\n });\n }\n\n protected enableSound(): void {\n void this.staffMedia.startAudioPlayback();\n }\n\n private async joinMedia(mode: StaffMediaMode): Promise<void> {\n if (this.mediaBusy() || this.callEnded()) return;\n const id = this.callId();\n if (!id) return;\n\n // Check the mic before joining so a blocked browser never leaves the AI paused.\n if (mode === 'takeover' && !this.api.usesMockStreaming()) {\n const blocked = this.staffMedia.microphoneBlockedReason();\n if (blocked) {\n this.toast.show(blocked, 'error', 6000);\n return;\n }\n }\n\n this.mediaBusy.set(true);\n try {\n const { data } = await firstValueFrom(this.api.postMediaJoin(id, mode));\n this.applyJoinMetadata(data);\n\n if (!this.api.usesMockStreaming()) {\n await this.staffMedia.join(data);\n }\n this.staffJoined = true;\n this.toast.show(\n mode === 'takeover' ? 'You are on the call' : 'Listening to the call',\n 'success',\n );\n } catch (err) {\n const message =\n err instanceof Error ? err.message : `Failed to ${mode === 'takeover' ? 'take over' : 'listen'}`;\n this.toast.show(message, 'error');\n try {\n await this.staffMedia.disconnect();\n await firstValueFrom(this.api.postMediaLeave(id));\n } catch {\n /* ignore cleanup errors */\n }\n this.staffJoined = false;\n } finally {\n this.mediaBusy.set(false);\n }\n }\n\n /**\n * Disconnect LiveKit first, then tell the server to drop staff and restore AI.\n * Only valid in listen mode — a taken-over call stays with the human.\n * Does not hang up the patient.\n */\n private async leaveMedia(notifyServer: boolean): Promise<void> {\n const id = this.callId();\n const wasJoined = this.staffJoined || this.staffMedia.isConnectedTo(id);\n try {\n await this.staffMedia.disconnect();\n } catch {\n /* ignore */\n }\n this.staffJoined = false;\n\n if (!notifyServer || !wasJoined || !id || this.callEnded()) return;\n\n this.mediaBusy.set(true);\n try {\n await firstValueFrom(this.api.postResumeAi(id));\n this.call.update((c) =>\n c\n ? {\n ...c,\n status: c.status === 'takeover' ? 'ai' : c.status,\n controlMode: 'ai',\n assigned: null,\n aiPaused: false,\n }\n : c,\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to resume AI';\n this.toast.show(message, 'error');\n } finally {\n this.mediaBusy.set(false);\n }\n }\n\n private applyJoinMetadata(data: {\n controlMode?: string | null;\n aiPaused?: boolean;\n aiHandedOff?: boolean;\n assigned?: string | null;\n mode: StaffMediaMode;\n }): void {\n this.call.update((c) => {\n if (!c) return c;\n const controlMode = (data.controlMode as CallControlMode) || data.mode;\n return {\n ...c,\n controlMode,\n aiPaused: typeof data.aiPaused === 'boolean' ? data.aiPaused : data.mode === 'takeover',\n aiHandedOff:\n data.aiHandedOff === true || data.mode === 'takeover' || c.aiHandedOff === true,\n assigned:\n data.assigned !== undefined && data.assigned !== null\n ? data.assigned\n : data.mode === 'takeover'\n ? c.assigned || 'You'\n : c.assigned,\n status: data.mode === 'takeover' ? 'takeover' : c.status,\n };\n });\n }\n\n /** Initial load — seeds transcript/tools from REST, then starts socket. */\n private loadCallMetadata(): void {\n const id = this.callId();\n if (!id) return;\n this.api.getLiveCall(id).subscribe(({ data }) => {\n this.call.set(data);\n this.loading.set(false);\n if (data) {\n this.stream.seed(data.transcript, data.tools);\n if (!this.callEnded()) {\n this.stream.watch(id, true);\n }\n }\n });\n }\n\n /** Metadata-only refresh after staff actions — does not overwrite live transcript/tools. */\n private refreshMetadata(): void {\n const id = this.callId();\n if (!id) return;\n this.api.getLiveCall(id).subscribe(({ data }) => {\n if (data) this.call.set(data);\n });\n }\n\n /** One-time metadata refresh after call ends (no socket). */\n private loadCallMetadataOnce(): void {\n const id = this.callId();\n if (!id) return;\n this.api.getLiveCall(id).subscribe(({ data }) => {\n if (data) {\n this.call.set(data);\n }\n });\n }\n\n private loadPostCallSummary(): void {\n const id = this.callId();\n if (!id || this.summaryLoaded) return;\n this.summaryLoading.set(true);\n this.api.getCallSummary(id).subscribe(({ data }) => {\n this.summaryLoading.set(false);\n this.summaryLoaded = true;\n if (!data) return;\n this.summary.set(data.summary);\n this.stream.seed(data.transcript, data.tools);\n });\n }\n}\n","<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…\n } @else if (mediaMode() === 'takeover') {\n {{ micEnabled() ? 'On call · mic on' : 'On call · 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"],"names":["toSentimentLabel"],"mappings":"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"}
|