Add /events/[year]/[term] page #158
Merged
a3thakra
merged 46 commits from feat/events-term
into main
2 years ago
@ -1 +0,0 @@ |
||||
# Events page |
@ -0,0 +1,33 @@ |
||||
.main { |
||||
margin-top: calc(60rem / 16); |
||||
margin-bottom: calc(60rem / 16); |
||||
} |
||||
|
||||
.main > h2 { |
||||
padding-bottom: 1rem; |
||||
border-bottom: 1px solid var(--primary-heading); |
||||
} |
||||
|
||||
@media only screen and (max-width: calc(768rem / 16)) { |
||||
.main { |
||||
margin-top: calc(60rem / 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); |
||||
} |
||||
|
||||
.miniEventCards { |
||||
margin-top: calc(30rem / 16); |
||||
} |
@ -0,0 +1,154 @@ |
||||
import { ParsedUrlQuery } from "querystring"; |
||||
|
||||
import { GetStaticPaths, GetStaticProps } from "next"; |
||||
import { MDXRemote } from "next-mdx-remote"; |
||||
import React from "react"; |
||||
j285he marked this conversation as resolved
|
||||
|
||||
import { EventCard } from "@/components/EventCard"; |
||||
import { Link } from "@/components/Link"; |
||||
import { MiniEventCard } from "@/components/MiniEventCard"; |
||||
import { |
||||
Event, |
||||
getProps, |
||||
getEventYears, |
||||
getEventTermsByYear, |
||||
} from "@/lib/events"; |
||||
|
||||
import styles from "./index.module.css"; |
||||
|
||||
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 ( |
||||
<div className={styles.main}> |
||||
<div className={styles.header}> |
||||
{headerTerms.map((link) => ( |
||||
<HeaderLink |
||||
{...link} |
||||
isCurrentTerm={link.year === props.year && link.term === props.term} |
||||
key={link.year + link.term} |
||||
/> |
||||
))} |
||||
<Link href="/events/archives">Archives</Link> |
||||
</div> |
||||
{hasFutureEvents && ( |
||||
<> |
||||
<h2>Upcoming Events</h2> |
||||
<div className={styles.miniEventCards}> |
||||
{props.futureEvents.map(({ content, metadata }) => ( |
||||
<EventCard |
||||
{...metadata} |
||||
date={new Date(metadata.date)} |
||||
key={metadata.name + metadata.date.toString()} |
||||
> |
||||
<MDXRemote {...content} /> |
||||
</EventCard> |
||||
))} |
||||
</div> |
||||
</> |
||||
)} |
||||
{hasPastEvents && props.isCurrentTerm && <h2>Past Events</h2>} |
||||
{hasPastEvents && !props.isCurrentTerm && ( |
||||
<h2> |
||||
Events Archive: |
||||
<span className={styles.blue}> |
||||
{` ${capitalize(props.term)} ${props.year}`} |
||||
</span> |
||||
</h2> |
||||
)} |
||||
<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> |
||||
); |
||||
} |
||||
|
||||
function HeaderLink(props: { |
||||
year: string; |
||||
term: string; |
||||
isCurrentTerm?: boolean; |
||||
}) { |
||||
return ( |
||||
<Link href={`/events/${props.year}/${props.term}`}> |
||||
<span className={props.isCurrentTerm ? styles.curTerm : ""}> |
||||
{`${capitalize(props.term)} ${props.year}`} |
||||
</span> |
||||
</Link> |
||||
); |
||||
} |
||||
|
||||
interface Params extends ParsedUrlQuery { |
||||
year: string; |
||||
term: string; |
||||
} |
||||
|
||||
export const getStaticProps: GetStaticProps<Props, Params> = async ( |
||||
context |
||||
) => { |
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const { year, term } = context.params!; |
||||
|
||||
return { props: await getProps(year, term) }; |
||||
}; |
||||
|
||||
export const getStaticPaths: GetStaticPaths<Params> = async () => { |
||||
const years = await getEventYears(); |
||||
const paths = ( |
||||
await Promise.all( |
||||
years.map(async (year) => { |
||||
const terms = await getEventTermsByYear(year); |
||||
return terms.map((curTerm) => ({ |
||||
params: { year: year, term: curTerm }, |
||||
})); |
||||
}) |
||||
) |
||||
).flat(); |
||||
|
||||
return { |
||||
paths: paths, |
||||
fallback: false, |
||||
}; |
||||
}; |
||||
|
||||
function capitalize(str: string) { |
||||
return str.slice(0, 1).toUpperCase() + str.slice(1); |
||||
} |
Loading…
Reference in new issue
Use "@/components/..." instead of "../../../../components/..."