1706da8598
- Organization (site-wide), Product (/todo-cards), BlogPosting (every
/blog/[slug]) JSON-LD via new app/lib/structuredData.ts — no new
Payload fields needed, derived from existing data. Verified locally
by curling each page and checking the rendered script tag.
- Order confirmation email gains the same "please transfer to this
account, processed after payment received" notice the invoice PDF
already had for Vorkasse orders — OrderConfirmationData's new
isManualPayment flag is set explicitly by each caller (never derived
from paymentMethodTitle, which already broke once this session after
a payment-methods rename). CompanySettings gains bankName (existed on
the backend, was missing from the frontend's type/usage).
- Newsletter signup now detects an already-subscribed email
(verified empirically: Brevo's doubleOptinConfirmation endpoint gives
identical 201 responses for new vs. already-confirmed contacts) via a
GET /v3/contacts/{email} pre-check, and shows a distinct message
instead of silently resending the confirmation mail. Success message
text centralized in useNewsletterSignup.ts instead of duplicated
across 4 forms.
- Bumped @einfach-produktiv/invoicing to the version with the
unpaid-notice layout fix (full width, more top spacing — was
squeezed into the narrow paid-badge column).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
65 lines
2.1 KiB
TypeScript
65 lines
2.1 KiB
TypeScript
import type { Metadata } from "next";
|
||
import { draftMode } from "next/headers";
|
||
import { TodoKartenHero } from "./components/TodoKartenHero";
|
||
import { HowItWorks } from "./components/HowItWorks";
|
||
import { Focus } from "./components/Focus";
|
||
import { Pricing } from "./components/Pricing";
|
||
import { Footer } from "../components/Footer";
|
||
import { TestimonialsGrid } from "../components/TestimonialsGrid";
|
||
import { LiveTestimonialsGrid } from "../components/LiveTestimonialsGrid";
|
||
import { getTestimonials, getProductBySlug, getCompanySettings } from "../lib/payload";
|
||
import { buildProductSchema } from "../lib/structuredData";
|
||
|
||
const title = "ToDo-Karten – Kleine Karten. Große Wirkung.";
|
||
const description =
|
||
"Ein einfaches Werkzeug, das dir hilft, deinen Kopf frei zu bekommen und das Wesentliche zu sehen. 50 hochwertige ToDo-Karten für mehr Fokus im Alltag.";
|
||
|
||
export const metadata: Metadata = {
|
||
title,
|
||
description,
|
||
alternates: {
|
||
canonical: "/todo-cards",
|
||
},
|
||
openGraph: {
|
||
title,
|
||
description,
|
||
url: "/todo-cards",
|
||
images: ["/hero-todo-karten.png"],
|
||
},
|
||
twitter: {
|
||
title,
|
||
description,
|
||
images: ["/hero-todo-karten.png"],
|
||
},
|
||
};
|
||
|
||
export default async function TodoCardsPage() {
|
||
const { isEnabled: isPreview } = await draftMode();
|
||
const [testimonials, product, seller] = await Promise.all([
|
||
getTestimonials("todo-cards", { draft: isPreview }),
|
||
getProductBySlug("todo-karten"),
|
||
getCompanySettings(),
|
||
]);
|
||
const productSchema = product ? buildProductSchema(product, "https://einfach-produktiv.mk360.de/todo-cards", seller) : null;
|
||
|
||
return (
|
||
<>
|
||
{productSchema && (
|
||
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(productSchema) }} />
|
||
)}
|
||
<main className="flex flex-col flex-1">
|
||
<TodoKartenHero />
|
||
<HowItWorks />
|
||
<Focus />
|
||
{isPreview ? (
|
||
<LiveTestimonialsGrid testimonials={testimonials} />
|
||
) : (
|
||
<TestimonialsGrid testimonials={testimonials} />
|
||
)}
|
||
<Pricing />
|
||
</main>
|
||
<Footer />
|
||
</>
|
||
);
|
||
}
|