Files
einfach-produktiv/app/tasse-die-pause/page.tsx
T
Marco 14d824491f Wire up real Live Preview for block-driven PDPs
Products.ts's admin.livePreview (added earlier this session) only made
the admin UI show a preview iframe — the actual page had no mechanism
to receive postMessage updates and re-render with unsaved draft data,
unlike Pages/Posts which already have this (LivePageContent.tsx/
LivePostContent.tsx). Edits in the backend were invisible in the
preview until an actual save (reported 2026-08-30).

New LiveProductContent.tsx mirrors LivePageContent.tsx's pattern
exactly: useLivePreview<PayloadProduct> + mapPayloadProduct, rendering
via ProductBlocks.tsx's now-exported renderProductBlock (sync) instead
of the full async ProductBlocks wrapper. testimonialsRef/crossSell
skipped in the live subset (need an async fetch a client component
can't perform inline) — same "editable subset only" scope Pages/Posts
already accept. shipping/tax/Kleinunternehmer context is fetched once
via the newly-exported getProductBlockContext() and passed in rather
than re-fetched per keystroke.

/der-eine and /tasse-die-pause now check draftMode() and swap in
LiveProductContent instead of the normal async ProductBlocks when
Payload's Live Preview iframe has it enabled.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Eg6h91yngXmSnM51wxXM8
2026-08-30 00:09:07 +00:00

53 lines
2.2 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 { notFound } from "next/navigation";
import { draftMode } from "next/headers";
import { ProductBlocks, getProductBlockContext } from "../components/ProductBlocks";
import { LiveProductContent } from "../components/LiveProductContent";
import { Footer } from "../components/Footer";
import { getProductBySlug, getCompanySettings } from "../lib/payload";
import { buildProductSchema } from "../lib/structuredData";
// "Die Pause." finally has real copy and a name (2026-08-29) — first PDP
// migrated off its own hand-coded Hero/Pricing onto the block-driven
// system (Products.layout/ProductBlocks.tsx), now that both exist. Was a
// provisional scaffold before (naming/design undecided, parked
// 2026-08-24); Hero.tsx/Pricing.tsx in ./components are dead code now,
// kept only until a next cleanup pass removes them.
export async function generateMetadata(): Promise<Metadata> {
const product = await getProductBySlug("tasse-die-pause");
const title = product ? `${product.name} einfach produktiv.` : "Tasse einfach produktiv.";
const description = product?.descriptionText || undefined;
return {
title,
description,
alternates: { canonical: "/tasse-die-pause" },
openGraph: { title, description, url: "/tasse-die-pause" },
twitter: { title, description },
};
}
export default async function TasseDiePausePage() {
const { isEnabled: isPreview } = await draftMode();
const [product, seller] = await Promise.all([
getProductBySlug("tasse-die-pause"),
getCompanySettings(),
]);
if (!product) notFound();
const productSchema = buildProductSchema(product, "https://einfach-produktiv.mk360.de/tasse-die-pause", seller);
const ctx = isPreview ? await getProductBlockContext(product) : null;
return (
<>
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(productSchema) }} />
<main className="flex flex-col flex-1">
{ctx ? (
<LiveProductContent initialProduct={product} shipping={ctx.shipping} taxRate={ctx.taxRate} kleinunternehmer={ctx.kleinunternehmer} />
) : (
<ProductBlocks product={product} />
)}
</main>
<Footer />
</>
);
}