@edvak99/voice-receptionist-widget 1.1.0 → 1.1.2
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/README.md +1 -0
- package/fesm2022/{edvak99-voice-receptionist-widget-analytics-page.component-CoVjr5Y3.mjs → edvak99-voice-receptionist-widget-analytics-page.component-CW5OKmik.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-analytics-page.component-CoVjr5Y3.mjs.map → edvak99-voice-receptionist-widget-analytics-page.component-CW5OKmik.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-audit-page.component-ou9oxnJp.mjs → edvak99-voice-receptionist-widget-audit-page.component-DL1GfQyF.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-audit-page.component-ou9oxnJp.mjs.map → edvak99-voice-receptionist-widget-audit-page.component-DL1GfQyF.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-call-history-detail-page.component-BV7KOhd9.mjs → edvak99-voice-receptionist-widget-call-history-detail-page.component-CTwfUHUf.mjs} +4 -4
- package/fesm2022/{edvak99-voice-receptionist-widget-call-history-detail-page.component-BV7KOhd9.mjs.map → edvak99-voice-receptionist-widget-call-history-detail-page.component-CTwfUHUf.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-call-history-page.component-CWWma-6r.mjs → edvak99-voice-receptionist-widget-call-history-page.component-Cj4wxd4e.mjs} +3 -3
- package/fesm2022/{edvak99-voice-receptionist-widget-call-history-page.component-CWWma-6r.mjs.map → edvak99-voice-receptionist-widget-call-history-page.component-Cj4wxd4e.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-call-recording-player.component-B2IuwsVH.mjs → edvak99-voice-receptionist-widget-call-recording-player.component-AN6GcSDq.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-call-recording-player.component-B2IuwsVH.mjs.map → edvak99-voice-receptionist-widget-call-recording-player.component-AN6GcSDq.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-call-review.service-D-GutOar.mjs → edvak99-voice-receptionist-widget-call-review.service-Cy_Bf7AO.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-call-review.service-D-GutOar.mjs.map → edvak99-voice-receptionist-widget-call-review.service-Cy_Bf7AO.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-dashboard-page.component-B93giErR.mjs → edvak99-voice-receptionist-widget-dashboard-page.component-DzdIt2A7.mjs} +4 -4
- package/fesm2022/{edvak99-voice-receptionist-widget-dashboard-page.component-B93giErR.mjs.map → edvak99-voice-receptionist-widget-dashboard-page.component-DzdIt2A7.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-eds-elapsed.pipe-BrMNsxB5.mjs → edvak99-voice-receptionist-widget-eds-elapsed.pipe-ouRlPpwT.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-eds-elapsed.pipe-BrMNsxB5.mjs.map → edvak99-voice-receptionist-widget-eds-elapsed.pipe-ouRlPpwT.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-DClMfxeY.mjs → edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CMhknpGf.mjs} +35 -44
- package/fesm2022/edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CMhknpGf.mjs.map +1 -0
- package/fesm2022/{edvak99-voice-receptionist-widget-knowledge-hub.page-BNsM-o3z.mjs → edvak99-voice-receptionist-widget-knowledge-hub.page-cZqBuull.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-knowledge-hub.page-BNsM-o3z.mjs.map → edvak99-voice-receptionist-widget-knowledge-hub.page-cZqBuull.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-live-calls-list.service-C2UZJ5wF.mjs → edvak99-voice-receptionist-widget-live-calls-list.service-CDtFRW8w.mjs} +3 -3
- package/fesm2022/{edvak99-voice-receptionist-widget-live-calls-list.service-C2UZJ5wF.mjs.map → edvak99-voice-receptionist-widget-live-calls-list.service-CDtFRW8w.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-live-calls-page.component-DQTVJjsP.mjs → edvak99-voice-receptionist-widget-live-calls-page.component-DrYzXJQW.mjs} +4 -4
- package/fesm2022/{edvak99-voice-receptionist-widget-live-calls-page.component-DQTVJjsP.mjs.map → edvak99-voice-receptionist-widget-live-calls-page.component-DrYzXJQW.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-live-monitor-page.component-C3iTtVdn.mjs → edvak99-voice-receptionist-widget-live-monitor-page.component-D7dlk0y2.mjs} +4 -4
- package/fesm2022/{edvak99-voice-receptionist-widget-live-monitor-page.component-C3iTtVdn.mjs.map → edvak99-voice-receptionist-widget-live-monitor-page.component-D7dlk0y2.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-outbound-purposes-page.component-C10N-x5g.mjs → edvak99-voice-receptionist-widget-outbound-purposes-page.component-CJ8NEjcj.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-outbound-purposes-page.component-C10N-x5g.mjs.map → edvak99-voice-receptionist-widget-outbound-purposes-page.component-CJ8NEjcj.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-settings-page.component-BBE_H2jb.mjs → edvak99-voice-receptionist-widget-settings-page.component-Bo3XNK3b.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-settings-page.component-BBE_H2jb.mjs.map → edvak99-voice-receptionist-widget-settings-page.component-Bo3XNK3b.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-tasks-page.component-COnYcaMT.mjs → edvak99-voice-receptionist-widget-tasks-page.component-CBwl15NP.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-tasks-page.component-COnYcaMT.mjs.map → edvak99-voice-receptionist-widget-tasks-page.component-CBwl15NP.mjs.map} +1 -1
- package/fesm2022/{edvak99-voice-receptionist-widget-wizard-page.component-Box7X-Cq.mjs → edvak99-voice-receptionist-widget-wizard-page.component-CJLa5pia.mjs} +2 -2
- package/fesm2022/{edvak99-voice-receptionist-widget-wizard-page.component-Box7X-Cq.mjs.map → edvak99-voice-receptionist-widget-wizard-page.component-CJLa5pia.mjs.map} +1 -1
- package/fesm2022/edvak99-voice-receptionist-widget.mjs +1 -1
- package/lib/config.d.ts +5 -0
- package/lib/layout/eds-app-shell.component.d.ts +2 -0
- package/package.json +1 -1
- package/fesm2022/edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-DClMfxeY.mjs.map +0 -1
- package/lib/layout/eds-app-rail.component.d.ts +0 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edvak99-voice-receptionist-widget-call-recording-player.component-B2IuwsVH.mjs","sources":["../../../projects/voice-receptionist-widget/src/lib/components/call-recording-player/call-recording-player.component.ts","../../../projects/voice-receptionist-widget/src/lib/components/call-recording-player/call-recording-player.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n inject,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\nimport { catchError, distinctUntilChanged, EMPTY, map, switchMap, tap } from 'rxjs';\n\nimport { CallRecordingStatus } from '../../models/ai-receptionist.types';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport { EdsIconComponent } from '../../ui/eds-icon.component';\n\ntype PlayerPhase = 'loading' | CallRecordingStatus | 'error';\n\n@Component({\n selector: 'eds-call-recording-player',\n imports: [EdsIconComponent],\n templateUrl: './call-recording-player.component.html',\n styleUrl: './call-recording-player.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class CallRecordingPlayerComponent {\n readonly callId = input.required<string>();\n readonly currentTimeChange = output<number>();\n readonly durationChange = output<number>();\n\n private readonly audioRef = viewChild<ElementRef<HTMLAudioElement>>('audioEl');\n\n private readonly api = inject(AiReceptionistApiService);\n private readonly destroyRef = inject(DestroyRef);\n\n protected readonly phase = signal<PlayerPhase>('loading');\n protected readonly blobUrl = signal<string | null>(null);\n protected readonly durationSeconds = signal<number | null>(null);\n protected readonly message = signal<string | null>(null);\n\n /** Tracked outside signals so cleanup never reads blobUrl (avoids effect/subscription loops). */\n private objectUrl: string | null = null;\n\n constructor() {\n toObservable(this.callId)\n .pipe(\n distinctUntilChanged(),\n tap(() => this.revokeObjectUrl()),\n switchMap((id) => {\n if (!id) {\n this.resetUi();\n return EMPTY;\n }\n this.phase.set('loading');\n this.message.set(null);\n return this.api.getCallRecording(id).pipe(\n switchMap((meta) => {\n if (meta.status !== 'ready' || !meta.url) {\n this.phase.set(meta.status);\n this.message.set(meta.message ?? null);\n this.durationSeconds.set(meta.durationSeconds ?? null);\n return EMPTY;\n }\n this.durationSeconds.set(meta.durationSeconds ?? null);\n return this.api.getCallRecordingBlob(meta.url).pipe(\n map((blob) => blob),\n catchError(() => {\n this.phase.set('error');\n this.message.set('Could not load recording audio.');\n return EMPTY;\n }),\n );\n }),\n catchError(() => {\n this.phase.set('unavailable');\n this.message.set('Could not load recording metadata.');\n return EMPTY;\n }),\n );\n }),\n takeUntilDestroyed(),\n )\n .subscribe((blob) => {\n this.revokeObjectUrl();\n this.objectUrl = URL.createObjectURL(blob);\n this.blobUrl.set(this.objectUrl);\n this.phase.set('ready');\n this.message.set(null);\n const dur = this.durationSeconds();\n if (dur != null && dur > 0) {\n this.durationChange.emit(dur);\n }\n });\n\n this.destroyRef.onDestroy(() => this.revokeObjectUrl());\n }\n\n protected formatDuration(seconds: number): string {\n const m = Math.floor(seconds / 60);\n const s = seconds % 60;\n return `${m}:${s.toString().padStart(2, '0')}`;\n }\n\n protected onAudioError(): void {\n this.phase.set('error');\n this.message.set('Playback error — try reloading the page.');\n }\n\n protected onTimeUpdate(event: Event): void {\n const el = event.target as HTMLAudioElement;\n this.currentTimeChange.emit(el.currentTime);\n }\n\n protected onLoadedMetadata(event: Event): void {\n const el = event.target as HTMLAudioElement;\n if (Number.isFinite(el.duration) && el.duration > 0) {\n this.durationChange.emit(el.duration);\n }\n }\n\n /** Seek playback — used by synced transcript lines. */\n seekTo(seconds: number): void {\n const el = this.audioRef()?.nativeElement;\n if (!el) return;\n el.currentTime = Math.max(0, seconds);\n void el.play().catch(() => undefined);\n this.currentTimeChange.emit(el.currentTime);\n }\n\n private revokeObjectUrl(): void {\n if (this.objectUrl) {\n URL.revokeObjectURL(this.objectUrl);\n this.objectUrl = null;\n }\n this.blobUrl.set(null);\n }\n\n private resetUi(): void {\n this.phase.set('loading');\n this.durationSeconds.set(null);\n this.message.set(null);\n }\n}\n","<section class=\"call-recording-player\" aria-labelledby=\"call-recording-title\">\n <header class=\"call-recording-player__header\">\n <eds-icon name=\"graphic_eq\" [size]=\"20\" />\n <h3 id=\"call-recording-title\" class=\"eds-h3\">Call recording</h3>\n @if (durationSeconds(); as dur) {\n <span class=\"eds-mono-sm call-recording-player__duration\">{{ formatDuration(dur) }}</span>\n }\n </header>\n\n @switch (phase()) {\n @case ('loading') {\n <p class=\"call-recording-player__status eds-body-sm\">Loading recording…</p>\n }\n @case ('ready') {\n @if (blobUrl(); as src) {\n <audio\n #audioEl\n class=\"call-recording-player__audio\"\n controls\n [src]=\"src\"\n (error)=\"onAudioError()\"\n (timeupdate)=\"onTimeUpdate($event)\"\n (loadedmetadata)=\"onLoadedMetadata($event)\"\n >\n Your browser does not support audio playback.\n </audio>\n }\n }\n @case ('pending') {\n <p class=\"call-recording-player__status eds-body-sm\">\n {{ message() ?? 'Recording is still processing…' }}\n </p>\n }\n @case ('unavailable') {\n <p class=\"call-recording-player__status eds-body-sm call-recording-player__status--muted\">\n {{ message() ?? 'No recording available for this call.' }}\n </p>\n }\n @case ('failed') {\n <p class=\"call-recording-player__status eds-body-sm call-recording-player__status--error\">\n {{ message() ?? 'Recording could not be retrieved.' }}\n </p>\n }\n @case ('error') {\n <p class=\"call-recording-player__status eds-body-sm call-recording-player__status--error\">\n {{ message() ?? 'Playback error.' }}\n </p>\n }\n }\n</section>\n"],"names":[],"mappings":";;;;;;MA2Ba,4BAA4B,CAAA;AAkBvC,IAAA,WAAA,GAAA;AAjBS,QAAA,IAAA,CAAA,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAU;QACjC,IAAA,CAAA,iBAAiB,GAAG,MAAM,EAAU;QACpC,IAAA,CAAA,cAAc,GAAG,MAAM,EAAU;AAEzB,QAAA,IAAA,CAAA,QAAQ,GAAG,SAAS,CAA+B,SAAS,CAAC;AAE7D,QAAA,IAAA,CAAA,GAAG,GAAG,MAAM,CAAC,wBAAwB,CAAC;AACtC,QAAA,IAAA,CAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AAE7B,QAAA,IAAA,CAAA,KAAK,GAAG,MAAM,CAAc,SAAS,CAAC;AACtC,QAAA,IAAA,CAAA,OAAO,GAAG,MAAM,CAAgB,IAAI,CAAC;AACrC,QAAA,IAAA,CAAA,eAAe,GAAG,MAAM,CAAgB,IAAI,CAAC;AAC7C,QAAA,IAAA,CAAA,OAAO,GAAG,MAAM,CAAgB,IAAI,CAAC;;QAGhD,IAAA,CAAA,SAAS,GAAkB,IAAI;AAGrC,QAAA,YAAY,CAAC,IAAI,CAAC,MAAM;aACrB,IAAI,CACH,oBAAoB,EAAE,EACtB,GAAG,CAAC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC,EACjC,SAAS,CAAC,CAAC,EAAE,KAAI;YACf,IAAI,CAAC,EAAE,EAAE;gBACP,IAAI,CAAC,OAAO,EAAE;AACd,gBAAA,OAAO,KAAK;YACd;AACA,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;AACzB,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;AACtB,YAAA,OAAO,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,IAAI,CACvC,SAAS,CAAC,CAAC,IAAI,KAAI;gBACjB,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;oBACxC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;oBAC3B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;oBACtC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC;AACtD,oBAAA,OAAO,KAAK;gBACd;gBACA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC;gBACtD,OAAO,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CACjD,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EACnB,UAAU,CAAC,MAAK;AACd,oBAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;AACvB,oBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC;AACnD,oBAAA,OAAO,KAAK;gBACd,CAAC,CAAC,CACH;AACH,YAAA,CAAC,CAAC,EACF,UAAU,CAAC,MAAK;AACd,gBAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC;AAC7B,gBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC;AACtD,gBAAA,OAAO,KAAK;YACd,CAAC,CAAC,CACH;AACH,QAAA,CAAC,CAAC,EACF,kBAAkB,EAAE;AAErB,aAAA,SAAS,CAAC,CAAC,IAAI,KAAI;YAClB,IAAI,CAAC,eAAe,EAAE;YACtB,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC;YAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;AAChC,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;AACvB,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;AACtB,YAAA,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,EAAE;YAClC,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,EAAE;AAC1B,gBAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC;YAC/B;AACF,QAAA,CAAC,CAAC;AAEJ,QAAA,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;IACzD;AAEU,IAAA,cAAc,CAAC,OAAe,EAAA;QACtC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC;AAClC,QAAA,MAAM,CAAC,GAAG,OAAO,GAAG,EAAE;AACtB,QAAA,OAAO,CAAA,EAAG,CAAC,CAAA,CAAA,EAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;IAChD;IAEU,YAAY,GAAA;AACpB,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;AACvB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC;IAC9D;AAEU,IAAA,YAAY,CAAC,KAAY,EAAA;AACjC,QAAA,MAAM,EAAE,GAAG,KAAK,CAAC,MAA0B;QAC3C,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC;IAC7C;AAEU,IAAA,gBAAgB,CAAC,KAAY,EAAA;AACrC,QAAA,MAAM,EAAE,GAAG,KAAK,CAAC,MAA0B;AAC3C,QAAA,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,GAAG,CAAC,EAAE;YACnD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC;QACvC;IACF;;AAGA,IAAA,MAAM,CAAC,OAAe,EAAA;QACpB,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,EAAE,aAAa;AACzC,QAAA,IAAI,CAAC,EAAE;YAAE;QACT,EAAE,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC;AACrC,QAAA,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,SAAS,CAAC;QACrC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC;IAC7C;IAEQ,eAAe,GAAA;AACrB,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC;AACnC,YAAA,IAAI,CAAC,SAAS,GAAG,IAAI;QACvB;AACA,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IACxB;IAEQ,OAAO,GAAA;AACb,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;AACzB,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;AAC9B,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IACxB;+GApHW,4BAA4B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;mGAA5B,4BAA4B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,UAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,SAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EC3BzC,4wDAkDA,EAAA,MAAA,EAAA,CAAA,qnBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,ED5Bc,gBAAgB,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA,CAAA;;4FAKjB,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBAPxC,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,2BAA2B,WAC5B,CAAC,gBAAgB,CAAC,EAAA,eAAA,EAGV,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,4wDAAA,EAAA,MAAA,EAAA,CAAA,qnBAAA,CAAA,EAAA;;;;;"}
|
|
1
|
+
{"version":3,"file":"edvak99-voice-receptionist-widget-call-recording-player.component-AN6GcSDq.mjs","sources":["../../../projects/voice-receptionist-widget/src/lib/components/call-recording-player/call-recording-player.component.ts","../../../projects/voice-receptionist-widget/src/lib/components/call-recording-player/call-recording-player.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n inject,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\nimport { catchError, distinctUntilChanged, EMPTY, map, switchMap, tap } from 'rxjs';\n\nimport { CallRecordingStatus } from '../../models/ai-receptionist.types';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport { EdsIconComponent } from '../../ui/eds-icon.component';\n\ntype PlayerPhase = 'loading' | CallRecordingStatus | 'error';\n\n@Component({\n selector: 'eds-call-recording-player',\n imports: [EdsIconComponent],\n templateUrl: './call-recording-player.component.html',\n styleUrl: './call-recording-player.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class CallRecordingPlayerComponent {\n readonly callId = input.required<string>();\n readonly currentTimeChange = output<number>();\n readonly durationChange = output<number>();\n\n private readonly audioRef = viewChild<ElementRef<HTMLAudioElement>>('audioEl');\n\n private readonly api = inject(AiReceptionistApiService);\n private readonly destroyRef = inject(DestroyRef);\n\n protected readonly phase = signal<PlayerPhase>('loading');\n protected readonly blobUrl = signal<string | null>(null);\n protected readonly durationSeconds = signal<number | null>(null);\n protected readonly message = signal<string | null>(null);\n\n /** Tracked outside signals so cleanup never reads blobUrl (avoids effect/subscription loops). */\n private objectUrl: string | null = null;\n\n constructor() {\n toObservable(this.callId)\n .pipe(\n distinctUntilChanged(),\n tap(() => this.revokeObjectUrl()),\n switchMap((id) => {\n if (!id) {\n this.resetUi();\n return EMPTY;\n }\n this.phase.set('loading');\n this.message.set(null);\n return this.api.getCallRecording(id).pipe(\n switchMap((meta) => {\n if (meta.status !== 'ready' || !meta.url) {\n this.phase.set(meta.status);\n this.message.set(meta.message ?? null);\n this.durationSeconds.set(meta.durationSeconds ?? null);\n return EMPTY;\n }\n this.durationSeconds.set(meta.durationSeconds ?? null);\n return this.api.getCallRecordingBlob(meta.url).pipe(\n map((blob) => blob),\n catchError(() => {\n this.phase.set('error');\n this.message.set('Could not load recording audio.');\n return EMPTY;\n }),\n );\n }),\n catchError(() => {\n this.phase.set('unavailable');\n this.message.set('Could not load recording metadata.');\n return EMPTY;\n }),\n );\n }),\n takeUntilDestroyed(),\n )\n .subscribe((blob) => {\n this.revokeObjectUrl();\n this.objectUrl = URL.createObjectURL(blob);\n this.blobUrl.set(this.objectUrl);\n this.phase.set('ready');\n this.message.set(null);\n const dur = this.durationSeconds();\n if (dur != null && dur > 0) {\n this.durationChange.emit(dur);\n }\n });\n\n this.destroyRef.onDestroy(() => this.revokeObjectUrl());\n }\n\n protected formatDuration(seconds: number): string {\n const m = Math.floor(seconds / 60);\n const s = seconds % 60;\n return `${m}:${s.toString().padStart(2, '0')}`;\n }\n\n protected onAudioError(): void {\n this.phase.set('error');\n this.message.set('Playback error — try reloading the page.');\n }\n\n protected onTimeUpdate(event: Event): void {\n const el = event.target as HTMLAudioElement;\n this.currentTimeChange.emit(el.currentTime);\n }\n\n protected onLoadedMetadata(event: Event): void {\n const el = event.target as HTMLAudioElement;\n if (Number.isFinite(el.duration) && el.duration > 0) {\n this.durationChange.emit(el.duration);\n }\n }\n\n /** Seek playback — used by synced transcript lines. */\n seekTo(seconds: number): void {\n const el = this.audioRef()?.nativeElement;\n if (!el) return;\n el.currentTime = Math.max(0, seconds);\n void el.play().catch(() => undefined);\n this.currentTimeChange.emit(el.currentTime);\n }\n\n private revokeObjectUrl(): void {\n if (this.objectUrl) {\n URL.revokeObjectURL(this.objectUrl);\n this.objectUrl = null;\n }\n this.blobUrl.set(null);\n }\n\n private resetUi(): void {\n this.phase.set('loading');\n this.durationSeconds.set(null);\n this.message.set(null);\n }\n}\n","<section class=\"call-recording-player\" aria-labelledby=\"call-recording-title\">\n <header class=\"call-recording-player__header\">\n <eds-icon name=\"graphic_eq\" [size]=\"20\" />\n <h3 id=\"call-recording-title\" class=\"eds-h3\">Call recording</h3>\n @if (durationSeconds(); as dur) {\n <span class=\"eds-mono-sm call-recording-player__duration\">{{ formatDuration(dur) }}</span>\n }\n </header>\n\n @switch (phase()) {\n @case ('loading') {\n <p class=\"call-recording-player__status eds-body-sm\">Loading recording…</p>\n }\n @case ('ready') {\n @if (blobUrl(); as src) {\n <audio\n #audioEl\n class=\"call-recording-player__audio\"\n controls\n [src]=\"src\"\n (error)=\"onAudioError()\"\n (timeupdate)=\"onTimeUpdate($event)\"\n (loadedmetadata)=\"onLoadedMetadata($event)\"\n >\n Your browser does not support audio playback.\n </audio>\n }\n }\n @case ('pending') {\n <p class=\"call-recording-player__status eds-body-sm\">\n {{ message() ?? 'Recording is still processing…' }}\n </p>\n }\n @case ('unavailable') {\n <p class=\"call-recording-player__status eds-body-sm call-recording-player__status--muted\">\n {{ message() ?? 'No recording available for this call.' }}\n </p>\n }\n @case ('failed') {\n <p class=\"call-recording-player__status eds-body-sm call-recording-player__status--error\">\n {{ message() ?? 'Recording could not be retrieved.' }}\n </p>\n }\n @case ('error') {\n <p class=\"call-recording-player__status eds-body-sm call-recording-player__status--error\">\n {{ message() ?? 'Playback error.' }}\n </p>\n }\n }\n</section>\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { inject, signal, Injectable } from '@angular/core';
|
|
3
3
|
import { tap, map } from 'rxjs';
|
|
4
|
-
import { A as AiReceptionistApiService } from './edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-
|
|
4
|
+
import { A as AiReceptionistApiService } from './edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CMhknpGf.mjs';
|
|
5
5
|
|
|
6
6
|
class CallReviewService {
|
|
7
7
|
constructor() {
|
|
@@ -26,4 +26,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
26
26
|
}] });
|
|
27
27
|
|
|
28
28
|
export { CallReviewService as C };
|
|
29
|
-
//# sourceMappingURL=edvak99-voice-receptionist-widget-call-review.service-
|
|
29
|
+
//# sourceMappingURL=edvak99-voice-receptionist-widget-call-review.service-Cy_Bf7AO.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edvak99-voice-receptionist-widget-call-review.service-
|
|
1
|
+
{"version":3,"file":"edvak99-voice-receptionist-widget-call-review.service-Cy_Bf7AO.mjs","sources":["../../../projects/voice-receptionist-widget/src/lib/services/call-review.service.ts"],"sourcesContent":["import { Injectable, inject, signal } from '@angular/core';\nimport { Observable, map, tap } from 'rxjs';\n\nimport { CallReviewStatus } from '../utils/call-review.util';\nimport { AiReceptionistApiService } from './ai-receptionist-api.service';\n\n@Injectable({ providedIn: 'root' })\nexport class CallReviewService {\n private readonly api = inject(AiReceptionistApiService);\n\n /** Cached from dashboard summary; decremented optimistically on review. */\n readonly needsReviewCount = signal<number | null>(null);\n\n setNeedsReviewCount(count: number): void {\n this.needsReviewCount.set(count);\n }\n\n markReviewed(callId: string): Observable<CallReviewStatus> {\n return this.api.postReview(callId).pipe(\n tap(() => {\n this.needsReviewCount.update((c) => (c != null && c > 0 ? c - 1 : c));\n }),\n map(() => 'reviewed'),\n );\n }\n}\n"],"names":[],"mappings":";;;;;MAOa,iBAAiB,CAAA;AAD9B,IAAA,WAAA,GAAA;AAEmB,QAAA,IAAA,CAAA,GAAG,GAAG,MAAM,CAAC,wBAAwB,CAAC;;AAG9C,QAAA,IAAA,CAAA,gBAAgB,GAAG,MAAM,CAAgB,IAAI,CAAC;AAcxD,IAAA;AAZC,IAAA,mBAAmB,CAAC,KAAa,EAAA;AAC/B,QAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC;IAClC;AAEA,IAAA,YAAY,CAAC,MAAc,EAAA;AACzB,QAAA,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CACrC,GAAG,CAAC,MAAK;AACP,YAAA,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QACvE,CAAC,CAAC,EACF,GAAG,CAAC,MAAM,UAAU,CAAC,CACtB;IACH;+GAjBW,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAjB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,iBAAiB,cADJ,MAAM,EAAA,CAAA,CAAA;;4FACnB,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAD7B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;;;"}
|
|
@@ -2,14 +2,14 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { inject, EventEmitter, signal, Output, Input, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
3
|
import { Router, ActivatedRoute, RouterLink } from '@angular/router';
|
|
4
4
|
import { DatePipe } from '@angular/common';
|
|
5
|
-
import { A as AiReceptionistApiService, T as ToastService, M as ModalComponent, E as EdsButtonComponent, a as EdsBadgeComponent, b as EdsIconComponent, c as EdsPulseDotComponent } from './edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-
|
|
6
|
-
import { L as LiveCallsListService } from './edvak99-voice-receptionist-widget-live-calls-list.service-
|
|
5
|
+
import { A as AiReceptionistApiService, T as ToastService, M as ModalComponent, E as EdsButtonComponent, a as EdsBadgeComponent, b as EdsIconComponent, c as EdsPulseDotComponent } from './edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CMhknpGf.mjs';
|
|
6
|
+
import { L as LiveCallsListService } from './edvak99-voice-receptionist-widget-live-calls-list.service-CDtFRW8w.mjs';
|
|
7
7
|
import { o as outcomeBadgeTone, f as formatOutcomeLabel, r as reviewLabel, a as reviewBadgeTone, i as isNeedsReview } from './edvak99-voice-receptionist-widget-call-review.util-DQLIw7xb.mjs';
|
|
8
8
|
import * as i1 from '@angular/forms';
|
|
9
9
|
import { FormsModule } from '@angular/forms';
|
|
10
10
|
import { r as requiredFieldLabel, a as renderOpeningPreview, p as purposeShowsCustomScript, i as isCustomScriptRequired, b as isPurposeFormValid } from './edvak99-voice-receptionist-widget-outbound-purpose.util-BQECIuJu.mjs';
|
|
11
11
|
import { E as EdsAvatarComponent } from './edvak99-voice-receptionist-widget-eds-avatar.component-PCnIWeOA.mjs';
|
|
12
|
-
import { E as EdsElapsedPipe } from './edvak99-voice-receptionist-widget-eds-elapsed.pipe-
|
|
12
|
+
import { E as EdsElapsedPipe } from './edvak99-voice-receptionist-widget-eds-elapsed.pipe-ouRlPpwT.mjs';
|
|
13
13
|
|
|
14
14
|
const E164_PATTERN = /^\+[1-9]\d{6,14}$/;
|
|
15
15
|
class OutboundDialModalComponent {
|
|
@@ -245,4 +245,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
245
245
|
}] });
|
|
246
246
|
|
|
247
247
|
export { DashboardPageComponent };
|
|
248
|
-
//# sourceMappingURL=edvak99-voice-receptionist-widget-dashboard-page.component-
|
|
248
|
+
//# sourceMappingURL=edvak99-voice-receptionist-widget-dashboard-page.component-DzdIt2A7.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edvak99-voice-receptionist-widget-dashboard-page.component-B93giErR.mjs","sources":["../../../projects/voice-receptionist-widget/src/lib/components/outbound-dial-modal/outbound-dial-modal.component.ts","../../../projects/voice-receptionist-widget/src/lib/components/outbound-dial-modal/outbound-dial-modal.component.html","../../../projects/voice-receptionist-widget/src/lib/pages/dashboard-page/dashboard-page.component.ts","../../../projects/voice-receptionist-widget/src/lib/pages/dashboard-page/dashboard-page.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n OnChanges,\n Output,\n SimpleChanges,\n inject,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimport { OutboundPurpose } from '../../models/outbound-purpose.types';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport {\n isCustomScriptRequired,\n isPurposeFormValid,\n purposeShowsCustomScript,\n renderOpeningPreview,\n requiredFieldLabel,\n} from '../../utils/outbound-purpose.util';\nimport { EdsButtonComponent } from '../../ui/eds-button.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, EdsButtonComponent],\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\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 submitting = signal(false);\n protected readonly serverError = signal<string | null>(null);\n\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 ngOnChanges(changes: SimpleChanges): void {\n if (changes['open']?.currentValue) {\n this.resetForm();\n this.loadPurposes();\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 previewText(): string {\n const p = this.selectedPurpose;\n if (!p) return '—';\n return renderOpeningPreview(p.sampleOpening, p.openingTemplate, p.placeholders ?? []);\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 onPurposeChange(): void {\n this.appointmentDate = '';\n this.appointmentTime = '';\n this.providerName = '';\n this.customScript = '';\n this.serverError.set(null);\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 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 };\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 resetForm(): void {\n this.phone = '';\n this.name = '';\n this.purposeId = '';\n this.appointmentDate = '';\n this.appointmentTime = '';\n this.providerName = '';\n this.customScript = '';\n this.serverError.set(null);\n this.submitting.set(false);\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=\"Place a patient call using a purpose template\"\n maxWidth=\"560px\"\n (closed)=\"close()\"\n >\n @if (loading()) {\n <p class=\"eds-body-sm\">Loading purposes…</p>\n } @else {\n <form class=\"dial-form\" (ngSubmit)=\"submit()\" novalidate>\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">Phone <span class=\"dial-form__req\">*</span></span>\n <input\n type=\"tel\"\n class=\"dial-form__input\"\n [(ngModel)]=\"phone\"\n name=\"phone\"\n placeholder=\"+14155550100\"\n autocomplete=\"tel\"\n required\n />\n <span class=\"dial-form__hint\">E.164 format, e.g. +14155550100</span>\n </label>\n\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">Patient name <span class=\"dial-form__req\">*</span></span>\n <input\n type=\"text\"\n class=\"dial-form__input\"\n [(ngModel)]=\"name\"\n name=\"name\"\n placeholder=\"Maria Garcia\"\n required\n />\n </label>\n\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">Purpose <span class=\"dial-form__req\">*</span></span>\n <select\n class=\"dial-form__input\"\n [(ngModel)]=\"purposeId\"\n name=\"purposeId\"\n (ngModelChange)=\"onPurposeChange()\"\n required\n >\n @for (p of purposes(); track p.purposeId) {\n <option [value]=\"p.purposeId\">{{ p.label }}</option>\n }\n </select>\n </label>\n\n @if (showsField('appointmentDate')) {\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">{{ requiredFieldLabel('appointmentDate') }} <span class=\"dial-form__req\">*</span></span>\n <input type=\"date\" class=\"dial-form__input\" [(ngModel)]=\"appointmentDate\" name=\"appointmentDate\" required />\n </label>\n }\n\n @if (showsField('appointmentTime')) {\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">{{ requiredFieldLabel('appointmentTime') }} <span class=\"dial-form__req\">*</span></span>\n <input type=\"time\" class=\"dial-form__input\" [(ngModel)]=\"appointmentTime\" name=\"appointmentTime\" required />\n </label>\n }\n\n @if (showsField('providerName')) {\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">{{ requiredFieldLabel('providerName') }} <span class=\"dial-form__req\">*</span></span>\n <input\n type=\"text\"\n class=\"dial-form__input\"\n [(ngModel)]=\"providerName\"\n name=\"providerName\"\n placeholder=\"Dr. Patel\"\n required\n />\n </label>\n }\n\n @if (showsCustomScript()) {\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">\n Custom script\n @if (customScriptRequired()) {\n <span class=\"dial-form__req\">*</span>\n }\n </span>\n <textarea\n class=\"dial-form__textarea\"\n rows=\"4\"\n [(ngModel)]=\"customScript\"\n name=\"customScript\"\n [required]=\"customScriptRequired()\"\n placeholder=\"What should the agent say or do?\"\n ></textarea>\n </label>\n }\n\n <section class=\"dial-form__preview eds-card\">\n <h3 class=\"eds-label\">Opening preview</h3>\n <p class=\"dial-form__preview-text\">{{ previewText }}</p>\n </section>\n\n @if (serverError()) {\n <p class=\"dial-form__error\" role=\"alert\">{{ serverError() }}</p>\n }\n\n <footer class=\"dial-form__footer\">\n <eds-button variant=\"secondary\" type=\"button\" (click)=\"close()\" [disabled]=\"submitting()\">\n Cancel\n </eds-button>\n <eds-button variant=\"primary\" type=\"submit\" [disabled]=\"submitting() || !canPlaceCall()\">\n {{ submitting() ? 'Dialing…' : 'Place call' }}\n </eds-button>\n </footer>\n </form>\n }\n </app-modal>\n}\n","import { ChangeDetectionStrategy, Component, inject, OnDestroy, OnInit, signal } from '@angular/core';\nimport { ActivatedRoute, Router, RouterLink } from '@angular/router';\nimport { DatePipe } from '@angular/common';\n\nimport { DashboardData } from '../../models/ai-receptionist.types';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport { LiveCallsListService } from '../../services/live-calls-list.service';\nimport { formatOutcomeLabel, outcomeBadgeTone } from '../../utils/call-outcome.util';\nimport {\n isNeedsReview,\n reviewBadgeTone,\n reviewLabel,\n} from '../../utils/call-review.util';\nimport { OutboundDialModalComponent } from '../../components/outbound-dial-modal/outbound-dial-modal.component';\nimport { EdsAvatarComponent } from '../../ui/eds-avatar.component';\nimport { EdsBadgeComponent } from '../../ui/eds-badge.component';\nimport { EdsButtonComponent } from '../../ui/eds-button.component';\nimport { EdsIconComponent } from '../../ui/eds-icon.component';\nimport { EdsPulseDotComponent } from '../../ui/eds-pulse-dot.component';\nimport { EdsElapsedPipe } from '../../pipes/eds-elapsed.pipe';\n\n@Component({\n selector: 'eds-dashboard-page',\n imports: [\n RouterLink,\n DatePipe,\n EdsAvatarComponent,\n EdsBadgeComponent,\n EdsButtonComponent,\n EdsIconComponent,\n EdsPulseDotComponent,\n EdsElapsedPipe,\n OutboundDialModalComponent,\n ],\n templateUrl: './dashboard-page.component.html',\n styleUrl: './dashboard-page.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DashboardPageComponent implements OnInit, OnDestroy {\n private readonly api = inject(AiReceptionistApiService);\n private readonly liveCallsList = inject(LiveCallsListService);\n private readonly router = inject(Router);\n private readonly route = inject(ActivatedRoute);\n\n protected readonly data = signal<DashboardData | null>(null);\n protected readonly loading = signal(true);\n\n protected readonly liveCalls = this.liveCallsList.calls;\n protected readonly liveCallsLoading = this.liveCallsList.loading;\n protected readonly liveCallsError = this.liveCallsList.error;\n protected readonly outboundOpen = signal(false);\n\n protected readonly statTiles = [\n { key: 'activeCalls' as const, label: 'Live calls', icon: 'graphic_eq' },\n { key: 'answeredToday' as const, label: 'Calls today', icon: 'call' },\n { key: 'tasksCreated' as const, label: 'Open tasks', icon: 'task_alt' },\n {\n key: 'appointmentsBooked' as const,\n label: 'Appointments booked',\n icon: 'event_available',\n },\n { key: 'completionRate' as const, label: 'AI handled', icon: 'trending_up', suffix: '%' },\n ];\n\n ngOnInit(): void {\n this.liveCallsList.start();\n this.api.getDashboard().subscribe(({ data }) => {\n this.data.set(data);\n this.loading.set(false);\n });\n }\n\n ngOnDestroy(): void {\n this.liveCallsList.stop();\n }\n\n protected statValue(key: keyof DashboardData['stats']): number {\n if (key === 'activeCalls') {\n return this.liveCallsList.calls().length;\n }\n return this.data()?.stats[key] ?? 0;\n }\n\n protected statusTone(status: string): 'brand' | 'pos' | 'notice' | 'neg' | 'violet' | 'gray' {\n const normalized = status || 'ai';\n const map: Record<string, 'brand' | 'pos' | 'notice' | 'neg' | 'violet'> = {\n ai: 'brand',\n 'needs-help': 'notice',\n 'human-requested': 'violet',\n urgent: 'neg',\n takeover: 'violet',\n transferring: 'notice',\n };\n return map[normalized] ?? 'brand';\n }\n\n protected statusLabel(status: string): string {\n return status || 'ai';\n }\n\n protected outcomeTone = outcomeBadgeTone;\n protected outcomeLabel = formatOutcomeLabel;\n protected reviewLabel = reviewLabel;\n protected reviewTone = reviewBadgeTone;\n protected isNeedsReview = isNeedsReview;\n\n protected exportCsv(): void {\n // mock export\n }\n\n protected openOutboundDial(): void {\n this.outboundOpen.set(true);\n }\n\n protected closeOutboundDial(): void {\n this.outboundOpen.set(false);\n }\n\n protected openHistoryDetail(id: string): void {\n void this.router.navigate(['../history', id], { relativeTo: this.route });\n }\n\n protected callDetailLink(callId: string): string[] {\n return callId.startsWith('HC-') ? ['../history', callId] : ['../live', callId];\n }\n}\n","<div class=\"eds-page dashboard-page\">\n <header class=\"dashboard-page__header\">\n <div>\n <h1 class=\"eds-h1\">Dashboard</h1>\n <p class=\"eds-body-sm\">AI receptionist overview and live activity</p>\n </div>\n <div class=\"dashboard-page__actions\">\n <eds-button variant=\"secondary\" (click)=\"exportCsv()\">\n <eds-icon name=\"download\" [size]=\"18\" /> Export\n </eds-button>\n <eds-button variant=\"primary\" (click)=\"openOutboundDial()\">\n <eds-icon name=\"call_made\" [size]=\"18\" /> New outbound call\n </eds-button>\n </div>\n </header>\n\n @if (loading()) {\n <p class=\"eds-body-sm\">Loading dashboard…</p>\n } @else if (data()) {\n <section class=\"dashboard-page__stats\">\n @for (tile of statTiles; track tile.key) {\n @if (tile.key === 'appointmentsBooked') {\n <a routerLink=\"../appointments\" class=\"eds-card dashboard-page__stat dashboard-page__stat--link\">\n <eds-icon [name]=\"tile.icon\" [size]=\"22\" />\n <span class=\"eds-label\">{{ tile.label }}</span>\n <span class=\"dashboard-page__stat-value\">\n {{ statValue(tile.key) }}{{ tile.suffix ?? '' }}\n </span>\n </a>\n } @else if (tile.key === 'activeCalls') {\n <a routerLink=\"../live\" class=\"eds-card dashboard-page__stat dashboard-page__stat--link\">\n <eds-icon [name]=\"tile.icon\" [size]=\"22\" />\n <span class=\"eds-label\">{{ tile.label }}</span>\n <span class=\"dashboard-page__stat-value\">\n {{ statValue(tile.key) }}{{ tile.suffix ?? '' }}\n </span>\n </a>\n } @else {\n <article class=\"eds-card dashboard-page__stat\">\n <eds-icon [name]=\"tile.icon\" [size]=\"22\" />\n <span class=\"eds-label\">{{ tile.label }}</span>\n <span class=\"dashboard-page__stat-value\">\n {{ statValue(tile.key) }}{{ tile.suffix ?? '' }}\n </span>\n </article>\n }\n }\n </section>\n\n <section class=\"dashboard-page__grid\">\n <article class=\"eds-card dashboard-page__panel\">\n <header class=\"dashboard-page__panel-head\">\n <h2 class=\"eds-h2\">Live calls</h2>\n <eds-pulse-dot />\n </header>\n <ul class=\"dashboard-page__live-list\">\n @if (liveCallsError()) {\n <li class=\"dashboard-page__live-error eds-body-sm\" role=\"alert\">{{ liveCallsError() }}</li>\n }\n @if (liveCallsLoading() && liveCalls().length === 0) {\n <li class=\"eds-body-sm\">Loading live calls…</li>\n }\n @for (call of liveCalls(); track call.id) {\n <li>\n <a [routerLink]=\"['../live', call.id]\" class=\"dashboard-page__live-row\">\n <eds-avatar [initials]=\"call.initials\" tone=\"brand\" />\n <div class=\"dashboard-page__live-meta\">\n <span class=\"eds-body-sm-bold\">{{ call.name }}</span>\n <span class=\"eds-body-sm\">{{ call.reason }}</span>\n </div>\n <span class=\"eds-mono-sm\">{{ call.started | edsElapsed }}</span>\n </a>\n </li>\n } @empty {\n @if (!liveCallsLoading()) {\n <li class=\"eds-body-sm\">No active calls right now.</li>\n }\n }\n </ul>\n </article>\n\n <article class=\"eds-card dashboard-page__panel\">\n <header class=\"dashboard-page__panel-head\">\n <h2 class=\"eds-h2\">Tasks created</h2>\n <a routerLink=\"../tasks\" class=\"eds-body-sm\">View all</a>\n </header>\n <ul class=\"dashboard-page__attention-list\">\n @for (task of data()!.latestTasks; track task.id) {\n <li>\n <a\n [routerLink]=\"task.callId ? callDetailLink(task.callId) : ['../tasks']\"\n class=\"dashboard-page__attention-row\"\n [attr.aria-label]=\"'View task: ' + task.title\"\n >\n \n <div>\n <span class=\"eds-body-sm-bold\">{{ task.title }}</span>\n <span class=\"eds-body-sm\">\n {{ task.patient }} · {{ task.created | date: 'short' }}\n </span>\n </div>\n <eds-icon name=\"chevron_right\" [size]=\"20\" />\n </a>\n </li>\n } @empty {\n <li class=\"eds-body-sm\">No AI-created tasks yet.</li>\n }\n </ul>\n </article>\n\n <article class=\"eds-card dashboard-page__panel\">\n <header class=\"dashboard-page__panel-head\">\n <h2 class=\"eds-h2\">Appointments created</h2>\n <a routerLink=\"../appointments\" class=\"eds-body-sm\">View all</a>\n </header>\n <ul class=\"dashboard-page__attention-list\">\n @for (appointment of data()!.latestAppointments; track appointment.id) {\n <li>\n <a\n routerLink=\"../appointments\"\n class=\"dashboard-page__attention-row\"\n [attr.aria-label]=\"'View appointment for ' + appointment.patientName\"\n >\n \n <div>\n <span class=\"eds-body-sm-bold\">{{ appointment.patientName }}</span>\n <span class=\"eds-body-sm\">\n {{ appointment.providerName ?? 'Provider not assigned' }}\n · {{ appointment.startTime ? (appointment.startTime | date: 'short') : 'Time pending' }}\n </span>\n </div>\n <eds-icon name=\"chevron_right\" [size]=\"20\" />\n </a>\n </li>\n } @empty {\n <li class=\"eds-body-sm\">No AI-booked appointments yet.</li>\n }\n </ul>\n </article>\n\n </section>\n\n <article class=\"eds-card dashboard-page__history\">\n <header class=\"dashboard-page__panel-head\">\n <h2 class=\"eds-h2\">Recent call history</h2>\n <a routerLink=\"../history\" class=\"eds-body-sm\">View all</a>\n </header>\n <table class=\"eds-table\">\n <thead>\n <tr>\n <th>Caller</th>\n <th>Reason</th>\n <th>Outcome</th>\n <th>Review</th>\n <th>Location</th>\n <th>When</th>\n </tr>\n </thead>\n <tbody>\n @for (row of data()!.recentHistory; track row.id) {\n <tr\n class=\"dashboard-page__history-row\"\n [class.dashboard-page__row--needs-review]=\"isNeedsReview(row.review)\"\n tabindex=\"0\"\n role=\"link\"\n [attr.aria-label]=\"'View call details for ' + row.name\"\n (click)=\"openHistoryDetail(row.id)\"\n (keyup.enter)=\"openHistoryDetail(row.id)\"\n >\n <td>\n <div class=\"dashboard-page__caller\">\n <eds-avatar [initials]=\"row.initials\" />\n <span>{{ row.name }}</span>\n </div>\n </td>\n <td>{{ row.reason }}</td>\n <td>\n <eds-badge [tone]=\"outcomeTone(row.outcome)\">\n {{ outcomeLabel(row.outcome) }}\n </eds-badge>\n </td>\n <td>\n <eds-badge [tone]=\"reviewTone(row.review)\">\n {{ reviewLabel(row.review) }}\n </eds-badge>\n </td>\n <td>{{ row.location }}</td>\n <td class=\"eds-mono-sm\">{{ row.whenLabel ?? (row.started ? (row.started | date: 'short') : '—') }}</td>\n </tr>\n }\n </tbody>\n </table>\n </article>\n }\n</div>\n\n<eds-outbound-dial-modal\n [open]=\"outboundOpen()\"\n (closed)=\"closeOutboundDial()\"\n (dialed)=\"closeOutboundDial()\"\n/>\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"edvak99-voice-receptionist-widget-dashboard-page.component-DzdIt2A7.mjs","sources":["../../../projects/voice-receptionist-widget/src/lib/components/outbound-dial-modal/outbound-dial-modal.component.ts","../../../projects/voice-receptionist-widget/src/lib/components/outbound-dial-modal/outbound-dial-modal.component.html","../../../projects/voice-receptionist-widget/src/lib/pages/dashboard-page/dashboard-page.component.ts","../../../projects/voice-receptionist-widget/src/lib/pages/dashboard-page/dashboard-page.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n OnChanges,\n Output,\n SimpleChanges,\n inject,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimport { OutboundPurpose } from '../../models/outbound-purpose.types';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport {\n isCustomScriptRequired,\n isPurposeFormValid,\n purposeShowsCustomScript,\n renderOpeningPreview,\n requiredFieldLabel,\n} from '../../utils/outbound-purpose.util';\nimport { EdsButtonComponent } from '../../ui/eds-button.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, EdsButtonComponent],\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\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 submitting = signal(false);\n protected readonly serverError = signal<string | null>(null);\n\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 ngOnChanges(changes: SimpleChanges): void {\n if (changes['open']?.currentValue) {\n this.resetForm();\n this.loadPurposes();\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 previewText(): string {\n const p = this.selectedPurpose;\n if (!p) return '—';\n return renderOpeningPreview(p.sampleOpening, p.openingTemplate, p.placeholders ?? []);\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 onPurposeChange(): void {\n this.appointmentDate = '';\n this.appointmentTime = '';\n this.providerName = '';\n this.customScript = '';\n this.serverError.set(null);\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 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 };\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 resetForm(): void {\n this.phone = '';\n this.name = '';\n this.purposeId = '';\n this.appointmentDate = '';\n this.appointmentTime = '';\n this.providerName = '';\n this.customScript = '';\n this.serverError.set(null);\n this.submitting.set(false);\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=\"Place a patient call using a purpose template\"\n maxWidth=\"560px\"\n (closed)=\"close()\"\n >\n @if (loading()) {\n <p class=\"eds-body-sm\">Loading purposes…</p>\n } @else {\n <form class=\"dial-form\" (ngSubmit)=\"submit()\" novalidate>\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">Phone <span class=\"dial-form__req\">*</span></span>\n <input\n type=\"tel\"\n class=\"dial-form__input\"\n [(ngModel)]=\"phone\"\n name=\"phone\"\n placeholder=\"+14155550100\"\n autocomplete=\"tel\"\n required\n />\n <span class=\"dial-form__hint\">E.164 format, e.g. +14155550100</span>\n </label>\n\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">Patient name <span class=\"dial-form__req\">*</span></span>\n <input\n type=\"text\"\n class=\"dial-form__input\"\n [(ngModel)]=\"name\"\n name=\"name\"\n placeholder=\"Maria Garcia\"\n required\n />\n </label>\n\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">Purpose <span class=\"dial-form__req\">*</span></span>\n <select\n class=\"dial-form__input\"\n [(ngModel)]=\"purposeId\"\n name=\"purposeId\"\n (ngModelChange)=\"onPurposeChange()\"\n required\n >\n @for (p of purposes(); track p.purposeId) {\n <option [value]=\"p.purposeId\">{{ p.label }}</option>\n }\n </select>\n </label>\n\n @if (showsField('appointmentDate')) {\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">{{ requiredFieldLabel('appointmentDate') }} <span class=\"dial-form__req\">*</span></span>\n <input type=\"date\" class=\"dial-form__input\" [(ngModel)]=\"appointmentDate\" name=\"appointmentDate\" required />\n </label>\n }\n\n @if (showsField('appointmentTime')) {\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">{{ requiredFieldLabel('appointmentTime') }} <span class=\"dial-form__req\">*</span></span>\n <input type=\"time\" class=\"dial-form__input\" [(ngModel)]=\"appointmentTime\" name=\"appointmentTime\" required />\n </label>\n }\n\n @if (showsField('providerName')) {\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">{{ requiredFieldLabel('providerName') }} <span class=\"dial-form__req\">*</span></span>\n <input\n type=\"text\"\n class=\"dial-form__input\"\n [(ngModel)]=\"providerName\"\n name=\"providerName\"\n placeholder=\"Dr. Patel\"\n required\n />\n </label>\n }\n\n @if (showsCustomScript()) {\n <label class=\"dial-form__field\">\n <span class=\"eds-label\">\n Custom script\n @if (customScriptRequired()) {\n <span class=\"dial-form__req\">*</span>\n }\n </span>\n <textarea\n class=\"dial-form__textarea\"\n rows=\"4\"\n [(ngModel)]=\"customScript\"\n name=\"customScript\"\n [required]=\"customScriptRequired()\"\n placeholder=\"What should the agent say or do?\"\n ></textarea>\n </label>\n }\n\n <section class=\"dial-form__preview eds-card\">\n <h3 class=\"eds-label\">Opening preview</h3>\n <p class=\"dial-form__preview-text\">{{ previewText }}</p>\n </section>\n\n @if (serverError()) {\n <p class=\"dial-form__error\" role=\"alert\">{{ serverError() }}</p>\n }\n\n <footer class=\"dial-form__footer\">\n <eds-button variant=\"secondary\" type=\"button\" (click)=\"close()\" [disabled]=\"submitting()\">\n Cancel\n </eds-button>\n <eds-button variant=\"primary\" type=\"submit\" [disabled]=\"submitting() || !canPlaceCall()\">\n {{ submitting() ? 'Dialing…' : 'Place call' }}\n </eds-button>\n </footer>\n </form>\n }\n </app-modal>\n}\n","import { ChangeDetectionStrategy, Component, inject, OnDestroy, OnInit, signal } from '@angular/core';\nimport { ActivatedRoute, Router, RouterLink } from '@angular/router';\nimport { DatePipe } from '@angular/common';\n\nimport { DashboardData } from '../../models/ai-receptionist.types';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport { LiveCallsListService } from '../../services/live-calls-list.service';\nimport { formatOutcomeLabel, outcomeBadgeTone } from '../../utils/call-outcome.util';\nimport {\n isNeedsReview,\n reviewBadgeTone,\n reviewLabel,\n} from '../../utils/call-review.util';\nimport { OutboundDialModalComponent } from '../../components/outbound-dial-modal/outbound-dial-modal.component';\nimport { EdsAvatarComponent } from '../../ui/eds-avatar.component';\nimport { EdsBadgeComponent } from '../../ui/eds-badge.component';\nimport { EdsButtonComponent } from '../../ui/eds-button.component';\nimport { EdsIconComponent } from '../../ui/eds-icon.component';\nimport { EdsPulseDotComponent } from '../../ui/eds-pulse-dot.component';\nimport { EdsElapsedPipe } from '../../pipes/eds-elapsed.pipe';\n\n@Component({\n selector: 'eds-dashboard-page',\n imports: [\n RouterLink,\n DatePipe,\n EdsAvatarComponent,\n EdsBadgeComponent,\n EdsButtonComponent,\n EdsIconComponent,\n EdsPulseDotComponent,\n EdsElapsedPipe,\n OutboundDialModalComponent,\n ],\n templateUrl: './dashboard-page.component.html',\n styleUrl: './dashboard-page.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DashboardPageComponent implements OnInit, OnDestroy {\n private readonly api = inject(AiReceptionistApiService);\n private readonly liveCallsList = inject(LiveCallsListService);\n private readonly router = inject(Router);\n private readonly route = inject(ActivatedRoute);\n\n protected readonly data = signal<DashboardData | null>(null);\n protected readonly loading = signal(true);\n\n protected readonly liveCalls = this.liveCallsList.calls;\n protected readonly liveCallsLoading = this.liveCallsList.loading;\n protected readonly liveCallsError = this.liveCallsList.error;\n protected readonly outboundOpen = signal(false);\n\n protected readonly statTiles = [\n { key: 'activeCalls' as const, label: 'Live calls', icon: 'graphic_eq' },\n { key: 'answeredToday' as const, label: 'Calls today', icon: 'call' },\n { key: 'tasksCreated' as const, label: 'Open tasks', icon: 'task_alt' },\n {\n key: 'appointmentsBooked' as const,\n label: 'Appointments booked',\n icon: 'event_available',\n },\n { key: 'completionRate' as const, label: 'AI handled', icon: 'trending_up', suffix: '%' },\n ];\n\n ngOnInit(): void {\n this.liveCallsList.start();\n this.api.getDashboard().subscribe(({ data }) => {\n this.data.set(data);\n this.loading.set(false);\n });\n }\n\n ngOnDestroy(): void {\n this.liveCallsList.stop();\n }\n\n protected statValue(key: keyof DashboardData['stats']): number {\n if (key === 'activeCalls') {\n return this.liveCallsList.calls().length;\n }\n return this.data()?.stats[key] ?? 0;\n }\n\n protected statusTone(status: string): 'brand' | 'pos' | 'notice' | 'neg' | 'violet' | 'gray' {\n const normalized = status || 'ai';\n const map: Record<string, 'brand' | 'pos' | 'notice' | 'neg' | 'violet'> = {\n ai: 'brand',\n 'needs-help': 'notice',\n 'human-requested': 'violet',\n urgent: 'neg',\n takeover: 'violet',\n transferring: 'notice',\n };\n return map[normalized] ?? 'brand';\n }\n\n protected statusLabel(status: string): string {\n return status || 'ai';\n }\n\n protected outcomeTone = outcomeBadgeTone;\n protected outcomeLabel = formatOutcomeLabel;\n protected reviewLabel = reviewLabel;\n protected reviewTone = reviewBadgeTone;\n protected isNeedsReview = isNeedsReview;\n\n protected exportCsv(): void {\n // mock export\n }\n\n protected openOutboundDial(): void {\n this.outboundOpen.set(true);\n }\n\n protected closeOutboundDial(): void {\n this.outboundOpen.set(false);\n }\n\n protected openHistoryDetail(id: string): void {\n void this.router.navigate(['../history', id], { relativeTo: this.route });\n }\n\n protected callDetailLink(callId: string): string[] {\n return callId.startsWith('HC-') ? ['../history', callId] : ['../live', callId];\n }\n}\n","<div class=\"eds-page dashboard-page\">\n <header class=\"dashboard-page__header\">\n <div>\n <h1 class=\"eds-h1\">Dashboard</h1>\n <p class=\"eds-body-sm\">AI receptionist overview and live activity</p>\n </div>\n <div class=\"dashboard-page__actions\">\n <eds-button variant=\"secondary\" (click)=\"exportCsv()\">\n <eds-icon name=\"download\" [size]=\"18\" /> Export\n </eds-button>\n <eds-button variant=\"primary\" (click)=\"openOutboundDial()\">\n <eds-icon name=\"call_made\" [size]=\"18\" /> New outbound call\n </eds-button>\n </div>\n </header>\n\n @if (loading()) {\n <p class=\"eds-body-sm\">Loading dashboard…</p>\n } @else if (data()) {\n <section class=\"dashboard-page__stats\">\n @for (tile of statTiles; track tile.key) {\n @if (tile.key === 'appointmentsBooked') {\n <a routerLink=\"../appointments\" class=\"eds-card dashboard-page__stat dashboard-page__stat--link\">\n <eds-icon [name]=\"tile.icon\" [size]=\"22\" />\n <span class=\"eds-label\">{{ tile.label }}</span>\n <span class=\"dashboard-page__stat-value\">\n {{ statValue(tile.key) }}{{ tile.suffix ?? '' }}\n </span>\n </a>\n } @else if (tile.key === 'activeCalls') {\n <a routerLink=\"../live\" class=\"eds-card dashboard-page__stat dashboard-page__stat--link\">\n <eds-icon [name]=\"tile.icon\" [size]=\"22\" />\n <span class=\"eds-label\">{{ tile.label }}</span>\n <span class=\"dashboard-page__stat-value\">\n {{ statValue(tile.key) }}{{ tile.suffix ?? '' }}\n </span>\n </a>\n } @else {\n <article class=\"eds-card dashboard-page__stat\">\n <eds-icon [name]=\"tile.icon\" [size]=\"22\" />\n <span class=\"eds-label\">{{ tile.label }}</span>\n <span class=\"dashboard-page__stat-value\">\n {{ statValue(tile.key) }}{{ tile.suffix ?? '' }}\n </span>\n </article>\n }\n }\n </section>\n\n <section class=\"dashboard-page__grid\">\n <article class=\"eds-card dashboard-page__panel\">\n <header class=\"dashboard-page__panel-head\">\n <h2 class=\"eds-h2\">Live calls</h2>\n <eds-pulse-dot />\n </header>\n <ul class=\"dashboard-page__live-list\">\n @if (liveCallsError()) {\n <li class=\"dashboard-page__live-error eds-body-sm\" role=\"alert\">{{ liveCallsError() }}</li>\n }\n @if (liveCallsLoading() && liveCalls().length === 0) {\n <li class=\"eds-body-sm\">Loading live calls…</li>\n }\n @for (call of liveCalls(); track call.id) {\n <li>\n <a [routerLink]=\"['../live', call.id]\" class=\"dashboard-page__live-row\">\n <eds-avatar [initials]=\"call.initials\" tone=\"brand\" />\n <div class=\"dashboard-page__live-meta\">\n <span class=\"eds-body-sm-bold\">{{ call.name }}</span>\n <span class=\"eds-body-sm\">{{ call.reason }}</span>\n </div>\n <span class=\"eds-mono-sm\">{{ call.started | edsElapsed }}</span>\n </a>\n </li>\n } @empty {\n @if (!liveCallsLoading()) {\n <li class=\"eds-body-sm\">No active calls right now.</li>\n }\n }\n </ul>\n </article>\n\n <article class=\"eds-card dashboard-page__panel\">\n <header class=\"dashboard-page__panel-head\">\n <h2 class=\"eds-h2\">Tasks created</h2>\n <a routerLink=\"../tasks\" class=\"eds-body-sm\">View all</a>\n </header>\n <ul class=\"dashboard-page__attention-list\">\n @for (task of data()!.latestTasks; track task.id) {\n <li>\n <a\n [routerLink]=\"task.callId ? callDetailLink(task.callId) : ['../tasks']\"\n class=\"dashboard-page__attention-row\"\n [attr.aria-label]=\"'View task: ' + task.title\"\n >\n \n <div>\n <span class=\"eds-body-sm-bold\">{{ task.title }}</span>\n <span class=\"eds-body-sm\">\n {{ task.patient }} · {{ task.created | date: 'short' }}\n </span>\n </div>\n <eds-icon name=\"chevron_right\" [size]=\"20\" />\n </a>\n </li>\n } @empty {\n <li class=\"eds-body-sm\">No AI-created tasks yet.</li>\n }\n </ul>\n </article>\n\n <article class=\"eds-card dashboard-page__panel\">\n <header class=\"dashboard-page__panel-head\">\n <h2 class=\"eds-h2\">Appointments created</h2>\n <a routerLink=\"../appointments\" class=\"eds-body-sm\">View all</a>\n </header>\n <ul class=\"dashboard-page__attention-list\">\n @for (appointment of data()!.latestAppointments; track appointment.id) {\n <li>\n <a\n routerLink=\"../appointments\"\n class=\"dashboard-page__attention-row\"\n [attr.aria-label]=\"'View appointment for ' + appointment.patientName\"\n >\n \n <div>\n <span class=\"eds-body-sm-bold\">{{ appointment.patientName }}</span>\n <span class=\"eds-body-sm\">\n {{ appointment.providerName ?? 'Provider not assigned' }}\n · {{ appointment.startTime ? (appointment.startTime | date: 'short') : 'Time pending' }}\n </span>\n </div>\n <eds-icon name=\"chevron_right\" [size]=\"20\" />\n </a>\n </li>\n } @empty {\n <li class=\"eds-body-sm\">No AI-booked appointments yet.</li>\n }\n </ul>\n </article>\n\n </section>\n\n <article class=\"eds-card dashboard-page__history\">\n <header class=\"dashboard-page__panel-head\">\n <h2 class=\"eds-h2\">Recent call history</h2>\n <a routerLink=\"../history\" class=\"eds-body-sm\">View all</a>\n </header>\n <table class=\"eds-table\">\n <thead>\n <tr>\n <th>Caller</th>\n <th>Reason</th>\n <th>Outcome</th>\n <th>Review</th>\n <th>Location</th>\n <th>When</th>\n </tr>\n </thead>\n <tbody>\n @for (row of data()!.recentHistory; track row.id) {\n <tr\n class=\"dashboard-page__history-row\"\n [class.dashboard-page__row--needs-review]=\"isNeedsReview(row.review)\"\n tabindex=\"0\"\n role=\"link\"\n [attr.aria-label]=\"'View call details for ' + row.name\"\n (click)=\"openHistoryDetail(row.id)\"\n (keyup.enter)=\"openHistoryDetail(row.id)\"\n >\n <td>\n <div class=\"dashboard-page__caller\">\n <eds-avatar [initials]=\"row.initials\" />\n <span>{{ row.name }}</span>\n </div>\n </td>\n <td>{{ row.reason }}</td>\n <td>\n <eds-badge [tone]=\"outcomeTone(row.outcome)\">\n {{ outcomeLabel(row.outcome) }}\n </eds-badge>\n </td>\n <td>\n <eds-badge [tone]=\"reviewTone(row.review)\">\n {{ reviewLabel(row.review) }}\n </eds-badge>\n </td>\n <td>{{ row.location }}</td>\n <td class=\"eds-mono-sm\">{{ row.whenLabel ?? (row.started ? (row.started | date: 'short') : '—') }}</td>\n </tr>\n }\n </tbody>\n </table>\n </article>\n }\n</div>\n\n<eds-outbound-dial-modal\n [open]=\"outboundOpen()\"\n (closed)=\"closeOutboundDial()\"\n (dialed)=\"closeOutboundDial()\"\n/>\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { inject, signal, Injectable, Pipe } from '@angular/core';
|
|
3
3
|
import { io } from 'socket.io-client';
|
|
4
|
-
import { V as VOICE_RECEPTIONIST_CONFIG, e as createVoiceReceptionistPaths } from './edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-
|
|
4
|
+
import { V as VOICE_RECEPTIONIST_CONFIG, e as createVoiceReceptionistPaths } from './edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CMhknpGf.mjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Single shared Socket.io connection to the `/dashboard` namespace.
|
|
@@ -133,4 +133,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
133
133
|
}] });
|
|
134
134
|
|
|
135
135
|
export { DashboardSocketService as D, EdsElapsedPipe as E };
|
|
136
|
-
//# sourceMappingURL=edvak99-voice-receptionist-widget-eds-elapsed.pipe-
|
|
136
|
+
//# sourceMappingURL=edvak99-voice-receptionist-widget-eds-elapsed.pipe-ouRlPpwT.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edvak99-voice-receptionist-widget-eds-elapsed.pipe-
|
|
1
|
+
{"version":3,"file":"edvak99-voice-receptionist-widget-eds-elapsed.pipe-ouRlPpwT.mjs","sources":["../../../projects/voice-receptionist-widget/src/lib/services/dashboard-socket.service.ts","../../../projects/voice-receptionist-widget/src/lib/pipes/eds-elapsed.pipe.ts"],"sourcesContent":["import { Injectable, inject, signal } from '@angular/core';\nimport { io, Socket } from 'socket.io-client';\n\nimport { createVoiceReceptionistPaths } from '../api-paths';\nimport { VOICE_RECEPTIONIST_CONFIG } from '../config';\n\ntype SocketHandler = (...args: unknown[]) => void;\n\n/**\n * Single shared Socket.io connection to the `/dashboard` namespace.\n * Used by live calls list + per-call transcript stream.\n */\n@Injectable({ providedIn: 'root' })\nexport class DashboardSocketService {\n private readonly config = inject(VOICE_RECEPTIONIST_CONFIG);\n private readonly paths = createVoiceReceptionistPaths(this.config);\n\n readonly connected = signal(false);\n\n private socket: Socket | null = null;\n private refCount = 0;\n private readonly handlers = new Map<string, Map<SocketHandler, SocketHandler>>();\n private readonly connectCallbacks = new Set<() => void>();\n\n acquire(): void {\n this.refCount++;\n if (this.refCount === 1) {\n this.connect();\n }\n }\n\n release(): void {\n this.refCount = Math.max(0, this.refCount - 1);\n if (this.refCount === 0) {\n this.disconnect();\n }\n }\n\n onConnect(callback: () => void): void {\n this.connectCallbacks.add(callback);\n if (this.connected()) {\n callback();\n }\n }\n\n offConnect(callback: () => void): void {\n this.connectCallbacks.delete(callback);\n }\n\n on<T>(event: string, handler: (payload: T) => void): void {\n const wrapped: SocketHandler = (payload) => handler(payload as T);\n if (!this.handlers.has(event)) {\n this.handlers.set(event, new Map());\n }\n this.handlers.get(event)!.set(handler as SocketHandler, wrapped);\n\n if (this.socket) {\n this.socket.on(event, wrapped);\n }\n }\n\n off<T>(event: string, handler: (payload: T) => void): void {\n const eventHandlers = this.handlers.get(event);\n const wrapped = eventHandlers?.get(handler as SocketHandler);\n if (wrapped) {\n this.socket?.off(event, wrapped);\n eventHandlers!.delete(handler as SocketHandler);\n }\n }\n\n emit(event: string, payload?: unknown): void {\n this.socket?.emit(event, payload);\n }\n\n private connect(): void {\n if (this.config.useMockApi) {\n this.connected.set(true);\n this.fireConnectCallbacks();\n return;\n }\n\n this.socket = io(`${this.paths.apiRoot()}/dashboard`, {\n path: '/socket.io',\n transports: ['websocket'],\n autoConnect: false,\n });\n\n this.socket.on('connect', () => {\n this.connected.set(true);\n this.fireConnectCallbacks();\n });\n\n this.socket.on('disconnect', () => {\n this.connected.set(false);\n });\n\n this.socket.io.on('reconnect', () => {\n this.fireConnectCallbacks();\n });\n\n for (const [event, handlerMap] of this.handlers) {\n for (const wrapped of handlerMap.values()) {\n this.socket.on(event, wrapped);\n }\n }\n\n this.socket.connect();\n }\n\n private disconnect(): void {\n if (!this.socket) {\n this.connected.set(false);\n return;\n }\n\n for (const [event, handlerMap] of this.handlers) {\n for (const wrapped of handlerMap.values()) {\n this.socket.off(event, wrapped);\n }\n }\n\n this.socket.removeAllListeners();\n this.socket.disconnect();\n this.socket = null;\n this.connected.set(false);\n }\n\n private fireConnectCallbacks(): void {\n for (const cb of this.connectCallbacks) {\n cb();\n }\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({ name: 'edsElapsed', standalone: true, pure: false })\nexport class EdsElapsedPipe implements PipeTransform {\n transform(startMs: number | null | undefined): string {\n if (!startMs) return '0:00';\n const sec = Math.max(0, Math.floor((Date.now() - startMs) / 1000));\n const m = Math.floor(sec / 60);\n const s = sec % 60;\n return `${m}:${s.toString().padStart(2, '0')}`;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -57,34 +57,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
57
57
|
args: [{ selector: 'app-toast-container', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"toast-stack\" aria-live=\"polite\" aria-atomic=\"false\">\n @for (toast of toastService.toasts(); track toast.id) {\n <div class=\"toast\" [class]=\"'toast-' + toast.variant\" role=\"status\">\n <span class=\"toast-icon\" aria-hidden=\"true\">\n @switch (toast.variant) {\n @case ('success') {\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n }\n @case ('error') {\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"13\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n }\n @default {\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n }\n }\n </span>\n <span class=\"toast-text\">{{ toast.text }}</span>\n <button\n type=\"button\"\n class=\"toast-dismiss\"\n (click)=\"toastService.dismiss(toast.id)\"\n aria-label=\"Dismiss notification\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n }\n</div>\n", styles: [":host{position:fixed;bottom:24px;right:24px;z-index:1100;pointer-events:none}.toast-stack{display:flex;flex-direction:column;gap:10px;max-width:380px}.toast{pointer-events:auto;display:flex;align-items:flex-start;gap:10px;padding:12px 14px;background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);box-shadow:0 6px 24px #141e321f;font-size:13px;color:var(--color-text);animation:slide-in .16s ease}.toast-icon{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;flex-shrink:0}.toast-info .toast-icon{background:var(--color-primary-soft);color:var(--color-primary)}.toast-success .toast-icon{background:var(--color-success-soft);color:var(--color-success)}.toast-error .toast-icon{background:var(--color-danger-soft);color:var(--color-danger)}.toast-text{flex:1;line-height:1.45}.toast-dismiss{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;color:var(--color-text-soft);border-radius:4px;transition:background .12s ease,color .12s ease}.toast-dismiss:hover{background:var(--color-surface-alt);color:var(--color-text)}@keyframes slide-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}\n"] }]
|
|
58
58
|
}] });
|
|
59
59
|
|
|
60
|
-
class EdsIconComponent {
|
|
61
|
-
constructor() {
|
|
62
|
-
this.name = input.required();
|
|
63
|
-
this.size = input(20);
|
|
64
|
-
this.fill = input(0);
|
|
65
|
-
this.weight = input(400);
|
|
66
|
-
this.variation = computed(() => `'FILL' ${this.fill()}, 'wght' ${this.weight()}, 'GRAD' 0, 'opsz' ${this.size()}`);
|
|
67
|
-
}
|
|
68
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EdsIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
69
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.17", type: EdsIconComponent, isStandalone: true, selector: "eds-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null }, weight: { classPropertyName: "weight", publicName: "weight", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `<span class="eds-icon" [style.font-size.px]="size()" [style.font-variation-settings]="variation()">{{ name() }}</span>`, isInline: true, styles: [":host{display:inline-flex;line-height:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
70
|
-
}
|
|
71
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EdsIconComponent, decorators: [{
|
|
72
|
-
type: Component,
|
|
73
|
-
args: [{ selector: 'eds-icon', standalone: true, template: `<span class="eds-icon" [style.font-size.px]="size()" [style.font-variation-settings]="variation()">{{ name() }}</span>`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:inline-flex;line-height:0}\n"] }]
|
|
74
|
-
}] });
|
|
75
|
-
|
|
76
|
-
class EdsAppRailComponent {
|
|
77
|
-
constructor() {
|
|
78
|
-
this.includePracticeNav = !!inject(VOICE_RECEPTIONIST_CONFIG).includePracticeNav;
|
|
79
|
-
}
|
|
80
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EdsAppRailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
81
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: EdsAppRailComponent, isStandalone: true, selector: "eds-app-rail", ngImport: i0, template: "<aside class=\"eds-rail\" aria-label=\"EDS product navigation\">\n <a routerLink=\"dashboard\" class=\"eds-rail-logo\" title=\"Edvak\">e</a>\n <nav class=\"eds-rail-nav\">\n <a routerLink=\"dashboard\" routerLinkActive=\"active\" title=\"Dashboard\">\n <eds-icon name=\"space_dashboard\" [size]=\"22\" />\n </a>\n @if (includePracticeNav) {\n <a routerLink=\"appointments\" routerLinkActive=\"active\" title=\"Appointments\">\n <eds-icon name=\"calendar_month\" [size]=\"22\" />\n </a>\n <a routerLink=\"patients\" routerLinkActive=\"active\" title=\"Patients\">\n <eds-icon name=\"groups\" [size]=\"22\" />\n </a>\n }\n <span title=\"Chat (coming soon)\"><eds-icon name=\"chat\" [size]=\"22\" /></span>\n <a routerLink=\"live\" routerLinkActive=\"active\" title=\"AI Receptionist\">\n <eds-icon name=\"headset_mic\" [size]=\"22\" [fill]=\"1\" />\n </a>\n <span title=\"Billing (coming soon)\"><eds-icon name=\"currency_exchange\" [size]=\"22\" /></span>\n <span title=\"Documents (coming soon)\"><eds-icon name=\"description\" [size]=\"22\" /></span>\n <span title=\"Leaderboard (coming soon)\"><eds-icon name=\"leaderboard\" [size]=\"22\" /></span>\n </nav>\n <div class=\"eds-rail-footer\">\n <a routerLink=\"settings\" routerLinkActive=\"active\" title=\"Settings\">\n <eds-icon name=\"settings\" [size]=\"22\" />\n </a>\n <span class=\"eds-rail-avatar\" title=\"User\">HS</span>\n </div>\n</aside>\n", styles: [":host{display:block;flex-shrink:0}.eds-rail{width:var(--eds-rail-width);min-height:100vh;background:var(--surface-l0);border-right:1px solid var(--border-default);display:flex;flex-direction:column;align-items:center;padding:12px 0;position:sticky;top:0;height:100vh}.eds-rail-logo{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:var(--eds-radius-md);background:var(--bg-brand);color:#fff;font-family:var(--font-figtree);font-weight:800;font-size:18px;text-decoration:none;margin-bottom:16px}.eds-rail-nav{display:flex;flex-direction:column;gap:4px;flex:1}.eds-rail-nav a,.eds-rail-nav span{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--eds-radius-md);color:var(--gray-500);cursor:default}.eds-rail-nav a{cursor:pointer;text-decoration:none}.eds-rail-nav a:hover{background:var(--gray-100);color:var(--gray-700)}.eds-rail-nav a.active{background:#3681f41f;color:var(--brand-600)}.eds-rail-footer{display:flex;flex-direction:column;align-items:center;gap:8px}.eds-rail-footer a{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--eds-radius-md);color:var(--gray-500);text-decoration:none}.eds-rail-footer a:hover{background:var(--gray-100)}.eds-rail-avatar{width:32px;height:32px;border-radius:50%;background:var(--gray-200);color:var(--gray-600);font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: EdsIconComponent, selector: "eds-icon", inputs: ["name", "size", "fill", "weight"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
82
|
-
}
|
|
83
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EdsAppRailComponent, decorators: [{
|
|
84
|
-
type: Component,
|
|
85
|
-
args: [{ selector: 'eds-app-rail', imports: [RouterLink, RouterLinkActive, EdsIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<aside class=\"eds-rail\" aria-label=\"EDS product navigation\">\n <a routerLink=\"dashboard\" class=\"eds-rail-logo\" title=\"Edvak\">e</a>\n <nav class=\"eds-rail-nav\">\n <a routerLink=\"dashboard\" routerLinkActive=\"active\" title=\"Dashboard\">\n <eds-icon name=\"space_dashboard\" [size]=\"22\" />\n </a>\n @if (includePracticeNav) {\n <a routerLink=\"appointments\" routerLinkActive=\"active\" title=\"Appointments\">\n <eds-icon name=\"calendar_month\" [size]=\"22\" />\n </a>\n <a routerLink=\"patients\" routerLinkActive=\"active\" title=\"Patients\">\n <eds-icon name=\"groups\" [size]=\"22\" />\n </a>\n }\n <span title=\"Chat (coming soon)\"><eds-icon name=\"chat\" [size]=\"22\" /></span>\n <a routerLink=\"live\" routerLinkActive=\"active\" title=\"AI Receptionist\">\n <eds-icon name=\"headset_mic\" [size]=\"22\" [fill]=\"1\" />\n </a>\n <span title=\"Billing (coming soon)\"><eds-icon name=\"currency_exchange\" [size]=\"22\" /></span>\n <span title=\"Documents (coming soon)\"><eds-icon name=\"description\" [size]=\"22\" /></span>\n <span title=\"Leaderboard (coming soon)\"><eds-icon name=\"leaderboard\" [size]=\"22\" /></span>\n </nav>\n <div class=\"eds-rail-footer\">\n <a routerLink=\"settings\" routerLinkActive=\"active\" title=\"Settings\">\n <eds-icon name=\"settings\" [size]=\"22\" />\n </a>\n <span class=\"eds-rail-avatar\" title=\"User\">HS</span>\n </div>\n</aside>\n", styles: [":host{display:block;flex-shrink:0}.eds-rail{width:var(--eds-rail-width);min-height:100vh;background:var(--surface-l0);border-right:1px solid var(--border-default);display:flex;flex-direction:column;align-items:center;padding:12px 0;position:sticky;top:0;height:100vh}.eds-rail-logo{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:var(--eds-radius-md);background:var(--bg-brand);color:#fff;font-family:var(--font-figtree);font-weight:800;font-size:18px;text-decoration:none;margin-bottom:16px}.eds-rail-nav{display:flex;flex-direction:column;gap:4px;flex:1}.eds-rail-nav a,.eds-rail-nav span{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--eds-radius-md);color:var(--gray-500);cursor:default}.eds-rail-nav a{cursor:pointer;text-decoration:none}.eds-rail-nav a:hover{background:var(--gray-100);color:var(--gray-700)}.eds-rail-nav a.active{background:#3681f41f;color:var(--brand-600)}.eds-rail-footer{display:flex;flex-direction:column;align-items:center;gap:8px}.eds-rail-footer a{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--eds-radius-md);color:var(--gray-500);text-decoration:none}.eds-rail-footer a:hover{background:var(--gray-100)}.eds-rail-avatar{width:32px;height:32px;border-radius:50%;background:var(--gray-200);color:var(--gray-600);font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center}\n"] }]
|
|
86
|
-
}] });
|
|
87
|
-
|
|
88
60
|
/** Build URL helpers from a config (or raw base URL). Safe outside injection context. */
|
|
89
61
|
function createVoiceReceptionistPaths(configOrBase) {
|
|
90
62
|
const base = typeof configOrBase === 'string' ? configOrBase : configOrBase.apiBaseUrl;
|
|
@@ -2336,6 +2308,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
2336
2308
|
args: [{ providedIn: 'root' }]
|
|
2337
2309
|
}] });
|
|
2338
2310
|
|
|
2311
|
+
class EdsIconComponent {
|
|
2312
|
+
constructor() {
|
|
2313
|
+
this.name = input.required();
|
|
2314
|
+
this.size = input(20);
|
|
2315
|
+
this.fill = input(0);
|
|
2316
|
+
this.weight = input(400);
|
|
2317
|
+
this.variation = computed(() => `'FILL' ${this.fill()}, 'wght' ${this.weight()}, 'GRAD' 0, 'opsz' ${this.size()}`);
|
|
2318
|
+
}
|
|
2319
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EdsIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2320
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.17", type: EdsIconComponent, isStandalone: true, selector: "eds-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null }, weight: { classPropertyName: "weight", publicName: "weight", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `<span class="eds-icon" [style.font-size.px]="size()" [style.font-variation-settings]="variation()">{{ name() }}</span>`, isInline: true, styles: [":host{display:inline-flex;line-height:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2321
|
+
}
|
|
2322
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EdsIconComponent, decorators: [{
|
|
2323
|
+
type: Component,
|
|
2324
|
+
args: [{ selector: 'eds-icon', standalone: true, template: `<span class="eds-icon" [style.font-size.px]="size()" [style.font-variation-settings]="variation()">{{ name() }}</span>`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:inline-flex;line-height:0}\n"] }]
|
|
2325
|
+
}] });
|
|
2326
|
+
|
|
2339
2327
|
class EdsPulseDotComponent {
|
|
2340
2328
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EdsPulseDotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2341
2329
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: EdsPulseDotComponent, isStandalone: true, selector: "eds-pulse-dot", ngImport: i0, template: `<span class="eds-pulse-dot"><span class="eds-pulse-dot__core"></span></span>`, isInline: true, styles: [".eds-pulse-dot{position:relative;display:inline-flex;width:8px;height:8px}.eds-pulse-dot__core{width:8px;height:8px;border-radius:50%;background:var(--green-500)}.eds-pulse-dot__core:after{content:\"\";position:absolute;inset:0;border-radius:50%;background:var(--green-500);animation:eds-ping 1.4s cubic-bezier(0,0,.2,1) infinite}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
@@ -2564,18 +2552,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
2564
2552
|
}], ctorParameters: () => [] });
|
|
2565
2553
|
|
|
2566
2554
|
class EdsAppShellComponent {
|
|
2555
|
+
constructor() {
|
|
2556
|
+
/** EHR embed: false (default). Standalone Voice Hub: set showModuleNav: true. */
|
|
2557
|
+
this.showModuleNav = !!inject(VOICE_RECEPTIONIST_CONFIG).showModuleNav;
|
|
2558
|
+
}
|
|
2567
2559
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EdsAppShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2568
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
2560
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: EdsAppShellComponent, isStandalone: true, selector: "eds-app-shell", ngImport: i0, template: "<div class=\"eds-layout\">\n @if (showModuleNav) {\n <eds-module-nav />\n }\n <div class=\"eds-main\">\n <eds-topbar />\n <div class=\"eds-content\">\n <router-outlet />\n </div>\n </div>\n</div>\n<app-toast-container />\n", styles: [":host{display:block}.eds-layout{display:flex;min-height:100vh;background:var(--surface-l1)}.eds-main{flex:1;min-width:0;display:flex;flex-direction:column}.eds-content{flex:1;overflow:auto}\n"], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: EdsModuleNavComponent, selector: "eds-module-nav" }, { kind: "component", type: EdsTopbarComponent, selector: "eds-topbar" }, { kind: "component", type: ToastContainerComponent, selector: "app-toast-container" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2569
2561
|
}
|
|
2570
2562
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EdsAppShellComponent, decorators: [{
|
|
2571
2563
|
type: Component,
|
|
2572
2564
|
args: [{ selector: 'eds-app-shell', imports: [
|
|
2573
2565
|
RouterOutlet,
|
|
2574
|
-
EdsAppRailComponent,
|
|
2575
2566
|
EdsModuleNavComponent,
|
|
2576
2567
|
EdsTopbarComponent,
|
|
2577
2568
|
ToastContainerComponent,
|
|
2578
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"eds-layout\">\n
|
|
2569
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"eds-layout\">\n @if (showModuleNav) {\n <eds-module-nav />\n }\n <div class=\"eds-main\">\n <eds-topbar />\n <div class=\"eds-content\">\n <router-outlet />\n </div>\n </div>\n</div>\n<app-toast-container />\n", styles: [":host{display:block}.eds-layout{display:flex;min-height:100vh;background:var(--surface-l1)}.eds-main{flex:1;min-width:0;display:flex;flex-direction:column}.eds-content{flex:1;overflow:auto}\n"] }]
|
|
2579
2570
|
}] });
|
|
2580
2571
|
|
|
2581
2572
|
/** Feature child routes (under the embed shell). */
|
|
@@ -2583,51 +2574,51 @@ const VOICE_RECEPTIONIST_FEATURE_ROUTES = [
|
|
|
2583
2574
|
{ path: '', pathMatch: 'full', redirectTo: 'dashboard' },
|
|
2584
2575
|
{
|
|
2585
2576
|
path: 'dashboard',
|
|
2586
|
-
loadComponent: () => import('./edvak99-voice-receptionist-widget-dashboard-page.component-
|
|
2577
|
+
loadComponent: () => import('./edvak99-voice-receptionist-widget-dashboard-page.component-DzdIt2A7.mjs').then((m) => m.DashboardPageComponent),
|
|
2587
2578
|
},
|
|
2588
2579
|
{
|
|
2589
2580
|
path: 'live',
|
|
2590
|
-
loadComponent: () => import('./edvak99-voice-receptionist-widget-live-calls-page.component-
|
|
2581
|
+
loadComponent: () => import('./edvak99-voice-receptionist-widget-live-calls-page.component-DrYzXJQW.mjs').then((m) => m.LiveCallsPageComponent),
|
|
2591
2582
|
},
|
|
2592
2583
|
{
|
|
2593
2584
|
path: 'live/:id',
|
|
2594
|
-
loadComponent: () => import('./edvak99-voice-receptionist-widget-live-monitor-page.component-
|
|
2585
|
+
loadComponent: () => import('./edvak99-voice-receptionist-widget-live-monitor-page.component-D7dlk0y2.mjs').then((m) => m.LiveMonitorPageComponent),
|
|
2595
2586
|
},
|
|
2596
2587
|
{
|
|
2597
2588
|
path: 'history',
|
|
2598
|
-
loadComponent: () => import('./edvak99-voice-receptionist-widget-call-history-page.component-
|
|
2589
|
+
loadComponent: () => import('./edvak99-voice-receptionist-widget-call-history-page.component-Cj4wxd4e.mjs').then((m) => m.CallHistoryPageComponent),
|
|
2599
2590
|
},
|
|
2600
2591
|
{
|
|
2601
2592
|
path: 'history/:id',
|
|
2602
|
-
loadComponent: () => import('./edvak99-voice-receptionist-widget-call-history-detail-page.component-
|
|
2593
|
+
loadComponent: () => import('./edvak99-voice-receptionist-widget-call-history-detail-page.component-CTwfUHUf.mjs').then((m) => m.CallHistoryDetailPageComponent),
|
|
2603
2594
|
},
|
|
2604
2595
|
{
|
|
2605
2596
|
path: 'tasks',
|
|
2606
|
-
loadComponent: () => import('./edvak99-voice-receptionist-widget-tasks-page.component-
|
|
2597
|
+
loadComponent: () => import('./edvak99-voice-receptionist-widget-tasks-page.component-CBwl15NP.mjs').then((m) => m.TasksPageComponent),
|
|
2607
2598
|
},
|
|
2608
2599
|
{
|
|
2609
2600
|
path: 'analytics',
|
|
2610
|
-
loadComponent: () => import('./edvak99-voice-receptionist-widget-analytics-page.component-
|
|
2601
|
+
loadComponent: () => import('./edvak99-voice-receptionist-widget-analytics-page.component-CW5OKmik.mjs').then((m) => m.AnalyticsPageComponent),
|
|
2611
2602
|
},
|
|
2612
2603
|
{
|
|
2613
2604
|
path: 'settings',
|
|
2614
|
-
loadComponent: () => import('./edvak99-voice-receptionist-widget-settings-page.component-
|
|
2605
|
+
loadComponent: () => import('./edvak99-voice-receptionist-widget-settings-page.component-Bo3XNK3b.mjs').then((m) => m.SettingsPageComponent),
|
|
2615
2606
|
},
|
|
2616
2607
|
{
|
|
2617
2608
|
path: 'settings/outbound-purposes',
|
|
2618
|
-
loadComponent: () => import('./edvak99-voice-receptionist-widget-outbound-purposes-page.component-
|
|
2609
|
+
loadComponent: () => import('./edvak99-voice-receptionist-widget-outbound-purposes-page.component-CJ8NEjcj.mjs').then((m) => m.OutboundPurposesPageComponent),
|
|
2619
2610
|
},
|
|
2620
2611
|
{
|
|
2621
2612
|
path: 'knowledge',
|
|
2622
|
-
loadComponent: () => import('./edvak99-voice-receptionist-widget-knowledge-hub.page-
|
|
2613
|
+
loadComponent: () => import('./edvak99-voice-receptionist-widget-knowledge-hub.page-cZqBuull.mjs').then((m) => m.KnowledgeHubPageComponent),
|
|
2623
2614
|
},
|
|
2624
2615
|
{
|
|
2625
2616
|
path: 'audit',
|
|
2626
|
-
loadComponent: () => import('./edvak99-voice-receptionist-widget-audit-page.component-
|
|
2617
|
+
loadComponent: () => import('./edvak99-voice-receptionist-widget-audit-page.component-DL1GfQyF.mjs').then((m) => m.AuditPageComponent),
|
|
2627
2618
|
},
|
|
2628
2619
|
{
|
|
2629
2620
|
path: 'wizard',
|
|
2630
|
-
loadComponent: () => import('./edvak99-voice-receptionist-widget-wizard-page.component-
|
|
2621
|
+
loadComponent: () => import('./edvak99-voice-receptionist-widget-wizard-page.component-CJLa5pia.mjs').then((m) => m.WizardPageComponent),
|
|
2631
2622
|
},
|
|
2632
2623
|
];
|
|
2633
2624
|
/**
|
|
@@ -2663,4 +2654,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
2663
2654
|
*/
|
|
2664
2655
|
|
|
2665
2656
|
export { AiReceptionistApiService as A, DEFAULT_PLACEHOLDERS as D, EdsButtonComponent as E, ModalComponent as M, ToastService as T, VOICE_RECEPTIONIST_CONFIG as V, WELCOME_MESSAGE_MAX as W, EdsBadgeComponent as a, EdsIconComponent as b, EdsPulseDotComponent as c, resolveToolDisplayName as d, createVoiceReceptionistPaths as e, buildAutoWelcomeTemplate as f, resolveWelcomePreview as g, EdsAppShellComponent as h, VOICE_RECEPTIONIST_FEATURE_ROUTES as i, VOICE_RECEPTIONIST_ROUTES as j, VOICE_RECEPTIONIST_SESSION as k, provideVoiceReceptionist as p, resolveToolKey as r, toolEventTrackKey as t };
|
|
2666
|
-
//# sourceMappingURL=edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-
|
|
2657
|
+
//# sourceMappingURL=edvak99-voice-receptionist-widget-edvak99-voice-receptionist-widget-CMhknpGf.mjs.map
|