Skip to content
Snippets Groups Projects
navbar.jsx 7.81 KiB
Newer Older
Alexander Schoch's avatar
Alexander Schoch committed
import React, { ReactNode, useState, useEffect } from "react";
Alexander Schoch's avatar
Alexander Schoch committed
import Link from "next/link";
import { useRouter } from "next/router";

import { useTranslation } from "next-i18next";
import { useSession } from "next-auth/react";

  Box,
  Button,
  ColorSchemeProvider,
  Group,
  MediaQuery,
  Menu,
} from "@mantine/core";
Alexander Schoch's avatar
Alexander Schoch committed
import { NotificationsProvider } from "@mantine/notifications";
import { useWindowScroll } from "@mantine/hooks";
Alexander Schoch's avatar
Alexander Schoch committed

import { Icon, ICONS } from "vseth-canine-ui";

Alexander Schoch's avatar
Alexander Schoch committed
import { ApolloProvider } from "@apollo/client";
import apolloClient from "../lib/apollo";

import {
  makeVsethTheme,
  useConfig,
  VSETHExternalApp,
  VSETHThemeProvider,
} from "vseth-canine-ui";

import hasAccess from "../utilities/hasAccess";

import LoginButton from "../components/loginButton";
Alexander Schoch's avatar
Alexander Schoch committed
import ThemeSwitcher from "../components/themeSwitcher";
Alexander Schoch's avatar
Alexander Schoch committed

export default function Navbar(props) {
  const router = useRouter();
  const { locale, pathname, asPath, query } = router;
  const { t } = useTranslation("common");
  const { data: session } = useSession();

  const theme = makeVsethTheme();
  const [selectedLanguage, setSelectedLanguage] = React.useState(locale);

  const [colorScheme, setColorScheme] = useState("light");
Alexander Schoch's avatar
Alexander Schoch committed
  const toggleColorScheme = (value) =>
    setColorScheme(value || (colorScheme === "dark" ? "light" : "dark"));
  theme.colorScheme = colorScheme;

  const [scroll, scrollTo] = useWindowScroll();

Alexander Schoch's avatar
Alexander Schoch committed
  /*
   * VSETH Colors: See https://s.aschoch.ch/canine-colors
   * theme.colors.vsethMain[7] is #009fe3 (cyan)
   */
  theme.colors.vsethMain[7] = "#244471";
Alexander Schoch's avatar
Alexander Schoch committed
  theme.colors.vsethMain[0] = "#dee5ef"; // light color
Alexander Schoch's avatar
Alexander Schoch committed
  theme.colors.vsethMain[1] = "#b7cae5"; // light color
  theme.colors.vsethMain[8] = "#4f6d96"; // light color

Alexander Schoch's avatar
Alexander Schoch committed
  theme.colors.orange = [
    "#f28a20",
    "#f28a20",
    "#f28a20",
    "#f28a20",
    "#f28a20",
    "#f28a20",
    "#f28a20",
    "#f28a20",
    "#f28a20",
    "#f28a20",
  ];

  theme.fontSizes = {
    md: 17,
  };

Alexander Schoch's avatar
Alexander Schoch committed
  // NOTE: This is a hack, as colors are hardcoded in vseth-canine
  useEffect(() => {
    const footerDiv = document.querySelector("footer>div");
    const footerLogo = document.querySelector("footer img");
    const selectItems = document.querySelector("header a");

    if (colorScheme == "dark") {
      footerDiv.classList.add("vseth-footer-dark");
      footerLogo.classList.add("vseth-logo-dark");
      if (selectItems) selectItems.classList.add("vseth-text-dark");
    } else {
      footerDiv.classList.remove("vseth-footer-dark");
      footerLogo.classList.remove("vseth-logo-dark");
      if (selectItems) selectItems.classList.remove("vseth-text-dark");
    }
  }, [colorScheme]);

Alexander Schoch's avatar
Alexander Schoch committed
  const { data } = useConfig(
    "https://static.vseth.ethz.ch/assets/vseth-0522-thealt/config.json"
  );

  const customDemoNav = [
Alexander Schoch's avatar
Alexander Schoch committed
    { title: t("bashGuide"), href: "/bash" },
    { title: t("installGuide"), href: "/install" },
    {
      title: t("courses"),
      href: "https://gitlab.ethz.ch/thealternative/courses",
    },
  ];
Alexander Schoch's avatar
Alexander Schoch committed

  const customNav = [
    {
      title: (
        <>
          <MediaQuery smallerThan="md" styles={{ display: "none" }}>
            <Menu shadow="md" width={200}>
              <Menu.Target>
                <Group>
                  <span style={{ color: "#f28a20" }}>{t("guides")}</span>
                  <Icon icon={ICONS.DOWN} color="#f28a20" />
                </Group>
              </Menu.Target>

              <Menu.Dropdown>
                <Menu.Item>
                  <Link style={{ textDecoration: "none" }} href="/bash">
                    {t("bashGuide")}
                  </Link>
                </Menu.Item>
                <Menu.Item>
                  <Link style={{ textDecoration: "none" }} href="/install">
                    {t("installGuide")}
                  </Link>
                </Menu.Item>
              </Menu.Dropdown>
            </Menu>
          </MediaQuery>
          <MediaQuery largerThan="md" styles={{ display: "none" }}>
            <span style={{ color: "white" }}>
              <Link style={{ textDecoration: "none" }} href="/bash">
                {t("bashGuide")}
              </Link>
              &nbsp;&nbsp;
              <Link style={{ textDecoration: "none" }} href="/install">
                {t("installGuide")}
              </Link>
            </span>
          </MediaQuery>
        </>
      ),
      href: "",
    },
    {
      title: (
        <a
          style={{ textDecoration: "none" }}
          target="_blank"
          href="https://gitlab.ethz.ch/thealternative/courses"
        >
          {t("courses")}
        </a>
      ),
      href: "",
    },
  ];

Alexander Schoch's avatar
Alexander Schoch committed
  return (
    <React.StrictMode>
Alexander Schoch's avatar
Alexander Schoch committed
      <ColorSchemeProvider
        colorScheme={colorScheme}
        toggleColorScheme={toggleColorScheme}
      >
        <VSETHThemeProvider theme={theme}>
          <Box
            sx={(theme) => ({
              main: {
                backgroundColor:
                  theme.colorScheme === "dark" ? theme.colors.dark[8] : "white",
              },
            })}
          >
            <VSETHExternalApp
              selectedLanguage={selectedLanguage}
              onLanguageSelect={(lang) => {
                setSelectedLanguage(lang);
                router.push({ pathname, query }, asPath, { locale: lang });
              }}
              languages={data?.languages}
              title={
                <>
                  <MediaQuery largerThan="md" styles={{ display: "none" }}>
                    <Link href="/">
                      <img
                        style={{ maxWidth: "250px" }}
                        src={
                          "https://static.vseth.ethz.ch/assets/vseth-0522-thealt/logo-inv.svg"
                        }
                      />
                    </Link>
                  </MediaQuery>
                  <MediaQuery smallerThan="md" styles={{ display: "none" }}>
                    <Link href="/">
                      <img
                        style={{ maxWidth: "250px" }}
                        src={
                          theme.colorScheme === "dark"
                            ? "https://static.vseth.ethz.ch/assets/vseth-0522-thealt/logo-inv.svg"
                            : "/images/logo.svg"
                        }
                      />
                    </Link>
                  </MediaQuery>
                </>
              }
              appNav={customNav}
              organizationNav={data.externalNav}
              makeWrapper={(url, child) => <span>{child}</span>}
              privacyPolicy={data?.privacy}
              disclaimer={data?.copyright}
              //activeHref is the current active url path. Required to style the active page in the Nav
              activeHref={"/"}
              socialMedia={data?.socialMedia}
              logo={"/images/vseth_inv_nobyline.svg"}
              loginButton={
                <Group>
                  <ThemeSwitcher />
                  <LoginButton />
                </Group>
              }
              signet={"/images/empty.svg"}
              size="xl"
            >
              <ApolloProvider client={apolloClient}>
                <NotificationsProvider>{props.children}</NotificationsProvider>
              </ApolloProvider>
            </VSETHExternalApp>
          </Box>
          <Affix position={{ bottom: 20, right: 20 }}>
            <Transition transition="slide-up" mounted={scroll.y > 0}>
              {(transitionStyles) => (
                <Button
                  leftIcon={<Icon icon={ICONS.UP} size={20} color="#f28a20" />}
                  style={{ ...transitionStyles, color: "#f28a20" }}
                  onClick={() => scrollTo({ y: 0 })}
                >
                  {t("scrollToTop")}
                </Button>
              )}
            </Transition>
          </Affix>
Alexander Schoch's avatar
Alexander Schoch committed
        </VSETHThemeProvider>
      </ColorSchemeProvider>
Alexander Schoch's avatar
Alexander Schoch committed
    </React.StrictMode>
  );
}