Fetch upcoming events and recent news on home page #162
|
@ -62,3 +62,38 @@ export async function getEventsByTerm(
|
||||||
.filter((name) => name.endsWith(".md"))
|
.filter((name) => name.endsWith(".md"))
|
||||||
.map((name) => name.slice(0, -".md".length));
|
.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))
|
||||||
|
);
|
||||||
a3thakra marked this conversation as resolved
Outdated
|
|||||||
|
} 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,
|
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 {
|
.cards > section {
|
||||||
|
width: calc(540rem / 16);
|
||||||
max-width: calc(540rem / 16);
|
max-width: calc(540rem / 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,13 +172,14 @@
|
||||||
.cards {
|
.cards {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: stretch;
|
||||||
gap: calc(8rem / 16);
|
gap: calc(8rem / 16);
|
||||||
|
|
||||||
padding: calc(36rem / 16) calc(20rem / 16) calc(20rem / 16);
|
padding: calc(36rem / 16) calc(20rem / 16) calc(20rem / 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cards > section {
|
.cards > section {
|
||||||
|
width: unset;
|
||||||
max-width: unset;
|
max-width: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { GetStaticProps } from "next";
|
||||||
|
import { MDXRemote } from "next-mdx-remote";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { ConnectWithUs } from "@/components/ConnectWithUs";
|
import { ConnectWithUs } from "@/components/ConnectWithUs";
|
||||||
|
@ -5,29 +7,21 @@ import { DefaultLayout } from "@/components/DefaultLayout";
|
||||||
import { EmailSignup } from "@/components/EmailSignup";
|
import { EmailSignup } from "@/components/EmailSignup";
|
||||||
import { EventDescriptionCard } from "@/components/EventDescriptionCard";
|
import { EventDescriptionCard } from "@/components/EventDescriptionCard";
|
||||||
import { Image } from "@/components/Image";
|
import { Image } from "@/components/Image";
|
||||||
|
import { Link } from "@/components/Link";
|
||||||
import { NewsCard } from "@/components/NewsCard";
|
import { NewsCard } from "@/components/NewsCard";
|
||||||
import { SocialLinks } from "@/components/SocialLinks";
|
import { SocialLinks } from "@/components/SocialLinks";
|
||||||
|
import { Event, getUpcomingEvents } from "@/lib/events";
|
||||||
import AltTab, {
|
import { News, getRecentNews } from "@/lib/news";
|
||||||
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 styles from "./index.module.css";
|
import styles from "./index.module.css";
|
||||||
|
|
||||||
// temporary event and news imports
|
interface Props {
|
||||||
|
moreEvents: boolean; // true if there are more than 2 upcoming events
|
||||||
a258wang marked this conversation as resolved
Outdated
a3thakra
commented
this seems redundant, why can't we just use events.length? this seems redundant, why can't we just use events.length?
a258wang
commented
Currently, we're displaying a link to the upcoming events page iff there are more than 2 upcoming events, however we are only passing up to 2 events in the events array (that is, 0 <= events.length <= 2). Currently, we're displaying a link to the upcoming events page iff there are more than 2 upcoming events, however we are only passing up to 2 events in the events array (that is, 0 <= events.length <= 2).
a3thakra
commented
oh, I see. In that case, you should pass in a boolean prop (eg oh, I see. In that case, you should pass in a boolean prop (eg `moreUpcomingEvents`) instead of `numberOfEvents`.
|
|||||||
export default function Home() {
|
events: Event[]; // array of 0 - 2 events
|
||||||
const events = [
|
news: News;
|
||||||
a3thakra marked this conversation as resolved
Outdated
a3thakra
commented
We only need the first news, so we should only pass 1 news item, instead of an array. We only need the first news, so we should only pass 1 news item, instead of an array.
|
|||||||
{ Content: OOTBReact, metadata: OOTBReactEventMetadata },
|
}
|
||||||
{ Content: AltTab, metadata: altTabEventMetadata },
|
|
||||||
];
|
|
||||||
|
|
||||||
|
export default function Home(props: Props) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DefaultLayout>
|
<DefaultLayout>
|
||||||
|
@ -54,30 +48,58 @@ export default function Home() {
|
||||||
</DefaultLayout>
|
</DefaultLayout>
|
||||||
<div className={styles.cardsBackground}>
|
<div className={styles.cardsBackground}>
|
||||||
<div className={styles.cards}>
|
<div className={styles.cards}>
|
||||||
{/* TODO: add links to past events and past news */}
|
|
||||||
<section className={styles.events}>
|
<section className={styles.events}>
|
||||||
a3thakra marked this conversation as resolved
Outdated
a3thakra
commented
links:
note that we will never have upcoming news. links:
- upcoming events: `/events`
- past events: `/events/archive`
- past news: `/news/archive`
note that we will never have upcoming news.
|
|||||||
<h1 className={styles.cardsHeading}>Upcoming Events</h1>
|
<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} />
|
<hr className={styles.cardsDividingLine} />
|
||||||
|
{props.events.length === 0 ? (
|
||||||
a3thakra marked this conversation as resolved
Outdated
a3thakra
commented
Use Use `===`. Only use `==` for null checks.
|
|||||||
|
<p>
|
||||||
|
There are no upcoming events right now. Please check back later!
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
<div className={styles.eventCards}>
|
<div className={styles.eventCards}>
|
||||||
{events.map(({ metadata }) => (
|
{props.events.length > 0
|
||||||
<EventDescriptionCard
|
? props.events.map((event) => (
|
||||||
{...metadata}
|
<EventDescriptionCard
|
||||||
key={metadata.name + metadata.date.toString()}
|
{...event.metadata}
|
||||||
/>
|
date={new Date(event.metadata.date)}
|
||||||
))}
|
key={event.metadata.name + event.metadata.date.toString()}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
: null}
|
||||||
</div>
|
</div>
|
||||||
|
{props.moreEvents ? (
|
||||||
|
<p>
|
||||||
|
See more upcoming events{" "}
|
||||||
|
<Link href="/events">
|
||||||
|
<a title="Events">here</a>
|
||||||
|
</Link>
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
</section>
|
</section>
|
||||||
<section className={styles.news} id="news">
|
<section className={styles.news} id="news">
|
||||||
<h1 className={styles.cardsHeading}>News</h1>
|
<h1 className={styles.cardsHeading}>News</h1>
|
||||||
<p className={styles.cardsDescription}>
|
<p className={styles.cardsDescription}>
|
||||||
Updates from our execs! <br />
|
Updates from our execs! <br />
|
||||||
See past news here
|
See past news{" "}
|
||||||
|
<Link href="/news/archive">
|
||||||
|
<a title="News Archive">here</a>
|
||||||
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
<hr className={styles.cardsDividingLine} />
|
<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>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -92,3 +114,15 @@ export default function Home() {
|
||||||
Home.Layout = function HomeLayout(props: { children: React.ReactNode }) {
|
Home.Layout = function HomeLayout(props: { children: React.ReactNode }) {
|
||||||
a3thakra marked this conversation as resolved
Outdated
a3thakra
commented
Just Just `GetStaticProps<Props>` is fine, you can omit Params here.
|
|||||||
return <div className={styles.page}>{props.children}</div>;
|
return <div className={styles.page}>{props.children}</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
a3thakra marked this conversation as resolved
Outdated
a3thakra
commented
You should slice these arrays here, if you don't that will make the HTML pages gigantic, as all the events and news will be serialized in HTML. You should slice these arrays here, if you don't that will make the HTML pages gigantic, as all the events and news will be serialized in HTML.
|
|||||||
|
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
no need to use async and await if the thing you're returning from your function is a promise.
so:
async (slug) => await getEventBySlug(year, TERMS[term], slug)
is the same as
(slug) => getEventBySlug(year, TERMS[term], slug)