214 lines
9.0 KiB
TypeScript
214 lines
9.0 KiB
TypeScript
import type { ReactNode } from "react";
|
|
import Link from "next/link";
|
|
import { ChevronDown } from "lucide-react";
|
|
import Nav from "@/components/nav";
|
|
import Footer from "@/components/footer";
|
|
import RelatedTools from "@/components/related-tools";
|
|
import RelatedGuides from "@/components/related-guides";
|
|
|
|
export type FaqItem = {
|
|
q: string;
|
|
a: string;
|
|
};
|
|
|
|
type SubpageLayoutProps = {
|
|
toolSlug: string;
|
|
toolName: string;
|
|
h1Title: string;
|
|
introText: string;
|
|
steps: string[];
|
|
examples: string[];
|
|
vorteileText: ReactNode;
|
|
additionalContent?: ReactNode;
|
|
faqs: FaqItem[];
|
|
updatedDate: string;
|
|
children: ReactNode;
|
|
};
|
|
|
|
export default function SubpageLayout({
|
|
toolSlug,
|
|
toolName,
|
|
h1Title,
|
|
introText,
|
|
steps,
|
|
examples,
|
|
vorteileText,
|
|
additionalContent,
|
|
faqs,
|
|
updatedDate,
|
|
children,
|
|
}: SubpageLayoutProps) {
|
|
const howItWorksName =
|
|
toolSlug === "muenze-werfen" ? "der Münzwurf" : toolName;
|
|
|
|
return (
|
|
<>
|
|
<Nav />
|
|
<main className="relative flex-1 pt-16 overflow-hidden">
|
|
{/* Full-width Viewport Background: Architektonisches Grid & Geometrie-Muster (wie im Referenzbild) mit sanftem Übergang nach unten */}
|
|
<div
|
|
aria-hidden
|
|
className="pointer-events-none absolute inset-x-0 top-0 -z-10 h-[620px] w-full overflow-hidden [mask-image:linear-gradient(to_bottom,black_45%,transparent_98%)]"
|
|
>
|
|
{/* Weiche Aquarell-Glows (einheitlich in Salbeigrün) */}
|
|
<div className="absolute top-8 left-[12%] h-72 w-72 rounded-full bg-[#8da399]/20 blur-3xl" />
|
|
<div className="absolute top-48 left-[50%] h-64 w-64 rounded-full bg-[#8da399]/18 blur-3xl" />
|
|
|
|
{/* Vektor-Muster: Feines architektonisches Raster, Kreise & Punkte */}
|
|
<svg
|
|
className="absolute inset-0 h-full w-full opacity-75"
|
|
width="100%"
|
|
height="100%"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<defs>
|
|
<pattern
|
|
id="archPattern"
|
|
width="160"
|
|
height="160"
|
|
patternUnits="userSpaceOnUse"
|
|
>
|
|
{/* Feine Rasterlinien */}
|
|
<line x1="0" y1="0" x2="160" y2="0" stroke="#747874" strokeWidth="0.5" strokeOpacity="0.22" />
|
|
<line x1="0" y1="80" x2="160" y2="80" stroke="#747874" strokeWidth="0.5" strokeOpacity="0.15" strokeDasharray="4 4" />
|
|
<line x1="0" y1="0" x2="0" y2="160" stroke="#747874" strokeWidth="0.5" strokeOpacity="0.22" />
|
|
<line x1="80" y1="0" x2="80" y2="160" stroke="#747874" strokeWidth="0.5" strokeOpacity="0.15" strokeDasharray="4 4" />
|
|
|
|
{/* Diagonale feine Hilfslinien */}
|
|
<line x1="0" y1="0" x2="160" y2="160" stroke="#8da399" strokeWidth="0.4" strokeOpacity="0.15" />
|
|
|
|
{/* Geometrische Bögen & Kreise */}
|
|
<circle cx="80" cy="80" r="50" stroke="#8da399" strokeWidth="0.5" strokeOpacity="0.3" fill="none" />
|
|
<circle cx="80" cy="80" r="75" stroke="#8da399" strokeWidth="0.4" strokeOpacity="0.2" strokeDasharray="2 4" fill="none" />
|
|
<circle cx="0" cy="0" r="40" stroke="#8da399" strokeWidth="0.4" strokeOpacity="0.22" fill="none" />
|
|
|
|
{/* Punkte auf den Schnittstellen */}
|
|
<circle cx="80" cy="80" r="2" fill="#707a65" fillOpacity="0.5" />
|
|
<circle cx="0" cy="0" r="2.2" fill="#707a65" fillOpacity="0.45" />
|
|
<circle cx="160" cy="0" r="1.6" fill="#707a65" fillOpacity="0.4" />
|
|
<circle cx="0" cy="160" r="1.6" fill="#707a65" fillOpacity="0.4" />
|
|
<circle cx="160" cy="160" r="2.2" fill="#707a65" fillOpacity="0.45" />
|
|
|
|
<circle cx="80" cy="30" r="1.6" fill="#8da399" fillOpacity="0.45" />
|
|
<circle cx="80" cy="130" r="1.6" fill="#8da399" fillOpacity="0.45" />
|
|
<circle cx="30" cy="80" r="1.6" fill="#8da399" fillOpacity="0.4" />
|
|
<circle cx="130" cy="80" r="1.6" fill="#8da399" fillOpacity="0.4" />
|
|
</pattern>
|
|
</defs>
|
|
<rect width="100%" height="100%" fill="url(#archPattern)" />
|
|
</svg>
|
|
</div>
|
|
|
|
<div className="relative mx-auto w-full max-w-6xl px-5 py-12 sm:px-8 sm:py-16 md:py-20">
|
|
{/* Header Section ohne Container-Box */}
|
|
<header className="relative max-w-3xl mb-12 sm:mb-16">
|
|
<nav
|
|
aria-label="Breadcrumb"
|
|
className="flex items-center gap-2 mb-3 text-xs font-semibold uppercase tracking-widest text-ink-soft"
|
|
>
|
|
<Link href="/" className="hover:text-[#c97d60] transition-colors">
|
|
Entscheidomat
|
|
</Link>
|
|
<span className="text-line">/</span>
|
|
<span className="text-ink font-medium">{toolName}</span>
|
|
</nav>
|
|
|
|
<h1 className="font-display text-4xl sm:text-5xl lg:text-6xl font-semibold leading-[1.15] tracking-tight text-ink mb-4">
|
|
{h1Title}
|
|
</h1>
|
|
|
|
<p className="text-base sm:text-lg text-ink-soft leading-relaxed">
|
|
{introText}
|
|
</p>
|
|
</header>
|
|
|
|
{/* Main Interactive Tool Container */}
|
|
<section className="mb-14 sm:mb-20 rounded-3xl border border-line bg-surface p-6 sm:p-8 md:p-10 shadow-lift relative overflow-hidden">
|
|
{children}
|
|
</section>
|
|
|
|
{/* 2-Column Content Structure: Explanations & FAQ */}
|
|
<div className="grid grid-cols-1 lg:grid-cols-12 gap-10 lg:gap-14">
|
|
{/* Left Column: Guide & Info */}
|
|
<div className="lg:col-span-7 space-y-10">
|
|
<article>
|
|
<h2 className="font-display text-2xl sm:text-3xl font-semibold text-ink mb-4">
|
|
So funktioniert {howItWorksName.toLowerCase().startsWith("der") || howItWorksName.toLowerCase().startsWith("das") || howItWorksName.toLowerCase().startsWith("die") ? howItWorksName : `das ${howItWorksName}`}
|
|
</h2>
|
|
<ol className="space-y-3 text-base text-ink-soft pl-4 border-l-2 border-[#c97d60]/40">
|
|
{steps.map((step, idx) => (
|
|
<li key={idx} className="pl-2">
|
|
<span className="font-semibold text-ink">{idx + 1}. </span>
|
|
{step}
|
|
</li>
|
|
))}
|
|
</ol>
|
|
</article>
|
|
|
|
<article>
|
|
<h2 className="font-display text-2xl sm:text-3xl font-semibold text-ink mb-4">
|
|
Beispiele
|
|
</h2>
|
|
<ul className="space-y-2 text-base text-ink-soft list-disc pl-5">
|
|
{examples.map((ex, idx) => (
|
|
<li key={idx}>{ex}</li>
|
|
))}
|
|
</ul>
|
|
</article>
|
|
|
|
<article>
|
|
<h2 className="font-display text-2xl sm:text-3xl font-semibold text-ink mb-4">
|
|
Vorteile und Grenzen
|
|
</h2>
|
|
<div className="text-base text-ink-soft leading-relaxed">
|
|
{vorteileText}
|
|
</div>
|
|
</article>
|
|
|
|
{additionalContent}
|
|
|
|
<article className="p-6 sm:p-7 bg-paper/90 rounded-2xl border border-line shadow-soft">
|
|
<h2 className="font-display text-xl font-semibold text-ink mb-3">
|
|
Verwandte Tools
|
|
</h2>
|
|
<RelatedTools current={toolSlug} />
|
|
</article>
|
|
|
|
<RelatedGuides toolSlug={toolSlug} />
|
|
</div>
|
|
|
|
{/* Right Column: FAQ Accordion */}
|
|
<div className="lg:col-span-5">
|
|
<h2 className="font-display text-2xl sm:text-3xl font-semibold text-ink mb-6">
|
|
Häufige Fragen
|
|
</h2>
|
|
<div className="space-y-3">
|
|
{faqs.map((faq) => (
|
|
<details
|
|
key={faq.q}
|
|
className="group rounded-2xl border border-line bg-surface transition-colors hover:border-[#c97d60]/40 [&_summary::-webkit-details-marker]:hidden"
|
|
>
|
|
<summary className="flex cursor-pointer items-center justify-between gap-3 p-4 sm:p-5 font-display text-base font-semibold text-ink">
|
|
<span>{faq.q}</span>
|
|
<span className="shrink-0 text-ink-soft transition-transform duration-300 group-open:rotate-180">
|
|
<ChevronDown className="h-5 w-5" />
|
|
</span>
|
|
</summary>
|
|
<div className="px-4 pb-4 sm:px-5 sm:pb-5 text-sm sm:text-base leading-relaxed text-ink-soft border-t border-line/50 pt-3 mt-1">
|
|
{faq.a}
|
|
</div>
|
|
</details>
|
|
))}
|
|
</div>
|
|
<p className="mt-6 text-xs text-ink-soft">
|
|
Zuletzt aktualisiert: {updatedDate}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
<Footer />
|
|
</>
|
|
);
|
|
}
|