Files
entscheidomat/components/subpage-layout.tsx
2026-08-05 19:33:11 +02:00

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 />
</>
);
}