Compare commits
5 Commits
177744db9c
...
017812443b
Author | SHA1 | Date |
---|---|---|
b38peng | 017812443b | |
Amy Wang | 8bb5f160f0 | |
Jared He | 966129adf8 | |
Aditya Thakral | a0d0b8e843 | |
Amy Wang | 0bb8049db3 |
|
@ -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 "/";
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -3,4 +3,4 @@ title: License Information and Attribution
|
||||||
index: 11
|
index: 11
|
||||||
---
|
---
|
||||||
|
|
||||||
- The Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike License](http://creativecommons.org/licenses/by-sa/3.0/) , derived from the [Women in Computer Science Code of Conduct](http://wics.uwaterloo.ca/code-of-conduct/) , the [UW Amateur Radio Club Code of Conduct](http://uwarc.uwaterloo.ca/policies-procedures/code-of-conduct/) , and the [FASS Code of Conduct (Article 2, Section 16)](http://fass.uwaterloo.ca/wp-content/uploads/2015/03/constitution.pdf) .
|
- The Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike License](http://creativecommons.org/licenses/by-sa/3.0/), derived from the [Women in Computer Science Code of Conduct](http://wics.uwaterloo.ca/deprecated/code-of-conduct/), the [UW Amateur Radio Club Code of Conduct](http://uwarc.uwaterloo.ca/policies-procedures/code-of-conduct/), and the [FASS Code of Conduct](http://fass.uwaterloo.ca/fassconstitution).
|
||||||
|
|
|
@ -4,5 +4,5 @@ index: 12
|
||||||
---
|
---
|
||||||
|
|
||||||
1. The Club has a [Code of Conduct](/about/code-of-conduct).
|
1. The Club has a [Code of Conduct](/about/code-of-conduct).
|
||||||
2. The [scope of the Code of Conduct](/about/code-of-conduct/scopes-and-spaces) is specified by the Code of Conduct.
|
2. The [scope of the Code of Conduct](/about/code-of-conduct/scope-and-spaces) is specified by the Code of Conduct.
|
||||||
3. Changes to the Code of Conduct are governed by the same rules as changes to the Constitution.
|
3. Changes to the Code of Conduct are governed by the same rules as changes to the Constitution.
|
||||||
|
|
|
@ -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
|
|
@ -80,6 +80,6 @@ Each term, the CSC holds elections to determine the executive council:
|
||||||
- Assistant Vice-President
|
- Assistant Vice-President
|
||||||
- Treasurer
|
- Treasurer
|
||||||
|
|
||||||
To find out when and where the next elections will be held, keep an eye on on the [News](/).
|
To find out when and where the next elections will be held, keep an eye on on the [News](/#news).
|
||||||
|
|
||||||
For details on the elections, see the [Constitution](/about/constitution).
|
For details on the elections, see the [Constitution](/about/constitution).
|
|
@ -3,7 +3,7 @@ title: CS Club Email
|
||||||
index: 2
|
index: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
Members also receive a **username@csclub.uwaterloo.ca** email address.
|
Members also receive a **[username@csclub.uwaterloo.ca](#)** email address.
|
||||||
|
|
||||||
- Mailboxes are considered as part of your disk quota, so your mailbox may grow up to the amount of disk quota you have.
|
- Mailboxes are considered as part of your disk quota, so your mailbox may grow up to the amount of disk quota you have.
|
||||||
- Attachments of any file size or type may be sent.
|
- Attachments of any file size or type may be sent.
|
||||||
|
|
|
@ -3,8 +3,8 @@ title: Mailing Lists
|
||||||
index: 10
|
index: 10
|
||||||
---
|
---
|
||||||
|
|
||||||
Our [csc-general mailing list](http://mailman.csclub.uwaterloo.ca/listinfo/csc-general) informs members about our current events.
|
Our [csc-general mailing list](https://mailman.csclub.uwaterloo.ca/postorius/lists/csc-general.csclub.uwaterloo.ca/) informs members about our current events.
|
||||||
|
|
||||||
Our [csc-industry mailing list](http://mailman.csclub.uwaterloo.ca/listinfo/csc-industry) allows students to opt-in to receiving emails from industry representatives.
|
Our [csc-industry mailing list](https://mailman.csclub.uwaterloo.ca/postorius/lists/csc-industry.csclub.uwaterloo.ca/) allows students to opt-in to receiving emails from industry representatives.
|
||||||
|
|
||||||
- Corporate events, job postings, info sessions, and related events may be posted here.
|
- Corporate events, job postings, info sessions, and related events may be posted here.
|
||||||
|
|
|
@ -179,28 +179,34 @@ export async function getEventsPageProps({
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentTerm(): { year: string; term: string } {
|
export function getCurrentTerm() {
|
||||||
const date = new Date();
|
const today = new Date().toLocaleDateString("en-CA", {
|
||||||
let term = "";
|
timeZone: "EST",
|
||||||
const year = date.getUTCFullYear().toString();
|
year: "numeric",
|
||||||
|
month: "numeric",
|
||||||
|
day: "numeric",
|
||||||
|
});
|
||||||
|
|
||||||
if (
|
const [year] = today.split("-");
|
||||||
new Date(`${year}-01-01 EST`).getTime() <= date.getTime() &&
|
|
||||||
date.getTime() <= new Date(`${year}-04-30 EST`).getTime()
|
let term = "";
|
||||||
) {
|
|
||||||
|
if (`${year}-01-01` <= today) {
|
||||||
term = "winter";
|
term = "winter";
|
||||||
} else if (
|
}
|
||||||
new Date(`${year}-05-01 EST`).getTime() <= date.getTime() &&
|
|
||||||
date.getTime() <= new Date(`${year}-08-31 EST`).getTime()
|
if (`${year}-05-01` <= today) {
|
||||||
) {
|
|
||||||
term = "spring";
|
term = "spring";
|
||||||
} else if (
|
}
|
||||||
new Date(`${year}-09-01 EST`).getTime() <= date.getTime() &&
|
|
||||||
date.getTime() <= new Date(`${year}-12-31 EST`).getTime()
|
if (`${year}-09-01` <= today) {
|
||||||
) {
|
|
||||||
term = "fall";
|
term = "fall";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (term === "") {
|
||||||
|
throw new Error("Error setting the current term");
|
||||||
|
}
|
||||||
|
|
||||||
return { year, term };
|
return { year, term };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +217,7 @@ function getPastTerm(
|
||||||
const index = TERMS.indexOf(term);
|
const index = TERMS.indexOf(term);
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
throw new Error("Not a valid term");
|
throw new Error(`[getPastTerm] Not a valid term: "${term}" "${year}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return index === 0
|
return index === 0
|
||||||
|
@ -232,7 +238,7 @@ function getFutureTerm(
|
||||||
const index = TERMS.indexOf(term);
|
const index = TERMS.indexOf(term);
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
throw new Error("Not a valid term");
|
throw new Error(`[getFutureTerm] Not a valid term: "${term}" "${year}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return index === TERMS.length - 1
|
return index === TERMS.length - 1
|
||||||
|
|
|
@ -83,9 +83,18 @@ export default function Term(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
{hasPastEvents && props.isCurrentTerm && (
|
{hasPastEvents && (
|
||||||
<section>
|
<section>
|
||||||
|
{props.isCurrentTerm ? (
|
||||||
<h1>Past Events</h1>
|
<h1>Past Events</h1>
|
||||||
|
) : (
|
||||||
|
<h1>
|
||||||
|
Events Archive:
|
||||||
|
<span className={styles.blue}>
|
||||||
|
{` ${capitalize(props.term)} ${props.year}`}
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
)}
|
||||||
<div className={styles.miniEventCards}>
|
<div className={styles.miniEventCards}>
|
||||||
{props.pastEvents.map(({ content, metadata }) => (
|
{props.pastEvents.map(({ content, metadata }) => (
|
||||||
<MiniEventCard
|
<MiniEventCard
|
||||||
|
@ -98,14 +107,6 @@ export default function Term(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
{hasPastEvents && !props.isCurrentTerm && (
|
|
||||||
<h1>
|
|
||||||
Events Archive:
|
|
||||||
<span className={styles.blue}>
|
|
||||||
{` ${capitalize(props.term)} ${props.year}`}
|
|
||||||
</span>
|
|
||||||
</h1>
|
|
||||||
)}
|
|
||||||
{!hasFutureEvents && !hasPastEvents && (
|
{!hasFutureEvents && !hasPastEvents && (
|
||||||
<>
|
<>
|
||||||
<h1>Events</h1>
|
<h1>Events</h1>
|
||||||
|
@ -114,16 +115,6 @@ export default function Term(props: Props) {
|
||||||
later!
|
later!
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<div className={styles.miniEventCards}>
|
|
||||||
{props.pastEvents.map(({ content, metadata }) => (
|
|
||||||
<MiniEventCard
|
|
||||||
{...metadata}
|
|
||||||
date={new Date(metadata.date)}
|
|
||||||
description={<MDXRemote {...content} />}
|
|
||||||
key={metadata.name + metadata.date.toString()}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -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">
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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 (
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
Loading…
Reference in New Issue