feat: Tagesablauf laut Wochenplan, Termin 03. bis 09. Mai 2027
Docker-Images bauen und veroeffentlichen / build-and-push (push) Successful in 2m51s
Docker-Images bauen und veroeffentlichen / build-and-push (push) Successful in 2m51s
- Alle sieben Tage aus dem Wochenplan-PDF mit Uhrzeit, Coach und Foto-Kennzeichnung im Karussell - Migration: Camp-Termin 03.05. bis 09.05.2027 (ersetzt 08. bis 15.05.) - Leistungen laut PDF: 20 Workshops und Shootings, sechs Naechte, Bustransfer ab und bis Florenz, Fruehstueck, Snacks und Abendessen - FAQ Anreise mit Transferzeiten - Hinweise "Programmentwurf" und "Laut Beschreibung der Unterkunft" entfernt Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
3f5a2554ee
commit
84c8f2f32b
7 files changed
+138
-52
No files matched your search
@@ -1,15 +1,16 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import type { ScheduleItem } from "@/content/site";
|
||||
|
||||
export type ScheduleCard = { label: string; date: string | null; title: string | null; items: string[] };
|
||||
export type ScheduleCard = { label: string; date: string | null; title: string; items: ScheduleItem[] };
|
||||
|
||||
/**
|
||||
* Tagesablauf als waagerechte Kartenreihe mit Einrasten (scroll-snap).
|
||||
* Wischen auf dem Smartphone, Pfeile und Punkte auf allen Groessen. Die
|
||||
* Liste bleibt eine echte Liste: ohne JavaScript scrollt sie trotzdem.
|
||||
*/
|
||||
export function ScheduleCarousel({ days, emptyText }: { days: ScheduleCard[]; emptyText: string }) {
|
||||
export function ScheduleCarousel({ days }: { days: ScheduleCard[] }) {
|
||||
const track = useRef<HTMLOListElement>(null);
|
||||
const cards = useRef<(HTMLLIElement | null)[]>([]);
|
||||
const [current, setCurrent] = useState(0);
|
||||
@@ -52,23 +53,28 @@ export function ScheduleCarousel({ days, emptyText }: { days: ScheduleCard[]; em
|
||||
cards.current[index] = el;
|
||||
}}
|
||||
data-index={index}
|
||||
className="flex w-[85%] shrink-0 snap-start flex-col rounded-2xl bg-paper p-7 shadow-[0_1px_0_var(--color-line)] sm:w-[60%] md:w-[44%] md:p-9 lg:w-[31%]"
|
||||
className="flex w-[88%] shrink-0 snap-start flex-col rounded-2xl bg-paper p-6 shadow-[0_1px_0_var(--color-line)] sm:w-[62%] md:w-[46%] md:p-8 lg:w-[34%]"
|
||||
>
|
||||
<p className="text-sm font-semibold uppercase tracking-[0.16em] text-rosso">{day.label}</p>
|
||||
<p className="text-sm font-semibold uppercase tracking-[0.16em] text-rosso">
|
||||
{day.label} · {day.title}
|
||||
</p>
|
||||
{day.date && <p className="mt-1 text-xl font-bold md:text-2xl">{day.date}</p>}
|
||||
{day.title && <p className="mt-1 text-stone">{day.title}</p>}
|
||||
{day.items.length > 0 ? (
|
||||
<ul className="mt-6 space-y-3 border-t border-line pt-5">
|
||||
{day.items.map((item) => (
|
||||
<li key={item} className="flex gap-3">
|
||||
<span aria-hidden className="mt-[0.6em] h-1.5 w-1.5 shrink-0 rounded-full bg-rosso" />
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<p className="mt-6 border-t border-line pt-5 text-stone">{emptyText}</p>
|
||||
)}
|
||||
<ul className="mt-5 divide-y divide-line border-t border-line">
|
||||
{day.items.map((item) => (
|
||||
<li key={`${item.time} ${item.text}`} className="grid grid-cols-[5.75rem_1fr] gap-x-3 py-3 text-[0.9375rem] leading-snug">
|
||||
<span className="font-semibold tabular-nums text-ink/75">{item.time}</span>
|
||||
<span>
|
||||
{item.text}
|
||||
{item.photo && (
|
||||
<span className="ml-2 inline-block translate-y-[-1px] rounded bg-sand/60 px-1.5 py-px align-middle text-[0.6875rem] font-bold uppercase tracking-[0.08em]">
|
||||
Foto
|
||||
</span>
|
||||
)}
|
||||
{item.coach && <span className="mt-0.5 block text-sm text-stone">mit {item.coach}</span>}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
|
||||
@@ -29,7 +29,6 @@ export function AccommodationSection({ facts, showDrafts }: { facts: PublicCampF
|
||||
<li key={feature} className="py-2.5">{feature}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="mt-2 text-sm text-stone">Laut Beschreibung der Unterkunft.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -52,13 +52,11 @@ export function ScheduleSection({ facts }: { facts: PublicCampFacts }) {
|
||||
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>
|
||||
<h2 id="ablauf-title" className="section-title">{schedule.title}</h2>
|
||||
<div className="mt-12">
|
||||
<ScheduleCarousel days={scheduleCards(facts)} emptyText="Programm folgt." />
|
||||
<ScheduleCarousel days={scheduleCards(facts)} />
|
||||
</div>
|
||||
<p className="mt-8 text-ink/80">{schedule.footnote}</p>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -33,7 +33,7 @@ function faqs(facts: PublicCampFacts, pricing: PublicPricing): Faq[] {
|
||||
},
|
||||
{
|
||||
q: "Wie reise ich an?",
|
||||
a: `Du reist selbst nach Florenz an. Am Anreisetag holen wir dich am Bahnhof Firenze Santa Maria Novella ab und bringen dich zur Villa. Kommst du mit dem Auto, fährst du direkt zur Unterkunft. Die Anreise nach Italien und zurück ist nicht im Preis enthalten.${facts.location ? ` Das Camp findet in der ${facts.location} statt.` : ""}`,
|
||||
a: `Du reist selbst nach Florenz an. Am Anreisetag fährt um 15:30 Uhr ein Bus vom Bahnhof Firenze Santa Maria Novella zur Villa. Kommst du mit dem Auto, fährst du direkt zur Unterkunft und bist zwischen 17:30 und 18:00 Uhr da. Am Abreisetag bringt dich der Bus zwischen 09:00 und 12:00 Uhr zurück nach Florenz. Die Anreise nach Italien und zurück ist nicht im Preis enthalten.${facts.location ? ` Das Camp findet in der ${facts.location} statt.` : ""}`,
|
||||
},
|
||||
{
|
||||
q: "Habe ich ein Widerrufsrecht?",
|
||||
|
||||
Reference in new issue
Block a user