@mindbill/angular 0.16.0 → 0.17.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 +1 -1
- package/fesm2022/mindbill-angular.mjs +158 -84
- package/fesm2022/mindbill-angular.mjs.map +1 -1
- package/package.json +2 -2
- package/types/mindbill-angular.d.ts +17 -14
package/README.md
CHANGED
|
@@ -170,7 +170,7 @@ The operations surfaces consume a normalized list of bills, so they can be used
|
|
|
170
170
|
|
|
171
171
|
`summarizeMindBillDashboard`, `buildMindBillReportRows`, `buildMindBillReportCsv`, `buildMindBillStatusAgingMatrix`, and `buildMindBillStatusAgingCsv` are also exported for custom layouts and server-side reporting.
|
|
172
172
|
|
|
173
|
-
`mindbill-bill-tasks-dashboard` is
|
|
173
|
+
`mindbill-bill-tasks-dashboard` is a Bill Tasks worklist: one tone-colored card per task section, rows bucketed by age in days with clickable counts, and a grand-total card. Aggregate your own work items with `buildBillTasksDashboard` from `@mindbill/browser` (types re-exported here) and pass the result as `[data]`:
|
|
174
174
|
|
|
175
175
|
```html
|
|
176
176
|
<mindbill-bill-tasks-dashboard
|
|
@@ -1248,11 +1248,12 @@ class MindBillBillLifecycleComponent {
|
|
|
1248
1248
|
payment = { amount: 0, method: "check", depositDate: new Date().toISOString().slice(0, 10) };
|
|
1249
1249
|
review = { reason: "", payerClaimControlNumber: "", disputedAmount: 0 };
|
|
1250
1250
|
reportStatusOptions = REPORT_BILL_STATUS_OPTIONS;
|
|
1251
|
+
report = { status: null, company: "", representativeName: "", representativeRole: "", phone: "", callReference: "", note: "" };
|
|
1252
|
+
reportContactSummary = "";
|
|
1251
1253
|
duplicateDelivery = null;
|
|
1252
1254
|
duplicateDeliveryError = "";
|
|
1255
|
+
duplicateDraftInput = null;
|
|
1253
1256
|
duplicate = { route: "ebill", faxNumber: "", email: "", mailingAddress: "" };
|
|
1254
|
-
report = { status: null, company: "", representativeName: "", representativeRole: "", phone: "", callReference: "", note: "" };
|
|
1255
|
-
reportContactSummary = "";
|
|
1256
1257
|
correctionInitialBill = null;
|
|
1257
1258
|
correctionAttachments = [];
|
|
1258
1259
|
correctionAttentionFields = [];
|
|
@@ -1300,57 +1301,12 @@ class MindBillBillLifecycleComponent {
|
|
|
1300
1301
|
else if (action === "close")
|
|
1301
1302
|
this.panel = "close";
|
|
1302
1303
|
else if (action === "send_duplicate")
|
|
1303
|
-
this.
|
|
1304
|
+
this.prepareDuplicate(data);
|
|
1304
1305
|
else if (action === "report_bill_status")
|
|
1305
1306
|
this.beginReportStatus(data);
|
|
1306
1307
|
else if (action === "view_eor" && data.eors[0])
|
|
1307
1308
|
void this.openEor(data.eors[0].id, data.eors[0].filename);
|
|
1308
1309
|
}
|
|
1309
|
-
beginSendDuplicate() { this.panel = "duplicate"; this.loadDuplicateDelivery(); }
|
|
1310
|
-
loadDuplicateDelivery() {
|
|
1311
|
-
this.duplicateDeliveryError = "";
|
|
1312
|
-
if (this.duplicateDelivery)
|
|
1313
|
-
return;
|
|
1314
|
-
this.store.getDeliveryOptions().then((delivery) => {
|
|
1315
|
-
this.duplicateDelivery = delivery;
|
|
1316
|
-
this.duplicate.route = delivery.recommended.route;
|
|
1317
|
-
this.duplicate.faxNumber = delivery.contacts.faxNumber || "";
|
|
1318
|
-
this.duplicate.email = delivery.contacts.claimsEmail || "";
|
|
1319
|
-
this.duplicate.mailingAddress = delivery.contacts.mailingAddress || "";
|
|
1320
|
-
}).catch((cause) => {
|
|
1321
|
-
this.duplicateDeliveryError = cause instanceof Error ? cause.message : "Delivery options could not be loaded.";
|
|
1322
|
-
});
|
|
1323
|
-
}
|
|
1324
|
-
duplicateRoutes() {
|
|
1325
|
-
const seen = new Set();
|
|
1326
|
-
return (this.duplicateDelivery?.options ?? []).filter((option) => {
|
|
1327
|
-
if (seen.has(option.route))
|
|
1328
|
-
return false;
|
|
1329
|
-
seen.add(option.route);
|
|
1330
|
-
return true;
|
|
1331
|
-
});
|
|
1332
|
-
}
|
|
1333
|
-
duplicateReady() {
|
|
1334
|
-
if (this.duplicate.route === "fax")
|
|
1335
|
-
return this.duplicate.faxNumber.replace(/\D/g, "").length >= 10;
|
|
1336
|
-
if (this.duplicate.route === "email")
|
|
1337
|
-
return this.duplicate.email.includes("@");
|
|
1338
|
-
if (this.duplicate.route === "mail")
|
|
1339
|
-
return this.duplicate.mailingAddress.trim().length > 2;
|
|
1340
|
-
return true;
|
|
1341
|
-
}
|
|
1342
|
-
async sendDuplicate() {
|
|
1343
|
-
if (!this.duplicateDelivery || !this.duplicateReady())
|
|
1344
|
-
return;
|
|
1345
|
-
const route = this.duplicate.route;
|
|
1346
|
-
const destination = route === "fax" ? { faxNumber: this.duplicate.faxNumber.trim() }
|
|
1347
|
-
: route === "email" ? { email: this.duplicate.email.trim() }
|
|
1348
|
-
: route === "mail" ? { mailingAddress: this.duplicate.mailingAddress.trim() }
|
|
1349
|
-
: null;
|
|
1350
|
-
await this.store.sendDuplicateBill({ route, ...(destination ? { destination } : {}) });
|
|
1351
|
-
this.panel = "";
|
|
1352
|
-
this.notice = "Duplicate bill sent.";
|
|
1353
|
-
}
|
|
1354
1310
|
beginReportStatus(data) {
|
|
1355
1311
|
const contacts = reportBillStatusContacts(data.delivery);
|
|
1356
1312
|
const parts = [];
|
|
@@ -1385,7 +1341,7 @@ class MindBillBillLifecycleComponent {
|
|
|
1385
1341
|
async openAttachment(id, filename) { this.openBlob(await this.store.getAttachment(id), filename); }
|
|
1386
1342
|
async openEor(id, filename) { this.openBlob(await this.store.getEor(id), filename); }
|
|
1387
1343
|
async postPayment() { await this.store.postPayment(this.payment); this.panel = ""; this.notice = "Payment posted."; }
|
|
1388
|
-
async submitReview() { await this.store.submitSecondReview({ ...this.review,
|
|
1344
|
+
async submitReview() { await this.store.submitSecondReview({ ...this.review, ...(this.review.disputedAmount > 0 ? { disputedAmount: this.review.disputedAmount } : {}), attachmentIds: this.store.data()?.bill.attachments.map((document) => document.id) ?? [], route: "ebill" }); this.panel = ""; this.notice = "Second Review submitted."; }
|
|
1389
1345
|
async closeBill() { if (!this.closeReason.trim())
|
|
1390
1346
|
return; await this.store.closeBill({ reason: this.closeReason }); this.panel = ""; this.notice = "Bill closed."; }
|
|
1391
1347
|
resubmitFromForm = async (input) => {
|
|
@@ -1397,6 +1353,66 @@ class MindBillBillLifecycleComponent {
|
|
|
1397
1353
|
return { billId: data.bill.id, bill: { id: data.bill.id, state: data.lifecycle.state } };
|
|
1398
1354
|
};
|
|
1399
1355
|
finishCorrection() { this.panel = ""; this.correctionReason = ""; this.notice = "Corrected submission sent."; }
|
|
1356
|
+
duplicateFromForm = async (input) => {
|
|
1357
|
+
this.duplicateDraftInput = input;
|
|
1358
|
+
this.panel = "duplicate_route";
|
|
1359
|
+
await this.loadDuplicateDelivery();
|
|
1360
|
+
const billId = this.store.data()?.bill.id || this.billId;
|
|
1361
|
+
return { billId, bill: { id: billId, state: "draft" } };
|
|
1362
|
+
};
|
|
1363
|
+
finishDuplicate() { }
|
|
1364
|
+
async loadDuplicateDelivery() {
|
|
1365
|
+
this.duplicateDeliveryError = "";
|
|
1366
|
+
if (this.duplicateDelivery)
|
|
1367
|
+
return;
|
|
1368
|
+
try {
|
|
1369
|
+
const delivery = await this.store.getDeliveryOptions();
|
|
1370
|
+
this.duplicateDelivery = delivery;
|
|
1371
|
+
this.duplicate.route = delivery.recommended.route;
|
|
1372
|
+
this.duplicate.faxNumber = delivery.contacts.faxNumber || "";
|
|
1373
|
+
this.duplicate.email = delivery.contacts.claimsEmail || "";
|
|
1374
|
+
this.duplicate.mailingAddress = delivery.contacts.mailingAddress || "";
|
|
1375
|
+
}
|
|
1376
|
+
catch (cause) {
|
|
1377
|
+
this.duplicateDeliveryError = cause instanceof Error ? cause.message : "Delivery options could not be loaded.";
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
duplicateRoutes() {
|
|
1381
|
+
const seen = new Set();
|
|
1382
|
+
return (this.duplicateDelivery?.options ?? []).filter((option) => {
|
|
1383
|
+
if (seen.has(option.route))
|
|
1384
|
+
return false;
|
|
1385
|
+
seen.add(option.route);
|
|
1386
|
+
return true;
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
duplicateReady() {
|
|
1390
|
+
if (!this.duplicateDraftInput)
|
|
1391
|
+
return false;
|
|
1392
|
+
if (this.duplicate.route === "fax")
|
|
1393
|
+
return this.duplicate.faxNumber.replace(/\D/g, "").length >= 10;
|
|
1394
|
+
if (this.duplicate.route === "email")
|
|
1395
|
+
return this.duplicate.email.includes("@");
|
|
1396
|
+
if (this.duplicate.route === "mail")
|
|
1397
|
+
return this.duplicate.mailingAddress.trim().length > 2;
|
|
1398
|
+
return true;
|
|
1399
|
+
}
|
|
1400
|
+
async sendDuplicate() {
|
|
1401
|
+
if (!this.duplicateDelivery || !this.duplicateDraftInput || !this.duplicateReady())
|
|
1402
|
+
return;
|
|
1403
|
+
const route = this.duplicate.route;
|
|
1404
|
+
const destination = route === "fax" ? { faxNumber: this.duplicate.faxNumber.trim() }
|
|
1405
|
+
: route === "email" ? { email: this.duplicate.email.trim() }
|
|
1406
|
+
: route === "mail" ? { mailingAddress: this.duplicate.mailingAddress.trim() }
|
|
1407
|
+
: null;
|
|
1408
|
+
await this.store.sendDuplicateBill({
|
|
1409
|
+
bill: this.duplicateDraftInput.bill,
|
|
1410
|
+
...(this.duplicateDraftInput.documents?.length ? { documents: this.duplicateDraftInput.documents } : {}),
|
|
1411
|
+
submission: { route, ...(destination ? { destination } : {}) },
|
|
1412
|
+
});
|
|
1413
|
+
this.panel = "";
|
|
1414
|
+
this.notice = "Duplicate bill sent.";
|
|
1415
|
+
}
|
|
1400
1416
|
// "Submit New Bill" from a CLOSED bill: same prefilled submission form as the
|
|
1401
1417
|
// correction flow, but the server keeps the closed bill closed and creates a
|
|
1402
1418
|
// fresh original linked to it (both records chain in the submissions timeline).
|
|
@@ -1425,6 +1441,22 @@ class MindBillBillLifecycleComponent {
|
|
|
1425
1441
|
this.correctionReason = "";
|
|
1426
1442
|
this.panel = "resubmit";
|
|
1427
1443
|
}
|
|
1444
|
+
prepareDuplicate(data) {
|
|
1445
|
+
this.correctionInitialBill = correctionBill(data);
|
|
1446
|
+
this.correctionAttachments = data.bill.attachments.map((attachment) => ({
|
|
1447
|
+
filename: attachment.filename,
|
|
1448
|
+
documentType: correctionDocumentType(attachment.documentType),
|
|
1449
|
+
...(attachment.description ? { description: attachment.description } : {}),
|
|
1450
|
+
...(attachment.reportType ? { reportTypeCode: attachment.reportType } : {}),
|
|
1451
|
+
loadBlob: () => this.store.getAttachment(attachment.id),
|
|
1452
|
+
...(attachment.documentType === "w9" ? { locked: true, badge: "Auto-attached" } : {}),
|
|
1453
|
+
}));
|
|
1454
|
+
this.correctionAttentionFields = [];
|
|
1455
|
+
this.duplicateDraftInput = null;
|
|
1456
|
+
this.duplicateDelivery = null;
|
|
1457
|
+
this.duplicateDeliveryError = "";
|
|
1458
|
+
this.panel = "duplicate";
|
|
1459
|
+
}
|
|
1428
1460
|
prepareNewBill(data) {
|
|
1429
1461
|
this.correctionInitialBill = correctionBill(data);
|
|
1430
1462
|
this.correctionAttachments = data.bill.attachments.map((attachment) => ({
|
|
@@ -1485,7 +1517,7 @@ class MindBillBillLifecycleComponent {
|
|
|
1485
1517
|
|
|
1486
1518
|
<section class="card"><div class="card-title"><div><h3>Bill history</h3><p>Submissions, payer responses, follow-up, and payments.</p></div><span>{{ data.history?.length ?? data.activity.length }}</span></div>
|
|
1487
1519
|
@if (data.history?.length) {
|
|
1488
|
-
<!--
|
|
1520
|
+
<!-- Date/Action/User/Details table: submissions are pale-blue
|
|
1489
1521
|
expandable rows (documents + compliance due dates), notes pale-yellow,
|
|
1490
1522
|
277 responses expand into decoded status-code sentences. Rows arrive
|
|
1491
1523
|
pre-worded from the MindBill API (BillLifecycleData.history). -->
|
|
@@ -1526,22 +1558,6 @@ class MindBillBillLifecycleComponent {
|
|
|
1526
1558
|
@if (panel === 'payment') { <form class="card action-form" (submit)="$event.preventDefault(); postPayment()"><h3>Post payment</h3><label>Amount<input required type="number" min="0.01" step="0.01" [(ngModel)]="payment.amount" name="amount"></label><label>Method<select [(ngModel)]="payment.method" name="method"><option value="check">Check</option><option value="eft">EFT</option></select></label><label>Deposit date<input required type="date" [(ngModel)]="payment.depositDate" name="depositDate"></label><div><button type="button" (click)="panel=''">Cancel</button><button class="primary" type="submit">Post payment</button></div></form> }
|
|
1527
1559
|
@if (panel === 'review') { <form class="card action-form" (submit)="$event.preventDefault(); submitReview()"><h3>Submit Second Bill Review</h3><label>Reason<textarea required [(ngModel)]="review.reason" name="reason"></textarea></label><label>Payer claim control number<input required [(ngModel)]="review.payerClaimControlNumber" name="control"></label><label>Disputed amount<input type="number" min="0" step="0.01" [(ngModel)]="review.disputedAmount" name="disputed"></label><div><button type="button" (click)="panel=''">Cancel</button><button class="primary" type="submit">Submit review</button></div></form> }
|
|
1528
1560
|
@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> }
|
|
1529
|
-
@if (panel === 'duplicate') {
|
|
1530
|
-
<form class="card action-form" (submit)="$event.preventDefault(); sendDuplicate()">
|
|
1531
|
-
<h3>Send duplicate bill</h3>
|
|
1532
|
-
@if (!duplicateDelivery) {
|
|
1533
|
-
<p class="muted">{{ duplicateDeliveryError || 'Loading delivery options…' }}</p>
|
|
1534
|
-
<div><button type="button" (click)="panel=''">Cancel</button>@if (duplicateDeliveryError) { <button class="primary" type="button" (click)="loadDuplicateDelivery()">Try again</button> }</div>
|
|
1535
|
-
} @else {
|
|
1536
|
-
<p class="muted">Resend the unchanged submission packet to {{ duplicateDelivery.payerName }}.</p>
|
|
1537
|
-
<label>Delivery method<select [(ngModel)]="duplicate.route" name="duplicateRoute">@for (option of duplicateRoutes(); track option.route) { <option [ngValue]="option.route">{{ option.label }}</option> }</select></label>
|
|
1538
|
-
@if (duplicate.route === 'fax') { <label>Fax number<input required [(ngModel)]="duplicate.faxNumber" name="duplicateFax" placeholder="(000) 000-0000"></label> }
|
|
1539
|
-
@if (duplicate.route === 'email') { <label>Email<input required type="email" [(ngModel)]="duplicate.email" name="duplicateEmail" placeholder="claims@payer.example"></label> }
|
|
1540
|
-
@if (duplicate.route === 'mail') { <label>Mailing address<textarea required [(ngModel)]="duplicate.mailingAddress" name="duplicateMail"></textarea></label> }
|
|
1541
|
-
<div><button type="button" (click)="panel=''">Cancel</button><button class="primary" type="submit" [disabled]="store.mutating() || !duplicateReady()">Send duplicate</button></div>
|
|
1542
|
-
}
|
|
1543
|
-
</form>
|
|
1544
|
-
}
|
|
1545
1561
|
@if (panel === 'report_status') {
|
|
1546
1562
|
<form class="card action-form" (submit)="$event.preventDefault(); reportStatus()">
|
|
1547
1563
|
<h3>Report Bill Status</h3>
|
|
@@ -1587,6 +1603,43 @@ class MindBillBillLifecycleComponent {
|
|
|
1587
1603
|
</section>
|
|
1588
1604
|
</div>
|
|
1589
1605
|
}
|
|
1606
|
+
@if (panel === 'duplicate' && correctionInitialBill) {
|
|
1607
|
+
<div class="correction-backdrop" (mousedown)="closeCorrectionBackdrop($event)">
|
|
1608
|
+
<section class="correction-dialog" role="dialog" aria-modal="true" aria-label="Send duplicate bill">
|
|
1609
|
+
<button type="button" class="dialog-close" aria-label="Close" (click)="panel=''">×</button>
|
|
1610
|
+
<header><h2>Send duplicate bill</h2><p>The original submission remains immutable. Review or edit this fresh bill before choosing its delivery route and confirming transmission.</p></header>
|
|
1611
|
+
<mindbill-bill-submission
|
|
1612
|
+
[initialBill]="correctionInitialBill"
|
|
1613
|
+
[attachments]="correctionAttachments"
|
|
1614
|
+
[appearance]="appearance"
|
|
1615
|
+
[sessionEndpoint]="sessionEndpoint"
|
|
1616
|
+
[getSession]="getSession"
|
|
1617
|
+
[apiBaseUrl]="apiBaseUrl"
|
|
1618
|
+
[submitter]="duplicateFromForm"
|
|
1619
|
+
heading="Duplicate bill information"
|
|
1620
|
+
description="Review every field. The final step confirms the payer delivery route before the duplicate is sent."
|
|
1621
|
+
submitLabel="Continue to delivery"
|
|
1622
|
+
(submitted)="finishDuplicate()"
|
|
1623
|
+
/>
|
|
1624
|
+
</section>
|
|
1625
|
+
</div>
|
|
1626
|
+
}
|
|
1627
|
+
@if (panel === 'duplicate_route') {
|
|
1628
|
+
<form class="card action-form" (submit)="$event.preventDefault(); sendDuplicate()">
|
|
1629
|
+
<h3>Confirm duplicate bill delivery</h3>
|
|
1630
|
+
@if (!duplicateDelivery) {
|
|
1631
|
+
<p class="muted">{{ duplicateDeliveryError || 'Loading delivery options…' }}</p>
|
|
1632
|
+
<div><button type="button" (click)="panel='duplicate'">Back</button>@if (duplicateDeliveryError) { <button class="primary" type="button" (click)="loadDuplicateDelivery()">Try again</button> }</div>
|
|
1633
|
+
} @else {
|
|
1634
|
+
<p class="muted">Confirm how this edited duplicate will be delivered to {{ duplicateDelivery.payerName }}.</p>
|
|
1635
|
+
<label>Delivery method<select [(ngModel)]="duplicate.route" name="duplicateRoute">@for (option of duplicateRoutes(); track option.route) { <option [ngValue]="option.route">{{ option.label }}</option> }</select></label>
|
|
1636
|
+
@if (duplicate.route === 'fax') { <label>Fax number<input required [(ngModel)]="duplicate.faxNumber" name="duplicateFax" placeholder="(000) 000-0000"></label> }
|
|
1637
|
+
@if (duplicate.route === 'email') { <label>Email<input required type="email" [(ngModel)]="duplicate.email" name="duplicateEmail" placeholder="claims@payer.example"></label> }
|
|
1638
|
+
@if (duplicate.route === 'mail') { <label>Mailing address<textarea required [(ngModel)]="duplicate.mailingAddress" name="duplicateMail"></textarea></label> }
|
|
1639
|
+
<div><button type="button" (click)="panel='duplicate'">Back</button><button class="primary" type="submit" [disabled]="store.mutating() || !duplicateReady()">Send duplicate</button></div>
|
|
1640
|
+
}
|
|
1641
|
+
</form>
|
|
1642
|
+
}
|
|
1590
1643
|
@if (panel === 'submit_new_bill' && correctionInitialBill) {
|
|
1591
1644
|
<div class="correction-backdrop" (mousedown)="closeCorrectionBackdrop($event)">
|
|
1592
1645
|
<section class="correction-dialog" role="dialog" aria-modal="true" aria-label="Submit New Bill">
|
|
@@ -1658,7 +1711,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
1658
1711
|
|
|
1659
1712
|
<section class="card"><div class="card-title"><div><h3>Bill history</h3><p>Submissions, payer responses, follow-up, and payments.</p></div><span>{{ data.history?.length ?? data.activity.length }}</span></div>
|
|
1660
1713
|
@if (data.history?.length) {
|
|
1661
|
-
<!--
|
|
1714
|
+
<!-- Date/Action/User/Details table: submissions are pale-blue
|
|
1662
1715
|
expandable rows (documents + compliance due dates), notes pale-yellow,
|
|
1663
1716
|
277 responses expand into decoded status-code sentences. Rows arrive
|
|
1664
1717
|
pre-worded from the MindBill API (BillLifecycleData.history). -->
|
|
@@ -1699,22 +1752,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
1699
1752
|
@if (panel === 'payment') { <form class="card action-form" (submit)="$event.preventDefault(); postPayment()"><h3>Post payment</h3><label>Amount<input required type="number" min="0.01" step="0.01" [(ngModel)]="payment.amount" name="amount"></label><label>Method<select [(ngModel)]="payment.method" name="method"><option value="check">Check</option><option value="eft">EFT</option></select></label><label>Deposit date<input required type="date" [(ngModel)]="payment.depositDate" name="depositDate"></label><div><button type="button" (click)="panel=''">Cancel</button><button class="primary" type="submit">Post payment</button></div></form> }
|
|
1700
1753
|
@if (panel === 'review') { <form class="card action-form" (submit)="$event.preventDefault(); submitReview()"><h3>Submit Second Bill Review</h3><label>Reason<textarea required [(ngModel)]="review.reason" name="reason"></textarea></label><label>Payer claim control number<input required [(ngModel)]="review.payerClaimControlNumber" name="control"></label><label>Disputed amount<input type="number" min="0" step="0.01" [(ngModel)]="review.disputedAmount" name="disputed"></label><div><button type="button" (click)="panel=''">Cancel</button><button class="primary" type="submit">Submit review</button></div></form> }
|
|
1701
1754
|
@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> }
|
|
1702
|
-
@if (panel === 'duplicate') {
|
|
1703
|
-
<form class="card action-form" (submit)="$event.preventDefault(); sendDuplicate()">
|
|
1704
|
-
<h3>Send duplicate bill</h3>
|
|
1705
|
-
@if (!duplicateDelivery) {
|
|
1706
|
-
<p class="muted">{{ duplicateDeliveryError || 'Loading delivery options…' }}</p>
|
|
1707
|
-
<div><button type="button" (click)="panel=''">Cancel</button>@if (duplicateDeliveryError) { <button class="primary" type="button" (click)="loadDuplicateDelivery()">Try again</button> }</div>
|
|
1708
|
-
} @else {
|
|
1709
|
-
<p class="muted">Resend the unchanged submission packet to {{ duplicateDelivery.payerName }}.</p>
|
|
1710
|
-
<label>Delivery method<select [(ngModel)]="duplicate.route" name="duplicateRoute">@for (option of duplicateRoutes(); track option.route) { <option [ngValue]="option.route">{{ option.label }}</option> }</select></label>
|
|
1711
|
-
@if (duplicate.route === 'fax') { <label>Fax number<input required [(ngModel)]="duplicate.faxNumber" name="duplicateFax" placeholder="(000) 000-0000"></label> }
|
|
1712
|
-
@if (duplicate.route === 'email') { <label>Email<input required type="email" [(ngModel)]="duplicate.email" name="duplicateEmail" placeholder="claims@payer.example"></label> }
|
|
1713
|
-
@if (duplicate.route === 'mail') { <label>Mailing address<textarea required [(ngModel)]="duplicate.mailingAddress" name="duplicateMail"></textarea></label> }
|
|
1714
|
-
<div><button type="button" (click)="panel=''">Cancel</button><button class="primary" type="submit" [disabled]="store.mutating() || !duplicateReady()">Send duplicate</button></div>
|
|
1715
|
-
}
|
|
1716
|
-
</form>
|
|
1717
|
-
}
|
|
1718
1755
|
@if (panel === 'report_status') {
|
|
1719
1756
|
<form class="card action-form" (submit)="$event.preventDefault(); reportStatus()">
|
|
1720
1757
|
<h3>Report Bill Status</h3>
|
|
@@ -1760,6 +1797,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
1760
1797
|
</section>
|
|
1761
1798
|
</div>
|
|
1762
1799
|
}
|
|
1800
|
+
@if (panel === 'duplicate' && correctionInitialBill) {
|
|
1801
|
+
<div class="correction-backdrop" (mousedown)="closeCorrectionBackdrop($event)">
|
|
1802
|
+
<section class="correction-dialog" role="dialog" aria-modal="true" aria-label="Send duplicate bill">
|
|
1803
|
+
<button type="button" class="dialog-close" aria-label="Close" (click)="panel=''">×</button>
|
|
1804
|
+
<header><h2>Send duplicate bill</h2><p>The original submission remains immutable. Review or edit this fresh bill before choosing its delivery route and confirming transmission.</p></header>
|
|
1805
|
+
<mindbill-bill-submission
|
|
1806
|
+
[initialBill]="correctionInitialBill"
|
|
1807
|
+
[attachments]="correctionAttachments"
|
|
1808
|
+
[appearance]="appearance"
|
|
1809
|
+
[sessionEndpoint]="sessionEndpoint"
|
|
1810
|
+
[getSession]="getSession"
|
|
1811
|
+
[apiBaseUrl]="apiBaseUrl"
|
|
1812
|
+
[submitter]="duplicateFromForm"
|
|
1813
|
+
heading="Duplicate bill information"
|
|
1814
|
+
description="Review every field. The final step confirms the payer delivery route before the duplicate is sent."
|
|
1815
|
+
submitLabel="Continue to delivery"
|
|
1816
|
+
(submitted)="finishDuplicate()"
|
|
1817
|
+
/>
|
|
1818
|
+
</section>
|
|
1819
|
+
</div>
|
|
1820
|
+
}
|
|
1821
|
+
@if (panel === 'duplicate_route') {
|
|
1822
|
+
<form class="card action-form" (submit)="$event.preventDefault(); sendDuplicate()">
|
|
1823
|
+
<h3>Confirm duplicate bill delivery</h3>
|
|
1824
|
+
@if (!duplicateDelivery) {
|
|
1825
|
+
<p class="muted">{{ duplicateDeliveryError || 'Loading delivery options…' }}</p>
|
|
1826
|
+
<div><button type="button" (click)="panel='duplicate'">Back</button>@if (duplicateDeliveryError) { <button class="primary" type="button" (click)="loadDuplicateDelivery()">Try again</button> }</div>
|
|
1827
|
+
} @else {
|
|
1828
|
+
<p class="muted">Confirm how this edited duplicate will be delivered to {{ duplicateDelivery.payerName }}.</p>
|
|
1829
|
+
<label>Delivery method<select [(ngModel)]="duplicate.route" name="duplicateRoute">@for (option of duplicateRoutes(); track option.route) { <option [ngValue]="option.route">{{ option.label }}</option> }</select></label>
|
|
1830
|
+
@if (duplicate.route === 'fax') { <label>Fax number<input required [(ngModel)]="duplicate.faxNumber" name="duplicateFax" placeholder="(000) 000-0000"></label> }
|
|
1831
|
+
@if (duplicate.route === 'email') { <label>Email<input required type="email" [(ngModel)]="duplicate.email" name="duplicateEmail" placeholder="claims@payer.example"></label> }
|
|
1832
|
+
@if (duplicate.route === 'mail') { <label>Mailing address<textarea required [(ngModel)]="duplicate.mailingAddress" name="duplicateMail"></textarea></label> }
|
|
1833
|
+
<div><button type="button" (click)="panel='duplicate'">Back</button><button class="primary" type="submit" [disabled]="store.mutating() || !duplicateReady()">Send duplicate</button></div>
|
|
1834
|
+
}
|
|
1835
|
+
</form>
|
|
1836
|
+
}
|
|
1763
1837
|
@if (panel === 'submit_new_bill' && correctionInitialBill) {
|
|
1764
1838
|
<div class="correction-backdrop" (mousedown)="closeCorrectionBackdrop($event)">
|
|
1765
1839
|
<section class="correction-dialog" role="dialog" aria-modal="true" aria-label="Submit New Bill">
|
|
@@ -2250,7 +2324,7 @@ function mindBillBillTasksCell(section, row, bucketIndex, buckets) {
|
|
|
2250
2324
|
};
|
|
2251
2325
|
}
|
|
2252
2326
|
|
|
2253
|
-
//
|
|
2327
|
+
// "Bill Tasks" dashboard: one rounded, tone-colored card per
|
|
2254
2328
|
// task section, rows bucketed by age in days with colored bucket header pills,
|
|
2255
2329
|
// per-cell click-through counts, and a closing grand-total card. The pure
|
|
2256
2330
|
// aggregation lives in @mindbill/browser (buildBillTasksDashboard) so React
|