From 6da987df4ce4838023816906add040d06927a229 Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Tue, 3 Jun 2025 15:05:13 +0200 Subject: [PATCH 01/22] wip --- src/app/conf/2025/components/speaker-card.tsx | 81 +------ .../conf/2025/components/speaker-links.tsx | 54 +++++ src/app/conf/2025/components/speaker-tags.tsx | 44 ++++ .../2025/speakers/[id]/long-session-card.tsx | 10 + src/app/conf/2025/speakers/[id]/page.tsx | 213 +++++++++++------- .../speakers/[id]/past-speaker-sessions.tsx | 13 ++ 6 files changed, 264 insertions(+), 151 deletions(-) create mode 100644 src/app/conf/2025/components/speaker-links.tsx create mode 100644 src/app/conf/2025/components/speaker-tags.tsx create mode 100644 src/app/conf/2025/speakers/[id]/long-session-card.tsx create mode 100644 src/app/conf/2025/speakers/[id]/past-speaker-sessions.tsx diff --git a/src/app/conf/2025/components/speaker-card.tsx b/src/app/conf/2025/components/speaker-card.tsx index 7c6afa7248..c26eef6772 100644 --- a/src/app/conf/2025/components/speaker-card.tsx +++ b/src/app/conf/2025/components/speaker-card.tsx @@ -7,13 +7,11 @@ import { Anchor } from "../../_design-system/anchor" import { Tag } from "../../_design-system/tag" import { SchedSpeaker } from "../../2023/types" import { StripesDecoration } from "../../_design-system/stripes-decoration" -import { SocialIcon, SocialIconType } from "../../_design-system/social-icon" -import ReloadIcon from "@/app/conf/_design-system/pixelarticons/reload.svg?svgr" -import PlayIcon from "@/app/conf/_design-system/pixelarticons/play.svg?svgr" +import { SpeakerTags } from "./speaker-tags" +import { SpeakerLinks } from "./speaker-links" import styles from "./speaker-card.module.css" -import { returningSpeakers, speakerSessions } from "../_data" export interface SpeakerCardProps extends React.HTMLAttributes { tags?: string[] @@ -43,7 +41,10 @@ export function SpeakerCard({ >
{showSocials && ( - + )}
@@ -107,41 +108,6 @@ export function SpeakerCard({ ) } -function SpeakerLinks({ - speaker, - className, -}: { - speaker: SchedSpeaker - className?: string -}) { - const speakerUrls = SocialIconType.all - .map(social => speaker.socialurls.find(x => x.service === social)) - .concat([{ service: "website", url: speaker.url || "" }]) - .filter((x): x is Exclude => !!x?.url) - .slice(-3) - - return ( -
- {speakerUrls.map(social => ( - - - - ))} -
- ) -} - function Stripes() { return (
) } - -function SpeakerTags({ - speaker, - className, -}: { - speaker: SchedSpeaker - className?: string -}) { - const eventType = speakerSessions.get(speaker.username)?.[0]?.event_type - - return ( -
- {eventType && ( - - {eventType === "Federation and Composite Schemas" - ? "Federation" - : eventType} - - )} - - - {returningSpeakers.has(speaker.username) ? ( - <> - - returning speaker - - ) : ( - <> - first time speaker - - )} - -
- ) -} diff --git a/src/app/conf/2025/components/speaker-links.tsx b/src/app/conf/2025/components/speaker-links.tsx new file mode 100644 index 0000000000..2242a11706 --- /dev/null +++ b/src/app/conf/2025/components/speaker-links.tsx @@ -0,0 +1,54 @@ +import clsx from "clsx" + +import { SchedSpeaker } from "@/app/conf/2023/types" +import { + SocialIcon, + SocialIconType, +} from "@/app/conf/_design-system/social-icon" + +export interface SpeakerLinksProps + extends React.HTMLAttributes { + speaker: SchedSpeaker + size?: "lg" | "md" +} + +export function SpeakerLinks({ + speaker, + className, + size = "md", + ...rest +}: SpeakerLinksProps) { + const speakerUrls = SocialIconType.all + .map(social => speaker.socialurls.find(x => x.service === social)) + .concat([{ service: "website", url: speaker.url || "" }]) + .filter((x): x is Exclude => !!x?.url) + .slice(-3) + + return ( +
+ {speakerUrls.map(social => ( + + + + ))} +
+ ) +} diff --git a/src/app/conf/2025/components/speaker-tags.tsx b/src/app/conf/2025/components/speaker-tags.tsx new file mode 100644 index 0000000000..3e497cd826 --- /dev/null +++ b/src/app/conf/2025/components/speaker-tags.tsx @@ -0,0 +1,44 @@ +import clsx from "clsx" + +import { SchedSpeaker } from "@/app/conf/2023/types" +import { Tag } from "@/app/conf/_design-system/tag" +import ReloadIcon from "@/app/conf/_design-system/pixelarticons/reload.svg?svgr" +import PlayIcon from "@/app/conf/_design-system/pixelarticons/play.svg?svgr" + +import { returningSpeakers, speakerSessions } from "../_data" +import { eventsColors } from "../utils" + +export function SpeakerTags({ + speaker, + className, +}: { + speaker: SchedSpeaker + className?: string +}) { + const eventType = speakerSessions.get(speaker.username)?.[0]?.event_type + + return ( +
+ {eventType && ( + + {eventType === "Federation and Composite Schemas" + ? "Federation" + : eventType} + + )} + + + {returningSpeakers.has(speaker.username) ? ( + <> + + returning speaker + + ) : ( + <> + first time speaker + + )} + +
+ ) +} diff --git a/src/app/conf/2025/speakers/[id]/long-session-card.tsx b/src/app/conf/2025/speakers/[id]/long-session-card.tsx new file mode 100644 index 0000000000..06b546da39 --- /dev/null +++ b/src/app/conf/2025/speakers/[id]/long-session-card.tsx @@ -0,0 +1,10 @@ +import { ScheduleSession } from "@/app/conf/2023/types" + +export interface LongSessionCardProps + extends React.HTMLAttributes { + session: ScheduleSession +} + +export function LongSessionCard({ session, className }: LongSessionCardProps) { + return
LongSessionCard
+} diff --git a/src/app/conf/2025/speakers/[id]/page.tsx b/src/app/conf/2025/speakers/[id]/page.tsx index cd623f356e..fda3c656b3 100644 --- a/src/app/conf/2025/speakers/[id]/page.tsx +++ b/src/app/conf/2025/speakers/[id]/page.tsx @@ -1,21 +1,21 @@ import { Metadata } from "next" -import NextLink from "next/link" +import { notFound } from "next/navigation" import React from "react" -import { SessionList } from "@/app/conf/_components/schedule/session-list" -import { - SocialMediaIcon, - SocialMediaIconServiceType, -} from "@/app/conf/_components/speakers/social-media" -import { Avatar } from "@/app/conf/_components/speakers/avatar" -import { ChevronLeftIcon } from "@/icons" - -import { speakers, schedule } from "../../_data" +import { speakers, speakerSessions } from "../../_data" import { metadata as layoutMetadata } from "../../layout" -import { filterCategories2024 } from "@/app/conf/_components/schedule/filter-categories" -import { eventsColors } from "../../utils" +import { eventsColors, HERO_MARQUEE_ITEMS } from "../../utils" import { BackLink } from "../../schedule/_components/back-link" +import { NavbarPlaceholder } from "../../components/navbar" +import { CtaCardSection } from "../../components/cta-card-section" +import clsx from "clsx" +import { SchedSpeaker } from "@/app/conf/2023/types" +import { Button } from "@/app/conf/_design-system/button" +import { MarqueeRows } from "../../components/marquee-rows" +import { GET_TICKETS_LINK } from "../../links" +import { Anchor } from "@/app/conf/_design-system/anchor" +import { SpeakerTags } from "../../components/speaker-tags" type SpeakerProps = { params: { id: string } } @@ -42,77 +42,138 @@ export function generateStaticParams() { } export default function SpeakerPage({ params }: SpeakerProps) { - const decodedId = decodeURIComponent(params.id) - const speaker = speakers.find(s => s.username === decodedId)! - - const s = schedule - .filter(s => s.speakers && s.speakers.some(s => s.username === decodedId)) - .map(s => ({ - ...s, - speakers: s.speakers!.map( - s => speakers.find(speaker => speaker.username === s.username)!, - ), - })) + const event = speakers.find(s => s.username === params.id) + if (!event) { + notFound() + } return ( -
-
-
- - -
-
-
-

{speaker.name}

- - - {speaker.company} - {speaker.company && ", "} - {speaker.position} - - -

{speaker.about}

- - {!!speaker.socialurls?.length && ( -
-
- {speaker.socialurls.map(social => ( - - - - ))} -
-
- )} + <> + +
+
+
+
+
+ + +
+ +
+

+ {event.about} +

+ +
+ +

+ 2025 Sessions +

+ + +
+ +

+ Sessions from previous editions +

+
+
+
+
- +
+
+ + + +
+
-

Sessions

-
-
+ + + ) +} + +function SpeakerHeader({ + speaker, + year, + className, +}: { + speaker: SchedSpeaker + year: `20${number}` + className?: string +}) { + return ( +
+ +

= 4 ? "typography-body-lg" : "typography-h3", + )} + > + {speakers.map((s, i) => ( + + + {s.name} + + {i !== speakers.length - 1 && , } + + ))} +

+

Meet the speaker

+

{speaker.name}

+
+ {[speaker.position, speaker.company === "-" ? "" : speaker.company] + .filter(Boolean) + .join(", ")} + +
+
+ ) +} + +function SpeakerSessions({ + speaker, + className, +}: { + speaker: SchedSpeaker + className?: string +}) { + return ( +
+ {speakerSessions + .get(speaker.username) + ?.map(session => ( + + ))}
) } + +function Hr({ className }: { className?: string }) { + return ( +
+ ) +} diff --git a/src/app/conf/2025/speakers/[id]/past-speaker-sessions.tsx b/src/app/conf/2025/speakers/[id]/past-speaker-sessions.tsx new file mode 100644 index 0000000000..fa4d799eb6 --- /dev/null +++ b/src/app/conf/2025/speakers/[id]/past-speaker-sessions.tsx @@ -0,0 +1,13 @@ +// TODO + +import { SchedSpeaker } from "@/app/conf/2023/types" + +export function PastSpeakerSessions({ + speaker, + className, +}: { + speaker: SchedSpeaker + className?: string +}) { + return
PastSpeakerSessions
+} From 657ea87f33aee270ade3766824633b5432c52f37 Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Tue, 3 Jun 2025 15:07:40 +0200 Subject: [PATCH 02/22] wip --- .../2025/speakers/[id]/long-session-card.tsx | 15 +++++++++++++-- src/app/conf/2025/speakers/[id]/page.tsx | 18 ++++++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/app/conf/2025/speakers/[id]/long-session-card.tsx b/src/app/conf/2025/speakers/[id]/long-session-card.tsx index 06b546da39..27efd82314 100644 --- a/src/app/conf/2025/speakers/[id]/long-session-card.tsx +++ b/src/app/conf/2025/speakers/[id]/long-session-card.tsx @@ -1,10 +1,21 @@ import { ScheduleSession } from "@/app/conf/2023/types" +import clsx from "clsx" export interface LongSessionCardProps extends React.HTMLAttributes { session: ScheduleSession + year: `20${number}` } -export function LongSessionCard({ session, className }: LongSessionCardProps) { - return
LongSessionCard
+export function LongSessionCard({ + session, + className, + year, + ...rest +}: LongSessionCardProps) { + return ( +
+ LongSessionCard {year} +
+ ) } diff --git a/src/app/conf/2025/speakers/[id]/page.tsx b/src/app/conf/2025/speakers/[id]/page.tsx index fda3c656b3..6653b10d03 100644 --- a/src/app/conf/2025/speakers/[id]/page.tsx +++ b/src/app/conf/2025/speakers/[id]/page.tsx @@ -16,6 +16,8 @@ import { MarqueeRows } from "../../components/marquee-rows" import { GET_TICKETS_LINK } from "../../links" import { Anchor } from "@/app/conf/_design-system/anchor" import { SpeakerTags } from "../../components/speaker-tags" +import { SpeakerLinks } from "../../components/speaker-links" +import { LongSessionCard } from "./long-session-card" type SpeakerProps = { params: { id: string } } @@ -42,8 +44,8 @@ export function generateStaticParams() { } export default function SpeakerPage({ params }: SpeakerProps) { - const event = speakers.find(s => s.username === params.id) - if (!event) { + const speaker = speakers.find(s => s.username === params.id) + if (!speaker) { notFound() } @@ -55,13 +57,13 @@ export default function SpeakerPage({ params }: SpeakerProps) {
- +
- +

- {event.about} + {speaker.about}


@@ -69,14 +71,14 @@ export default function SpeakerPage({ params }: SpeakerProps) {

2025 Sessions

- +

Sessions from previous editions

- +
@@ -161,7 +163,7 @@ function SpeakerSessions({ {speakerSessions .get(speaker.username) ?.map(session => ( - + ))}
) From f5ecee97a098727fba51dfa38f5d90041e007da1 Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Tue, 3 Jun 2025 15:17:25 +0200 Subject: [PATCH 03/22] wip --- src/app/conf/2025/schedule/[id]/page.tsx | 44 ++++-------------------- 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/src/app/conf/2025/schedule/[id]/page.tsx b/src/app/conf/2025/schedule/[id]/page.tsx index 372be4653a..844952086d 100644 --- a/src/app/conf/2025/schedule/[id]/page.tsx +++ b/src/app/conf/2025/schedule/[id]/page.tsx @@ -11,8 +11,7 @@ import { ScheduleSession } from "../../../2023/types" import { findVideo, SessionVideo } from "./session-video" import { NavbarPlaceholder } from "../../components/navbar" import { BackLink } from "../_components/back-link" -import { Tag } from "@/app/conf/_design-system/tag" -import { eventsColors, getEventTitle, HERO_MARQUEE_ITEMS } from "../../utils" +import { getEventTitle, HERO_MARQUEE_ITEMS } from "../../utils" import { PinIcon } from "@/app/conf/_design-system/pixelarticons/pin-icon" import { CalendarIcon } from "@/app/conf/_design-system/pixelarticons/calendar-icon" import { SpeakerCard } from "../../components/speaker-card" @@ -21,6 +20,7 @@ import { MarqueeRows } from "../../components/marquee-rows" import { GET_TICKETS_LINK } from "../../links" import { CtaCardSection } from "../../components/cta-card-section" import { Button } from "@/app/conf/_design-system/button" +import { SessionTags } from "../../components/session-tags" type SessionProps = { params: { id: string } } @@ -90,7 +90,7 @@ export default function SessionPage({ params }: SessionProps) { )}
-

+

Session description

{event.description}

@@ -98,14 +98,14 @@ export default function SessionPage({ params }: SessionProps) {
-

+

Session speakers


-

+

Session resources

@@ -142,36 +142,6 @@ export default function SessionPage({ params }: SessionProps) { ) } -function SessionTags({ session }: { session: ScheduleSession }) { - const eventType = session.event_type.endsWith("s") - ? session.event_type.slice(0, -1) - : session.event_type - - return ( -
- {eventType && ( - {eventType} - )} - {session.audience && ( - - {session.audience} - - )} - {session.event_subtype && ( - - {session.event_subtype} - - )} -
- ) -} - function SessionHeader({ event, eventTitle, @@ -206,9 +176,9 @@ function SessionHeader({ ))}

-

{eventTitle}

+

{eventTitle}

-
+
From 2ddc07a227cc3f889bcb3895de3861e63130329f Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Tue, 3 Jun 2025 15:24:41 +0200 Subject: [PATCH 04/22] wip --- .../2025/speakers/[id]/long-session-card.tsx | 132 +++++++++++++++++- 1 file changed, 126 insertions(+), 6 deletions(-) diff --git a/src/app/conf/2025/speakers/[id]/long-session-card.tsx b/src/app/conf/2025/speakers/[id]/long-session-card.tsx index 27efd82314..cd28ca5d96 100644 --- a/src/app/conf/2025/speakers/[id]/long-session-card.tsx +++ b/src/app/conf/2025/speakers/[id]/long-session-card.tsx @@ -1,21 +1,141 @@ +import { clsx } from "clsx" import { ScheduleSession } from "@/app/conf/2023/types" -import clsx from "clsx" +import { Tag } from "@/app/conf/_design-system/tag" +import { Button } from "@/app/conf/_design-system/button" +import { CalendarIcon } from "@/app/conf/_design-system/pixelarticons/calendar-icon" +import { PinIcon } from "@/app/conf/_design-system/pixelarticons/pin-icon" +import ClockIcon from "@/app/conf/_design-system/pixelarticons/clock.svg?svgr" +import PlusIcon from "@/app/conf/_design-system/pixelarticons/plus.svg?svgr" +import PlayIcon from "@/app/conf/_design-system/pixelarticons/play.svg?svgr" export interface LongSessionCardProps extends React.HTMLAttributes { session: ScheduleSession - year: `20${number}` + variant?: "current" | "previous" + eventColors?: Record +} + +function formatTime(dateString: string): string { + return new Date(dateString).toLocaleTimeString("en-US", { + hour: "2-digit", + minute: "2-digit", + hour12: false, + }) +} + +function formatDate(dateString: string): string { + return new Date(dateString).toLocaleDateString("en-US", { + day: "numeric", + month: "long", + }) } export function LongSessionCard({ session, + variant = "current", + eventColors = {}, className, - year, - ...rest + ...props }: LongSessionCardProps) { + const eventType = session.event_type.endsWith("s") + ? session.event_type.slice(0, -1) + : session.event_type + + const formattedDate = formatDate(session.event_start) + const formattedTime = formatTime(session.event_start) + + if (variant === "previous") { + return ( +
+
+
+ {eventType} +
+ + graphql conf 2024 + +
+
+
+
+

{session.name}

+
+
+ + {session.speakers?.[0]?.name || "Speaker"} + +
+ + 25 min +
+
+
+
+ +
+ ) + } + return ( -
- LongSessionCard {year} +
+
+
+ {eventType} +
+
+
+

{session.name}

+
+
+ + {session.speakers?.[0]?.name || "Speaker"} + +
+
+
+
+
+
+ + + {formattedDate} + +
+
+ + + {formattedTime} + +
+
+ + + {session.venue} + +
+
+
+ +
+
) } From 44611c778fa0c48c6ffe5c0e88f6d05767bc360e Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Tue, 3 Jun 2025 15:24:46 +0200 Subject: [PATCH 05/22] wip --- src/app/conf/2025/components/session-tags.tsx | 35 +++++++++++++++++++ .../_design-system/pixelarticons/clock.svg | 3 ++ .../_design-system/pixelarticons/plus.svg | 3 ++ 3 files changed, 41 insertions(+) create mode 100644 src/app/conf/2025/components/session-tags.tsx create mode 100644 src/app/conf/_design-system/pixelarticons/clock.svg create mode 100644 src/app/conf/_design-system/pixelarticons/plus.svg diff --git a/src/app/conf/2025/components/session-tags.tsx b/src/app/conf/2025/components/session-tags.tsx new file mode 100644 index 0000000000..a1707d582f --- /dev/null +++ b/src/app/conf/2025/components/session-tags.tsx @@ -0,0 +1,35 @@ +import { ScheduleSession } from "@/app/conf/2023/types" +import { Tag } from "@/app/conf/_design-system/tag" +import React from "react" + +import { eventsColors } from "../utils" + +export function SessionTags({ session }: { session: ScheduleSession }) { + const eventType = session.event_type.endsWith("s") + ? session.event_type.slice(0, -1) + : session.event_type + + return ( +
+ {eventType && ( + {eventType} + )} + {session.audience && ( + + {session.audience} + + )} + {session.event_subtype && ( + + {session.event_subtype} + + )} +
+ ) +} diff --git a/src/app/conf/_design-system/pixelarticons/clock.svg b/src/app/conf/_design-system/pixelarticons/clock.svg new file mode 100644 index 0000000000..71a9321608 --- /dev/null +++ b/src/app/conf/_design-system/pixelarticons/clock.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/app/conf/_design-system/pixelarticons/plus.svg b/src/app/conf/_design-system/pixelarticons/plus.svg new file mode 100644 index 0000000000..9e859fc573 --- /dev/null +++ b/src/app/conf/_design-system/pixelarticons/plus.svg @@ -0,0 +1,3 @@ + + + From 9971b712dd12fd849c3203cad325842f0605aa7b Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Tue, 3 Jun 2025 16:59:59 +0200 Subject: [PATCH 06/22] Tweak things --- src/app/conf/2025/schedule/[id]/page.tsx | 41 +++++++------ .../2025/speakers/[id]/long-session-card.tsx | 16 ++++-- src/app/conf/2025/speakers/[id]/page.tsx | 57 +++++++++---------- .../_design-system/session-card.example.tsx | 54 ++++++++++++++++++ 4 files changed, 117 insertions(+), 51 deletions(-) create mode 100644 src/app/conf/_design-system/session-card.example.tsx diff --git a/src/app/conf/2025/schedule/[id]/page.tsx b/src/app/conf/2025/schedule/[id]/page.tsx index 844952086d..07b0a3e0c7 100644 --- a/src/app/conf/2025/schedule/[id]/page.tsx +++ b/src/app/conf/2025/schedule/[id]/page.tsx @@ -68,8 +68,8 @@ export default function SessionPage({ params }: SessionProps) { return ( <> - -
+ +
@@ -101,22 +101,29 @@ export default function SessionPage({ params }: SessionProps) {

Session speakers

- - -
+ -

- Session resources -

-
- {event.files?.map(({ path }) => ( -