Adminbereich für VanVan: Produkte/Kategorien als bearbeitbare JSON-Dateien + Sveltia-CMS-Login unter /admin/

This commit is contained in:
qcigano
2026-08-02 13:36:04 +02:00
parent 2e340f7a8a
commit 81b1a50158
19 changed files with 677 additions and 292 deletions
+14 -87
View File
@@ -1,14 +1,10 @@
import type { Locale } from "../i18n/config";
// Hauptkategorien laut Pflichtenheft (Abschnitt 6 "Shop & Kategorien").
// Neue Kategorien/Unterkategorien einfach hier ergänzen — alle Shop-Routen lesen aus dieser Datei,
// nichts ist fest verdrahtet ("beliebig viele Unterkategorien ... müssen möglich sein").
// name/description sind je Sprache hinterlegt (DE/EN/CH/FR) für die Mehrsprachigkeit.
//
// Unterkategorien (seit 02.08.2026, auf VanVans Wunsch): bereits vollständig angelegt, auch
// ohne dass schon Produkte zugeordnet sind — "damit später Produkte direkt den entsprechenden
// Bereichen zugeordnet werden können" (siehe Dokument1.pdf). Zeigen bis dahin einen
// "noch keine Produkte"-Hinweis auf ihrer eigenen Seite.
// Kategoriedaten kommen seit 02.08.2026 aus src/content/categories/*.json — eine Datei pro
// Hauptkategorie, inkl. verschachtelter Unterkategorien. Im Admin-Bereich (/admin/, Sveltia
// CMS) kann VanVan Name/Beschreibung ändern und neue Unterkategorien ergänzen, ohne Code
// anzufassen. `order` bestimmt die Reihenfolge (Dateien in einem Ordner haben von sich aus
// keine garantierte Reihenfolge).
type LocalizedText = Record<Locale, string>;
@@ -19,90 +15,21 @@ export interface Subcategory {
export interface Category {
slug: string;
order: number;
name: LocalizedText;
description: LocalizedText;
icon: string; // dezentes Emoji als Platzhalter-Icon, bis es echte Icons/Fotos gibt
subcategories?: Subcategory[];
}
export const categories: Category[] = [
{
slug: "diy-plushies",
name: { de: "DIY Plushies", en: "DIY Plushies", ch: "DIY Plushies", fr: "Peluches DIY" },
description: {
de: "Handgenähte Kuscheltiere und Plüschfiguren jedes Stück ein Unikat.",
en: "Hand-sewn stuffed animals and plush figures every piece a one-of-a-kind.",
ch: "Vo Hang gnähti Kuscheltier und Plüschfigure jedes Sächeli es Unikat.",
fr: "Peluches et figurines cousues à la main chaque pièce est unique.",
},
icon: "🧸",
subcategories: [
{ slug: "kuh-frieda", name: { de: "Kuh „Frieda”", en: "Cow \"Frieda\"", ch: "Kuh „Frieda”", fr: "Vache « Frieda »" } },
{ slug: "hase-hasidog", name: { de: "Hase „HasiDog”", en: "Bunny \"HasiDog\"", ch: "Hase „HasiDog”", fr: "Lapin « HasiDog »" } },
{ slug: "wal-sam", name: { de: "Wal „Sam”", en: "Whale \"Sam\"", ch: "Wal „Sam”", fr: "Baleine « Sam »" } },
{ slug: "oktopus-siggi", name: { de: "Oktopus „Siggi”", en: "Octopus \"Siggi\"", ch: "Oktopus „Siggi”", fr: "Poulpe « Siggi »" } },
{ slug: "schildkroete-gaby", name: { de: "Schildkröte „Gaby”", en: "Turtle \"Gaby\"", ch: "Schildchröte „Gaby”", fr: "Tortue « Gaby »" } },
{ slug: "pinguin-pingi", name: { de: "Pinguin „Pingi”", en: "Penguin \"Pingi\"", ch: "Pinguin „Pingi”", fr: "Pingouin « Pingi »" } },
],
},
{
slug: "diy-haekelwerke",
name: { de: "DIY Häkelwerke", en: "DIY Crochet", ch: "DIY Häkelwerke", fr: "Crochet DIY" },
description: {
de: "Gehäkelte Deko, Accessoires und kleine Kunstwerke aus feiner Wolle.",
en: "Crocheted décor, accessories and small works of art made from fine yarn.",
ch: "Ghäkleti Deko, Accessoires und chlini Kunstwerch us feiner Wolle.",
fr: "Décorations, accessoires et petites œuvres crochetés en laine fine.",
},
icon: "🧶",
},
{
slug: "modeschmuck-accessoires",
name: { de: "DIY Modeschmuck & Accessoires", en: "DIY Jewelry & Accessories", ch: "DIY Modeschmuck & Accessoires", fr: "Bijoux & accessoires DIY" },
description: {
de: "Selbstgemachter Schmuck und Accessoires für den besonderen Auftritt.",
en: "Handmade jewelry and accessories for that special touch.",
ch: "Sälber gmachte Schmuck und Accessoires für dr bsundere Uftritt.",
fr: "Bijoux et accessoires faits main pour une touche unique.",
},
icon: "📿",
subcategories: [
{ slug: "glasperlenarmbaender", name: { de: "Glasperlenarmbänder", en: "Glass Bead Bracelets", ch: "Glasperle-Armbändel", fr: "Bracelets en perles de verre" } },
{ slug: "kunststoffperlenarmbaender", name: { de: "Kunststoffperlenarmbänder", en: "Plastic Bead Bracelets", ch: "Kunststoffperle-Armbändel", fr: "Bracelets en perles plastique" } },
{ slug: "edelstahlhalsketten", name: { de: "Edelstahlhalsketten", en: "Stainless Steel Necklaces", ch: "Edelstahl-Halschette", fr: "Colliers en acier inoxydable" } },
{ slug: "polyesterhalsketten", name: { de: "Polyesterhalsketten", en: "Polyester Necklaces", ch: "Polyester-Halschette", fr: "Colliers en polyester" } },
],
},
{
slug: "haekelzubehoer",
name: { de: "Häkelzubehör", en: "Crochet Supplies", ch: "Häkelzubehör", fr: "Fournitures de crochet" },
description: {
de: "Nadeln, Garne und alles, was dein nächstes Häkelprojekt braucht.",
en: "Hooks, yarn and everything your next crochet project needs.",
ch: "Nadle, Garn und alles, wo's für dis nächschte Häkelprojekt bruucht.",
fr: "Crochets, fils et tout ce qu'il faut pour votre prochain projet.",
},
icon: "🪡",
subcategories: [
{ slug: "maschenmarkierer", name: { de: "Maschenmarkierer", en: "Stitch Markers", ch: "Masche-Markierer", fr: "Marqueurs de mailles" } },
],
},
{
slug: "bastelzubehoer",
name: { de: "Bastelzubehör", en: "Craft Supplies", ch: "Bastelzubehör", fr: "Fournitures créatives" },
description: {
de: "Grundausstattung und kleine Helfer für kreative DIY-Projekte.",
en: "Essentials and handy little helpers for creative DIY projects.",
ch: "Grundusstattig und chlini Helfer für kreativi DIY-Projäkt.",
fr: "L'essentiel et de petits accessoires pour vos projets créatifs.",
},
icon: "✂️",
subcategories: [
{ slug: "holzknoepfe", name: { de: "Holzknöpfe", en: "Wooden Buttons", ch: "Holzchnöpf", fr: "Boutons en bois" } },
{ slug: "kunststoffknoepfe", name: { de: "Kunststoffknöpfe", en: "Plastic Buttons", ch: "Kunststoffchnöpf", fr: "Boutons en plastique" } },
],
},
];
const modules = import.meta.glob("/src/content/categories/*.json", { eager: true }) as Record<
string,
{ default: Category }
>;
export const categories: Category[] = Object.values(modules)
.map((m) => m.default)
.sort((a, b) => a.order - b.order);
export function getCategory(slug: string): Category | undefined {
return categories.find((c) => c.slug === slug);
+15 -205
View File
@@ -1,18 +1,11 @@
import type { Locale } from "../i18n/config";
// Platzhalter-Produktdaten für Phase 1 (rein clientseitige Demo-Daten).
// Struktur folgt bewusst den optionalen Feldern aus dem Pflichtenheft (Abschnitt 7
// "Produktverwaltung") — nicht gesetzte Felder werden auf den Seiten automatisch
// ausgeblendet ("nicht benötigte Felder müssen deaktivierbar sein").
//
// Mehrsprachigkeit: `name` und `beschreibung` sind je Sprache hinterlegt (DE/EN/CH/FR).
// Die technischen Detail-Felder (material, groesse, farben, ...) bleiben bewusst nur auf
// Deutsch — das sind ohnehin Platzhalterdaten, die in Phase 2 durch VanVans echte
// Produktangaben ersetzt werden. Die zugehörigen LABEL-Texte (z.B. "Material") kommen aus
// src/i18n/ui.ts und sind bereits übersetzt.
//
// TODO Phase 2: diese Datei durch echte Daten aus Cloudflare D1 + Worker-API ersetzen.
// TODO VanVan: echte Produktfotos, Texte und Preise liefern — alles hier ist Platzhalter.
// Produktdaten kommen seit 02.08.2026 aus src/content/products/*.json — eine Datei pro
// Produkt. Diese JSON-Dateien werden im Admin-Bereich (/admin/, Sveltia CMS) von VanVan
// bearbeitet: neues Foto hochladen, Text ändern, Preis anpassen, fertig — kein Code nötig.
// `import.meta.glob(..., { eager: true })` lädt sie zur Build-Zeit synchron ein, damit sich
// an der bestehenden API dieser Datei (products-Array + Helper-Funktionen) nichts ändert —
// alle Seiten, die von hier importieren, funktionieren unverändert weiter.
export type Badge = "neu" | "bestseller" | "sale" | "handgemacht";
@@ -34,200 +27,17 @@ export interface Product {
pflegehinweise?: string;
lieferzeit?: string;
badges: Badge[];
bilder?: string[]; // Pfade zu Produktfotos, von VanVan im Admin-Bereich hochgeladen
}
export const products: Product[] = [
{
slug: "wolke-plushie-lavendel",
name: {
de: "Wolke-Plushie „Lavendel”", en: "Cloud Plushie \"Lavender\"",
ch: "Wolke-Plushie „Lavendel”", fr: "Peluche nuage « Lavande »",
},
artikelnummer: "PLU-001",
kategorie: "diy-plushies",
preis: 28.5,
bestand: 6,
beschreibung: {
de: "Weiche, handgenähte Wolke zum Kuscheln aus kuscheligem Plüschstoff mit dezenter Lavendel-Stickerei.",
en: "A soft, hand-sewn cloud made for cuddling plush fabric with subtle lavender embroidery.",
ch: "Weichi, vo Hang gnähti Wolke zum Kuschle us kuschlige Plüschstoff mit dezenter Lavendel-Stickerei.",
fr: "Nuage doux cousu à la main, parfait à câliner tissu peluche avec une broderie lavande discrète.",
},
material: "Plüschstoff (Polyester), Füllwatte OEKO-TEX",
groesse: "ca. 24 × 16 cm",
farben: ["Lavendel", "Cremeweiß"],
lieferumfang: "1 Plushie",
pflegehinweise: "Handwäsche bei 30°C, nicht bügeln.",
lieferzeit: "24 Werktage",
badges: ["handgemacht", "bestseller"],
},
{
slug: "fuchs-plushie-mini",
name: { de: "Mini-Fuchs Plushie", en: "Mini Fox Plushie", ch: "Mini-Fuchs Plushie", fr: "Peluche mini renard" },
artikelnummer: "PLU-002",
kategorie: "diy-plushies",
preis: 19.9,
bestand: 0,
beschreibung: {
de: "Kleiner handgenähter Fuchs für die Tasche oder als Deko im Kinderzimmer.",
en: "A small hand-sewn fox to take along or as décor for a kid's room.",
ch: "Chline, vo Hang gnähte Fuchs für d'Täsche oder als Deko im Chinderzimmer.",
fr: "Petit renard cousu à la main, pour le sac ou pour décorer une chambre d'enfant.",
},
material: "Baumwollstoff, Füllwatte OEKO-TEX",
groesse: "ca. 14 cm",
lieferzeit: "24 Werktage",
badges: ["handgemacht"],
},
{
slug: "haekeldecke-boho",
name: {
de: "Häkeldecke „Boho Sonnenuntergang”", en: "Crochet Blanket \"Boho Sunset\"",
ch: "Häkeldecke „Boho Sonnenuntergang”", fr: "Plaid au crochet « Coucher de soleil bohème »",
},
artikelnummer: "HAE-010",
kategorie: "diy-haekelwerke",
preis: 89,
preisAlt: 109,
bestand: 3,
beschreibung: {
de: "Großformatige Häkeldecke in warmen Terracotta- und Lila-Tönen, komplett handgehäkelt.",
en: "A large crochet blanket in warm terracotta and purple tones, entirely hand-crocheted.",
ch: "Grossformatigi Häkeldecki i warme Terracotta- und Lila-Töne, komplett vo Hang ghäkelt.",
fr: "Grand plaid au crochet dans des tons chauds terracotta et violet, entièrement fait main.",
},
material: "100 % Baumwollgarn",
groesse: "ca. 130 × 160 cm",
farben: ["Terracotta", "Lila", "Sandbeige"],
pflegehinweise: "Handwäsche empfohlen, liegend trocknen.",
lieferzeit: "57 Werktage (Sonderanfertigung)",
badges: ["sale", "handgemacht"],
},
{
slug: "haekel-untersetzer-set",
name: { de: "Häkel-Untersetzer Set (4er)", en: "Crochet Coaster Set (4-pack)", ch: "Häkel-Untersetzer Set (4er)", fr: "Set de 4 sous-verres au crochet" },
artikelnummer: "HAE-004",
kategorie: "diy-haekelwerke",
preis: 16,
bestand: 14,
beschreibung: {
de: "Vier runde Untersetzer im Granny-Square-Stil, mixbar in vielen Farben.",
en: "Four round coasters in granny-square style, mix and match in many colors.",
ch: "Vier rundi Untersetzer im Granny-Square-Stil, mixbar i viel Farbe.",
fr: "Quatre sous-verres ronds façon granny square, à combiner dans de nombreuses couleurs.",
},
material: "Baumwollgarn",
lieferumfang: "4 Untersetzer",
lieferzeit: "24 Werktage",
badges: ["neu"],
},
{
slug: "perlen-armband-hellblau",
name: { de: "Perlenarmband „Himmelblau”", en: "Beaded Bracelet \"Sky Blue\"", ch: "Perlenarmband „Himmelblau”", fr: "Bracelet de perles « Bleu ciel »" },
artikelnummer: "SCH-021",
kategorie: "modeschmuck-accessoires",
preis: 14.5,
bestand: 9,
beschreibung: {
de: "Zartes, handgefädeltes Perlenarmband mit vergoldetem Verschluss.",
en: "A delicate, hand-strung beaded bracelet with a gold-plated clasp.",
ch: "Zarts, vo Hang gfädlets Perlearmband mit vergoldetem Verschluss.",
fr: "Bracelet de perles délicat, enfilé à la main, avec fermoir plaqué or.",
},
material: "Glasperlen, vergoldeter Edelstahl-Verschluss",
farben: ["Hellblau", "Silber"],
lieferzeit: "24 Werktage",
badges: ["handgemacht", "neu"],
},
{
slug: "makramee-ohrringe",
name: { de: "Makramee-Ohrringe „Terra”", en: "Macramé Earrings \"Terra\"", ch: "Makramee-Ohrringe „Terra”", fr: "Boucles d'oreilles macramé « Terra »" },
artikelnummer: "SCH-014",
kategorie: "modeschmuck-accessoires",
preis: 12,
bestand: 0,
beschreibung: {
de: "Leichte, geknüpfte Ohrringe aus Makramee-Garn mit Holzperle.",
en: "Lightweight knotted earrings made from macramé cord with a wooden bead.",
ch: "Lychti, gknüpfti Ohrringe us Makramee-Garn mit Holzperle.",
fr: "Boucles d'oreilles légères, nouées en fil macramé, avec perle en bois.",
},
material: "Makramee-Garn, Holzperle, Edelstahlhaken",
lieferzeit: "24 Werktage",
badges: ["handgemacht"],
},
{
slug: "haekelnadel-set-ergonomisch",
name: { de: "Ergonomisches Häkelnadel-Set (9-teilig)", en: "Ergonomic Crochet Hook Set (9-piece)", ch: "Ergonomisches Häkelnadel-Set (9-teilig)", fr: "Set de 9 crochets ergonomiques" },
artikelnummer: "ZUB-101",
kategorie: "haekelzubehoer",
preis: 22,
bestand: 21,
beschreibung: {
de: "Griffige, ergonomische Häkelnadeln in 9 gängigen Stärken, inkl. Aufbewahrungsrolle.",
en: "Comfortable, ergonomic crochet hooks in 9 common sizes, incl. a storage roll.",
ch: "Griffigi, ergonomischi Häkelnadle i 9 gängige Stärche, inkl. Ufbewahrigsrolle.",
fr: "Crochets ergonomiques et faciles à tenir en 9 tailles courantes, avec pochette de rangement.",
},
material: "Aluminium, Softgrip-Griff",
lieferumfang: "9 Nadeln + Stoffrolle",
lieferzeit: "24 Werktage",
badges: ["bestseller"],
},
{
slug: "baumwollgarn-bundle",
name: { de: "Baumwollgarn-Bundle „Pastell” (6 Knäuel)", en: "Cotton Yarn Bundle \"Pastel\" (6 skeins)", ch: "Baumwollgarn-Bundle „Pastell” (6 Knäuel)", fr: "Lot de fil coton « Pastel » (6 pelotes)" },
artikelnummer: "ZUB-205",
kategorie: "haekelzubehoer",
preis: 24.9,
bestand: 17,
beschreibung: {
de: "Sechs Knäuel weiches Baumwollgarn in aufeinander abgestimmten Pastelltönen.",
en: "Six skeins of soft cotton yarn in coordinated pastel shades.",
ch: "Sächs Chnöiel weichs Baumwollgarn i aufenand abgstimmte Pastelltöne.",
fr: "Six pelotes de fil coton doux dans des tons pastel assortis.",
},
material: "100 % Baumwolle",
farben: ["Pastellmix"],
lieferzeit: "24 Werktage",
badges: ["neu"],
},
{
slug: "bastel-starterset",
name: { de: "DIY Bastel-Starterset", en: "DIY Craft Starter Kit", ch: "DIY Bastel-Starterset", fr: "Kit créatif de démarrage DIY" },
artikelnummer: "BAS-050",
kategorie: "bastelzubehoer",
preis: 34,
preisAlt: 42,
bestand: 8,
beschreibung: {
de: "Alles für den Einstieg: Schere, Kleber, Knöpfe, Bänder und eine kleine Anleitung mit drei Projekten.",
en: "Everything to get started: scissors, glue, buttons, ribbon and a little guide with three projects.",
ch: "Alles für dr Iistig: Schere, Chläber, Chnöpf, Bändel und e chlini Aaleitig mit drei Projäkt.",
fr: "Tout pour débuter : ciseaux, colle, boutons, rubans et un petit guide avec trois projets.",
},
lieferumfang: "1 Set (siehe Beschreibung)",
lieferzeit: "24 Werktage",
badges: ["sale"],
},
{
slug: "stoffreste-bundle",
name: { de: "Stoffreste-Bundle „Bunte Mischung”", en: "Fabric Scraps Bundle \"Colorful Mix\"", ch: "Stoffreste-Bundle „Bunte Mischung”", fr: "Lot de chutes de tissu « Mélange coloré »" },
artikelnummer: "BAS-018",
kategorie: "bastelzubehoer",
preis: 9.9,
bestand: 25,
beschreibung: {
de: "Restestoffe in verschiedenen Mustern und Farben ideal für kleine Nähprojekte.",
en: "Leftover fabrics in various patterns and colors perfect for small sewing projects.",
ch: "Restestoff i verschiedene Muster und Farbe ideal für chlini Nöihprojäkt.",
fr: "Chutes de tissu aux motifs et couleurs variés idéales pour de petits projets de couture.",
},
material: "Baumwollmix",
lieferzeit: "24 Werktage",
badges: [],
},
];
const modules = import.meta.glob("/src/content/products/*.json", { eager: true }) as Record<
string,
{ default: Product }
>;
export const products: Product[] = Object.values(modules)
.map((m) => m.default)
.sort((a, b) => a.slug.localeCompare(b.slug));
export function getProduct(slug: string): Product | undefined {
return products.find((p) => p.slug === slug);