diff --git a/lib/events.ts b/lib/events.ts index 86de2e63..a909434d 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,13 @@ 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)); + try { + return (await fs.readdir(path.join(EVENTS_PATH, year, term))) + .filter((name) => name.endsWith(".md")) + .map((name) => name.slice(0, -".md".length)); + } catch { + return []; + } } export async function getUpcomingEvents(): Promise { @@ -97,3 +103,135 @@ export async function getUpcomingEvents(): Promise { ); }); } + +export async function getProps(year: string, term: string): Promise { + 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); + } + } + pastTerms.reverse(); + + 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 { + 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 EST`).getTime() <= date.getTime() && + date.getTime() <= new Date(`${year}-04-30 EST`).getTime() + ) { + term = "winter"; + } else if ( + 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 EST`).getTime() <= date.getTime() && + date.getTime() <= new Date(`${year}-12-31 EST`).getTime() + ) { + term = "fall"; + } + + return { year, term }; +} + +function getPastTerm( + year: string, + term: string +): { year: string; term: string } { + const index = TERMS.indexOf(term); + + if (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( + year: string, + term: string +): { year: string; term: string } { + const index = TERMS.indexOf(term); + + if (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.module.css b/pages/events/[year]/[term]/index.module.css index f47389fc..ab651690 100644 --- a/pages/events/[year]/[term]/index.module.css +++ b/pages/events/[year]/[term]/index.module.css @@ -14,6 +14,16 @@ } } +.header a { + color: var(--text); + font-size: calc(18rem / 16); + margin-right: 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 8a97026b..34a8c8e4 100644 --- a/pages/events/[year]/[term]/index.tsx +++ b/pages/events/[year]/[term]/index.tsx @@ -5,32 +5,64 @@ 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, + 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) { + 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 (
+
+ {headerTerms.map((link) => ( + + ))} + Archives +
{hasFutureEvents && ( <>

Upcoming Events

@@ -52,9 +84,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}`}

)} @@ -72,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; @@ -83,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 () => { @@ -105,108 +149,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); }