@mindbill/react 0.24.0 → 0.25.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 CHANGED
@@ -161,6 +161,8 @@ Partners supply tenant-specific bootstrap data, one short-lived browser session
161
161
 
162
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.
163
163
 
164
+ The complete immutable snapshot requires patient identity and address; employer, injury date, service date, and a canonical claims-administrator directory selection; at least one ICD-10 diagnosis and procedure line; billing provider name, Tax ID, NPI, phone, and address; rendering provider name, NPI, and taxonomy; and service-facility address plus place-of-service code. Address line 2 and physician license metadata remain optional. For California workers-comp CMS-1500 output, `renderingProvider.taxonomy` is the 10-character provider taxonomy placed in shaded Box 24J with qualifier `ZZ`; it is not replaced by the physician license number.
165
+
164
166
  `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.
165
167
 
166
168
  `BillReviewForm` remains available for legacy integrations that already own a custom review model. New integrations should use `BillSubmissionForm`.
package/dist/index.d.ts CHANGED
@@ -367,6 +367,7 @@ declare const BILL_SUBMISSION_REPORT_TYPES: readonly BillSubmissionReportTypeOpt
367
367
  type BillSubmissionEvaluationType = "qme" | "ame" | "psych_qme";
368
368
  type BillSubmissionAddress = {
369
369
  line1: string;
370
+ line2?: string;
370
371
  city: string;
371
372
  state: string;
372
373
  postalCode: string;
@@ -455,6 +456,36 @@ type BillSubmissionInput = {
455
456
  diagnosisPointers?: number[];
456
457
  }>;
457
458
  };
459
+ /** A validated, submission-ready bill. The form accepts partial provider data while editing,
460
+ * but only emits this complete contract after every required field has passed validation. */
461
+ type CompleteBillSubmissionInput = Omit<BillSubmissionInput, "claim" | "billingProvider" | "renderingProvider" | "serviceLocation" | "diagnoses" | "serviceLines"> & {
462
+ claim: BillSubmissionInput["claim"] & {
463
+ employer: string;
464
+ dateOfInjury: string;
465
+ claimsAdministrator: {
466
+ id: string;
467
+ name: string;
468
+ };
469
+ };
470
+ billingProvider: {
471
+ name: string;
472
+ taxId: string;
473
+ npi: string;
474
+ phone: string;
475
+ address: BillSubmissionAddress;
476
+ };
477
+ renderingProvider: NonNullable<BillSubmissionInput["renderingProvider"]> & {
478
+ name: string;
479
+ npi: string;
480
+ taxonomy: string;
481
+ };
482
+ serviceLocation: NonNullable<BillSubmissionInput["serviceLocation"]> & {
483
+ address: BillSubmissionAddress;
484
+ placeOfServiceCode: string;
485
+ };
486
+ diagnoses: string[];
487
+ serviceLines: BillSubmissionInput["serviceLines"];
488
+ };
458
489
  type BillSubmissionSourceAttachment = {
459
490
  id: string;
460
491
  fileName: string;
@@ -475,7 +506,7 @@ type BillSubmissionUpload = {
475
506
  reportTypeCode?: string;
476
507
  };
477
508
  type BillSubmissionFormValue = {
478
- bill: BillSubmissionInput;
509
+ bill: CompleteBillSubmissionInput;
479
510
  sourceAttachmentIds: string[];
480
511
  sourceAttachmentReportTypes: Record<string, string>;
481
512
  uploads: BillSubmissionUpload[];
@@ -518,7 +549,7 @@ type BillSubmissionFormProps = {
518
549
  */
519
550
  children?: ReactNode;
520
551
  };
521
- 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"];
552
+ 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.employer", "claim.dateOfInjury", "claim.claimsAdministrator", "service.date", "billingProvider.name", "billingProvider.taxId", "billingProvider.npi", "billingProvider.phone", "billingProvider.address.line1", "billingProvider.address.city", "billingProvider.address.state", "billingProvider.address.postalCode", "renderingProvider.name", "renderingProvider.npi", "renderingProvider.taxonomy", "serviceLocation.placeOfServiceCode", "serviceLocation.address.line1", "serviceLocation.address.city", "serviceLocation.address.state", "serviceLocation.address.postalCode", "diagnoses[]", "serviceLines[].code", "serviceLines[].units"];
522
553
  type BillSubmissionValidation = {
523
554
  valid: boolean;
524
555
  fieldErrors: Record<string, string>;
package/dist/index.js CHANGED
@@ -1376,8 +1376,26 @@ var BILL_SUBMISSION_REQUIRED_FIELDS = [
1376
1376
  "patient.address.state",
1377
1377
  "patient.address.postalCode",
1378
1378
  "claim.claimNumber",
1379
+ "claim.employer",
1380
+ "claim.dateOfInjury",
1379
1381
  "claim.claimsAdministrator",
1380
1382
  "service.date",
1383
+ "billingProvider.name",
1384
+ "billingProvider.taxId",
1385
+ "billingProvider.npi",
1386
+ "billingProvider.phone",
1387
+ "billingProvider.address.line1",
1388
+ "billingProvider.address.city",
1389
+ "billingProvider.address.state",
1390
+ "billingProvider.address.postalCode",
1391
+ "renderingProvider.name",
1392
+ "renderingProvider.npi",
1393
+ "renderingProvider.taxonomy",
1394
+ "serviceLocation.placeOfServiceCode",
1395
+ "serviceLocation.address.line1",
1396
+ "serviceLocation.address.city",
1397
+ "serviceLocation.address.state",
1398
+ "serviceLocation.address.postalCode",
1381
1399
  "diagnoses[]",
1382
1400
  "serviceLines[].code",
1383
1401
  "serviceLines[].units"
@@ -1537,8 +1555,26 @@ function validateBillSubmission(bill) {
1537
1555
  required("patient.address.state", bill.patient.address.state, "Enter the patient's 2-letter state code.");
1538
1556
  required("patient.address.postalCode", bill.patient.address.postalCode, "Enter the patient's ZIP code.");
1539
1557
  required("claim.claimNumber", bill.claim.claimNumber, "Enter the claim number.");
1558
+ required("claim.employer", bill.claim.employer, "Enter the employer name.");
1559
+ required("claim.dateOfInjury", bill.claim.dateOfInjury, "Enter the date of injury.");
1540
1560
  required("claim.claimsAdministrator", bill.claim.claimsAdministrator?.name, "Select a claims administrator so MindBill can route this bill.");
1541
1561
  required("service.date", bill.service.date, "Enter the date of service.");
1562
+ required("billingProvider.name", bill.billingProvider?.name, "Enter the billing provider name.");
1563
+ required("billingProvider.taxId", bill.billingProvider?.taxId, "Enter the billing provider Tax ID (EIN or SSN).");
1564
+ required("billingProvider.npi", bill.billingProvider?.npi, "Enter the billing provider NPI.");
1565
+ required("billingProvider.phone", bill.billingProvider?.phone, "Enter the billing provider phone number.");
1566
+ required("billingProvider.address.line1", bill.billingProvider?.address?.line1, "Enter the billing provider street address.");
1567
+ required("billingProvider.address.city", bill.billingProvider?.address?.city, "Enter the billing provider city.");
1568
+ required("billingProvider.address.state", bill.billingProvider?.address?.state, "Enter the billing provider 2-letter state code.");
1569
+ required("billingProvider.address.postalCode", bill.billingProvider?.address?.postalCode, "Enter the billing provider ZIP code.");
1570
+ required("renderingProvider.name", bill.renderingProvider?.name, "Enter the rendering provider name.");
1571
+ required("renderingProvider.npi", bill.renderingProvider?.npi, "Enter the rendering provider NPI.");
1572
+ required("renderingProvider.taxonomy", bill.renderingProvider?.taxonomy, "Enter the rendering provider taxonomy code.");
1573
+ required("serviceLocation.placeOfServiceCode", bill.serviceLocation?.placeOfServiceCode, "Enter the 2-digit place of service code.");
1574
+ required("serviceLocation.address.line1", bill.serviceLocation?.address?.line1, "Enter the service facility street address.");
1575
+ required("serviceLocation.address.city", bill.serviceLocation?.address?.city, "Enter the service facility city.");
1576
+ required("serviceLocation.address.state", bill.serviceLocation?.address?.state, "Enter the service facility 2-letter state code.");
1577
+ required("serviceLocation.address.postalCode", bill.serviceLocation?.address?.postalCode, "Enter the service facility ZIP code.");
1542
1578
  if (!(bill.diagnoses ?? []).some((code) => code.trim())) {
1543
1579
  errors.diagnoses = "Select at least one ICD-10 diagnosis code.";
1544
1580
  }
@@ -1546,7 +1582,16 @@ function validateBillSubmission(bill) {
1546
1582
  errors["claim.claimsAdministrator"] = "Select a claims administrator from the payer directory.";
1547
1583
  }
1548
1584
  if (bill.patient.dateOfBirth && !parseBillSubmissionDate(bill.patient.dateOfBirth)) errors["patient.dateOfBirth"] = "Use MM/DD/YYYY";
1585
+ if (bill.claim.dateOfInjury && !parseBillSubmissionDate(bill.claim.dateOfInjury)) errors["claim.dateOfInjury"] = "Use MM/DD/YYYY";
1549
1586
  if (bill.patient.address.state.trim().length !== 2) errors["patient.address.state"] = "Use a 2-letter state code";
1587
+ if (bill.billingProvider?.address?.state && bill.billingProvider.address.state.trim().length !== 2) errors["billingProvider.address.state"] = "Use a 2-letter state code.";
1588
+ if (bill.serviceLocation?.address?.state && bill.serviceLocation.address.state.trim().length !== 2) errors["serviceLocation.address.state"] = "Use a 2-letter state code.";
1589
+ const digits = (value) => value?.replace(/\D/g, "") ?? "";
1590
+ if (bill.billingProvider?.taxId && digits(bill.billingProvider.taxId).length !== 9) errors["billingProvider.taxId"] = "Enter a valid 9-digit EIN or SSN.";
1591
+ if (bill.billingProvider?.npi && !/^\d{10}$/.test(digits(bill.billingProvider.npi))) errors["billingProvider.npi"] = "Enter a valid 10-digit NPI.";
1592
+ if (bill.renderingProvider?.npi && !/^\d{10}$/.test(digits(bill.renderingProvider.npi))) errors["renderingProvider.npi"] = "Enter a valid 10-digit NPI.";
1593
+ if (bill.renderingProvider?.taxonomy && !/^[A-Za-z0-9]{10}$/.test(bill.renderingProvider.taxonomy.trim())) errors["renderingProvider.taxonomy"] = "Enter a valid 10-character taxonomy code.";
1594
+ if (bill.serviceLocation?.placeOfServiceCode && !/^\d{2}$/.test(bill.serviceLocation.placeOfServiceCode.trim())) errors["serviceLocation.placeOfServiceCode"] = "Enter a valid 2-digit place of service code.";
1550
1595
  const lines = submittedLines(bill.serviceLines);
1551
1596
  if (!lines.length) errors.serviceLines = "Add at least one service line";
1552
1597
  lines.forEach((line, index) => {
@@ -1559,7 +1604,7 @@ function validateBillSubmission(bill) {
1559
1604
  var css = `
1560
1605
  .mbsf{display:grid;gap:20px;color:var(--mb-text);font-family:var(--mb-font);font-size:15px}.mbsf *{box-sizing:border-box}
1561
1606
  .mbsf-head,.mbsf-section-head,.mbsf-attach-row,.mbsf-actions{display:flex;align-items:center;justify-content:space-between;gap:16px}.mbsf-title{margin:0;font-size:24px}.mbsf-copy,.mbsf-help{color:var(--mb-muted);margin:5px 0 0}.mbsf-required{font-size:13px;color:var(--mb-muted);white-space:nowrap}.mbsf-star,.mbsf-error{color:var(--mb-danger)}
1562
- .mbsf-card{min-width:0;margin:0;padding:24px;border:1px solid var(--mb-border);border-radius:var(--mb-radius);background:var(--mb-surface);box-shadow:var(--mb-shadow)}.mbsf-card[data-invalid=true]{border-color:var(--mb-danger)}.mbsf-legend{padding:0 10px;font-size:18px;font-weight:760}.mbsf-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px 24px}.mbsf-span{grid-column:1/-1}.mbsf-field{display:grid;align-content:start;gap:7px;min-width:0}.mbsf-label{font-weight:680}.mbsf-input,.mbsf-select{width:100%;min-height:46px;padding:10px 12px;border:1px solid var(--mb-border);border-radius:var(--mb-control-radius);background:var(--mb-input);color:var(--mb-text);font:inherit}.mbsf-input:focus,.mbsf-select:focus{outline:3px solid color-mix(in srgb,var(--mb-accent) 22%,transparent);border-color:var(--mb-accent)}.mbsf-field[data-invalid=true] .mbsf-input,.mbsf-field[data-invalid=true] .mbsf-select,.mbsf-invalid-control .mbsf-input{border-color:var(--mb-danger);background:color-mix(in srgb,var(--mb-danger) 4%,var(--mb-input))}.mbsf-field[data-invalid=true] .mbsf-input:focus,.mbsf-field[data-invalid=true] .mbsf-select:focus{outline-color:color-mix(in srgb,var(--mb-danger) 24%,transparent)}
1607
+ .mbsf-card{min-width:0;margin:0;padding:24px;border:1px solid var(--mb-border);border-radius:var(--mb-radius);background:var(--mb-surface);box-shadow:var(--mb-shadow)}.mbsf-card[data-invalid=true]{border-color:var(--mb-danger)}.mbsf-legend{padding:0 10px;font-size:18px;font-weight:760}.mbsf-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px 24px}.mbsf-subhead{grid-column:1/-1;margin:6px 0 -2px;padding-top:14px;border-top:1px solid var(--mb-border);font-size:15px;font-weight:780;letter-spacing:.01em}.mbsf-subhead:first-child{margin-top:0;padding-top:0;border-top:0}.mbsf-span{grid-column:1/-1}.mbsf-field{display:grid;align-content:start;gap:7px;min-width:0}.mbsf-label{font-weight:680}.mbsf-input,.mbsf-select{width:100%;min-height:46px;padding:10px 12px;border:1px solid var(--mb-border);border-radius:var(--mb-control-radius);background:var(--mb-input);color:var(--mb-text);font:inherit}.mbsf-input:focus,.mbsf-select:focus{outline:3px solid color-mix(in srgb,var(--mb-accent) 22%,transparent);border-color:var(--mb-accent)}.mbsf-field[data-invalid=true] .mbsf-input,.mbsf-field[data-invalid=true] .mbsf-select,.mbsf-invalid-control .mbsf-input{border-color:var(--mb-danger);background:color-mix(in srgb,var(--mb-danger) 4%,var(--mb-input))}.mbsf-field[data-invalid=true] .mbsf-input:focus,.mbsf-field[data-invalid=true] .mbsf-select:focus{outline-color:color-mix(in srgb,var(--mb-danger) 24%,transparent)}
1563
1608
  .mbsf-combo{position:relative}.mbsf-menu{position:absolute;z-index:20;top:calc(100% + 5px);left:0;right:0;max-height:min(360px,46vh);overflow:auto;overscroll-behavior:contain;padding:7px;border:1px solid var(--mb-border);border-radius:12px;background:var(--mb-surface);box-shadow:0 14px 35px rgba(17,38,49,.16)}.mbsf-option{display:grid;width:100%;gap:2px;padding:10px;border:0;border-radius:8px;background:transparent;color:var(--mb-text);font:inherit;text-align:left;cursor:pointer}.mbsf-option:hover,.mbsf-option:focus{background:color-mix(in srgb,var(--mb-accent) 9%,var(--mb-surface))}.mbsf-option small{color:var(--mb-muted)}.mbsf-menu-status{padding:12px;text-align:center;color:var(--mb-muted);font-size:13px}
1564
1609
  .mbsf-payer-status{display:flex;align-items:center;gap:7px;color:#087f5b;font-size:13px;font-weight:650}.mbsf-payer-intro{margin:4px 0 0;color:var(--mb-muted)}.mbsf-payer-list{display:grid;gap:8px}.mbsf-payer-option{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:11px 12px;border:1px solid var(--mb-border);border-radius:var(--mb-control-radius);background:color-mix(in srgb,var(--mb-accent) 3%,var(--mb-surface))}.mbsf-payer-option-main{display:grid;gap:5px;min-width:0}.mbsf-payer-option-main strong{overflow-wrap:anywhere}.mbsf-payer-signals{display:flex;flex-wrap:wrap;gap:6px}.mbsf-payer-signal{padding:2px 7px;border:1px solid var(--mb-border);border-radius:999px;color:var(--mb-muted);font-size:12px}.mbsf-payer-signal[data-state=match]{border-color:color-mix(in srgb,#159447 45%,var(--mb-border));color:#087f5b}.mbsf-payer-signal[data-state=warning]{border-color:color-mix(in srgb,#c56a00 55%,var(--mb-border));color:#9a5200}
1565
1610
  .mbsf-chips,.mbsf-quick-picks{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:8px}.mbsf-chip,.mbsf-quick-pick{display:inline-flex;align-items:center;gap:7px;padding:5px 9px;border:1px solid var(--mb-border);border-radius:999px;background:var(--mb-input)}.mbsf-chip button{border:0;background:transparent;color:var(--mb-muted);cursor:pointer;font:inherit}.mbsf-quick-pick{color:var(--mb-text);font:inherit;cursor:pointer}.mbsf-quick-pick[data-selected=true]{border-color:var(--mb-accent);color:var(--mb-accent)}
@@ -1952,10 +1997,11 @@ function BillSubmissionForm({
1952
1997
  return;
1953
1998
  }
1954
1999
  if (selectedIds.length + uploads.length > MAX_DOCUMENTS) return setFormError(`A bill can include at most ${MAX_DOCUMENTS} attachments.`);
2000
+ const complete = clean;
1955
2001
  setSubmitting(true);
1956
2002
  try {
1957
2003
  if (onSubmit) {
1958
- await onSubmit({ bill: clean, sourceAttachmentIds: selectedIds, sourceAttachmentReportTypes, uploads });
2004
+ await onSubmit({ bill: complete, sourceAttachmentIds: selectedIds, sourceAttachmentReportTypes, uploads });
1959
2005
  } else {
1960
2006
  if (!submissionClient) throw new Error("The connected billing client is unavailable.");
1961
2007
  const documents = await prepareBillSubmissionDocuments({
@@ -1966,7 +2012,7 @@ function BillSubmissionForm({
1966
2012
  ...forcedAttachmentReportType ? { defaultReportTypeCode: forcedAttachmentReportType } : {},
1967
2013
  ...fetchOverride ? { fetch: fetchOverride } : {}
1968
2014
  });
1969
- const result = await submissionClient.submitBill({ bill: clean, documents });
2015
+ const result = await submissionClient.submitBill({ bill: complete, documents });
1970
2016
  await onSubmitted?.(result);
1971
2017
  }
1972
2018
  } catch (caught) {
@@ -2010,8 +2056,8 @@ function BillSubmissionForm({
2010
2056
  /* @__PURE__ */ jsx3("legend", { className: "mbsf-legend", children: "Injury & claim" }),
2011
2057
  /* @__PURE__ */ jsxs3("div", { className: "mbsf-grid", children: [
2012
2058
  /* @__PURE__ */ jsx3(Field2, { path: "service.date", label: "Date of service", required: true, error: errors["service.date"], children: /* @__PURE__ */ jsx3(TextDateInput, { ariaLabel: "Date of service", value: bill.service.date, disabled: locked, required: true, onChange: (date2) => setBill((c) => ({ ...c, service: { ...c.service, date: date2 } })) }) }),
2013
- /* @__PURE__ */ jsx3(Field2, { label: "Date of injury", children: /* @__PURE__ */ jsx3(TextDateInput, { ariaLabel: "Date of injury", value: bill.claim.dateOfInjury, disabled: locked, onChange: (dateOfInjury) => setBill((c) => ({ ...c, claim: { ...c.claim, dateOfInjury } })) }) }),
2014
- /* @__PURE__ */ jsx3(Field2, { label: "Employer (optional)", children: text(bill.claim.employer, (employer) => setBill((c) => ({ ...c, claim: { ...c.claim, employer } }))) }),
2059
+ /* @__PURE__ */ jsx3(Field2, { path: "claim.dateOfInjury", label: "Date of injury", required: true, error: errors["claim.dateOfInjury"], children: /* @__PURE__ */ jsx3(TextDateInput, { ariaLabel: "Date of injury", value: bill.claim.dateOfInjury, disabled: locked, required: true, onChange: (dateOfInjury) => setBill((c) => ({ ...c, claim: { ...c.claim, dateOfInjury } })) }) }),
2060
+ /* @__PURE__ */ jsx3(Field2, { path: "claim.employer", label: "Employer name", required: true, error: errors["claim.employer"], children: text(bill.claim.employer, (employer) => setBill((c) => ({ ...c, claim: { ...c.claim, employer } }))) }),
2015
2061
  /* @__PURE__ */ jsx3(Field2, { path: "claim.claimNumber", label: "Claim number", required: true, error: errors["claim.claimNumber"], children: text(bill.claim.claimNumber, (claimNumber) => setBill((c) => ({ ...c, claim: { ...c.claim, claimNumber } }))) }),
2016
2062
  /* @__PURE__ */ jsx3(Field2, { label: "WCAB / ADJ number (optional)", children: text(bill.claim.adjNumber, (adjNumber) => setBill((c) => ({ ...c, claim: { ...c.claim, adjNumber } }))) }),
2017
2063
  /* @__PURE__ */ jsxs3(Field2, { path: "claim.claimsAdministrator", label: "Claims administrator", required: true, span: true, error: claimsAdministratorError, children: [
@@ -2073,17 +2119,34 @@ function BillSubmissionForm({
2073
2119
  const providersSection = /* @__PURE__ */ jsxs3("fieldset", { className: "mbsf-card", disabled: locked, children: [
2074
2120
  /* @__PURE__ */ jsx3("legend", { className: "mbsf-legend", children: "Providers & place of service" }),
2075
2121
  /* @__PURE__ */ jsxs3("div", { className: "mbsf-grid", children: [
2076
- /* @__PURE__ */ jsx3(Field2, { label: "Billing provider", children: text(bill.billingProvider?.name, (name) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, name } }))) }),
2077
- /* @__PURE__ */ jsx3(Field2, { label: "Billing tax ID", children: text(bill.billingProvider?.taxId, (taxId) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, taxId } }))) }),
2078
- /* @__PURE__ */ jsx3(Field2, { label: "Billing NPI", children: text(bill.billingProvider?.npi, (npi) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, npi } }))) }),
2079
- /* @__PURE__ */ jsx3(Field2, { label: "Billing phone", children: text(bill.billingProvider?.phone, (phone) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, phone } })), { type: "tel" }) }),
2080
- /* @__PURE__ */ jsx3(Field2, { label: "Rendering provider", children: text(bill.renderingProvider?.name, (name) => setBill((c) => ({ ...c, renderingProvider: { ...c.renderingProvider, name } }))) }),
2081
- /* @__PURE__ */ jsx3(Field2, { label: "Specialty", children: text(bill.renderingProvider?.specialty, (specialty) => setBill((c) => ({ ...c, renderingProvider: { ...c.renderingProvider, specialty } }))) }),
2082
- /* @__PURE__ */ jsx3(Field2, { label: "Rendering NPI", children: text(bill.renderingProvider?.npi, (npi) => setBill((c) => ({ ...c, renderingProvider: { ...c.renderingProvider, npi } }))) }),
2083
- /* @__PURE__ */ jsx3(Field2, { label: "License number", children: text(bill.renderingProvider?.licenseNumber, (licenseNumber) => setBill((c) => ({ ...c, renderingProvider: { ...c.renderingProvider, licenseNumber } }))) }),
2084
- /* @__PURE__ */ jsx3(Field2, { label: "License state", children: text(bill.renderingProvider?.licenseState, (licenseState) => setBill((c) => ({ ...c, renderingProvider: { ...c.renderingProvider, licenseState: licenseState.toUpperCase() } })), { maxLength: 2 }) }),
2085
- /* @__PURE__ */ jsx3(Field2, { label: "Service location", children: text(bill.serviceLocation?.name, (name) => setBill((c) => ({ ...c, serviceLocation: { ...c.serviceLocation, name } }))) }),
2086
- /* @__PURE__ */ jsx3(Field2, { label: "Place of service", children: text(bill.serviceLocation?.placeOfServiceCode, (placeOfServiceCode) => setBill((c) => ({ ...c, serviceLocation: { ...c.serviceLocation, placeOfServiceCode } })), { maxLength: 2 }) })
2122
+ /* @__PURE__ */ jsx3("h4", { className: "mbsf-subhead", children: "Billing provider" }),
2123
+ /* @__PURE__ */ jsx3(Field2, { path: "billingProvider.name", label: "Billing provider name", required: true, error: errors["billingProvider.name"], children: text(bill.billingProvider?.name, (name) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, name } }))) }),
2124
+ /* @__PURE__ */ jsx3(Field2, { path: "billingProvider.taxId", label: "Tax ID (EIN / SSN)", required: true, error: errors["billingProvider.taxId"], children: text(bill.billingProvider?.taxId, (taxId) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, taxId } })), { inputMode: "numeric" }) }),
2125
+ /* @__PURE__ */ jsx3(Field2, { path: "billingProvider.npi", label: "Billing provider NPI", required: true, error: errors["billingProvider.npi"], children: text(bill.billingProvider?.npi, (npi) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, npi } })), { inputMode: "numeric", maxLength: 10 }) }),
2126
+ /* @__PURE__ */ jsx3(Field2, { path: "billingProvider.phone", label: "Billing provider phone", required: true, error: errors["billingProvider.phone"], children: text(bill.billingProvider?.phone, (phone) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, phone } })), { type: "tel" }) }),
2127
+ /* @__PURE__ */ jsx3(Field2, { path: "billingProvider.address.line1", label: "Billing address line 1", required: true, span: true, error: errors["billingProvider.address.line1"], children: text(bill.billingProvider?.address?.line1, (line1) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, address: { line1, line2: c.billingProvider?.address?.line2 ?? "", city: c.billingProvider?.address?.city ?? "", state: c.billingProvider?.address?.state ?? "", postalCode: c.billingProvider?.address?.postalCode ?? "" } } }))) }),
2128
+ /* @__PURE__ */ jsx3(Field2, { label: "Billing address line 2 (optional)", span: true, children: text(bill.billingProvider?.address?.line2, (line2) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, address: { line1: c.billingProvider?.address?.line1 ?? "", line2, city: c.billingProvider?.address?.city ?? "", state: c.billingProvider?.address?.state ?? "", postalCode: c.billingProvider?.address?.postalCode ?? "" } } }))) }),
2129
+ /* @__PURE__ */ jsx3(Field2, { path: "billingProvider.address.city", label: "Billing city", required: true, error: errors["billingProvider.address.city"], children: text(bill.billingProvider?.address?.city, (city) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, address: { line1: c.billingProvider?.address?.line1 ?? "", line2: c.billingProvider?.address?.line2 ?? "", city, state: c.billingProvider?.address?.state ?? "", postalCode: c.billingProvider?.address?.postalCode ?? "" } } }))) }),
2130
+ /* @__PURE__ */ jsx3(Field2, { path: "billingProvider.address.state", label: "Billing state", required: true, error: errors["billingProvider.address.state"], children: text(bill.billingProvider?.address?.state, (state) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, address: { line1: c.billingProvider?.address?.line1 ?? "", line2: c.billingProvider?.address?.line2 ?? "", city: c.billingProvider?.address?.city ?? "", state: state.toUpperCase(), postalCode: c.billingProvider?.address?.postalCode ?? "" } } })), { maxLength: 2 }) }),
2131
+ /* @__PURE__ */ jsx3(Field2, { path: "billingProvider.address.postalCode", label: "Billing ZIP", required: true, error: errors["billingProvider.address.postalCode"], children: text(bill.billingProvider?.address?.postalCode, (postalCode) => setBill((c) => ({ ...c, billingProvider: { ...c.billingProvider, address: { line1: c.billingProvider?.address?.line1 ?? "", line2: c.billingProvider?.address?.line2 ?? "", city: c.billingProvider?.address?.city ?? "", state: c.billingProvider?.address?.state ?? "", postalCode } } }))) }),
2132
+ /* @__PURE__ */ jsx3("h4", { className: "mbsf-subhead", children: "Rendering provider" }),
2133
+ /* @__PURE__ */ jsx3(Field2, { path: "renderingProvider.name", label: "Rendering provider name", required: true, error: errors["renderingProvider.name"], children: text(bill.renderingProvider?.name, (name) => setBill((c) => ({ ...c, renderingProvider: { ...c.renderingProvider, name } }))) }),
2134
+ /* @__PURE__ */ jsx3(Field2, { path: "renderingProvider.npi", label: "Rendering provider NPI", required: true, error: errors["renderingProvider.npi"], children: text(bill.renderingProvider?.npi, (npi) => setBill((c) => ({ ...c, renderingProvider: { ...c.renderingProvider, npi } })), { inputMode: "numeric", maxLength: 10 }) }),
2135
+ /* @__PURE__ */ jsxs3(Field2, { path: "renderingProvider.taxonomy", label: "Rendering taxonomy code", required: true, error: errors["renderingProvider.taxonomy"], children: [
2136
+ text(bill.renderingProvider?.taxonomy, (taxonomy) => setBill((c) => ({ ...c, renderingProvider: { ...c.renderingProvider, taxonomy: taxonomy.toUpperCase() } })), { maxLength: 10, placeholder: "10-character NUCC code" }),
2137
+ /* @__PURE__ */ jsx3("small", { className: "mbsf-help", children: "Sent in CMS-1500 Box 24J with qualifier ZZ." })
2138
+ ] }),
2139
+ /* @__PURE__ */ jsx3(Field2, { label: "Specialty (optional)", children: text(bill.renderingProvider?.specialty, (specialty) => setBill((c) => ({ ...c, renderingProvider: { ...c.renderingProvider, specialty } }))) }),
2140
+ /* @__PURE__ */ jsx3(Field2, { label: "License number (optional)", children: text(bill.renderingProvider?.licenseNumber, (licenseNumber) => setBill((c) => ({ ...c, renderingProvider: { ...c.renderingProvider, licenseNumber } }))) }),
2141
+ /* @__PURE__ */ jsx3(Field2, { label: "License state (optional)", children: text(bill.renderingProvider?.licenseState, (licenseState) => setBill((c) => ({ ...c, renderingProvider: { ...c.renderingProvider, licenseState: licenseState.toUpperCase() } })), { maxLength: 2 }) }),
2142
+ /* @__PURE__ */ jsx3("h4", { className: "mbsf-subhead", children: "Service facility (CMS-1500 Box 32)" }),
2143
+ /* @__PURE__ */ jsx3(Field2, { label: "Service facility name (optional)", children: text(bill.serviceLocation?.name, (name) => setBill((c) => ({ ...c, serviceLocation: { ...c.serviceLocation, name } }))) }),
2144
+ /* @__PURE__ */ jsx3(Field2, { path: "serviceLocation.placeOfServiceCode", label: "Place of service code", required: true, error: errors["serviceLocation.placeOfServiceCode"], children: text(bill.serviceLocation?.placeOfServiceCode, (placeOfServiceCode) => setBill((c) => ({ ...c, serviceLocation: { ...c.serviceLocation, placeOfServiceCode } })), { inputMode: "numeric", maxLength: 2, placeholder: "11" }) }),
2145
+ /* @__PURE__ */ jsx3(Field2, { path: "serviceLocation.address.line1", label: "Service address line 1", required: true, span: true, error: errors["serviceLocation.address.line1"], children: text(bill.serviceLocation?.address?.line1, (line1) => setBill((c) => ({ ...c, serviceLocation: { ...c.serviceLocation, address: { line1, line2: c.serviceLocation?.address?.line2 ?? "", city: c.serviceLocation?.address?.city ?? "", state: c.serviceLocation?.address?.state ?? "", postalCode: c.serviceLocation?.address?.postalCode ?? "" } } }))) }),
2146
+ /* @__PURE__ */ jsx3(Field2, { label: "Service address line 2 (optional)", span: true, children: text(bill.serviceLocation?.address?.line2, (line2) => setBill((c) => ({ ...c, serviceLocation: { ...c.serviceLocation, address: { line1: c.serviceLocation?.address?.line1 ?? "", line2, city: c.serviceLocation?.address?.city ?? "", state: c.serviceLocation?.address?.state ?? "", postalCode: c.serviceLocation?.address?.postalCode ?? "" } } }))) }),
2147
+ /* @__PURE__ */ jsx3(Field2, { path: "serviceLocation.address.city", label: "Service city", required: true, error: errors["serviceLocation.address.city"], children: text(bill.serviceLocation?.address?.city, (city) => setBill((c) => ({ ...c, serviceLocation: { ...c.serviceLocation, address: { line1: c.serviceLocation?.address?.line1 ?? "", line2: c.serviceLocation?.address?.line2 ?? "", city, state: c.serviceLocation?.address?.state ?? "", postalCode: c.serviceLocation?.address?.postalCode ?? "" } } }))) }),
2148
+ /* @__PURE__ */ jsx3(Field2, { path: "serviceLocation.address.state", label: "Service state", required: true, error: errors["serviceLocation.address.state"], children: text(bill.serviceLocation?.address?.state, (state) => setBill((c) => ({ ...c, serviceLocation: { ...c.serviceLocation, address: { line1: c.serviceLocation?.address?.line1 ?? "", line2: c.serviceLocation?.address?.line2 ?? "", city: c.serviceLocation?.address?.city ?? "", state: state.toUpperCase(), postalCode: c.serviceLocation?.address?.postalCode ?? "" } } })), { maxLength: 2 }) }),
2149
+ /* @__PURE__ */ jsx3(Field2, { path: "serviceLocation.address.postalCode", label: "Service ZIP", required: true, error: errors["serviceLocation.address.postalCode"], children: text(bill.serviceLocation?.address?.postalCode, (postalCode) => setBill((c) => ({ ...c, serviceLocation: { ...c.serviceLocation, address: { line1: c.serviceLocation?.address?.line1 ?? "", line2: c.serviceLocation?.address?.line2 ?? "", city: c.serviceLocation?.address?.city ?? "", state: c.serviceLocation?.address?.state ?? "", postalCode } } }))) })
2087
2150
  ] })
2088
2151
  ] });
2089
2152
  const serviceLinesSection = /* @__PURE__ */ jsxs3("fieldset", { className: "mbsf-card", disabled: locked, children: [
@@ -2093,9 +2156,15 @@ function BillSubmissionForm({
2093
2156
  /* @__PURE__ */ jsx3("p", { className: "mbsf-help", children: evaluationType === "ame" ? "Agreed Medical Evaluator \u2014 eligible ML evaluation codes default to modifier -94." : evaluationType === "psych_qme" ? "Psychiatric QME \u2014 eligible ML evaluation codes default to modifier -96 (-95 for ML200)." : "Qualified Medical Evaluator \u2014 eligible ML evaluation codes default to modifier -95." }),
2094
2157
  /* @__PURE__ */ jsxs3("div", { className: "mbsf-lines", "data-field-path": "serviceLines", "data-invalid": Boolean(errors.serviceLines), children: [
2095
2158
  /* @__PURE__ */ jsxs3("div", { className: "mbsf-line-head", children: [
2096
- /* @__PURE__ */ jsx3("span", { children: "Procedure code" }),
2159
+ /* @__PURE__ */ jsxs3("span", { children: [
2160
+ "Procedure code",
2161
+ /* @__PURE__ */ jsx3(RequiredMark, {})
2162
+ ] }),
2097
2163
  /* @__PURE__ */ jsx3("span", { children: "Modifiers" }),
2098
- /* @__PURE__ */ jsx3("span", { children: "Units" }),
2164
+ /* @__PURE__ */ jsxs3("span", { children: [
2165
+ "Units",
2166
+ /* @__PURE__ */ jsx3(RequiredMark, {})
2167
+ ] }),
2099
2168
  /* @__PURE__ */ jsx3("span", { children: "Allowed" }),
2100
2169
  /* @__PURE__ */ jsx3("span", {}),
2101
2170
  " "