@mindbill/angular 0.8.0 → 0.10.0
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 +40 -0
- package/fesm2022/mindbill-angular.mjs +479 -26
- package/fesm2022/mindbill-angular.mjs.map +1 -1
- package/package.json +2 -2
- package/types/mindbill-angular.d.ts +82 -9
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, computed,
|
|
3
|
-
import { createBillLifecycleClient, createBillReferenceClient, createBillSubmissionClient } from '@mindbill/browser';
|
|
2
|
+
import { signal, computed, Input, Component, EventEmitter, effect, Output, Directive, inject, ChangeDetectorRef, HostListener } from '@angular/core';
|
|
3
|
+
import { createBillLifecycleClient, createBillReferenceClient, createBillSubmissionClient, createOrganizationClient } from '@mindbill/browser';
|
|
4
4
|
import * as i1 from '@angular/common';
|
|
5
5
|
import { CommonModule } from '@angular/common';
|
|
6
6
|
import * as i2 from '@angular/forms';
|
|
@@ -80,11 +80,114 @@ class MindBillLifecycleStore {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
const THEMES = {
|
|
83
|
-
mindbill: { preset: "mindbill", accentColor: "#238dbd", accentTextColor: "#fff", backgroundColor: "#f3f8fa", surfaceColor: "#fff", textColor: "#203743", mutedColor: "#657982", borderColor: "#dbe6ea", borderRadius: "14px", controlRadius: "8px", fontFamily: "Inter,system-ui,sans-serif" },
|
|
84
|
-
"qme-companion": { preset: "qme-companion", accentColor: "#53b5dc", accentTextColor: "#173542", backgroundColor: "#f2f8fb", surfaceColor: "#fff", textColor: "#1d3440", mutedColor: "#617783", borderColor: "#d7e5eb", borderRadius: "12px", controlRadius: "8px", fontFamily: "Inter,system-ui,sans-serif" },
|
|
85
|
-
"orange-bright": { preset: "orange-bright", accentColor: "#f4510b", accentTextColor: "#fff", backgroundColor: "#fffaf6", surfaceColor: "#fffefd", textColor: "#090f1f", mutedColor: "#626a73", borderColor: "#e7e1da", borderRadius: "16px", controlRadius: "10px", fontFamily: "Inter,system-ui,sans-serif" },
|
|
86
|
-
"clinical-blue": { preset: "clinical-blue", accentColor: "#1677ff", accentTextColor: "#fff", backgroundColor: "#f5f7fa", surfaceColor: "#fff", textColor: "#1f2d3d", mutedColor: "#66788a", borderColor: "#d9e2ec", borderRadius: "8px", controlRadius: "6px", fontFamily: "Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif" },
|
|
83
|
+
mindbill: { preset: "mindbill", accentColor: "#238dbd", accentTextColor: "#fff", backgroundColor: "#f3f8fa", surfaceColor: "#fff", textColor: "#203743", mutedColor: "#657982", borderColor: "#dbe6ea", borderRadius: "14px", controlRadius: "8px", fontFamily: "Inter,system-ui,sans-serif", dangerColor: "#b63d35" },
|
|
84
|
+
"qme-companion": { preset: "qme-companion", accentColor: "#53b5dc", accentTextColor: "#173542", backgroundColor: "#f2f8fb", surfaceColor: "#fff", textColor: "#1d3440", mutedColor: "#617783", borderColor: "#d7e5eb", borderRadius: "12px", controlRadius: "8px", fontFamily: "Inter,system-ui,sans-serif", dangerColor: "#b83f3a" },
|
|
85
|
+
"orange-bright": { preset: "orange-bright", accentColor: "#f4510b", accentTextColor: "#fff", backgroundColor: "#fffaf6", surfaceColor: "#fffefd", textColor: "#090f1f", mutedColor: "#626a73", borderColor: "#e7e1da", borderRadius: "16px", controlRadius: "10px", fontFamily: "Inter,system-ui,sans-serif", dangerColor: "#c4322b" },
|
|
86
|
+
"clinical-blue": { preset: "clinical-blue", accentColor: "#1677ff", accentTextColor: "#fff", backgroundColor: "#f5f7fa", surfaceColor: "#fff", textColor: "#1f2d3d", mutedColor: "#66788a", borderColor: "#d9e2ec", borderRadius: "8px", controlRadius: "6px", fontFamily: "Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif", dangerColor: "#d4380d" },
|
|
87
87
|
};
|
|
88
|
+
function mindBillAngularAppearanceStyle(appearance = { preset: "mindbill" }) {
|
|
89
|
+
const base = THEMES[appearance.preset ?? "mindbill"];
|
|
90
|
+
return {
|
|
91
|
+
"--a": appearance.accentColor ?? base.accentColor,
|
|
92
|
+
"--ac": appearance.accentTextColor ?? base.accentTextColor,
|
|
93
|
+
"--bg": appearance.backgroundColor ?? base.backgroundColor,
|
|
94
|
+
"--s": appearance.surfaceColor ?? base.surfaceColor,
|
|
95
|
+
"--t": appearance.textColor ?? base.textColor,
|
|
96
|
+
"--m": appearance.mutedColor ?? base.mutedColor,
|
|
97
|
+
"--b": appearance.borderColor ?? base.borderColor,
|
|
98
|
+
"--r": appearance.borderRadius ?? base.borderRadius,
|
|
99
|
+
"--cr": appearance.controlRadius ?? base.controlRadius,
|
|
100
|
+
"--font": appearance.fontFamily ?? base.fontFamily,
|
|
101
|
+
"--danger": appearance.dangerColor ?? base.dangerColor,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function billRejectionIssues(rejection) {
|
|
106
|
+
return rejection.issues?.length
|
|
107
|
+
? [...rejection.issues]
|
|
108
|
+
: [{ code: rejection.code ?? null, description: rejection.reason }];
|
|
109
|
+
}
|
|
110
|
+
function billRejectionIssueSummary(rejection, count) {
|
|
111
|
+
const noun = count === 1 ? "validation error" : "validation errors";
|
|
112
|
+
const source = rejection.source?.trim().replace(/\.$/, "");
|
|
113
|
+
if (!source)
|
|
114
|
+
return `${count} ${noun}.`;
|
|
115
|
+
if (/acknowledg/i.test(source))
|
|
116
|
+
return `${count} clearinghouse ${noun}.`;
|
|
117
|
+
return `${count} ${noun} returned by ${source}.`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
class MindBillBillRejectionNoticeComponent {
|
|
121
|
+
rejection;
|
|
122
|
+
submittedAt = null;
|
|
123
|
+
title = "Rejected — action required";
|
|
124
|
+
appearance = { preset: "mindbill" };
|
|
125
|
+
get issues() { return billRejectionIssues(this.rejection); }
|
|
126
|
+
get hasCodes() { return this.issues.some((issue) => Boolean(issue.code)); }
|
|
127
|
+
get issueSummary() { return billRejectionIssueSummary(this.rejection, this.issues.length); }
|
|
128
|
+
get themeStyle() { return mindBillAngularAppearanceStyle(this.appearance); }
|
|
129
|
+
formatDate(value) { const parsed = new Date(value); return Number.isNaN(parsed.getTime()) ? value : new Intl.DateTimeFormat(undefined, { dateStyle: "medium", timeStyle: "short" }).format(parsed); }
|
|
130
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: MindBillBillRejectionNoticeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
131
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: MindBillBillRejectionNoticeComponent, isStandalone: true, selector: "mindbill-bill-rejection-notice", inputs: { rejection: "rejection", submittedAt: "submittedAt", title: "title", appearance: "appearance" }, ngImport: i0, template: `
|
|
132
|
+
<section class="notice" [ngStyle]="themeStyle" role="alert" aria-label="Bill rejection reasons">
|
|
133
|
+
<div class="overview">
|
|
134
|
+
<header>
|
|
135
|
+
<span class="icon" aria-hidden="true">!</span>
|
|
136
|
+
<div><strong>{{ title }}</strong><span>Fix the {{ issues.length === 1 ? 'issue' : 'issues' }} below, then resubmit.</span></div>
|
|
137
|
+
</header>
|
|
138
|
+
<ol class="progress" aria-label="Submission status">
|
|
139
|
+
<li><span aria-hidden="true">✓</span><b>Sent</b>@if (submittedAt) { <small>{{ formatDate(submittedAt) }}</small> }</li>
|
|
140
|
+
<li class="rejected" aria-current="step"><span aria-hidden="true">!</span><b>Rejected</b>@if (rejection.receivedAt) { <small>{{ formatDate(rejection.receivedAt) }}</small> }</li>
|
|
141
|
+
</ol>
|
|
142
|
+
</div>
|
|
143
|
+
<div class="issues" aria-label="Rejection reasons">
|
|
144
|
+
<div class="issues-heading"><strong><span aria-hidden="true">△</span> Rejection reasons</strong><span>{{ issueSummary }}</span></div>
|
|
145
|
+
<ol [attr.aria-label]="issues.length + ' rejection ' + (issues.length === 1 ? 'reason' : 'reasons')">
|
|
146
|
+
@for (issue of issues; track $index) {
|
|
147
|
+
<li><span class="bullet" aria-hidden="true"></span><p>{{ issue.description }}</p>@if (issue.code) { <span class="code">{{ issue.code }}</span> }</li>
|
|
148
|
+
}
|
|
149
|
+
</ol>
|
|
150
|
+
@if (hasCodes) { <p class="code-note"><span aria-hidden="true">i</span> Technical error codes are included for support and auditability.</p> }
|
|
151
|
+
</div>
|
|
152
|
+
</section>
|
|
153
|
+
`, isInline: true, styles: [":host{display:block}.notice,.notice *{box-sizing:border-box}.notice{font-family:var(--font,Inter,system-ui,sans-serif);color:var(--t,#203743);border:1px solid color-mix(in srgb,var(--danger) 30%,var(--b));border-left:4px solid var(--danger);border-radius:var(--r,14px);background:color-mix(in srgb,var(--danger) 5%,var(--s));box-shadow:0 14px 38px color-mix(in srgb,var(--danger) 9%,transparent);padding:26px 28px 18px}.overview{display:grid;grid-template-columns:minmax(230px,.72fr) minmax(360px,1.28fr);align-items:start;gap:38px}header{display:flex;align-items:flex-start;gap:14px}header>div{display:grid;gap:5px}header strong{color:var(--danger);font-size:19px;line-height:1.25}header div>span{color:color-mix(in srgb,var(--danger) 48%,var(--t));font-size:14px;line-height:1.45}.icon{display:grid;place-items:center;flex:0 0 auto;width:42px;height:42px;border-radius:50%;background:var(--danger);box-shadow:0 5px 14px color-mix(in srgb,var(--danger) 25%,transparent);color:#fff;font-size:21px;font-weight:900}.progress{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));list-style:none;margin:5px 0 24px;padding:0}.progress li{display:grid;grid-template-rows:34px auto auto;gap:4px;position:relative;text-align:center;font-size:12px}.progress li:first-child:after{content:\"\";position:absolute;left:calc(50% + 17px);right:calc(-50% + 17px);top:16px;height:2px;background:color-mix(in srgb,var(--danger) 48%,var(--b))}.progress li>span{display:grid;place-items:center;justify-self:center;position:relative;z-index:1;width:34px;height:34px;border:2px solid color-mix(in srgb,var(--danger) 32%,var(--b));border-radius:50%;background:var(--s);color:var(--danger);font-size:16px;font-weight:900}.progress li.rejected>span{border-color:var(--danger);background:var(--danger);color:#fff}.progress b{font-size:13px}.progress small{color:var(--m);font-size:11px;line-height:1.3}.issues{border:1px solid color-mix(in srgb,var(--danger) 19%,var(--b));border-radius:12px;background:color-mix(in srgb,var(--danger) 2%,var(--s));overflow:hidden}.issues-heading{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:12px 16px;border-bottom:1px solid color-mix(in srgb,var(--danger) 14%,var(--b))}.issues-heading strong{display:flex;align-items:center;gap:8px;font-size:13px}.issues-heading strong>span{color:var(--danger);font-size:17px}.issues-heading>span{color:var(--m);font-size:12px;text-align:right}.issues ol{display:grid;gap:7px;list-style:none;margin:0;padding:10px 12px}.issues li{display:grid;grid-template-columns:8px minmax(0,1fr) auto;align-items:center;gap:11px;padding:10px 12px;border:1px solid color-mix(in srgb,var(--danger) 11%,var(--b));border-radius:8px;background:color-mix(in srgb,var(--danger) 1%,var(--s));box-shadow:0 1px 3px #1727300a}.bullet{width:7px;height:7px;border-radius:50%;background:var(--danger)}.issues p{margin:0;font-size:14px;line-height:1.45}.code{justify-self:end;border:1px solid color-mix(in srgb,var(--danger) 20%,var(--b));border-radius:999px;background:color-mix(in srgb,var(--danger) 6%,var(--s));color:var(--danger);font-size:11px;font-weight:850;line-height:1.2;padding:4px 8px}.code-note{display:flex;align-items:center;gap:7px;margin:0;padding:1px 16px 13px;color:var(--m);font-size:11px}.code-note>span{display:grid;place-items:center;width:16px;height:16px;border:1px solid currentColor;border-radius:50%;font-size:10px;font-weight:850}@media(max-width:700px){.notice{padding:18px 14px 14px}.overview{grid-template-columns:1fr;gap:18px}header strong{font-size:17px}.icon{width:36px;height:36px}.progress{margin:0 0 4px}.issues-heading{align-items:flex-start;flex-direction:column;gap:4px}.issues-heading>span{text-align:left}.issues li{grid-template-columns:8px minmax(0,1fr);gap:8px 10px}.code{grid-column:2;justify-self:start}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
154
|
+
}
|
|
155
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: MindBillBillRejectionNoticeComponent, decorators: [{
|
|
156
|
+
type: Component,
|
|
157
|
+
args: [{ selector: "mindbill-bill-rejection-notice", standalone: true, imports: [CommonModule], template: `
|
|
158
|
+
<section class="notice" [ngStyle]="themeStyle" role="alert" aria-label="Bill rejection reasons">
|
|
159
|
+
<div class="overview">
|
|
160
|
+
<header>
|
|
161
|
+
<span class="icon" aria-hidden="true">!</span>
|
|
162
|
+
<div><strong>{{ title }}</strong><span>Fix the {{ issues.length === 1 ? 'issue' : 'issues' }} below, then resubmit.</span></div>
|
|
163
|
+
</header>
|
|
164
|
+
<ol class="progress" aria-label="Submission status">
|
|
165
|
+
<li><span aria-hidden="true">✓</span><b>Sent</b>@if (submittedAt) { <small>{{ formatDate(submittedAt) }}</small> }</li>
|
|
166
|
+
<li class="rejected" aria-current="step"><span aria-hidden="true">!</span><b>Rejected</b>@if (rejection.receivedAt) { <small>{{ formatDate(rejection.receivedAt) }}</small> }</li>
|
|
167
|
+
</ol>
|
|
168
|
+
</div>
|
|
169
|
+
<div class="issues" aria-label="Rejection reasons">
|
|
170
|
+
<div class="issues-heading"><strong><span aria-hidden="true">△</span> Rejection reasons</strong><span>{{ issueSummary }}</span></div>
|
|
171
|
+
<ol [attr.aria-label]="issues.length + ' rejection ' + (issues.length === 1 ? 'reason' : 'reasons')">
|
|
172
|
+
@for (issue of issues; track $index) {
|
|
173
|
+
<li><span class="bullet" aria-hidden="true"></span><p>{{ issue.description }}</p>@if (issue.code) { <span class="code">{{ issue.code }}</span> }</li>
|
|
174
|
+
}
|
|
175
|
+
</ol>
|
|
176
|
+
@if (hasCodes) { <p class="code-note"><span aria-hidden="true">i</span> Technical error codes are included for support and auditability.</p> }
|
|
177
|
+
</div>
|
|
178
|
+
</section>
|
|
179
|
+
`, styles: [":host{display:block}.notice,.notice *{box-sizing:border-box}.notice{font-family:var(--font,Inter,system-ui,sans-serif);color:var(--t,#203743);border:1px solid color-mix(in srgb,var(--danger) 30%,var(--b));border-left:4px solid var(--danger);border-radius:var(--r,14px);background:color-mix(in srgb,var(--danger) 5%,var(--s));box-shadow:0 14px 38px color-mix(in srgb,var(--danger) 9%,transparent);padding:26px 28px 18px}.overview{display:grid;grid-template-columns:minmax(230px,.72fr) minmax(360px,1.28fr);align-items:start;gap:38px}header{display:flex;align-items:flex-start;gap:14px}header>div{display:grid;gap:5px}header strong{color:var(--danger);font-size:19px;line-height:1.25}header div>span{color:color-mix(in srgb,var(--danger) 48%,var(--t));font-size:14px;line-height:1.45}.icon{display:grid;place-items:center;flex:0 0 auto;width:42px;height:42px;border-radius:50%;background:var(--danger);box-shadow:0 5px 14px color-mix(in srgb,var(--danger) 25%,transparent);color:#fff;font-size:21px;font-weight:900}.progress{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));list-style:none;margin:5px 0 24px;padding:0}.progress li{display:grid;grid-template-rows:34px auto auto;gap:4px;position:relative;text-align:center;font-size:12px}.progress li:first-child:after{content:\"\";position:absolute;left:calc(50% + 17px);right:calc(-50% + 17px);top:16px;height:2px;background:color-mix(in srgb,var(--danger) 48%,var(--b))}.progress li>span{display:grid;place-items:center;justify-self:center;position:relative;z-index:1;width:34px;height:34px;border:2px solid color-mix(in srgb,var(--danger) 32%,var(--b));border-radius:50%;background:var(--s);color:var(--danger);font-size:16px;font-weight:900}.progress li.rejected>span{border-color:var(--danger);background:var(--danger);color:#fff}.progress b{font-size:13px}.progress small{color:var(--m);font-size:11px;line-height:1.3}.issues{border:1px solid color-mix(in srgb,var(--danger) 19%,var(--b));border-radius:12px;background:color-mix(in srgb,var(--danger) 2%,var(--s));overflow:hidden}.issues-heading{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:12px 16px;border-bottom:1px solid color-mix(in srgb,var(--danger) 14%,var(--b))}.issues-heading strong{display:flex;align-items:center;gap:8px;font-size:13px}.issues-heading strong>span{color:var(--danger);font-size:17px}.issues-heading>span{color:var(--m);font-size:12px;text-align:right}.issues ol{display:grid;gap:7px;list-style:none;margin:0;padding:10px 12px}.issues li{display:grid;grid-template-columns:8px minmax(0,1fr) auto;align-items:center;gap:11px;padding:10px 12px;border:1px solid color-mix(in srgb,var(--danger) 11%,var(--b));border-radius:8px;background:color-mix(in srgb,var(--danger) 1%,var(--s));box-shadow:0 1px 3px #1727300a}.bullet{width:7px;height:7px;border-radius:50%;background:var(--danger)}.issues p{margin:0;font-size:14px;line-height:1.45}.code{justify-self:end;border:1px solid color-mix(in srgb,var(--danger) 20%,var(--b));border-radius:999px;background:color-mix(in srgb,var(--danger) 6%,var(--s));color:var(--danger);font-size:11px;font-weight:850;line-height:1.2;padding:4px 8px}.code-note{display:flex;align-items:center;gap:7px;margin:0;padding:1px 16px 13px;color:var(--m);font-size:11px}.code-note>span{display:grid;place-items:center;width:16px;height:16px;border:1px solid currentColor;border-radius:50%;font-size:10px;font-weight:850}@media(max-width:700px){.notice{padding:18px 14px 14px}.overview{grid-template-columns:1fr;gap:18px}header strong{font-size:17px}.icon{width:36px;height:36px}.progress{margin:0 0 4px}.issues-heading{align-items:flex-start;flex-direction:column;gap:4px}.issues-heading>span{text-align:left}.issues li{grid-template-columns:8px minmax(0,1fr);gap:8px 10px}.code{grid-column:2;justify-self:start}}\n"] }]
|
|
180
|
+
}], propDecorators: { rejection: [{
|
|
181
|
+
type: Input,
|
|
182
|
+
args: [{ required: true }]
|
|
183
|
+
}], submittedAt: [{
|
|
184
|
+
type: Input
|
|
185
|
+
}], title: [{
|
|
186
|
+
type: Input
|
|
187
|
+
}], appearance: [{
|
|
188
|
+
type: Input
|
|
189
|
+
}] } });
|
|
190
|
+
|
|
88
191
|
class MindBillBillLifecycleComponent {
|
|
89
192
|
billId = "";
|
|
90
193
|
sessionEndpoint = "/api/mindbill/session";
|
|
@@ -117,8 +220,7 @@ class MindBillBillLifecycleComponent {
|
|
|
117
220
|
}
|
|
118
221
|
ngOnDestroy() { this.store.disconnect(); }
|
|
119
222
|
get themeStyle() {
|
|
120
|
-
|
|
121
|
-
return { "--a": this.appearance.accentColor ?? base.accentColor, "--ac": this.appearance.accentTextColor ?? base.accentTextColor, "--bg": this.appearance.backgroundColor ?? base.backgroundColor, "--s": this.appearance.surfaceColor ?? base.surfaceColor, "--t": this.appearance.textColor ?? base.textColor, "--m": this.appearance.mutedColor ?? base.mutedColor, "--b": this.appearance.borderColor ?? base.borderColor, "--r": this.appearance.borderRadius ?? base.borderRadius, "--cr": this.appearance.controlRadius ?? base.controlRadius, "--font": this.appearance.fontFamily ?? base.fontFamily };
|
|
223
|
+
return mindBillAngularAppearanceStyle(this.appearance);
|
|
122
224
|
}
|
|
123
225
|
stateLabel(data) { return data.lifecycle.state.replace(/_/g, " ").replace(/\b\w/g, (value) => value.toUpperCase()); }
|
|
124
226
|
lifecycleDetail(data) { return data.lifecycle.submittedAt ? `Submitted ${new Date(data.lifecycle.submittedAt).toLocaleDateString()}${data.lifecycle.agingDays != null ? ` · ${data.lifecycle.agingDays} days old` : ""}` : "Submitted bill"; }
|
|
@@ -159,9 +261,18 @@ class MindBillBillLifecycleComponent {
|
|
|
159
261
|
<div class="money"><span>{{ data.bill.balanceDue | currency }}</span><small>balance</small></div>
|
|
160
262
|
</header>
|
|
161
263
|
|
|
162
|
-
|
|
163
|
-
<
|
|
164
|
-
|
|
264
|
+
@if (data.lifecycle.state.toLowerCase() === 'rejected' && data.rejection) {
|
|
265
|
+
<mindbill-bill-rejection-notice
|
|
266
|
+
class="rejection"
|
|
267
|
+
[rejection]="data.rejection"
|
|
268
|
+
[submittedAt]="data.lifecycle.submittedAt ?? null"
|
|
269
|
+
[appearance]="appearance"
|
|
270
|
+
/>
|
|
271
|
+
} @else {
|
|
272
|
+
<section class="card progress" aria-label="Bill lifecycle">
|
|
273
|
+
<ol>@for (stage of lifecycleStages; track stage.id; let i=$index) { <li [class.complete]="i < currentStageIndex(data)" [class.current]="i === currentStageIndex(data)"><b>{{ i < currentStageIndex(data) ? '✓' : i + 1 }}</b><span>{{ stage.label }}</span></li> }</ol>
|
|
274
|
+
</section>
|
|
275
|
+
}
|
|
165
276
|
|
|
166
277
|
<section class="card snapshot" aria-label="Bill snapshot">
|
|
167
278
|
<div class="card-title"><div><h3>Bill snapshot</h3><p>The immutable values submitted to the payer.</p></div></div>
|
|
@@ -187,11 +298,11 @@ class MindBillBillLifecycleComponent {
|
|
|
187
298
|
@if (panel === 'close') { <form class="card action-form" (submit)="$event.preventDefault(); closeBill()"><h3>Close bill</h3><label>Reason<textarea required [(ngModel)]="closeReason" name="closeReason"></textarea></label><div><button type="button" (click)="panel=''">Cancel</button><button class="primary" type="submit">Close bill</button></div></form> }
|
|
188
299
|
}
|
|
189
300
|
</section>
|
|
190
|
-
`, isInline: true, styles: [":host{display:block}.mb{font-family:var(--font);color:var(--t);background:var(--bg);padding:20px}.summary,.card,.columns{max-width:1120px;margin:0 auto 16px}.summary{display:flex;justify-content:space-between;align-items:end}.summary h2{margin:4px 0}.summary p,.muted{color:var(--m)}.eyebrow,dt{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--m)}.money{text-align:right}.money span{display:block;font-size:28px;font-weight:800}.money small{color:var(--m)}.card{background:var(--s);border:1px solid var(--b);border-radius:var(--r);padding:20px}.card-title{display:flex;justify-content:space-between;gap:20px}.card-title h3{margin:0}.card-title p{margin:5px 0;color:var(--m)}.progress ol{display:flex;list-style:none;padding:0;margin:0}.progress li{flex:1;text-align:center;position:relative;color:var(--m)}.progress li:before{content:\"\";position:absolute;top:16px;left:0;right:0;border-top:2px solid var(--b)}.progress li:first-child:before{left:50%}.progress li:last-child:before{right:50%}.progress b{position:relative;z-index:1;display:grid;place-items:center;width:32px;height:32px;margin:auto;border:2px solid var(--b);border-radius:50%;background:var(--s)}.progress .complete b,.progress .current b{border-color:var(--a);background:var(--a);color:var(--ac)}.progress span{display:block;margin-top:8px;font-size:12px;font-weight:700}.snapshot dl,.columns dl{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}.snapshot dd,.columns dd{font-weight:700;margin:6px 0}.columns{display:grid;grid-template-columns:1fr 1fr;gap:16px}.columns .card{margin:0}.rows,.timeline{list-style:none;margin:12px 0 0;padding:0}.rows li{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-top:1px solid var(--b)}.rows small{display:block;color:var(--m);margin-top:3px}.timeline li{display:flex;gap:14px;padding:10px 0}.timeline i{width:10px;height:10px;margin-top:5px;border:3px solid var(--a);border-radius:50%}.timeline p{margin:4px 0}.timeline small{color:var(--m)}button,input,select,textarea{font:inherit;border:1px solid var(--b);border-radius:var(--cr);padding:9px 12px;background:var(--s);color:var(--t)}button{cursor:pointer;font-weight:700}.primary{background:var(--a);border-color:var(--a);color:var(--ac)}.actions{max-width:1120px;margin:0 auto;display:flex;justify-content:flex-end;gap:10px}.action-form{display:grid;gap:12px}.action-form label{display:grid;gap:5px;font-weight:700}.action-form div{display:flex;justify-content:flex-end;gap:10px}.state{max-width:720px;margin:auto;padding:32px;text-align:center}.state span{display:block;margin:8px}.error{color:#9b1c1c}.notice{max-width:1120px;margin:0 auto 12px;color:var(--m)}@media(max-width:760px){.mb{padding:12px}.summary,.columns{display:block}.money{text-align:left;margin-top:12px}.columns .card{margin-bottom:12px}.snapshot dl,.columns dl{grid-template-columns:1fr 1fr}.progress span{font-size:10px}.card{padding:15px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i1.DatePipe, name: "date" }] });
|
|
301
|
+
`, isInline: true, styles: [":host{display:block}.mb{font-family:var(--font);color:var(--t);background:var(--bg);padding:20px}.summary,.card,.columns,.rejection{display:block;max-width:1120px;margin:0 auto 16px}.summary{display:flex;justify-content:space-between;align-items:end}.summary h2{margin:4px 0}.summary p,.muted{color:var(--m)}.eyebrow,dt{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--m)}.money{text-align:right}.money span{display:block;font-size:28px;font-weight:800}.money small{color:var(--m)}.card{background:var(--s);border:1px solid var(--b);border-radius:var(--r);padding:20px}.card-title{display:flex;justify-content:space-between;gap:20px}.card-title h3{margin:0}.card-title p{margin:5px 0;color:var(--m)}.progress ol{display:flex;list-style:none;padding:0;margin:0}.progress li{flex:1;text-align:center;position:relative;color:var(--m)}.progress li:before{content:\"\";position:absolute;top:16px;left:0;right:0;border-top:2px solid var(--b)}.progress li:first-child:before{left:50%}.progress li:last-child:before{right:50%}.progress b{position:relative;z-index:1;display:grid;place-items:center;width:32px;height:32px;margin:auto;border:2px solid var(--b);border-radius:50%;background:var(--s)}.progress .complete b,.progress .current b{border-color:var(--a);background:var(--a);color:var(--ac)}.progress span{display:block;margin-top:8px;font-size:12px;font-weight:700}.snapshot dl,.columns dl{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}.snapshot dd,.columns dd{font-weight:700;margin:6px 0}.columns{display:grid;grid-template-columns:1fr 1fr;gap:16px}.columns .card{margin:0}.rows,.timeline{list-style:none;margin:12px 0 0;padding:0}.rows li{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-top:1px solid var(--b)}.rows small{display:block;color:var(--m);margin-top:3px}.timeline li{display:flex;gap:14px;padding:10px 0}.timeline i{width:10px;height:10px;margin-top:5px;border:3px solid var(--a);border-radius:50%}.timeline p{margin:4px 0}.timeline small{color:var(--m)}button,input,select,textarea{font:inherit;border:1px solid var(--b);border-radius:var(--cr);padding:9px 12px;background:var(--s);color:var(--t)}button{cursor:pointer;font-weight:700}.primary{background:var(--a);border-color:var(--a);color:var(--ac)}.actions{max-width:1120px;margin:0 auto;display:flex;justify-content:flex-end;gap:10px}.action-form{display:grid;gap:12px}.action-form label{display:grid;gap:5px;font-weight:700}.action-form div{display:flex;justify-content:flex-end;gap:10px}.state{max-width:720px;margin:auto;padding:32px;text-align:center}.state span{display:block;margin:8px}.error{color:#9b1c1c}.notice{max-width:1120px;margin:0 auto 12px;color:var(--m)}@media(max-width:760px){.mb{padding:12px}.summary,.columns{display:block}.money{text-align:left;margin-top:12px}.columns .card{margin-bottom:12px}.snapshot dl,.columns dl{grid-template-columns:1fr 1fr}.progress span{font-size:10px}.card{padding:15px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: MindBillBillRejectionNoticeComponent, selector: "mindbill-bill-rejection-notice", inputs: ["rejection", "submittedAt", "title", "appearance"] }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i1.DatePipe, name: "date" }] });
|
|
191
302
|
}
|
|
192
303
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: MindBillBillLifecycleComponent, decorators: [{
|
|
193
304
|
type: Component,
|
|
194
|
-
args: [{ selector: "mindbill-bill-lifecycle", standalone: true, imports: [CommonModule, FormsModule], template: `
|
|
305
|
+
args: [{ selector: "mindbill-bill-lifecycle", standalone: true, imports: [CommonModule, FormsModule, MindBillBillRejectionNoticeComponent], template: `
|
|
195
306
|
<section class="mb" [ngStyle]="themeStyle">
|
|
196
307
|
@if (!billId) {
|
|
197
308
|
<div class="state error"><strong>A submitted bill ID is required.</strong></div>
|
|
@@ -205,9 +316,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
205
316
|
<div class="money"><span>{{ data.bill.balanceDue | currency }}</span><small>balance</small></div>
|
|
206
317
|
</header>
|
|
207
318
|
|
|
208
|
-
|
|
209
|
-
<
|
|
210
|
-
|
|
319
|
+
@if (data.lifecycle.state.toLowerCase() === 'rejected' && data.rejection) {
|
|
320
|
+
<mindbill-bill-rejection-notice
|
|
321
|
+
class="rejection"
|
|
322
|
+
[rejection]="data.rejection"
|
|
323
|
+
[submittedAt]="data.lifecycle.submittedAt ?? null"
|
|
324
|
+
[appearance]="appearance"
|
|
325
|
+
/>
|
|
326
|
+
} @else {
|
|
327
|
+
<section class="card progress" aria-label="Bill lifecycle">
|
|
328
|
+
<ol>@for (stage of lifecycleStages; track stage.id; let i=$index) { <li [class.complete]="i < currentStageIndex(data)" [class.current]="i === currentStageIndex(data)"><b>{{ i < currentStageIndex(data) ? '✓' : i + 1 }}</b><span>{{ stage.label }}</span></li> }</ol>
|
|
329
|
+
</section>
|
|
330
|
+
}
|
|
211
331
|
|
|
212
332
|
<section class="card snapshot" aria-label="Bill snapshot">
|
|
213
333
|
<div class="card-title"><div><h3>Bill snapshot</h3><p>The immutable values submitted to the payer.</p></div></div>
|
|
@@ -233,7 +353,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
233
353
|
@if (panel === 'close') { <form class="card action-form" (submit)="$event.preventDefault(); closeBill()"><h3>Close bill</h3><label>Reason<textarea required [(ngModel)]="closeReason" name="closeReason"></textarea></label><div><button type="button" (click)="panel=''">Cancel</button><button class="primary" type="submit">Close bill</button></div></form> }
|
|
234
354
|
}
|
|
235
355
|
</section>
|
|
236
|
-
`, styles: [":host{display:block}.mb{font-family:var(--font);color:var(--t);background:var(--bg);padding:20px}.summary,.card,.columns{max-width:1120px;margin:0 auto 16px}.summary{display:flex;justify-content:space-between;align-items:end}.summary h2{margin:4px 0}.summary p,.muted{color:var(--m)}.eyebrow,dt{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--m)}.money{text-align:right}.money span{display:block;font-size:28px;font-weight:800}.money small{color:var(--m)}.card{background:var(--s);border:1px solid var(--b);border-radius:var(--r);padding:20px}.card-title{display:flex;justify-content:space-between;gap:20px}.card-title h3{margin:0}.card-title p{margin:5px 0;color:var(--m)}.progress ol{display:flex;list-style:none;padding:0;margin:0}.progress li{flex:1;text-align:center;position:relative;color:var(--m)}.progress li:before{content:\"\";position:absolute;top:16px;left:0;right:0;border-top:2px solid var(--b)}.progress li:first-child:before{left:50%}.progress li:last-child:before{right:50%}.progress b{position:relative;z-index:1;display:grid;place-items:center;width:32px;height:32px;margin:auto;border:2px solid var(--b);border-radius:50%;background:var(--s)}.progress .complete b,.progress .current b{border-color:var(--a);background:var(--a);color:var(--ac)}.progress span{display:block;margin-top:8px;font-size:12px;font-weight:700}.snapshot dl,.columns dl{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}.snapshot dd,.columns dd{font-weight:700;margin:6px 0}.columns{display:grid;grid-template-columns:1fr 1fr;gap:16px}.columns .card{margin:0}.rows,.timeline{list-style:none;margin:12px 0 0;padding:0}.rows li{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-top:1px solid var(--b)}.rows small{display:block;color:var(--m);margin-top:3px}.timeline li{display:flex;gap:14px;padding:10px 0}.timeline i{width:10px;height:10px;margin-top:5px;border:3px solid var(--a);border-radius:50%}.timeline p{margin:4px 0}.timeline small{color:var(--m)}button,input,select,textarea{font:inherit;border:1px solid var(--b);border-radius:var(--cr);padding:9px 12px;background:var(--s);color:var(--t)}button{cursor:pointer;font-weight:700}.primary{background:var(--a);border-color:var(--a);color:var(--ac)}.actions{max-width:1120px;margin:0 auto;display:flex;justify-content:flex-end;gap:10px}.action-form{display:grid;gap:12px}.action-form label{display:grid;gap:5px;font-weight:700}.action-form div{display:flex;justify-content:flex-end;gap:10px}.state{max-width:720px;margin:auto;padding:32px;text-align:center}.state span{display:block;margin:8px}.error{color:#9b1c1c}.notice{max-width:1120px;margin:0 auto 12px;color:var(--m)}@media(max-width:760px){.mb{padding:12px}.summary,.columns{display:block}.money{text-align:left;margin-top:12px}.columns .card{margin-bottom:12px}.snapshot dl,.columns dl{grid-template-columns:1fr 1fr}.progress span{font-size:10px}.card{padding:15px}}\n"] }]
|
|
356
|
+
`, styles: [":host{display:block}.mb{font-family:var(--font);color:var(--t);background:var(--bg);padding:20px}.summary,.card,.columns,.rejection{display:block;max-width:1120px;margin:0 auto 16px}.summary{display:flex;justify-content:space-between;align-items:end}.summary h2{margin:4px 0}.summary p,.muted{color:var(--m)}.eyebrow,dt{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--m)}.money{text-align:right}.money span{display:block;font-size:28px;font-weight:800}.money small{color:var(--m)}.card{background:var(--s);border:1px solid var(--b);border-radius:var(--r);padding:20px}.card-title{display:flex;justify-content:space-between;gap:20px}.card-title h3{margin:0}.card-title p{margin:5px 0;color:var(--m)}.progress ol{display:flex;list-style:none;padding:0;margin:0}.progress li{flex:1;text-align:center;position:relative;color:var(--m)}.progress li:before{content:\"\";position:absolute;top:16px;left:0;right:0;border-top:2px solid var(--b)}.progress li:first-child:before{left:50%}.progress li:last-child:before{right:50%}.progress b{position:relative;z-index:1;display:grid;place-items:center;width:32px;height:32px;margin:auto;border:2px solid var(--b);border-radius:50%;background:var(--s)}.progress .complete b,.progress .current b{border-color:var(--a);background:var(--a);color:var(--ac)}.progress span{display:block;margin-top:8px;font-size:12px;font-weight:700}.snapshot dl,.columns dl{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}.snapshot dd,.columns dd{font-weight:700;margin:6px 0}.columns{display:grid;grid-template-columns:1fr 1fr;gap:16px}.columns .card{margin:0}.rows,.timeline{list-style:none;margin:12px 0 0;padding:0}.rows li{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-top:1px solid var(--b)}.rows small{display:block;color:var(--m);margin-top:3px}.timeline li{display:flex;gap:14px;padding:10px 0}.timeline i{width:10px;height:10px;margin-top:5px;border:3px solid var(--a);border-radius:50%}.timeline p{margin:4px 0}.timeline small{color:var(--m)}button,input,select,textarea{font:inherit;border:1px solid var(--b);border-radius:var(--cr);padding:9px 12px;background:var(--s);color:var(--t)}button{cursor:pointer;font-weight:700}.primary{background:var(--a);border-color:var(--a);color:var(--ac)}.actions{max-width:1120px;margin:0 auto;display:flex;justify-content:flex-end;gap:10px}.action-form{display:grid;gap:12px}.action-form label{display:grid;gap:5px;font-weight:700}.action-form div{display:flex;justify-content:flex-end;gap:10px}.state{max-width:720px;margin:auto;padding:32px;text-align:center}.state span{display:block;margin:8px}.error{color:#9b1c1c}.notice{max-width:1120px;margin:0 auto 12px;color:var(--m)}@media(max-width:760px){.mb{padding:12px}.summary,.columns{display:block}.money{text-align:left;margin-top:12px}.columns .card{margin-bottom:12px}.snapshot dl,.columns dl{grid-template-columns:1fr 1fr}.progress span{font-size:10px}.card{padding:15px}}\n"] }]
|
|
237
357
|
}], ctorParameters: () => [], propDecorators: { billId: [{
|
|
238
358
|
type: Input
|
|
239
359
|
}], sessionEndpoint: [{
|
|
@@ -275,7 +395,7 @@ function ensureTrailingProcedureLine(lines) {
|
|
|
275
395
|
: entered;
|
|
276
396
|
}
|
|
277
397
|
|
|
278
|
-
const THEME$
|
|
398
|
+
const THEME$4 = {
|
|
279
399
|
mindbill: { a: "#238dbd", ac: "#fff", bg: "#f3f8fa", s: "#fff", t: "#203743", m: "#657982", b: "#dbe6ea", r: "14px", cr: "8px", font: "Inter,system-ui,sans-serif" },
|
|
280
400
|
"qme-companion": { a: "#53b5dc", ac: "#173542", bg: "#f2f8fb", s: "#fff", t: "#1d3440", m: "#617783", b: "#d7e5eb", r: "12px", cr: "8px", font: "Inter,system-ui,sans-serif" },
|
|
281
401
|
"orange-bright": { a: "#f4510b", ac: "#fff", bg: "#fffaf6", s: "#fffefd", t: "#090f1f", m: "#626a73", b: "#e7e1da", r: "16px", cr: "10px", font: "Inter,system-ui,sans-serif" },
|
|
@@ -349,7 +469,7 @@ function buildMindBillReportCsv(rows) {
|
|
|
349
469
|
class DashboardBase {
|
|
350
470
|
appearance = { preset: "mindbill" };
|
|
351
471
|
get themeStyle() {
|
|
352
|
-
const base = THEME$
|
|
472
|
+
const base = THEME$4[this.appearance.preset ?? "mindbill"] ?? THEME$4["mindbill"];
|
|
353
473
|
return {
|
|
354
474
|
"--a": this.appearance.accentColor ?? base["a"], "--ac": this.appearance.accentTextColor ?? base["ac"],
|
|
355
475
|
"--bg": this.appearance.backgroundColor ?? base["bg"], "--s": this.appearance.surfaceColor ?? base["s"],
|
|
@@ -512,7 +632,7 @@ function buildMindBillStatusAgingCsv(bills, stateOrder) {
|
|
|
512
632
|
return [header, ...lines].map((line) => line.map(quote).join(",")).join("\n");
|
|
513
633
|
}
|
|
514
634
|
|
|
515
|
-
const THEME$
|
|
635
|
+
const THEME$3 = {
|
|
516
636
|
mindbill: { a: "#238dbd", ac: "#fff", bg: "#f3f8fa", s: "#fff", t: "#203743", m: "#657982", b: "#dbe6ea", r: "14px", cr: "8px", font: "Inter,system-ui,sans-serif" },
|
|
517
637
|
"qme-companion": { a: "#53b5dc", ac: "#173542", bg: "#f2f8fb", s: "#fff", t: "#1d3440", m: "#617783", b: "#d7e5eb", r: "12px", cr: "8px", font: "Inter,system-ui,sans-serif" },
|
|
518
638
|
"orange-bright": { a: "#f4510b", ac: "#fff", bg: "#fffaf6", s: "#fffefd", t: "#090f1f", m: "#626a73", b: "#e7e1da", r: "16px", cr: "10px", font: "Inter,system-ui,sans-serif" },
|
|
@@ -531,7 +651,7 @@ class MindBillStatusAgingMatrixComponent {
|
|
|
531
651
|
return buildMindBillStatusAgingMatrix(this.bills, this.stateOrder);
|
|
532
652
|
}
|
|
533
653
|
get themeStyle() {
|
|
534
|
-
const base = THEME$
|
|
654
|
+
const base = THEME$3[this.appearance.preset ?? "mindbill"] ?? THEME$3["mindbill"];
|
|
535
655
|
return {
|
|
536
656
|
"--a": this.appearance.accentColor ?? base["a"], "--ac": this.appearance.accentTextColor ?? base["ac"],
|
|
537
657
|
"--bg": this.appearance.backgroundColor ?? base["bg"], "--s": this.appearance.surfaceColor ?? base["s"],
|
|
@@ -968,7 +1088,7 @@ const QUICK_DIAGNOSES = [
|
|
|
968
1088
|
{ label: "Left knee", code: "M25.562", description: "Pain in left knee" },
|
|
969
1089
|
{ label: "Right knee", code: "M25.561", description: "Pain in right knee" },
|
|
970
1090
|
];
|
|
971
|
-
const THEME$
|
|
1091
|
+
const THEME$2 = {
|
|
972
1092
|
mindbill: { a: "#238dbd", ac: "#fff", bg: "#f3f8fa", s: "#fff", t: "#203743", m: "#657982", b: "#dbe6ea", r: "14px", cr: "8px", font: "Inter,system-ui,sans-serif" },
|
|
973
1093
|
"qme-companion": { a: "#53b5dc", ac: "#173542", bg: "#f2f8fb", s: "#fff", t: "#1d3440", m: "#617783", b: "#d7e5eb", r: "12px", cr: "8px", font: "Inter,system-ui,sans-serif" },
|
|
974
1094
|
"orange-bright": { a: "#f4510b", ac: "#fff", bg: "#fffaf6", s: "#fffefd", t: "#090f1f", m: "#626a73", b: "#e7e1da", r: "16px", cr: "10px", font: "Inter,system-ui,sans-serif" },
|
|
@@ -1041,7 +1161,7 @@ class MindBillBillSubmissionComponent {
|
|
|
1041
1161
|
this.workingAttachments = this.attachments.map((item) => ({ ...item }));
|
|
1042
1162
|
}
|
|
1043
1163
|
get themeStyle() {
|
|
1044
|
-
const base = THEME$
|
|
1164
|
+
const base = THEME$2[this.appearance.preset ?? "mindbill"] ?? THEME$2["mindbill"];
|
|
1045
1165
|
return {
|
|
1046
1166
|
"--a": this.appearance.accentColor ?? base["a"], "--ac": this.appearance.accentTextColor ?? base["ac"],
|
|
1047
1167
|
"--bg": this.appearance.backgroundColor ?? base["bg"], "--s": this.appearance.surfaceColor ?? base["s"],
|
|
@@ -1593,7 +1713,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
1593
1713
|
args: ["window:drop", ["$event"]]
|
|
1594
1714
|
}] } });
|
|
1595
1715
|
|
|
1596
|
-
const THEME = {
|
|
1716
|
+
const THEME$1 = {
|
|
1597
1717
|
mindbill: { a: "#238dbd", ac: "#fff", b: "#dbe6ea", r: "8px", font: "Inter,system-ui,sans-serif" },
|
|
1598
1718
|
"qme-companion": { a: "#53b5dc", ac: "#173542", b: "#d7e5eb", r: "8px", font: "Inter,system-ui,sans-serif" },
|
|
1599
1719
|
"orange-bright": { a: "#f4510b", ac: "#fff", b: "#e7e1da", r: "10px", font: "Inter,system-ui,sans-serif" },
|
|
@@ -1611,7 +1731,7 @@ class MindBillBillingManagementButtonComponent {
|
|
|
1611
1731
|
errorMessage = "";
|
|
1612
1732
|
changeDetector = inject(ChangeDetectorRef);
|
|
1613
1733
|
get themeStyle() {
|
|
1614
|
-
const base = THEME[this.appearance.preset ?? "mindbill"] ?? THEME["mindbill"];
|
|
1734
|
+
const base = THEME$1[this.appearance.preset ?? "mindbill"] ?? THEME$1["mindbill"];
|
|
1615
1735
|
return {
|
|
1616
1736
|
"--a": this.appearance.accentColor ?? base["a"],
|
|
1617
1737
|
"--ac": this.appearance.accentTextColor ?? base["ac"],
|
|
@@ -1700,9 +1820,342 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
1700
1820
|
type: Output
|
|
1701
1821
|
}] } });
|
|
1702
1822
|
|
|
1823
|
+
// Embeddable organization onboarding (INC-1470): practice identity, billing
|
|
1824
|
+
// provider, locations, and the W-9 captured once and saved straight to
|
|
1825
|
+
// MindBill through the partner browser session (organization:manage
|
|
1826
|
+
// permission). variant="settings" stacks every section for edit-after-setup.
|
|
1827
|
+
const THEME = {
|
|
1828
|
+
mindbill: { a: "#238dbd", ac: "#fff", bg: "#f3f8fa", s: "#fff", t: "#203743", m: "#657982", b: "#dbe6ea", r: "14px", cr: "8px", font: "Inter,system-ui,sans-serif" },
|
|
1829
|
+
"qme-companion": { a: "#53b5dc", ac: "#173542", bg: "#f2f8fb", s: "#fff", t: "#1d3440", m: "#617783", b: "#d7e5eb", r: "12px", cr: "8px", font: "Inter,system-ui,sans-serif" },
|
|
1830
|
+
"orange-bright": { a: "#f4510b", ac: "#fff", bg: "#fffaf6", s: "#fffefd", t: "#090f1f", m: "#626a73", b: "#e7e1da", r: "16px", cr: "10px", font: "Inter,system-ui,sans-serif" },
|
|
1831
|
+
"clinical-blue": { a: "#1677ff", ac: "#fff", bg: "#fff", s: "#fff", t: "#1f2d3d", m: "#66788a", b: "#d9e2ec", r: "8px", cr: "6px", font: "Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif" },
|
|
1832
|
+
};
|
|
1833
|
+
async function fileToBase64(file) {
|
|
1834
|
+
const buffer = new Uint8Array(await file.arrayBuffer());
|
|
1835
|
+
let binary = "";
|
|
1836
|
+
for (const byte of buffer)
|
|
1837
|
+
binary += String.fromCharCode(byte);
|
|
1838
|
+
return btoa(binary);
|
|
1839
|
+
}
|
|
1840
|
+
class MindBillOrganizationOnboardingComponent {
|
|
1841
|
+
appearance = { preset: "mindbill" };
|
|
1842
|
+
sessionEndpoint = "/api/mindbill/session";
|
|
1843
|
+
getSession;
|
|
1844
|
+
apiBaseUrl;
|
|
1845
|
+
heading = "Billing setup";
|
|
1846
|
+
description = "Practice identity, locations, and the W-9 — saved once, used on every bill.";
|
|
1847
|
+
variant = "onboarding";
|
|
1848
|
+
saved$ = new EventEmitter();
|
|
1849
|
+
completed = new EventEmitter();
|
|
1850
|
+
organizationError = new EventEmitter();
|
|
1851
|
+
steps = [
|
|
1852
|
+
{ id: "practice", label: "Practice & billing" },
|
|
1853
|
+
{ id: "locations", label: "Locations" },
|
|
1854
|
+
{ id: "w9", label: "W-9" },
|
|
1855
|
+
{ id: "review", label: "Review" },
|
|
1856
|
+
];
|
|
1857
|
+
profile = null;
|
|
1858
|
+
loadError = "";
|
|
1859
|
+
errorMessage = "";
|
|
1860
|
+
step = "practice";
|
|
1861
|
+
saving = false;
|
|
1862
|
+
saved = {};
|
|
1863
|
+
identity = { name: "", legalName: "", taxId: "", npi: "", phone: "", email: "" };
|
|
1864
|
+
provider = { name: "", taxId: "", npi: "", billType: "Professional", phone: "", billingStreet: "", billingCity: "", billingState: "", billingZip: "" };
|
|
1865
|
+
locations = [{ name: "", street: "", city: "", state: "", zip: "", isPrimary: false }];
|
|
1866
|
+
w9File = null;
|
|
1867
|
+
changeDetector = inject(ChangeDetectorRef);
|
|
1868
|
+
completedFired = false;
|
|
1869
|
+
client;
|
|
1870
|
+
ngOnInit() {
|
|
1871
|
+
this.client = createOrganizationClient({
|
|
1872
|
+
sessionEndpoint: this.sessionEndpoint,
|
|
1873
|
+
...(this.getSession ? { getSession: this.getSession } : {}),
|
|
1874
|
+
...(this.apiBaseUrl ? { apiBaseUrl: this.apiBaseUrl } : {}),
|
|
1875
|
+
});
|
|
1876
|
+
this.client.getOrganization()
|
|
1877
|
+
.then((profile) => { this.loadError = ""; this.adoptProfile(profile); })
|
|
1878
|
+
.catch((error) => {
|
|
1879
|
+
const failure = error instanceof Error ? error : new Error("The organization could not be loaded.");
|
|
1880
|
+
this.loadError = failure.message;
|
|
1881
|
+
this.organizationError.emit(failure);
|
|
1882
|
+
})
|
|
1883
|
+
.finally(() => this.changeDetector.markForCheck());
|
|
1884
|
+
}
|
|
1885
|
+
get themeStyle() {
|
|
1886
|
+
const base = THEME[this.appearance.preset ?? "mindbill"] ?? THEME["mindbill"];
|
|
1887
|
+
return {
|
|
1888
|
+
"--a": this.appearance.accentColor ?? base["a"], "--ac": this.appearance.accentTextColor ?? base["ac"],
|
|
1889
|
+
"--bg": this.appearance.backgroundColor ?? base["bg"], "--s": this.appearance.surfaceColor ?? base["s"],
|
|
1890
|
+
"--t": this.appearance.textColor ?? base["t"], "--m": this.appearance.mutedColor ?? base["m"],
|
|
1891
|
+
"--b": this.appearance.borderColor ?? base["b"], "--r": this.appearance.borderRadius ?? base["r"],
|
|
1892
|
+
"--cr": this.appearance.controlRadius ?? base["cr"], "--font": this.appearance.fontFamily ?? base["font"],
|
|
1893
|
+
};
|
|
1894
|
+
}
|
|
1895
|
+
adoptProfile(profile) {
|
|
1896
|
+
this.profile = profile;
|
|
1897
|
+
this.identity = {
|
|
1898
|
+
name: profile.practiceIdentity.name ?? this.identity.name,
|
|
1899
|
+
legalName: profile.practiceIdentity.legalName ?? this.identity.legalName,
|
|
1900
|
+
taxId: profile.practiceIdentity.taxId ?? this.identity.taxId,
|
|
1901
|
+
npi: profile.practiceIdentity.npi ?? this.identity.npi,
|
|
1902
|
+
phone: profile.practiceIdentity.phone ?? this.identity.phone,
|
|
1903
|
+
email: profile.practiceIdentity.email ?? this.identity.email,
|
|
1904
|
+
};
|
|
1905
|
+
if (profile.billingProviders[0])
|
|
1906
|
+
this.provider = { billType: "Professional", ...profile.billingProviders[0] };
|
|
1907
|
+
if (profile.locations.length)
|
|
1908
|
+
this.locations = profile.locations.map((item) => ({ ...item }));
|
|
1909
|
+
if (profile.onboarding.complete && !this.completedFired) {
|
|
1910
|
+
this.completedFired = true;
|
|
1911
|
+
this.completed.emit(profile);
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
addLocation() {
|
|
1915
|
+
this.locations.push({ name: "", street: "", city: "", state: "", zip: "", isPrimary: false });
|
|
1916
|
+
}
|
|
1917
|
+
setPrimary(index) {
|
|
1918
|
+
this.locations = this.locations.map((item, itemIndex) => ({ ...item, isPrimary: itemIndex === index }));
|
|
1919
|
+
}
|
|
1920
|
+
w9Selected(event) {
|
|
1921
|
+
this.w9File = event.target.files?.[0] ?? null;
|
|
1922
|
+
}
|
|
1923
|
+
async run(work, stepId) {
|
|
1924
|
+
this.saving = true;
|
|
1925
|
+
this.errorMessage = "";
|
|
1926
|
+
try {
|
|
1927
|
+
const profile = await work();
|
|
1928
|
+
this.adoptProfile(profile);
|
|
1929
|
+
this.saved[stepId] = true;
|
|
1930
|
+
this.saved$.emit(profile);
|
|
1931
|
+
if (this.variant === "onboarding") {
|
|
1932
|
+
const order = ["practice", "locations", "w9", "review"];
|
|
1933
|
+
const next = order[order.indexOf(stepId) + 1];
|
|
1934
|
+
if (next)
|
|
1935
|
+
this.step = next;
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
catch (error) {
|
|
1939
|
+
const failure = error instanceof Error ? error : new Error("Saving failed.");
|
|
1940
|
+
this.errorMessage = failure.message;
|
|
1941
|
+
this.organizationError.emit(failure);
|
|
1942
|
+
}
|
|
1943
|
+
finally {
|
|
1944
|
+
this.saving = false;
|
|
1945
|
+
this.changeDetector.markForCheck();
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
savePractice() {
|
|
1949
|
+
void this.run(() => this.client.saveBillingProfile({
|
|
1950
|
+
practiceIdentity: this.identity,
|
|
1951
|
+
...(this.provider.name.trim() || this.provider.taxId.trim() || this.provider.npi.trim()
|
|
1952
|
+
? { billingProviders: [this.provider] }
|
|
1953
|
+
: {}),
|
|
1954
|
+
}), "practice");
|
|
1955
|
+
}
|
|
1956
|
+
saveLocations() {
|
|
1957
|
+
void this.run(() => this.client.saveLocations(this.locations.filter((item) => item.name.trim() || item.street.trim())), "locations");
|
|
1958
|
+
}
|
|
1959
|
+
saveW9() {
|
|
1960
|
+
void this.run(async () => {
|
|
1961
|
+
if (!this.w9File)
|
|
1962
|
+
throw new Error("Choose the practice W-9 PDF first.");
|
|
1963
|
+
return this.client.saveW9({ filename: this.w9File.name, contentBase64: await fileToBase64(this.w9File) });
|
|
1964
|
+
}, "w9");
|
|
1965
|
+
}
|
|
1966
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: MindBillOrganizationOnboardingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1967
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: MindBillOrganizationOnboardingComponent, isStandalone: true, selector: "mindbill-organization-onboarding", inputs: { appearance: "appearance", sessionEndpoint: "sessionEndpoint", getSession: "getSession", apiBaseUrl: "apiBaseUrl", heading: "heading", description: "description", variant: "variant" }, outputs: { saved$: "saved$", completed: "completed", organizationError: "organizationError" }, ngImport: i0, template: `
|
|
1968
|
+
<section class="mbob" [ngStyle]="themeStyle">
|
|
1969
|
+
<div class="card">
|
|
1970
|
+
<header><h2>{{ heading }}</h2><p>{{ description }}</p></header>
|
|
1971
|
+
@if (loadError) { <div class="error" role="alert">{{ loadError }}</div> }
|
|
1972
|
+
|
|
1973
|
+
@if (variant === 'onboarding') {
|
|
1974
|
+
<div class="steps">
|
|
1975
|
+
@for (item of steps; track item.id) {
|
|
1976
|
+
<button type="button" [class.active]="step === item.id" [class.done]="saved[item.id]" (click)="step = item.id"><i>{{ saved[item.id] ? '✓' : '' }}</i>{{ item.label }}</button>
|
|
1977
|
+
}
|
|
1978
|
+
</div>
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
@if (variant === 'settings' || step === 'practice') {
|
|
1982
|
+
<div class="grid">
|
|
1983
|
+
<label>Practice name<input [(ngModel)]="identity.name" [disabled]="saving"></label>
|
|
1984
|
+
<label>Legal name<input [(ngModel)]="identity.legalName" [disabled]="saving"></label>
|
|
1985
|
+
<label>Tax ID (EIN)<input [(ngModel)]="identity.taxId" placeholder="94-1234567" [disabled]="saving"></label>
|
|
1986
|
+
<label>Group NPI<input [(ngModel)]="identity.npi" [disabled]="saving"></label>
|
|
1987
|
+
<label>Phone<input [(ngModel)]="identity.phone" [disabled]="saving"></label>
|
|
1988
|
+
<label>Email<input [(ngModel)]="identity.email" [disabled]="saving"></label>
|
|
1989
|
+
</div>
|
|
1990
|
+
<h3>Billing provider (pay-to)</h3>
|
|
1991
|
+
<div class="grid">
|
|
1992
|
+
<label>Billing provider name<input [(ngModel)]="provider.name" [disabled]="saving"></label>
|
|
1993
|
+
<label>Billing tax ID<input [(ngModel)]="provider.taxId" [disabled]="saving"></label>
|
|
1994
|
+
<label>Billing NPI<input [(ngModel)]="provider.npi" [disabled]="saving"></label>
|
|
1995
|
+
<label>Billing phone<input [(ngModel)]="provider.phone" [disabled]="saving"></label>
|
|
1996
|
+
<label class="span">Street<input [(ngModel)]="provider.billingStreet" [disabled]="saving"></label>
|
|
1997
|
+
<label>City<input [(ngModel)]="provider.billingCity" [disabled]="saving"></label>
|
|
1998
|
+
<label>State<input [(ngModel)]="provider.billingState" maxlength="2" [disabled]="saving"></label>
|
|
1999
|
+
<label>ZIP<input [(ngModel)]="provider.billingZip" [disabled]="saving"></label>
|
|
2000
|
+
</div>
|
|
2001
|
+
<div class="actions"><span>{{ saved['practice'] ? 'Saved to MindBill.' : 'Saved once, used on every bill.' }}</span><button type="button" class="save" [disabled]="saving" (click)="savePractice()">{{ saving ? 'Saving…' : 'Save practice' }}</button></div>
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
@if (variant === 'settings') { <h3>Locations</h3> }
|
|
2005
|
+
@if (variant === 'settings' || step === 'locations') {
|
|
2006
|
+
@for (location of locations; track $index; let index = $index) {
|
|
2007
|
+
<div class="loc">
|
|
2008
|
+
<label>Name<input [(ngModel)]="location.name" [disabled]="saving"></label>
|
|
2009
|
+
<label>Street<input [(ngModel)]="location.street" [disabled]="saving"></label>
|
|
2010
|
+
<label>City<input [(ngModel)]="location.city" [disabled]="saving"></label>
|
|
2011
|
+
<label>State<input [(ngModel)]="location.state" maxlength="2" [disabled]="saving"></label>
|
|
2012
|
+
<label>ZIP<input [(ngModel)]="location.zip" [disabled]="saving"></label>
|
|
2013
|
+
<label class="primary"><input type="radio" name="mbob-primary" [checked]="location.isPrimary === true" (change)="setPrimary(index)"> Primary</label>
|
|
2014
|
+
<button type="button" class="remove" aria-label="Remove location" (click)="locations.splice(index, 1)">×</button>
|
|
2015
|
+
</div>
|
|
2016
|
+
}
|
|
2017
|
+
<button type="button" class="add" (click)="addLocation()">+ Add location</button>
|
|
2018
|
+
<div class="actions"><span>{{ saved['locations'] ? 'Saved to MindBill.' : 'Where evaluations happen.' }}</span><button type="button" class="save" [disabled]="saving" (click)="saveLocations()">{{ saving ? 'Saving…' : 'Save locations' }}</button></div>
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
@if (variant === 'settings') { <h3>Practice W-9</h3> }
|
|
2022
|
+
@if (variant === 'settings' || step === 'w9') {
|
|
2023
|
+
@if (profile?.w9; as w9) {
|
|
2024
|
+
<div class="w9-current"><div><strong>{{ w9.filename }}</strong><span> · added {{ w9.addDate }}</span></div><span>Rides on every bill automatically</span></div>
|
|
2025
|
+
}
|
|
2026
|
+
<label class="drop">
|
|
2027
|
+
<input type="file" accept="application/pdf,.pdf" (change)="w9Selected($event)">
|
|
2028
|
+
<strong>{{ w9File ? w9File.name : (profile?.w9 ? 'Replace the W-9 PDF' : 'Drop the practice W-9 PDF here, or click to choose') }}</strong>
|
|
2029
|
+
<span>The W-9 is auto-attached to every submission.</span>
|
|
2030
|
+
</label>
|
|
2031
|
+
<div class="actions"><span>{{ saved['w9'] ? 'Saved to MindBill.' : '' }}</span><button type="button" class="save" [disabled]="saving || !w9File" (click)="saveW9()">{{ saving ? 'Uploading…' : 'Save W-9' }}</button></div>
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
@if (variant === 'settings') { <h3>Checklist</h3> }
|
|
2035
|
+
@if (variant === 'settings' || step === 'review') {
|
|
2036
|
+
<div class="check">
|
|
2037
|
+
@for (item of profile?.onboarding?.checklist ?? []; track item.id) {
|
|
2038
|
+
<div class="check-item" [class.complete]="item.complete"><i>{{ item.complete ? '✓' : '•' }}</i><span>{{ item.label }}</span></div>
|
|
2039
|
+
}
|
|
2040
|
+
@if (profile?.onboarding?.complete) { <p class="done-copy">Billing setup is complete — bills submitted from your product carry this profile automatically.</p> }
|
|
2041
|
+
@else { <p class="muted">Items above complete themselves as each section is saved.</p> }
|
|
2042
|
+
</div>
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
@if (errorMessage) { <div class="error" role="alert">{{ errorMessage }}</div> }
|
|
2046
|
+
</div>
|
|
2047
|
+
</section>
|
|
2048
|
+
`, isInline: true, styles: [":host{display:block}.mbob{font-family:var(--font);color:var(--t);font-size:15px}.mbob *{box-sizing:border-box}.card{border:1px solid var(--b);border-radius:var(--r);background:var(--s);padding:24px}header{margin-bottom:18px}header h2{margin:0;font-size:22px}header p{margin:5px 0 0;color:var(--m)}.steps{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:20px}.steps button{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--b);border-radius:999px;background:var(--s);padding:7px 13px;color:var(--m);font:inherit;font-size:13px;font-weight:700;cursor:pointer}.steps button.active{border-color:var(--a);color:var(--a);background:color-mix(in srgb,var(--a) 8%,var(--s))}.steps button.done i{color:#159447;font-style:normal}.grid{display:grid;grid-template-columns:1fr 1fr;gap:16px 22px}.span{grid-column:1/-1}label{display:grid;gap:7px;font-size:13px;font-weight:720}input:not([type=radio]):not([type=file]){width:100%;min-height:44px;border:1px solid var(--b);border-radius:var(--cr);background:var(--s);padding:10px 12px;color:var(--t);font:inherit;font-weight:450}input:focus{outline:3px solid color-mix(in srgb,var(--a) 22%,transparent);border-color:var(--a)}h3{margin:20px 0 12px;padding-top:16px;border-top:1px solid var(--b);font-size:15px}.loc{display:grid;grid-template-columns:1.2fr 1.4fr .9fr .4fr .6fr auto auto;gap:10px;align-items:end;border-top:1px solid color-mix(in srgb,var(--b) 60%,transparent);padding:12px 0}.loc:first-of-type{border-top:0}.primary{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--m);white-space:nowrap;padding-bottom:12px}.remove{border:0;background:transparent;color:var(--m);font-size:20px;cursor:pointer;padding-bottom:8px}.add{border:1px solid var(--b);border-radius:var(--cr);background:var(--s);padding:10px 14px;color:var(--t);font:inherit;font-weight:700;cursor:pointer}.drop{display:grid;place-content:center;gap:6px;min-height:150px;border:2px dashed color-mix(in srgb,var(--m) 55%,transparent);border-radius:var(--cr);text-align:center;cursor:pointer;position:relative}.drop input{position:absolute;inset:0;opacity:0;cursor:pointer}.drop span{color:var(--m);font-size:13px}.w9-current{display:flex;align-items:center;justify-content:space-between;gap:12px;border:1px solid #9fd6b4;border-radius:var(--cr);background:#f3fcf6;padding:12px 14px;margin-bottom:14px}.w9-current span{color:var(--m);font-size:13px}.check{display:grid;gap:9px}.check-item{display:flex;align-items:center;gap:10px;border:1px solid var(--b);border-radius:var(--cr);padding:11px 14px}.check-item.complete{border-color:#9fd6b4;background:#f3fcf6}.check-item i{font-style:normal}.actions{display:flex;justify-content:space-between;align-items:center;gap:14px;margin-top:20px}.actions>span{color:var(--m)}.save{min-width:170px;border:0;border-radius:var(--cr);background:var(--a);color:var(--ac);padding:12px 22px;font:inherit;font-weight:780;cursor:pointer}.save:disabled{opacity:.6;cursor:wait}.error{margin-top:14px;border-left:4px solid #c83c3c;border-radius:var(--cr);background:color-mix(in srgb,#c83c3c 8%,var(--s));padding:12px 14px;color:#c83c3c}.done-copy{color:#159447;font-weight:750}.muted{color:var(--m)}@media(max-width:820px){.grid{grid-template-columns:1fr}.span{grid-column:auto}.loc{grid-template-columns:1fr 1fr;align-items:center}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
2049
|
+
}
|
|
2050
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: MindBillOrganizationOnboardingComponent, decorators: [{
|
|
2051
|
+
type: Component,
|
|
2052
|
+
args: [{ selector: "mindbill-organization-onboarding", standalone: true, imports: [CommonModule, FormsModule], template: `
|
|
2053
|
+
<section class="mbob" [ngStyle]="themeStyle">
|
|
2054
|
+
<div class="card">
|
|
2055
|
+
<header><h2>{{ heading }}</h2><p>{{ description }}</p></header>
|
|
2056
|
+
@if (loadError) { <div class="error" role="alert">{{ loadError }}</div> }
|
|
2057
|
+
|
|
2058
|
+
@if (variant === 'onboarding') {
|
|
2059
|
+
<div class="steps">
|
|
2060
|
+
@for (item of steps; track item.id) {
|
|
2061
|
+
<button type="button" [class.active]="step === item.id" [class.done]="saved[item.id]" (click)="step = item.id"><i>{{ saved[item.id] ? '✓' : '' }}</i>{{ item.label }}</button>
|
|
2062
|
+
}
|
|
2063
|
+
</div>
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2066
|
+
@if (variant === 'settings' || step === 'practice') {
|
|
2067
|
+
<div class="grid">
|
|
2068
|
+
<label>Practice name<input [(ngModel)]="identity.name" [disabled]="saving"></label>
|
|
2069
|
+
<label>Legal name<input [(ngModel)]="identity.legalName" [disabled]="saving"></label>
|
|
2070
|
+
<label>Tax ID (EIN)<input [(ngModel)]="identity.taxId" placeholder="94-1234567" [disabled]="saving"></label>
|
|
2071
|
+
<label>Group NPI<input [(ngModel)]="identity.npi" [disabled]="saving"></label>
|
|
2072
|
+
<label>Phone<input [(ngModel)]="identity.phone" [disabled]="saving"></label>
|
|
2073
|
+
<label>Email<input [(ngModel)]="identity.email" [disabled]="saving"></label>
|
|
2074
|
+
</div>
|
|
2075
|
+
<h3>Billing provider (pay-to)</h3>
|
|
2076
|
+
<div class="grid">
|
|
2077
|
+
<label>Billing provider name<input [(ngModel)]="provider.name" [disabled]="saving"></label>
|
|
2078
|
+
<label>Billing tax ID<input [(ngModel)]="provider.taxId" [disabled]="saving"></label>
|
|
2079
|
+
<label>Billing NPI<input [(ngModel)]="provider.npi" [disabled]="saving"></label>
|
|
2080
|
+
<label>Billing phone<input [(ngModel)]="provider.phone" [disabled]="saving"></label>
|
|
2081
|
+
<label class="span">Street<input [(ngModel)]="provider.billingStreet" [disabled]="saving"></label>
|
|
2082
|
+
<label>City<input [(ngModel)]="provider.billingCity" [disabled]="saving"></label>
|
|
2083
|
+
<label>State<input [(ngModel)]="provider.billingState" maxlength="2" [disabled]="saving"></label>
|
|
2084
|
+
<label>ZIP<input [(ngModel)]="provider.billingZip" [disabled]="saving"></label>
|
|
2085
|
+
</div>
|
|
2086
|
+
<div class="actions"><span>{{ saved['practice'] ? 'Saved to MindBill.' : 'Saved once, used on every bill.' }}</span><button type="button" class="save" [disabled]="saving" (click)="savePractice()">{{ saving ? 'Saving…' : 'Save practice' }}</button></div>
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
@if (variant === 'settings') { <h3>Locations</h3> }
|
|
2090
|
+
@if (variant === 'settings' || step === 'locations') {
|
|
2091
|
+
@for (location of locations; track $index; let index = $index) {
|
|
2092
|
+
<div class="loc">
|
|
2093
|
+
<label>Name<input [(ngModel)]="location.name" [disabled]="saving"></label>
|
|
2094
|
+
<label>Street<input [(ngModel)]="location.street" [disabled]="saving"></label>
|
|
2095
|
+
<label>City<input [(ngModel)]="location.city" [disabled]="saving"></label>
|
|
2096
|
+
<label>State<input [(ngModel)]="location.state" maxlength="2" [disabled]="saving"></label>
|
|
2097
|
+
<label>ZIP<input [(ngModel)]="location.zip" [disabled]="saving"></label>
|
|
2098
|
+
<label class="primary"><input type="radio" name="mbob-primary" [checked]="location.isPrimary === true" (change)="setPrimary(index)"> Primary</label>
|
|
2099
|
+
<button type="button" class="remove" aria-label="Remove location" (click)="locations.splice(index, 1)">×</button>
|
|
2100
|
+
</div>
|
|
2101
|
+
}
|
|
2102
|
+
<button type="button" class="add" (click)="addLocation()">+ Add location</button>
|
|
2103
|
+
<div class="actions"><span>{{ saved['locations'] ? 'Saved to MindBill.' : 'Where evaluations happen.' }}</span><button type="button" class="save" [disabled]="saving" (click)="saveLocations()">{{ saving ? 'Saving…' : 'Save locations' }}</button></div>
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
@if (variant === 'settings') { <h3>Practice W-9</h3> }
|
|
2107
|
+
@if (variant === 'settings' || step === 'w9') {
|
|
2108
|
+
@if (profile?.w9; as w9) {
|
|
2109
|
+
<div class="w9-current"><div><strong>{{ w9.filename }}</strong><span> · added {{ w9.addDate }}</span></div><span>Rides on every bill automatically</span></div>
|
|
2110
|
+
}
|
|
2111
|
+
<label class="drop">
|
|
2112
|
+
<input type="file" accept="application/pdf,.pdf" (change)="w9Selected($event)">
|
|
2113
|
+
<strong>{{ w9File ? w9File.name : (profile?.w9 ? 'Replace the W-9 PDF' : 'Drop the practice W-9 PDF here, or click to choose') }}</strong>
|
|
2114
|
+
<span>The W-9 is auto-attached to every submission.</span>
|
|
2115
|
+
</label>
|
|
2116
|
+
<div class="actions"><span>{{ saved['w9'] ? 'Saved to MindBill.' : '' }}</span><button type="button" class="save" [disabled]="saving || !w9File" (click)="saveW9()">{{ saving ? 'Uploading…' : 'Save W-9' }}</button></div>
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
@if (variant === 'settings') { <h3>Checklist</h3> }
|
|
2120
|
+
@if (variant === 'settings' || step === 'review') {
|
|
2121
|
+
<div class="check">
|
|
2122
|
+
@for (item of profile?.onboarding?.checklist ?? []; track item.id) {
|
|
2123
|
+
<div class="check-item" [class.complete]="item.complete"><i>{{ item.complete ? '✓' : '•' }}</i><span>{{ item.label }}</span></div>
|
|
2124
|
+
}
|
|
2125
|
+
@if (profile?.onboarding?.complete) { <p class="done-copy">Billing setup is complete — bills submitted from your product carry this profile automatically.</p> }
|
|
2126
|
+
@else { <p class="muted">Items above complete themselves as each section is saved.</p> }
|
|
2127
|
+
</div>
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
@if (errorMessage) { <div class="error" role="alert">{{ errorMessage }}</div> }
|
|
2131
|
+
</div>
|
|
2132
|
+
</section>
|
|
2133
|
+
`, styles: [":host{display:block}.mbob{font-family:var(--font);color:var(--t);font-size:15px}.mbob *{box-sizing:border-box}.card{border:1px solid var(--b);border-radius:var(--r);background:var(--s);padding:24px}header{margin-bottom:18px}header h2{margin:0;font-size:22px}header p{margin:5px 0 0;color:var(--m)}.steps{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:20px}.steps button{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--b);border-radius:999px;background:var(--s);padding:7px 13px;color:var(--m);font:inherit;font-size:13px;font-weight:700;cursor:pointer}.steps button.active{border-color:var(--a);color:var(--a);background:color-mix(in srgb,var(--a) 8%,var(--s))}.steps button.done i{color:#159447;font-style:normal}.grid{display:grid;grid-template-columns:1fr 1fr;gap:16px 22px}.span{grid-column:1/-1}label{display:grid;gap:7px;font-size:13px;font-weight:720}input:not([type=radio]):not([type=file]){width:100%;min-height:44px;border:1px solid var(--b);border-radius:var(--cr);background:var(--s);padding:10px 12px;color:var(--t);font:inherit;font-weight:450}input:focus{outline:3px solid color-mix(in srgb,var(--a) 22%,transparent);border-color:var(--a)}h3{margin:20px 0 12px;padding-top:16px;border-top:1px solid var(--b);font-size:15px}.loc{display:grid;grid-template-columns:1.2fr 1.4fr .9fr .4fr .6fr auto auto;gap:10px;align-items:end;border-top:1px solid color-mix(in srgb,var(--b) 60%,transparent);padding:12px 0}.loc:first-of-type{border-top:0}.primary{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--m);white-space:nowrap;padding-bottom:12px}.remove{border:0;background:transparent;color:var(--m);font-size:20px;cursor:pointer;padding-bottom:8px}.add{border:1px solid var(--b);border-radius:var(--cr);background:var(--s);padding:10px 14px;color:var(--t);font:inherit;font-weight:700;cursor:pointer}.drop{display:grid;place-content:center;gap:6px;min-height:150px;border:2px dashed color-mix(in srgb,var(--m) 55%,transparent);border-radius:var(--cr);text-align:center;cursor:pointer;position:relative}.drop input{position:absolute;inset:0;opacity:0;cursor:pointer}.drop span{color:var(--m);font-size:13px}.w9-current{display:flex;align-items:center;justify-content:space-between;gap:12px;border:1px solid #9fd6b4;border-radius:var(--cr);background:#f3fcf6;padding:12px 14px;margin-bottom:14px}.w9-current span{color:var(--m);font-size:13px}.check{display:grid;gap:9px}.check-item{display:flex;align-items:center;gap:10px;border:1px solid var(--b);border-radius:var(--cr);padding:11px 14px}.check-item.complete{border-color:#9fd6b4;background:#f3fcf6}.check-item i{font-style:normal}.actions{display:flex;justify-content:space-between;align-items:center;gap:14px;margin-top:20px}.actions>span{color:var(--m)}.save{min-width:170px;border:0;border-radius:var(--cr);background:var(--a);color:var(--ac);padding:12px 22px;font:inherit;font-weight:780;cursor:pointer}.save:disabled{opacity:.6;cursor:wait}.error{margin-top:14px;border-left:4px solid #c83c3c;border-radius:var(--cr);background:color-mix(in srgb,#c83c3c 8%,var(--s));padding:12px 14px;color:#c83c3c}.done-copy{color:#159447;font-weight:750}.muted{color:var(--m)}@media(max-width:820px){.grid{grid-template-columns:1fr}.span{grid-column:auto}.loc{grid-template-columns:1fr 1fr;align-items:center}}\n"] }]
|
|
2134
|
+
}], propDecorators: { appearance: [{
|
|
2135
|
+
type: Input
|
|
2136
|
+
}], sessionEndpoint: [{
|
|
2137
|
+
type: Input
|
|
2138
|
+
}], getSession: [{
|
|
2139
|
+
type: Input
|
|
2140
|
+
}], apiBaseUrl: [{
|
|
2141
|
+
type: Input
|
|
2142
|
+
}], heading: [{
|
|
2143
|
+
type: Input
|
|
2144
|
+
}], description: [{
|
|
2145
|
+
type: Input
|
|
2146
|
+
}], variant: [{
|
|
2147
|
+
type: Input
|
|
2148
|
+
}], saved$: [{
|
|
2149
|
+
type: Output
|
|
2150
|
+
}], completed: [{
|
|
2151
|
+
type: Output
|
|
2152
|
+
}], organizationError: [{
|
|
2153
|
+
type: Output
|
|
2154
|
+
}] } });
|
|
2155
|
+
|
|
1703
2156
|
/**
|
|
1704
2157
|
* Generated bundle index. Do not edit.
|
|
1705
2158
|
*/
|
|
1706
2159
|
|
|
1707
|
-
export { MINDBILL_STATUS_AGING_BUCKETS, MindBillBillAgingSummaryComponent, MindBillBillLifecycleComponent, MindBillBillListComponent, MindBillBillSubmissionComponent, MindBillBillingDashboardComponent, MindBillBillingManagementButtonComponent, MindBillBillingReportComponent, MindBillComboBoxComponent, MindBillDateInputComponent, MindBillLifecycleStore, MindBillStatusAgingMatrixComponent, buildMindBillReportCsv, buildMindBillReportRows, buildMindBillStatusAgingCsv, buildMindBillStatusAgingMatrix, ensureTrailingProcedureLine, formatMindBillSubmissionDate, isEmptyProcedureLine, mindBillAgingBucket, mindBillAgingDays, mindBillCustomProcedureOption, parseMindBillSubmissionDate, summarizeMindBillDashboard };
|
|
2160
|
+
export { MINDBILL_STATUS_AGING_BUCKETS, MindBillBillAgingSummaryComponent, MindBillBillLifecycleComponent, MindBillBillListComponent, MindBillBillRejectionNoticeComponent, MindBillBillSubmissionComponent, MindBillBillingDashboardComponent, MindBillBillingManagementButtonComponent, MindBillBillingReportComponent, MindBillComboBoxComponent, MindBillDateInputComponent, MindBillLifecycleStore, MindBillOrganizationOnboardingComponent, MindBillStatusAgingMatrixComponent, billRejectionIssueSummary, billRejectionIssues, buildMindBillReportCsv, buildMindBillReportRows, buildMindBillStatusAgingCsv, buildMindBillStatusAgingMatrix, ensureTrailingProcedureLine, formatMindBillSubmissionDate, isEmptyProcedureLine, mindBillAgingBucket, mindBillAgingDays, mindBillAngularAppearanceStyle, mindBillCustomProcedureOption, parseMindBillSubmissionDate, summarizeMindBillDashboard };
|
|
1708
2161
|
//# sourceMappingURL=mindbill-angular.mjs.map
|