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>
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { headingId } from "../../components/RichText";
|
||||
import type { CompanySettings } from "../../lib/payload";
|
||||
import type { TOCSection } from "../../components/SectionTOC";
|
||||
|
||||
// Renders "2. Vertragspartner" straight from company-settings, same
|
||||
// single-source-of-truth pattern as Impressum's AnbieterAngaben.tsx and
|
||||
// Datenschutz's VerantwortlicherBlock.tsx — this used to be hand-typed
|
||||
// name/address/email baked into the AGB richText (seed-agb.ts on the
|
||||
// Payload side), and had already drifted from the real company-settings
|
||||
// values once (the richText's placeholder "Björn Wendt"/"Musterstraße
|
||||
// 12" never got updated when the real address was set). Sits mid-document
|
||||
// (section 1 "Geltungsbereich" comes before it), which is why AGB's
|
||||
// content is split into `content` (section 1) + `contentPart2` (sections
|
||||
// 3 onward) rather than just prepending this block like Datenschutz did —
|
||||
// see LegalPages.ts's `contentPart2` field comment.
|
||||
export function vertragspartnerHeadings(): TOCSection[] {
|
||||
return [{ id: headingId("2. Vertragspartner"), title: "2. Vertragspartner" }];
|
||||
}
|
||||
|
||||
function Heading({ children }: { children: string }) {
|
||||
return (
|
||||
<h2
|
||||
id={headingId(children)}
|
||||
className="font-semibold text-h-small text-text-primary mt-2 scroll-mt-32 first:mt-0"
|
||||
style={{ fontFamily: "var(--font-lora)" }}
|
||||
>
|
||||
{children}
|
||||
<span className="block h-[0.125rem] w-8 bg-brand mt-2" aria-hidden />
|
||||
</h2>
|
||||
);
|
||||
}
|
||||
|
||||
function P({ children }: { children: React.ReactNode }) {
|
||||
return <p className="text-body text-text-body">{children}</p>;
|
||||
}
|
||||
|
||||
export function VertragspartnerBlock({ seller }: { seller: CompanySettings }) {
|
||||
return (
|
||||
<div className="flex flex-col gap-4 w-full">
|
||||
<Heading>2. Vertragspartner</Heading>
|
||||
<P>Der Kaufvertrag kommt zustande mit:</P>
|
||||
<div className="flex flex-col gap-1">
|
||||
<P>
|
||||
<strong>einfach produktiv. – {seller.sellerName}</strong>
|
||||
</P>
|
||||
<P>
|
||||
<strong>
|
||||
{seller.sellerStreet}, {seller.sellerZip} {seller.sellerCity}
|
||||
</strong>
|
||||
</P>
|
||||
<P>
|
||||
<strong>
|
||||
E-Mail: <a href={`mailto:${seller.sellerEmail}`} className="hover:underline">{seller.sellerEmail}</a>
|
||||
</strong>
|
||||
</P>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+23
-5
@@ -8,8 +8,9 @@ import { TrustRow } from "../components/TrustRow";
|
||||
import { RichText, extractHeadings } from "../components/RichText";
|
||||
import { LiveRichText } from "../components/LiveRichText";
|
||||
import { SectionTOC, MobileSectionTOC } from "../components/SectionTOC";
|
||||
import { getLegalPage } from "../lib/payload";
|
||||
import { getLegalPage, getCompanySettings } from "../lib/payload";
|
||||
import { formatMonthYear } from "../lib/format";
|
||||
import { VertragspartnerBlock, vertragspartnerHeadings } from "./components/VertragspartnerBlock";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "AGB",
|
||||
@@ -19,8 +20,16 @@ export const metadata: Metadata = {
|
||||
|
||||
export default async function AgbPage() {
|
||||
const { isEnabled: isPreview } = await draftMode();
|
||||
const page = await getLegalPage("agb", { draft: isPreview });
|
||||
const headings = page ? extractHeadings(page.content) : [];
|
||||
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 (
|
||||
<>
|
||||
@@ -69,9 +78,18 @@ export default async function AgbPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full lg:flex-1 min-w-0">
|
||||
<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} />
|
||||
<>
|
||||
{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>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user