Skip to content

Commit a42d95a

Browse files
committed
Add calendar link and fix long session cards
1 parent e931b9a commit a42d95a

File tree

3 files changed

+72
-32
lines changed

3 files changed

+72
-32
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"@tailwindcss/nesting": "0.0.0-insiders.565cd3e",
2828
"@tailwindcss/typography": "^0.5.15",
2929
"autoprefixer": "^10.4.20",
30+
"calendar-link": "^2.10.0",
3031
"clsx": "^2.1.1",
3132
"codemirror": "^5.65.19",
3233
"codemirror-graphql": "1.3.2",

pnpm-lock.yaml

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/conf/2025/speakers/[id]/long-session-card.tsx

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { clsx } from "clsx"
2-
import { ScheduleSession } from "@/app/conf/2023/types"
2+
import { ics } from "calendar-link"
3+
4+
import { SchedSpeaker, ScheduleSession } from "@/app/conf/2023/types"
35
import { Button } from "@/app/conf/_design-system/button"
46
import { Anchor } from "@/app/conf/_design-system/anchor"
57
import { CalendarIcon } from "@/app/conf/_design-system/pixelarticons/calendar-icon"
@@ -16,30 +18,27 @@ export interface LongSessionCardProps
1618
extends React.HTMLAttributes<HTMLDivElement> {
1719
session: ScheduleSession
1820
eventColors?: Record<string, string>
19-
year?: string
2021
}
2122

2223
export function LongSessionCard({
2324
session,
24-
year = "2025",
2525
className,
2626
...props
2727
}: LongSessionCardProps) {
28-
const formattedDate = new Date(session.event_start).toLocaleDateString(
29-
"en-US",
30-
{
31-
day: "numeric",
32-
month: "long",
33-
},
34-
)
35-
const formattedTime = new Date(session.event_start).toLocaleTimeString(
36-
"en-US",
37-
{
38-
hour: "2-digit",
39-
minute: "2-digit",
40-
hour12: false,
41-
},
42-
)
28+
const eventStart = new Date(session.event_start)
29+
30+
const formattedDate = eventStart.toLocaleDateString("en-US", {
31+
day: "numeric",
32+
month: "short",
33+
})
34+
35+
const year = eventStart.getFullYear()
36+
37+
const formattedTime = eventStart.toLocaleTimeString("en-US", {
38+
hour: "2-digit",
39+
minute: "2-digit",
40+
hour12: false,
41+
})
4342

4443
const eventTitle = getEventTitle(
4544
session,
@@ -68,14 +67,11 @@ export function LongSessionCard({
6867
/>
6968

7069
<div className="flex flex-col gap-6 p-4 lg:p-6">
71-
<div className="flex items-center justify-between gap-6">
70+
<div className="flex items-start justify-between gap-6">
7271
<SessionTags session={session} />
73-
{video && (
72+
{year !== new Date().getFullYear() && (
7473
<div className="flex items-center gap-2 border border-neu-400 bg-neu-100 px-2 py-1">
75-
<span className="typography-menu text-neu-900">
76-
{/* todo: find year */}
77-
2024
78-
</span>
74+
<span className="typography-menu text-neu-900">{year}</span>
7975
</div>
8076
)}
8177
</div>
@@ -107,7 +103,8 @@ export function LongSessionCard({
107103
</span>
108104
)}
109105
{video && (
110-
<div className="flex items-center gap-0.5">
106+
// ideally, we'd display the duration of the video, not the projected duration of the talk
107+
<div className="flex shrink-0 items-center gap-0.5">
111108
<ClockIcon className="size-3" />
112109
<span className="typography-body-xs text-neu-600">
113110
{Math.round(eventDurationMs / (1000 * 60))} min
@@ -118,8 +115,6 @@ export function LongSessionCard({
118115
</div>
119116
</div>
120117

121-
{/* todo: past session no recording variant */}
122-
123118
{video ? (
124119
<footer className="p-4 pt-0 lg:px-6 lg:pb-6">
125120
<Button
@@ -133,7 +128,7 @@ export function LongSessionCard({
133128
</footer>
134129
) : (
135130
<footer className="flex items-center border-t border-neu-200 text-neu-800 dark:border-neu-100">
136-
<div className="flex flex-1 items-center gap-6 border-r border-neu-200 p-4 dark:border-neu-100 lg:p-6">
131+
<div className="flex flex-1 items-center gap-2 border-r border-neu-200 p-4 dark:border-neu-100 lg:p-6 xl:gap-6">
137132
<div className="contents flex-col md:max-xl:flex">
138133
<div className="flex items-center gap-0.5 whitespace-pre">
139134
<CalendarIcon className="size-4 shrink-0 -translate-y-px text-sec-dark" />
@@ -149,12 +144,46 @@ export function LongSessionCard({
149144
<span className="typography-body-xs">{session.venue}</span>
150145
</div>
151146
</div>
152-
{/* <button className="relative z-[2] flex h-full flex-row items-center justify-center gap-0.5 p-4 text-neu-800 ring-inset ring-neu-400 hover:bg-sec-base/[.035] hover:ring-1 dark:ring-neu-100 lg:px-6">
153-
<PlusIcon className="size-4 shrink-0 text-sec-dark" />
154-
<span className="typography-body-xs">Add to calendar</span>
155-
</button> */}
147+
{year === new Date().getFullYear() && (
148+
<AddToCalendarLink
149+
eventTitle={eventTitle}
150+
session={session}
151+
speakers={speakers}
152+
/>
153+
)}
156154
</footer>
157155
)}
158156
</div>
159157
)
160158
}
159+
160+
function AddToCalendarLink({
161+
eventTitle,
162+
session,
163+
speakers,
164+
}: {
165+
eventTitle: string
166+
session: ScheduleSession
167+
speakers: SchedSpeaker[]
168+
}) {
169+
return (
170+
<a
171+
className="relative z-[2] flex h-full flex-row items-center justify-center gap-0.5 p-4 text-neu-800 ring-inset ring-neu-400 hover:bg-sec-base/[.035] hover:ring-1 dark:ring-neu-100 lg:px-6"
172+
href={ics({
173+
title: eventTitle,
174+
start: session.event_start,
175+
end: session.event_end,
176+
description: session.description,
177+
location: session.venue,
178+
organizer: {
179+
name: `GraphQLConf ${new Date().getFullYear()}`,
180+
181+
},
182+
guests: speakers.map(s => s.name),
183+
})}
184+
>
185+
<PlusIcon className="size-4 shrink-0 text-sec-dark" />
186+
<span className="typography-body-xs">Add to calendar</span>
187+
</a>
188+
)
189+
}

0 commit comments

Comments
 (0)