diff --git a/src/components/sections/speakers.astro b/src/components/sections/speakers.astro new file mode 100644 index 000000000..5903ce5b4 --- /dev/null +++ b/src/components/sections/speakers.astro @@ -0,0 +1,219 @@ +--- +import { getCollection } from "astro:content"; +import type { CollectionEntry } from "astro:content"; +import { Image } from "astro:assets"; + +const allSpeakers = await getCollection("speakers"); + +const validSpeakers = allSpeakers.filter(speaker => + !!speaker.data?.name && !!speaker.data?.avatar +); + +function getRandomSpeakers(speakers: CollectionEntry<"speakers">[], count: number) { + const shuffled = [...speakers].sort(() => 0.5 - Math.random()); + return shuffled.slice(0, Math.min(count, speakers.length)); +} + +const featuredSpeakers = getRandomSpeakers(validSpeakers, 15); + +const sectionTitle = "Featured Speakers"; +const sectionSubtitle = "Meet some of our amazing speakers"; + +--- + +
+
+
+

{sectionTitle}

+

{sectionSubtitle}

+
+ + + + +
+
+ + + + diff --git a/src/pages/index.astro b/src/pages/index.astro index c1c8b74b3..dc881ad84 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -8,6 +8,7 @@ import Updates from "@sections/updates.astro"; import Prague from "@sections/prague.astro"; import Sponsors from "@components/sponsors/sponsors.astro"; import Subscribe from "@sections/subscribe.astro"; +import Speakers from "@sections/speakers.astro"; let deadlines = await getCollection("deadlines"); deadlines = deadlines @@ -23,6 +24,7 @@ deadlines = deadlines + diff --git a/src/pages/speakers.astro b/src/pages/speakers.astro index f72dc19e6..d6e419208 100644 --- a/src/pages/speakers.astro +++ b/src/pages/speakers.astro @@ -1,42 +1,65 @@ --- -import { getCollection } from "astro:content"; -import Layout from "../layouts/Layout.astro"; -import Prose from "../components/prose/prose.astro"; -import { Separator } from "../components/separator/separator"; +import { getCollection, type CollectionEntry } from "astro:content"; +import Layout from "@layouts/Layout.astro"; +import Prose from "@components/prose/prose.astro"; +import { Image } from "astro:assets"; + +type Speaker = CollectionEntry<"speakers">; -// Fetch all speaker entries const speakersCollection = await getCollection("speakers"); -// Define the type for the groups object -type Speaker = { - id: string; - data: { - name: string; - }; -}; - -type Groups = { - [key: string]: Speaker[]; -}; - -// Group speakers by the first letter of their name -const groups: Groups = speakersCollection - .filter((speaker: Speaker) => !!speaker.data.name) - .reduce((acc: Groups, speaker: Speaker) => { - const letter = speaker.data.name[0].toUpperCase(); - if (!acc[letter]) { - acc[letter] = []; +const speakersWithNames = speakersCollection.filter((speaker) => + !!speaker.data?.name +); + +const getFirstLetter = (name: string): string => name.charAt(0).toUpperCase(); + +function createOptimalGroups(speakers: Speaker[]): Record { + const sortedSpeakers = [...speakers].sort((a, b) => + a.data.name.localeCompare(b.data.name) + ); + + const groups: Record = {}; + let currentGroup: Speaker[] = []; + let currentLetter = ''; + let groupKey = ''; + + sortedSpeakers.forEach((speaker) => { + const letter = getFirstLetter(speaker.data.name); + + if (currentGroup.length === 0) { + currentLetter = letter; + groupKey = letter; + currentGroup.push(speaker); + } + else if (letter === currentLetter && currentGroup.length < 15) { + currentGroup.push(speaker); + } + else { + if (currentGroup.length < 10 && currentGroup.length + 1 <= 15) { + currentGroup.push(speaker); + groupKey = `${currentLetter}-${letter}`; + } else { + groups[groupKey] = currentGroup; + currentLetter = letter; + groupKey = letter; + currentGroup = [speaker]; + } } - acc[letter].push(speaker); - return acc; - }, {} as Groups); + }); -const letters = Object.keys(groups).sort((a, b) => a.localeCompare(b)); + if (currentGroup.length > 0) { + groups[groupKey] = currentGroup; + } -const title = "Speakers"; + return groups; +} + +const speakerGroups = createOptimalGroups(speakersWithNames); +const groupKeys = Object.keys(speakerGroups); -const description = - "Alphabetical list of all confirmed speakers for the conference"; +const title = "Speakers"; +const description = "Our conference speakers organized alphabetically"; --- @@ -45,49 +68,50 @@ const description =

Speakers

-
- { - letters.map((letter) => ( -

- {letter} -

- )) - } -
- -
    - { - letters.map((letter, index) => ( - <> -
    -

    - {letter} -

    - -
      - {groups[letter] - .sort((a, b) => a.data.name.localeCompare(b.data.name)) - .map((speaker) => ( -
    • - - {speaker.data.name} - -
    • - ))} -
    + { + groupKeys.map((key, index) => ( + <> + - {index !== letters.length - 1 ? ( - - ) : ( -
    - )} - - )) - } -
+ + )) + }
+ +