Fetch upcoming events and recent news on home page #162
|
@ -62,3 +62,38 @@ export async function getEventsByTerm(
|
|||
.filter((name) => name.endsWith(".md"))
|
||||
.map((name) => name.slice(0, -".md".length));
|
||||
}
|
||||
|
||||
export async function getUpcomingEvents(): Promise<Event[]> {
|
||||
const today = new Date();
|
||||
const currentYear = today.getFullYear();
|
||||
const currentTerm = Math.trunc(today.getMonth() / 4);
|
||||
const nextYear = currentTerm < 2 ? currentYear : currentYear + 1;
|
||||
const nextTerm = (currentTerm + 1) % 3;
|
||||
|
||||
const events: Event[] = (
|
||||
await Promise.all(
|
||||
[
|
||||
{ year: currentYear.toString(), term: currentTerm },
|
||||
{ year: nextYear.toString(), term: nextTerm },
|
||||
].map(async ({ year, term }) => {
|
||||
try {
|
||||
const eventsInTerm = await getEventsByTerm(year, TERMS[term]);
|
||||
return await Promise.all(
|
||||
eventsInTerm.map((slug) => getEventBySlug(year, TERMS[term], slug))
|
||||
);
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
})
|
||||
)
|
||||
).flat();
|
||||
|
||||
return events
|
||||
.filter((ev) => new Date(ev.metadata.date).getTime() >= Date.now())
|
||||
.sort((a, b) => {
|
||||
return (
|
||||
new Date(a.metadata.date).getTime() -
|
||||
new Date(b.metadata.date).getTime()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
35
lib/news.ts
35
lib/news.ts
|
@ -65,3 +65,38 @@ export async function getNewsBySlug(
|
|||
metadata: metadata as Metadata,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getRecentNews(): Promise<News[]> {
|
||||
const today = new Date();
|
||||
const currentYear = today.getFullYear();
|
||||
const currentTerm = Math.trunc(today.getMonth() / 4);
|
||||
const prevYear = currentTerm > 0 ? currentYear : currentYear - 1;
|
||||
const prevTerm = (currentTerm - 1 + 3) % 3;
|
||||
|
||||
const news: News[] = (
|
||||
await Promise.all(
|
||||
[
|
||||
{ year: currentYear.toString(), term: currentTerm },
|
||||
{ year: prevYear.toString(), term: prevTerm },
|
||||
].map(async ({ year, term }) => {
|
||||
try {
|
||||
const newsInTerm = await getNewsByTerm(year, TERMS[term]);
|
||||
return await Promise.all(
|
||||
newsInTerm.map((slug) => getNewsBySlug(year, TERMS[term], slug))
|
||||
);
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
})
|
||||
)
|
||||
).flat();
|
||||
|
||||
return news
|
||||
.filter((news) => new Date(news.metadata.date).getTime() <= Date.now())
|
||||
.sort((a, b) => {
|
||||
return (
|
||||
new Date(b.metadata.date).getTime() -
|
||||
new Date(a.metadata.date).getTime()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -119,6 +119,7 @@
|
|||
}
|
||||
|
||||
.cards > section {
|
||||
width: calc(540rem / 16);
|
||||
max-width: calc(540rem / 16);
|
||||
}
|
||||
}
|
||||
|
@ -171,13 +172,14 @@
|
|||
.cards {
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
gap: calc(8rem / 16);
|
||||
|
||||
padding: calc(36rem / 16) calc(20rem / 16) calc(20rem / 16);
|
||||
}
|
||||
|
||||
.cards > section {
|
||||
width: unset;
|
||||
max-width: unset;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { GetStaticProps } from "next";
|
||||
import { MDXRemote } from "next-mdx-remote";
|
||||
import React from "react";
|
||||
|
||||
import { ConnectWithUs } from "@/components/ConnectWithUs";
|
||||
|
@ -5,29 +7,21 @@ import { DefaultLayout } from "@/components/DefaultLayout";
|
|||
import { EmailSignup } from "@/components/EmailSignup";
|
||||
import { EventDescriptionCard } from "@/components/EventDescriptionCard";
|
||||
import { Image } from "@/components/Image";
|
||||
import { Link } from "@/components/Link";
|
||||
import { NewsCard } from "@/components/NewsCard";
|
||||
import { SocialLinks } from "@/components/SocialLinks";
|
||||
|
||||
import AltTab, {
|
||||
metadata as altTabEventMetadata,
|
||||
} from "../content/playground/alt-tab.event.mdx";
|
||||
import OOTBReact, {
|
||||
metadata as OOTBReactEventMetadata,
|
||||
} from "../content/playground/ootb-react.event.mdx";
|
||||
import UnavailableContent, {
|
||||
metadata as unavailableMetadata,
|
||||
} from "../content/playground/unavailable.news.mdx";
|
||||
import { Event, getUpcomingEvents } from "@/lib/events";
|
||||
import { News, getRecentNews } from "@/lib/news";
|
||||
|
||||
import styles from "./index.module.css";
|
||||
|
||||
// temporary event and news imports
|
||||
|
||||
export default function Home() {
|
||||
const events = [
|
||||
{ Content: OOTBReact, metadata: OOTBReactEventMetadata },
|
||||
{ Content: AltTab, metadata: altTabEventMetadata },
|
||||
];
|
||||
interface Props {
|
||||
moreEvents: boolean; // true if there are more than 2 upcoming events
|
||||
events: Event[]; // array of 0 - 2 events
|
||||
news: News;
|
||||
}
|
||||
|
||||
export default function Home(props: Props) {
|
||||
return (
|
||||
<>
|
||||
<DefaultLayout>
|
||||
|
@ -54,30 +48,58 @@ export default function Home() {
|
|||
</DefaultLayout>
|
||||
<div className={styles.cardsBackground}>
|
||||
<div className={styles.cards}>
|
||||
{/* TODO: add links to past events and past news */}
|
||||
<section className={styles.events}>
|
||||
<h1 className={styles.cardsHeading}>Upcoming Events</h1>
|
||||
<p className={styles.cardsDescription}>See past events here</p>
|
||||
<p className={styles.cardsDescription}>
|
||||
See past events{" "}
|
||||
<Link href="/events/archive">
|
||||
<a title="Events Archive">here</a>
|
||||
</Link>
|
||||
</p>
|
||||
<hr className={styles.cardsDividingLine} />
|
||||
{props.events.length === 0 ? (
|
||||
<p>
|
||||
There are no upcoming events right now. Please check back later!
|
||||
</p>
|
||||
) : null}
|
||||
<div className={styles.eventCards}>
|
||||
{events.map(({ metadata }) => (
|
||||
<EventDescriptionCard
|
||||
{...metadata}
|
||||
key={metadata.name + metadata.date.toString()}
|
||||
/>
|
||||
))}
|
||||
{props.events.length > 0
|
||||
? props.events.map((event) => (
|
||||
<EventDescriptionCard
|
||||
{...event.metadata}
|
||||
date={new Date(event.metadata.date)}
|
||||
key={event.metadata.name + event.metadata.date.toString()}
|
||||
/>
|
||||
))
|
||||
: null}
|
||||
</div>
|
||||
{props.moreEvents ? (
|
||||
<p>
|
||||
See more upcoming events{" "}
|
||||
<Link href="/events">
|
||||
<a title="Events">here</a>
|
||||
</Link>
|
||||
</p>
|
||||
) : null}
|
||||
</section>
|
||||
<section className={styles.news} id="news">
|
||||
<h1 className={styles.cardsHeading}>News</h1>
|
||||
<p className={styles.cardsDescription}>
|
||||
Updates from our execs! <br />
|
||||
See past news here
|
||||
See past news{" "}
|
||||
<Link href="/news/archive">
|
||||
<a title="News Archive">here</a>
|
||||
</Link>
|
||||
</p>
|
||||
<hr className={styles.cardsDividingLine} />
|
||||
<NewsCard {...unavailableMetadata}>
|
||||
<UnavailableContent />
|
||||
</NewsCard>
|
||||
{
|
||||
<NewsCard
|
||||
{...props.news.metadata}
|
||||
date={new Date(props.news.metadata.date)}
|
||||
>
|
||||
<MDXRemote {...props.news.content} />
|
||||
</NewsCard>
|
||||
}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -92,3 +114,15 @@ export default function Home() {
|
|||
Home.Layout = function HomeLayout(props: { children: React.ReactNode }) {
|
||||
return <div className={styles.page}>{props.children}</div>;
|
||||
};
|
||||
|
||||
export const getStaticProps: GetStaticProps<Props> = async () => {
|
||||
const upcomingEvents = await getUpcomingEvents();
|
||||
const recentNews = await getRecentNews();
|
||||
return {
|
||||
props: {
|
||||
moreEvents: upcomingEvents.length > 2,
|
||||
events: upcomingEvents.slice(0, 2),
|
||||
news: recentNews[0],
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue