@mindbill/react 0.22.0 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -7
- package/dist/index.d.ts +19 -7
- package/dist/index.js +68 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ npm install @mindbill/react @mindbill/node
|
|
|
8
8
|
|
|
9
9
|
## Connected lifecycle
|
|
10
10
|
|
|
11
|
-
`ConnectedBillLifecycle` starts after
|
|
11
|
+
`ConnectedBillLifecycle` starts after `BillSubmissionForm` atomically submits an immutable bill. It owns the submitted-to-closed progress rail, a read-only rendering of the exact submitted snapshot, server-owned human-readable history, packet download, EORs, payment posting, Second Bill Review, close, and reopen. The only persistent header action is **Download packet**; status-dependent actions appear in the details view when MindBill makes them available.
|
|
12
12
|
|
|
13
13
|
```tsx
|
|
14
14
|
import { ConnectedBillLifecycle } from "@mindbill/react";
|
|
@@ -132,7 +132,7 @@ Browser callbacks such as `onChanged` are for immediate UI, navigation, optimist
|
|
|
132
132
|
|
|
133
133
|
`BillSubmissionForm` owns the complete pre-submission experience: the bill field schema, required-field rules and red asterisks, validation, service-line editing, source-document selection, PDF uploads, and the single Submit action. Its `bill` value is structurally identical to the server SDK's `CreateBillRequest`.
|
|
134
134
|
|
|
135
|
-
The partner application only loads initial values and
|
|
135
|
+
The partner application only loads initial values and mints a short-lived browser session. Uploaded files stay in the browser until the user submits; the component validates and sends the immutable snapshot and PDF bytes directly to MindBill.
|
|
136
136
|
|
|
137
137
|
```tsx
|
|
138
138
|
import { BillSubmissionForm } from "@mindbill/react";
|
|
@@ -142,9 +142,7 @@ import { BillSubmissionForm } from "@mindbill/react";
|
|
|
142
142
|
attachments={bootstrap.attachments}
|
|
143
143
|
getSession={() => fetch("/api/mindbill/session", { method: "POST" }).then(r => r.json())}
|
|
144
144
|
appearance={{ preset: "qme-companion" }}
|
|
145
|
-
|
|
146
|
-
submitBill({ bill, sourceAttachmentIds, uploads })
|
|
147
|
-
}
|
|
145
|
+
onSubmitted={({ billId }) => saveLocalBillLink(billId)}
|
|
148
146
|
/>
|
|
149
147
|
```
|
|
150
148
|
|
|
@@ -159,11 +157,11 @@ The component includes the interaction model, not just the markup:
|
|
|
159
157
|
- searchable workers-comp procedure/modifier controls, medical-legal fee-schedule amounts, totals, valid manual CPT/HCPCS entry, and an automatically maintained empty line;
|
|
160
158
|
- removable source documents with new-tab previews, a locked auto-attached practice W-9, and a full-width click, panel-drop, or whole-page PDF upload area. Every visible source document is included until removed; uploaded PDFs do not require document-type tagging.
|
|
161
159
|
|
|
162
|
-
Partners supply tenant-specific bootstrap data, one short-lived browser session callback, and
|
|
160
|
+
Partners supply tenant-specific bootstrap data, one short-lived browser session callback, and optionally an `onSubmitted` callback to persist the returned `billId`. Required fields, validation, ZIP lookup, ICD-10 and payer directories, service-line behavior, PDF encoding, wire-format serialization, atomic submission, attachments, and submission UX stay inside `@mindbill/react`, so every integration receives the same billing workflow. Optional `diagnosisOptions`, `procedureOptions`, `modifierOptions`, and lookup callbacks extend or replace defaults when a partner has licensed or organization-specific data.
|
|
163
161
|
|
|
164
162
|
Validation is component-owned as well. A missing routing payer is highlighted immediately; Submit highlights every invalid control with a specific message, focuses and scrolls to the first problem, and continues validating as the user corrects the form.
|
|
165
163
|
|
|
166
|
-
`BILL_SUBMISSION_REQUIRED_FIELDS` and `validateBillSubmission` expose the same contract for tests and non-visual integrations. The component never creates a draft;
|
|
164
|
+
`BILL_SUBMISSION_REQUIRED_FIELDS` and `validateBillSubmission` expose the same contract for tests and non-visual integrations. The component never creates a draft; `onSubmitted` fires only after MindBill accepts a locally valid immutable snapshot. The legacy `onSubmit` escape hatch remains optional for unusual deployments, but connected integrations should omit it so the library owns the complete contract.
|
|
167
165
|
|
|
168
166
|
`BillReviewForm` remains available for legacy integrations that already own a custom review model. New integrations should use `BillSubmissionForm`.
|
|
169
167
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { MindBillAppearance, MindBillEventDetail, MindBillErrorDetail } from '@mindbill/embed';
|
|
2
2
|
export { MindBillAppearance, MindBillErrorDetail, MindBillEventDetail } from '@mindbill/embed';
|
|
3
3
|
import { CSSProperties, ReactElement, ReactNode } from 'react';
|
|
4
|
-
import { BillReviewData as BillReviewData$1, BillReviewAttachment as BillReviewAttachment$1, BillLifecycleSessionProvider, BillReviewPayer as BillReviewPayer$1, BillLifecycleAction, BillLifecycleDelivery, BillPaymentRecord, BillRemittanceSummary, BillLifecycleData, BillLifecycleClientOptions, BillLifecycleClient, BillEorDocument } from '@mindbill/browser';
|
|
5
|
-
export { BillActivityRecord, BillEorDocument, BillLifecycleAction, BillLifecycleActionId, BillLifecycleClient, BillLifecycleClientOptions, BillLifecycleData, BillLifecycleDelivery, BillLifecycleSession, BillLifecycleSessionProvider, BillLifecycleSessionRequest, BillPaymentRecord, BillRemittanceSummary, CloseBillInput, PostBillPaymentInput, ReopenBillInput, SubmitSecondReviewInput, createBillLifecycleClient } from '@mindbill/browser';
|
|
4
|
+
import { BillReviewData as BillReviewData$1, BillReviewAttachment as BillReviewAttachment$1, BrowserBillSubmissionResult, BillLifecycleSessionProvider, BillReviewPayer as BillReviewPayer$1, BrowserBillSubmissionDocument, BillLifecycleAction, BillLifecycleDelivery, BillPaymentRecord, BillRemittanceSummary, BillLifecycleData, BillLifecycleClientOptions, BillLifecycleClient, BillEorDocument } from '@mindbill/browser';
|
|
5
|
+
export { BillActivityRecord, BillEorDocument, BillLifecycleAction, BillLifecycleActionId, BillLifecycleClient, BillLifecycleClientOptions, BillLifecycleData, BillLifecycleDelivery, BillLifecycleSession, BillLifecycleSessionProvider, BillLifecycleSessionRequest, BillPaymentRecord, BillRemittanceSummary, BrowserBillSubmissionResult, CloseBillInput, PostBillPaymentInput, ReopenBillInput, SubmitSecondReviewInput, createBillLifecycleClient } from '@mindbill/browser';
|
|
6
6
|
|
|
7
7
|
type MindBillThemePreset = "mindbill" | "qme-companion" | "orange-bright" | "clinical-blue";
|
|
8
8
|
type MindBillReactAppearance = MindBillAppearance & {
|
|
@@ -473,8 +473,14 @@ type BillSubmissionFormValue = {
|
|
|
473
473
|
type BillSubmissionFormProps = {
|
|
474
474
|
initialBill: BillSubmissionInput;
|
|
475
475
|
attachments?: BillSubmissionSourceAttachment[];
|
|
476
|
-
|
|
477
|
-
|
|
476
|
+
/**
|
|
477
|
+
* Legacy custom submission escape hatch. Connected forms should omit this so
|
|
478
|
+
* the component owns PDF encoding and the Partner API wire contract.
|
|
479
|
+
*/
|
|
480
|
+
onSubmit?: (value: BillSubmissionFormValue) => void | Promise<void>;
|
|
481
|
+
/** Called after the connected component atomically creates and submits the bill. */
|
|
482
|
+
onSubmitted?: (result: BrowserBillSubmissionResult) => void | Promise<void>;
|
|
483
|
+
/** Short-lived partner browser session. Enables reference data and direct submission. */
|
|
478
484
|
getSession?: BillLifecycleSessionProvider;
|
|
479
485
|
sessionEndpoint?: string;
|
|
480
486
|
apiBaseUrl?: string;
|
|
@@ -498,11 +504,17 @@ type BillSubmissionFormProps = {
|
|
|
498
504
|
*/
|
|
499
505
|
children?: ReactNode;
|
|
500
506
|
};
|
|
501
|
-
declare const BILL_SUBMISSION_REQUIRED_FIELDS: readonly ["patient.firstName", "patient.lastName", "patient.dateOfBirth", "patient.address.line1", "patient.address.city", "patient.address.state", "patient.address.postalCode", "claim.claimNumber", "claim.claimsAdministrator", "service.date", "serviceLines[].code", "serviceLines[].units"];
|
|
507
|
+
declare const BILL_SUBMISSION_REQUIRED_FIELDS: readonly ["patient.firstName", "patient.lastName", "patient.dateOfBirth", "patient.address.line1", "patient.address.city", "patient.address.state", "patient.address.postalCode", "claim.claimNumber", "claim.claimsAdministrator", "service.date", "diagnoses[]", "serviceLines[].code", "serviceLines[].units"];
|
|
502
508
|
type BillSubmissionValidation = {
|
|
503
509
|
valid: boolean;
|
|
504
510
|
fieldErrors: Record<string, string>;
|
|
505
511
|
};
|
|
512
|
+
declare function prepareBillSubmissionDocuments({ attachments, selectedIds, uploads, fetch: fetchOverride, }: {
|
|
513
|
+
attachments: BillSubmissionSourceAttachment[];
|
|
514
|
+
selectedIds: string[];
|
|
515
|
+
uploads: BillSubmissionUpload[];
|
|
516
|
+
fetch?: typeof globalThis.fetch;
|
|
517
|
+
}): Promise<BrowserBillSubmissionDocument[]>;
|
|
506
518
|
declare function ensureTrailingBillSubmissionLine(lines: BillSubmissionInput["serviceLines"]): BillSubmissionInput["serviceLines"];
|
|
507
519
|
declare function parseBillSubmissionDate(value: string): string | undefined;
|
|
508
520
|
declare function formatBillSubmissionDate(value: string | null | undefined): string;
|
|
@@ -516,7 +528,7 @@ declare function BillSubmissionProvidersSection(): ReactElement;
|
|
|
516
528
|
declare function BillSubmissionServiceLinesSection(): ReactElement;
|
|
517
529
|
declare function BillSubmissionAttachmentsSection(): ReactElement;
|
|
518
530
|
declare function BillSubmissionActions(): ReactElement;
|
|
519
|
-
declare function BillSubmissionForm({ initialBill, attachments, onSubmit, getSession, sessionEndpoint, apiBaseUrl, fetch: fetchOverride, onSearchClaimsAdministrators, diagnosisOptions, onSearchDiagnoses, onLookupPostalCode, procedureOptions, modifierOptions, appearance, className, style, disabled, submitLabel, heading, description, children, }: BillSubmissionFormProps): ReactElement;
|
|
531
|
+
declare function BillSubmissionForm({ initialBill, attachments, onSubmit, onSubmitted, getSession, sessionEndpoint, apiBaseUrl, fetch: fetchOverride, onSearchClaimsAdministrators, diagnosisOptions, onSearchDiagnoses, onLookupPostalCode, procedureOptions, modifierOptions, appearance, className, style, disabled, submitLabel, heading, description, children, }: BillSubmissionFormProps): ReactElement;
|
|
520
532
|
|
|
521
533
|
/** Public-domain and MindBill-owned metadata. CPT descriptions are intentionally limited to the curated catalog. */
|
|
522
534
|
declare const DEFAULT_BILL_SUBMISSION_PROCEDURES: BillSubmissionProcedureOption[];
|
|
@@ -778,4 +790,4 @@ type MindBillWidgetProps = {
|
|
|
778
790
|
declare function MindBillBillTimeline(props: MindBillWidgetProps): ReactElement;
|
|
779
791
|
declare function MindBillBillReview(props: MindBillWidgetProps): ReactElement;
|
|
780
792
|
|
|
781
|
-
export { BILL_SUBMISSION_DIAGNOSIS_QUICK_PICKS, BILL_SUBMISSION_DOCUMENT_TYPES, BILL_SUBMISSION_REQUIRED_FIELDS, type BillActivityEvent, BillActivityTimeline, type BillActivityTimelineProps, type BillAgingBucket, type BillAgingBucketId, BillAgingSummary, type BillAgingSummaryProps, BillLifecycleActions, type BillLifecycleActionsProps, BillLifecycleProgress, type BillLifecycleProgressProps, type BillLifecycleStage, BillList, type BillListProps, BillPayerContactCard, type BillPayerContactCardProps, BillPaymentLedger, type BillPaymentLedgerProps, BillReadOnlyForm, type BillReadOnlyFormProps, BillRemittanceCard, type BillRemittanceCardProps, type BillReviewAttachment, type BillReviewBillingProvider, type BillReviewClinician, type BillReviewData, type BillReviewDocumentType, type BillReviewDraft, type BillReviewFeatures, BillReviewForm, type BillReviewFormProps, type BillReviewLineItem, type BillReviewLocation, type BillReviewPayer, type BillReviewSaveInput, BillSnapshotSummary, type BillSnapshotSummaryProps, type BillStatusAction, type BillStatusClient, type BillStatusClientOptions, type BillStatusData, type BillStatusSession, type BillStatusSessionProvider, type BillStatusSessionRequest, BillStatusSummary, type BillStatusSummaryProps, BillSubmissionActions, type BillSubmissionAddress, BillSubmissionAttachmentsSection, BillSubmissionClaimSection, type BillSubmissionDiagnosisOption, type BillSubmissionDocumentType, type BillSubmissionEvaluationType, BillSubmissionForm, type BillSubmissionFormProps, type BillSubmissionFormValue, BillSubmissionHeader, type BillSubmissionInput, type BillSubmissionModifierOption, BillSubmissionPatientSection, type BillSubmissionPostalPlace, type BillSubmissionProcedureOption, BillSubmissionProvidersSection, type BillSubmissionRoute, type BillSubmissionSectionId, BillSubmissionServiceLinesSection, type BillSubmissionSourceAttachment, type BillSubmissionUpload, type BillSubmissionValidation, type BillingComponentProps, BillingDashboard, type BillingDashboardBill, type BillingDashboardProps, type BillingDashboardSummary, BillingReport, type BillingReportDimension, type BillingReportProps, type BillingReportRow, ConnectedBillLifecycle, type ConnectedBillLifecycleProps, ConnectedBillStatus, type ConnectedBillStatusProps, DEFAULT_BILL_SUBMISSION_MODIFIERS, DEFAULT_BILL_SUBMISSION_PROCEDURES, MindBillBillReview, MindBillBillTimeline, type MindBillReactAppearance, type MindBillThemePreset, type MindBillWidgetProps, type UseBillLifecycleOptions, type UseBillLifecycleResult, type UseBillStatusOptions, type UseBillStatusResult, applyBillSubmissionEvaluationModifiers, billActivityEventLabel, billAgingBucket, billAgingDays, billLifecycleDisplayLabel, billLifecycleStage, buildBillReviewSaveInput, buildBillingReportCsv, buildBillingReportRows, calculateBillSubmissionAllowedAmount, createBillStatusClient, ensureTrailingBillSubmissionLine, ensureTrailingProcedureLine, formatBillSubmissionDate, mindBillAppearanceStyle, mindBillThemePresets, parseBillSubmissionDate, resolveMindBillAppearance, summarizeBillingDashboard, useBillLifecycle, useBillStatus, validateBillSubmission, visibleBillLifecycleActions };
|
|
793
|
+
export { BILL_SUBMISSION_DIAGNOSIS_QUICK_PICKS, BILL_SUBMISSION_DOCUMENT_TYPES, BILL_SUBMISSION_REQUIRED_FIELDS, type BillActivityEvent, BillActivityTimeline, type BillActivityTimelineProps, type BillAgingBucket, type BillAgingBucketId, BillAgingSummary, type BillAgingSummaryProps, BillLifecycleActions, type BillLifecycleActionsProps, BillLifecycleProgress, type BillLifecycleProgressProps, type BillLifecycleStage, BillList, type BillListProps, BillPayerContactCard, type BillPayerContactCardProps, BillPaymentLedger, type BillPaymentLedgerProps, BillReadOnlyForm, type BillReadOnlyFormProps, BillRemittanceCard, type BillRemittanceCardProps, type BillReviewAttachment, type BillReviewBillingProvider, type BillReviewClinician, type BillReviewData, type BillReviewDocumentType, type BillReviewDraft, type BillReviewFeatures, BillReviewForm, type BillReviewFormProps, type BillReviewLineItem, type BillReviewLocation, type BillReviewPayer, type BillReviewSaveInput, BillSnapshotSummary, type BillSnapshotSummaryProps, type BillStatusAction, type BillStatusClient, type BillStatusClientOptions, type BillStatusData, type BillStatusSession, type BillStatusSessionProvider, type BillStatusSessionRequest, BillStatusSummary, type BillStatusSummaryProps, BillSubmissionActions, type BillSubmissionAddress, BillSubmissionAttachmentsSection, BillSubmissionClaimSection, type BillSubmissionDiagnosisOption, type BillSubmissionDocumentType, type BillSubmissionEvaluationType, BillSubmissionForm, type BillSubmissionFormProps, type BillSubmissionFormValue, BillSubmissionHeader, type BillSubmissionInput, type BillSubmissionModifierOption, BillSubmissionPatientSection, type BillSubmissionPostalPlace, type BillSubmissionProcedureOption, BillSubmissionProvidersSection, type BillSubmissionRoute, type BillSubmissionSectionId, BillSubmissionServiceLinesSection, type BillSubmissionSourceAttachment, type BillSubmissionUpload, type BillSubmissionValidation, type BillingComponentProps, BillingDashboard, type BillingDashboardBill, type BillingDashboardProps, type BillingDashboardSummary, BillingReport, type BillingReportDimension, type BillingReportProps, type BillingReportRow, ConnectedBillLifecycle, type ConnectedBillLifecycleProps, ConnectedBillStatus, type ConnectedBillStatusProps, DEFAULT_BILL_SUBMISSION_MODIFIERS, DEFAULT_BILL_SUBMISSION_PROCEDURES, MindBillBillReview, MindBillBillTimeline, type MindBillReactAppearance, type MindBillThemePreset, type MindBillWidgetProps, type UseBillLifecycleOptions, type UseBillLifecycleResult, type UseBillStatusOptions, type UseBillStatusResult, applyBillSubmissionEvaluationModifiers, billActivityEventLabel, billAgingBucket, billAgingDays, billLifecycleDisplayLabel, billLifecycleStage, buildBillReviewSaveInput, buildBillingReportCsv, buildBillingReportRows, calculateBillSubmissionAllowedAmount, createBillStatusClient, ensureTrailingBillSubmissionLine, ensureTrailingProcedureLine, formatBillSubmissionDate, mindBillAppearanceStyle, mindBillThemePresets, parseBillSubmissionDate, prepareBillSubmissionDocuments, resolveMindBillAppearance, summarizeBillingDashboard, useBillLifecycle, useBillStatus, validateBillSubmission, visibleBillLifecycleActions };
|
package/dist/index.js
CHANGED
|
@@ -1157,7 +1157,8 @@ var READ_ONLY_STYLES = `
|
|
|
1157
1157
|
// src/bill-submission-form.tsx
|
|
1158
1158
|
import { createContext, useCallback, useContext, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
1159
1159
|
import {
|
|
1160
|
-
createBillReferenceClient
|
|
1160
|
+
createBillReferenceClient,
|
|
1161
|
+
createBillSubmissionClient
|
|
1161
1162
|
} from "@mindbill/browser";
|
|
1162
1163
|
|
|
1163
1164
|
// src/billing-catalog.ts
|
|
@@ -1303,6 +1304,7 @@ var BILL_SUBMISSION_REQUIRED_FIELDS = [
|
|
|
1303
1304
|
"claim.claimNumber",
|
|
1304
1305
|
"claim.claimsAdministrator",
|
|
1305
1306
|
"service.date",
|
|
1307
|
+
"diagnoses[]",
|
|
1306
1308
|
"serviceLines[].code",
|
|
1307
1309
|
"serviceLines[].units"
|
|
1308
1310
|
];
|
|
@@ -1322,6 +1324,48 @@ var MAX_UPLOAD_BYTES = 100 * 1024 * 1024;
|
|
|
1322
1324
|
var MAX_DOCUMENTS = 25;
|
|
1323
1325
|
var DIAGNOSIS_PAGE_SIZE = 100;
|
|
1324
1326
|
var EMPTY_ATTACHMENTS = [];
|
|
1327
|
+
function bytesToBase64(bytes) {
|
|
1328
|
+
let binary = "";
|
|
1329
|
+
for (let offset = 0; offset < bytes.length; offset += 32768) {
|
|
1330
|
+
binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
|
|
1331
|
+
}
|
|
1332
|
+
return globalThis.btoa(binary);
|
|
1333
|
+
}
|
|
1334
|
+
async function pdfDocument(blob, input) {
|
|
1335
|
+
if (blob.size > MAX_PDF_BYTES) throw new Error(`${input.filename} is larger than 25 MB.`);
|
|
1336
|
+
const bytes = new Uint8Array(await blob.arrayBuffer());
|
|
1337
|
+
if (bytes.length < 5 || bytes[0] !== 37 || bytes[1] !== 80 || bytes[2] !== 68 || bytes[3] !== 70 || bytes[4] !== 45) {
|
|
1338
|
+
throw new Error(`${input.filename} is not a valid PDF.`);
|
|
1339
|
+
}
|
|
1340
|
+
return { ...input, contentBase64: bytesToBase64(bytes) };
|
|
1341
|
+
}
|
|
1342
|
+
async function prepareBillSubmissionDocuments({
|
|
1343
|
+
attachments,
|
|
1344
|
+
selectedIds,
|
|
1345
|
+
uploads,
|
|
1346
|
+
fetch: fetchOverride
|
|
1347
|
+
}) {
|
|
1348
|
+
const fetcher = fetchOverride ?? globalThis.fetch;
|
|
1349
|
+
if (typeof fetcher !== "function") throw new Error("A Fetch API implementation is required.");
|
|
1350
|
+
const selected = selectedIds.map((id) => attachments.find((item) => item.id === id)).filter((item) => Boolean(item));
|
|
1351
|
+
const sourceDocuments = await Promise.all(selected.map(async (attachment) => {
|
|
1352
|
+
if (!attachment.previewUrl) throw new Error(`${attachment.fileName} cannot be submitted because its document URL is missing.`);
|
|
1353
|
+
const response = await fetcher(attachment.previewUrl, { credentials: "same-origin" });
|
|
1354
|
+
if (!response.ok) throw new Error(`${attachment.fileName} could not be loaded for submission.`);
|
|
1355
|
+
return pdfDocument(await response.blob(), {
|
|
1356
|
+
externalId: attachment.id,
|
|
1357
|
+
filename: attachment.fileName,
|
|
1358
|
+
documentType: attachment.documentType,
|
|
1359
|
+
...attachment.description ? { description: attachment.description } : {}
|
|
1360
|
+
});
|
|
1361
|
+
}));
|
|
1362
|
+
const uploadedDocuments = await Promise.all(uploads.map(({ file, documentType, description }) => pdfDocument(file, {
|
|
1363
|
+
filename: file.name,
|
|
1364
|
+
documentType,
|
|
1365
|
+
...description ? { description } : {}
|
|
1366
|
+
})));
|
|
1367
|
+
return [...sourceDocuments, ...uploadedDocuments];
|
|
1368
|
+
}
|
|
1325
1369
|
function previewUploadedPdf(file) {
|
|
1326
1370
|
const url = URL.createObjectURL(file);
|
|
1327
1371
|
window.open(url, "_blank", "noopener,noreferrer");
|
|
@@ -1403,6 +1447,9 @@ function validateBillSubmission(bill) {
|
|
|
1403
1447
|
required("claim.claimNumber", bill.claim.claimNumber, "Enter the claim number.");
|
|
1404
1448
|
required("claim.claimsAdministrator", bill.claim.claimsAdministrator?.name, "Select a claims administrator so MindBill can route this bill.");
|
|
1405
1449
|
required("service.date", bill.service.date, "Enter the date of service.");
|
|
1450
|
+
if (!(bill.diagnoses ?? []).some((code) => code.trim())) {
|
|
1451
|
+
errors.diagnoses = "Select at least one ICD-10 diagnosis code.";
|
|
1452
|
+
}
|
|
1406
1453
|
if (bill.claim.claimsAdministrator?.name && !bill.claim.claimsAdministrator.id) {
|
|
1407
1454
|
errors["claim.claimsAdministrator"] = "Select a claims administrator from the payer directory.";
|
|
1408
1455
|
}
|
|
@@ -1559,6 +1606,7 @@ function BillSubmissionForm({
|
|
|
1559
1606
|
initialBill,
|
|
1560
1607
|
attachments = EMPTY_ATTACHMENTS,
|
|
1561
1608
|
onSubmit,
|
|
1609
|
+
onSubmitted,
|
|
1562
1610
|
getSession,
|
|
1563
1611
|
sessionEndpoint,
|
|
1564
1612
|
apiBaseUrl,
|
|
@@ -1602,7 +1650,9 @@ function BillSubmissionForm({
|
|
|
1602
1650
|
const procedures = useMemo2(() => mergeOptions(DEFAULT_BILL_SUBMISSION_PROCEDURES, procedureOptions), [procedureOptions]);
|
|
1603
1651
|
const modifiers = useMemo2(() => mergeOptions(DEFAULT_BILL_SUBMISSION_MODIFIERS, modifierOptions), [modifierOptions]);
|
|
1604
1652
|
const [evaluationType, setEvaluationType] = useState2(() => initialBill.renderingProvider?.isAme ? "ame" : initialBill.renderingProvider?.specialty?.toLowerCase().includes("psych") ? "psych_qme" : "qme");
|
|
1605
|
-
const
|
|
1653
|
+
const connected = !onSubmit;
|
|
1654
|
+
const referenceClient = useMemo2(() => getSession || sessionEndpoint || connected ? createBillReferenceClient({ getSession, sessionEndpoint, apiBaseUrl, fetch: fetchOverride }) : null, [getSession, sessionEndpoint, apiBaseUrl, fetchOverride, connected]);
|
|
1655
|
+
const submissionClient = useMemo2(() => connected ? createBillSubmissionClient({ getSession, sessionEndpoint, apiBaseUrl, fetch: fetchOverride }) : null, [getSession, sessionEndpoint, apiBaseUrl, fetchOverride, connected]);
|
|
1606
1656
|
const locked = disabled || submitting;
|
|
1607
1657
|
useEffect2(() => {
|
|
1608
1658
|
setBill(cloneBill(initialBill));
|
|
@@ -1760,7 +1810,19 @@ function BillSubmissionForm({
|
|
|
1760
1810
|
if (selectedIds.length + uploads.length > MAX_DOCUMENTS) return setFormError(`A bill can include at most ${MAX_DOCUMENTS} attachments.`);
|
|
1761
1811
|
setSubmitting(true);
|
|
1762
1812
|
try {
|
|
1763
|
-
|
|
1813
|
+
if (onSubmit) {
|
|
1814
|
+
await onSubmit({ bill: clean, sourceAttachmentIds: selectedIds, uploads });
|
|
1815
|
+
} else {
|
|
1816
|
+
if (!submissionClient) throw new Error("The connected billing client is unavailable.");
|
|
1817
|
+
const documents = await prepareBillSubmissionDocuments({
|
|
1818
|
+
attachments,
|
|
1819
|
+
selectedIds,
|
|
1820
|
+
uploads,
|
|
1821
|
+
...fetchOverride ? { fetch: fetchOverride } : {}
|
|
1822
|
+
});
|
|
1823
|
+
const result = await submissionClient.submitBill({ bill: clean, documents });
|
|
1824
|
+
await onSubmitted?.(result);
|
|
1825
|
+
}
|
|
1764
1826
|
} catch (caught) {
|
|
1765
1827
|
setFormError(caught instanceof Error ? caught.message : "Unable to submit the bill.");
|
|
1766
1828
|
} finally {
|
|
@@ -1805,7 +1867,7 @@ function BillSubmissionForm({
|
|
|
1805
1867
|
/* @__PURE__ */ jsx3(Field2, { label: "WCAB / ADJ number (optional)", children: text(bill.claim.adjNumber, (adjNumber) => setBill((c) => ({ ...c, claim: { ...c.claim, adjNumber } }))) }),
|
|
1806
1868
|
/* @__PURE__ */ jsx3(Field2, { path: "claim.claimsAdministrator", label: "Claims administrator", required: true, span: true, error: claimsAdministratorError, children: /* @__PURE__ */ jsx3(ComboBox, { ariaLabel: "Claims administrator", invalid: Boolean(claimsAdministratorError), disabled: locked, loading: payerLoading, value: bill.claim.claimsAdministrator?.name ?? "", placeholder: "Search the payer directory\u2026", options: payerResults.map((payer) => ({ id: payer.id, label: payer.name, detail: [payer.hasElectronic ? "Electronic" : "Work comp", ...payer.states ?? []].join(" \xB7 ") })), onQuery: searchPayers, onSelect: (option) => setBill((c) => ({ ...c, claim: { ...c.claim, claimsAdministrator: { id: option.id, name: option.label } } })) }) }),
|
|
1807
1869
|
/* @__PURE__ */ jsx3(Field2, { label: "Injury description (optional)", span: true, children: text(bill.claim.description, (description2) => setBill((c) => ({ ...c, claim: { ...c.claim, description: description2 } }))) }),
|
|
1808
|
-
/* @__PURE__ */ jsxs3(Field2, { label: "Diagnosis codes (ICD-10)", span: true, children: [
|
|
1870
|
+
/* @__PURE__ */ jsxs3(Field2, { path: "diagnoses", label: "Diagnosis codes (ICD-10)", required: true, span: true, error: errors.diagnoses, children: [
|
|
1809
1871
|
/* @__PURE__ */ jsx3("div", { className: "mbsf-quick-picks", "aria-label": "Common diagnosis codes", children: BILL_SUBMISSION_DIAGNOSIS_QUICK_PICKS.map((option) => {
|
|
1810
1872
|
const selected = (bill.diagnoses ?? []).includes(option.code);
|
|
1811
1873
|
return /* @__PURE__ */ jsxs3("button", { className: "mbsf-quick-pick", "data-selected": selected, type: "button", "aria-pressed": selected, title: `${option.code} \u2014 ${option.description}`, onClick: () => setBill((current) => ({ ...current, diagnoses: selected ? (current.diagnoses ?? []).filter((code) => code !== option.code) : [.../* @__PURE__ */ new Set([...current.diagnoses ?? [], option.code])] })), children: [
|
|
@@ -1822,7 +1884,7 @@ function BillSubmissionForm({
|
|
|
1822
1884
|
/* @__PURE__ */ jsx3("button", { type: "button", "aria-label": `Remove ${code}`, onClick: () => setBill((c) => ({ ...c, diagnoses: (c.diagnoses ?? []).filter((item) => item !== code) })), children: "\xD7" })
|
|
1823
1885
|
] }, code);
|
|
1824
1886
|
}) }),
|
|
1825
|
-
/* @__PURE__ */ jsx3(ComboBox, { ariaLabel: "Add diagnosis code", disabled: locked, loading: diagnosisLoading, loadingMore: diagnosisLoadingMore, value: "", placeholder: bill.diagnoses?.length ?? 0 ? `${bill.diagnoses.length} selected \u2014 add more\u2026` : "Search ICD-10 codes\u2026", options: diagnosisChoices.filter((item) => !(bill.diagnoses ?? []).includes(item.code)).map((item) => ({ id: item.code, label: item.code, detail: item.description })), onOpen: () => {
|
|
1887
|
+
/* @__PURE__ */ jsx3(ComboBox, { ariaLabel: "Add diagnosis code", invalid: Boolean(errors.diagnoses), disabled: locked, loading: diagnosisLoading, loadingMore: diagnosisLoadingMore, value: "", placeholder: bill.diagnoses?.length ?? 0 ? `${bill.diagnoses.length} selected \u2014 add more\u2026` : "Search ICD-10 codes\u2026", options: diagnosisChoices.filter((item) => !(bill.diagnoses ?? []).includes(item.code)).map((item) => ({ id: item.code, label: item.code, detail: item.description })), onOpen: () => {
|
|
1826
1888
|
if (diagnosisQuery !== "") loadDiagnoses("");
|
|
1827
1889
|
}, onQuery: searchDiagnoses, onEndReached: () => loadDiagnoses(diagnosisQuery ?? "", true), onSelect: (option) => setBill((c) => ({ ...c, diagnoses: [.../* @__PURE__ */ new Set([...c.diagnoses ?? [], option.id])] })) })
|
|
1828
1890
|
] })
|
|
@@ -3225,6 +3287,7 @@ export {
|
|
|
3225
3287
|
mindBillAppearanceStyle,
|
|
3226
3288
|
mindBillThemePresets,
|
|
3227
3289
|
parseBillSubmissionDate,
|
|
3290
|
+
prepareBillSubmissionDocuments,
|
|
3228
3291
|
resolveMindBillAppearance,
|
|
3229
3292
|
summarizeBillingDashboard,
|
|
3230
3293
|
useBillLifecycle,
|