From 994517e959d6851fda196fcbfce00412e4cfdb7a Mon Sep 17 00:00:00 2001 From: Jared He <66887902+jaredjhe@users.noreply.github.com> Date: Thu, 26 Aug 2021 18:49:36 -0500 Subject: [PATCH 1/6] Add header functionality --- lib/events.ts | 150 +++++++++++++++++++++++- pages/events/[year]/[term]/index.tsx | 164 ++++++++------------------- tsconfig.json | 3 +- 3 files changed, 199 insertions(+), 118 deletions(-) diff --git a/lib/events.ts b/lib/events.ts index 86de2e63..5246f02f 100644 --- a/lib/events.ts +++ b/lib/events.ts @@ -5,6 +5,8 @@ import matter from "gray-matter"; import { MDXRemoteSerializeResult } from "next-mdx-remote"; import { serialize } from "next-mdx-remote/serialize"; +import type { Props } from "@/pages/events/[year]/[term]/index"; + const EVENTS_PATH = path.join("content", "events"); export const TERMS = ["winter", "spring", "fall"]; @@ -58,9 +60,15 @@ export async function getEventsByTerm( year: string, term: string ): Promise { - return (await fs.readdir(path.join(EVENTS_PATH, year, term))) - .filter((name) => name.endsWith(".md")) - .map((name) => name.slice(0, -".md".length)); + let retval: string[] = []; + try { + retval = (await fs.readdir(path.join(EVENTS_PATH, year, term))) + .filter((name) => name.endsWith(".md")) + .map((name) => name.slice(0, -".md".length)); + } catch { + return []; + } + return retval; } export async function getUpcomingEvents(): Promise { @@ -97,3 +105,139 @@ export async function getUpcomingEvents(): Promise { ); }); } + +export async function getProps( + year: string, + term: string +): Promise<{ props: Props }> { + const eventNames = await getEventsByTerm(year, term); + + const events: Event[] = ( + await Promise.all( + eventNames.map((file: string) => getEventBySlug(year, term, file)) + ) + ).sort( + (a, b) => + new Date(a.metadata.date).getTime() - new Date(b.metadata.date).getTime() + ); + + const pastEvents = events + .filter((event) => new Date(event.metadata.date).getTime() < Date.now()) + .reverse(); + + const futureEvents = events.filter( + (event) => new Date(event.metadata.date).getTime() >= Date.now() + ); + + const current = getCurrentTerm(); + + const eventYears = await getEventYears(); + + const minYear = eventYears[0]; + const pastTerms: { year: string; term: string }[] = []; + let curPastYear = year; + let curPastTerm = term; + while (parseInt(curPastYear) >= parseInt(minYear) && pastTerms.length < 2) { + const pastTerm = getPastTerm(curPastYear, curPastTerm); + curPastYear = pastTerm.year; + curPastTerm = pastTerm.term; + if ((await getEventsByTerm(curPastYear, curPastTerm)).length !== 0) { + pastTerms.push(pastTerm); + } + } + + const maxYear = eventYears[eventYears.length - 1]; + const futureTerms: { year: string; term: string }[] = []; + let curFutureYear = year; + let curFutureTerm = term; + while ( + parseInt(curFutureYear) <= parseInt(maxYear) && + futureTerms.length < 2 + ) { + const futureTerm = getFutureTerm(curFutureYear, curFutureTerm); + curFutureYear = futureTerm.year; + curFutureTerm = futureTerm.term; + if ((await getEventsByTerm(curFutureYear, curFutureTerm)).length !== 0) { + futureTerms.push(futureTerm); + } + } + + return { + props: { + year: year, + term: term, + pastEvents: pastEvents, + futureEvents: futureEvents, + isCurrentTerm: term === current.term && year === current.year, + pastTerms: pastTerms, + futureTerms: futureTerms, + }, + }; +} + +export function getCurrentTerm(): { year: string; term: string } { + const date = new Date(); + let term = ""; + const year = date.getUTCFullYear().toString(); + + if ( + new Date(`${year}-01-01`).getTime() <= date.getTime() && + date.getTime() <= new Date(`${year}-04-30`).getTime() + ) { + term = "winter"; + } else if ( + new Date(`${year}-05-01`).getTime() <= date.getTime() && + date.getTime() <= new Date(`${year}-08-31`).getTime() + ) { + term = "spring"; + } else if ( + new Date(`${year}-09-01`).getTime() <= date.getTime() && + date.getTime() <= new Date(`${year}-12-31`).getTime() + ) { + term = "fall"; + } + + return { year, term }; +} + +function getPastTerm( + year: string, + term: string +): { year: string; term: string } { + const index = TERMS.indexOf(term); + if (index === -1) { + console.error("Not a valid term"); + return { year: "", term: "" }; + } else if (index === 0) { + return { + year: (parseInt(year) - 1).toString(), + term: TERMS[TERMS.length - 1], + }; + } else { + return { + year: year, + term: TERMS[index - 1], + }; + } +} + +function getFutureTerm( + year: string, + term: string +): { year: string; term: string } { + const index = TERMS.indexOf(term); + if (index === -1) { + console.error("Not a valid term"); + return { year: "", term: "" }; + } else if (index === TERMS.length - 1) { + return { + year: (parseInt(year) + 1).toString(), + term: TERMS[0], + }; + } else { + return { + year: year, + term: TERMS[index + 1], + }; + } +} diff --git a/pages/events/[year]/[term]/index.tsx b/pages/events/[year]/[term]/index.tsx index 8a97026b..54a28bc7 100644 --- a/pages/events/[year]/[term]/index.tsx +++ b/pages/events/[year]/[term]/index.tsx @@ -7,30 +7,70 @@ import React from "react"; import { EventCard } from "@/components/EventCard"; import { MiniEventCard } from "@/components/MiniEventCard"; import { + Event, + getProps, getEventYears, getEventTermsByYear, - getEventsByTerm, - getEventBySlug, - Event, - TERMS, } from "@/lib/events"; import styles from "./index.module.css"; -interface Props { - term: string; +export interface Props { year: string; + term: string; pastEvents: Event[]; futureEvents: Event[]; isCurrentTerm: boolean; + pastTerms: { year: string; term: string }[]; + futureTerms: { year: string; term: string }[]; } export default function Term(props: Props) { + const hasPastTerms = props.pastTerms.length !== 0; + const hasFutureTerms = props.futureTerms.length !== 0; const hasPastEvents = props.pastEvents.length !== 0; const hasFutureEvents = props.futureEvents.length !== 0; - return (
+ {!hasPastTerms && hasFutureTerms && ( +
+

{`${capitalize(props.term)} ${ + props.year + }`}

+

{`${capitalize(props.futureTerms[0].term)} ${ + props.futureTerms[0].year + }`}

+

{`${capitalize(props.futureTerms[1].term)} ${ + props.futureTerms[1].year + }`}

+
+ )} + {hasPastTerms && hasFutureTerms && ( +
+

{`${capitalize(props.pastTerms[0].term)} ${ + props.pastTerms[0].year + }`}

+

{`${capitalize(props.term)} ${ + props.year + }`}

+

{`${capitalize(props.futureTerms[0].term)} ${ + props.futureTerms[0].year + }`}

+
+ )} + {hasPastTerms && !hasFutureTerms && ( +
+

{`${capitalize(props.pastTerms[1].term)} ${ + props.pastTerms[1].year + } `}

+

{`${capitalize(props.pastTerms[0].term)} ${ + props.pastTerms[0].year + }`}

+

{`${capitalize(props.term)} ${ + props.year + }`}

+
+ )} {hasFutureEvents && ( <>

Upcoming Events

@@ -52,9 +92,7 @@ export default function Term(props: Props) {

Events Archive: - {` ${props.term.charAt(0).toUpperCase()}${props.term.slice(1)} ${ - props.year - }`} + {` ${capitalize(props.term)} ${props.year}`}

)} @@ -105,108 +143,6 @@ export const getStaticPaths: GetStaticPaths = async () => { }; }; -export const getProps = async ( - year: string, - term: string -): Promise<{ props: Props }> => { - const eventNames = await getEventsByTerm(year, term); - - const events: Event[] = ( - await Promise.all( - eventNames.map((file: string) => getEventBySlug(year, term, file)) - ) - ).sort( - (a, b) => - new Date(a.metadata.date).getTime() - new Date(b.metadata.date).getTime() - ); - - const pastEvents = events - .filter((event) => new Date(event.metadata.date).getTime() < Date.now()) - .reverse(); - - const futureEvents = events.filter( - (event) => new Date(event.metadata.date).getTime() >= Date.now() - ); - - const current = getCurrentTerm(); - - // console.log(getPreviousTerm(term, year)); - // console.log(getNextTerm(term, year)); - - return { - props: { - term: term, - year: year, - pastEvents: pastEvents, - futureEvents: futureEvents, - isCurrentTerm: term === current.term && year === current.year, - }, - }; -}; - -const getPreviousTerm = ( - year: string, - term: string -): { year: string; term: string } => { - const index = TERMS.indexOf(term); - if (index === -1) { - console.error("Not a valid term"); - return { year: "", term: "" }; - } else if (index === 0) { - return { - year: (parseInt(year) - 1).toString(), - term: TERMS[TERMS.length - 1], - }; - } else { - return { - year: year, - term: TERMS[index - 1], - }; - } -}; - -const getNextTerm = ( - year: string, - term: string -): { year: string; term: string } => { - const index = TERMS.indexOf(term); - if (index === -1) { - console.error("Not a valid term"); - return { year: "", term: "" }; - } else if (index === TERMS.length - 1) { - return { - year: (parseInt(year) + 1).toString(), - term: TERMS[0], - }; - } else { - return { - year: year, - term: TERMS[index + 1], - }; - } -}; - -export function getCurrentTerm() { - const date = new Date(); - let term = ""; - const year = date.getUTCFullYear().toString(); - - if ( - new Date(`${year}-01-01`).getTime() <= date.getTime() && - date.getTime() <= new Date(`${year}-04-30`).getTime() - ) { - term = "winter"; - } else if ( - new Date(`${year}-05-01`).getTime() <= date.getTime() && - date.getTime() <= new Date(`${year}-08-31`).getTime() - ) { - term = "spring"; - } else if ( - new Date(`${year}-09-01`).getTime() <= date.getTime() && - date.getTime() <= new Date(`${year}-12-31`).getTime() - ) { - term = "fall"; - } - - return { term, year }; +function capitalize(str: string) { + return str.slice(0, 1).toUpperCase() + str.slice(1); } diff --git a/tsconfig.json b/tsconfig.json index d886e684..5cdd8812 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,7 +23,8 @@ "paths": { "@/components/*": ["components/*"], "@/lib/*": ["lib/*"], - "@/hooks/*": ["hooks/*"] + "@/hooks/*": ["hooks/*"], + "@/pages/*": ["pages/*"] } }, "include": ["next-env.d.ts", "types.d.ts", "**/*.ts", "**/*.tsx"], -- 2.39.2 From 85e24e04f06a9000d7cfaae836dc1d6e9ad71c78 Mon Sep 17 00:00:00 2001 From: Jared He <66887902+jaredjhe@users.noreply.github.com> Date: Thu, 26 Aug 2021 19:07:12 -0500 Subject: [PATCH 2/6] Styling and changing --- pages/events/[year]/[term]/index.module.css | 9 +++ pages/events/[year]/[term]/index.tsx | 64 ++++++++++++++------- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/pages/events/[year]/[term]/index.module.css b/pages/events/[year]/[term]/index.module.css index f47389fc..f7873912 100644 --- a/pages/events/[year]/[term]/index.module.css +++ b/pages/events/[year]/[term]/index.module.css @@ -14,6 +14,15 @@ } } +.header a { + color: var(--text); + margin-left: calc(30rem / 16); +} + +.header a .curTerm { + color: var(--primary-accent); +} + .blue { color: var(--primary-accent); } diff --git a/pages/events/[year]/[term]/index.tsx b/pages/events/[year]/[term]/index.tsx index 54a28bc7..065cff4a 100644 --- a/pages/events/[year]/[term]/index.tsx +++ b/pages/events/[year]/[term]/index.tsx @@ -5,6 +5,7 @@ import { MDXRemote } from "next-mdx-remote"; import React from "react"; import { EventCard } from "@/components/EventCard"; +import { Link } from "@/components/Link"; import { MiniEventCard } from "@/components/MiniEventCard"; import { Event, @@ -34,41 +35,62 @@ export default function Term(props: Props) {
{!hasPastTerms && hasFutureTerms && (
-

{`${capitalize(props.term)} ${ - props.year - }`}

-

{`${capitalize(props.futureTerms[0].term)} ${ + + + {`${capitalize(props.term)} ${props.year}`} + + + {`${capitalize(props.futureTerms[0].term)} ${ props.futureTerms[0].year - }`}

-

{`${capitalize(props.futureTerms[1].term)} ${ + }`} + {`${capitalize(props.futureTerms[1].term)} ${ props.futureTerms[1].year - }`}

+ }`} + Archives
)} {hasPastTerms && hasFutureTerms && (
-

{`${capitalize(props.pastTerms[0].term)} ${ + {`${capitalize(props.pastTerms[0].term)} ${ props.pastTerms[0].year - }`}

-

{`${capitalize(props.term)} ${ - props.year - }`}

-

{`${capitalize(props.futureTerms[0].term)} ${ + }`} + + + {`${capitalize(props.term)} ${props.year}`} + + + {`${capitalize(props.futureTerms[0].term)} ${ props.futureTerms[0].year - }`}

+ }`} + Archives
)} {hasPastTerms && !hasFutureTerms && (
-

{`${capitalize(props.pastTerms[1].term)} ${ + {`${capitalize(props.pastTerms[1].term)} ${ props.pastTerms[1].year - } `}

-

{`${capitalize(props.pastTerms[0].term)} ${ + } `} + {`${capitalize(props.pastTerms[0].term)} ${ props.pastTerms[0].year - }`}

-

{`${capitalize(props.term)} ${ - props.year - }`}

+ }`} + + + {`${capitalize(props.term)} ${props.year}`} + + + Archives
)} {hasFutureEvents && ( -- 2.39.2 From 6649ef8f03b1c98ba9342abdf54627d534f932e5 Mon Sep 17 00:00:00 2001 From: Jared He <66887902+jaredjhe@users.noreply.github.com> Date: Thu, 26 Aug 2021 19:08:10 -0500 Subject: [PATCH 3/6] Change margin direction --- pages/events/[year]/[term]/index.module.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/events/[year]/[term]/index.module.css b/pages/events/[year]/[term]/index.module.css index f7873912..85eaf5a4 100644 --- a/pages/events/[year]/[term]/index.module.css +++ b/pages/events/[year]/[term]/index.module.css @@ -16,7 +16,7 @@ .header a { color: var(--text); - margin-left: calc(30rem / 16); + margin-right: calc(30rem / 16); } .header a .curTerm { -- 2.39.2 From 97e434e536459a601cc10261a2bf5046134e0f69 Mon Sep 17 00:00:00 2001 From: Jared He <66887902+jaredjhe@users.noreply.github.com> Date: Thu, 26 Aug 2021 19:09:04 -0500 Subject: [PATCH 4/6] Font size fix --- pages/events/[year]/[term]/index.module.css | 1 + 1 file changed, 1 insertion(+) diff --git a/pages/events/[year]/[term]/index.module.css b/pages/events/[year]/[term]/index.module.css index 85eaf5a4..ab651690 100644 --- a/pages/events/[year]/[term]/index.module.css +++ b/pages/events/[year]/[term]/index.module.css @@ -16,6 +16,7 @@ .header a { color: var(--text); + font-size: calc(18rem / 16); margin-right: calc(30rem / 16); } -- 2.39.2 From 95d3328cda9cdd36b43839f2a31c22d2ae973856 Mon Sep 17 00:00:00 2001 From: Jared He <66887902+jaredjhe@users.noreply.github.com> Date: Thu, 26 Aug 2021 19:15:02 -0500 Subject: [PATCH 5/6] Use relative link --- lib/events.ts | 2 +- tsconfig.json | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/events.ts b/lib/events.ts index 5246f02f..ac89237b 100644 --- a/lib/events.ts +++ b/lib/events.ts @@ -5,7 +5,7 @@ import matter from "gray-matter"; import { MDXRemoteSerializeResult } from "next-mdx-remote"; import { serialize } from "next-mdx-remote/serialize"; -import type { Props } from "@/pages/events/[year]/[term]/index"; +import type { Props } from "../pages/events/[year]/[term]/index"; const EVENTS_PATH = path.join("content", "events"); export const TERMS = ["winter", "spring", "fall"]; diff --git a/tsconfig.json b/tsconfig.json index 5cdd8812..d886e684 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,8 +23,7 @@ "paths": { "@/components/*": ["components/*"], "@/lib/*": ["lib/*"], - "@/hooks/*": ["hooks/*"], - "@/pages/*": ["pages/*"] + "@/hooks/*": ["hooks/*"] } }, "include": ["next-env.d.ts", "types.d.ts", "**/*.ts", "**/*.tsx"], -- 2.39.2 From e1b41e2a37f0f69a8d3f17313b5015ada2988f28 Mon Sep 17 00:00:00 2001 From: Aditya Thakral Date: Fri, 27 Aug 2021 16:04:03 -0400 Subject: [PATCH 6/6] PR feedback --- lib/events.ts | 86 ++++++++++----------- pages/events/[year]/[term]/index.tsx | 110 ++++++++++++--------------- 2 files changed, 87 insertions(+), 109 deletions(-) diff --git a/lib/events.ts b/lib/events.ts index ac89237b..a909434d 100644 --- a/lib/events.ts +++ b/lib/events.ts @@ -60,15 +60,13 @@ export async function getEventsByTerm( year: string, term: string ): Promise { - let retval: string[] = []; try { - retval = (await fs.readdir(path.join(EVENTS_PATH, year, term))) + return (await fs.readdir(path.join(EVENTS_PATH, year, term))) .filter((name) => name.endsWith(".md")) .map((name) => name.slice(0, -".md".length)); } catch { return []; } - return retval; } export async function getUpcomingEvents(): Promise { @@ -106,10 +104,7 @@ export async function getUpcomingEvents(): Promise { }); } -export async function getProps( - year: string, - term: string -): Promise<{ props: Props }> { +export async function getProps(year: string, term: string): Promise { const eventNames = await getEventsByTerm(year, term); const events: Event[] = ( @@ -145,6 +140,7 @@ export async function getProps( pastTerms.push(pastTerm); } } + pastTerms.reverse(); const maxYear = eventYears[eventYears.length - 1]; const futureTerms: { year: string; term: string }[] = []; @@ -163,15 +159,13 @@ export async function getProps( } return { - props: { - year: year, - term: term, - pastEvents: pastEvents, - futureEvents: futureEvents, - isCurrentTerm: term === current.term && year === current.year, - pastTerms: pastTerms, - futureTerms: futureTerms, - }, + year: year, + term: term, + pastEvents: pastEvents, + futureEvents: futureEvents, + isCurrentTerm: term === current.term && year === current.year, + pastTerms: pastTerms, + futureTerms: futureTerms, }; } @@ -181,18 +175,18 @@ export function getCurrentTerm(): { year: string; term: string } { const year = date.getUTCFullYear().toString(); if ( - new Date(`${year}-01-01`).getTime() <= date.getTime() && - date.getTime() <= new Date(`${year}-04-30`).getTime() + new Date(`${year}-01-01 EST`).getTime() <= date.getTime() && + date.getTime() <= new Date(`${year}-04-30 EST`).getTime() ) { term = "winter"; } else if ( - new Date(`${year}-05-01`).getTime() <= date.getTime() && - date.getTime() <= new Date(`${year}-08-31`).getTime() + new Date(`${year}-05-01 EST`).getTime() <= date.getTime() && + date.getTime() <= new Date(`${year}-08-31 EST`).getTime() ) { term = "spring"; } else if ( - new Date(`${year}-09-01`).getTime() <= date.getTime() && - date.getTime() <= new Date(`${year}-12-31`).getTime() + new Date(`${year}-09-01 EST`).getTime() <= date.getTime() && + date.getTime() <= new Date(`${year}-12-31 EST`).getTime() ) { term = "fall"; } @@ -205,20 +199,20 @@ function getPastTerm( term: string ): { year: string; term: string } { const index = TERMS.indexOf(term); + if (index === -1) { - console.error("Not a valid term"); - return { year: "", term: "" }; - } else if (index === 0) { - return { - year: (parseInt(year) - 1).toString(), - term: TERMS[TERMS.length - 1], - }; - } else { - return { - year: year, - term: TERMS[index - 1], - }; + throw new Error("Not a valid term"); } + + return index === 0 + ? { + year: (parseInt(year) - 1).toString(), + term: TERMS[TERMS.length - 1], + } + : { + year: year, + term: TERMS[index - 1], + }; } function getFutureTerm( @@ -226,18 +220,18 @@ function getFutureTerm( term: string ): { year: string; term: string } { const index = TERMS.indexOf(term); + if (index === -1) { - console.error("Not a valid term"); - return { year: "", term: "" }; - } else if (index === TERMS.length - 1) { - return { - year: (parseInt(year) + 1).toString(), - term: TERMS[0], - }; - } else { - return { - year: year, - term: TERMS[index + 1], - }; + throw new Error("Not a valid term"); } + + return index === TERMS.length - 1 + ? { + year: (parseInt(year) + 1).toString(), + term: TERMS[0], + } + : { + year: year, + term: TERMS[index + 1], + }; } diff --git a/pages/events/[year]/[term]/index.tsx b/pages/events/[year]/[term]/index.tsx index 065cff4a..34a8c8e4 100644 --- a/pages/events/[year]/[term]/index.tsx +++ b/pages/events/[year]/[term]/index.tsx @@ -27,72 +27,42 @@ export interface Props { } export default function Term(props: Props) { - const hasPastTerms = props.pastTerms.length !== 0; - const hasFutureTerms = props.futureTerms.length !== 0; + let headerTerms = [{ year: props.year, term: props.term }]; + + // p, Current, f + if (props.pastTerms.length > 0 && props.futureTerms.length > 0) { + headerTerms = [ + ...props.pastTerms.slice(-1), + ...headerTerms, + ...props.futureTerms.slice(0, 1), + ]; + } + // p, p, Current + else if (props.pastTerms.length > 0) { + headerTerms = [...props.pastTerms.slice(-2), ...headerTerms]; + } + // Current, f, f + else { + headerTerms = [...headerTerms, ...props.futureTerms.slice(0, 2)]; + } + + headerTerms.reverse(); + const hasPastEvents = props.pastEvents.length !== 0; const hasFutureEvents = props.futureEvents.length !== 0; + return (
- {!hasPastTerms && hasFutureTerms && ( -
- - - {`${capitalize(props.term)} ${props.year}`} - - - {`${capitalize(props.futureTerms[0].term)} ${ - props.futureTerms[0].year - }`} - {`${capitalize(props.futureTerms[1].term)} ${ - props.futureTerms[1].year - }`} - Archives -
- )} - {hasPastTerms && hasFutureTerms && ( -
- {`${capitalize(props.pastTerms[0].term)} ${ - props.pastTerms[0].year - }`} - - - {`${capitalize(props.term)} ${props.year}`} - - - {`${capitalize(props.futureTerms[0].term)} ${ - props.futureTerms[0].year - }`} - Archives -
- )} - {hasPastTerms && !hasFutureTerms && ( -
- {`${capitalize(props.pastTerms[1].term)} ${ - props.pastTerms[1].year - } `} - {`${capitalize(props.pastTerms[0].term)} ${ - props.pastTerms[0].year - }`} - - - {`${capitalize(props.term)} ${props.year}`} - - - Archives -
- )} +
+ {headerTerms.map((link) => ( + + ))} + Archives +
{hasFutureEvents && ( <>

Upcoming Events

@@ -132,6 +102,20 @@ export default function Term(props: Props) { ); } +function HeaderLink(props: { + year: string; + term: string; + isCurrentTerm?: boolean; +}) { + return ( + + + {`${capitalize(props.term)} ${props.year}`} + + + ); +} + interface Params extends ParsedUrlQuery { year: string; term: string; @@ -143,7 +127,7 @@ export const getStaticProps: GetStaticProps = async ( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const { year, term } = context.params!; - return await getProps(year, term); + return { props: await getProps(year, term) }; }; export const getStaticPaths: GetStaticPaths = async () => { -- 2.39.2