import { L as Layout } from "./style-5e656732.js";
import { P as PropTypes, r as reactExports, a as classnames, j as jsxRuntimeExports, l as libExports, v as validateCsv, b as validateJson, c as client, R as React } from "./vendor-23e3c97a.js";
const SPACER_GIF = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
const FileInput = ({
  name,
  id,
  disabled,
  className,
  accept,
  onChange,
  onDrop,
  ...inputProps
}) => {
  const internalRef = reactExports.useRef(null);
  const [file, setFile] = reactExports.useState(null);
  const [isDragging, setIsDragging] = reactExports.useState(false);
  const [showError, setShowError] = reactExports.useState(false);
  const [hideDragText, setHideDragText] = reactExports.useState(false);
  reactExports.useEffect(() => {
    if (typeof navigator === "undefined")
      return;
    const hideDragText2 = /rv:11.0/i.test(navigator == null ? void 0 : navigator.userAgent) || /Edge\/\d./i.test(navigator == null ? void 0 : navigator.userAgent);
    setHideDragText(hideDragText2);
  }, [typeof navigator]);
  const fileInputClasses = classnames(
    "usa-file-input",
    {
      "usa-file-input--disabled": disabled
    },
    className
  );
  const targetClasses = classnames("usa-file-input__target", {
    "usa-file-input--drag": isDragging,
    "has-invalid-file": showError
  });
  const instructionClasses = classnames("usa-file-input__instructions", {
    "display-none": !!file
  });
  const preventInvalidFiles = (e) => {
    setShowError(false);
    if (accept) {
      const acceptedTypes = accept.split(",");
      let allFilesAllowed = true;
      for (let i = 0; i < e.target.files.length; i += 1) {
        const file2 = e.target.files[parseInt(`${i}`)];
        if (allFilesAllowed) {
          for (let j = 0; j < acceptedTypes.length; j += 1) {
            const fileType = acceptedTypes[parseInt(`${j}`)];
            allFilesAllowed = file2.name.indexOf(fileType) > 0 || file2.type.includes(fileType.replace(/\*/g, ""));
            if (allFilesAllowed)
              break;
          }
        } else
          break;
      }
      if (!allFilesAllowed) {
        setFile(null);
        setShowError(true);
        e.preventDefault();
        e.stopPropagation();
      }
      return allFilesAllowed;
    }
  };
  const handleDragOver = () => setIsDragging(true);
  const handleDragLeave = () => setIsDragging(false);
  const handleDrop = (e) => {
    setIsDragging(false);
    if (onDrop)
      onDrop(e);
  };
  const handleChange = (e) => {
    const allFilesAllowed = preventInvalidFiles(e);
    if (allFilesAllowed) {
      setFile(e.target.files.length > 0 ? e.target.files[0] : null);
      if (onChange)
        onChange(e);
    }
  };
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
    "div",
    {
      "data-testid": "file-input",
      className: fileInputClasses,
      "aria-disabled": disabled,
      children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
        "div",
        {
          "data-testid": "file-input-droptarget",
          className: targetClasses,
          onDragOver: handleDragOver,
          onDragLeave: handleDragLeave,
          onDrop: handleDrop,
          children: [
            file && /* @__PURE__ */ jsxRuntimeExports.jsxs(
              "div",
              {
                "data-testid": "file-input-preview-heading",
                className: "usa-file-input__preview-heading",
                children: [
                  "Selected file",
                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "usa-file-input__choose", children: "Change file" })
                ]
              }
            ),
            /* @__PURE__ */ jsxRuntimeExports.jsxs(
              "div",
              {
                "data-testid": "file-input-instructions",
                className: instructionClasses,
                "aria-hidden": "true",
                children: [
                  !hideDragText && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "usa-file-input__drag-text", children: [
                    "Drag file here or",
                    " "
                  ] }),
                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "usa-file-input__choose", children: "choose from folder" })
                ]
              }
            ),
            file && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "usa-file-input__preview", "aria-hidden": "true", children: [
              /* @__PURE__ */ jsxRuntimeExports.jsx(
                "img",
                {
                  src: SPACER_GIF,
                  className: "usa-file-input__preview-image usa-file-input__preview-image--generic"
                }
              ),
              file.name
            ] }),
            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-testid": "file-input-box", className: "usa-file-input__box" }),
            showError && /* @__PURE__ */ jsxRuntimeExports.jsx(
              "div",
              {
                "data-testid": "file-input-error",
                className: "usa-file-input__accepted-files-message",
                children: "This is not a valid file type."
              }
            ),
            /* @__PURE__ */ jsxRuntimeExports.jsx(
              "input",
              {
                ...inputProps,
                ref: internalRef,
                type: "file",
                "data-testid": "file-input-input",
                name,
                id,
                className: "usa-file-input__input",
                disabled,
                onChange: handleChange,
                accept
              }
            )
          ]
        }
      )
    }
  );
};
FileInput.propTypes = {
  name: PropTypes.string,
  id: PropTypes.string,
  disabled: PropTypes.bool,
  className: PropTypes.string,
  accept: PropTypes.string,
  onChange: PropTypes.func,
  onDrop: PropTypes.func
};
const ValidationResults = ({
  filename,
  valid,
  errors,
  warnings,
  maxErrors,
  locationHeader,
  loading,
  readError,
  didMount
}) => {
  const resultsHeaderRef = reactExports.useRef(null);
  const atMaxErrors = errors.length >= maxErrors;
  const atMaxWarnings = warnings.length >= maxErrors;
  reactExports.useEffect(() => {
    if (didMount && !loading && resultsHeaderRef.current) {
      resultsHeaderRef.current.scrollIntoView({
        behavior: "smooth",
        align: "top"
      });
      resultsHeaderRef.current.focus();
    }
  }, [didMount, loading]);
  return /* @__PURE__ */ jsxRuntimeExports.jsx(libExports.Grid, { row: true, gap: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "usa-prose width-full", children: [
    /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { id: "validation-results-header", tabIndex: "-1", ref: resultsHeaderRef, children: "Validation results" }),
    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { id: "validation-results-body", children: [
      loading && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "font-sans-l loading-skeleton", children: [
        "Your file is processing. Some larger files may take a minute or two. Results will appear here once completed. If you are experiencing issues, please let us know at :",
        " ",
        /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "mailto:PriceTransparencyHospitalCharges@cms.hhs.gov", children: "PriceTransparencyHospitalCharges@cms.hhs.gov" }),
        "."
      ] }),
      readError && /* @__PURE__ */ jsxRuntimeExports.jsx(libExports.Alert, { type: `error`, "aria-live": "polite", "aria-atomic": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "There's something preventing your file from being machine readable. Please check your file to make sure it is readable and then try again." }) }),
      !loading && !readError && filename && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
        /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { children: "Errors" }),
        /* @__PURE__ */ jsxRuntimeExports.jsx(
          libExports.Alert,
          {
            type: valid ? `success` : `error`,
            "aria-live": "polite",
            "aria-atomic": "true",
            children: valid ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-bold", children: "No errors found in file" }),
              ":",
              " ",
              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-underline", children: filename })
            ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
              /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-bold", children: [
                "There",
                errors.length === 1 ? " is 1 error" : ` are ${atMaxErrors ? "at least " : ""}${errors.length} errors`,
                " ",
                "found in the file"
              ] }),
              ": ",
              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-underline", children: filename }),
              /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
              atMaxErrors && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
                "The first ",
                maxErrors,
                " errors are shown below. See the",
                " ",
                /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "https://github.com/CMSgov/hospital-price-transparency/", children: "Hospital Price Transparency Data Dictionary GitHub Repository" }),
                " ",
                "for detailed technical specifications to understand and address these errors."
              ] }),
              !atMaxErrors && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
                "See the",
                " ",
                /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "https://github.com/CMSgov/hospital-price-transparency/", children: "Hospital Price Transparency Data Dictionary GitHub Repository" }),
                " ",
                "for detailed technical specifications to understand and address these errors."
              ] })
            ] })
          }
        ),
        errors.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(libExports.Table, { className: "width-full", bordered: true, striped: true, children: [
          /* @__PURE__ */ jsxRuntimeExports.jsx("thead", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { children: [
            /* @__PURE__ */ jsxRuntimeExports.jsx("th", { scope: "col", children: locationHeader }),
            /* @__PURE__ */ jsxRuntimeExports.jsx("th", { scope: "col", children: "Error description" })
          ] }) }),
          /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: errors.slice(0, maxErrors).map(({ path, message }, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { children: [
            /* @__PURE__ */ jsxRuntimeExports.jsx("td", { children: path }),
            /* @__PURE__ */ jsxRuntimeExports.jsx("td", { children: message })
          ] }, index)) })
        ] }) }),
        /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { children: "Warnings" }),
        /* @__PURE__ */ jsxRuntimeExports.jsx(libExports.Alert, { type: warnings.length === 0 ? `success` : `warning`, children: warnings.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-bold", children: "No warnings found in file" }),
          ": ",
          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-underline", children: filename })
        ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-bold", children: [
            "There",
            warnings.length === 1 ? " is 1 warning" : ` are ${atMaxWarnings ? "at least " : ""}${warnings.length} warnings`,
            " ",
            "found in the file"
          ] }),
          ": ",
          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-underline", children: filename }),
          /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
          atMaxWarnings && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
            "The first ",
            maxErrors,
            " warnings are shown below."
          ] }),
          /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "These warnings represent requirements that are enforced beginning January 1, 2025." })
        ] }) }),
        warnings.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(libExports.Table, { className: "width-full", bordered: true, striped: true, children: [
          /* @__PURE__ */ jsxRuntimeExports.jsx("thead", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { children: [
            /* @__PURE__ */ jsxRuntimeExports.jsx("th", { scope: "col", children: locationHeader }),
            /* @__PURE__ */ jsxRuntimeExports.jsx("th", { scope: "col", children: "Warning description" })
          ] }) }),
          /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: warnings.slice(0, maxErrors).map(({ path, message }, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { children: [
            /* @__PURE__ */ jsxRuntimeExports.jsx("td", { children: path }),
            /* @__PURE__ */ jsxRuntimeExports.jsx("td", { children: message })
          ] }, index)) })
        ] })
      ] })
    ] })
  ] }) });
};
ValidationResults.propTypes = {
  filename: PropTypes.string,
  valid: PropTypes.bool,
  errors: PropTypes.arrayOf(PropTypes.object),
  warnings: PropTypes.arrayOf(PropTypes.object),
  maxErrors: PropTypes.number,
  locationHeader: PropTypes.string,
  loading: PropTypes.bool,
  readError: PropTypes.bool,
  didMount: PropTypes.bool
};
const MAX_ERRORS = 250;
const STORAGE_PATH = "cms-hpt-validation-results";
const getFileExtension = (filename) => {
  const splitFilename = filename.toLowerCase().split(".");
  if (splitFilename.length < 1)
    return null;
  return splitFilename.slice(-1)[0];
};
const OnlineValidator = () => {
  const [state, setState] = reactExports.useState(
    JSON.parse(window.sessionStorage.getItem(STORAGE_PATH)) || {
      valid: true,
      filename: "",
      schemaVersion: "v2.0",
      fileUrl: "",
      pageUrl: "",
      loading: false,
      didMount: false,
      readError: false,
      errors: [],
      warnings: []
    }
  );
  const validateFile = async (evt) => {
    const file = evt.target.files[0];
    const initialState = {
      filename: file.name,
      schemaVersion: state.schemaVersion
    };
    setState({ ...state, ...initialState, readError: false, loading: true });
    const fileExt = getFileExtension(file.name);
    if (["csv", "json"].includes(fileExt)) {
      try {
        const { valid, errors } = await (fileExt === "csv" ? validateCsv(file, state.schemaVersion, { maxErrors: MAX_ERRORS }) : validateJson(file, state.schemaVersion, { maxErrors: MAX_ERRORS }));
        const stateObj = {
          ...initialState,
          valid,
          errors: errors.filter(({ warning }) => !warning),
          warnings: errors.filter(({ warning }) => warning),
          loading: false,
          didMount: true
        };
        setState(stateObj);
        window.sessionStorage.setItem(STORAGE_PATH, JSON.stringify(stateObj));
      } catch (error) {
        console.error(error);
        setState({
          ...initialState,
          loading: false,
          didMount: true,
          readError: true
        });
      }
    }
  };
  const locationHeader = getFileExtension(state.filename) === "csv" ? "CSV cell" : "JSON location";
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(Layout, { children: [
    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-base-lightest", children: /* @__PURE__ */ jsxRuntimeExports.jsx("section", { className: "grid-container usa-section", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(libExports.Grid, { row: true, gap: true, children: [
      /* @__PURE__ */ jsxRuntimeExports.jsxs(
        libExports.Grid,
        {
          desktop: { col: 6 },
          className: "bg-white flex-align-self-start margin-bottom-4",
          children: [
            /* @__PURE__ */ jsxRuntimeExports.jsx("form", { action: "", method: "GET", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(libExports.FormGroup, { children: [
              /* @__PURE__ */ jsxRuntimeExports.jsxs(libExports.Label, { htmlFor: "file-input", children: [
                /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "font-sans-xl text-bold margin-bottom-0", children: "Upload file" }),
                "Files must be in a required CMS template format (.json or .csv)"
              ] }),
              /* @__PURE__ */ jsxRuntimeExports.jsx(
                FileInput,
                {
                  id: "file-input",
                  name: "file-input",
                  accept: ".csv,.json,text/csv,application/json",
                  onChange: validateFile
                }
              )
            ] }) }),
            state.loading && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { "aria-live": "polite", "aria-atomic": "true", className: "text-bold", children: [
              "Loading file ",
              state.filename,
              "..."
            ] })
          ]
        }
      ),
      /* @__PURE__ */ jsxRuntimeExports.jsx(
        libExports.Grid,
        {
          gap: true,
          desktop: { col: 6 },
          className: "border-top border-base-lighter padding-top-4 desktop:border-0 desktop:padding-top-0",
          children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "usa-prose", children: [
            /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: "About This Tool" }),
            /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
              "The V2.0 Online Validator tool assists your hospital in developing a machine- readable file (MRF) to ensure it conforms to the required form and manner requirements (45 CFR 180.50(c)(2)). These form and manner requirements are described in the",
              " ",
              /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "https://www.federalregister.gov/documents/2023/11/22/2023-24293/medicare-program-hospital-outpatient-prospective-payment-and-ambulatory-surgical-center-payment", children: "CY 2024 OPPS/ASC Final Rule" }),
              ", and detailed technical specifications can be found in the",
              " ",
              /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "https://github.com/CMSgov/hospital-price-transparency/", children: "Hospital Price Transparency Data Dictionary GitHub Repository" }),
              "."
            ] }),
            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "The Online Validator reviews your uploaded MRF against the required CMS template layout and data specifications. If your MRF does not conform to the form and manner requirements, the Online Validator will generate an output consisting of 'errors' and 'warnings'. Online Validator 'errors' represent requirements that are enforced beginning July 1, 2024, whereas 'warnings' represent requirements that are enforced beginning January 1, 2025. The Online Validator stops reviewing an MRF if there are more than 250 errors. Additionally for CSV MRFs, the Online Validator stops reviewing if an error is found in row 1 through 3 (i.e., errors in the general data element headers, general data element values, and standard charges, item/service, and coding headers). You should therefore address each error displayed and run your MRF through the Online Validator repeatedly until no more errors are generated." }),
            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Please note: Leveraging the Validator helps ensure adherence to CMS form and manner requirements (45 CFR 180.50(c)(2)), but it does not certify that your MRF fully complies with all HPT requirements at 45 CFR 180.50." }) }),
            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Additionally, the Online Validator tool runs in a web browser and does not store, record, report, or share any information with CMS related to your hospital's use of the tool. In short, CMS does not track individual hospitals' use of the Online Validator. However, if your hospital becomes subject to a compliance review, CMS may use the Validator to assess whether your hospital meets the form and manner requirements." }),
            /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
              "For a video demonstration of how to use the CMS Hospital Price Transparency Online Validator tool, please visit",
              " ",
              /* @__PURE__ */ jsxRuntimeExports.jsx(
                "a",
                {
                  target: "_blank",
                  href: "https://www.youtube.com/watch?v=e6b9kN9B11c",
                  rel: "noreferrer",
                  children: "https://www.youtube.com/watch?v=e6b9kN9B11c"
                }
              ),
              " "
            ] }),
            /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
              "For frequently asked questions and answers about the validator, please refer to the",
              " ",
              /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "https://www.cms.gov/files/document/hospital-price-transparency-validator-faqs.pdf", children: "Validator FAQs" }),
              ". Additional resources are available on the",
              " ",
              /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "https://www.cms.gov/priorities/key-initiatives/hospital-price-transparency/resources", children: "Hospital Price Transparency Resources Page" }),
              ". For other validator questions or concerns, you may email",
              " ",
              /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "mailto:PriceTransparencyHospitalCharges@cms.hhs.gov", children: "PriceTransparencyHospitalCharges@cms.hhs.gov" })
            ] }),
            /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
            /* @__PURE__ */ jsxRuntimeExports.jsx("hr", {})
          ] })
        }
      )
    ] }) }) }),
    /* @__PURE__ */ jsxRuntimeExports.jsx("section", { className: "grid-container usa-section", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
      ValidationResults,
      {
        filename: state.filename,
        valid: state.valid,
        errors: state.errors,
        warnings: state.warnings,
        maxErrors: MAX_ERRORS,
        locationHeader,
        readError: state.readError,
        loading: state.loading,
        didMount: state.didMount
      }
    ) })
  ] });
};
const root = client.createRoot(document.getElementById("root"));
root.render(
  /* @__PURE__ */ jsxRuntimeExports.jsx(React.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(OnlineValidator, {}) })
);
