All files / src/components/CustomBreadcrumbsPage CustomBreadcrumbs.tsx

95.45% Statements 21/22
63.63% Branches 7/11
100% Functions 7/7
95.23% Lines 20/21

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                                                      19x               1x 2x       1x   1x 2x   1x         2x 2x   2x 1x                           1x     1x     2x   2x             2x 3x     2x 2x               19x                          
import { BaseLink } from "@common/Campaigns/BaseLink";
import {
  styled,
  BreadcrumbsProps,
  Breadcrumbs as BreadcrumbsMui,
  useTheme,
} from "@mui/material";
 
type BreadcrumbsElementProps = {
  pageName?: string;
  path: string;
};
 
type renderComponentProps<T> = {
  indexes: number[];
  component: React.FC<T>;
};
 
interface StyledBreadcrumbsProps<T extends BreadcrumbsElementProps>
  extends BreadcrumbsProps {
  paths: T[];
  breadcrumbsElements: renderComponentProps<T>[];
  FallbackComponent?: React.FC<T>;
  isAlwaysReturnFallback?: boolean;
  maxElements: number;
}
 
const CustomBreadcrumbs = <T extends BreadcrumbsElementProps>({
  paths,
  breadcrumbsElements,
  FallbackComponent,
  isAlwaysReturnFallback = false,
  maxElements,
  ...rest
}: StyledBreadcrumbsProps<T>) => {
  const allIndexes = breadcrumbsElements.reduce(
    (acc, { indexes }: renderComponentProps<T>) => acc.concat(indexes),
    new Array<number>(),
  );
 
  const maxPaths = paths.slice(0, maxElements);
 
  const shouldRenderFallback = (index: number) =>
    isAlwaysReturnFallback || !allIndexes.includes(index);
 
  const linkWrapper = (
    currentIndex: number,
    path: string,
    component: JSX.Element,
  ) => {
    const theme = useTheme();
    const isLastItem = maxPaths.length - 1 === currentIndex;
 
    if (!isLastItem) {
      return (
        <BaseLink
          data-testid={`${path}-base-link`}
          key={currentIndex}
          link={path}
          sx={{
            "&:hover .MuiTypography-root": {
              color: theme.palette.neutral[100],
            },
          }}
        >
          {component}
        </BaseLink>
      );
    } else return component;
  };
 
  return (
    <StyledBreadcrumbs itemScope {...rest}>
      {maxPaths.map((props, index) => {
        const { path } = props;
 
        Iif (shouldRenderFallback(index) && FallbackComponent)
          return linkWrapper(
            index,
            path,
            <FallbackComponent key={index} {...props} />,
          );
 
        const Component = breadcrumbsElements.find(({ indexes }) =>
          indexes.includes(index),
        )?.component;
 
        Eif (Component)
          return linkWrapper(index, path, <Component key={index} {...props} />);
      })}
    </StyledBreadcrumbs>
  );
};
 
export default CustomBreadcrumbs;
 
const StyledBreadcrumbs = styled(BreadcrumbsMui)(({ theme }) => ({
  marginTop: "3px",
  [".MuiBreadcrumbs-ol"]: {
    flexWrap: "nowrap",
  },
  [".MuiBreadcrumbs-separator"]: {
    fontSize: "20px",
    color: theme.palette.neutral["70"],
    fontWeight: 100,
    margin: "0 15px",
    marginTop: "2px",
  },
}));