@edvak99/voice-receptionist-widget 1.1.8 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-DTSc452x.mjs +388 -0
  2. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-DTSc452x.mjs.map +1 -0
  3. package/fesm2022/{edvak99-voice-receptionist-widget-call-history-detail-page.component-BuNyPmhn.mjs → edvak99-voice-receptionist-widget-call-history-detail-page.component-BkT3Qfsk.mjs} +3 -3
  4. package/fesm2022/{edvak99-voice-receptionist-widget-call-history-detail-page.component-BuNyPmhn.mjs.map → edvak99-voice-receptionist-widget-call-history-detail-page.component-BkT3Qfsk.mjs.map} +1 -1
  5. package/fesm2022/edvak99-voice-receptionist-widget-settings-page.component-9qSZL9mc.mjs +1059 -0
  6. package/fesm2022/edvak99-voice-receptionist-widget-settings-page.component-9qSZL9mc.mjs.map +1 -0
  7. package/fesm2022/edvak99-voice-receptionist-widget-task-detail-drawer.component-B3KmFJNH.mjs +194 -0
  8. package/fesm2022/edvak99-voice-receptionist-widget-task-detail-drawer.component-B3KmFJNH.mjs.map +1 -0
  9. package/fesm2022/{edvak99-voice-receptionist-widget-tasks-page.component-Dfz-_0Jz.mjs → edvak99-voice-receptionist-widget-tasks-page.component-D4bWKglj.mjs} +5 -181
  10. package/fesm2022/edvak99-voice-receptionist-widget-tasks-page.component-D4bWKglj.mjs.map +1 -0
  11. package/fesm2022/edvak99-voice-receptionist-widget.mjs +5 -5
  12. package/lib/components/task-detail-drawer/task-detail-drawer.component.d.ts +1 -0
  13. package/lib/pages/activities-page/activities-page.component.d.ts +6 -0
  14. package/lib/pages/settings-page/settings-page.component.d.ts +11 -2
  15. package/lib/pages/settings-page/tts-voice-presets.d.ts +2 -0
  16. package/package.json +1 -1
  17. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-CtaPoY1k.mjs +0 -344
  18. package/fesm2022/edvak99-voice-receptionist-widget-activities-page.component-CtaPoY1k.mjs.map +0 -1
  19. package/fesm2022/edvak99-voice-receptionist-widget-settings-page.component-CspheAr8.mjs +0 -992
  20. package/fesm2022/edvak99-voice-receptionist-widget-settings-page.component-CspheAr8.mjs.map +0 -1
  21. package/fesm2022/edvak99-voice-receptionist-widget-tasks-page.component-Dfz-_0Jz.mjs.map +0 -1
@@ -1,186 +1,10 @@
1
1
  import { DatePipe } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, signal, Input, ChangeDetectionStrategy, Component, input, output, computed } from '@angular/core';
4
- import { RouterLink, ActivatedRoute } from '@angular/router';
5
- import { ToastService, EdsBadgeComponent, EdsButtonComponent, EdsIconComponent } from './edvak99-voice-receptionist-widget.mjs';
3
+ import { inject, signal, computed, ChangeDetectionStrategy, Component } from '@angular/core';
4
+ import { ActivatedRoute, RouterLink } from '@angular/router';
5
+ import { a as TASK_TYPE_OPTIONS, t as taskStatusLabel, b as taskStatusTone, c as taskPriorityTone, d as taskSourceLabel, e as taskTypeTone, f as taskCallRoute, T as TaskDetailDrawerComponent } from './edvak99-voice-receptionist-widget-task-detail-drawer.component-B3KmFJNH.mjs';
6
6
  import { A as AiReceptionistApiService, D as DEFAULT_PAGE_SIZE, j as totalPages } from './edvak99-voice-receptionist-widget-ai-receptionist-api.service-CK6tM862.mjs';
7
-
8
- class CopyButtonComponent {
9
- constructor() {
10
- /** Raw value to copy (full ID / phone / etc.) */
11
- this.value = '';
12
- /** Accessible label, e.g. "patient ID" */
13
- this.label = 'value';
14
- this.toast = inject(ToastService);
15
- this.copied = signal(false);
16
- }
17
- get copyValue() {
18
- const v = this.value?.trim();
19
- return v && v !== '—' ? v : '';
20
- }
21
- get ariaLabel() {
22
- return this.copied() ? 'Copied' : `Copy ${this.label}`;
23
- }
24
- async onCopy(event) {
25
- event.stopPropagation();
26
- const text = this.copyValue;
27
- if (!text)
28
- return;
29
- try {
30
- await navigator.clipboard.writeText(text);
31
- this.copied.set(true);
32
- setTimeout(() => this.copied.set(false), 1500);
33
- }
34
- catch {
35
- this.toast.show('Could not copy — clipboard unavailable', 'error', 2500);
36
- }
37
- }
38
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CopyButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
39
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: CopyButtonComponent, isStandalone: true, selector: "app-copy-btn", inputs: { value: "value", label: "label" }, ngImport: i0, template: `
40
- @if (copyValue) {
41
- <button
42
- type="button"
43
- class="copy-btn inline-flex shrink-0 items-center justify-center p-0"
44
- (click)="onCopy($event)"
45
- [attr.aria-label]="ariaLabel"
46
- [title]="copied() ? 'Copied' : 'Copy to clipboard'"
47
- >
48
- @if (copied()) {
49
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor"
50
- stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
51
- <polyline points="20 6 9 17 4 12" />
52
- </svg>
53
- } @else {
54
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor"
55
- stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
56
- <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
57
- <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
58
- </svg>
59
- }
60
- </button>
61
- }
62
- `, isInline: true, styles: [".copy-btn{width:22px;height:22px;border:1px solid var(--eds-color-border);border-radius:4px;background:var(--eds-color-surface);color:var(--eds-color-text-muted);cursor:pointer;transition:background .1s ease,color .1s ease,border-color .1s ease}.copy-btn:hover{background:var(--eds-color-surface-alt);color:var(--eds-color-primary);border-color:var(--eds-color-border-strong)}.copy-btn:focus-visible{outline:2px solid var(--eds-color-primary);outline-offset:1px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
63
- }
64
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CopyButtonComponent, decorators: [{
65
- type: Component,
66
- args: [{ selector: 'app-copy-btn', standalone: true, template: `
67
- @if (copyValue) {
68
- <button
69
- type="button"
70
- class="copy-btn inline-flex shrink-0 items-center justify-center p-0"
71
- (click)="onCopy($event)"
72
- [attr.aria-label]="ariaLabel"
73
- [title]="copied() ? 'Copied' : 'Copy to clipboard'"
74
- >
75
- @if (copied()) {
76
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor"
77
- stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
78
- <polyline points="20 6 9 17 4 12" />
79
- </svg>
80
- } @else {
81
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor"
82
- stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
83
- <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
84
- <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
85
- </svg>
86
- }
87
- </button>
88
- }
89
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".copy-btn{width:22px;height:22px;border:1px solid var(--eds-color-border);border-radius:4px;background:var(--eds-color-surface);color:var(--eds-color-text-muted);cursor:pointer;transition:background .1s ease,color .1s ease,border-color .1s ease}.copy-btn:hover{background:var(--eds-color-surface-alt);color:var(--eds-color-primary);border-color:var(--eds-color-border-strong)}.copy-btn:focus-visible{outline:2px solid var(--eds-color-primary);outline-offset:1px}\n"] }]
90
- }], propDecorators: { value: [{
91
- type: Input
92
- }], label: [{
93
- type: Input
94
- }] } });
95
-
96
- const TASK_TYPE_OPTIONS = [
97
- 'Refill request',
98
- 'Callback',
99
- 'Billing',
100
- 'Scheduling',
101
- 'Clinical',
102
- 'Other',
103
- ];
104
- function taskStatusLabel(status) {
105
- if (status === 'in_progress')
106
- return 'In progress';
107
- if (status === 'done')
108
- return 'Done';
109
- return 'Open';
110
- }
111
- function taskStatusTone(status) {
112
- const map = {
113
- open: 'brand',
114
- in_progress: 'notice',
115
- done: 'pos',
116
- };
117
- return map[status];
118
- }
119
- function taskPriorityTone(priority) {
120
- return priority === 'urgent' ? 'neg' : 'gray';
121
- }
122
- function taskPriorityLabel(priority) {
123
- return priority === 'urgent' ? 'Urgent' : 'Normal';
124
- }
125
- function taskSourceLabel(source) {
126
- if (source === 'voice')
127
- return 'Voice';
128
- if (source === 'sync')
129
- return 'Sync';
130
- return 'Manual';
131
- }
132
- function taskTypeTone(type) {
133
- const key = type.toLowerCase();
134
- if (key.includes('refill'))
135
- return 'violet';
136
- if (key.includes('callback'))
137
- return 'brand';
138
- if (key.includes('billing'))
139
- return 'notice';
140
- return 'gray';
141
- }
142
- function taskCallRoute(callId) {
143
- return callId.startsWith('LC') ? ['../live', callId] : ['../history', callId];
144
- }
145
-
146
- class TaskDetailDrawerComponent {
147
- constructor() {
148
- this.task = input.required();
149
- this.closed = output();
150
- this.statusChange = output();
151
- this.taskStatusLabel = taskStatusLabel;
152
- this.taskStatusTone = taskStatusTone;
153
- this.taskPriorityLabel = taskPriorityLabel;
154
- this.taskPriorityTone = taskPriorityTone;
155
- this.taskSourceLabel = taskSourceLabel;
156
- this.taskTypeTone = taskTypeTone;
157
- this.taskCallRoute = taskCallRoute;
158
- }
159
- close() {
160
- this.closed.emit();
161
- }
162
- markDone() {
163
- const t = this.task();
164
- this.statusChange.emit(t.status === 'done' ? 'open' : 'done');
165
- }
166
- onBackdropClick(event) {
167
- if (event.target === event.currentTarget)
168
- this.close();
169
- }
170
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TaskDetailDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
171
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: TaskDetailDrawerComponent, isStandalone: true, selector: "eds-task-detail-drawer", inputs: { task: { classPropertyName: "task", publicName: "task", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { closed: "closed", statusChange: "statusChange" }, ngImport: i0, template: "<div class=\"fixed inset-0 z-[200] flex justify-end bg-[rgba(15,23,42,0.4)]\" (click)=\"onBackdropClick($event)\">\n <aside class=\"task-drawer flex h-full w-[min(440px,100%)] flex-col bg-white shadow-[-8px_0_32px_rgba(15,23,42,0.12)]\" role=\"dialog\" aria-modal=\"true\" [attr.aria-label]=\"task().title\">\n <header class=\"flex items-start justify-between gap-3 border-b border-[var(--eds-color-border,#e2e8f0)] px-6 py-5\">\n <div>\n <eds-badge [tone]=\"taskTypeTone(task().type)\">{{ task().type }}</eds-badge>\n <h2 class=\"mt-2 text-xl font-semibold leading-snug text-[var(--eds-color-text,#0f172a)]\">{{ task().title }}</h2>\n </div>\n <button\n type=\"button\"\n class=\"cursor-pointer rounded-md border-none bg-transparent p-1 text-[var(--eds-color-text-muted,#64748b)] hover:bg-[var(--eds-color-surface-alt,#f1f5f9)]\"\n (click)=\"close()\"\n aria-label=\"Close\"\n >\n <eds-icon name=\"close\" [size]=\"22\" />\n </button>\n </header>\n\n <div class=\"flex flex-1 flex-col gap-6 overflow-y-auto px-6 py-5\">\n <section>\n <h3 class=\"eds-label\">Description</h3>\n <p class=\"mt-2 whitespace-pre-wrap text-[15px] leading-relaxed text-[var(--eds-color-text,#0f172a)]\">{{ task().description || '\u2014' }}</p>\n </section>\n\n <dl class=\"m-0 grid grid-cols-2 gap-4\">\n <div>\n <dt class=\"eds-label mb-1\">Patient</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\">{{ task().patient }}</dd>\n </div>\n <div>\n <dt class=\"eds-label mb-1\">Assignee</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\">{{ task().assignee }}</dd>\n </div>\n <div>\n <dt class=\"eds-label mb-1\">Status</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\"><eds-badge [tone]=\"taskStatusTone(task().status)\">{{ taskStatusLabel(task().status) }}</eds-badge></dd>\n </div>\n <div>\n <dt class=\"eds-label mb-1\">Priority</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\"><eds-badge [tone]=\"taskPriorityTone(task().priority)\">{{ taskPriorityLabel(task().priority) }}</eds-badge></dd>\n </div>\n <div>\n <dt class=\"eds-label mb-1\">Source</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\">{{ taskSourceLabel(task().source) }}</dd>\n </div>\n <div>\n <dt class=\"eds-label mb-1\">Created</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\">{{ task().created | date: 'medium' }}</dd>\n </div>\n <div>\n <dt class=\"eds-label mb-1\">Call</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\">\n @if (task().callId) {\n <a [routerLink]=\"taskCallRoute(task().callId!)\" class=\"font-medium text-[var(--eds-color-primary,#3681f4)] no-underline hover:underline\">{{ task().callId }}</a>\n } @else {\n \u2014\n }\n </dd>\n </div>\n </dl>\n\n @if (task().edvakTaskId || task().edvakStatus || task().medicationName || task().medicationId) {\n <section class=\"rounded-lg border border-[var(--eds-color-border,#e2e8f0)] bg-[var(--eds-color-surface-alt,#f8fafc)] p-4\">\n <h3 class=\"eds-label\">Edvak / refill details</h3>\n <dl class=\"m-0 grid grid-cols-2 gap-4\">\n @if (task().edvakTaskId) {\n <div>\n <dt class=\"eds-label mb-1\">Edvak task ID</dt>\n <dd class=\"inline-flex items-center gap-2 text-sm\">\n <code class=\"rounded bg-[var(--eds-color-surface-alt,#f1f5f9)] px-2 py-1 font-mono text-xs\">{{ task().edvakTaskId }}</code>\n <app-copy-btn [value]=\"task().edvakTaskId\" label=\"Edvak task ID\" />\n </dd>\n </div>\n }\n @if (task().edvakStatus) {\n <div>\n <dt class=\"eds-label mb-1\">Edvak status</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\"><eds-badge tone=\"brand\">{{ task().edvakStatus }}</eds-badge></dd>\n </div>\n }\n @if (task().medicationName) {\n <div>\n <dt class=\"eds-label mb-1\">Medication</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\">{{ task().medicationName }}</dd>\n </div>\n }\n @if (task().medicationId) {\n <div>\n <dt class=\"eds-label mb-1\">Medication ID</dt>\n <dd class=\"inline-flex items-center gap-2 text-sm\">\n <code class=\"rounded bg-[var(--eds-color-surface-alt,#f1f5f9)] px-2 py-1 font-mono text-xs\">{{ task().medicationId }}</code>\n <app-copy-btn [value]=\"task().medicationId\" label=\"medication ID\" />\n </dd>\n </div>\n }\n </dl>\n </section>\n }\n </div>\n\n <footer class=\"border-t border-[var(--eds-color-border,#e2e8f0)] px-6 py-4\">\n <eds-button variant=\"secondary\" type=\"button\" (click)=\"markDone()\">\n {{ task().status === 'done' ? 'Reopen task' : 'Mark done' }}\n </eds-button>\n </footer>\n </aside>\n</div>\n", styles: [".task-drawer{animation:task-drawer-in .2s ease}@keyframes task-drawer-in{0%{transform:translate(100%)}to{transform:translate(0)}}\n"], dependencies: [{ kind: "pipe", type: DatePipe, name: "date" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: CopyButtonComponent, selector: "app-copy-btn", inputs: ["value", "label"] }, { kind: "component", type: EdsBadgeComponent, selector: "eds-badge", inputs: ["tone"] }, { kind: "component", type: EdsButtonComponent, selector: "eds-button", inputs: ["variant", "type", "disabled"] }, { kind: "component", type: EdsIconComponent, selector: "eds-icon", inputs: ["name", "size", "fill", "weight"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
172
- }
173
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TaskDetailDrawerComponent, decorators: [{
174
- type: Component,
175
- args: [{ selector: 'eds-task-detail-drawer', imports: [
176
- DatePipe,
177
- RouterLink,
178
- CopyButtonComponent,
179
- EdsBadgeComponent,
180
- EdsButtonComponent,
181
- EdsIconComponent,
182
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fixed inset-0 z-[200] flex justify-end bg-[rgba(15,23,42,0.4)]\" (click)=\"onBackdropClick($event)\">\n <aside class=\"task-drawer flex h-full w-[min(440px,100%)] flex-col bg-white shadow-[-8px_0_32px_rgba(15,23,42,0.12)]\" role=\"dialog\" aria-modal=\"true\" [attr.aria-label]=\"task().title\">\n <header class=\"flex items-start justify-between gap-3 border-b border-[var(--eds-color-border,#e2e8f0)] px-6 py-5\">\n <div>\n <eds-badge [tone]=\"taskTypeTone(task().type)\">{{ task().type }}</eds-badge>\n <h2 class=\"mt-2 text-xl font-semibold leading-snug text-[var(--eds-color-text,#0f172a)]\">{{ task().title }}</h2>\n </div>\n <button\n type=\"button\"\n class=\"cursor-pointer rounded-md border-none bg-transparent p-1 text-[var(--eds-color-text-muted,#64748b)] hover:bg-[var(--eds-color-surface-alt,#f1f5f9)]\"\n (click)=\"close()\"\n aria-label=\"Close\"\n >\n <eds-icon name=\"close\" [size]=\"22\" />\n </button>\n </header>\n\n <div class=\"flex flex-1 flex-col gap-6 overflow-y-auto px-6 py-5\">\n <section>\n <h3 class=\"eds-label\">Description</h3>\n <p class=\"mt-2 whitespace-pre-wrap text-[15px] leading-relaxed text-[var(--eds-color-text,#0f172a)]\">{{ task().description || '\u2014' }}</p>\n </section>\n\n <dl class=\"m-0 grid grid-cols-2 gap-4\">\n <div>\n <dt class=\"eds-label mb-1\">Patient</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\">{{ task().patient }}</dd>\n </div>\n <div>\n <dt class=\"eds-label mb-1\">Assignee</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\">{{ task().assignee }}</dd>\n </div>\n <div>\n <dt class=\"eds-label mb-1\">Status</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\"><eds-badge [tone]=\"taskStatusTone(task().status)\">{{ taskStatusLabel(task().status) }}</eds-badge></dd>\n </div>\n <div>\n <dt class=\"eds-label mb-1\">Priority</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\"><eds-badge [tone]=\"taskPriorityTone(task().priority)\">{{ taskPriorityLabel(task().priority) }}</eds-badge></dd>\n </div>\n <div>\n <dt class=\"eds-label mb-1\">Source</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\">{{ taskSourceLabel(task().source) }}</dd>\n </div>\n <div>\n <dt class=\"eds-label mb-1\">Created</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\">{{ task().created | date: 'medium' }}</dd>\n </div>\n <div>\n <dt class=\"eds-label mb-1\">Call</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\">\n @if (task().callId) {\n <a [routerLink]=\"taskCallRoute(task().callId!)\" class=\"font-medium text-[var(--eds-color-primary,#3681f4)] no-underline hover:underline\">{{ task().callId }}</a>\n } @else {\n \u2014\n }\n </dd>\n </div>\n </dl>\n\n @if (task().edvakTaskId || task().edvakStatus || task().medicationName || task().medicationId) {\n <section class=\"rounded-lg border border-[var(--eds-color-border,#e2e8f0)] bg-[var(--eds-color-surface-alt,#f8fafc)] p-4\">\n <h3 class=\"eds-label\">Edvak / refill details</h3>\n <dl class=\"m-0 grid grid-cols-2 gap-4\">\n @if (task().edvakTaskId) {\n <div>\n <dt class=\"eds-label mb-1\">Edvak task ID</dt>\n <dd class=\"inline-flex items-center gap-2 text-sm\">\n <code class=\"rounded bg-[var(--eds-color-surface-alt,#f1f5f9)] px-2 py-1 font-mono text-xs\">{{ task().edvakTaskId }}</code>\n <app-copy-btn [value]=\"task().edvakTaskId\" label=\"Edvak task ID\" />\n </dd>\n </div>\n }\n @if (task().edvakStatus) {\n <div>\n <dt class=\"eds-label mb-1\">Edvak status</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\"><eds-badge tone=\"brand\">{{ task().edvakStatus }}</eds-badge></dd>\n </div>\n }\n @if (task().medicationName) {\n <div>\n <dt class=\"eds-label mb-1\">Medication</dt>\n <dd class=\"m-0 text-sm text-[var(--eds-color-text,#0f172a)]\">{{ task().medicationName }}</dd>\n </div>\n }\n @if (task().medicationId) {\n <div>\n <dt class=\"eds-label mb-1\">Medication ID</dt>\n <dd class=\"inline-flex items-center gap-2 text-sm\">\n <code class=\"rounded bg-[var(--eds-color-surface-alt,#f1f5f9)] px-2 py-1 font-mono text-xs\">{{ task().medicationId }}</code>\n <app-copy-btn [value]=\"task().medicationId\" label=\"medication ID\" />\n </dd>\n </div>\n }\n </dl>\n </section>\n }\n </div>\n\n <footer class=\"border-t border-[var(--eds-color-border,#e2e8f0)] px-6 py-4\">\n <eds-button variant=\"secondary\" type=\"button\" (click)=\"markDone()\">\n {{ task().status === 'done' ? 'Reopen task' : 'Mark done' }}\n </eds-button>\n </footer>\n </aside>\n</div>\n", styles: [".task-drawer{animation:task-drawer-in .2s ease}@keyframes task-drawer-in{0%{transform:translate(100%)}to{transform:translate(0)}}\n"] }]
183
- }] });
7
+ import { EdsBadgeComponent, EdsButtonComponent } from './edvak99-voice-receptionist-widget.mjs';
184
8
 
185
9
  class TasksPageComponent {
186
10
  constructor() {
@@ -313,4 +137,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
313
137
  }] });
314
138
 
315
139
  export { TasksPageComponent };
316
- //# sourceMappingURL=edvak99-voice-receptionist-widget-tasks-page.component-Dfz-_0Jz.mjs.map
140
+ //# sourceMappingURL=edvak99-voice-receptionist-widget-tasks-page.component-D4bWKglj.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edvak99-voice-receptionist-widget-tasks-page.component-D4bWKglj.mjs","sources":["../../../projects/voice-receptionist-widget/src/lib/pages/tasks-page/tasks-page.component.ts","../../../projects/voice-receptionist-widget/src/lib/pages/tasks-page/tasks-page.component.html"],"sourcesContent":["import { DatePipe } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n inject,\n OnInit,\n signal,\n} from '@angular/core';\nimport { ActivatedRoute, RouterLink } from '@angular/router';\n\nimport { TaskDetailDrawerComponent } from '../../components/task-detail-drawer/task-detail-drawer.component';\nimport {\n TaskFilters,\n TaskItem,\n TaskSource,\n TaskStatus,\n} from '../../models/ai-receptionist.types';\nimport { DEFAULT_PAGE_SIZE, totalPages as calcTotalPages } from '../../models/pagination';\nimport { AiReceptionistApiService } from '../../services/ai-receptionist-api.service';\nimport { EdsBadgeComponent } from '../../ui/eds-badge.component';\nimport { EdsButtonComponent } from '../../ui/eds-button.component';\nimport {\n TASK_TYPE_OPTIONS,\n taskCallRoute,\n taskPriorityTone,\n taskSourceLabel,\n taskStatusLabel,\n taskStatusTone,\n taskTypeTone,\n} from '../../utils/task.util';\n\n@Component({\n selector: 'eds-tasks-page',\n imports: [\n DatePipe,\n RouterLink,\n EdsBadgeComponent,\n EdsButtonComponent,\n TaskDetailDrawerComponent,\n ],\n templateUrl: './tasks-page.component.html',\n styleUrl: './tasks-page.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TasksPageComponent implements OnInit {\n private readonly api = inject(AiReceptionistApiService);\n private readonly route = inject(ActivatedRoute);\n\n protected readonly pageSize = DEFAULT_PAGE_SIZE;\n protected readonly tasks = signal<TaskItem[]>([]);\n protected readonly total = signal(0);\n protected readonly page = signal(1);\n protected readonly loading = signal(true);\n protected readonly selectedTask = signal<TaskItem | null>(null);\n\n protected readonly statusFilter = signal<'' | TaskStatus>('');\n protected readonly typeFilter = signal('');\n protected readonly sourceFilter = signal<'' | TaskSource>('');\n protected readonly callIdFilter = signal('');\n\n protected readonly typeOptions = TASK_TYPE_OPTIONS;\n protected readonly taskStatusLabel = taskStatusLabel;\n protected readonly taskStatusTone = taskStatusTone;\n protected readonly taskPriorityTone = taskPriorityTone;\n protected readonly taskSourceLabel = taskSourceLabel;\n protected readonly taskTypeTone = taskTypeTone;\n protected readonly taskCallRoute = taskCallRoute;\n\n protected readonly hasActiveFilters = computed(\n () =>\n !!this.statusFilter() ||\n !!this.typeFilter() ||\n !!this.sourceFilter() ||\n !!this.callIdFilter(),\n );\n\n ngOnInit(): void {\n const callId = this.route.snapshot.queryParamMap.get('callId') ?? '';\n if (callId) this.callIdFilter.set(callId);\n this.load();\n }\n\n protected setStatusFilter(value: string): void {\n this.statusFilter.set(value as '' | TaskStatus);\n this.page.set(1);\n this.load();\n }\n\n protected setTypeFilter(value: string): void {\n this.typeFilter.set(value);\n this.page.set(1);\n this.load();\n }\n\n protected setSourceFilter(value: string): void {\n this.sourceFilter.set(value as '' | TaskSource);\n this.page.set(1);\n this.load();\n }\n\n protected setCallIdFilter(value: string): void {\n this.callIdFilter.set(value);\n this.page.set(1);\n this.load();\n }\n\n protected clearFilters(): void {\n this.statusFilter.set('');\n this.typeFilter.set('');\n this.sourceFilter.set('');\n this.callIdFilter.set('');\n this.page.set(1);\n this.load();\n }\n\n protected openTask(task: TaskItem): void {\n this.selectedTask.set(task);\n }\n\n protected closeDrawer(): void {\n this.selectedTask.set(null);\n }\n\n protected onStatusChange(status: TaskStatus): void {\n const task = this.selectedTask();\n if (!task) return;\n this.api.patchTask(task.id, status).subscribe(({ data }) => {\n if (data) {\n this.selectedTask.set(data);\n this.tasks.update((rows) => rows.map((r) => (r.id === data.id ? data : r)));\n }\n });\n }\n\n protected totalPages(): number {\n return calcTotalPages(this.total(), DEFAULT_PAGE_SIZE);\n }\n\n protected prevPage(): void {\n if (this.page() <= 1) return;\n this.page.update((p) => p - 1);\n this.load();\n }\n\n protected nextPage(): void {\n if (this.page() >= this.totalPages()) return;\n this.page.update((p) => p + 1);\n this.load();\n }\n\n private load(): void {\n this.loading.set(true);\n const filters: TaskFilters = {\n page: this.page(),\n limit: DEFAULT_PAGE_SIZE,\n };\n if (this.statusFilter()) filters.status = this.statusFilter() as TaskStatus;\n if (this.typeFilter()) filters.type = this.typeFilter();\n if (this.sourceFilter()) filters.source = this.sourceFilter() as TaskSource;\n if (this.callIdFilter().trim()) filters.callId = this.callIdFilter().trim();\n\n this.api.getTasks(filters).subscribe({\n next: ({ items, total, page }) => {\n this.tasks.set(items);\n this.total.set(total);\n this.page.set(page);\n this.loading.set(false);\n },\n error: () => this.loading.set(false),\n });\n }\n}\n","<div class=\"eds-page tasks-page\">\n <header class=\"mb-5 flex items-start justify-between gap-4\">\n <div>\n <h1 class=\"eds-h1\">Tasks & follow-ups</h1>\n <p class=\"eds-body-sm\">Action items from calls — all types, not just refills</p>\n </div>\n </header>\n\n <section class=\"eds-card overflow-hidden shadow-sm\">\n <div class=\"flex flex-wrap items-end gap-4 border-b border-zinc-200 px-6 py-4 max-[920px]:px-4 max-[920px]:py-4\">\n <div class=\"flex flex-col gap-1\">\n <label class=\"text-xs font-medium text-zinc-500\" for=\"task-status\">Status</label>\n <select\n id=\"task-status\"\n class=\"min-w-36 rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm\"\n [value]=\"statusFilter()\"\n (change)=\"setStatusFilter($any($event.target).value)\" autocomplete=\"off\">\n <option value=\"\">All</option>\n <option value=\"open\">Open</option>\n <option value=\"in_progress\">In progress</option>\n <option value=\"done\">Done</option>\n </select>\n </div>\n <div class=\"flex flex-col gap-1\">\n <label class=\"text-xs font-medium text-zinc-500\" for=\"task-type\">Type</label>\n <select\n id=\"task-type\"\n class=\"min-w-36 rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm\"\n [value]=\"typeFilter()\"\n (change)=\"setTypeFilter($any($event.target).value)\" autocomplete=\"off\">\n <option value=\"\">All types</option>\n @for (t of typeOptions; track t) {\n <option [value]=\"t\">{{ t }}</option>\n }\n </select>\n </div>\n <div class=\"flex flex-col gap-1\">\n <label class=\"text-xs font-medium text-zinc-500\" for=\"task-source\">Source</label>\n <select\n id=\"task-source\"\n class=\"min-w-36 rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm\"\n [value]=\"sourceFilter()\"\n (change)=\"setSourceFilter($any($event.target).value)\" autocomplete=\"off\">\n <option value=\"\">All sources</option>\n <option value=\"voice\">Voice</option>\n <option value=\"sync\">Sync</option>\n <option value=\"manual\">Manual</option>\n </select>\n </div>\n <div class=\"flex flex-col gap-1\">\n <label class=\"text-xs font-medium text-zinc-500\" for=\"task-call\">Call ID</label>\n <input\n id=\"task-call\"\n type=\"text\"\n class=\"min-w-36 rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm\"\n [value]=\"callIdFilter()\"\n placeholder=\"Filter by call\"\n (change)=\"setCallIdFilter($any($event.target).value)\" autocomplete=\"off\" />\n </div>\n @if (hasActiveFilters()) {\n <button\n type=\"button\"\n class=\"cursor-pointer border-none bg-transparent p-0 text-sm font-medium text-blue-600 hover:underline\"\n (click)=\"clearFilters()\"\n >\n Clear filters\n </button>\n }\n </div>\n\n @if (loading()) {\n <p class=\"eds-body-sm m-0 p-6\">Loading tasks…</p>\n } @else {\n <div class=\"overflow-x-auto\">\n <table class=\"w-full min-w-3xl border-collapse\">\n <thead>\n <tr>\n <th class=\"whitespace-nowrap border-b border-zinc-200 bg-zinc-100 px-5 py-3 text-left text-sm font-semibold text-zinc-600\">Created</th>\n <th class=\"whitespace-nowrap border-b border-zinc-200 bg-zinc-100 px-5 py-3 text-left text-sm font-semibold text-zinc-600\">Title</th>\n <th class=\"whitespace-nowrap border-b border-zinc-200 bg-zinc-100 px-5 py-3 text-left text-sm font-semibold text-zinc-600\">Type</th>\n <th class=\"whitespace-nowrap border-b border-zinc-200 bg-zinc-100 px-5 py-3 text-left text-sm font-semibold text-zinc-600\">Patient</th>\n <th class=\"whitespace-nowrap border-b border-zinc-200 bg-zinc-100 px-5 py-3 text-left text-sm font-semibold text-zinc-600\">Priority</th>\n <th class=\"whitespace-nowrap border-b border-zinc-200 bg-zinc-100 px-5 py-3 text-left text-sm font-semibold text-zinc-600\">Status</th>\n <th class=\"whitespace-nowrap border-b border-zinc-200 bg-zinc-100 px-5 py-3 text-left text-sm font-semibold text-zinc-600\">Source</th>\n <th class=\"whitespace-nowrap border-b border-zinc-200 bg-zinc-100 px-5 py-3 text-left text-sm font-semibold text-zinc-600\">Call</th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-zinc-200\">\n @for (task of tasks(); track task.id) {\n <tr class=\"cursor-pointer transition-colors hover:bg-zinc-50\" (click)=\"openTask(task)\">\n <td class=\"px-5 py-4 align-middle text-sm text-zinc-500\">{{ task.created | date: 'MM/dd/yy, h:mm a' }}</td>\n <td class=\"max-w-72 px-5 py-4 align-middle text-sm font-medium text-zinc-900\">{{ task.title }}</td>\n <td class=\"px-5 py-4 align-middle text-sm text-zinc-900\"><eds-badge [tone]=\"taskTypeTone(task.type)\">{{ task.type }}</eds-badge></td>\n <td class=\"px-5 py-4 align-middle text-sm text-zinc-900\">{{ task.patient }}</td>\n <td class=\"px-5 py-4 align-middle text-sm text-zinc-900\">\n <eds-badge [tone]=\"taskPriorityTone(task.priority)\">\n {{ task.priority === 'urgent' ? 'Urgent' : 'Normal' }}\n </eds-badge>\n </td>\n <td class=\"px-5 py-4 align-middle text-sm text-zinc-900\"><eds-badge [tone]=\"taskStatusTone(task.status)\">{{ taskStatusLabel(task.status) }}</eds-badge></td>\n <td class=\"px-5 py-4 align-middle text-sm text-zinc-500\">{{ taskSourceLabel(task.source) }}</td>\n <td class=\"px-5 py-4 align-middle text-sm text-zinc-900\" (click)=\"$event.stopPropagation()\">\n @if (task.callId) {\n <a\n [routerLink]=\"taskCallRoute(task.callId)\"\n class=\"text-sm font-medium text-blue-600 no-underline hover:underline\"\n >{{ task.callId }}</a>\n } @else {\n <span class=\"text-zinc-500\">—</span>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td colspan=\"8\" class=\"px-5 py-12 text-center text-sm text-zinc-400\">No tasks match these filters.</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n <footer class=\"flex items-center justify-between border-t border-zinc-200 px-6 py-4 text-sm text-zinc-500\">\n <span>Page {{ page() }} of {{ totalPages() }} · {{ total() }} total</span>\n <div class=\"flex gap-2\">\n <eds-button variant=\"secondary\" [disabled]=\"page() <= 1\" (click)=\"prevPage()\">Previous</eds-button>\n <eds-button variant=\"secondary\" [disabled]=\"page() >= totalPages()\" (click)=\"nextPage()\">Next</eds-button>\n </div>\n </footer>\n </section>\n</div>\n\n@if (selectedTask(); as task) {\n <eds-task-detail-drawer\n [task]=\"task\"\n (closed)=\"closeDrawer()\"\n (statusChange)=\"onStatusChange($event)\"\n />\n}\n"],"names":["calcTotalPages"],"mappings":"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"}
@@ -135,15 +135,15 @@ const VOICE_RECEPTIONIST_FEATURE_ROUTES = [
135
135
  },
136
136
  {
137
137
  path: 'history/:id',
138
- loadComponent: () => import('./edvak99-voice-receptionist-widget-call-history-detail-page.component-BuNyPmhn.mjs').then((m) => m.CallHistoryDetailPageComponent),
138
+ loadComponent: () => import('./edvak99-voice-receptionist-widget-call-history-detail-page.component-BkT3Qfsk.mjs').then((m) => m.CallHistoryDetailPageComponent),
139
139
  },
140
140
  {
141
141
  path: 'activities',
142
- loadComponent: () => import('./edvak99-voice-receptionist-widget-activities-page.component-CtaPoY1k.mjs').then((m) => m.ActivitiesPageComponent),
142
+ loadComponent: () => import('./edvak99-voice-receptionist-widget-activities-page.component-DTSc452x.mjs').then((m) => m.ActivitiesPageComponent),
143
143
  },
144
144
  {
145
145
  path: 'tasks',
146
- loadComponent: () => import('./edvak99-voice-receptionist-widget-tasks-page.component-Dfz-_0Jz.mjs').then((m) => m.TasksPageComponent),
146
+ loadComponent: () => import('./edvak99-voice-receptionist-widget-tasks-page.component-D4bWKglj.mjs').then((m) => m.TasksPageComponent),
147
147
  },
148
148
  {
149
149
  path: 'analytics',
@@ -151,7 +151,7 @@ const VOICE_RECEPTIONIST_FEATURE_ROUTES = [
151
151
  },
152
152
  {
153
153
  path: 'settings',
154
- loadComponent: () => import('./edvak99-voice-receptionist-widget-settings-page.component-CspheAr8.mjs').then((m) => m.SettingsPageComponent),
154
+ loadComponent: () => import('./edvak99-voice-receptionist-widget-settings-page.component-9qSZL9mc.mjs').then((m) => m.SettingsPageComponent),
155
155
  },
156
156
  {
157
157
  path: 'settings/outbound-purposes',
@@ -159,7 +159,7 @@ const VOICE_RECEPTIONIST_FEATURE_ROUTES = [
159
159
  },
160
160
  {
161
161
  path: 'knowledge',
162
- loadComponent: () => import('./edvak99-voice-receptionist-widget-settings-page.component-CspheAr8.mjs').then((m) => m.SettingsPageComponent),
162
+ loadComponent: () => import('./edvak99-voice-receptionist-widget-settings-page.component-9qSZL9mc.mjs').then((m) => m.SettingsPageComponent),
163
163
  data: { settingsTab: 'knowledge' },
164
164
  },
165
165
  {
@@ -12,6 +12,7 @@ export declare class TaskDetailDrawerComponent {
12
12
  protected readonly taskSourceLabel: typeof taskSourceLabel;
13
13
  protected readonly taskTypeTone: typeof taskTypeTone;
14
14
  protected readonly taskCallRoute: typeof taskCallRoute;
15
+ protected assigneeInitials(): string;
15
16
  protected close(): void;
16
17
  protected markDone(): void;
17
18
  protected onBackdropClick(event: MouseEvent): void;
@@ -1,5 +1,6 @@
1
1
  import { OnInit } from '@angular/core';
2
2
  import { ActivitiesTab, AgentActivity } from '../../models/agent-activity.types';
3
+ import { TaskItem, TaskStatus } from '../../models/ai-receptionist.types';
3
4
  import * as i0 from "@angular/core";
4
5
  type TabId = ActivitiesTab;
5
6
  export declare class ActivitiesPageComponent implements OnInit {
@@ -18,6 +19,7 @@ export declare class ActivitiesPageComponent implements OnInit {
18
19
  protected readonly callIdFilter: import("@angular/core").WritableSignal<string | null>;
19
20
  protected readonly loading: import("@angular/core").WritableSignal<boolean>;
20
21
  protected readonly loadError: import("@angular/core").WritableSignal<string | null>;
22
+ protected readonly selectedTask: import("@angular/core").WritableSignal<TaskItem | null>;
21
23
  ngOnInit(): void;
22
24
  protected setTab(tab: TabId): void;
23
25
  private tabFromQuery;
@@ -29,6 +31,10 @@ export declare class ActivitiesPageComponent implements OnInit {
29
31
  protected nextPage(): void;
30
32
  protected historyLink(callId: string | null | undefined): string[] | null;
31
33
  protected openCallHistory(callId: string | null | undefined, ev?: Event): void;
34
+ protected openTask(item: AgentActivity): void;
35
+ protected closeTaskDrawer(): void;
36
+ protected onTaskStatusChange(status: TaskStatus): void;
37
+ private activityToTask;
32
38
  protected displayMrn(item: AgentActivity): string;
33
39
  protected providerSpecialtyLabel(item: AgentActivity): string | null;
34
40
  /** Day-anchored stamp — a bare clock time gave no idea which day a row belonged to. */
@@ -1,14 +1,16 @@
1
- import { OnInit } from '@angular/core';
1
+ import { OnDestroy, OnInit } from '@angular/core';
2
2
  import { AgentSettings, LocationOption } from '../../models/ai-receptionist.types';
3
3
  import { isFieldReadOnly, SettingsFieldMeta } from './settings-fields.config';
4
4
  import * as i0 from "@angular/core";
5
5
  type SettingsTab = keyof AgentSettings;
6
- export declare class SettingsPageComponent implements OnInit {
6
+ export declare class SettingsPageComponent implements OnInit, OnDestroy {
7
7
  private readonly api;
8
8
  private readonly toast;
9
9
  private readonly route;
10
10
  private readonly agentOnline;
11
11
  private originalSettings;
12
+ private voiceAudio;
13
+ private voiceObjectUrl;
12
14
  protected readonly isFieldReadOnly: typeof isFieldReadOnly;
13
15
  protected readonly knowledgeMax = 8000;
14
16
  protected readonly disclosureMax = 1000;
@@ -35,6 +37,8 @@ export declare class SettingsPageComponent implements OnInit {
35
37
  protected readonly locations: import("@angular/core").WritableSignal<LocationOption[]>;
36
38
  protected readonly locationsMenuOpen: import("@angular/core").WritableSignal<boolean>;
37
39
  protected readonly confirmOffOpen: import("@angular/core").WritableSignal<boolean>;
40
+ protected readonly voicePreviewBusy: import("@angular/core").WritableSignal<boolean>;
41
+ protected readonly voicePreviewPlaying: import("@angular/core").WritableSignal<boolean>;
38
42
  protected readonly online: import("@angular/core").Signal<import("../../services/agent-online.service").AgentOnlineKnownState>;
39
43
  protected readonly agentLoading: import("@angular/core").Signal<boolean>;
40
44
  protected readonly toggling: import("@angular/core").Signal<boolean>;
@@ -56,6 +60,7 @@ export declare class SettingsPageComponent implements OnInit {
56
60
  protected readonly disclosureText: import("@angular/core").Signal<string>;
57
61
  protected readonly agentSwitchDisabled: import("@angular/core").Signal<boolean>;
58
62
  ngOnInit(): void;
63
+ ngOnDestroy(): void;
59
64
  protected fieldIsReadOnly(section: SettingsTab, key: string): boolean;
60
65
  protected sectionIsReadOnly(section: SettingsTab): boolean;
61
66
  protected isTabDisabled(id: SettingsTab): boolean;
@@ -75,6 +80,10 @@ export declare class SettingsPageComponent implements OnInit {
75
80
  protected openTestCall(): void;
76
81
  protected closeTestCall(): void;
77
82
  protected selectedVoiceId(): string;
83
+ protected onVoiceChange(voiceId: string): void;
84
+ protected toggleVoicePreview(): void;
85
+ private playVoiceBlob;
86
+ private stopVoicePreview;
78
87
  protected onAgentToggleClick(): void;
79
88
  protected cancelConfirmOff(): void;
80
89
  protected confirmTurnOff(): void;
@@ -2,6 +2,8 @@
2
2
  export interface TtsVoicePreset {
3
3
  id: string;
4
4
  label: string;
5
+ /** Display gender hint next to the voice name. */
6
+ gender: 'M' | 'F';
5
7
  }
6
8
  export declare const DEFAULT_TTS_VOICE_ID = "7EzWGsX10sAS4c9m9cPf";
7
9
  export declare const TTS_VOICE_PRESETS: readonly TtsVoicePreset[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edvak99/voice-receptionist-widget",
3
- "version": "1.1.8",
3
+ "version": "1.1.9",
4
4
  "description": "Edvak AI Receptionist — embeddable Angular routes and UI for EHR hosts",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^19.2.0",