Abosystem mit dauerhaften Rabatten und Teddy-Prämien
Drei Mitgliedschaftsstufen (Klein 4,99€/5%, Mittel 9,99€/10%, Groß 19,99€/20%) mit automatischem Bestellrabatt und Teddy-Prämien nach Meilensteinen (12-Monats- Rhythmus bzw. 6+12 bei Groß). Preise/Rabatte und alle Admin-Regeln (Kombinier- barkeit mit anderen Rabatten, Fortsetzung bei Wiederanmeldung, Monate über Stufen zusammenzählen, kostenloser Versand bei Prämie) sind über Decap CMS einstellbar (src/content/abo-einstellungen.json). Neuer "Mein Abo"-Bereich im Kundenkonto (6. Nav-Kachel) mit Plan-Vergleich, Live-Status (Laufzeit, nächste Zahlung, Rabatt, Fortschritt bis zur nächsten Prämie), Einlösen-Buttons für freigeschaltete Teddys, Kündigen/Wechseln sowie einer übersetzten Benachrichtigungsliste. Dazu ein extra hervorgehobener "Mein Abo verwalten"-Button neben Abmelden in der Kopfkarte. Warenkorb/Checkout rechnen den Abo-Rabatt korrekt in die Summe ein und stellen eingelöste Teddys als 0€-Gratisposition dar. Alles in 4 Sprachen (DE/EN/CH/FR). Unterwegs zwei echte Bugs gefunden und behoben: addMonateISO() vermischte lokale Zeit mit toISOString() (UTC) und verlor dadurch bei jeder Monats- verlängerung reproduzierbar einen Tag; die Checkout-Positionsliste zeigte für Gratis-Prämien fälschlich den vollen Preis statt 0€. Wie beim Treuebonus gilt: Speicherung aktuell im localStorage des Geräts (Phase 1) statt einer echten geräteübergreifenden Datenbank — folgt mit der Zahlungsanbindung in Phase 2. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
0cb7d3ca65
commit
208d995941
@@ -173,20 +173,19 @@ const t = useTranslations(lang);
|
||||
</section>
|
||||
</Layout>
|
||||
|
||||
<script define:vars={{ freeLabel: t.checkout.free, totalLabel: t.checkout.total, shippingLabel: t.cart.shipping, emptyCartAlert: t.checkout.emptyCartAlert, thankYouPath: "/ch/checkout/danke/", checkoutLang: lang, discountLabel: t.cart.discount, couponInvalid: t.cart.couponInvalid, couponAppliedTemplate: t.cart.couponApplied("__C__"), couponRemoveLabel: t.cart.couponRemove, klarnaConnectLabel: t.checkout.klarnaConnect, klarnaConnectingLabel: t.checkout.klarnaConnecting, klarnaConnectedLabel: t.checkout.klarnaConnected, bankHolderLabel: t.checkout.bankHolder, bankIbanLabel: t.checkout.bankIban, bankBicLabel: t.checkout.bankBic, bankBankNameLabel: t.checkout.bankBankName, bankPlaceholderLabel: t.checkout.bankPlaceholder, partnerDiscountLabel: t.cart.partnerDiscount, partnerCodeInvalid: t.cart.partnerCodeInvalid, partnerCodeAppliedTemplate: t.cart.partnerCodeApplied("__C__"), partnerCodeRemoveLabel: t.cart.partnerCodeRemove, loyaltyDiscountLabel: t.cart.loyaltyDiscount }}>
|
||||
<script define:vars={{ freeLabel: t.checkout.free, totalLabel: t.checkout.total, shippingLabel: t.cart.shipping, emptyCartAlert: t.checkout.emptyCartAlert, thankYouPath: "/ch/checkout/danke/", checkoutLang: lang, discountLabel: t.cart.discount, couponInvalid: t.cart.couponInvalid, couponAppliedTemplate: t.cart.couponApplied("__C__"), couponRemoveLabel: t.cart.couponRemove, klarnaConnectLabel: t.checkout.klarnaConnect, klarnaConnectingLabel: t.checkout.klarnaConnecting, klarnaConnectedLabel: t.checkout.klarnaConnected, bankHolderLabel: t.checkout.bankHolder, bankIbanLabel: t.checkout.bankIban, bankBicLabel: t.checkout.bankBic, bankBankNameLabel: t.checkout.bankBankName, bankPlaceholderLabel: t.checkout.bankPlaceholder, partnerDiscountLabel: t.cart.partnerDiscount, partnerCodeInvalid: t.cart.partnerCodeInvalid, partnerCodeAppliedTemplate: t.cart.partnerCodeApplied("__C__"), partnerCodeRemoveLabel: t.cart.partnerCodeRemove, loyaltyDiscountLabel: t.cart.loyaltyDiscount, aboDiscountLabel: t.cart.aboDiscount, gratisPraemieLabel: t.cart.gratisPraemie }}>
|
||||
// WICHTIG: define:vars-Skripte laufen als IIFE, keine "import"-Anweisungen möglich.
|
||||
window.__checkoutVars = { freeLabel, totalLabel, shippingLabel, emptyCartAlert, thankYouPath, checkoutLang, discountLabel, couponInvalid, couponAppliedTemplate, couponRemoveLabel, klarnaConnectLabel, klarnaConnectingLabel, klarnaConnectedLabel, bankHolderLabel, bankIbanLabel, bankBicLabel, bankBankNameLabel, bankPlaceholderLabel, partnerDiscountLabel, partnerCodeInvalid, partnerCodeAppliedTemplate, partnerCodeRemoveLabel, loyaltyDiscountLabel };
|
||||
window.__checkoutVars = { freeLabel, totalLabel, shippingLabel, emptyCartAlert, thankYouPath, checkoutLang, discountLabel, couponInvalid, couponAppliedTemplate, couponRemoveLabel, klarnaConnectLabel, klarnaConnectingLabel, klarnaConnectedLabel, bankHolderLabel, bankIbanLabel, bankBicLabel, bankBankNameLabel, bankPlaceholderLabel, partnerDiscountLabel, partnerCodeInvalid, partnerCodeAppliedTemplate, partnerCodeRemoveLabel, loyaltyDiscountLabel, aboDiscountLabel, gratisPraemieLabel };
|
||||
</script>
|
||||
<script type="module">
|
||||
import { getCart, cartTotal, appliedCoupon, couponDiscount, setCouponCode, clearCoupon, appliedPartnerCode, partnerCodeDiscount, setPartnerCode, clearPartnerCode, totalDiscount, treuebonusDiscount, istAusgewaehlt } from "../../../scripts/cart";
|
||||
import { getCart, cartTotal, appliedCoupon, couponDiscount, setCouponCode, clearCoupon, appliedPartnerCode, partnerCodeDiscount, setPartnerCode, clearPartnerCode, totalDiscount, treuebonusDiscount, aboDiscount, istAusgewaehlt, zeilenpreisFuer } from "../../../scripts/cart";
|
||||
import { formatPrice } from "../../../i18n/format";
|
||||
import { products } from "../../../data/products";
|
||||
import { berechneVersandkosten } from "../../../data/versand";
|
||||
import { effektiverZeilenpreis } from "../../../data/rabatt";
|
||||
import { bankverbindung, bankverbindungVollstaendig } from "../../../data/bankverbindung";
|
||||
import { registriereAbgeschlosseneBestellung, treuebonusEinloesen } from "../../../scripts/account";
|
||||
|
||||
const { freeLabel, totalLabel, shippingLabel, emptyCartAlert, thankYouPath, checkoutLang, discountLabel, couponInvalid, couponAppliedTemplate, couponRemoveLabel, klarnaConnectLabel, klarnaConnectingLabel, klarnaConnectedLabel, bankHolderLabel, bankIbanLabel, bankBicLabel, bankBankNameLabel, bankPlaceholderLabel, partnerDiscountLabel, partnerCodeInvalid, partnerCodeAppliedTemplate, partnerCodeRemoveLabel, loyaltyDiscountLabel } = window.__checkoutVars;
|
||||
const { freeLabel, totalLabel, shippingLabel, emptyCartAlert, thankYouPath, checkoutLang, discountLabel, couponInvalid, couponAppliedTemplate, couponRemoveLabel, klarnaConnectLabel, klarnaConnectingLabel, klarnaConnectedLabel, bankHolderLabel, bankIbanLabel, bankBicLabel, bankBankNameLabel, bankPlaceholderLabel, partnerDiscountLabel, partnerCodeInvalid, partnerCodeAppliedTemplate, partnerCodeRemoveLabel, loyaltyDiscountLabel, aboDiscountLabel, gratisPraemieLabel } = window.__checkoutVars;
|
||||
|
||||
const summary = document.getElementById("checkout-summary");
|
||||
const landSelect = document.getElementById("land");
|
||||
@@ -204,18 +203,19 @@ import { registriereAbgeschlosseneBestellung, treuebonusEinloesen } from "../../
|
||||
const partnerCode = appliedPartnerCode();
|
||||
const partnerDiscount = partnerCodeDiscount(subtotal);
|
||||
const loyaltyDiscount = treuebonusDiscount();
|
||||
const aboDiscountBetrag = aboDiscount(subtotal);
|
||||
const total = Math.max(0, subtotal - totalDiscount(subtotal)) + shipping;
|
||||
currentTotal = total;
|
||||
|
||||
summary.innerHTML = `
|
||||
${cart.map((i) => {
|
||||
const produkt = products.find((p) => p.slug === i.slug);
|
||||
const zeilenpreis = produkt ? effektiverZeilenpreis(produkt, i.menge) : i.menge * i.preis;
|
||||
return `<div class="row"><span>${i.menge}× ${i.name}</span><span>${formatPrice(zeilenpreis, checkoutLang)}</span></div>`;
|
||||
const zeilenpreis = zeilenpreisFuer(i);
|
||||
return `<div class="row"><span>${i.menge}× ${i.name}${i.gratis ? ` <span class="small">(${gratisPraemieLabel})</span>` : ""}</span><span>${formatPrice(zeilenpreis, checkoutLang)}</span></div>`;
|
||||
}).join("")}
|
||||
${coupon && discount > 0 ? `<div class="row"><span>${discountLabel}</span><span>-${formatPrice(discount, checkoutLang)}</span></div>` : ""}
|
||||
${partnerCode && partnerDiscount > 0 ? `<div class="row"><span>${partnerDiscountLabel}</span><span>-${formatPrice(partnerDiscount, checkoutLang)}</span></div>` : ""}
|
||||
${loyaltyDiscount > 0 ? `<div class="row"><span>${loyaltyDiscountLabel}</span><span>-${formatPrice(loyaltyDiscount, checkoutLang)}</span></div>` : ""}
|
||||
${aboDiscountBetrag > 0 ? `<div class="row"><span>${aboDiscountLabel}</span><span>-${formatPrice(aboDiscountBetrag, checkoutLang)}</span></div>` : ""}
|
||||
<div class="row"><span>${shippingLabel}</span><span>${shipping === 0 ? freeLabel : formatPrice(shipping, checkoutLang)}</span></div>
|
||||
<div class="row total"><span>${totalLabel}</span><span>${formatPrice(total, checkoutLang)}</span></div>
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user