@mindbill/angular 0.16.1 → 0.18.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 +4 -0
- package/fesm2022/mindbill-angular.mjs +251 -118
- package/fesm2022/mindbill-angular.mjs.map +1 -1
- package/package.json +2 -2
- package/types/mindbill-angular.d.ts +25 -22
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { signal, computed, Input, Component, EventEmitter, Output, inject, ChangeDetectorRef, HostListener, effect, Directive } from '@angular/core';
|
|
3
|
-
import { createBillLifecycleClient, createBillReferenceClient, defaultBillReviewPayerOption, createBillSubmissionClient, REPORT_BILL_STATUS_OPTIONS, reportBillStatusContacts, BILL_TASKS_AGING_BUCKETS, createOrganizationClient } from '@mindbill/browser';
|
|
3
|
+
import { createBillLifecycleClient, createBillReferenceClient, defaultBillReviewPayerOption, createBillSubmissionClient, REPORT_BILL_STATUS_OPTIONS, reportBillStatusContacts, BILL_TASKS_AGING_BUCKETS, createOrganizationClient, organizationTaxIdWrite } from '@mindbill/browser';
|
|
4
4
|
export { REPORT_BILL_STATUS_OPTIONS, defaultBillReviewPayerOption, reportBillStatusContacts } from '@mindbill/browser';
|
|
5
5
|
import * as i1 from '@angular/common';
|
|
6
6
|
import { CommonModule } from '@angular/common';
|
|
@@ -579,6 +579,20 @@ class MindBillBillSubmissionComponent {
|
|
|
579
579
|
submissionError = new EventEmitter();
|
|
580
580
|
billChange = new EventEmitter();
|
|
581
581
|
bill = {};
|
|
582
|
+
get inlineBillingProvider() {
|
|
583
|
+
const provider = this.bill.billingProvider;
|
|
584
|
+
return provider && 'name' in provider ? provider : null;
|
|
585
|
+
}
|
|
586
|
+
setBillingTaxIdType(type) {
|
|
587
|
+
const provider = this.inlineBillingProvider;
|
|
588
|
+
if (!provider || (provider.taxIdType ?? 'EIN') === type)
|
|
589
|
+
return;
|
|
590
|
+
provider.taxIdType = type;
|
|
591
|
+
provider.taxId = '';
|
|
592
|
+
}
|
|
593
|
+
useManualBillingProvider() {
|
|
594
|
+
this.bill.billingProvider = { name: '', taxId: '', taxIdType: 'EIN', npi: '', phone: '', address: { line1: '', city: '', state: '', postalCode: '' } };
|
|
595
|
+
}
|
|
582
596
|
workingAttachments = [];
|
|
583
597
|
payerQuery = "";
|
|
584
598
|
payerResults = [];
|
|
@@ -895,12 +909,20 @@ class MindBillBillSubmissionComponent {
|
|
|
895
909
|
["claim.claimsAdministrator", this.bill.claim.claimsAdministrator.id],
|
|
896
910
|
["claim.claimsAdministrator.payerId", !this.payerSelectionRequired || this.bill.claim.claimsAdministrator.payerId],
|
|
897
911
|
["diagnoses", this.bill.diagnoses.length],
|
|
898
|
-
["billingProvider.name", this.bill.billingProvider.name], ["billingProvider.taxId", this.bill.billingProvider.taxId], ["billingProvider.npi", this.bill.billingProvider.npi], ["billingProvider.phone", this.bill.billingProvider.phone],
|
|
899
|
-
["billingProvider.address.line1", this.bill.billingProvider.address.line1], ["billingProvider.address.city", this.bill.billingProvider.address.city], ["billingProvider.address.state", this.bill.billingProvider.address.state], ["billingProvider.address.postalCode", this.bill.billingProvider.address.postalCode],
|
|
900
912
|
["renderingProvider.name", this.bill.renderingProvider.name], ["renderingProvider.npi", this.bill.renderingProvider.npi], ["renderingProvider.taxonomy", this.bill.renderingProvider.taxonomy],
|
|
901
913
|
["serviceLocation.placeOfServiceCode", this.bill.serviceLocation.placeOfServiceCode], ["serviceLocation.address.line1", this.bill.serviceLocation.address.line1], ["serviceLocation.address.city", this.bill.serviceLocation.address.city], ["serviceLocation.address.state", this.bill.serviceLocation.address.state], ["serviceLocation.address.postalCode", this.bill.serviceLocation.address.postalCode],
|
|
902
914
|
["serviceLines", this.bill.serviceLines.some((line) => required(line.code) && (line.units ?? 1) > 0)],
|
|
903
915
|
];
|
|
916
|
+
const provider = this.bill.billingProvider;
|
|
917
|
+
if ('savedProviderId' in provider) {
|
|
918
|
+
candidates.push(['billingProvider.savedProviderId', provider.savedProviderId]);
|
|
919
|
+
}
|
|
920
|
+
else if ('sourceBillId' in provider) {
|
|
921
|
+
candidates.push(['billingProvider.sourceBillId', provider.sourceBillId]);
|
|
922
|
+
}
|
|
923
|
+
else {
|
|
924
|
+
candidates.push(['billingProvider.name', provider.name], ['billingProvider.taxId', provider.taxId], ['billingProvider.npi', provider.npi], ['billingProvider.phone', provider.phone], ['billingProvider.address.line1', provider.address.line1], ['billingProvider.address.city', provider.address.city], ['billingProvider.address.state', provider.address.state], ['billingProvider.address.postalCode', provider.address.postalCode]);
|
|
925
|
+
}
|
|
904
926
|
this.invalidFields = new Set(candidates.filter(([, value]) => !value || !required(value)).map(([path]) => path));
|
|
905
927
|
if (this.invalidFields.size) {
|
|
906
928
|
this.errorMessage = `Complete ${this.invalidFields.size} highlighted required field${this.invalidFields.size === 1 ? "" : "s"} before submitting.`;
|
|
@@ -1014,14 +1036,19 @@ class MindBillBillSubmissionComponent {
|
|
|
1014
1036
|
|
|
1015
1037
|
<fieldset id="mbs-provider"><legend>Providers & place of service</legend><div class="grid">
|
|
1016
1038
|
<h3 class="wide">Billing provider</h3>
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1039
|
+
@if (inlineBillingProvider; as provider) {
|
|
1040
|
+
<label [class.invalid]="bad('billingProvider.name')">Billing provider name <b>*</b><input name="billingProvider" [(ngModel)]="provider.name"></label>
|
|
1041
|
+
<label>Tax ID type<select name="taxIdType" [ngModel]="provider.taxIdType ?? 'EIN'" (ngModelChange)="setBillingTaxIdType($event)"><option value="EIN">EIN</option><option value="SSN">SSN</option></select></label>
|
|
1042
|
+
<label [class.invalid]="bad('billingProvider.taxId')">{{ provider.taxIdType === 'SSN' ? 'SSN' : 'EIN' }} <b>*</b><input name="taxId" [(ngModel)]="provider.taxId" [type]="provider.taxIdType === 'SSN' ? 'password' : 'text'" autocomplete="off" inputmode="numeric"></label>
|
|
1043
|
+
<label [class.invalid]="bad('billingProvider.npi')">Billing NPI <b>*</b><input name="billingNpi" [(ngModel)]="provider.npi" inputmode="numeric" maxlength="10"></label>
|
|
1044
|
+
<label [class.invalid]="bad('billingProvider.phone')">Billing phone <b>*</b><input name="billingPhone" type="tel" [(ngModel)]="provider.phone"></label>
|
|
1045
|
+
<label class="wide" [class.invalid]="bad('billingProvider.address.line1')">Billing address <b>*</b><input name="billingAddress" [(ngModel)]="provider.address.line1"></label>
|
|
1046
|
+
<label [class.invalid]="bad('billingProvider.address.postalCode')">Billing ZIP <b>*</b><input name="billingZip" [(ngModel)]="provider.address.postalCode" inputmode="numeric"></label>
|
|
1047
|
+
<label [class.invalid]="bad('billingProvider.address.city')">Billing city <b>*</b><input name="billingCity" [(ngModel)]="provider.address.city"></label>
|
|
1048
|
+
<label [class.invalid]="bad('billingProvider.address.state')">Billing state <b>*</b><input name="billingState" [(ngModel)]="provider.address.state" maxlength="2"></label>
|
|
1049
|
+
} @else {
|
|
1050
|
+
<div class="wide" [class.invalid]="bad('billingProvider.savedProviderId') || bad('billingProvider.sourceBillId')"><span>Using a saved billing provider</span><small>The saved tax ID is resolved securely when you submit, without returning the SSN to this form.</small><div class="quick"><button type="button" (click)="useManualBillingProvider()">Enter a different billing provider</button></div></div>
|
|
1051
|
+
}
|
|
1025
1052
|
<h3 class="wide">Rendering provider</h3>
|
|
1026
1053
|
<label [class.invalid]="bad('renderingProvider.name')">Rendering provider name <b>*</b><input name="renderingProvider" [(ngModel)]="bill.renderingProvider.name"></label>
|
|
1027
1054
|
<label [class.invalid]="bad('renderingProvider.npi')">Rendering provider NPI <b>*</b><input name="renderingNpi" [(ngModel)]="bill.renderingProvider.npi" inputmode="numeric" maxlength="10"></label>
|
|
@@ -1073,7 +1100,7 @@ class MindBillBillSubmissionComponent {
|
|
|
1073
1100
|
<div class="submit-row"><span>{{ invalidFields.size ? 'Complete the highlighted required fields.' : 'All required billing data is ready.' }}</span><button type="submit" [disabled]="submitting">{{ submitting ? 'Submitting…' : submitLabel }}</button></div>
|
|
1074
1101
|
@if (dragActive) { <div class="drop-overlay" aria-hidden="true"><div><strong>Drop PDFs to attach</strong><span>Supporting documents are added to this submission.</span></div></div> }
|
|
1075
1102
|
</form>
|
|
1076
|
-
`, isInline: true, styles: [":host{display:block}.mbs{--danger:#c83c3c;font-family:var(--font);color:var(--t)}*{box-sizing:border-box}.intro{display:flex;justify-content:space-between;align-items:start;margin:0 0 24px}.intro h2{margin:0;font-size:24px;font-weight:600}.intro p{margin:6px 0 0;color:var(--m)}.intro>span{color:var(--m);font-size:13px}.mbs b{color:inherit}.intro b,label>b,.lookup>label>b,.diagnosis>label>b,.cell>label>b{color:var(--danger)}fieldset{border:1px solid var(--b);border-radius:var(--r);margin:0 0 22px;padding:24px 26px 26px;background:var(--s)}legend{padding:0 10px;font-size:18px;font-weight:700}.grid{display:grid;grid-template-columns:1fr 1fr;gap:20px 28px}.wide{grid-column:1/-1}h3{margin:4px 0 -4px;padding-top:12px;border-top:1px solid var(--b);font-size:16px}h3:first-child{border:0;padding-top:0}label,.lookup,.diagnosis{display:grid;gap:8px;font-size:14px;font-weight:700}.grid>label{display:flex;flex-wrap:wrap;align-content:start;align-items:center;column-gap:4px;row-gap:8px}.grid>label>input,.grid>label>select,.grid>label>small,.grid>label>mindbill-date-input{flex:0 0 100%}.grid>div.wide{display:grid;gap:8px;font-size:14px;font-weight:700}input,select{width:100%;min-height:46px;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,select:focus{outline:3px solid color-mix(in srgb,var(--a) 22%,transparent);border-color:var(--a)}.invalid input,.invalid select,.invalid-set{border-color:var(--danger)!important;background:color-mix(in srgb,var(--danger) 4%,var(--s))}.invalid>label{color:var(--danger)}small{color:var(--m);font-weight:450}.selected{color:#238655}.options{position:relative;z-index:4;max-height:300px;overflow:auto;border:1px solid var(--b);border-radius:var(--cr);background:var(--s);box-shadow:0 14px 35px #172b3730}.options button{display:grid;width:100%;gap:3px;border:0;border-bottom:1px solid var(--b);background:var(--s);padding:12px 14px;text-align:left;color:var(--t);cursor:pointer}.options button:hover{background:color-mix(in srgb,var(--a) 7%,var(--s))}.options span{color:var(--m);font-size:12px}.quick,.chips{display:flex;flex-wrap:wrap;gap:8px}.quick button,.chips button{border:1px solid var(--b);border-radius:999px;background:var(--s);padding:7px 11px;color:var(--t);font:inherit;font-size:13px;cursor:pointer}.quick .on{border-color:var(--a);color:var(--a);background:color-mix(in srgb,var(--a) 8%,var(--s))}.chips button{border-color:color-mix(in srgb,var(--a) 40%,var(--b));background:color-mix(in srgb,var(--a) 7%,var(--s));font-weight:700}.dx{display:flex;flex-wrap:wrap;gap:5px;padding-top:6px}.dx button{width:30px;height:30px;border:1px solid var(--b);border-radius:8px;background:var(--s);color:var(--m);font:inherit;font-size:13px;font-weight:750;cursor:pointer;padding:0}.dx button.on{border-color:var(--a);background:color-mix(in srgb,var(--a) 10%,var(--s));color:var(--a)}.line-head,.service-line{display:grid;grid-template-columns:1.5fr 1.35fr .8fr .5fr .7fr 36px;gap:14px;align-items:start}.line-head{padding:0 0 9px;color:var(--m);font-size:12px;font-weight:700}.service-line{border-top:1px solid var(--b);padding:12px 0}.service-line label,.service-line .cell{display:grid;gap:6px;font-size:14px;font-weight:700}.service-line strong{text-align:right;padding-top:12px}.remove{border:0;background:transparent;color:var(--m);font-size:25px;cursor:pointer}.mobile-label{display:none}.total{display:flex;justify-content:flex-end;gap:36px;border-top:1px solid var(--b);padding-top:14px;font-size:17px}.attachment{display:flex;align-items:center;justify-content:space-between;gap:16px;border:1px solid var(--b);border-radius:var(--cr);margin-bottom:10px;padding:14px 16px}.attachment.locked{border-color:#9fd6b4;background:#f3fcf6}.attachment>div:first-child{display:grid;gap:4px}.attachment span{color:var(--m);font-size:13px}.attachment-actions{display:flex;gap:8px}.attachment button{border:1px solid var(--b);border-radius:var(--cr);background:var(--s);padding:8px 12px;color:var(--t);font-weight:700;cursor:pointer}.dropzone{position:relative;display:grid;min-height:170px;place-content:center;gap:8px;border:2px dashed color-mix(in srgb,var(--m) 60%,transparent);border-radius:var(--cr);text-align:center;cursor:pointer;transition:border-color .15s,background .15s}.dropzone.drag-active{border-color:var(--a);background:color-mix(in srgb,var(--a) 8%,var(--s))}.dropzone input{position:absolute;inset:0;opacity:0;cursor:pointer}.dropzone span{color:var(--m);font-weight:450}.drop-overlay{position:fixed;inset:0;z-index:60;display:grid;place-content:center;background:color-mix(in srgb,var(--a) 14%,#ffffffd9);pointer-events:none}.drop-overlay div{display:grid;gap:6px;border:2px dashed var(--a);border-radius:var(--r);background:var(--s);padding:34px 44px;text-align:center;box-shadow:0 24px 60px #172b3740}.drop-overlay strong{font-size:19px}.drop-overlay span{color:var(--m)}.error{margin:0 0 14px;border-left:4px solid var(--danger);border-radius:var(--cr);background:color-mix(in srgb,var(--danger) 10%,var(--s));padding:14px;color:var(--danger)}.submit-row{position:sticky;bottom:0;z-index:3;display:flex;align-items:center;justify-content:space-between;border:1px solid var(--b);border-radius:var(--r);background:color-mix(in srgb,var(--s) 96%,transparent);box-shadow:0 -8px 24px #172b3718;padding:14px 18px}.submit-row>span{color:#43835f}.submit-row button{min-width:190px;border:0;border-radius:var(--cr);background:var(--a);color:var(--ac);padding:12px 24px;font:inherit;font-weight:800;cursor:pointer}.submit-row button:disabled{opacity:.6;cursor:wait}@media(max-width:760px){fieldset{padding:18px 16px}.grid{grid-template-columns:1fr}.wide{grid-column:auto}.intro{display:grid;gap:10px}.line-head{display:none}.service-line{grid-template-columns:1fr 1fr}.service-line>*{grid-column:1/-1}.service-line label:nth-child(3){grid-column:1}.service-line>strong{grid-column:2;grid-row:3;text-align:left}.service-line>.remove{grid-column:1/-1}.mobile-label{display:block;color:var(--m);font-size:12px}.attachment{align-items:flex-start}.attachment-actions{align-items:center}.submit-row>span{display:none}.submit-row button{width:100%}}\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.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { 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: "component", type: MindBillComboBoxComponent, selector: "mindbill-combo-box", inputs: ["value", "placeholder", "options", "disabled", "loading", "loadingMore", "invalid", "preserveValueOnOpen", "ariaLabel", "createOption"], outputs: ["opened", "queryChange", "endReached", "selected"] }, { kind: "component", type: MindBillDateInputComponent, selector: "mindbill-date-input", inputs: ["value", "disabled", "ariaLabel"], outputs: ["valueChange"] }, { kind: "pipe", type: i1.CurrencyPipe, name: "currency" }] });
|
|
1103
|
+
`, isInline: true, styles: [":host{display:block}.mbs{--danger:#c83c3c;font-family:var(--font);color:var(--t)}*{box-sizing:border-box}.intro{display:flex;justify-content:space-between;align-items:start;margin:0 0 24px}.intro h2{margin:0;font-size:24px;font-weight:600}.intro p{margin:6px 0 0;color:var(--m)}.intro>span{color:var(--m);font-size:13px}.mbs b{color:inherit}.intro b,label>b,.lookup>label>b,.diagnosis>label>b,.cell>label>b{color:var(--danger)}fieldset{border:1px solid var(--b);border-radius:var(--r);margin:0 0 22px;padding:24px 26px 26px;background:var(--s)}legend{padding:0 10px;font-size:18px;font-weight:700}.grid{display:grid;grid-template-columns:1fr 1fr;gap:20px 28px}.wide{grid-column:1/-1}h3{margin:4px 0 -4px;padding-top:12px;border-top:1px solid var(--b);font-size:16px}h3:first-child{border:0;padding-top:0}label,.lookup,.diagnosis{display:grid;gap:8px;font-size:14px;font-weight:700}.grid>label{display:flex;flex-wrap:wrap;align-content:start;align-items:center;column-gap:4px;row-gap:8px}.grid>label>input,.grid>label>select,.grid>label>small,.grid>label>mindbill-date-input{flex:0 0 100%}.grid>div.wide{display:grid;gap:8px;font-size:14px;font-weight:700}input,select{width:100%;min-height:46px;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,select:focus{outline:3px solid color-mix(in srgb,var(--a) 22%,transparent);border-color:var(--a)}.invalid input,.invalid select,.invalid-set{border-color:var(--danger)!important;background:color-mix(in srgb,var(--danger) 4%,var(--s))}.invalid>label{color:var(--danger)}small{color:var(--m);font-weight:450}.selected{color:#238655}.options{position:relative;z-index:4;max-height:300px;overflow:auto;border:1px solid var(--b);border-radius:var(--cr);background:var(--s);box-shadow:0 14px 35px #172b3730}.options button{display:grid;width:100%;gap:3px;border:0;border-bottom:1px solid var(--b);background:var(--s);padding:12px 14px;text-align:left;color:var(--t);cursor:pointer}.options button:hover{background:color-mix(in srgb,var(--a) 7%,var(--s))}.options span{color:var(--m);font-size:12px}.quick,.chips{display:flex;flex-wrap:wrap;gap:8px}.quick button,.chips button{border:1px solid var(--b);border-radius:999px;background:var(--s);padding:7px 11px;color:var(--t);font:inherit;font-size:13px;cursor:pointer}.quick .on{border-color:var(--a);color:var(--a);background:color-mix(in srgb,var(--a) 8%,var(--s))}.chips button{border-color:color-mix(in srgb,var(--a) 40%,var(--b));background:color-mix(in srgb,var(--a) 7%,var(--s));font-weight:700}.dx{display:flex;flex-wrap:wrap;gap:5px;padding-top:6px}.dx button{width:30px;height:30px;border:1px solid var(--b);border-radius:8px;background:var(--s);color:var(--m);font:inherit;font-size:13px;font-weight:750;cursor:pointer;padding:0}.dx button.on{border-color:var(--a);background:color-mix(in srgb,var(--a) 10%,var(--s));color:var(--a)}.line-head,.service-line{display:grid;grid-template-columns:1.5fr 1.35fr .8fr .5fr .7fr 36px;gap:14px;align-items:start}.line-head{padding:0 0 9px;color:var(--m);font-size:12px;font-weight:700}.service-line{border-top:1px solid var(--b);padding:12px 0}.service-line label,.service-line .cell{display:grid;gap:6px;font-size:14px;font-weight:700}.service-line strong{text-align:right;padding-top:12px}.remove{border:0;background:transparent;color:var(--m);font-size:25px;cursor:pointer}.mobile-label{display:none}.total{display:flex;justify-content:flex-end;gap:36px;border-top:1px solid var(--b);padding-top:14px;font-size:17px}.attachment{display:flex;align-items:center;justify-content:space-between;gap:16px;border:1px solid var(--b);border-radius:var(--cr);margin-bottom:10px;padding:14px 16px}.attachment.locked{border-color:#9fd6b4;background:#f3fcf6}.attachment>div:first-child{display:grid;gap:4px}.attachment span{color:var(--m);font-size:13px}.attachment-actions{display:flex;gap:8px}.attachment button{border:1px solid var(--b);border-radius:var(--cr);background:var(--s);padding:8px 12px;color:var(--t);font-weight:700;cursor:pointer}.dropzone{position:relative;display:grid;min-height:170px;place-content:center;gap:8px;border:2px dashed color-mix(in srgb,var(--m) 60%,transparent);border-radius:var(--cr);text-align:center;cursor:pointer;transition:border-color .15s,background .15s}.dropzone.drag-active{border-color:var(--a);background:color-mix(in srgb,var(--a) 8%,var(--s))}.dropzone input{position:absolute;inset:0;opacity:0;cursor:pointer}.dropzone span{color:var(--m);font-weight:450}.drop-overlay{position:fixed;inset:0;z-index:60;display:grid;place-content:center;background:color-mix(in srgb,var(--a) 14%,#ffffffd9);pointer-events:none}.drop-overlay div{display:grid;gap:6px;border:2px dashed var(--a);border-radius:var(--r);background:var(--s);padding:34px 44px;text-align:center;box-shadow:0 24px 60px #172b3740}.drop-overlay strong{font-size:19px}.drop-overlay span{color:var(--m)}.error{margin:0 0 14px;border-left:4px solid var(--danger);border-radius:var(--cr);background:color-mix(in srgb,var(--danger) 10%,var(--s));padding:14px;color:var(--danger)}.submit-row{position:sticky;bottom:0;z-index:3;display:flex;align-items:center;justify-content:space-between;border:1px solid var(--b);border-radius:var(--r);background:color-mix(in srgb,var(--s) 96%,transparent);box-shadow:0 -8px 24px #172b3718;padding:14px 18px}.submit-row>span{color:#43835f}.submit-row button{min-width:190px;border:0;border-radius:var(--cr);background:var(--a);color:var(--ac);padding:12px 24px;font:inherit;font-weight:800;cursor:pointer}.submit-row button:disabled{opacity:.6;cursor:wait}@media(max-width:760px){fieldset{padding:18px 16px}.grid{grid-template-columns:1fr}.wide{grid-column:auto}.intro{display:grid;gap:10px}.line-head{display:none}.service-line{grid-template-columns:1fr 1fr}.service-line>*{grid-column:1/-1}.service-line label:nth-child(3){grid-column:1}.service-line>strong{grid-column:2;grid-row:3;text-align:left}.service-line>.remove{grid-column:1/-1}.mobile-label{display:block;color:var(--m);font-size:12px}.attachment{align-items:flex-start}.attachment-actions{align-items:center}.submit-row>span{display:none}.submit-row button{width:100%}}\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.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: "component", type: MindBillComboBoxComponent, selector: "mindbill-combo-box", inputs: ["value", "placeholder", "options", "disabled", "loading", "loadingMore", "invalid", "preserveValueOnOpen", "ariaLabel", "createOption"], outputs: ["opened", "queryChange", "endReached", "selected"] }, { kind: "component", type: MindBillDateInputComponent, selector: "mindbill-date-input", inputs: ["value", "disabled", "ariaLabel"], outputs: ["valueChange"] }, { kind: "pipe", type: i1.CurrencyPipe, name: "currency" }] });
|
|
1077
1104
|
}
|
|
1078
1105
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: MindBillBillSubmissionComponent, decorators: [{
|
|
1079
1106
|
type: Component,
|
|
@@ -1123,14 +1150,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
1123
1150
|
|
|
1124
1151
|
<fieldset id="mbs-provider"><legend>Providers & place of service</legend><div class="grid">
|
|
1125
1152
|
<h3 class="wide">Billing provider</h3>
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1153
|
+
@if (inlineBillingProvider; as provider) {
|
|
1154
|
+
<label [class.invalid]="bad('billingProvider.name')">Billing provider name <b>*</b><input name="billingProvider" [(ngModel)]="provider.name"></label>
|
|
1155
|
+
<label>Tax ID type<select name="taxIdType" [ngModel]="provider.taxIdType ?? 'EIN'" (ngModelChange)="setBillingTaxIdType($event)"><option value="EIN">EIN</option><option value="SSN">SSN</option></select></label>
|
|
1156
|
+
<label [class.invalid]="bad('billingProvider.taxId')">{{ provider.taxIdType === 'SSN' ? 'SSN' : 'EIN' }} <b>*</b><input name="taxId" [(ngModel)]="provider.taxId" [type]="provider.taxIdType === 'SSN' ? 'password' : 'text'" autocomplete="off" inputmode="numeric"></label>
|
|
1157
|
+
<label [class.invalid]="bad('billingProvider.npi')">Billing NPI <b>*</b><input name="billingNpi" [(ngModel)]="provider.npi" inputmode="numeric" maxlength="10"></label>
|
|
1158
|
+
<label [class.invalid]="bad('billingProvider.phone')">Billing phone <b>*</b><input name="billingPhone" type="tel" [(ngModel)]="provider.phone"></label>
|
|
1159
|
+
<label class="wide" [class.invalid]="bad('billingProvider.address.line1')">Billing address <b>*</b><input name="billingAddress" [(ngModel)]="provider.address.line1"></label>
|
|
1160
|
+
<label [class.invalid]="bad('billingProvider.address.postalCode')">Billing ZIP <b>*</b><input name="billingZip" [(ngModel)]="provider.address.postalCode" inputmode="numeric"></label>
|
|
1161
|
+
<label [class.invalid]="bad('billingProvider.address.city')">Billing city <b>*</b><input name="billingCity" [(ngModel)]="provider.address.city"></label>
|
|
1162
|
+
<label [class.invalid]="bad('billingProvider.address.state')">Billing state <b>*</b><input name="billingState" [(ngModel)]="provider.address.state" maxlength="2"></label>
|
|
1163
|
+
} @else {
|
|
1164
|
+
<div class="wide" [class.invalid]="bad('billingProvider.savedProviderId') || bad('billingProvider.sourceBillId')"><span>Using a saved billing provider</span><small>The saved tax ID is resolved securely when you submit, without returning the SSN to this form.</small><div class="quick"><button type="button" (click)="useManualBillingProvider()">Enter a different billing provider</button></div></div>
|
|
1165
|
+
}
|
|
1134
1166
|
<h3 class="wide">Rendering provider</h3>
|
|
1135
1167
|
<label [class.invalid]="bad('renderingProvider.name')">Rendering provider name <b>*</b><input name="renderingProvider" [(ngModel)]="bill.renderingProvider.name"></label>
|
|
1136
1168
|
<label [class.invalid]="bad('renderingProvider.npi')">Rendering provider NPI <b>*</b><input name="renderingNpi" [(ngModel)]="bill.renderingProvider.npi" inputmode="numeric" maxlength="10"></label>
|
|
@@ -1248,11 +1280,12 @@ class MindBillBillLifecycleComponent {
|
|
|
1248
1280
|
payment = { amount: 0, method: "check", depositDate: new Date().toISOString().slice(0, 10) };
|
|
1249
1281
|
review = { reason: "", payerClaimControlNumber: "", disputedAmount: 0 };
|
|
1250
1282
|
reportStatusOptions = REPORT_BILL_STATUS_OPTIONS;
|
|
1283
|
+
report = { status: null, company: "", representativeName: "", representativeRole: "", phone: "", callReference: "", note: "" };
|
|
1284
|
+
reportContactSummary = "";
|
|
1251
1285
|
duplicateDelivery = null;
|
|
1252
1286
|
duplicateDeliveryError = "";
|
|
1287
|
+
duplicateDraftInput = null;
|
|
1253
1288
|
duplicate = { route: "ebill", faxNumber: "", email: "", mailingAddress: "" };
|
|
1254
|
-
report = { status: null, company: "", representativeName: "", representativeRole: "", phone: "", callReference: "", note: "" };
|
|
1255
|
-
reportContactSummary = "";
|
|
1256
1289
|
correctionInitialBill = null;
|
|
1257
1290
|
correctionAttachments = [];
|
|
1258
1291
|
correctionAttentionFields = [];
|
|
@@ -1300,57 +1333,12 @@ class MindBillBillLifecycleComponent {
|
|
|
1300
1333
|
else if (action === "close")
|
|
1301
1334
|
this.panel = "close";
|
|
1302
1335
|
else if (action === "send_duplicate")
|
|
1303
|
-
this.
|
|
1336
|
+
this.prepareDuplicate(data);
|
|
1304
1337
|
else if (action === "report_bill_status")
|
|
1305
1338
|
this.beginReportStatus(data);
|
|
1306
1339
|
else if (action === "view_eor" && data.eors[0])
|
|
1307
1340
|
void this.openEor(data.eors[0].id, data.eors[0].filename);
|
|
1308
1341
|
}
|
|
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
1342
|
beginReportStatus(data) {
|
|
1355
1343
|
const contacts = reportBillStatusContacts(data.delivery);
|
|
1356
1344
|
const parts = [];
|
|
@@ -1385,7 +1373,7 @@ class MindBillBillLifecycleComponent {
|
|
|
1385
1373
|
async openAttachment(id, filename) { this.openBlob(await this.store.getAttachment(id), filename); }
|
|
1386
1374
|
async openEor(id, filename) { this.openBlob(await this.store.getEor(id), filename); }
|
|
1387
1375
|
async postPayment() { await this.store.postPayment(this.payment); this.panel = ""; this.notice = "Payment posted."; }
|
|
1388
|
-
async submitReview() { await this.store.submitSecondReview({ ...this.review,
|
|
1376
|
+
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
1377
|
async closeBill() { if (!this.closeReason.trim())
|
|
1390
1378
|
return; await this.store.closeBill({ reason: this.closeReason }); this.panel = ""; this.notice = "Bill closed."; }
|
|
1391
1379
|
resubmitFromForm = async (input) => {
|
|
@@ -1397,6 +1385,66 @@ class MindBillBillLifecycleComponent {
|
|
|
1397
1385
|
return { billId: data.bill.id, bill: { id: data.bill.id, state: data.lifecycle.state } };
|
|
1398
1386
|
};
|
|
1399
1387
|
finishCorrection() { this.panel = ""; this.correctionReason = ""; this.notice = "Corrected submission sent."; }
|
|
1388
|
+
duplicateFromForm = async (input) => {
|
|
1389
|
+
this.duplicateDraftInput = input;
|
|
1390
|
+
this.panel = "duplicate_route";
|
|
1391
|
+
await this.loadDuplicateDelivery();
|
|
1392
|
+
const billId = this.store.data()?.bill.id || this.billId;
|
|
1393
|
+
return { billId, bill: { id: billId, state: "draft" } };
|
|
1394
|
+
};
|
|
1395
|
+
finishDuplicate() { }
|
|
1396
|
+
async loadDuplicateDelivery() {
|
|
1397
|
+
this.duplicateDeliveryError = "";
|
|
1398
|
+
if (this.duplicateDelivery)
|
|
1399
|
+
return;
|
|
1400
|
+
try {
|
|
1401
|
+
const delivery = await this.store.getDeliveryOptions();
|
|
1402
|
+
this.duplicateDelivery = delivery;
|
|
1403
|
+
this.duplicate.route = delivery.recommended.route;
|
|
1404
|
+
this.duplicate.faxNumber = delivery.contacts.faxNumber || "";
|
|
1405
|
+
this.duplicate.email = delivery.contacts.claimsEmail || "";
|
|
1406
|
+
this.duplicate.mailingAddress = delivery.contacts.mailingAddress || "";
|
|
1407
|
+
}
|
|
1408
|
+
catch (cause) {
|
|
1409
|
+
this.duplicateDeliveryError = cause instanceof Error ? cause.message : "Delivery options could not be loaded.";
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
duplicateRoutes() {
|
|
1413
|
+
const seen = new Set();
|
|
1414
|
+
return (this.duplicateDelivery?.options ?? []).filter((option) => {
|
|
1415
|
+
if (seen.has(option.route))
|
|
1416
|
+
return false;
|
|
1417
|
+
seen.add(option.route);
|
|
1418
|
+
return true;
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1421
|
+
duplicateReady() {
|
|
1422
|
+
if (!this.duplicateDraftInput)
|
|
1423
|
+
return false;
|
|
1424
|
+
if (this.duplicate.route === "fax")
|
|
1425
|
+
return this.duplicate.faxNumber.replace(/\D/g, "").length >= 10;
|
|
1426
|
+
if (this.duplicate.route === "email")
|
|
1427
|
+
return this.duplicate.email.includes("@");
|
|
1428
|
+
if (this.duplicate.route === "mail")
|
|
1429
|
+
return this.duplicate.mailingAddress.trim().length > 2;
|
|
1430
|
+
return true;
|
|
1431
|
+
}
|
|
1432
|
+
async sendDuplicate() {
|
|
1433
|
+
if (!this.duplicateDelivery || !this.duplicateDraftInput || !this.duplicateReady())
|
|
1434
|
+
return;
|
|
1435
|
+
const route = this.duplicate.route;
|
|
1436
|
+
const destination = route === "fax" ? { faxNumber: this.duplicate.faxNumber.trim() }
|
|
1437
|
+
: route === "email" ? { email: this.duplicate.email.trim() }
|
|
1438
|
+
: route === "mail" ? { mailingAddress: this.duplicate.mailingAddress.trim() }
|
|
1439
|
+
: null;
|
|
1440
|
+
await this.store.sendDuplicateBill({
|
|
1441
|
+
bill: this.duplicateDraftInput.bill,
|
|
1442
|
+
...(this.duplicateDraftInput.documents?.length ? { documents: this.duplicateDraftInput.documents } : {}),
|
|
1443
|
+
submission: { route, ...(destination ? { destination } : {}) },
|
|
1444
|
+
});
|
|
1445
|
+
this.panel = "";
|
|
1446
|
+
this.notice = "Duplicate bill sent.";
|
|
1447
|
+
}
|
|
1400
1448
|
// "Submit New Bill" from a CLOSED bill: same prefilled submission form as the
|
|
1401
1449
|
// correction flow, but the server keeps the closed bill closed and creates a
|
|
1402
1450
|
// fresh original linked to it (both records chain in the submissions timeline).
|
|
@@ -1425,6 +1473,22 @@ class MindBillBillLifecycleComponent {
|
|
|
1425
1473
|
this.correctionReason = "";
|
|
1426
1474
|
this.panel = "resubmit";
|
|
1427
1475
|
}
|
|
1476
|
+
prepareDuplicate(data) {
|
|
1477
|
+
this.correctionInitialBill = correctionBill(data);
|
|
1478
|
+
this.correctionAttachments = data.bill.attachments.map((attachment) => ({
|
|
1479
|
+
filename: attachment.filename,
|
|
1480
|
+
documentType: correctionDocumentType(attachment.documentType),
|
|
1481
|
+
...(attachment.description ? { description: attachment.description } : {}),
|
|
1482
|
+
...(attachment.reportType ? { reportTypeCode: attachment.reportType } : {}),
|
|
1483
|
+
loadBlob: () => this.store.getAttachment(attachment.id),
|
|
1484
|
+
...(attachment.documentType === "w9" ? { locked: true, badge: "Auto-attached" } : {}),
|
|
1485
|
+
}));
|
|
1486
|
+
this.correctionAttentionFields = [];
|
|
1487
|
+
this.duplicateDraftInput = null;
|
|
1488
|
+
this.duplicateDelivery = null;
|
|
1489
|
+
this.duplicateDeliveryError = "";
|
|
1490
|
+
this.panel = "duplicate";
|
|
1491
|
+
}
|
|
1428
1492
|
prepareNewBill(data) {
|
|
1429
1493
|
this.correctionInitialBill = correctionBill(data);
|
|
1430
1494
|
this.correctionAttachments = data.bill.attachments.map((attachment) => ({
|
|
@@ -1526,22 +1590,6 @@ class MindBillBillLifecycleComponent {
|
|
|
1526
1590
|
@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
1591
|
@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
1592
|
@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
1593
|
@if (panel === 'report_status') {
|
|
1546
1594
|
<form class="card action-form" (submit)="$event.preventDefault(); reportStatus()">
|
|
1547
1595
|
<h3>Report Bill Status</h3>
|
|
@@ -1587,6 +1635,43 @@ class MindBillBillLifecycleComponent {
|
|
|
1587
1635
|
</section>
|
|
1588
1636
|
</div>
|
|
1589
1637
|
}
|
|
1638
|
+
@if (panel === 'duplicate' && correctionInitialBill) {
|
|
1639
|
+
<div class="correction-backdrop" (mousedown)="closeCorrectionBackdrop($event)">
|
|
1640
|
+
<section class="correction-dialog" role="dialog" aria-modal="true" aria-label="Send duplicate bill">
|
|
1641
|
+
<button type="button" class="dialog-close" aria-label="Close" (click)="panel=''">×</button>
|
|
1642
|
+
<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>
|
|
1643
|
+
<mindbill-bill-submission
|
|
1644
|
+
[initialBill]="correctionInitialBill"
|
|
1645
|
+
[attachments]="correctionAttachments"
|
|
1646
|
+
[appearance]="appearance"
|
|
1647
|
+
[sessionEndpoint]="sessionEndpoint"
|
|
1648
|
+
[getSession]="getSession"
|
|
1649
|
+
[apiBaseUrl]="apiBaseUrl"
|
|
1650
|
+
[submitter]="duplicateFromForm"
|
|
1651
|
+
heading="Duplicate bill information"
|
|
1652
|
+
description="Review every field. The final step confirms the payer delivery route before the duplicate is sent."
|
|
1653
|
+
submitLabel="Continue to delivery"
|
|
1654
|
+
(submitted)="finishDuplicate()"
|
|
1655
|
+
/>
|
|
1656
|
+
</section>
|
|
1657
|
+
</div>
|
|
1658
|
+
}
|
|
1659
|
+
@if (panel === 'duplicate_route') {
|
|
1660
|
+
<form class="card action-form" (submit)="$event.preventDefault(); sendDuplicate()">
|
|
1661
|
+
<h3>Confirm duplicate bill delivery</h3>
|
|
1662
|
+
@if (!duplicateDelivery) {
|
|
1663
|
+
<p class="muted">{{ duplicateDeliveryError || 'Loading delivery options…' }}</p>
|
|
1664
|
+
<div><button type="button" (click)="panel='duplicate'">Back</button>@if (duplicateDeliveryError) { <button class="primary" type="button" (click)="loadDuplicateDelivery()">Try again</button> }</div>
|
|
1665
|
+
} @else {
|
|
1666
|
+
<p class="muted">Confirm how this edited duplicate will be delivered to {{ duplicateDelivery.payerName }}.</p>
|
|
1667
|
+
<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>
|
|
1668
|
+
@if (duplicate.route === 'fax') { <label>Fax number<input required [(ngModel)]="duplicate.faxNumber" name="duplicateFax" placeholder="(000) 000-0000"></label> }
|
|
1669
|
+
@if (duplicate.route === 'email') { <label>Email<input required type="email" [(ngModel)]="duplicate.email" name="duplicateEmail" placeholder="claims@payer.example"></label> }
|
|
1670
|
+
@if (duplicate.route === 'mail') { <label>Mailing address<textarea required [(ngModel)]="duplicate.mailingAddress" name="duplicateMail"></textarea></label> }
|
|
1671
|
+
<div><button type="button" (click)="panel='duplicate'">Back</button><button class="primary" type="submit" [disabled]="store.mutating() || !duplicateReady()">Send duplicate</button></div>
|
|
1672
|
+
}
|
|
1673
|
+
</form>
|
|
1674
|
+
}
|
|
1590
1675
|
@if (panel === 'submit_new_bill' && correctionInitialBill) {
|
|
1591
1676
|
<div class="correction-backdrop" (mousedown)="closeCorrectionBackdrop($event)">
|
|
1592
1677
|
<section class="correction-dialog" role="dialog" aria-modal="true" aria-label="Submit New Bill">
|
|
@@ -1699,22 +1784,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
1699
1784
|
@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
1785
|
@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
1786
|
@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
1787
|
@if (panel === 'report_status') {
|
|
1719
1788
|
<form class="card action-form" (submit)="$event.preventDefault(); reportStatus()">
|
|
1720
1789
|
<h3>Report Bill Status</h3>
|
|
@@ -1760,6 +1829,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
1760
1829
|
</section>
|
|
1761
1830
|
</div>
|
|
1762
1831
|
}
|
|
1832
|
+
@if (panel === 'duplicate' && correctionInitialBill) {
|
|
1833
|
+
<div class="correction-backdrop" (mousedown)="closeCorrectionBackdrop($event)">
|
|
1834
|
+
<section class="correction-dialog" role="dialog" aria-modal="true" aria-label="Send duplicate bill">
|
|
1835
|
+
<button type="button" class="dialog-close" aria-label="Close" (click)="panel=''">×</button>
|
|
1836
|
+
<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>
|
|
1837
|
+
<mindbill-bill-submission
|
|
1838
|
+
[initialBill]="correctionInitialBill"
|
|
1839
|
+
[attachments]="correctionAttachments"
|
|
1840
|
+
[appearance]="appearance"
|
|
1841
|
+
[sessionEndpoint]="sessionEndpoint"
|
|
1842
|
+
[getSession]="getSession"
|
|
1843
|
+
[apiBaseUrl]="apiBaseUrl"
|
|
1844
|
+
[submitter]="duplicateFromForm"
|
|
1845
|
+
heading="Duplicate bill information"
|
|
1846
|
+
description="Review every field. The final step confirms the payer delivery route before the duplicate is sent."
|
|
1847
|
+
submitLabel="Continue to delivery"
|
|
1848
|
+
(submitted)="finishDuplicate()"
|
|
1849
|
+
/>
|
|
1850
|
+
</section>
|
|
1851
|
+
</div>
|
|
1852
|
+
}
|
|
1853
|
+
@if (panel === 'duplicate_route') {
|
|
1854
|
+
<form class="card action-form" (submit)="$event.preventDefault(); sendDuplicate()">
|
|
1855
|
+
<h3>Confirm duplicate bill delivery</h3>
|
|
1856
|
+
@if (!duplicateDelivery) {
|
|
1857
|
+
<p class="muted">{{ duplicateDeliveryError || 'Loading delivery options…' }}</p>
|
|
1858
|
+
<div><button type="button" (click)="panel='duplicate'">Back</button>@if (duplicateDeliveryError) { <button class="primary" type="button" (click)="loadDuplicateDelivery()">Try again</button> }</div>
|
|
1859
|
+
} @else {
|
|
1860
|
+
<p class="muted">Confirm how this edited duplicate will be delivered to {{ duplicateDelivery.payerName }}.</p>
|
|
1861
|
+
<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>
|
|
1862
|
+
@if (duplicate.route === 'fax') { <label>Fax number<input required [(ngModel)]="duplicate.faxNumber" name="duplicateFax" placeholder="(000) 000-0000"></label> }
|
|
1863
|
+
@if (duplicate.route === 'email') { <label>Email<input required type="email" [(ngModel)]="duplicate.email" name="duplicateEmail" placeholder="claims@payer.example"></label> }
|
|
1864
|
+
@if (duplicate.route === 'mail') { <label>Mailing address<textarea required [(ngModel)]="duplicate.mailingAddress" name="duplicateMail"></textarea></label> }
|
|
1865
|
+
<div><button type="button" (click)="panel='duplicate'">Back</button><button class="primary" type="submit" [disabled]="store.mutating() || !duplicateReady()">Send duplicate</button></div>
|
|
1866
|
+
}
|
|
1867
|
+
</form>
|
|
1868
|
+
}
|
|
1763
1869
|
@if (panel === 'submit_new_bill' && correctionInitialBill) {
|
|
1764
1870
|
<div class="correction-backdrop" (mousedown)="closeCorrectionBackdrop($event)">
|
|
1765
1871
|
<section class="correction-dialog" role="dialog" aria-modal="true" aria-label="Submit New Bill">
|
|
@@ -1826,8 +1932,9 @@ function correctionBill(data) {
|
|
|
1826
1932
|
claimsAdministrator: { id: data.injury.claimsAdminId || "", name: data.injury.claimsAdminName || "" },
|
|
1827
1933
|
},
|
|
1828
1934
|
service: { date: data.bill.dos, ...(data.bill.dosEnd !== undefined ? { endDate: data.bill.dosEnd } : {}), ...(data.bill.authorizationNumber !== undefined ? { authorizationNumber: data.bill.authorizationNumber } : {}) },
|
|
1829
|
-
billingProvider: {
|
|
1935
|
+
billingProvider: billing?.taxIdType === 'SSN' && billing.taxIdConfigured ? { sourceBillId: data.bill.id } : {
|
|
1830
1936
|
name: billing?.name || "", taxId: billing?.taxId || "", npi: billing?.npi || "", phone: billing?.phone || "",
|
|
1937
|
+
...(billing?.taxIdType ? { taxIdType: billing.taxIdType } : {}),
|
|
1831
1938
|
address: { line1: billing?.billingStreet || "", city: billing?.billingCity || "", state: billing?.billingState || "", postalCode: billing?.billingZip || "" },
|
|
1832
1939
|
},
|
|
1833
1940
|
renderingProvider: {
|
|
@@ -2560,7 +2667,7 @@ class MindBillOrganizationOnboardingComponent {
|
|
|
2560
2667
|
step = "practice";
|
|
2561
2668
|
saving = false;
|
|
2562
2669
|
saved = {};
|
|
2563
|
-
identity = { name: "", legalName: "", taxId: "", npi: "", phone: "", email: "" };
|
|
2670
|
+
identity = { name: "", legalName: "", taxId: "", taxIdType: "EIN", npi: "", phone: "", email: "" };
|
|
2564
2671
|
provider = { name: "", taxId: "", npi: "", billType: "Professional", phone: "", billingStreet: "", billingCity: "", billingState: "", billingZip: "" };
|
|
2565
2672
|
locations = [{ name: "", street: "", city: "", state: "", zip: "", isPrimary: false }];
|
|
2566
2673
|
w9File = null;
|
|
@@ -2595,12 +2702,15 @@ class MindBillOrganizationOnboardingComponent {
|
|
|
2595
2702
|
adoptProfile(profile) {
|
|
2596
2703
|
this.profile = profile;
|
|
2597
2704
|
this.identity = {
|
|
2598
|
-
name: profile.practiceIdentity.name ?? this.identity.name,
|
|
2599
|
-
legalName: profile.practiceIdentity.legalName ?? this.identity.legalName,
|
|
2600
|
-
taxId: profile.practiceIdentity.taxId ??
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2705
|
+
name: profile.practiceIdentity.name ?? this.identity.name ?? '',
|
|
2706
|
+
legalName: profile.practiceIdentity.legalName ?? this.identity.legalName ?? '',
|
|
2707
|
+
taxId: profile.practiceIdentity.taxId ?? '',
|
|
2708
|
+
taxIdType: profile.practiceIdentity.taxIdType ?? 'EIN',
|
|
2709
|
+
taxIdLast4: profile.practiceIdentity.taxIdLast4 ?? '',
|
|
2710
|
+
taxIdConfigured: profile.practiceIdentity.taxIdConfigured ?? false,
|
|
2711
|
+
npi: profile.practiceIdentity.npi ?? this.identity.npi ?? '',
|
|
2712
|
+
phone: profile.practiceIdentity.phone ?? this.identity.phone ?? '',
|
|
2713
|
+
email: profile.practiceIdentity.email ?? this.identity.email ?? '',
|
|
2604
2714
|
};
|
|
2605
2715
|
if (profile.billingProviders[0])
|
|
2606
2716
|
this.provider = { billType: "Professional", ...profile.billingProviders[0] };
|
|
@@ -2647,12 +2757,23 @@ class MindBillOrganizationOnboardingComponent {
|
|
|
2647
2757
|
}
|
|
2648
2758
|
savePractice() {
|
|
2649
2759
|
void this.run(() => this.client.saveBillingProfile({
|
|
2650
|
-
practiceIdentity: this.identity,
|
|
2651
|
-
...(this.provider.name.trim() || this.provider.taxId
|
|
2652
|
-
? { billingProviders: [this.provider] }
|
|
2760
|
+
practiceIdentity: organizationTaxIdWrite(this.identity),
|
|
2761
|
+
...(this.provider.id || this.provider.name.trim() || this.provider.taxId?.trim() || this.provider.npi.trim()
|
|
2762
|
+
? { billingProviders: [organizationTaxIdWrite(this.provider)] }
|
|
2653
2763
|
: {}),
|
|
2654
2764
|
}), "practice");
|
|
2655
2765
|
}
|
|
2766
|
+
setTaxIdType(value, type) {
|
|
2767
|
+
if ((value.taxIdType ?? 'EIN') === type)
|
|
2768
|
+
return;
|
|
2769
|
+
value.taxIdType = type;
|
|
2770
|
+
this.clearTaxId(value);
|
|
2771
|
+
}
|
|
2772
|
+
clearTaxId(value) {
|
|
2773
|
+
value.taxId = '';
|
|
2774
|
+
value.taxIdLast4 = '';
|
|
2775
|
+
value.taxIdConfigured = false;
|
|
2776
|
+
}
|
|
2656
2777
|
saveLocations() {
|
|
2657
2778
|
void this.run(() => this.client.saveLocations(this.locations.filter((item) => item.name.trim() || item.street.trim())), "locations");
|
|
2658
2779
|
}
|
|
@@ -2682,7 +2803,10 @@ class MindBillOrganizationOnboardingComponent {
|
|
|
2682
2803
|
<div class="grid">
|
|
2683
2804
|
<label>Practice name<input [(ngModel)]="identity.name" [disabled]="saving"></label>
|
|
2684
2805
|
<label>Legal name<input [(ngModel)]="identity.legalName" [disabled]="saving"></label>
|
|
2685
|
-
<label>
|
|
2806
|
+
<label>Practice tax ID type<select [ngModel]="identity.taxIdType ?? 'EIN'" (ngModelChange)="setTaxIdType(identity, $event)" [disabled]="saving"><option value="EIN">EIN</option><option value="SSN">SSN</option></select></label>
|
|
2807
|
+
<div class="tax-id"><label>{{ identity.taxIdType === 'SSN' ? 'Practice SSN' : 'Practice EIN' }}<input [(ngModel)]="identity.taxId" [type]="identity.taxIdType === 'SSN' ? 'password' : 'text'" autocomplete="off" inputmode="numeric" [disabled]="saving"></label>
|
|
2808
|
+
@if (identity.taxIdType === 'SSN' && identity.taxIdConfigured) { <small>SSN ending in {{ identity.taxIdLast4 }} is saved. Leave blank to keep it, or enter a replacement.</small><button type="button" class="add" [disabled]="saving" (click)="clearTaxId(identity)">Clear saved practice SSN</button> }
|
|
2809
|
+
</div>
|
|
2686
2810
|
<label>Group NPI<input [(ngModel)]="identity.npi" [disabled]="saving"></label>
|
|
2687
2811
|
<label>Phone<input [(ngModel)]="identity.phone" [disabled]="saving"></label>
|
|
2688
2812
|
<label>Email<input [(ngModel)]="identity.email" [disabled]="saving"></label>
|
|
@@ -2690,7 +2814,10 @@ class MindBillOrganizationOnboardingComponent {
|
|
|
2690
2814
|
<h3>Billing provider (pay-to)</h3>
|
|
2691
2815
|
<div class="grid">
|
|
2692
2816
|
<label>Billing provider name<input [(ngModel)]="provider.name" [disabled]="saving"></label>
|
|
2693
|
-
<label>Billing tax ID<
|
|
2817
|
+
<label>Billing tax ID type<select [ngModel]="provider.taxIdType ?? 'EIN'" (ngModelChange)="setTaxIdType(provider, $event)" [disabled]="saving"><option value="EIN">EIN</option><option value="SSN">SSN</option></select></label>
|
|
2818
|
+
<div class="tax-id"><label>{{ provider.taxIdType === 'SSN' ? 'Billing SSN' : 'Billing EIN' }}<input [(ngModel)]="provider.taxId" [type]="provider.taxIdType === 'SSN' ? 'password' : 'text'" autocomplete="off" inputmode="numeric" [disabled]="saving"></label>
|
|
2819
|
+
@if (provider.taxIdType === 'SSN' && provider.taxIdConfigured) { <small>SSN ending in {{ provider.taxIdLast4 }} is saved. Leave blank to keep it, or enter a replacement.</small><button type="button" class="add" [disabled]="saving" (click)="clearTaxId(provider)">Clear saved billing SSN</button> }
|
|
2820
|
+
</div>
|
|
2694
2821
|
<label>Billing NPI<input [(ngModel)]="provider.npi" [disabled]="saving"></label>
|
|
2695
2822
|
<label>Billing phone<input [(ngModel)]="provider.phone" [disabled]="saving"></label>
|
|
2696
2823
|
<label class="span">Street<input [(ngModel)]="provider.billingStreet" [disabled]="saving"></label>
|
|
@@ -2745,7 +2872,7 @@ class MindBillOrganizationOnboardingComponent {
|
|
|
2745
2872
|
@if (errorMessage) { <div class="error" role="alert">{{ errorMessage }}</div> }
|
|
2746
2873
|
</div>
|
|
2747
2874
|
</section>
|
|
2748
|
-
`, 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"] }] });
|
|
2875
|
+
`, 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]),select{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,select:focus{outline:3px solid color-mix(in srgb,var(--a) 22%,transparent);border-color:var(--a)}.tax-id{display:grid;gap:7px;align-content:start}.tax-id small{color:var(--m);font-size:12px}.tax-id button{justify-self:start}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.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.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.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"] }] });
|
|
2749
2876
|
}
|
|
2750
2877
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: MindBillOrganizationOnboardingComponent, decorators: [{
|
|
2751
2878
|
type: Component,
|
|
@@ -2767,7 +2894,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
2767
2894
|
<div class="grid">
|
|
2768
2895
|
<label>Practice name<input [(ngModel)]="identity.name" [disabled]="saving"></label>
|
|
2769
2896
|
<label>Legal name<input [(ngModel)]="identity.legalName" [disabled]="saving"></label>
|
|
2770
|
-
<label>
|
|
2897
|
+
<label>Practice tax ID type<select [ngModel]="identity.taxIdType ?? 'EIN'" (ngModelChange)="setTaxIdType(identity, $event)" [disabled]="saving"><option value="EIN">EIN</option><option value="SSN">SSN</option></select></label>
|
|
2898
|
+
<div class="tax-id"><label>{{ identity.taxIdType === 'SSN' ? 'Practice SSN' : 'Practice EIN' }}<input [(ngModel)]="identity.taxId" [type]="identity.taxIdType === 'SSN' ? 'password' : 'text'" autocomplete="off" inputmode="numeric" [disabled]="saving"></label>
|
|
2899
|
+
@if (identity.taxIdType === 'SSN' && identity.taxIdConfigured) { <small>SSN ending in {{ identity.taxIdLast4 }} is saved. Leave blank to keep it, or enter a replacement.</small><button type="button" class="add" [disabled]="saving" (click)="clearTaxId(identity)">Clear saved practice SSN</button> }
|
|
2900
|
+
</div>
|
|
2771
2901
|
<label>Group NPI<input [(ngModel)]="identity.npi" [disabled]="saving"></label>
|
|
2772
2902
|
<label>Phone<input [(ngModel)]="identity.phone" [disabled]="saving"></label>
|
|
2773
2903
|
<label>Email<input [(ngModel)]="identity.email" [disabled]="saving"></label>
|
|
@@ -2775,7 +2905,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
2775
2905
|
<h3>Billing provider (pay-to)</h3>
|
|
2776
2906
|
<div class="grid">
|
|
2777
2907
|
<label>Billing provider name<input [(ngModel)]="provider.name" [disabled]="saving"></label>
|
|
2778
|
-
<label>Billing tax ID<
|
|
2908
|
+
<label>Billing tax ID type<select [ngModel]="provider.taxIdType ?? 'EIN'" (ngModelChange)="setTaxIdType(provider, $event)" [disabled]="saving"><option value="EIN">EIN</option><option value="SSN">SSN</option></select></label>
|
|
2909
|
+
<div class="tax-id"><label>{{ provider.taxIdType === 'SSN' ? 'Billing SSN' : 'Billing EIN' }}<input [(ngModel)]="provider.taxId" [type]="provider.taxIdType === 'SSN' ? 'password' : 'text'" autocomplete="off" inputmode="numeric" [disabled]="saving"></label>
|
|
2910
|
+
@if (provider.taxIdType === 'SSN' && provider.taxIdConfigured) { <small>SSN ending in {{ provider.taxIdLast4 }} is saved. Leave blank to keep it, or enter a replacement.</small><button type="button" class="add" [disabled]="saving" (click)="clearTaxId(provider)">Clear saved billing SSN</button> }
|
|
2911
|
+
</div>
|
|
2779
2912
|
<label>Billing NPI<input [(ngModel)]="provider.npi" [disabled]="saving"></label>
|
|
2780
2913
|
<label>Billing phone<input [(ngModel)]="provider.phone" [disabled]="saving"></label>
|
|
2781
2914
|
<label class="span">Street<input [(ngModel)]="provider.billingStreet" [disabled]="saving"></label>
|
|
@@ -2830,7 +2963,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
2830
2963
|
@if (errorMessage) { <div class="error" role="alert">{{ errorMessage }}</div> }
|
|
2831
2964
|
</div>
|
|
2832
2965
|
</section>
|
|
2833
|
-
`, 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"] }]
|
|
2966
|
+
`, 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]),select{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,select:focus{outline:3px solid color-mix(in srgb,var(--a) 22%,transparent);border-color:var(--a)}.tax-id{display:grid;gap:7px;align-content:start}.tax-id small{color:var(--m);font-size:12px}.tax-id button{justify-self:start}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"] }]
|
|
2834
2967
|
}], propDecorators: { appearance: [{
|
|
2835
2968
|
type: Input
|
|
2836
2969
|
}], sessionEndpoint: [{
|