Some checks failed
Build and publish / build (push) Failing after 19s
Source moved verbatim from mp/shop/ on 2026-04-29; mp was the first concrete adapter consuming the libreshop toolkit. Builds and publishes git.librete.ch/libreshop/shop on every main / v* push via the standard .gitea/workflows/build.yml shared across libreshop components.
370 lines
13 KiB
TypeScript
370 lines
13 KiB
TypeScript
// 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 interface FeatureModule {
|
||
eyebrow?: string;
|
||
headline: string;
|
||
subtitle?: string;
|
||
body: string;
|
||
image?: string;
|
||
imageRight?: boolean;
|
||
}
|
||
|
||
export interface UseCase {
|
||
icon: "pen" | "palette" | "clipboard" | "briefcase";
|
||
title: string;
|
||
description: string;
|
||
}
|
||
|
||
// =============================================================================
|
||
// FEATURE MODULES - Storytelling sections per cover type
|
||
// =============================================================================
|
||
|
||
export const FEATURE_MODULES: Record<CoverType, FeatureModule[]> = {
|
||
Hardcover: [
|
||
{
|
||
eyebrow: "Handarbeit",
|
||
headline: "Klassische Fadenheftung",
|
||
subtitle: "Strapazierfähig bei intensivem Gebrauch",
|
||
body: `Jedes Heft wird mit Singer-Stich-Heftung von Hand gebunden.
|
||
Das Ergebnis: Ein Notizbuch, das sich vollständig flach öffnen
|
||
lässt und auch nach Jahren intensiver Nutzung nicht auseinanderfällt.
|
||
Der rote Vorsatzbogen setzt einen dezenten Farbakzent –
|
||
Deine erste Begegnung beim Öffnen.`,
|
||
image: "/images/features/hardcover/binding-closeup.jpg",
|
||
imageRight: false,
|
||
},
|
||
{
|
||
eyebrow: "100% Recycling",
|
||
headline: "VIVUS 89 Papier",
|
||
subtitle: "Außergewöhnliche Schreibqualität",
|
||
body: `VIVUS 89 ist nicht irgendein Recyclingpapier.
|
||
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.`,
|
||
image: "/images/features/hardcover/paper-texture.jpg",
|
||
imageRight: true,
|
||
},
|
||
{
|
||
headline: "160 Seiten für Deine Ideen",
|
||
subtitle: "Raum für 3-6 Monate intensive Arbeit",
|
||
body: `160 Seiten bedeuten genug Platz für ein abgeschlossenes Projekt,
|
||
eine komplette Reise, oder ein Quartal Deines Bullet Journals.
|
||
Blanko-Seiten geben Dir absolute Freiheit: Skizzieren, Schreiben,
|
||
Collagieren – ohne Raster, das Deine Kreativität einschränkt.`,
|
||
image: "/images/features/hardcover/lifestyle-desk.jpg",
|
||
imageRight: false,
|
||
},
|
||
{
|
||
headline: "Kein Heft gleicht dem anderen",
|
||
subtitle: "13 einzigartige Mustervarianten",
|
||
body: `Jeder Einband wird individuell mit variierenden geometrischen
|
||
Mustern bedruckt. Die Kombination aus mattem Schwarz (300g/qm Karton)
|
||
und den Mustern macht Dein Heft unverwechselbar.`,
|
||
image: "/images/features/hardcover/cover-pattern.jpg",
|
||
imageRight: true,
|
||
},
|
||
{
|
||
eyebrow: "Made in Stuttgart",
|
||
headline: "Transparente Lieferkette",
|
||
subtitle: "Messbare Nachhaltigkeit",
|
||
body: `<strong>100% Recyclingpapier</strong> (FSC® C018175)<br>
|
||
<strong>CO₂-neutral</strong> produziert<br>
|
||
<strong>Blauer Engel + EU Ecolabel</strong> zertifiziert<br>
|
||
<strong>Hergestellt in Stuttgart</strong>, Deutschland<br><br>
|
||
Keine langen Transportwege, keine Ausbeutung, kein Greenwashing.
|
||
Nur ehrliches Handwerk mit messbaren Umweltstandards.`,
|
||
image: "/images/production/04.png",
|
||
imageRight: false,
|
||
},
|
||
],
|
||
|
||
Softcover: [
|
||
{
|
||
eyebrow: "Leicht & Flexibel",
|
||
headline: "Der tägliche Begleiter",
|
||
subtitle: "Passt in jede Tasche",
|
||
body: `Das Softcover ist Dein unkomplizierter Alltagsbegleiter.
|
||
Leicht, flexibel und robust – perfekt für unterwegs.
|
||
Die weiche Hülle schmiegt sich an und übersteht jeden Rucksack.`,
|
||
image: "/images/features/softcover/flexible-cover.jpg",
|
||
imageRight: false,
|
||
},
|
||
{
|
||
eyebrow: "100% Recycling",
|
||
headline: "VIVUS 89 Papier",
|
||
subtitle: "Dieselbe Qualität, leichteres Format",
|
||
body: `Auch im Softcover kommt unser bewährtes VIVUS 89 Recyclingpapier
|
||
zum Einsatz. 120g/qm für optimale Schreibqualität ohne Durchschlagen.
|
||
Perfekt für Füllfederhalter, Fineliner und Aquarellstifte.`,
|
||
image: "/images/features/softcover/paper-writing.jpg",
|
||
imageRight: true,
|
||
},
|
||
{
|
||
headline: "Praktische Steppstich-Bindung",
|
||
subtitle: "Liegt flach, bleibt offen",
|
||
body: `Die Steppstich-Bindung ermöglicht ein vollständiges Aufklappen.
|
||
Ideal zum Schreiben, Zeichnen und für alle, die beide Seiten
|
||
gleichzeitig nutzen möchten.`,
|
||
image: "/images/features/softcover/binding-detail.jpg",
|
||
imageRight: false,
|
||
},
|
||
{
|
||
eyebrow: "Made in Stuttgart",
|
||
headline: "Nachhaltig produziert",
|
||
subtitle: "Lokale Fertigung, globale Standards",
|
||
body: `<strong>FSC® zertifiziert</strong><br>
|
||
<strong>Blauer Engel</strong> Umweltzeichen<br>
|
||
<strong>CO₂-neutral</strong> hergestellt<br><br>
|
||
Kurze Wege, faire Produktion, messbare Nachhaltigkeit.`,
|
||
image: "/images/features/softcover/workshop.png",
|
||
imageRight: true,
|
||
},
|
||
],
|
||
|
||
Heft: [
|
||
{
|
||
eyebrow: "Kompakt & Praktisch",
|
||
headline: "Das klassische Notizheft",
|
||
subtitle: "Für schnelle Notizen und Ideen",
|
||
body: `Manchmal braucht man kein dickes Notizbuch – sondern ein
|
||
handliches Heft für den Moment. Perfekt für Meeting-Notizen,
|
||
Einkaufslisten oder spontane Skizzen.`,
|
||
image: "/images/features/heft/compact-size.jpg",
|
||
imageRight: false,
|
||
},
|
||
{
|
||
eyebrow: "100% Recycling",
|
||
headline: "Qualität im Kleinformat",
|
||
subtitle: "VIVUS 89 auch im Heft",
|
||
body: `Unser Recyclingpapier macht auch im kleinen Format keine
|
||
Kompromisse. Die gleiche Schreibqualität, die Du von unseren
|
||
größeren Notizbüchern kennst.`,
|
||
image: "/images/features/heft/paper-quality.jpg",
|
||
imageRight: true,
|
||
},
|
||
{
|
||
headline: "Ruckzuck-Heftung",
|
||
subtitle: "Einfach, aber solide",
|
||
body: `Die klassische Rückstich-Heftung hält Dein Heft zusammen
|
||
und ermöglicht ein flaches Aufklappen. Bewährt seit Generationen,
|
||
nachhaltig für die Zukunft.`,
|
||
image: "/images/features/heft/binding.jpg",
|
||
imageRight: false,
|
||
},
|
||
],
|
||
|
||
Spiralbindung: [
|
||
{
|
||
eyebrow: "360° Flexibilität",
|
||
headline: "Wire-O-Bindung",
|
||
subtitle: "Komplett umklappbar",
|
||
body: `Die Spiralbindung lässt sich vollständig umklappen –
|
||
ideal für beengte Arbeitsflächen. Schreibe auf einer Seite,
|
||
während die andere flach auf dem Tisch liegt.`,
|
||
image: "/images/features/spiral/360-flip.jpg",
|
||
imageRight: false,
|
||
},
|
||
{
|
||
eyebrow: "100% Recycling",
|
||
headline: "VIVUS 89 Papier",
|
||
subtitle: "Premium-Qualität, flexibles Format",
|
||
body: `Unser bewährtes Recyclingpapier in der praktischen
|
||
Spiralbindung. 120g/qm verhindern Durchschlagen –
|
||
auch bei intensiver Nutzung mit verschiedenen Stiften.`,
|
||
image: "/images/features/spiral/paper-texture.jpg",
|
||
imageRight: true,
|
||
},
|
||
{
|
||
headline: "Seiten heraustrennbar",
|
||
subtitle: "Perforation für sauberes Abtrennen",
|
||
body: `Jede Seite lässt sich sauber heraustrennen – perfekt,
|
||
wenn Du Notizen weitergeben oder Skizzen verschenken möchtest.
|
||
Die Mikroperforation sorgt für glatte Kanten.`,
|
||
image: "/images/features/spiral/tear-out.jpg",
|
||
imageRight: false,
|
||
},
|
||
{
|
||
eyebrow: "Made in Stuttgart",
|
||
headline: "Nachhaltig & Praktisch",
|
||
subtitle: "Das Beste aus beiden Welten",
|
||
body: `<strong>Recycling-Drahtbindung</strong><br>
|
||
<strong>FSC® zertifiziertes Papier</strong><br>
|
||
<strong>CO₂-neutral</strong> produziert<br><br>
|
||
Funktionalität trifft Nachhaltigkeit.`,
|
||
image: "/images/features/spiral/workshop.jpg",
|
||
imageRight: true,
|
||
},
|
||
],
|
||
};
|
||
|
||
// =============================================================================
|
||
// TECHNICAL SPECS - Collapsible details per cover type
|
||
// =============================================================================
|
||
|
||
export const TECHNICAL_SPECS: Record<CoverType, Record<string, string>> = {
|
||
Hardcover: {
|
||
Format: "150 × 210 mm (A5)",
|
||
Seitenanzahl: "160 Seiten (80 Blatt)",
|
||
Papier: "VIVUS 89, 120g/qm, 100% Recycling",
|
||
Einband: "300g/qm Recyclingkarton",
|
||
Bindung: "Klassische Fadenheftung (Singer-Stich)",
|
||
Vorsatzpapier: "Rot durchgefärbt",
|
||
Zertifizierung: "FSC® C018175, Blauer Engel, EU Ecolabel",
|
||
Herstellung: "Stuttgart, Deutschland",
|
||
},
|
||
Softcover: {
|
||
Format: "150 × 210 mm (A5)",
|
||
Seitenanzahl: "96 Seiten (48 Blatt)",
|
||
Papier: "VIVUS 89, 120g/qm, 100% Recycling",
|
||
Einband: "250g/qm Recyclingkarton, flexibel",
|
||
Bindung: "Steppstich-Heftung",
|
||
Zertifizierung: "FSC® C018175, Blauer Engel, EU Ecolabel",
|
||
Herstellung: "Stuttgart, Deutschland",
|
||
},
|
||
Heft: {
|
||
Format: "148 × 210 mm (A5)",
|
||
Seitenanzahl: "20, 40 oder 60 Seiten",
|
||
Papier: "VIVUS 89, 120g/qm, 100% Recycling",
|
||
Einband: "200g/qm Recyclingkarton",
|
||
Bindung: "Rückstich-Heftung",
|
||
Zertifizierung: "FSC® C018175, Blauer Engel",
|
||
Herstellung: "Stuttgart, Deutschland",
|
||
},
|
||
Spiralbindung: {
|
||
Format: "150 × 210 mm (A5)",
|
||
Seitenanzahl: "120 Seiten (60 Blatt)",
|
||
Papier: "VIVUS 89, 120g/qm, 100% Recycling",
|
||
Einband: "300g/qm Recyclingkarton",
|
||
Bindung: "Wire-O-Bindung (Doppeldraht)",
|
||
Perforation: "Mikroperforation zum Heraustrennen",
|
||
Zertifizierung: "FSC® C018175, Blauer Engel, EU Ecolabel",
|
||
Herstellung: "Stuttgart, Deutschland",
|
||
},
|
||
};
|
||
|
||
// =============================================================================
|
||
// USE CASES - Same for all products
|
||
// =============================================================================
|
||
|
||
export const USE_CASES: UseCase[] = [
|
||
{
|
||
icon: "pen",
|
||
title: "Schreibprojekte",
|
||
description: "Romane, Tagebuch, Morning Pages",
|
||
},
|
||
{
|
||
icon: "palette",
|
||
title: "Mixed-Media",
|
||
description: "Aquarell, Collage, Skizzen",
|
||
},
|
||
{
|
||
icon: "clipboard",
|
||
title: "Sketchbook",
|
||
description: "Layouts ohne Raster",
|
||
},
|
||
{
|
||
icon: "briefcase",
|
||
title: "Arbeit & Studium",
|
||
description: "Meetings, Forschung, Konzepte",
|
||
},
|
||
];
|
||
|
||
// =============================================================================
|
||
// HELPER: Get cover type from product.cover.name
|
||
// =============================================================================
|
||
|
||
export function getCoverType(coverName?: string): CoverType {
|
||
if (!coverName) return "Hardcover";
|
||
const name = coverName.toLowerCase();
|
||
if (name.includes("heft")) return "Heft";
|
||
if (name.includes("hardcover")) return "Hardcover";
|
||
if (name.includes("softcover")) return "Softcover";
|
||
if (name.includes("spiral") || name.includes("wire")) return "Spiralbindung";
|
||
return "Hardcover"; // fallback
|
||
}
|
||
|
||
// =============================================================================
|
||
// COMPOSABLE
|
||
// =============================================================================
|
||
|
||
import type { Product } from "~/types";
|
||
|
||
export function useProductContent(
|
||
coverName: Ref<string | undefined> | ComputedRef<string | undefined>,
|
||
product?: Ref<Product | null> | ComputedRef<Product | null>
|
||
) {
|
||
const coverType = computed(() => getCoverType(coverName.value));
|
||
const featureModules = computed(() => FEATURE_MODULES[coverType.value] ?? []);
|
||
|
||
// Derive technical specs from product data when available
|
||
const technicalSpecs = computed(() => {
|
||
const baseSpecs = TECHNICAL_SPECS[coverType.value] ?? {};
|
||
const prod = product?.value;
|
||
|
||
if (!prod) return baseSpecs;
|
||
|
||
const derivedSpecs: Record<string, string> = {};
|
||
|
||
// Format from copyText
|
||
if (prod.cover?.copyText?.format) {
|
||
derivedSpecs["Format"] = prod.cover.copyText.format;
|
||
}
|
||
|
||
// Seitenanzahl from pages
|
||
if (prod.pages?.name) {
|
||
derivedSpecs["Seitenanzahl"] = prod.pages.name;
|
||
} else if (prod.pages?.count) {
|
||
const sheets = Math.floor(prod.pages.count / 2);
|
||
derivedSpecs["Seitenanzahl"] = `${prod.pages.count} Seiten (${sheets} Blatt)`;
|
||
}
|
||
|
||
// Parse paper string: "VIVUS 89: 100% Recyclingpapier, ... Inhalt: 120g/qm, Einband: 300g/qm. Zertifizierung: ..."
|
||
if (prod.cover?.copyText?.paper) {
|
||
const paperText = prod.cover.copyText.paper;
|
||
|
||
// Extract paper name and description (before "Inhalt:")
|
||
const inhaltMatch = paperText.match(/^(.+?)(?:\s*Inhalt:|$)/);
|
||
if (inhaltMatch) {
|
||
derivedSpecs["Papier"] = inhaltMatch[1].trim().replace(/,\s*$/, "");
|
||
}
|
||
|
||
// Extract Inhalt (paper weight)
|
||
const inhaltWeightMatch = paperText.match(/Inhalt:\s*([^,]+)/);
|
||
if (inhaltWeightMatch) {
|
||
derivedSpecs["Papiergewicht"] = inhaltWeightMatch[1].trim();
|
||
}
|
||
|
||
// Extract Einband (cover weight)
|
||
const einbandMatch = paperText.match(/Einband:\s*([^.]+)/);
|
||
if (einbandMatch) {
|
||
derivedSpecs["Einband"] = einbandMatch[1].trim();
|
||
}
|
||
|
||
// Extract Zertifizierung
|
||
const zertMatch = paperText.match(/Zertifizierung:\s*(.+)$/);
|
||
if (zertMatch) {
|
||
derivedSpecs["Zertifizierung"] = zertMatch[1].trim();
|
||
}
|
||
}
|
||
|
||
// Bindung from cover binding
|
||
if (prod.cover?.binding) {
|
||
derivedSpecs["Bindung"] = prod.cover.binding;
|
||
}
|
||
|
||
// Merge: product data overrides base specs
|
||
return { ...baseSpecs, ...derivedSpecs };
|
||
});
|
||
|
||
return {
|
||
coverType,
|
||
featureModules,
|
||
technicalSpecs,
|
||
useCases: USE_CASES,
|
||
};
|
||
}
|