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"],