-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add event cards for each day to Schedule (#163)
* setup basic schedule page that fetches from sanity * feat: add event types to sanity * feat: add event announcements and miscellaneous events * feat: add time until event * fix: use Portable Text with announcement title * fix: commit pnpm-lock.yaml * feat: add mobile responsiveness * fix: display hosts when organization is undefined * feat: tabs stick to the top when scrolling near the top of screen on mobile screens * refactor: event type background * Revert "refactor: event type background" - doesn't work on preview This reverts commit 594aca7. * fix: change font sizes * fix: make announcement dates look cleaner * fix: switch from function calls to JSX component and extract converting dates to PST to utility function * fix: add metadata and maintenance variable * refactor: dynamically add Tailwind class based on event type * refactor: put EventProps into separate file
- Loading branch information
Showing
14 changed files
with
767 additions
and
270 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
export default interface EventProps { | ||
now: Date; | ||
title: string; | ||
eventType: string; | ||
location?: string | undefined; | ||
virtual?: string | undefined; | ||
startTime: Date; | ||
endTime: Date; | ||
organization?: string | undefined; | ||
hosts?: string[] | undefined; | ||
description: JSX.Element; | ||
} |
32 changes: 32 additions & 0 deletions
32
apps/site/src/app/schedule/components/EventAnnouncement.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import convertToPST from "@/lib/utils/convertToPST"; | ||
|
||
const dateTimeFormat = new Intl.DateTimeFormat("en", { | ||
month: "long", | ||
day: "numeric", | ||
hour: "numeric", | ||
minute: "numeric", | ||
}); | ||
|
||
interface EventAnnouncementProps { | ||
description: JSX.Element; | ||
startTime: Date; | ||
endTime: Date; | ||
} | ||
|
||
export default function EventAnnouncement({ | ||
description, | ||
startTime, | ||
endTime, | ||
}: EventAnnouncementProps) { | ||
const startTimeInPST = convertToPST(startTime); | ||
const endTimeInPST = convertToPST(endTime); | ||
|
||
return ( | ||
<div className="text-white bg-[#0F6722] p-5 mb-6 rounded-2xl text-center"> | ||
<div className="text-2xl">{description}</div> | ||
<p className="mb-2 text-lg"> | ||
{dateTimeFormat.formatRange(startTimeInPST, endTimeInPST)} PST | ||
</p> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import EventRegular from "./EventRegular"; | ||
import EventAnnouncement from "./EventAnnouncement"; | ||
import EventMiscellaneous from "./EventMiscellaneous"; | ||
import EventProps from "../EventProps"; | ||
|
||
export default function EventCard({ | ||
now, | ||
title, | ||
eventType, | ||
virtual, | ||
startTime, | ||
endTime, | ||
organization, | ||
hosts, | ||
description, | ||
}: EventProps) { | ||
if (eventType === "Announcement") { | ||
// description is used as the prop as opposed to title because description is a Portable Text object | ||
// that can reflect all text formats put in Sanity | ||
return ( | ||
<EventAnnouncement | ||
description={description} | ||
startTime={startTime} | ||
endTime={endTime} | ||
/> | ||
); | ||
} else if (eventType === "Miscellaneous") { | ||
return ( | ||
<EventMiscellaneous | ||
title={title} | ||
startTime={startTime} | ||
endTime={endTime} | ||
description={description} | ||
/> | ||
); | ||
} else { | ||
return ( | ||
<EventRegular | ||
now={now} | ||
title={title} | ||
eventType={eventType} | ||
virtual={virtual} | ||
startTime={startTime} | ||
endTime={endTime} | ||
organization={organization} | ||
hosts={hosts} | ||
description={description} | ||
/> | ||
); | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
apps/site/src/app/schedule/components/EventMiscellaneous.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import dayjs from "dayjs"; | ||
|
||
interface EventMiscellaneousProps { | ||
title: string; | ||
startTime: Date; | ||
endTime: Date; | ||
description: JSX.Element; | ||
} | ||
|
||
export default function EventMiscellaneous({ | ||
title, | ||
startTime, | ||
endTime, | ||
description, | ||
}: EventMiscellaneousProps) { | ||
const durationInHours = dayjs(endTime).diff(dayjs(startTime), "hour"); | ||
|
||
return ( | ||
<div className="text-white bg-[#973228] p-5 mb-6 rounded-2xl text-right text-lg"> | ||
<h3 className="text-2xl font-bold mb-3">{title}</h3> | ||
{description} | ||
<p>{durationInHours} hours</p> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import dayjs from "dayjs"; | ||
import relativeTime from "dayjs/plugin/relativeTime"; | ||
import convertToPST from "@/lib/utils/convertToPST"; | ||
import EventProps from "../EventProps"; | ||
dayjs.extend(relativeTime); | ||
|
||
const dateTimeFormat = new Intl.DateTimeFormat("en", { | ||
hour: "numeric", | ||
minute: "numeric", | ||
}); | ||
|
||
interface EventTypeProps { | ||
eventType: string; | ||
} | ||
|
||
interface EventMomentProps { | ||
now: Date; | ||
startTimeInPST: Date; | ||
endTimeInPST: Date; | ||
} | ||
|
||
interface EventBackgroundColors { | ||
Main: string; | ||
Workshop: string; | ||
Social: string; | ||
} | ||
|
||
const eventBackgroundColors: EventBackgroundColors = { | ||
Main: "bg-[#DFBA73]", | ||
Workshop: "bg-[#94A9BD]", | ||
Social: "bg-[#DFA9A9]", | ||
}; | ||
|
||
function EventTypeComponent({ eventType }: EventTypeProps) { | ||
return ( | ||
<div | ||
className={`inline-block px-4 py-1.5 font-semibold text-[#0D272D] ${ | ||
eventBackgroundColors[eventType as keyof EventBackgroundColors] | ||
} rounded-2xl sm:py-2`} | ||
> | ||
{eventType} | ||
</div> | ||
); | ||
} | ||
|
||
function EventMomentComponent({ | ||
now, | ||
startTimeInPST, | ||
endTimeInPST, | ||
}: EventMomentProps) { | ||
if (now > endTimeInPST) { | ||
const dEnd = dayjs(endTimeInPST); | ||
const timeAfterEnd = dEnd.from(now); | ||
return ( | ||
<p className="text-white/50 text-right mb-0"> | ||
Ended {timeAfterEnd} | ||
</p> | ||
); | ||
} else { | ||
if (now > startTimeInPST) { | ||
return <p className="text-white text-right mb-0">Happening Now!</p>; | ||
} else { | ||
const dStart = dayjs(startTimeInPST); | ||
const timeUntilStart = dStart.from(now); | ||
return ( | ||
<p className="text-white/50 text-right mb-0"> | ||
Starting {timeUntilStart} | ||
</p> | ||
); | ||
} | ||
} | ||
} | ||
|
||
export default function EventRegular({ | ||
now, | ||
title, | ||
eventType, | ||
virtual, | ||
startTime, | ||
endTime, | ||
organization, | ||
hosts, | ||
description, | ||
}: EventProps) { | ||
const startTimeInPST = convertToPST(startTime); | ||
const endTimeInPST = convertToPST(endTime); | ||
|
||
return ( | ||
<div className="text-[#FFFCE2] bg-[#432810] p-5 mb-6 rounded-2xl sm:text-lg"> | ||
<div className="mb-3 sm:flex sm:justify-between sm:items-center"> | ||
<h3 className="mb-3 text-2xl font-bold text-[#FFDA7B] sm:mb-0"> | ||
{title} | ||
</h3> | ||
<EventTypeComponent eventType={eventType} /> | ||
</div> | ||
<p className="mb-2"> | ||
Hosted by:{" "} | ||
{organization === undefined ? hosts?.join(", ") : organization} | ||
</p> | ||
<p className="mb-2"> | ||
{dateTimeFormat.formatRange(startTimeInPST, endTimeInPST)} PST |{" "} | ||
<a href={virtual}>Meeting Link</a> | ||
</p> | ||
{description} | ||
<EventMomentComponent | ||
now={now} | ||
startTimeInPST={startTimeInPST} | ||
endTimeInPST={endTimeInPST} | ||
/> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { z } from "zod"; | ||
import { cache } from "react"; | ||
import { client } from "@/lib/sanity/client"; | ||
import { SanityDocument } from "@/lib/sanity/types"; | ||
import { formatInTimeZone } from "date-fns-tz"; | ||
|
||
const Events = z.array( | ||
SanityDocument.extend({ | ||
_type: z.literal("event"), | ||
title: z.string(), | ||
eventType: z.string(), | ||
location: z.string().optional(), | ||
virtual: z.string().url().optional(), | ||
startTime: z | ||
.string() | ||
.datetime() | ||
.transform((time) => new Date(time)), | ||
endTime: z | ||
.string() | ||
.datetime() | ||
.transform((time) => new Date(time)), | ||
organization: z.string().optional(), | ||
hosts: z.array(z.string()).optional(), | ||
description: z.array( | ||
z.object({ | ||
_key: z.string(), | ||
markDefs: z.array( | ||
z.object({ | ||
_type: z.string(), | ||
href: z.optional(z.string()), | ||
_key: z.string(), | ||
}), | ||
), | ||
children: z.array( | ||
z.object({ | ||
text: z.string(), | ||
_key: z.string(), | ||
_type: z.literal("span"), | ||
marks: z.array(z.string()), | ||
}), | ||
), | ||
_type: z.literal("block"), | ||
style: z.literal("normal"), | ||
}), | ||
), | ||
}), | ||
); | ||
|
||
export const getSchedule = cache(async () => { | ||
const events = Events.parse( | ||
await client.fetch("*[_type == 'event'] | order(startTime asc)"), | ||
); | ||
const eventsByDay = new Map<string, z.infer<typeof Events>>(); | ||
|
||
events.forEach((event) => { | ||
const key = formatInTimeZone( | ||
new Date(event.startTime), | ||
"America/Los_Angeles", | ||
"MM/dd/yyyy", | ||
); | ||
eventsByDay.set(key, [...(eventsByDay.get(key) ?? []), event]); | ||
}); | ||
|
||
return Array.from(eventsByDay.values()); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.TabsTrigger[data-state="active"] { | ||
background-color: #fba80a; | ||
} |
Oops, something went wrong.