7f37f111e8
Checkout now persists orders server-side (Payload orders collection, re-priced from live product data, discount codes redeemed exactly once) instead of writing a client-only sessionStorage snapshot. Buying requires an account (registration inline in checkout, no separate step) — accounts get order history with delivery status, profile/address editing, password change, and a cart that syncs across devices while logged in. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
77 lines
2.1 KiB
TypeScript
77 lines
2.1 KiB
TypeScript
import type { Metadata } from "next";
|
||
import { Inter, Playfair_Display, Caveat, Lora } from "next/font/google";
|
||
import "./globals.css";
|
||
import { Navbar } from "./components/Navbar";
|
||
import { CartFlyProvider } from "./components/CartFly";
|
||
import { CartSync } from "./components/CartSync";
|
||
import { getProducts } from "./lib/payload";
|
||
|
||
const inter = Inter({
|
||
variable: "--font-inter",
|
||
subsets: ["latin"],
|
||
weight: ["400", "500", "600", "700"],
|
||
});
|
||
|
||
const playfair = Playfair_Display({
|
||
variable: "--font-playfair",
|
||
subsets: ["latin"],
|
||
weight: ["600", "700", "800"],
|
||
});
|
||
|
||
const caveat = Caveat({
|
||
variable: "--font-caveat",
|
||
subsets: ["latin"],
|
||
weight: ["700"],
|
||
});
|
||
|
||
const lora = Lora({
|
||
variable: "--font-lora",
|
||
subsets: ["latin"],
|
||
weight: ["400", "600"],
|
||
});
|
||
|
||
export const metadata: Metadata = {
|
||
metadataBase: new URL("https://einfach-produktiv.mk360.de"),
|
||
title: {
|
||
default: "einfach produktiv. – Werkzeuge und Impulse für einen leichteren Alltag",
|
||
template: "%s | einfach produktiv.",
|
||
},
|
||
description: "Werkzeuge, Impulse und ein Blog für mehr Klarheit im Alltag.",
|
||
openGraph: {
|
||
siteName: "einfach produktiv.",
|
||
locale: "de_DE",
|
||
type: "website",
|
||
},
|
||
twitter: {
|
||
card: "summary_large_image",
|
||
},
|
||
};
|
||
|
||
export default async function RootLayout({
|
||
children,
|
||
}: Readonly<{
|
||
children: React.ReactNode;
|
||
}>) {
|
||
// Same 60s-ISR-cached call every other page already makes — reused here
|
||
// just to know whether Navbar's "Shop" link should behave as an anchor
|
||
// to the homepage spotlight instead of a real /shop navigation (see
|
||
// Navbar.tsx/ProductSpotlight.tsx).
|
||
const products = await getProducts();
|
||
const singleActiveProduct = products.filter((p) => p.active).length === 1;
|
||
|
||
return (
|
||
<html
|
||
lang="de"
|
||
className={`${inter.variable} ${playfair.variable} ${caveat.variable} ${lora.variable} h-full antialiased scroll-smooth`}
|
||
>
|
||
<body className="min-h-full flex flex-col">
|
||
<CartFlyProvider>
|
||
<CartSync />
|
||
<Navbar singleActiveProduct={singleActiveProduct} />
|
||
{children}
|
||
</CartFlyProvider>
|
||
</body>
|
||
</html>
|
||
);
|
||
}
|