@mindbill/angular 0.1.2 → 0.2.1
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/LICENSE +21 -0
- package/dist/README.md +56 -0
- package/{fesm2022 → dist/fesm2022}/mindbill-angular.mjs +160 -16
- package/dist/fesm2022/mindbill-angular.mjs.map +1 -0
- package/{types → dist/types}/mindbill-angular.d.ts +23 -8
- package/ng-package.json +6 -0
- package/package.json +6 -14
- package/src/lib/bill-lifecycle.component.ts +378 -0
- package/src/lib/lifecycle-store.ts +109 -0
- package/src/lib/procedure-lines.ts +41 -0
- package/src/public-api.ts +20 -0
- package/tsconfig.lib.json +17 -0
- package/fesm2022/mindbill-angular.mjs.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 IncidentFox, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @mindbill/angular
|
|
2
|
+
|
|
3
|
+
Native Angular billing UI with built-in session renewal and lifecycle API calls.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @mindbill/angular @mindbill/node
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Import the standalone component and give it the one value your application keeps: the bill ID.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { Component } from "@angular/core";
|
|
13
|
+
import { MindBillBillLifecycleComponent } from "@mindbill/angular";
|
|
14
|
+
|
|
15
|
+
@Component({
|
|
16
|
+
selector: "app-case-billing",
|
|
17
|
+
standalone: true,
|
|
18
|
+
imports: [MindBillBillLifecycleComponent],
|
|
19
|
+
template: `
|
|
20
|
+
<mindbill-bill-lifecycle
|
|
21
|
+
[billId]="billId"
|
|
22
|
+
sessionEndpoint="/api/mindbill/bill-session"
|
|
23
|
+
[appearance]="{ preset: 'clinical-blue' }"
|
|
24
|
+
(billIdChange)="billId = $event"
|
|
25
|
+
/>
|
|
26
|
+
`,
|
|
27
|
+
})
|
|
28
|
+
export class CaseBillingComponent {
|
|
29
|
+
billId = "bill_123";
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The component loads and refreshes status, searches the payer directory, saves bill edits, manages the explicit payer packet, submits the bill, shows EORs, and exposes the correct payment, review, correction, resubmission, and close actions for the current state.
|
|
34
|
+
|
|
35
|
+
Procedure entry always keeps one empty row after the entered lines. Starting a code, modifier, or non-default unit count opens the next row automatically; the empty row is never included in save or submit payloads.
|
|
36
|
+
|
|
37
|
+
Add one authenticated server endpoint. It verifies that the signed-in user may access the bill, then mints a short-lived token bound to that bill and browser origin.
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { MindBillClient } from "@mindbill/node";
|
|
41
|
+
|
|
42
|
+
const mindbill = new MindBillClient({ apiKey: process.env["MINDBILL_API_KEY"]! });
|
|
43
|
+
|
|
44
|
+
app.post("/api/mindbill/bill-session", requireUser, async (req, res) => {
|
|
45
|
+
await requireBillAccess(req.user, req.body.billId);
|
|
46
|
+
const session = await mindbill.createBrowserSession({
|
|
47
|
+
component: "bill-review",
|
|
48
|
+
billId: req.body.billId,
|
|
49
|
+
allowedOrigin: `${req.protocol}://${req.get("host")}`,
|
|
50
|
+
expiresIn: 900,
|
|
51
|
+
});
|
|
52
|
+
res.json(session);
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Your permanent API key never reaches Angular. Available presets are `mindbill`, `qme-companion`, `orange-bright`, and `clinical-blue`; every visual token can also be overridden.
|
|
@@ -52,8 +52,9 @@ class MindBillLifecycleStore {
|
|
|
52
52
|
searchClaimsAdministrators(query, claimNumber) {
|
|
53
53
|
return this.requireClient().searchClaimsAdministrators(query, claimNumber);
|
|
54
54
|
}
|
|
55
|
+
getDeliveryOptions() { return this.requireClient().getDeliveryOptions(); }
|
|
55
56
|
saveReview(input) { return this.mutate(() => this.requireClient().saveReview(input)); }
|
|
56
|
-
submitBill(input,
|
|
57
|
+
submitBill(input, submission) { return this.mutate(() => this.requireClient().submitBill(input, submission)); }
|
|
57
58
|
addAttachment(file, type, description) { return this.mutate(() => this.requireClient().addAttachment(file, type, description)); }
|
|
58
59
|
removeAttachment(id) { return this.mutate(() => this.requireClient().removeAttachment(id)); }
|
|
59
60
|
getAttachment(id) { return this.requireClient().getAttachment(id); }
|
|
@@ -110,7 +111,13 @@ const EMPTY_PROCEDURE_LINE = {
|
|
|
110
111
|
charge: 0,
|
|
111
112
|
};
|
|
112
113
|
function isEmptyProcedureLine(line) {
|
|
113
|
-
return !line.code.trim()
|
|
114
|
+
return !line.code.trim()
|
|
115
|
+
&& line.modifiers.length === 0
|
|
116
|
+
&& line.units === 1
|
|
117
|
+
&& !line.serviceDate
|
|
118
|
+
&& !line.serviceDateEnd
|
|
119
|
+
&& !(line.diagnosisPointers?.length)
|
|
120
|
+
&& !line.charge;
|
|
114
121
|
}
|
|
115
122
|
/** Keeps completed/partial lines plus one keyboard-ready empty row. */
|
|
116
123
|
function ensureTrailingProcedureLine(lines) {
|
|
@@ -133,6 +140,7 @@ const DOCUMENT_TYPES = [
|
|
|
133
140
|
{ value: "proof_of_service", label: "Proof of service" },
|
|
134
141
|
{ value: "letter_of_attestation", label: "Letter of attestation" },
|
|
135
142
|
{ value: "form_122", label: "Required form" },
|
|
143
|
+
{ value: "return_to_work_voucher", label: "Return-to-work voucher" },
|
|
136
144
|
{ value: "w9", label: "W-9" },
|
|
137
145
|
{ value: "appeal", label: "Appeal support" },
|
|
138
146
|
{ value: "medical_records", label: "Medical records (intentional)" },
|
|
@@ -150,14 +158,17 @@ class MindBillBillLifecycleComponent {
|
|
|
150
158
|
billingError = new EventEmitter();
|
|
151
159
|
store = new MindBillLifecycleStore();
|
|
152
160
|
documentTypes = DOCUMENT_TYPES;
|
|
153
|
-
|
|
161
|
+
medLegalCodes = ["ML200", "ML201", "ML202", "ML203", "ML204", "ML205", "ML206", "MLPRR"];
|
|
154
162
|
draft = null;
|
|
155
163
|
dirty = false;
|
|
156
164
|
payerQuery = "";
|
|
157
165
|
payerResults = [];
|
|
158
166
|
documentType = "other";
|
|
159
167
|
pendingFile = null;
|
|
160
|
-
|
|
168
|
+
deliveryOptions = null;
|
|
169
|
+
submission = { route: "ebill" };
|
|
170
|
+
showSubmit = false;
|
|
171
|
+
deliveryBusy = false;
|
|
161
172
|
panel = "";
|
|
162
173
|
notice = "";
|
|
163
174
|
closeReason = "";
|
|
@@ -213,17 +224,68 @@ class MindBillBillLifecycleComponent {
|
|
|
213
224
|
lineChanged() { this.normalizeLineItems(); this.dirty = true; }
|
|
214
225
|
removeLine(index) { this.draft?.bill.lineItems.splice(index, 1); this.normalizeLineItems(); this.dirty = true; }
|
|
215
226
|
setModifiers(line, value) { line.modifiers = value.split(",").map((item) => item.trim().replace(/^-/, "")).filter(Boolean); this.normalizeLineItems(); this.dirty = true; }
|
|
227
|
+
setDiagnosisPointers(line, value) { line.diagnosisPointers = value.split(",").map((item) => Number(item.trim())).filter((item) => Number.isInteger(item) && item >= 1 && item <= 12); this.normalizeLineItems(); this.dirty = true; }
|
|
228
|
+
applyPreset(kind) {
|
|
229
|
+
if (!this.draft)
|
|
230
|
+
return;
|
|
231
|
+
const modifier = kind === "ame" ? "94" : kind === "psych" ? "96" : "95";
|
|
232
|
+
const entered = this.draft.bill.lineItems.filter((line) => line.code.trim());
|
|
233
|
+
if (entered.length === 0)
|
|
234
|
+
entered.push({ code: "ML201", modifiers: [modifier], units: 1, charge: 0 });
|
|
235
|
+
else
|
|
236
|
+
entered.forEach((line) => { if (!line.modifiers.length)
|
|
237
|
+
line.modifiers = [modifier]; });
|
|
238
|
+
this.draft.bill.lineItems = ensureTrailingProcedureLine(entered);
|
|
239
|
+
this.dirty = true;
|
|
240
|
+
}
|
|
216
241
|
fileSelected(event) { this.pendingFile = event.target.files?.[0] ?? null; }
|
|
217
242
|
async attach() { if (!this.pendingFile)
|
|
218
243
|
return; await this.store.addAttachment(this.pendingFile, this.documentType); this.pendingFile = null; this.notice = "Document attached."; }
|
|
219
244
|
async removeAttachment(id) { await this.store.removeAttachment(id); this.notice = "Document removed."; }
|
|
220
245
|
async openAttachment(id, filename) { this.openBlob(await this.store.getAttachment(id), filename); }
|
|
221
246
|
async openEor(id, filename) { this.openBlob(await this.store.getEor(id), filename); }
|
|
222
|
-
canSubmit() {
|
|
247
|
+
canSubmit() {
|
|
248
|
+
const input = this.buildInput();
|
|
249
|
+
if (!input || !input.claimsAdminId || !input.billingProvider?.name || !input.billingProvider.taxId || !input.billingProvider.npi || !input.renderingProvider?.name || !input.renderingProvider.npi || !input.lineItems.length)
|
|
250
|
+
return false;
|
|
251
|
+
return input.lineItems.every((line) => line.code && line.units > 0 && (this.draft?.bill.billingMode !== "professional" || Boolean(line.serviceDate && line.charge && line.charge > 0)));
|
|
252
|
+
}
|
|
223
253
|
async save() { const input = this.buildInput(); if (!input)
|
|
224
254
|
return; const data = await this.store.saveReview(input); this.dirty = false; this.draft = this.makeDraft(data); this.notice = "Bill saved."; }
|
|
225
|
-
async
|
|
226
|
-
|
|
255
|
+
async openSubmit() {
|
|
256
|
+
if (!this.canSubmit())
|
|
257
|
+
return;
|
|
258
|
+
this.deliveryBusy = true;
|
|
259
|
+
try {
|
|
260
|
+
this.deliveryOptions = await this.store.getDeliveryOptions();
|
|
261
|
+
this.chooseDelivery(this.deliveryOptions.recommended);
|
|
262
|
+
this.showSubmit = true;
|
|
263
|
+
}
|
|
264
|
+
finally {
|
|
265
|
+
this.deliveryBusy = false;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
closeSubmit() { this.showSubmit = false; }
|
|
269
|
+
selectedDelivery() { return this.deliveryOptions?.options.find((option) => option.route === this.submission.route); }
|
|
270
|
+
chooseDelivery(option) {
|
|
271
|
+
const destination = option.route === "fax" ? { faxNumber: option.target ?? this.deliveryOptions?.contacts.faxNumber ?? "" }
|
|
272
|
+
: option.route === "email" ? { email: option.target ?? this.deliveryOptions?.contacts.claimsEmail ?? "" }
|
|
273
|
+
: option.route === "mail" ? { mailingAddress: option.target ?? this.deliveryOptions?.contacts.mailingAddress ?? "" }
|
|
274
|
+
: undefined;
|
|
275
|
+
this.submission = { route: option.route, ...(destination ? { destination } : {}) };
|
|
276
|
+
}
|
|
277
|
+
setDestination(key, value) { this.submission = { ...this.submission, destination: { ...this.submission.destination, [key]: value } }; }
|
|
278
|
+
deliveryReady() {
|
|
279
|
+
if (this.submission.route === "fax")
|
|
280
|
+
return Boolean(this.submission.destination?.faxNumber?.trim());
|
|
281
|
+
if (this.submission.route === "email")
|
|
282
|
+
return Boolean(this.submission.destination?.email?.trim());
|
|
283
|
+
if (this.submission.route === "mail")
|
|
284
|
+
return Boolean(this.submission.destination?.mailingAddress?.trim());
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
async submit() { const input = this.buildInput(); if (!input || !this.canSubmit() || !this.deliveryReady())
|
|
288
|
+
return; const data = await this.store.submitBill(input, this.submission); this.showSubmit = false; this.dirty = false; this.draft = this.makeDraft(data); this.notice = "Bill submitted."; this.submitted.emit(data); }
|
|
227
289
|
beginAction(action) { if (action === "post_payment")
|
|
228
290
|
this.panel = "payment";
|
|
229
291
|
else if (action === "second_review" || action === "independent_bill_review")
|
|
@@ -270,6 +332,10 @@ class MindBillBillLifecycleComponent {
|
|
|
270
332
|
code: line.code,
|
|
271
333
|
modifiers: line.modifiers,
|
|
272
334
|
units: line.units,
|
|
335
|
+
...(line.charge > 0 ? { charge: line.charge } : {}),
|
|
336
|
+
...(line.serviceDate ? { serviceDate: line.serviceDate } : {}),
|
|
337
|
+
...(line.serviceDateEnd ? { serviceDateEnd: line.serviceDateEnd } : {}),
|
|
338
|
+
...(line.diagnosisPointers?.length ? { diagnosisPointers: line.diagnosisPointers } : {}),
|
|
273
339
|
})),
|
|
274
340
|
};
|
|
275
341
|
}
|
|
@@ -345,8 +411,29 @@ class MindBillBillLifecycleComponent {
|
|
|
345
411
|
</section>
|
|
346
412
|
|
|
347
413
|
<section class="card">
|
|
348
|
-
<div class="card-title"><div><h3>Charges</h3><p>
|
|
349
|
-
|
|
414
|
+
<div class="card-title"><div><h3>Charges</h3><p>{{ draft.bill.billingMode === 'professional' ? 'Enter each treatment or professional service.' : 'Choose medical-legal codes, modifiers, units, and allowed amounts.' }} A keyboard-ready row appears automatically.</p></div></div>
|
|
415
|
+
@if (draft.bill.billingMode === 'med_legal') {
|
|
416
|
+
<div class="presets"><button type="button" (click)="applyPreset('qme')">QME</button><button type="button" (click)="applyPreset('ame')">AME</button><button type="button" (click)="applyPreset('psych')">Psych QME</button></div>
|
|
417
|
+
}
|
|
418
|
+
<div class="lines">@for (line of draft.bill.lineItems; track $index; let i=$index) {
|
|
419
|
+
<div class="line" [class.professional]="draft.bill.billingMode === 'professional'">
|
|
420
|
+
<label><span>Procedure</span>
|
|
421
|
+
@if (draft.bill.billingMode === 'med_legal') {
|
|
422
|
+
<select [(ngModel)]="line.code" [name]="'code'+i" (ngModelChange)="lineChanged()"><option value="">Choose code…</option>@for (code of medLegalCodes; track code) { <option [value]="code">{{ code }}</option> }</select>
|
|
423
|
+
} @else { <input [(ngModel)]="line.code" [name]="'code'+i" (ngModelChange)="lineChanged()" placeholder="e.g. 99204"> }
|
|
424
|
+
</label>
|
|
425
|
+
<label><span>Modifiers</span><input [ngModel]="line.modifiers.join(', ')" (ngModelChange)="setModifiers(line,$any($event))" [name]="'modifiers'+i" placeholder="e.g. 25, 95"></label>
|
|
426
|
+
@if (draft.bill.billingMode === 'professional') {
|
|
427
|
+
<label><span>Service date</span><input type="date" [(ngModel)]="line.serviceDate" [name]="'serviceDate'+i" (ngModelChange)="lineChanged()"></label>
|
|
428
|
+
<label><span>End date</span><input type="date" [(ngModel)]="line.serviceDateEnd" [name]="'serviceDateEnd'+i" (ngModelChange)="lineChanged()"></label>
|
|
429
|
+
<label><span>Charge</span><input type="number" min="0" step="0.01" [(ngModel)]="line.charge" [name]="'charge'+i" (ngModelChange)="lineChanged()"></label>
|
|
430
|
+
<label><span>Diagnosis pointers</span><input [ngModel]="(line.diagnosisPointers || []).join(', ')" (ngModelChange)="setDiagnosisPointers(line,$any($event))" [name]="'pointers'+i" placeholder="1, 2"></label>
|
|
431
|
+
}
|
|
432
|
+
<label><span>Units</span><input type="number" min="1" [(ngModel)]="line.units" [name]="'units'+i" (ngModelChange)="lineChanged()"></label>
|
|
433
|
+
<div class="allowed"><span>{{ draft.bill.billingMode === 'professional' ? 'Charge' : 'Allowed' }}</span><strong>{{ line.charge | currency }}</strong></div>
|
|
434
|
+
<button type="button" class="remove" (click)="removeLine(i)" aria-label="Remove line">×</button>
|
|
435
|
+
</div>
|
|
436
|
+
}</div>
|
|
350
437
|
</section>
|
|
351
438
|
|
|
352
439
|
<section class="card">
|
|
@@ -355,7 +442,25 @@ class MindBillBillLifecycleComponent {
|
|
|
355
442
|
<div class="upload"><select [(ngModel)]="documentType" name="documentType">@for (type of documentTypes; track type.value) { <option [value]="type.value">{{ type.label }}</option> }</select><input #fileInput type="file" accept="application/pdf" (change)="fileSelected($event)"><button type="button" [disabled]="!pendingFile || store.mutating()" (click)="attach()">Attach document</button></div>
|
|
356
443
|
</section>
|
|
357
444
|
|
|
358
|
-
<section class="delivery"><div><span class="eyebrow">Delivery</span><h3>Submit this bill</h3><p>
|
|
445
|
+
<section class="delivery"><div><span class="eyebrow">Delivery</span><h3>Submit this bill</h3><p>Review the exact electronic, fax, email, or mail destination before anything is sent.</p></div><div class="actions"><button type="button" (click)="save()" [disabled]="store.mutating()">Save changes</button><button class="primary" type="button" (click)="openSubmit()" [disabled]="store.mutating() || deliveryBusy || !canSubmit()">{{ deliveryBusy ? 'Loading routes…' : 'Review delivery' }}</button></div></section>
|
|
446
|
+
|
|
447
|
+
@if (showSubmit && deliveryOptions) {
|
|
448
|
+
<div class="modal-backdrop" (click)="closeSubmit()">
|
|
449
|
+
<section class="submit-modal" role="dialog" aria-modal="true" aria-labelledby="mb-submit-title" (click)="$event.stopPropagation()">
|
|
450
|
+
<header><div><span class="eyebrow">Send bill</span><h3 id="mb-submit-title">Choose a delivery route</h3><p>{{ deliveryOptions.payerName }}</p></div><button type="button" class="close" (click)="closeSubmit()" aria-label="Close">×</button></header>
|
|
451
|
+
<div class="route-list">@for (option of deliveryOptions.options; track option.route) {
|
|
452
|
+
<button type="button" class="route-option" [class.selected]="submission.route === option.route" (click)="chooseDelivery(option)"><span class="radio"></span><span><strong>{{ option.label }}</strong><small>{{ option.detail }}</small></span>@if (option.route === deliveryOptions.recommended.route) { <b>Recommended</b> }</button>
|
|
453
|
+
}</div>
|
|
454
|
+
@if (selectedDelivery(); as option) {
|
|
455
|
+
@if (option.route === 'fax') { <label><span>Fax number</span><input [ngModel]="submission.destination?.faxNumber || ''" (ngModelChange)="setDestination('faxNumber',$any($event))" name="submitFax"></label> }
|
|
456
|
+
@if (option.route === 'email') { <label><span>Email address</span><input type="email" [ngModel]="submission.destination?.email || ''" (ngModelChange)="setDestination('email',$any($event))" name="submitEmail"></label><label><span>Subject</span><input [(ngModel)]="submission.subject" name="submitSubject"></label> }
|
|
457
|
+
@if (option.route === 'mail') { <label><span>Mailing address</span><textarea [ngModel]="submission.destination?.mailingAddress || ''" (ngModelChange)="setDestination('mailingAddress',$any($event))" name="submitMail"></textarea></label> }
|
|
458
|
+
@if (option.route !== 'ebill') { <label><span>Attention (optional)</span><input [(ngModel)]="submission.attention" name="submitAttention"></label> }
|
|
459
|
+
}
|
|
460
|
+
<footer><button type="button" (click)="closeSubmit()">Cancel</button><button type="button" class="primary" (click)="submit()" [disabled]="store.mutating() || !deliveryReady()">{{ store.mutating() ? 'Submitting…' : 'Submit bill' }}</button></footer>
|
|
461
|
+
</section>
|
|
462
|
+
</div>
|
|
463
|
+
}
|
|
359
464
|
</form>
|
|
360
465
|
} @else {
|
|
361
466
|
<section class="card lifecycle">
|
|
@@ -373,7 +478,7 @@ class MindBillBillLifecycleComponent {
|
|
|
373
478
|
}
|
|
374
479
|
<datalist id="mb-states"><option value="CA"></option><option value="AZ"></option><option value="NV"></option><option value="OR"></option><option value="WA"></option><option value="TX"></option><option value="NY"></option></datalist>
|
|
375
480
|
</section>
|
|
376
|
-
`, isInline: true, styles: [":host{display:block}.mb{--a:#238dbd;--ac:#fff;--bg:#f3f8fa;--s:#fff;--t:#203743;--m:#657982;--b:#dbe6ea;--r:12px;--cr:8px;display:grid;gap:16px;color:var(--t);font:14px/1.45 var(--font,Inter,system-ui,sans-serif)}*{box-sizing:border-box}h2,h3,h4,p{margin:0}.summary,.card,.delivery,.state{border:1px solid var(--b);border-radius:var(--r);background:var(--s)}.summary{display:flex;justify-content:space-between;gap:20px;padding:20px}.summary h2{font-size:24px}.summary p,.card p,.delivery p,small{color:var(--m)}.eyebrow{color:var(--m);font-size:11px;font-weight:800;letter-spacing:.13em;text-transform:uppercase}.money{text-align:right}.money span{display:block;font-size:28px;font-weight:800}.money small{font-size:12px}.review{display:grid;gap:16px}.card{padding:20px}.card-title{display:flex;align-items:start;justify-content:space-between;gap:16px;margin-bottom:18px}.card-title h3,.delivery h3{font-size:18px}.card-title>span{border-radius:999px;background:var(--bg);padding:5px 9px;color:var(--m);font-size:11px;font-weight:800;text-transform:uppercase}.grid{display:grid;gap:14px}.grid.four{grid-template-columns:repeat(4,minmax(0,1fr))}.grid.three{grid-template-columns:repeat(3,minmax(0,1fr))}.grid.two{grid-template-columns:repeat(2,minmax(0,1fr))}label{display:grid;gap:6px;color:var(--t);font-size:12px;font-weight:700}input,select,textarea,button{font:inherit}input,select,textarea{width:100%;min-height:42px;border:1px solid var(--b);border-radius:var(--cr);background:#fff;color:var(--t);padding:9px 11px}textarea{min-height:90px;resize:vertical}button{min-height:38px;border:1px solid var(--b);border-radius:var(--cr);background:#fff;color:var(--t);padding:8px 13px;cursor:pointer;font-weight:700}button.primary{border-color:var(--a);background:var(--a);color:var(--ac)}button.danger{border-color:#d4380d;background:#d4380d;color:#fff}button:disabled{cursor:not-allowed;opacity:.5}.subhead{margin:18px 0 9px;border-top:1px solid var(--b);padding-top:15px;font-size:12px;font-weight:800}.selected{display:flex;align-items:center;justify-content:space-between;border:1px solid var(--b);border-radius:var(--cr);padding:12px}.selected div{display:grid}.results{position:relative;z-index:3;display:grid;margin-top:5px;border:1px solid var(--b);border-radius:var(--cr);background:#fff;box-shadow:0 12px 30px #1f2d3d1f;overflow:hidden}.results button{display:grid;gap:2px;text-align:left;border:0;border-bottom:1px solid var(--b);border-radius:0;padding:12px}.results span{color:var(--m);font-weight:400}.lines{display:grid;gap:10px}.line{display:grid;grid-template-columns:1.2fr 1.2fr 110px 120px 40px;align-items:end;gap:10px;border-radius:var(--cr);background:var(--bg);padding:12px}.allowed{display:grid;gap:7px;text-align:right}.allowed span{color:var(--m);font-size:11px;font-weight:800;text-transform:uppercase}.allowed strong{font-size:17px}.remove{border:0;background:transparent;font-size:20px}.docs{list-style:none;margin:0;padding:0}.docs li{display:flex;align-items:center;gap:8px;border-top:1px solid var(--b);padding:11px 0}.docs li>div{display:grid;flex:1}.upload{display:grid;grid-template-columns:240px 1fr auto;gap:10px;margin-top:12px;border-radius:var(--cr);background:var(--bg);padding:12px}.delivery{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:20px;background:color-mix(in srgb,var(--a) 5%,white)}.
|
|
481
|
+
`, isInline: true, styles: [":host{display:block}.mb{--a:#238dbd;--ac:#fff;--bg:#f3f8fa;--s:#fff;--t:#203743;--m:#657982;--b:#dbe6ea;--r:12px;--cr:8px;display:grid;gap:16px;color:var(--t);font:14px/1.45 var(--font,Inter,system-ui,sans-serif)}*{box-sizing:border-box}h2,h3,h4,p{margin:0}.summary,.card,.delivery,.state{border:1px solid var(--b);border-radius:var(--r);background:var(--s)}.summary{display:flex;justify-content:space-between;gap:20px;padding:20px}.summary h2{font-size:24px}.summary p,.card p,.delivery p,small{color:var(--m)}.eyebrow{color:var(--m);font-size:11px;font-weight:800;letter-spacing:.13em;text-transform:uppercase}.money{text-align:right}.money span{display:block;font-size:28px;font-weight:800}.money small{font-size:12px}.review{display:grid;gap:16px}.card{padding:20px}.card-title{display:flex;align-items:start;justify-content:space-between;gap:16px;margin-bottom:18px}.card-title h3,.delivery h3{font-size:18px}.card-title>span{border-radius:999px;background:var(--bg);padding:5px 9px;color:var(--m);font-size:11px;font-weight:800;text-transform:uppercase}.grid{display:grid;gap:14px}.grid.four{grid-template-columns:repeat(4,minmax(0,1fr))}.grid.three{grid-template-columns:repeat(3,minmax(0,1fr))}.grid.two{grid-template-columns:repeat(2,minmax(0,1fr))}label{display:grid;gap:6px;color:var(--t);font-size:12px;font-weight:700}input,select,textarea,button{font:inherit}input,select,textarea{width:100%;min-height:42px;border:1px solid var(--b);border-radius:var(--cr);background:#fff;color:var(--t);padding:9px 11px}textarea{min-height:90px;resize:vertical}button{min-height:38px;border:1px solid var(--b);border-radius:var(--cr);background:#fff;color:var(--t);padding:8px 13px;cursor:pointer;font-weight:700}button.primary{border-color:var(--a);background:var(--a);color:var(--ac)}button.danger{border-color:#d4380d;background:#d4380d;color:#fff}button:disabled{cursor:not-allowed;opacity:.5}.subhead{margin:18px 0 9px;border-top:1px solid var(--b);padding-top:15px;font-size:12px;font-weight:800}.selected{display:flex;align-items:center;justify-content:space-between;border:1px solid var(--b);border-radius:var(--cr);padding:12px}.selected div{display:grid}.results{position:relative;z-index:3;display:grid;margin-top:5px;border:1px solid var(--b);border-radius:var(--cr);background:#fff;box-shadow:0 12px 30px #1f2d3d1f;overflow:hidden}.results button{display:grid;gap:2px;text-align:left;border:0;border-bottom:1px solid var(--b);border-radius:0;padding:12px}.results span{color:var(--m);font-weight:400}.presets{display:flex;gap:8px;margin:-4px 0 12px}.lines{display:grid;gap:10px}.line{display:grid;grid-template-columns:1.2fr 1.2fr 110px 120px 40px;align-items:end;gap:10px;border-radius:var(--cr);background:var(--bg);padding:12px}.line.professional{grid-template-columns:1.1fr 1fr 1fr 1fr 110px 1fr 90px 110px 40px}.allowed{display:grid;gap:7px;text-align:right}.allowed span{color:var(--m);font-size:11px;font-weight:800;text-transform:uppercase}.allowed strong{font-size:17px}.remove{border:0;background:transparent;font-size:20px}.docs{list-style:none;margin:0;padding:0}.docs li{display:flex;align-items:center;gap:8px;border-top:1px solid var(--b);padding:11px 0}.docs li>div{display:grid;flex:1}.upload{display:grid;grid-template-columns:240px 1fr auto;gap:10px;margin-top:12px;border-radius:var(--cr);background:var(--bg);padding:12px}.delivery{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:20px;background:color-mix(in srgb,var(--a) 5%,white)}.actions,.actionbar{display:flex;justify-content:flex-end;gap:8px}.lifecycle{display:grid;gap:16px}.actionbar{flex-wrap:wrap}.eors{display:grid;gap:8px}.eors>button{display:flex;align-items:center;justify-content:space-between;text-align:left}.eors span{display:grid}.panel{display:grid;gap:14px;border-top:1px solid var(--b);padding-top:16px}.notice,.state{padding:13px 15px}.notice{border-radius:var(--cr);background:#edf8f2;color:#23734c}.notice.error,.state.error{background:#fff2f0;color:#b42318}.state{display:grid;gap:10px}.state button{justify-self:start}.powered{text-align:right;color:var(--m);font-size:11px}.modal-backdrop{position:fixed;z-index:1000;inset:0;display:grid;place-items:center;background:#0f20288f;padding:20px}.submit-modal{display:grid;gap:18px;width:min(680px,100%);max-height:calc(100vh - 40px);overflow:auto;border:1px solid var(--b);border-radius:var(--r);background:var(--s);padding:22px;box-shadow:0 24px 80px #0f202847}.submit-modal>header,.submit-modal>footer{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}.submit-modal>footer{justify-content:flex-end}.submit-modal .close{border:0;background:transparent;font-size:26px}.route-list{display:grid;gap:8px}.route-option{display:grid;grid-template-columns:20px 1fr auto;align-items:center;gap:12px;text-align:left;padding:13px}.route-option>span:nth-child(2){display:grid}.route-option.selected{border-color:var(--a);box-shadow:0 0 0 2px color-mix(in srgb,var(--a) 18%,transparent)}.route-option .radio{width:16px;height:16px;border:2px solid var(--b);border-radius:50%}.route-option.selected .radio{border:5px solid var(--a)}.route-option b{color:var(--a);font-size:11px;text-transform:uppercase}@media(max-width:1100px){.line.professional{grid-template-columns:repeat(3,minmax(0,1fr))}.line.professional .allowed{grid-column:auto}}@media(max-width:900px){.grid.four,.grid.three{grid-template-columns:repeat(2,minmax(0,1fr))}.line{grid-template-columns:1fr 1fr 90px}.allowed{grid-column:1/-2;text-align:left}.upload{grid-template-columns:1fr}.delivery{align-items:stretch;flex-direction:column}.actions{justify-content:flex-start}}@media(max-width:600px){.summary,.card-title{align-items:stretch;flex-direction:column}.money{text-align:left}.grid.four,.grid.three,.grid.two,.line,.line.professional{grid-template-columns:1fr}.allowed{grid-column:auto}.docs li{align-items:flex-start;flex-wrap:wrap}.modal-backdrop{padding:8px}.submit-modal{max-height:calc(100vh - 16px);padding:16px}.route-option{grid-template-columns:20px 1fr}.route-option b{grid-column:2}}\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.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { 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.CurrencyPipe, name: "currency" }] });
|
|
377
482
|
}
|
|
378
483
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: MindBillBillLifecycleComponent, decorators: [{
|
|
379
484
|
type: Component,
|
|
@@ -440,8 +545,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
440
545
|
</section>
|
|
441
546
|
|
|
442
547
|
<section class="card">
|
|
443
|
-
<div class="card-title"><div><h3>Charges</h3><p>
|
|
444
|
-
|
|
548
|
+
<div class="card-title"><div><h3>Charges</h3><p>{{ draft.bill.billingMode === 'professional' ? 'Enter each treatment or professional service.' : 'Choose medical-legal codes, modifiers, units, and allowed amounts.' }} A keyboard-ready row appears automatically.</p></div></div>
|
|
549
|
+
@if (draft.bill.billingMode === 'med_legal') {
|
|
550
|
+
<div class="presets"><button type="button" (click)="applyPreset('qme')">QME</button><button type="button" (click)="applyPreset('ame')">AME</button><button type="button" (click)="applyPreset('psych')">Psych QME</button></div>
|
|
551
|
+
}
|
|
552
|
+
<div class="lines">@for (line of draft.bill.lineItems; track $index; let i=$index) {
|
|
553
|
+
<div class="line" [class.professional]="draft.bill.billingMode === 'professional'">
|
|
554
|
+
<label><span>Procedure</span>
|
|
555
|
+
@if (draft.bill.billingMode === 'med_legal') {
|
|
556
|
+
<select [(ngModel)]="line.code" [name]="'code'+i" (ngModelChange)="lineChanged()"><option value="">Choose code…</option>@for (code of medLegalCodes; track code) { <option [value]="code">{{ code }}</option> }</select>
|
|
557
|
+
} @else { <input [(ngModel)]="line.code" [name]="'code'+i" (ngModelChange)="lineChanged()" placeholder="e.g. 99204"> }
|
|
558
|
+
</label>
|
|
559
|
+
<label><span>Modifiers</span><input [ngModel]="line.modifiers.join(', ')" (ngModelChange)="setModifiers(line,$any($event))" [name]="'modifiers'+i" placeholder="e.g. 25, 95"></label>
|
|
560
|
+
@if (draft.bill.billingMode === 'professional') {
|
|
561
|
+
<label><span>Service date</span><input type="date" [(ngModel)]="line.serviceDate" [name]="'serviceDate'+i" (ngModelChange)="lineChanged()"></label>
|
|
562
|
+
<label><span>End date</span><input type="date" [(ngModel)]="line.serviceDateEnd" [name]="'serviceDateEnd'+i" (ngModelChange)="lineChanged()"></label>
|
|
563
|
+
<label><span>Charge</span><input type="number" min="0" step="0.01" [(ngModel)]="line.charge" [name]="'charge'+i" (ngModelChange)="lineChanged()"></label>
|
|
564
|
+
<label><span>Diagnosis pointers</span><input [ngModel]="(line.diagnosisPointers || []).join(', ')" (ngModelChange)="setDiagnosisPointers(line,$any($event))" [name]="'pointers'+i" placeholder="1, 2"></label>
|
|
565
|
+
}
|
|
566
|
+
<label><span>Units</span><input type="number" min="1" [(ngModel)]="line.units" [name]="'units'+i" (ngModelChange)="lineChanged()"></label>
|
|
567
|
+
<div class="allowed"><span>{{ draft.bill.billingMode === 'professional' ? 'Charge' : 'Allowed' }}</span><strong>{{ line.charge | currency }}</strong></div>
|
|
568
|
+
<button type="button" class="remove" (click)="removeLine(i)" aria-label="Remove line">×</button>
|
|
569
|
+
</div>
|
|
570
|
+
}</div>
|
|
445
571
|
</section>
|
|
446
572
|
|
|
447
573
|
<section class="card">
|
|
@@ -450,7 +576,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
450
576
|
<div class="upload"><select [(ngModel)]="documentType" name="documentType">@for (type of documentTypes; track type.value) { <option [value]="type.value">{{ type.label }}</option> }</select><input #fileInput type="file" accept="application/pdf" (change)="fileSelected($event)"><button type="button" [disabled]="!pendingFile || store.mutating()" (click)="attach()">Attach document</button></div>
|
|
451
577
|
</section>
|
|
452
578
|
|
|
453
|
-
<section class="delivery"><div><span class="eyebrow">Delivery</span><h3>Submit this bill</h3><p>
|
|
579
|
+
<section class="delivery"><div><span class="eyebrow">Delivery</span><h3>Submit this bill</h3><p>Review the exact electronic, fax, email, or mail destination before anything is sent.</p></div><div class="actions"><button type="button" (click)="save()" [disabled]="store.mutating()">Save changes</button><button class="primary" type="button" (click)="openSubmit()" [disabled]="store.mutating() || deliveryBusy || !canSubmit()">{{ deliveryBusy ? 'Loading routes…' : 'Review delivery' }}</button></div></section>
|
|
580
|
+
|
|
581
|
+
@if (showSubmit && deliveryOptions) {
|
|
582
|
+
<div class="modal-backdrop" (click)="closeSubmit()">
|
|
583
|
+
<section class="submit-modal" role="dialog" aria-modal="true" aria-labelledby="mb-submit-title" (click)="$event.stopPropagation()">
|
|
584
|
+
<header><div><span class="eyebrow">Send bill</span><h3 id="mb-submit-title">Choose a delivery route</h3><p>{{ deliveryOptions.payerName }}</p></div><button type="button" class="close" (click)="closeSubmit()" aria-label="Close">×</button></header>
|
|
585
|
+
<div class="route-list">@for (option of deliveryOptions.options; track option.route) {
|
|
586
|
+
<button type="button" class="route-option" [class.selected]="submission.route === option.route" (click)="chooseDelivery(option)"><span class="radio"></span><span><strong>{{ option.label }}</strong><small>{{ option.detail }}</small></span>@if (option.route === deliveryOptions.recommended.route) { <b>Recommended</b> }</button>
|
|
587
|
+
}</div>
|
|
588
|
+
@if (selectedDelivery(); as option) {
|
|
589
|
+
@if (option.route === 'fax') { <label><span>Fax number</span><input [ngModel]="submission.destination?.faxNumber || ''" (ngModelChange)="setDestination('faxNumber',$any($event))" name="submitFax"></label> }
|
|
590
|
+
@if (option.route === 'email') { <label><span>Email address</span><input type="email" [ngModel]="submission.destination?.email || ''" (ngModelChange)="setDestination('email',$any($event))" name="submitEmail"></label><label><span>Subject</span><input [(ngModel)]="submission.subject" name="submitSubject"></label> }
|
|
591
|
+
@if (option.route === 'mail') { <label><span>Mailing address</span><textarea [ngModel]="submission.destination?.mailingAddress || ''" (ngModelChange)="setDestination('mailingAddress',$any($event))" name="submitMail"></textarea></label> }
|
|
592
|
+
@if (option.route !== 'ebill') { <label><span>Attention (optional)</span><input [(ngModel)]="submission.attention" name="submitAttention"></label> }
|
|
593
|
+
}
|
|
594
|
+
<footer><button type="button" (click)="closeSubmit()">Cancel</button><button type="button" class="primary" (click)="submit()" [disabled]="store.mutating() || !deliveryReady()">{{ store.mutating() ? 'Submitting…' : 'Submit bill' }}</button></footer>
|
|
595
|
+
</section>
|
|
596
|
+
</div>
|
|
597
|
+
}
|
|
454
598
|
</form>
|
|
455
599
|
} @else {
|
|
456
600
|
<section class="card lifecycle">
|
|
@@ -468,7 +612,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
468
612
|
}
|
|
469
613
|
<datalist id="mb-states"><option value="CA"></option><option value="AZ"></option><option value="NV"></option><option value="OR"></option><option value="WA"></option><option value="TX"></option><option value="NY"></option></datalist>
|
|
470
614
|
</section>
|
|
471
|
-
`, styles: [":host{display:block}.mb{--a:#238dbd;--ac:#fff;--bg:#f3f8fa;--s:#fff;--t:#203743;--m:#657982;--b:#dbe6ea;--r:12px;--cr:8px;display:grid;gap:16px;color:var(--t);font:14px/1.45 var(--font,Inter,system-ui,sans-serif)}*{box-sizing:border-box}h2,h3,h4,p{margin:0}.summary,.card,.delivery,.state{border:1px solid var(--b);border-radius:var(--r);background:var(--s)}.summary{display:flex;justify-content:space-between;gap:20px;padding:20px}.summary h2{font-size:24px}.summary p,.card p,.delivery p,small{color:var(--m)}.eyebrow{color:var(--m);font-size:11px;font-weight:800;letter-spacing:.13em;text-transform:uppercase}.money{text-align:right}.money span{display:block;font-size:28px;font-weight:800}.money small{font-size:12px}.review{display:grid;gap:16px}.card{padding:20px}.card-title{display:flex;align-items:start;justify-content:space-between;gap:16px;margin-bottom:18px}.card-title h3,.delivery h3{font-size:18px}.card-title>span{border-radius:999px;background:var(--bg);padding:5px 9px;color:var(--m);font-size:11px;font-weight:800;text-transform:uppercase}.grid{display:grid;gap:14px}.grid.four{grid-template-columns:repeat(4,minmax(0,1fr))}.grid.three{grid-template-columns:repeat(3,minmax(0,1fr))}.grid.two{grid-template-columns:repeat(2,minmax(0,1fr))}label{display:grid;gap:6px;color:var(--t);font-size:12px;font-weight:700}input,select,textarea,button{font:inherit}input,select,textarea{width:100%;min-height:42px;border:1px solid var(--b);border-radius:var(--cr);background:#fff;color:var(--t);padding:9px 11px}textarea{min-height:90px;resize:vertical}button{min-height:38px;border:1px solid var(--b);border-radius:var(--cr);background:#fff;color:var(--t);padding:8px 13px;cursor:pointer;font-weight:700}button.primary{border-color:var(--a);background:var(--a);color:var(--ac)}button.danger{border-color:#d4380d;background:#d4380d;color:#fff}button:disabled{cursor:not-allowed;opacity:.5}.subhead{margin:18px 0 9px;border-top:1px solid var(--b);padding-top:15px;font-size:12px;font-weight:800}.selected{display:flex;align-items:center;justify-content:space-between;border:1px solid var(--b);border-radius:var(--cr);padding:12px}.selected div{display:grid}.results{position:relative;z-index:3;display:grid;margin-top:5px;border:1px solid var(--b);border-radius:var(--cr);background:#fff;box-shadow:0 12px 30px #1f2d3d1f;overflow:hidden}.results button{display:grid;gap:2px;text-align:left;border:0;border-bottom:1px solid var(--b);border-radius:0;padding:12px}.results span{color:var(--m);font-weight:400}.lines{display:grid;gap:10px}.line{display:grid;grid-template-columns:1.2fr 1.2fr 110px 120px 40px;align-items:end;gap:10px;border-radius:var(--cr);background:var(--bg);padding:12px}.allowed{display:grid;gap:7px;text-align:right}.allowed span{color:var(--m);font-size:11px;font-weight:800;text-transform:uppercase}.allowed strong{font-size:17px}.remove{border:0;background:transparent;font-size:20px}.docs{list-style:none;margin:0;padding:0}.docs li{display:flex;align-items:center;gap:8px;border-top:1px solid var(--b);padding:11px 0}.docs li>div{display:grid;flex:1}.upload{display:grid;grid-template-columns:240px 1fr auto;gap:10px;margin-top:12px;border-radius:var(--cr);background:var(--bg);padding:12px}.delivery{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:20px;background:color-mix(in srgb,var(--a) 5%,white)}.
|
|
615
|
+
`, styles: [":host{display:block}.mb{--a:#238dbd;--ac:#fff;--bg:#f3f8fa;--s:#fff;--t:#203743;--m:#657982;--b:#dbe6ea;--r:12px;--cr:8px;display:grid;gap:16px;color:var(--t);font:14px/1.45 var(--font,Inter,system-ui,sans-serif)}*{box-sizing:border-box}h2,h3,h4,p{margin:0}.summary,.card,.delivery,.state{border:1px solid var(--b);border-radius:var(--r);background:var(--s)}.summary{display:flex;justify-content:space-between;gap:20px;padding:20px}.summary h2{font-size:24px}.summary p,.card p,.delivery p,small{color:var(--m)}.eyebrow{color:var(--m);font-size:11px;font-weight:800;letter-spacing:.13em;text-transform:uppercase}.money{text-align:right}.money span{display:block;font-size:28px;font-weight:800}.money small{font-size:12px}.review{display:grid;gap:16px}.card{padding:20px}.card-title{display:flex;align-items:start;justify-content:space-between;gap:16px;margin-bottom:18px}.card-title h3,.delivery h3{font-size:18px}.card-title>span{border-radius:999px;background:var(--bg);padding:5px 9px;color:var(--m);font-size:11px;font-weight:800;text-transform:uppercase}.grid{display:grid;gap:14px}.grid.four{grid-template-columns:repeat(4,minmax(0,1fr))}.grid.three{grid-template-columns:repeat(3,minmax(0,1fr))}.grid.two{grid-template-columns:repeat(2,minmax(0,1fr))}label{display:grid;gap:6px;color:var(--t);font-size:12px;font-weight:700}input,select,textarea,button{font:inherit}input,select,textarea{width:100%;min-height:42px;border:1px solid var(--b);border-radius:var(--cr);background:#fff;color:var(--t);padding:9px 11px}textarea{min-height:90px;resize:vertical}button{min-height:38px;border:1px solid var(--b);border-radius:var(--cr);background:#fff;color:var(--t);padding:8px 13px;cursor:pointer;font-weight:700}button.primary{border-color:var(--a);background:var(--a);color:var(--ac)}button.danger{border-color:#d4380d;background:#d4380d;color:#fff}button:disabled{cursor:not-allowed;opacity:.5}.subhead{margin:18px 0 9px;border-top:1px solid var(--b);padding-top:15px;font-size:12px;font-weight:800}.selected{display:flex;align-items:center;justify-content:space-between;border:1px solid var(--b);border-radius:var(--cr);padding:12px}.selected div{display:grid}.results{position:relative;z-index:3;display:grid;margin-top:5px;border:1px solid var(--b);border-radius:var(--cr);background:#fff;box-shadow:0 12px 30px #1f2d3d1f;overflow:hidden}.results button{display:grid;gap:2px;text-align:left;border:0;border-bottom:1px solid var(--b);border-radius:0;padding:12px}.results span{color:var(--m);font-weight:400}.presets{display:flex;gap:8px;margin:-4px 0 12px}.lines{display:grid;gap:10px}.line{display:grid;grid-template-columns:1.2fr 1.2fr 110px 120px 40px;align-items:end;gap:10px;border-radius:var(--cr);background:var(--bg);padding:12px}.line.professional{grid-template-columns:1.1fr 1fr 1fr 1fr 110px 1fr 90px 110px 40px}.allowed{display:grid;gap:7px;text-align:right}.allowed span{color:var(--m);font-size:11px;font-weight:800;text-transform:uppercase}.allowed strong{font-size:17px}.remove{border:0;background:transparent;font-size:20px}.docs{list-style:none;margin:0;padding:0}.docs li{display:flex;align-items:center;gap:8px;border-top:1px solid var(--b);padding:11px 0}.docs li>div{display:grid;flex:1}.upload{display:grid;grid-template-columns:240px 1fr auto;gap:10px;margin-top:12px;border-radius:var(--cr);background:var(--bg);padding:12px}.delivery{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:20px;background:color-mix(in srgb,var(--a) 5%,white)}.actions,.actionbar{display:flex;justify-content:flex-end;gap:8px}.lifecycle{display:grid;gap:16px}.actionbar{flex-wrap:wrap}.eors{display:grid;gap:8px}.eors>button{display:flex;align-items:center;justify-content:space-between;text-align:left}.eors span{display:grid}.panel{display:grid;gap:14px;border-top:1px solid var(--b);padding-top:16px}.notice,.state{padding:13px 15px}.notice{border-radius:var(--cr);background:#edf8f2;color:#23734c}.notice.error,.state.error{background:#fff2f0;color:#b42318}.state{display:grid;gap:10px}.state button{justify-self:start}.powered{text-align:right;color:var(--m);font-size:11px}.modal-backdrop{position:fixed;z-index:1000;inset:0;display:grid;place-items:center;background:#0f20288f;padding:20px}.submit-modal{display:grid;gap:18px;width:min(680px,100%);max-height:calc(100vh - 40px);overflow:auto;border:1px solid var(--b);border-radius:var(--r);background:var(--s);padding:22px;box-shadow:0 24px 80px #0f202847}.submit-modal>header,.submit-modal>footer{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}.submit-modal>footer{justify-content:flex-end}.submit-modal .close{border:0;background:transparent;font-size:26px}.route-list{display:grid;gap:8px}.route-option{display:grid;grid-template-columns:20px 1fr auto;align-items:center;gap:12px;text-align:left;padding:13px}.route-option>span:nth-child(2){display:grid}.route-option.selected{border-color:var(--a);box-shadow:0 0 0 2px color-mix(in srgb,var(--a) 18%,transparent)}.route-option .radio{width:16px;height:16px;border:2px solid var(--b);border-radius:50%}.route-option.selected .radio{border:5px solid var(--a)}.route-option b{color:var(--a);font-size:11px;text-transform:uppercase}@media(max-width:1100px){.line.professional{grid-template-columns:repeat(3,minmax(0,1fr))}.line.professional .allowed{grid-column:auto}}@media(max-width:900px){.grid.four,.grid.three{grid-template-columns:repeat(2,minmax(0,1fr))}.line{grid-template-columns:1fr 1fr 90px}.allowed{grid-column:1/-2;text-align:left}.upload{grid-template-columns:1fr}.delivery{align-items:stretch;flex-direction:column}.actions{justify-content:flex-start}}@media(max-width:600px){.summary,.card-title{align-items:stretch;flex-direction:column}.money{text-align:left}.grid.four,.grid.three,.grid.two,.line,.line.professional{grid-template-columns:1fr}.allowed{grid-column:auto}.docs li{align-items:flex-start;flex-wrap:wrap}.modal-backdrop{padding:8px}.submit-modal{max-height:calc(100vh - 16px);padding:16px}.route-option{grid-template-columns:20px 1fr}.route-option b{grid-column:2}}\n"] }]
|
|
472
616
|
}], ctorParameters: () => [], propDecorators: { billId: [{
|
|
473
617
|
type: Input,
|
|
474
618
|
args: [{ required: true }]
|
|
@@ -494,5 +638,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
494
638
|
* Generated bundle index. Do not edit.
|
|
495
639
|
*/
|
|
496
640
|
|
|
497
|
-
export { MindBillBillLifecycleComponent, MindBillLifecycleStore, ensureTrailingProcedureLine };
|
|
641
|
+
export { MindBillBillLifecycleComponent, MindBillLifecycleStore, ensureTrailingProcedureLine, isEmptyProcedureLine };
|
|
498
642
|
//# sourceMappingURL=mindbill-angular.mjs.map
|