Files
einfach-produktiv/app/agb/page.tsx
T
Marco c8f231baa6 Dynamic AGB address, real shipping costs on /versand instead of hardcoded constants
- AGB: name/address/email now come from company-settings via new
  VertragspartnerBlock (mid-document, see LegalPages.ts's contentPart2).
- VersandSections/VersandModal/CartContent/CheckoutContent/versand page:
  shipping cost and free-shipping threshold now come from the real
  ShippingMethods data (already fetched elsewhere for checkout), not the
  hardcoded lib/shipping.ts constants — those had already drifted from
  the real Payload values once. lib/shipping.ts deleted, nothing left to
  export.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-02 06:53:12 +00:00

105 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { Metadata } from "next";
import Link from "next/link";
import Image from "next/image";
import { draftMode } from "next/headers";
import { Reveal } from "../components/Reveal";
import { Footer } from "../components/Footer";
import { TrustRow } from "../components/TrustRow";
import { RichText, extractHeadings } from "../components/RichText";
import { LiveRichText } from "../components/LiveRichText";
import { SectionTOC, MobileSectionTOC } from "../components/SectionTOC";
import { getLegalPage, getCompanySettings } from "../lib/payload";
import { formatMonthYear } from "../lib/format";
import { VertragspartnerBlock, vertragspartnerHeadings } from "./components/VertragspartnerBlock";
export const metadata: Metadata = {
title: "AGB",
description: "Allgemeine Geschäftsbedingungen von einfach produktiv.",
alternates: { canonical: "/agb" },
};
export default async function AgbPage() {
const { isEnabled: isPreview } = await draftMode();
const [page, seller] = await Promise.all([getLegalPage("agb", { draft: isPreview }), getCompanySettings()]);
// Section 1 ("Geltungsbereich") comes first from `content`, THEN
// "2. Vertragspartner" (dynamic, sits between two CMS-driven halves —
// see LegalPages.ts's `contentPart2` comment), then the rest from
// `contentPart2`.
const headings = [
...(page ? extractHeadings(page.content) : []),
...vertragspartnerHeadings(),
...(page?.contentPart2 ? extractHeadings(page.contentPart2) : []),
];
return (
<>
<main className="flex flex-col flex-1 bg-bg-base">
<Reveal className="flex flex-col gap-3 items-start pb-6 pt-10 px-[var(--layout-padding-x)] w-full">
<p className="flex items-center gap-2 text-body-sm text-text-muted">
<Link href="/" className="hover:text-brand transition-colors">Startseite</Link>
<span></span>
<span className="text-text-primary">AGB</span>
</p>
<p
className="font-semibold text-h-feature text-text-primary"
style={{ fontFamily: "var(--font-lora)" }}
>
Allgemeine Geschäftsbedingungen
</p>
{page && <p className="text-body text-text-muted">Stand: {formatMonthYear(page.updatedAt)}</p>}
</Reveal>
{/* MobileSectionTOC — below lg: only, see SectionTOC.tsx's own
comment. Outside the sidebar's `hidden lg:flex` wrapper below
(that wrapper's `hidden` would hide this too otherwise). */}
<div className="lg:hidden px-[var(--layout-padding-x)] pb-4 w-full">
<MobileSectionTOC sections={headings} />
</div>
<div className="flex flex-col lg:flex-row gap-8 lg:gap-12 items-start pb-10 pt-2 px-[var(--layout-padding-x)] w-full">
<div className="hidden lg:flex flex-col gap-6 w-[22.5rem] shrink-0 lg:sticky lg:top-32 lg:self-start">
<SectionTOC sections={headings} />
{/* Static, not part of the CMS content — same reasoning as
the Impressum/Datenschutz pages' own callout cards. */}
<div className="bg-bg-muted flex flex-col gap-3 items-start p-6 rounded-md w-full">
<Image alt="" src="/icon-trust-leaf.png" width={28} height={28} className="size-7 object-contain" />
<p
className="font-semibold text-body text-text-primary"
style={{ fontFamily: "var(--font-lora)" }}
>
Unser Anspruch
</p>
<p className="text-body-sm text-text-muted">
Wir entwickeln Produkte, die dich im Alltag wirklich weiterbringen mit Klarheit,
Qualität und einem bewussten Umgang mit Ressourcen.
</p>
<div className="h-[0.125rem] w-8 bg-brand" />
</div>
</div>
<div className="w-full lg:flex-1 min-w-0 flex flex-col gap-8">
{page ? (
<>
{isPreview ? <LiveRichText initialContent={page.content} /> : <RichText content={page.content} />}
{/* Name/Adresse/E-Mail kommen direkt aus company-settings,
nicht aus der CMS-Richtext — single-sourced, gleiche
Begründung wie Impressum/Datenschutz. */}
{seller && <VertragspartnerBlock seller={seller} />}
{page.contentPart2 ? (
isPreview ? <LiveRichText initialContent={page.contentPart2} /> : <RichText content={page.contentPart2} />
) : null}
</>
) : (
<p className="text-body text-text-muted">Inhalte werden gerade aktualisiert.</p>
)}
</div>
</div>
<TrustRow />
</main>
<Footer />
</>
);
}