Skip to content

Commit acda971

Browse files
committed
Progress
1 parent 9971b71 commit acda971

File tree

5 files changed

+127
-99
lines changed

5 files changed

+127
-99
lines changed

src/app/conf/2025/components/speaker-links.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export function SpeakerLinks({
3939
target="_blank"
4040
rel="noreferrer"
4141
className={clsx(
42-
"flex items-center text-neu-900",
42+
"flex items-center text-neu-900 hover:bg-neu-600/10",
4343
size === "lg" ? "p-4" : "p-2",
4444
)}
4545
>

src/app/conf/2025/schedule/[id]/page.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,17 @@ export default function SessionPage({ params }: SessionProps) {
8989
<Hr className="mt-10 2xl:mt-16" />
9090
)}
9191

92-
<div className="mt-8 flex gap-4 px-2 pb-8 max-lg:flex-col sm:px-3 lg:mt-16 lg:gap-8 xl:pb-16">
93-
<h3 className="typography-h2 min-w-[320px]">
94-
Session description
95-
</h3>
96-
<p className="typography-body-lg">{event.description}</p>
97-
</div>
98-
99-
<Hr />
92+
{event.description && (
93+
<>
94+
<div className="mt-8 flex gap-4 px-2 pb-8 max-lg:flex-col sm:px-3 lg:mt-16 lg:gap-8 xl:pb-16">
95+
<h3 className="typography-h2 min-w-[320px]">
96+
Session description
97+
</h3>
98+
<p className="typography-body-lg">{event.description}</p>
99+
</div>
100+
<Hr />
101+
</>
102+
)}
100103

101104
<h3 className="typography-h2 my-8 max-w-[408px] px-2 sm:px-3 lg:my-16">
102105
Session speakers
@@ -213,7 +216,7 @@ function SessionSpeakers({
213216
return (
214217
<div
215218
className={clsx(
216-
"grid max-lg:*:border-y-0 lg:grid-cols-2 lg:gap-5",
219+
"grid lg:grid-cols-2 lg:gap-5 max-lg:[&>*:not(:last-child)]:border-b-0",
217220
className,
218221
)}
219222
>

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

Lines changed: 94 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@ import { clsx } from "clsx"
22
import { ScheduleSession } from "@/app/conf/2023/types"
33
import { Tag } from "@/app/conf/_design-system/tag"
44
import { Button } from "@/app/conf/_design-system/button"
5+
import { Anchor } from "@/app/conf/_design-system/anchor"
56
import { CalendarIcon } from "@/app/conf/_design-system/pixelarticons/calendar-icon"
67
import { PinIcon } from "@/app/conf/_design-system/pixelarticons/pin-icon"
78
import ClockIcon from "@/app/conf/_design-system/pixelarticons/clock.svg?svgr"
89
import PlusIcon from "@/app/conf/_design-system/pixelarticons/plus.svg?svgr"
910
import PlayIcon from "@/app/conf/_design-system/pixelarticons/play.svg?svgr"
1011
import { findVideo } from "../../schedule/[id]/session-video"
11-
import { getEventTitle } from "../../utils"
12+
import { eventsColors, getEventTitle } from "../../utils"
13+
import React from "react"
1214

1315
export interface LongSessionCardProps
1416
extends React.HTMLAttributes<HTMLDivElement> {
1517
session: ScheduleSession
1618
eventColors?: Record<string, string>
19+
year?: string
1720
}
1821

1922
function formatTime(dateString: string): string {
@@ -33,7 +36,7 @@ function formatDate(dateString: string): string {
3336

3437
export function LongSessionCard({
3538
session,
36-
eventColors = {},
39+
year = "2025",
3740
className,
3841
...props
3942
}: LongSessionCardProps) {
@@ -49,101 +52,116 @@ export function LongSessionCard({
4952
session.speakers?.map(s => s.name) || [],
5053
)
5154
const video = findVideo(session, eventTitle)
52-
const hasVideo = video !== null
5355

54-
if (hasVideo) {
55-
return (
56-
<div
57-
className={clsx(
58-
"border border-neu-200 bg-neu-0 p-6 shadow-sm",
59-
className,
60-
)}
61-
{...props}
62-
>
63-
<div className="mb-6 flex flex-col gap-6">
64-
<div className="flex items-center justify-between gap-6">
65-
<Tag color={eventColors[session.event_type]}>{eventType}</Tag>
66-
<div className="flex items-center gap-2 border border-neu-400 bg-neu-100 px-2 py-1">
67-
<span className="typography-menu text-neu-900">
68-
{/* todo: find year */}
69-
GraphQLConf 2024
70-
</span>
71-
</div>
72-
</div>
73-
<div className="flex flex-col gap-2">
74-
<div className="min-h-[120px]">
75-
<h3 className="typography-h3 text-neu-900">{session.name}</h3>
76-
</div>
77-
<div className="flex items-center justify-between gap-2">
78-
<span className="typography-body-sm text-neu-600">
79-
{session.speakers?.[0]?.name || "Speaker"}
80-
</span>
81-
<div className="flex items-center gap-0.5">
82-
<ClockIcon className="size-3 text-neu-600" />
83-
<span className="typography-body-xs text-neu-600">25 min</span>
84-
</div>
85-
</div>
86-
</div>
87-
</div>
88-
<Button href="#" variant="primary" className="w-full">
89-
Watch
90-
<PlayIcon className="size-3" />
91-
</Button>
92-
</div>
93-
)
94-
}
56+
const eventDuration =
57+
new Date(session.event_end).getTime() -
58+
new Date(session.event_start).getTime()
59+
60+
const speakers = session.speakers || []
9561

9662
return (
9763
<div
9864
className={clsx(
99-
"flex flex-col gap-6 border border-neu-200 bg-neu-0 p-6 shadow-sm backdrop-blur-md",
65+
"group relative border border-neu-200 bg-neu-0 p-6",
66+
!!video && "flex flex-col gap-6 backdrop-blur-md",
10067
className,
10168
)}
10269
{...props}
10370
>
104-
<div className="flex flex-col gap-6">
71+
<Anchor
72+
href={`/conf/${year}/schedule/${session.id}?name=${session.name}`}
73+
className="absolute inset-0 z-[1] ring-inset ring-neu-400 hover:ring-1 dark:ring-neu-100"
74+
aria-label={`Read more about "${eventTitle}" by ${session.speakers?.[0]?.name || "Speaker"}`}
75+
/>
76+
77+
<div className={clsx("flex flex-col gap-6", video && "mb-6")}>
10578
<div className="flex items-center justify-between gap-6">
106-
<Tag color={eventColors[session.event_type]}>{eventType}</Tag>
79+
<Tag
80+
color={
81+
eventsColors[session.event_type] || "hsl(var(--color-neu-700))"
82+
}
83+
>
84+
{eventType}
85+
</Tag>
86+
{video && (
87+
<div className="flex items-center gap-2 border border-neu-400 bg-neu-100 px-2 py-1">
88+
<span className="typography-menu text-neu-900">
89+
{/* todo: find year */}
90+
GraphQLConf 2024
91+
</span>
92+
</div>
93+
)}
10794
</div>
95+
10896
<div className="flex flex-col gap-2">
10997
<div className="min-h-[120px]">
11098
<h3 className="typography-h3 text-neu-900">{session.name}</h3>
11199
</div>
112-
<div className="flex gap-2">
113-
<span className="typography-body-sm text-neu-600">
114-
{session.speakers?.[0]?.name || "Speaker"}
115-
</span>
100+
<div className="flex items-center justify-between gap-2">
101+
{(speakers?.length || 0) > 0 && (
102+
<span className="typography-body-sm">
103+
{speakers.map((s, i) => (
104+
<React.Fragment key={s.username || s.name}>
105+
{s.username ? (
106+
<Anchor
107+
href={`/conf/${year}/speakers/${s.username}`}
108+
className="relative z-[2] decoration-neu-600 hover:underline dark:decoration-neu-200"
109+
>
110+
{s.name}
111+
</Anchor>
112+
) : (
113+
s.name
114+
)}
115+
{i !== speakers.length - 1 && <span>, </span>}
116+
</React.Fragment>
117+
))}
118+
</span>
119+
)}
120+
{video && (
121+
<div className="flex items-center gap-0.5">
122+
<ClockIcon className="size-3" />
123+
<span className="typography-body-xs text-neu-600">
124+
{eventDuration}
125+
</span>
126+
</div>
127+
)}
116128
</div>
117129
</div>
118130
</div>
119-
<div className="flex items-center">
120-
<div className="flex flex-1 items-center gap-6 border-r border-neu-200 pr-6">
121-
<div className="flex items-center gap-0.5">
122-
<CalendarIcon className="size-3 text-sec-base" />
123-
<span className="typography-body-xs text-neu-600">
124-
{formattedDate}
125-
</span>
126-
</div>
127-
<div className="flex items-center gap-0.5">
128-
<ClockIcon className="size-3 text-sec-base" />
129-
<span className="typography-body-xs text-neu-600">
130-
{formattedTime}
131-
</span>
131+
132+
{video ? (
133+
<Button
134+
href={`https://youtube.com/embed/${video.id}`}
135+
variant="primary"
136+
className="relative z-[2] w-full"
137+
>
138+
Watch
139+
<PlayIcon className="size-6" />
140+
</Button>
141+
) : (
142+
<div className="flex items-center text-neu-800">
143+
<div className="flex flex-1 items-center gap-6 border-r border-neu-200 pr-6">
144+
<div className="flex items-center gap-0.5">
145+
<CalendarIcon className="size-4 text-sec-dark" />
146+
<span className="typography-body-xs">{formattedDate}</span>
147+
</div>
148+
<div className="flex items-center gap-0.5">
149+
<ClockIcon className="size-4 text-sec-dark" />
150+
<span className="typography-body-xs">{formattedTime}</span>
151+
</div>
152+
<div className="flex items-center gap-0.5">
153+
<PinIcon className="size-4 text-sec-dark" />
154+
<span className="typography-body-xs">{session.venue}</span>
155+
</div>
132156
</div>
133-
<div className="flex items-center gap-0.5">
134-
<PinIcon className="size-3 text-sec-base" />
135-
<span className="typography-body-xs text-neu-600">
136-
{session.venue}
137-
</span>
157+
<div className="flex flex-col items-center justify-center gap-6 pl-6">
158+
<button className="relative z-[2] flex items-center gap-0.5 text-neu-800">
159+
<PlusIcon className="size-4 text-sec-dark" />
160+
<span className="typography-body-xs">Add to calendar</span>
161+
</button>
138162
</div>
139163
</div>
140-
<div className="flex flex-col items-center justify-center gap-6 pl-6">
141-
<button className="flex items-center gap-0.5 text-neu-600 hover:text-neu-900">
142-
<PlusIcon className="size-3 text-sec-base" />
143-
<span className="typography-body-xs">Add to calendar</span>
144-
</button>
145-
</div>
146-
</div>
164+
)}
147165
</div>
148166
)
149167
}

src/app/conf/2025/speakers/[id]/page.tsx

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,15 @@ export default function SpeakerPage({ params }: SpeakerProps) {
6060
<div className="border-x border-neu-200 pt-8 dark:border-neu-100 2xl:pt-16">
6161
<SpeakerHeader speaker={speaker} year="2025" />
6262

63-
<div>
64-
<SpeakerLinks size="lg" speaker={speaker} />
63+
<div className="flex justify-end">
64+
<SpeakerLinks
65+
size="lg"
66+
speaker={speaker}
67+
className="!border-r-0"
68+
/>
6569
</div>
66-
<p className="typography-body-lg mt-8 p-4 lg:p-8 xl:px-24 xl:pb-24 xl:pt-16 xl:text-[32px]">
70+
71+
<p className="typography-body-lg px-4 py-8 lg:p-8 xl:px-24 xl:pb-24 xl:pt-16 xl:text-[32px]">
6772
{speaker.about}
6873
</p>
6974

@@ -116,20 +121,22 @@ function SpeakerHeader({
116121
}) {
117122
return (
118123
<header className={className}>
119-
<div>
124+
<div className="pl-2 sm:pl-3">
120125
<BackLink year="2025" kind="schedule" />
121-
<p className="typography-h3 mt-4 lg:mt-20">Meet the speaker</p>
122-
<h1 className="typography-h1 mt-2">{speaker.name}</h1>
126+
<p className="typography-body-lg mt-4 text-sec-darker lg:typography-h3 lg:mt-20">
127+
Meet the speaker
128+
</p>
129+
<h1 className="typography-h1 lg:mt-2">{speaker.name}</h1>
123130
<div className="flex flex-wrap items-center justify-between gap-2 lg:gap-x-4 xl:gap-x-8">
124131
{[speaker.position, speaker.company === "-" ? "" : speaker.company]
125132
.filter(Boolean)
126133
.join(", ")}
127-
<SpeakerTags speaker={speaker} />
134+
<SpeakerTags speaker={speaker} className="max-lg:flex-nowrap" />
128135
</div>
129136
</div>
130137
{speaker.avatar && (
131-
<div className="relative overflow-hidden">
132-
<div className="absolute inset-0 z-[1] bg-sec-lighter opacity-90 mix-blend-multiply" />
138+
<div className="relative overflow-hidden max-lg:mt-6">
139+
<div className="absolute inset-0 z-[1] bg-[hsl(79_81%_83.5%)] opacity-90 mix-blend-multiply" />
133140
<Image
134141
src={speaker.avatar}
135142
alt=""
@@ -153,7 +160,7 @@ function SpeakerSessions({
153160
return (
154161
<div
155162
className={clsx(
156-
"grid max-lg:*:border-y-0 lg:grid-cols-2 lg:gap-5",
163+
"grid lg:grid-cols-2 lg:gap-5 [&>*:not(:last-child)]:border-b-0",
157164
className,
158165
)}
159166
>
Lines changed: 3 additions & 3 deletions
Loading

0 commit comments

Comments
 (0)