Fix navbar highlight for Organized Content sections (#182)
continuous-integration/drone/push Build is failing Details

Also fixes the navbar highlight for the different Advice sections.

Closes #181

Co-authored-by: Amy <a258wang@uwaterloo.ca>
Reviewed-on: #182
Reviewed-by: Aditya Thakral <a3thakra@csclub.uwaterloo.ca>
Co-authored-by: Amy <a258wang@csclub.uwaterloo.ca>
Co-committed-by: Amy <a258wang@csclub.uwaterloo.ca>
This commit is contained in:
Amy Wang 2021-08-31 23:07:19 -04:00
parent 485230c95a
commit 0bb8049db3
9 changed files with 96 additions and 19 deletions

View File

@ -9,16 +9,15 @@ import styles from "./Navbar.module.css";
type Menu = {
name: string;
route: string;
submenu?: {
name: string;
route: string;
}[];
exact?: boolean;
submenu?: Menu;
}[];
const menu: Menu = [
{
name: "Home",
route: "/",
exact: true,
},
{
name: "About",
@ -27,6 +26,7 @@ const menu: Menu = [
{
name: "About Us",
route: "/about",
exact: true,
},
{
name: "Meet the Team",
@ -76,7 +76,21 @@ const menu: Menu = [
},
{
name: "Advice",
route: "/resources/advice/coop",
route: "/resources/advice/co-op",
submenu: [
{
name: "Co-op Advice",
route: "/resources/advice/co-op",
},
{
name: "Academic Advice",
route: "/resources/advice/academic",
},
{
name: "Additional Resources",
route: "/resources/advice/misc",
},
],
},
{
name: "Internships",
@ -198,10 +212,11 @@ interface NavItemProps {
function NavItem(props: NavItemProps) {
const router = useRouter();
const isCurrentPage =
router.pathname === props.route ||
(props.submenu != null &&
router.pathname.startsWith(getMainRoute(props.route)));
const isCurrentPage = shouldHighlight(
router.pathname,
props.name,
props.route
);
const isExternalLink =
props.route.includes("http://") || props.route.includes("https://");
@ -273,6 +288,54 @@ function NavItem(props: NavItemProps) {
);
}
interface Leaf {
name: string;
route: string;
exact?: boolean;
ancestors: { name: string; route: string }[];
}
function collectLeaves(
accumulator: Leaf[],
entry: {
name: string;
route: string;
exact?: boolean;
submenu?: Menu;
}
): Leaf[] {
if (entry.submenu == null) {
return [...accumulator, { ...entry, ancestors: [] }];
}
const subleaves = entry.submenu.reduce(collectLeaves, [] as Leaf[]);
return [
...accumulator,
...subleaves.map((leaf) => ({
...leaf,
ancestors: [...leaf.ancestors, { name: entry.name, route: entry.route }],
})),
];
}
const leaves: Leaf[] = menu.reduce(collectLeaves, [] as Leaf[]);
function shouldHighlight(
pathname: string,
name: string,
route: string
): boolean {
const match = leaves.find((leaf) =>
leaf.exact ? leaf.route === pathname : pathname.startsWith(leaf.route)
);
return match
? (match.name === name && match.route === route) ||
match.ancestors.find(
(ancestor) => ancestor.name === name && ancestor.route === route
) != null
: false;
}
function getMainRoute(route: string) {
if (route === "/") {
return "/";

View File

@ -45,7 +45,11 @@ export function ShapesBackground({ getConfig }: Props) {
}, [getConfig, width, height, prevWidth, prevRoute, router.asPath]);
return (
<div className={styles.shapesContainer} ref={shapesContainerRef}>
<div
className={styles.shapesContainer}
ref={shapesContainerRef}
aria-hidden
>
{Object.entries(config).map(([type, instances]) =>
instances.map((attributes, idx) => (
<Shape

View File

@ -1,4 +1,4 @@
## Coop Advice
## Co-op Advice
Although WaterlooWorks is quite reliable, there are many more opportunities outside of the job board.
Being able to apply for jobs externally not only prepares you to look for jobs full time but it also

View File

@ -4,7 +4,7 @@ import { Title } from "@/components/Title";
import Content from "../../../content/advice/academic-advice.mdx";
import { Advice } from "./coop";
import { Advice } from "./co-op";
export default function AcademicAdvice() {
return (

View File

@ -5,9 +5,9 @@ import React, { ReactNode } from "react";
import { Image } from "@/components/Image";
import { Title } from "@/components/Title";
import Content from "../../../content/advice/coop-advice.mdx";
import Content from "../../../content/advice/co-op-advice.mdx";
import styles from "./coop.module.css";
import styles from "./co-op.module.css";
export default function CoopAdvice() {
return (
@ -30,13 +30,13 @@ export function Advice(props: { children: ReactNode }) {
<Image src="/images/advice.svg" className={styles.codey} />
</div>
<div className={styles.adviceBarContainer}>
<Link href="/resources/advice/coop">
<Link href="/resources/advice/co-op">
<a
className={
path == "/resources/advice/coop" ? styles.currentAdvice : ""
path == "/resources/advice/co-op" ? styles.currentAdvice : ""
}
>
Coop Advice
Co-op Advice
</a>
</Link>
<Link href="/resources/advice/academic">

View File

@ -0,0 +1,10 @@
import Head from "next/head";
import React from "react";
export default function AdviceRedirect() {
return (
<Head>
<meta httpEquiv="refresh" content="0;url=/resources/advice/co-op" />
</Head>
);
}

View File

@ -4,7 +4,7 @@ import { Title } from "@/components/Title";
import Content from "../../../content/advice/misc-advice.mdx";
import { Advice } from "./coop";
import { Advice } from "./co-op";
export default function MiscAdvice() {
return (

View File

@ -1,7 +1,7 @@
import Head from "next/head";
import React from "react";
export default function Resources() {
export default function ResourcesRedirect() {
return (
<Head>
<meta httpEquiv="refresh" content="0;url=/resources/services" />