Rabatt-System, größerer Mengen-Stepper, Zahlungsart zuerst, echte HasiDog-Inhalte

- Neues Rabatt-System: Prozent-/Betrag-Rabatt mit optionalem Ablaufdatum,
  Mengenrabatt-Staffel pro Produkt, sowie site-weite Gutscheincodes.
  Wird live im Warenkorb/Checkout berechnet (src/data/rabatt.ts,
  src/data/gutscheine.ts, cart.ts) und ist im Adminbereich direkt unter dem
  Preis bearbeitbar (config.yml: "Rabatte" + neue Collection
  "Gutscheincodes"). Effektiver Preis + Rabatt-Badge auf Produktkarten und
  Produktseite sichtbar.
- Mengen-Stepper auf der Produktseite vergrößert (bereits vorbereitet,
  jetzt mit Build/Test verifiziert).
- Zahlungsart im Checkout auf Platz 1, mit markenfarbigen, fertig
  gestalteten Buttons (PayPal/Klarna/Banküberweisung).
- Unterkategorie-Seiten zeigen jetzt VanVans eigene Produktbeschreibung
  und das echte Fotos des Produkts statt Platzhaltertext, mit kleinem
  Link zur HasiDog-Universum-Seite statt großem Button.

Verifiziert per Puppeteer-Funktionstest gegen den echten Production-Build
(Rabatt-Berechnung, Mengenrabatt, Gutschein-Einlösung, Checkout-Summary,
keine Konsolenfehler).
This commit is contained in:
qcigano
2026-08-02 18:59:11 +02:00
parent 0f93ab73c3
commit 6f850181f1
25 changed files with 1098 additions and 194 deletions
+28 -12
View File
@@ -21,7 +21,7 @@ export const ui = {
common: {
addToCart: "In den Warenkorb", soldOut: "Ausverkauft", addedToCart: "Zum Warenkorb hinzugefügt ✓",
browseShop: "Jetzt stöbern", viewAll: "Alle ansehen →", viewAllSale: "Alle Angebote →",
toShop: "Zum Shop →", moreAboutMe: "Mehr über mich →",
toShop: "Zum Shop →", moreAboutMe: "Mehr über mich →", discoverNow: "Jetzt entdecken",
vatNote: "Gemäß §19 UStG wird keine Umsatzsteuer berechnet und ausgewiesen.",
allPricesPlusShipping: "Alle Preise zzgl. Versand.", plusShipping: "zzgl. Versand",
quantity: "Anzahl", photoSoon: "Produktfoto folgt", portraitSoon: "Porträtfoto von VanVan folgt",
@@ -149,13 +149,17 @@ export const ui = {
subtotal: "Zwischensumme", shipping: "Versand", shippingCalculated: "wird im Checkout berechnet",
total: "Gesamt", remaining: (v: string) => `Noch ${v} bis zum kostenlosen Versand.`, freeShipping: "🩵 Du bekommst kostenlosen Versand!",
toCheckout: "Weiter zum Checkout", remove: "Entfernen", perItem: "/ Stück",
discount: "Rabatt", mengenrabatt: (p: string) => `Mengenrabatt -${p}%`,
mengenrabattTier: (ab: string, p: string) => `ab ${ab} Stück -${p}%`,
couponLabel: "🎟️ Gutscheincode", couponPlaceholder: "Code eingeben", couponApply: "Einlösen", couponRemove: "Entfernen",
couponInvalid: "Code ungültig oder abgelaufen.", couponApplied: (code: string) => `Gutschein „${code}" eingelöst`,
},
checkout: {
eyebrow: "Checkout", title: "Bestellung abschließen",
todoNote: "Phase 1 Demo-Checkout. Es findet noch keine echte Zahlung statt. Die vollständige Anbindung an PayPal, Klarna und Banküberweisung sowie die Bestellverwaltung folgen in Phase 2 (Cloudflare Worker + D1, siehe Tech-Stack-Entscheidung im Projekt-Vault).",
step1: "1. Kontakt & Lieferadresse", email: "E-Mail", firstName: "Vorname", lastName: "Nachname",
step1: "2. Kontakt & Lieferadresse", email: "E-Mail", firstName: "Vorname", lastName: "Nachname",
street: "Straße & Hausnummer", zip: "PLZ", city: "Ort", country: "Land",
step2: "2. Zahlungsart",
step2: "1. Zahlungsart",
step3: "3. Bestellübersicht", agbPrefix: "Ich habe die", agbLink: "AGB", agbSuffix: "gelesen und akzeptiere sie.",
revocationPrefix: "Ich habe die", revocationLink: "Widerrufsbelehrung", revocationAnd: "und",
privacyLink: "Datenschutzerklärung", revocationSuffix: "zur Kenntnis genommen.",
@@ -190,7 +194,7 @@ export const ui = {
common: {
addToCart: "Add to cart", soldOut: "Sold out", addedToCart: "Added to cart ✓",
browseShop: "Browse now", viewAll: "View all →", viewAllSale: "View all offers →",
toShop: "To the shop →", moreAboutMe: "More about me →",
toShop: "To the shop →", moreAboutMe: "More about me →", discoverNow: "Discover now",
vatNote: "Under §19 UStG (German small-business rule) no VAT is charged or shown.",
allPricesPlusShipping: "All prices plus shipping.", plusShipping: "plus shipping",
quantity: "Quantity", photoSoon: "Product photo coming soon", portraitSoon: "VanVan's portrait photo coming soon",
@@ -318,13 +322,17 @@ export const ui = {
subtotal: "Subtotal", shipping: "Shipping", shippingCalculated: "calculated at checkout",
total: "Total", remaining: (v: string) => `${v} more for free shipping.`, freeShipping: "🩵 You qualify for free shipping!",
toCheckout: "Continue to checkout", remove: "Remove", perItem: "/ item",
discount: "Discount", mengenrabatt: (p: string) => `Bulk discount -${p}%`,
mengenrabattTier: (ab: string, p: string) => `from ${ab} pcs -${p}%`,
couponLabel: "🎟️ Coupon code", couponPlaceholder: "Enter code", couponApply: "Apply", couponRemove: "Remove",
couponInvalid: "Code invalid or expired.", couponApplied: (code: string) => `Coupon "${code}" applied`,
},
checkout: {
eyebrow: "Checkout", title: "Complete your order",
todoNote: "Phase 1 demo checkout. No real payment is processed yet. Full integration with PayPal, Klarna and bank transfer, plus order management, follow in Phase 2 (Cloudflare Worker + D1, see the tech-stack decision in the project vault).",
step1: "1. Contact & shipping address", email: "Email", firstName: "First name", lastName: "Last name",
step1: "2. Contact & shipping address", email: "Email", firstName: "First name", lastName: "Last name",
street: "Street & house number", zip: "ZIP code", city: "City", country: "Country",
step2: "2. Payment method",
step2: "1. Payment method",
step3: "3. Order summary", agbPrefix: "I have read the", agbLink: "terms & conditions", agbSuffix: "and accept them.",
revocationPrefix: "I have taken note of the", revocationLink: "withdrawal notice", revocationAnd: "and",
privacyLink: "privacy policy", revocationSuffix: ".",
@@ -359,7 +367,7 @@ export const ui = {
common: {
addToCart: "In Warenchorb", soldOut: "Usverkauft", addedToCart: "Zum Warenchorb dezuegfüegt ✓",
browseShop: "Jetzt use luege", viewAll: "Alles aluege →", viewAllSale: "Alli Aktione →",
toShop: "Zum Shop →", moreAboutMe: "Meh über mich →",
toShop: "Zum Shop →", moreAboutMe: "Meh über mich →", discoverNow: "Jetzt aluege",
vatNote: "Gemäss §19 UStG (dütsches Rächt) wird kei Umsatzsteuer berechnet und usgwiese.",
allPricesPlusShipping: "Alli Pryse zzgl. Versand.", plusShipping: "zzgl. Versand",
quantity: "Aazahl", photoSoon: "Produktfoto chunnt bald", portraitSoon: "Porträtfoto vo VanVan chunnt bald",
@@ -487,13 +495,17 @@ export const ui = {
subtotal: "Zwüschesumme", shipping: "Versand", shippingCalculated: "wird im Checkout berechnet",
total: "Total", remaining: (v: string) => `No ${v} bis zum Gratisversand.`, freeShipping: "🩵 Du übercho't Gratisversand!",
toCheckout: "Wyter zum Checkout", remove: "Ewägmache", perItem: "/ Stuck",
discount: "Rabatt", mengenrabatt: (p: string) => `Mengerabatt -${p}%`,
mengenrabattTier: (ab: string, p: string) => `ab ${ab} Stuck -${p}%`,
couponLabel: "🎟️ Gutschy-Code", couponPlaceholder: "Code igäh", couponApply: "Ilöse", couponRemove: "Ewägmache",
couponInvalid: "Code ungültig oder abgloffe.", couponApplied: (code: string) => `Gutschy „${code}" iglöst`,
},
checkout: {
eyebrow: "Checkout", title: "Bschtellig abschliesse",
todoNote: "Phase 1 Demo-Checkout. Es git no kei echti Zahlig. D'vollständigi Aabindig a PayPal, Klarna und Banküberwysig sowie d'Bstellverwaltig chöme i Phase 2.",
step1: "1. Kontakt & Lieferadrässe", email: "E-Mail", firstName: "Vorname", lastName: "Nachname",
step1: "2. Kontakt & Lieferadrässe", email: "E-Mail", firstName: "Vorname", lastName: "Nachname",
street: "Strasse & Huusnummere", zip: "PLZ", city: "Ort", country: "Land",
step2: "2. Zahligsart",
step2: "1. Zahligsart",
step3: "3. Bschtellübersicht", agbPrefix: "Ich ha d'", agbLink: "AGB", agbSuffix: "gläse und akzeptiere si.",
revocationPrefix: "Ich ha d'", revocationLink: "Widerrufsbelehrig", revocationAnd: "und d'",
privacyLink: "Datenschutzerklärig", revocationSuffix: "zur Kenntnis gnoh.",
@@ -528,7 +540,7 @@ export const ui = {
common: {
addToCart: "Ajouter au panier", soldOut: "Épuisé", addedToCart: "Ajouté au panier ✓",
browseShop: "Découvrir la boutique", viewAll: "Tout voir →", viewAllSale: "Toutes les offres →",
toShop: "Vers la boutique →", moreAboutMe: "En savoir plus sur moi →",
toShop: "Vers la boutique →", moreAboutMe: "En savoir plus sur moi →", discoverNow: "Découvrir maintenant",
vatNote: "Conformément à l'§19 UStG (droit allemand), aucune TVA n'est calculée ni indiquée.",
allPricesPlusShipping: "Tous les prix hors frais de port.", plusShipping: "hors frais de port",
quantity: "Quantité", photoSoon: "Photo du produit à venir", portraitSoon: "Photo de VanVan à venir",
@@ -656,13 +668,17 @@ export const ui = {
subtotal: "Sous-total", shipping: "Livraison", shippingCalculated: "calculée au moment du paiement",
total: "Total", remaining: (v: string) => `Encore ${v} avant la livraison gratuite.`, freeShipping: "🩵 Vous bénéficiez de la livraison gratuite !",
toCheckout: "Passer au paiement", remove: "Retirer", perItem: "/ pièce",
discount: "Remise", mengenrabatt: (p: string) => `Remise de quantité -${p}%`,
mengenrabattTier: (ab: string, p: string) => `dès ${ab} pièces -${p}%`,
couponLabel: "🎟️ Code promo", couponPlaceholder: "Entrer le code", couponApply: "Valider", couponRemove: "Retirer",
couponInvalid: "Code invalide ou expiré.", couponApplied: (code: string) => `Code promo « ${code} » appliqué`,
},
checkout: {
eyebrow: "Paiement", title: "Finaliser la commande",
todoNote: "Phase 1 paiement de démonstration. Aucun paiement réel n'est encore traité. L'intégration complète avec PayPal, Klarna et le virement bancaire, ainsi que la gestion des commandes, suivront en phase 2.",
step1: "1. Contact & adresse de livraison", email: "E-mail", firstName: "Prénom", lastName: "Nom",
step1: "2. Contact & adresse de livraison", email: "E-mail", firstName: "Prénom", lastName: "Nom",
street: "Rue & numéro", zip: "Code postal", city: "Ville", country: "Pays",
step2: "2. Moyen de paiement",
step2: "1. Moyen de paiement",
step3: "3. Récapitulatif de commande", agbPrefix: "J'ai lu les", agbLink: "CGV", agbSuffix: "et je les accepte.",
revocationPrefix: "J'ai pris connaissance de la", revocationLink: "notice de rétractation", revocationAnd: "et de la",
privacyLink: "politique de confidentialité", revocationSuffix: ".",