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 = { type Menu = {
name: string; name: string;
route: string; route: string;
submenu?: { exact?: boolean;
name: string; submenu?: Menu;
route: string;
}[];
}[]; }[];
const menu: Menu = [ const menu: Menu = [
{ {
name: "Home", name: "Home",
route: "/", route: "/",
exact: true,
}, },
{ {
name: "About", name: "About",
@ -27,6 +26,7 @@ const menu: Menu = [
{ {
name: "About Us", name: "About Us",
route: "/about", route: "/about",
exact: true,
}, },
{ {
name: "Meet the Team", name: "Meet the Team",
@ -76,7 +76,21 @@ const menu: Menu = [
}, },
{ {
name: "Advice", 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", name: "Internships",
@ -198,10 +212,11 @@ interface NavItemProps {
function NavItem(props: NavItemProps) { function NavItem(props: NavItemProps) {
const router = useRouter(); const router = useRouter();
const isCurrentPage = const isCurrentPage = shouldHighlight(
router.pathname === props.route || router.pathname,
(props.submenu != null && props.name,
router.pathname.startsWith(getMainRoute(props.route))); props.route
);
const isExternalLink = const isExternalLink =
props.route.includes("http://") || props.route.includes("https://"); 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) { function getMainRoute(route: string) {
if (route === "/") { if (route === "/") {
return "/"; return "/";

View File

@ -45,7 +45,11 @@ export function ShapesBackground({ getConfig }: Props) {
}, [getConfig, width, height, prevWidth, prevRoute, router.asPath]); }, [getConfig, width, height, prevWidth, prevRoute, router.asPath]);
return ( return (
<div className={styles.shapesContainer} ref={shapesContainerRef}> <div
className={styles.shapesContainer}
ref={shapesContainerRef}
aria-hidden
>
{Object.entries(config).map(([type, instances]) => {Object.entries(config).map(([type, instances]) =>
instances.map((attributes, idx) => ( instances.map((attributes, idx) => (
<Shape <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. 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 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 Content from "../../../content/advice/academic-advice.mdx";
import { Advice } from "./coop"; import { Advice } from "./co-op";
export default function AcademicAdvice() { export default function AcademicAdvice() {
return ( return (

View File

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

View File

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