156 lines
3.4 KiB
TypeScript
156 lines
3.4 KiB
TypeScript
import React from "react";
|
|
import Link from "next/link";
|
|
import { useRouter } from "next/router";
|
|
import { Image } from "./Image";
|
|
import styles from "./Navbar.module.css";
|
|
|
|
interface NavLink {
|
|
name: string;
|
|
route: string;
|
|
submenu?: {
|
|
name: string;
|
|
route: string;
|
|
}[];
|
|
}
|
|
|
|
const menu: NavLink[] = [
|
|
{
|
|
name: "Home",
|
|
route: "/",
|
|
},
|
|
{
|
|
name: "About",
|
|
route: "/about",
|
|
submenu: [
|
|
{
|
|
name: "About Us",
|
|
route: "/about",
|
|
},
|
|
{
|
|
name: "Meet the Team",
|
|
route: "/about/team",
|
|
},
|
|
{
|
|
name: "Constitution",
|
|
route: "/about/constitution",
|
|
},
|
|
{
|
|
name: "Code of Conduct",
|
|
route: "/about/code-of-conduct",
|
|
},
|
|
{
|
|
name: "Our Supporters",
|
|
route: "/about/our-supporters",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "Get Involved",
|
|
route: "/get-involved",
|
|
},
|
|
{
|
|
name: "Events",
|
|
route: "/events",
|
|
},
|
|
{
|
|
name: "Resources",
|
|
route: "/resources/services",
|
|
submenu: [
|
|
{
|
|
name: "Services",
|
|
route: "/resources/services",
|
|
},
|
|
{
|
|
name: "Tech Talks",
|
|
route: "/resources/tech-talks",
|
|
},
|
|
{
|
|
name: "CS Club Wiki",
|
|
route: "https://wiki.csclub.uwaterloo.ca/",
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
function NavItem(props: NavLink) {
|
|
const router = useRouter();
|
|
const externalLink =
|
|
props.route.includes("http://") || props.route.includes("https://");
|
|
return (
|
|
<>
|
|
{externalLink ? (
|
|
<a
|
|
href={props.route}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
onClick={() => {
|
|
if (document.activeElement instanceof HTMLElement) {
|
|
document.activeElement.blur();
|
|
}
|
|
}}
|
|
>
|
|
{props.name}
|
|
</a>
|
|
) : (
|
|
<Link href={props.route}>
|
|
<a
|
|
title={props.name}
|
|
className={
|
|
router.pathname === props.route ||
|
|
((props.submenu?.length ?? 0) > 0 &&
|
|
router.pathname.startsWith(props.route))
|
|
? styles.currentPage
|
|
: ""
|
|
}
|
|
onClick={() => {
|
|
if (document.activeElement instanceof HTMLElement) {
|
|
document.activeElement.blur();
|
|
}
|
|
}}
|
|
>
|
|
{props.name}
|
|
</a>
|
|
</Link>
|
|
)}
|
|
{(props.submenu?.length ?? 0) > 0 ? (
|
|
<ul className={styles.dropdown}>
|
|
{props.submenu?.map((item) => {
|
|
return (
|
|
<li className={styles.dropdownWrapper} key={item.name}>
|
|
<NavItem name={item.name} route={item.route} />
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
) : null}
|
|
</>
|
|
);
|
|
}
|
|
|
|
export function Navbar() {
|
|
return (
|
|
<nav className={styles.navbar}>
|
|
<div className={styles.navContent}>
|
|
<Link href="/">
|
|
<a className={styles.logo}>
|
|
<Image src="/images/logo-icon.png" alt="CSC Logo" />
|
|
</a>
|
|
</Link>
|
|
<ul className={styles.navMenu}>
|
|
{menu.map((item) => {
|
|
return (
|
|
<li className={styles.dropdownWrapper} key={item.name}>
|
|
<NavItem
|
|
name={item.name}
|
|
route={item.route}
|
|
submenu={item.submenu}
|
|
/>
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
);
|
|
}
|