Some checks are pending
Deploy to Cloudflare Workers (OpenNext) / deploy (push) Waiting to run
69 lines
2.4 KiB
TypeScript
69 lines
2.4 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { pageSeo } from "@/content/page-seo";
|
|
import { createPageMetadata } from "@/lib/seo";
|
|
import Link from "next/link";
|
|
import {
|
|
speakers,
|
|
speakerGroupLabels,
|
|
speakerGroupOrder,
|
|
type SpeakerGroup,
|
|
} from "@/content/people";
|
|
import { site } from "@/content/site";
|
|
import { Section } from "@/components/layout/Section";
|
|
import { SpeakerCard } from "@/components/speakers/SpeakerCard";
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
export const metadata: Metadata = createPageMetadata(pageSeo.speakers);
|
|
|
|
export default function SpeakersPage() {
|
|
const grouped = speakerGroupOrder.reduce(
|
|
(acc, group) => {
|
|
const list = speakers.filter((s) => s.group === group);
|
|
if (list.length) acc[group] = list;
|
|
return acc;
|
|
},
|
|
{} as Partial<Record<SpeakerGroup, typeof speakers>>
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<Section className="pt-28">
|
|
<p className="text-xs font-semibold uppercase tracking-widest text-[#ffb300]">Lineup</p>
|
|
<h1 className="mt-3 max-w-3xl text-4xl font-bold md:text-5xl lg:text-6xl">
|
|
Summit speakers & judges
|
|
</h1>
|
|
<p className="mt-4 max-w-2xl text-lg text-muted-foreground">
|
|
{site.dates.label} · {site.venue.name}
|
|
</p>
|
|
</Section>
|
|
|
|
<Section variant="muted" className="pt-0" riftPattern="vein-right">
|
|
<div className="space-y-20">
|
|
{(Object.entries(grouped) as [SpeakerGroup, typeof speakers][]).map(
|
|
([group, list]) => (
|
|
<div key={group}>
|
|
<div className="mb-8 flex flex-wrap items-end justify-between gap-4 border-b border-border pb-4">
|
|
<div>
|
|
<h2 className="text-3xl font-bold">{speakerGroupLabels[group]}</h2>
|
|
<p className="mt-1 text-sm text-muted-foreground">{site.dates.label}</p>
|
|
</div>
|
|
</div>
|
|
<div className="grid gap-5 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
|
|
{list.map((speaker) => (
|
|
<SpeakerCard key={speaker.id} speaker={speaker} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
)
|
|
)}
|
|
</div>
|
|
<div className="mt-16 text-center">
|
|
<Button className="rounded-full bg-[#ffb300] text-[#0f0404]" asChild>
|
|
<Link href="/payment">Get tickets</Link>
|
|
</Button>
|
|
</div>
|
|
</Section>
|
|
</>
|
|
);
|
|
}
|