This commit is contained in:
commit
59bb5a38a3
132 files changed
+19435
No files matched your search
@@ -0,0 +1,108 @@
|
||||
import { site } from "@/content/site";
|
||||
import type { PublicCampFacts } from "@/lib/camp";
|
||||
import type { PublicPricing } from "@/lib/public-page";
|
||||
import { BookButton } from "../booking/BookingProvider";
|
||||
|
||||
type Faq = { q: string; a: React.ReactNode };
|
||||
|
||||
function faqs(facts: PublicCampFacts, pricing: PublicPricing): Faq[] {
|
||||
return [
|
||||
{
|
||||
q: "Wie läuft die Buchung ab?",
|
||||
a: "Du gibst deine Daten ein, wählst die Zahlungsweise und prüfst alles in einer Übersicht. Bezahlt wird auf einer sicheren Zahlungsseite unseres Zahlungsdienstleisters Stripe. Verbindlich bestätigt ist deine Buchung, sobald die Zahlung bei uns eingegangen ist – dann bekommst du eine E-Mail.",
|
||||
},
|
||||
{
|
||||
q: "Wie lange gilt der angezeigte Preis?",
|
||||
a: `Es gilt der Preis zum Zeitpunkt, an dem du die Buchung startest. Er bleibt ${pricing.reservationMinutes} Minuten für dich reserviert. Schließt du die Zahlung in dieser Zeit nicht ab, verfällt die Reservierung, und ein neuer Buchungsversuch wird zum dann gültigen Preis berechnet. Der Early-Bird-Preis endet am 31. Dezember 2026 um 24 Uhr und wird nicht verlängert.`,
|
||||
},
|
||||
{
|
||||
q: "Kann ich in Raten zahlen?",
|
||||
a: pricing.installmentsAllowed
|
||||
? "Ja, in zwei oder drei Raten. Die erste Rate zahlst du bei der Buchung, die weiteren werden zu festen Terminen über deine hinterlegte Zahlungsmethode eingezogen – die letzte spätestens 30 Tage vor Anreise. Alle Beträge und Termine siehst du vor der Zahlung. Nach der letzten Rate finden keine weiteren Abbuchungen statt."
|
||||
: "Ob eine Ratenzahlung möglich ist, geben wir bekannt, sobald der Camp-Termin feststeht.",
|
||||
},
|
||||
{
|
||||
q: "Welche Zahlungsarten gibt es?",
|
||||
a: "Die verfügbaren Zahlungsarten siehst du auf der Zahlungsseite von Stripe. Kartendaten gibst du nur dort ein; wir speichern sie nicht.",
|
||||
},
|
||||
{
|
||||
q: "Wie bin ich untergebracht?",
|
||||
a: facts.accommodationText
|
||||
? `Du buchst einen Platz pro Person mit geteilter Unterbringung. ${facts.accommodationText}`
|
||||
: "Du buchst einen Platz pro Person mit geteilter Unterbringung. Die genaue Zimmer- und Bettaufteilung veröffentlichen wir, sobald sie verbindlich feststeht – in jedem Fall bevor du buchst.",
|
||||
},
|
||||
{
|
||||
q: "Wie reise ich an?",
|
||||
a: `Die Anreise nach Italien und zurück organisierst du selbst; sie ist nicht im Preis enthalten.${facts.location ? ` Das Camp findet in ${facts.location} statt.` : " Den genauen Ort geben wir bekannt, sobald er feststeht."}`,
|
||||
},
|
||||
{
|
||||
q: "Was ist nicht im Preis enthalten?",
|
||||
a: `${site.services.excluded.join(", ")}.`,
|
||||
},
|
||||
{
|
||||
q: "Was gilt, wenn ich nicht teilnehmen kann?",
|
||||
a: facts.termsUrl ? (
|
||||
<>
|
||||
Das regeln unsere{" "}
|
||||
<a href={facts.termsUrl} className="underline">
|
||||
Buchungs-, Storno- und Zahlungsbedingungen
|
||||
</a>
|
||||
. Eine Reiserücktrittsversicherung ist nicht enthalten.
|
||||
</>
|
||||
) : (
|
||||
"Die Buchungs-, Storno- und Zahlungsbedingungen veröffentlichen wir vor dem Verkaufsstart. Eine Reiserücktrittsversicherung ist nicht enthalten."
|
||||
),
|
||||
},
|
||||
{
|
||||
q: "Ich habe einen Gutscheincode. Wo gebe ich ihn ein?",
|
||||
a: "Im zweiten Schritt der Buchung. Pro Buchung lässt sich ein Gutschein einlösen.",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function FaqSection({ facts, pricing }: { facts: PublicCampFacts; pricing: PublicPricing }) {
|
||||
return (
|
||||
<section id="fragen" aria-labelledby="fragen-title" className="py-20 md:py-32">
|
||||
<div className="container-edge grid gap-10 md:grid-cols-12">
|
||||
<h2 id="fragen-title" className="section-title md:col-span-4">{site.faq.title}</h2>
|
||||
<div className="md:col-span-8">
|
||||
{faqs(facts, pricing).map((item) => (
|
||||
<details key={item.q} className="group border-b border-line py-1 first:border-t">
|
||||
<summary className="flex cursor-pointer list-none items-center justify-between gap-6 py-4 text-lg font-semibold [&::-webkit-details-marker]:hidden">
|
||||
{item.q}
|
||||
<span aria-hidden className="text-2xl font-normal text-rosso transition-transform duration-200 group-open:rotate-45">
|
||||
+
|
||||
</span>
|
||||
</summary>
|
||||
<div className="max-w-2xl pb-5 text-ink/85">{item.a}</div>
|
||||
</details>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export function ClosingSection({ pricing }: { pricing: PublicPricing }) {
|
||||
return (
|
||||
<section aria-labelledby="schluss-title" className="on-dark bg-ink py-24 text-paper md:py-36">
|
||||
<div className="container-edge">
|
||||
<h2 id="schluss-title" className="display max-w-4xl text-[clamp(2.75rem,7vw,6rem)] leading-[0.98]">
|
||||
Wir freuen uns auf dich in Italien.
|
||||
</h2>
|
||||
<div className="mt-10 flex flex-wrap gap-3">
|
||||
{pricing.checkoutOpen ? (
|
||||
<BookButton className="btn bg-paper px-8 text-lg text-ink hover:bg-plaster">Platz buchen</BookButton>
|
||||
) : (
|
||||
<a href="#preis" className="btn bg-paper px-8 text-lg text-ink hover:bg-plaster">
|
||||
Zum Buchungsstart
|
||||
</a>
|
||||
)}
|
||||
<a href="#fragen" className="btn btn-quiet text-paper">
|
||||
Fragen ansehen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user