diff --git a/components/CookieBanner.vue b/components/CookieBanner.vue index 59ad859..21c1cf6 100644 --- a/components/CookieBanner.vue +++ b/components/CookieBanner.vue @@ -16,7 +16,7 @@ Datenschutzerklärung diff --git a/components/Header.vue b/components/Header.vue index 0d1f104..87d44e9 100644 --- a/components/Header.vue +++ b/components/Header.vue @@ -45,12 +45,6 @@ :path="`/notebooks/${item.slug}`" @click="trackEvent('header-item-clicked', { label: item.label })" /> - { - return ( - props.product?.pattern && [ - randomTailwindColor(props.product.pattern.id, "group-hover:shadow", 200, "/60") - ] - ); + return props.product?.pattern + ? [randomTailwindColor(props.product.pattern.id, "group-hover:shadow", 200, "/60")] + : []; }); const hasProductOptions = computed(() => { diff --git a/components/SelectionBox.vue b/components/SelectionBox.vue index 23d8282..bd71bae 100644 --- a/components/SelectionBox.vue +++ b/components/SelectionBox.vue @@ -1,12 +1,14 @@ diff --git a/composables/useProductContent.ts b/composables/useProductContent.ts index 08eed13..f0a10a3 100644 --- a/composables/useProductContent.ts +++ b/composables/useProductContent.ts @@ -1,7 +1,7 @@ // Product content keyed by cover type // This content is displayed on product detail pages as storytelling modules -export type CoverType = "Hardcover" | "Softcover" | "Heft" | "Spiralbindung"; +export type CoverType = "Hardcover" | "Softcover" | "Heft" | "Spiralbindung" | "Promo"; export interface FeatureModule { eyebrow?: string; @@ -199,6 +199,44 @@ export const FEATURE_MODULES: Record = { imageRight: true, }, ], + + Promo: [ + { + eyebrow: "12 Wochen · 3 Monate", + headline: "Struktur für deinen Alltag", + subtitle: "Planung, Intention & Reflexion", + body: `Dieses Journaling Booklet im Format A5 sorgt für mehr Produktivität im Alltag. + Es beinhaltet Monats-, Wochen- und Tagesplanungen sowie inspirierenden Zitaten + für insgesamt 12 Wochen bzw. 3 Monate. Jeder Tag bietet Platz für eine + Tagesintention, den täglichen Aufgaben, dem Notieren von Mahlzeiten und der + Fitnessroutine. Darüber hinaus bietet es die Möglichkeit der eigene + Tagesreflexion. Als tägliche Begleiter soll es helfen, deine Zeit effektiv zu + managen, um mit mehr Klarheit und Struktur deine Ziele anzugehen.`, + imageRight: true, + }, + { + eyebrow: "Gestaltet von mk rietzl", + headline: "VIVUS 89 Recyclingpapier", + subtitle: "Matt, 120g/qm, fliederfarbener Umschlag", + body: `Das Journaling Booklet wurde konzipiert und gestaltet von Michèle Rietzl + (mk rietzl). Es ist auf VIVUS 89 Recyclingpapier gedruckt. Die matte, + ungestrichene Oberfläche mit feiner Textur verhindert Durchschlagen – selbst bei + Füllfederhaltern und Aquarellfarben. Mit 120g/qm und 1,2-fachem Volumen fühlt + sich jede Seite substanziell an, ohne starr zu wirken. Der fliederfarbene + Umschlag sorgt für schlichte Farbakzente.`, + imageRight: false, + }, + { + eyebrow: "Handgefertigt in Stuttgart", + headline: "Fadenbindung mit offenem Buchrücken", + subtitle: "Vollständiges Aufklappen zum Schreiben", + body: `Bei der Bindung handelt es sich um eine klassische Fadenbindung mit offenem + Buchrücken. Dies ermöglicht ein vollständiges Aufklappen, was sich ideal zum + Schreiben eignet. Die Booklets werden mit größter Sorgfalt in Stuttgart + produziert. Jedes Exemplar ist handgefertigt.`, + imageRight: true, + }, + ], }; // ============================================================================= @@ -244,6 +282,15 @@ export const TECHNICAL_SPECS: Record> = { Zertifizierung: "FSC® C018175, Blauer Engel, EU Ecolabel", Herstellung: "Stuttgart, Deutschland", }, + Promo: { + Format: "150 × 210 mm (A5)", + Umfang: "12 Wochen / 3 Monate", + Layout: "Vorgedruckt (Tages-, Wochen- & Monatsplanung)", + Papier: "VIVUS 89, 120g/qm, 1,2-faches Volumen, ungestrichen matt", + Einband: "Fliederfarbener Softcover", + Bindung: "Fadenbindung mit offenem Buchrücken", + Herstellung: "Handgefertigt in Stuttgart", + }, }; // ============================================================================= @@ -284,6 +331,8 @@ export function getCoverType(coverName?: string): CoverType { if (name.includes("hardcover")) return "Hardcover"; if (name.includes("softcover")) return "Softcover"; if (name.includes("spiral") || name.includes("wire")) return "Spiralbindung"; + // Standalone promo bucket (cover named "Promo"). + if (name.includes("promo")) return "Promo"; return "Hardcover"; // fallback } @@ -314,10 +363,10 @@ export function useProductContent( derivedSpecs["Format"] = prod.cover.copyText.format; } - // Seitenanzahl from pages - if (prod.pages?.name) { + // Seitenanzahl from pages (skip for Promo/standalone — page count not relevant) + if (prod.pages?.name && coverType.value !== "Promo") { derivedSpecs["Seitenanzahl"] = prod.pages.name; - } else if (prod.pages?.count) { + } else if (prod.pages?.count && coverType.value !== "Promo") { const sheets = Math.floor(prod.pages.count / 2); derivedSpecs["Seitenanzahl"] = `${prod.pages.count} Seiten (${sheets} Blatt)`; } diff --git a/nuxt.config.ts b/nuxt.config.ts index e5bd0f0..d225b10 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -45,7 +45,10 @@ export default defineNuxtConfig({ routeRules: { // Cart & Checkout: Client-only (no SSR) "/cart": { ssr: false }, - "/checkout/**": { ssr: false } + "/checkout/**": { ssr: false }, + // Local dev: proxy CMS media. In prod nginx routes /uploads → cms; + // without it the browser would hit the Nuxt origin and 404. + "/uploads/**": { proxy: "http://cms:5555/uploads/**" } // All other pages use default SSR }, diff --git a/pages/details/[slug].vue b/pages/details/[slug].vue index f8b247d..3dddf6e 100644 --- a/pages/details/[slug].vue +++ b/pages/details/[slug].vue @@ -77,48 +77,40 @@ {{ product?.cover?.copyText?.paper }}

-
+
- -
- -
+ +
+

Seiten

+

-
- -
+
+

Layout

+
@@ -126,15 +118,10 @@

- -
- -
+ +
+

Einband

+
-
+
+ + +
@@ -186,7 +184,7 @@
-
+
@@ -421,6 +419,18 @@ const productVariantsPatterns = computed(() => { })); }); +// Fixed/standalone products (no selectable pages & ruling, e.g. Journaling Booklet) +// surface their key specs as pre-selected locked chips in the buy box. +const buyBoxFacts = computed(() => { + if (productVariantsPages.value.length || productVariantsRuling.value.length) return []; + const s = (technicalSpecs.value ?? {}) as Record; + const facts: { label: string; value: string }[] = []; + if (s.Umfang) facts.push({ label: "Umfang", value: s.Umfang }); + if (s.Layout) facts.push({ label: "Layout", value: s.Layout }); + if (s.Einband) facts.push({ label: "Einband", value: s.Bindung ? `${s.Einband} · ${s.Bindung}` : s.Einband }); + return facts; +}); + // Testimonials data const testimonials: Testimonial[] = [ { diff --git a/pages/index.vue b/pages/index.vue index 9b1b923..1c47016 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -49,23 +49,32 @@
- -
-
-

Premium Notizbücher für kreative Köpfe

-

- Erfahre wie unsere handgefertigten Notizbücher aus recyceltem Papier hergestellt werden -

- - Jetzt entdecken + +
+
+
+

Neu im Sortiment

+ {{ promo.name }} +

+ + {{ promo.name }} entdecken + +

+ +
+