feat: add agenda page and update navigation

- Create dedicated agenda page with full-sized pretalx widget
- Update navigation: "Zgłoś się\!/CFP" → "Agenda/Schedule"
- Move agenda preview to top of contribute section
- Add calendar icon to agenda button in hero section
- Reorder hero buttons: agenda first, newsletter second
- Force light theme on agenda page for better widget compatibility
This commit is contained in:
Dariusz Niemczyk 2025-08-05 20:55:56 +02:00
parent f1ed363830
commit e69926a162
No known key found for this signature in database
3 changed files with 140 additions and 14 deletions

View file

@ -0,0 +1,78 @@
import Script from 'next/script';
import { getLocale, Lang, locales } from '@/i18n/locales';
import { translations } from '@/i18n/translations';
import { Metadata } from 'next';
import Link from 'next/link';
import { LanguageSelector } from '@/components/ui/language-selector';
export async function generateStaticParams() {
return locales.map((locale) => ({ locale }));
}
export async function generateMetadata({ params }: { params: Promise<{ locale: Lang }> }): Promise<Metadata> {
const { locale } = await params;
const currentLocale = getLocale(locale);
const t = translations[currentLocale];
return {
title: `${t.contribute.agenda.title} - ${t.hero.title}`,
description: t.about.description,
};
}
export default async function AgendaPage({ params }: { params: Promise<{ locale: Lang }> }) {
const { locale } = await params;
const currentLocale = getLocale(locale);
const t = translations[currentLocale];
return (
<>
<Script
src={`https://cfp.cebula.camp/camp-2025/schedule/widget/v2.${currentLocale}.js`}
strategy="afterInteractive"
/>
{/* Full page wrapper with forced light theme */}
<div className="fixed inset-0 bg-white">
{/* Custom light-themed navigation without theme context */}
<nav className="fixed top-0 left-0 right-0 bg-white border-b border-gray-200 z-[10000]">
<div className="container mx-auto px-4">
<div className="flex items-center justify-between h-16">
<div className="flex gap-4">
<Link href="/" className="text-xl font-bold tracking-tighter text-black hover:text-green-600 transition-colors">
<h1>{t.nav.title}</h1>
</Link>
</div>
<div className="flex items-center">
<LanguageSelector />
</div>
</div>
</div>
</nav>
<div className="h-full bg-white text-black pt-16 overflow-auto">
{/* Full-sized widget - no padding, full viewport */}
<div
style={{
'--pretalx-clr-primary': '#16a34a',
'--pretalx-clr-primary-text': '#ffffff',
'--pretalx-clr-secondary': '#f1f5f9',
'--pretalx-clr-text': '#000000',
'--pretalx-clr-background': '#ffffff',
'--pretalx-clr-border': '#e2e8f0',
'--pretalx-clr-hover': '#f8fafc',
} as React.CSSProperties}
>
{/* @ts-expect-error - pretalx-schedule is a custom web component */}
<pretalx-schedule
event-url="https://cfp.cebula.camp/camp-2025/"
locale={currentLocale}
style={{
display: 'block',
width: '100%',
minHeight: 'calc(100vh - 64px)' // Full height minus navbar
}}
/>
</div>
</div>
</div>
</>
);
}

View file

@ -187,7 +187,25 @@ export default function LandingPage(
<h1 className="text-5xl sm:text-6xl md:text-8xl font-bold tracking-tighter light:text-background">{t.hero.title}</h1>
<p className="mt-2 text-3xl sm:text-4xl md:text-5xl lg:text-6xl xl-text:7xl 2xl:text-8xl text-primary">{t.hero.subtitle}</p>
<p className="mt-2 text-3xl sm:text-4xl md:text-5xl lg:text-6xl xl-text:7xl 2xl:text-8xl text-primary ">{t.details.when.date}</p>
<div className='flex flex-col space-y-4 max-w-20 items-center justify-center m-auto'>
<div className='flex flex-col space-y-4 items-center justify-center m-auto'>
<Button className={`${oxanium.className} text-xl uppercase cursor-pointer`}>
<Link href={`/${currentLocale}/agenda`} className="flex items-center gap-2">
<svg
className="w-5 h-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
{t.contribute.agenda.title}
</Link>
</Button>
<NewsletterPopup t={t} />
</div>
</div>
@ -221,12 +239,7 @@ export default function LandingPage(
<Heading>{t.tickets.title}</Heading>
</div>
<section>
<TextWrapper><p>{t.tickets.status}</p></TextWrapper>
<TextWrapper>
<Button className={`${oxanium.className} text-xl mt-4 uppercase cursor-pointer`}>
<Link href="https://tickets.cebula.camp/cebulacamp/2025/">{t.tickets.link}</Link>
</Button>
</TextWrapper>
<TextWrapper><p className="text-2xl font-bold text-primary">{t.tickets.status}</p></TextWrapper>
</section>
</>
</NewSection>
@ -234,8 +247,39 @@ export default function LandingPage(
<NewSection id="contribute">
<>
<div>
<Heading>{t.contribute.title}</Heading>
<Heading>{t.contribute.agenda.title}</Heading>
</div>
<section>
<TextWrapper>
<div className="border border-border rounded-md bg-muted/30 p-8 text-center">
<div className="mb-6">
<svg
className="w-16 h-16 mx-auto text-primary mb-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
<p className="text-lg text-muted-foreground mb-4">
{currentLocale === 'pl'
? 'Zobacz pełny harmonogram wydarzeń, prelekcji i warsztatów'
: 'View the full schedule of events, talks, and workshops'}
</p>
</div>
<Button className={`${oxanium.className} text-xl uppercase cursor-pointer`} size="lg">
<Link href={`/${currentLocale}/agenda`}>
{currentLocale === 'pl' ? 'Zobacz agendę' : 'View agenda'}
</Link>
</Button>
</div>
</TextWrapper>
</section>
<section>
<Subheading>{t.contribute.talks.title}</Subheading>
<TextWrapper><p>{t.contribute.talks.description}</p></TextWrapper>

View file

@ -10,7 +10,7 @@ const pl = {
title: "CEBULACAMP",
about: "O wydarzeniu",
tickets: "Bilety",
contribute: "Zgłoś się!",
contribute: "Agenda",
details: "FAQ",
contact: "Kontakt",
},
@ -43,8 +43,7 @@ const pl = {
},
tickets: {
title: "Bilety",
status: `Ruszyła otwarta sprzedaż biletów na Cebula Camp 2025: Reaktywacja! Zarezerwuj swój bilet jak najszybciej!`,
link: "Kup bilet tutaj",
status: `Bilety na Cebula Camp 2025: Reaktywacja zostały wyprzedane!`,
},
contribute: {
title: "Zgłoś się!",
@ -62,6 +61,9 @@ const pl = {
link: "https://cfp.cebula.camp/camp-2025-art/cfp",
buttonText: "Zgłoś eksponat",
},
agenda: {
title: "Agenda",
},
},
faq: {
accommodation: {
@ -126,7 +128,7 @@ const en = {
title: "CEBULACAMP",
about: "About the event",
tickets: "Tickets",
contribute: "CFP",
contribute: "Schedule",
details: "FAQ",
contact: "Contact",
},
@ -158,8 +160,7 @@ const en = {
},
tickets: {
title: "Tickets",
status: `Open ticket sales for Cebula Camp 2025: Reactivated have started! Book your ticket as soon as possible!`,
link: "Get your ticket here!",
status: `Tickets for Cebula Camp 2025: Reactivated are sold out!`,
},
contribute: {
title: "Contribute!",
@ -177,6 +178,9 @@ const en = {
link: "https://cfp.cebula.camp/camp-2025-art/cfp",
buttonText: "Submit an exhibit",
},
agenda: {
title: "Schedule",
},
},
faq: {
accommodation: {