feat: Onepage nach Filmcamp-Gliederung umgebaut
- Figtree als einzige Schrift, Logo mittig in fester Kopfzeile - Headerbild ueber volle Breite und Hoehe, ohne Preis, mit Terminleiste - "Was dich erwartet" stellt die Villa mit animierter Bilderfolge vor, darunter Tagesablauf als Karussell (Programm folgt als PDF) - Preis: regulaerer Preis durchgestrichen, kein Verkaufsstartdatum, Ueberschrift "Jetzt Platz sichern mit Early Bird" - Team als "Mit dabei", danach drei Reels im Hochformat - Logo, Headerbild, Portraets und Reels ueber feste Dateinamen im Medienverzeichnis (docs/MEDIEN.md), ohne Neustart austauschbar - Widerrufsbelehrung im Admin pflegbar, Seite /widerruf, Live-Verkauf ohne Freigabe gesperrt - Anreise: Abholung am Bahnhof Firenze Santa Maria Novella - Booking-Link entfernt, Gedankenstriche aus Kundentexten entfernt Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
3cba3e2341
commit
7203cd1e6e
37 files changed
+962
-517
No files matched your search
@@ -0,0 +1,65 @@
|
||||
import { site } from "@/content/site";
|
||||
import type { PublicCampFacts } from "@/lib/camp";
|
||||
import { addDays, formatIsoWeekdayDate } from "@/lib/time";
|
||||
import { ScheduleCarousel, type ScheduleCard } from "../ScheduleCarousel";
|
||||
import { Slideshow } from "../Slideshow";
|
||||
|
||||
/** Stellt die Villa vor: Text links, laufende Bilderfolge rechts. */
|
||||
export function ExpectSection() {
|
||||
const { expect } = site;
|
||||
return (
|
||||
<section id="erwartet" aria-labelledby="erwartet-title" className="py-24 md:py-32">
|
||||
<div className="container-edge grid items-center gap-12 md:grid-cols-12 md:gap-10">
|
||||
<div className="md:col-span-5">
|
||||
<h2 id="erwartet-title" className="section-title">{expect.title}</h2>
|
||||
<p className="mt-6 text-xl font-semibold leading-snug md:text-2xl">{expect.lead}</p>
|
||||
<div className="prose-body mt-6 text-ink/85">
|
||||
{expect.paragraphs.map((p) => (
|
||||
<p key={p}>{p}</p>
|
||||
))}
|
||||
</div>
|
||||
<ul className="mt-8 space-y-3">
|
||||
{expect.highlights.map((item) => (
|
||||
<li key={item} className="flex items-center gap-3 font-medium">
|
||||
<span aria-hidden className="grid h-7 w-7 shrink-0 place-items-center rounded-full bg-rosso text-paper">
|
||||
<svg viewBox="0 0 24 24" className="h-4 w-4">
|
||||
<path d="M5 12.5l4.5 4.5L19 7.5" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
</span>
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<Slideshow images={expect.slides} className="md:col-span-7 md:col-start-6 lg:col-span-6 lg:col-start-7" />
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function scheduleCards(facts: PublicCampFacts): ScheduleCard[] {
|
||||
return site.schedule.days.map((day, index) => ({
|
||||
label: `Tag ${index + 1}`,
|
||||
date: facts.startDate ? formatIsoWeekdayDate(addDays(facts.startDate, index)) : null,
|
||||
title: day.title,
|
||||
items: day.items,
|
||||
}));
|
||||
}
|
||||
|
||||
/** Tagesablauf als Karten pro Tag, wie das Programm bei der Referenz. */
|
||||
export function ScheduleSection({ facts }: { facts: PublicCampFacts }) {
|
||||
const { schedule } = site;
|
||||
return (
|
||||
<section id="ablauf" aria-labelledby="ablauf-title" className="bg-sand/35 py-24 md:py-32">
|
||||
<div className="container-edge">
|
||||
<div className="flex flex-wrap items-end justify-between gap-6">
|
||||
<h2 id="ablauf-title" className="section-title">{schedule.title}</h2>
|
||||
<p className="max-w-md text-ink/80">{schedule.note}</p>
|
||||
</div>
|
||||
<div className="mt-12">
|
||||
<ScheduleCarousel days={scheduleCards(facts)} emptyText="Programm folgt." />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user