All files / src/components/Layout/Menu Menu.tsx

100% Statements 23/23
42.85% Branches 21/49
100% Functions 7/7
100% Lines 23/23

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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153                                          23x       23x 23x 23x 23x 23x 23x   23x           91x 91x 91x                                                         2x 48x 23x         2x                 2x   548x                                 91x 91x 91x 91x 91x 91x                                                                                      
// mui
import { Stack } from "@mui/material";
// types
import { MenuListItemV2 } from "types/data.types";
// router-dom
import { Link, useLocation } from "react-router-dom";
// components
import MobileMenu from "./MobileMenu";
import { getActiveItem } from "@utils/index";
import { useTranslation } from "react-i18next";
import { namespaces } from "@localization/resources/i18n.constants";
import { styled, useAppTheme } from "@theme/v2/Provider";
import { useCustomThemeV2 } from "@theme/hooks/useCustomThemeV2";
import useThemeSettings from "@components/EnterpriseSettings/Branding/hooks/useThemeSettings";
import { StyledTitle } from "@shared/Banner/styles";
 
interface MenuProps {
  menu: MenuListItemV2[];
  isHorizontal?: boolean;
}
export default function Menu({ ...props }: MenuProps) {
  return <GiveMenu {...props} />;
}
 
export function GiveMenu({ menu, isHorizontal }: MenuProps) {
  const { pathname } = useLocation();
  const theme = useAppTheme();
  const { isTabletView, isMobileView } = useCustomThemeV2();
  const isTabletOrMobile = isTabletView || isMobileView;
  const { t } = useTranslation(namespaces.pages.settings);
  const { textColor, isGradientText } = useThemeSettings();
 
  return (
    <>
      {!isTabletOrMobile ? (
        <List>
          <FixedWrapper isHorizontal={isHorizontal}>
            {menu.map((item: MenuListItemV2, index: number) => {
              const { path, name } = item || {};
              const isActive = getActiveItem(path, pathname);
              return (
                <ItemContainer
                  key={index}
                  isActive={isActive}
                  to={item.path}
                  borderPosition={isHorizontal ? "bottom" : "left"}
                  themeColor={textColor}
                  isGradientText={isGradientText}
                >
                  <StyledTitle
                    variant="bodyS"
                    theme={theme}
                    textColor={textColor}
                    isActive={isActive}
                  >
                    {t(name)}
                  </StyledTitle>
                </ItemContainer>
              );
            })}
          </FixedWrapper>
        </List>
      ) : (
        <MobileMenu menu={menu} />
      )}
    </>
  );
}
 
const FixedWrapper = styled(Stack, {
  shouldForwardProp: (prop) => prop !== "isHorizontal",
})(({ isHorizontal }: { isHorizontal?: boolean }) => ({
  position: "fixed",
  flexDirection: isHorizontal ? "row" : "column",
}));
 
const List = styled(Stack)({
  flexShrink: 0,
  height: "auto",
  width: "220px",
  gap: "4px",
  overflowY: "auto",
  overflowX: "hidden",
});
 
const ItemContainer = styled(Link, {
  shouldForwardProp: (prop) =>
    prop !== "isActive" &&
    prop !== "borderPosition" &&
    prop !== "themeColor" &&
    prop != "isGradientText",
})<{
  isActive: boolean;
  borderPosition?: "left" | "bottom";
  themeColor: string;
  isGradientText: boolean;
}>(
  ({
    theme,
    isActive,
    borderPosition = "left",
    themeColor,
    isGradientText,
  }) => {
    const activeColor = themeColor;
    const borderSecondaryColor = theme.palette.border?.secondary;
    const textHoverColor = theme.palette.text.primary;
    const isLeftBorder = borderPosition === "left";
    const isBottomBorder = borderPosition === "bottom";
    return {
      gap: "4px",
      fontSize: 14,
      fontWeight: 350,
      lineHeight: "16.2px",
      padding: isLeftBorder ? "8px 8px 8px 20px" : "8px 12px",
      display: "flex",
      alignItems: "center",
      flexDirection: "row",
      textDecoration: "none",
      cursor: "pointer",
      ...(isGradientText
        ? {
            borderLeft:
              isLeftBorder && isActive
                ? "2px solid transparent"
                : `2px solid ${borderSecondaryColor}`,
            borderImage: isLeftBorder && isActive ? activeColor : "none",
            borderImageSlice: isLeftBorder && isActive ? 1 : undefined,
          }
        : {
            borderLeft: isLeftBorder
              ? `2px solid ${isActive ? activeColor : borderSecondaryColor}`
              : "none",
          }),
 
      borderBottom: isBottomBorder
        ? `2px solid ${isActive ? activeColor : "transparent"}`
        : "none",
      ...(!isActive && {
        "&:hover": {
          color: textHoverColor,
          borderLeft: isLeftBorder
            ? `2px solid ${!isActive ? borderSecondaryColor : activeColor}`
            : "none",
          borderBottom: isBottomBorder
            ? `2px solid ${!isActive ? borderSecondaryColor : activeColor}`
            : "none",
        },
      }),
    };
  },
);