Add active-product-count-driven automation

- Products gain `active`/`spotlight*`/`updatedAt` on the base Product type
  (folded in from the now-removed separate SpotlightProduct type) so shop
  grid, spotlight, and related-products can each filter `.active` from the
  same already-fetched list — cart/checkout/order-confirmation/product-
  detail pages keep resolving any product regardless of active status.
- getSpotlightProduct() now derives from getProducts() instead of its own
  Payload query: with exactly 1 active product, that one IS the spotlight
  (overriding any `spotlight` flag elsewhere); otherwise same
  most-recently-updated tie-break as before, just computed client-side.
- ProductGrid drops the already-dead SHOP_GRID_EXCLUDE_IDS list in favor of
  the same `active` filter, with an empty-state message if 0 active.
- RelatedProducts gates on >=2 active products regardless of cart contents
  or how many display slots would otherwise resolve.
- Navbar's "Shop" link becomes an anchor to the homepage spotlight section
  (id="spotlight") instead of a real /shop navigation whenever exactly 1
  product is active — passed down from the now-async root layout, which
  fetches the catalog once for this decision.
This commit is contained in:
Marco
2026-07-21 20:39:22 +00:00
parent 37b710c933
commit 028a1fc4ec
6 changed files with 108 additions and 76 deletions
+10 -2
View File
@@ -3,6 +3,7 @@ import { Inter, Playfair_Display, Caveat, Lora } from "next/font/google";
import "./globals.css";
import { Navbar } from "./components/Navbar";
import { CartFlyProvider } from "./components/CartFly";
import { getProducts } from "./lib/payload";
const inter = Inter({
variable: "--font-inter",
@@ -45,11 +46,18 @@ export const metadata: Metadata = {
},
};
export default function RootLayout({
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"
@@ -57,7 +65,7 @@ export default function RootLayout({
>
<body className="min-h-full flex flex-col">
<CartFlyProvider>
<Navbar />
<Navbar singleActiveProduct={singleActiveProduct} />
{children}
</CartFlyProvider>
</body>