All files / react-app/src/components/BreadCrumb BreadCrumb.tsx

82.75% Statements 24/29
74.07% Branches 20/27
100% Functions 10/10
81.48% Lines 22/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122                                  97x 1483x                     1483x 770x                                       97x 4x   4x 1x 3x   3x   3x   3x 1x 2x   2x       4x 2x         2x           97x                               4x                             1492x   97x              
import { ChevronRight } from "lucide-react";
import { type ReactNode } from "react";
import { Link } from "react-router";
 
import { sendGAEvent } from "@/utils/ReactGA/SendGAEvent";
 
type BreadCrumbsProps = {
  options: BreadCrumbConfig[];
};
 
export type BreadCrumbConfig = {
  default?: boolean;
  order: number;
  to: string;
  displayText: string;
};
 
export const BreadCrumbs = ({ options }: BreadCrumbsProps) => {
  const defaultBreadCrumb = options.find((option) => option.default);
 
  return (
    <BreadCrumbBar>
      {defaultBreadCrumb && (
        <BreadCrumb to={defaultBreadCrumb.to} showSeperator={false}>
          {defaultBreadCrumb.displayText}
        </BreadCrumb>
      )}
      {/* After this we map over the config and check to see if the breadcrumb needs to be displayed. Proper route paths are important here. It should be hierarchical */}
      {options
        .filter((option) => !option.default)
        .toSorted((option, prevOption) => option.order - prevOption.order)
        .map(({ displayText, to }, index, optionsArray) => {
          return (
            <BreadCrumb key={displayText} to={to} active={index !== optionsArray.length - 1}>
              {displayText}
            </BreadCrumb>
          );
        })}
    </BreadCrumbBar>
  );
};
 
type BreadCrumbProps = {
  to: string;
  active?: boolean;
  showSeperator?: boolean;
  seperator?: ReactNode;
  children?: string;
};
 
const triggerGAEvent = (children: string | undefined) => {
  const pathName = window.location.pathname;
  let submissionType;
  if (pathName.includes("chip")) {
    submissionType = "chip";
  } else Iif (pathName.includes("medicaid")) {
    submissionType = "medicaid";
  } else Iif (pathName.includes("temporary-extensions")) {
    submissionType = "temporary-extension";
  } else Iif (pathName.includes("/waiver/b/b4/initial")) {
    submissionType = "1915b_waiver_initial";
  } else if (pathName.includes("/waiver/b/b4/renewal/")) {
    submissionType = "1915b_waiver_renewal";
  } else Iif (pathName.includes("/waiver/b/b4/amendment/")) {
    submissionType = "1915b_waiver_ammendment";
  } else Iif (pathName.includes("/waiver/app-k")) {
    submissionType = "app-k";
  }
 
  if (submissionType) {
    sendGAEvent("submit_breadcrumb_click", {
      crumb_name: typeof children === "string" ? children : undefined,
      submission_type: submissionType,
    });
  } else {
    sendGAEvent("breadcrumb_click", {
      breadcrumb_text: typeof children === "string" ? children : undefined,
    });
  }
};
 
export const BreadCrumb = ({
  to,
  seperator = <BreadCrumbSeperator />,
  showSeperator = true,
  active = true,
  children,
}: React.PropsWithChildren<BreadCrumbProps>) => {
  return (
    <li className="flex items-center text-sm">
      {showSeperator && <span>{seperator}</span>}
 
      {active && (
        <Link
          to={to}
          className="underline text-sky-700 hover:text-sky-800"
          onClick={() => {
            triggerGAEvent(children);
          }}
        >
          {children}
        </Link>
      )}
      {!active && (
        <span className="whitespace-nowrap" aria-disabled>
          {children}
        </span>
      )}
    </li>
  );
};
 
export const BreadCrumbSeperator = () => <ChevronRight className="w-5 h-5" />;
 
export const BreadCrumbBar = ({ children }: React.PropsWithChildren) => {
  return (
    <nav role="navigation" aria-label="breadcrumbs for spa or waiver choices" className="my-4">
      <ul className="flex flex-wrap gap-1">{children}</ul>
    </nav>
  );
};