Teddy-Praemien: zeigt jetzt WELCHE Teddys schon erhalten wurden, nicht nur wie viele

Statt "Bereits erhalten: 1x kleiner Teddy, 1x grosser Teddy" steht im Abo-Bereich jetzt eine
Liste mit dem tatsaechlichen Teddy-Namen, dem Einloesedatum und einem Link zum Produkt —
damit Kundinnen sehen, welchen Teddy sie schon besitzen, und keinen doppelt waehlen.

Dafuer haelt das Konto beim Einloesen fest, WELCHER Teddy vergeben wurde (neues Feld
abo.erhalteneTeddys mit Slug, Name und Datum). Bewusst als Verlauf gespeichert statt aus der
aktuellen Abo-Einstellung abgeleitet: VanVan kann die hinterlegten Teddy-Produkte jederzeit im
Adminbereich austauschen — eine nachtraeglich berechnete Liste wuerde dann einen Teddy
anzeigen, den die Kundin nie bekommen hat. Die Anzeige nimmt den aktuellen, uebersetzten
Produktnamen und faellt auf den gespeicherten Namen zurueck, falls das Produkt spaeter
umbenannt oder entfernt wird.

Nebenbei behoben: Beim Einloesen wanderte der Teddy in den Warenkorb, BEVOR geprueft wurde, ob
ueberhaupt eine Praemie offen ist. Bei einem zweiten Klick landete er dadurch erneut gratis im
Warenkorb, ohne im Konto gezaehlt zu werden. Jetzt wird zuerst geprueft.
Ausserdem sichert getAccount() nun auch die Listenfelder gegen kaputte Speicherwerte ab.

Getestet (Browser): Leerzustand, Einloesen beider Arten, Speicherung im Konto, zweiter Klick
ohne offene Praemie, Altkonto ohne Namensliste (ehrlicher Ersatztext) und entferntes Produkt
(gespeicherter Name greift). Beschriftungen in allen 4 Sprachen geprueft.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
qcigano
2026-08-04 10:27:14 +02:00
co-authored by Claude Opus 5
parent 578da49fd1
commit 915b71e43d
8 changed files with 359 additions and 55 deletions
+65 -9
View File
@@ -560,9 +560,12 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
</div>
</div>
<div class="abo-erhalten-chip">
<span aria-hidden="true">🧸</span>
<span id="abo-praemien-erhalten"></span>
{/* Zeigt nicht nur WIE VIELE Teddys schon eingeloest wurden, sondern WELCHE genau —
mit Name und Datum. So sieht die Kundin auf einen Blick, welchen Teddy sie schon
besitzt, und waehlt keinen doppelt. Wird per JS aus abo.erhalteneTeddys befuellt. */}
<div class="abo-erhalten-box" id="abo-erhalten-box">
<p class="abo-erhalten-titel"><span aria-hidden="true">🧸</span> <span id="abo-erhalten-titel-text"></span></p>
<ul class="abo-erhalten-liste" id="abo-erhalten-liste"></ul>
</div>
<p id="abo-gekuendigt-hinweis" class="small" style="display:none;"></p>
@@ -607,7 +610,7 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
</section>
</Layout>
<script define:vars={{ loginPath: "/ch/konto/", fallbackName: "Kundin", greetingTemplate: t.accountDash.greeting("{name}"), reviewedBadgeText: t.accountDash.reviewedBadge , invoiceLang: lang, invoiceLabels: { title: t.accountDash.invoiceTitle, numberLabel: t.accountDash.invoiceNumberLabel, dateLabel: t.accountDash.invoiceDateLabel, sellerLabel: t.accountDash.invoiceSellerLabel, billToLabel: t.accountDash.invoiceBillToLabel, itemLabel: t.accountDash.invoiceItemLabel, qtyLabel: t.accountDash.invoiceQtyLabel, unitPriceLabel: t.accountDash.invoiceUnitPriceLabel, sumLabel: t.accountDash.invoiceSumLabel, totalLabel: t.accountDash.orderTotal, vatNote: t.common.vatNote }, loyaltyProgressTemplate: t.accountDash.loyaltyProgressTemplate, loyaltyRemainingOne: t.accountDash.loyaltyRemainingOne, loyaltyRemainingOther: t.accountDash.loyaltyRemainingOther, loyaltyUnlockedTitle: t.accountDash.loyaltyUnlockedTitle, loyaltyUnlockedText: t.accountDash.loyaltyUnlockedText, loyaltyStatRedeemedNever: t.accountDash.loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix: t.accountDash.loyaltyStatRedeemedSuffix, loyaltyLastRedeemed: t.accountDash.loyaltyLastRedeemed, aboLang: lang, aboLabels: { nameKlein: t.accountDash.aboNameKlein, nameMittel: t.accountDash.aboNameMittel, nameGross: t.accountDash.aboNameGross, preisSuffix: t.accountDash.aboPreisSuffix, monateSuffix: t.accountDash.aboMonateSuffix, fortschrittKleinTemplate: t.accountDash.aboFortschrittKleinTemplate, fortschrittGrossTemplate: t.accountDash.aboFortschrittGrossTemplate, praemienErhaltenTemplate: t.accountDash.aboPraemienErhaltenTemplate, aktivBadge: t.accountDash.aboAktivesLabel, nichtAktivBadge: t.accountDash.aboNichtAktivBadge, gekuendigtHinweisTemplate: t.accountDash.aboGekuendigtHinweisTemplate, kuendigenConfirm: t.accountDash.aboKuendigenConfirm, abschliessenBtn: t.accountDash.aboAbschliessenBtn, wechselnBtn: t.accountDash.aboWechselnBtn, nichtBuchbar: t.accountDash.aboNichtBuchbar, keineBenachrichtigungen: t.accountDash.aboKeineBenachrichtigungen, notifKeyLabels: { abo_abgeschlossen: t.accountDash.notifAboAbgeschlossen, abo_gewechselt: t.accountDash.notifAboGewechselt, abo_zahlung_erfolgreich: t.accountDash.notifAboZahlungErfolgreich, abo_teddy_klein_frei: t.accountDash.notifAboTeddyKleinFrei, abo_teddy_gross_frei: t.accountDash.notifAboTeddyGrossFrei, abo_bald_praemie: t.accountDash.notifAboBaldPraemie, abo_gekuendigt: t.accountDash.notifAboGekuendigt, abo_teddy_klein_eingeloest: t.accountDash.notifAboTeddyKleinEingeloest, abo_teddy_gross_eingeloest: t.accountDash.notifAboTeddyGrossEingeloest } }, deleteAccountConfirm: t.accountDash.deleteAccountConfirm, deleteAccountError: t.accountDash.deleteAccountError }}>
<script define:vars={{ loginPath: "/ch/konto/", fallbackName: "Kundin", greetingTemplate: t.accountDash.greeting("{name}"), reviewedBadgeText: t.accountDash.reviewedBadge , invoiceLang: lang, invoiceLabels: { title: t.accountDash.invoiceTitle, numberLabel: t.accountDash.invoiceNumberLabel, dateLabel: t.accountDash.invoiceDateLabel, sellerLabel: t.accountDash.invoiceSellerLabel, billToLabel: t.accountDash.invoiceBillToLabel, itemLabel: t.accountDash.invoiceItemLabel, qtyLabel: t.accountDash.invoiceQtyLabel, unitPriceLabel: t.accountDash.invoiceUnitPriceLabel, sumLabel: t.accountDash.invoiceSumLabel, totalLabel: t.accountDash.orderTotal, vatNote: t.common.vatNote }, loyaltyProgressTemplate: t.accountDash.loyaltyProgressTemplate, loyaltyRemainingOne: t.accountDash.loyaltyRemainingOne, loyaltyRemainingOther: t.accountDash.loyaltyRemainingOther, loyaltyUnlockedTitle: t.accountDash.loyaltyUnlockedTitle, loyaltyUnlockedText: t.accountDash.loyaltyUnlockedText, loyaltyStatRedeemedNever: t.accountDash.loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix: t.accountDash.loyaltyStatRedeemedSuffix, loyaltyLastRedeemed: t.accountDash.loyaltyLastRedeemed, aboLang: lang, aboLabels: { nameKlein: t.accountDash.aboNameKlein, nameMittel: t.accountDash.aboNameMittel, nameGross: t.accountDash.aboNameGross, preisSuffix: t.accountDash.aboPreisSuffix, monateSuffix: t.accountDash.aboMonateSuffix, fortschrittKleinTemplate: t.accountDash.aboFortschrittKleinTemplate, fortschrittGrossTemplate: t.accountDash.aboFortschrittGrossTemplate, praemienErhaltenTitel: t.accountDash.aboPraemienErhaltenTitel, praemienKeine: t.accountDash.aboPraemienKeine, praemienAmTemplate: t.accountDash.aboPraemienAmTemplate, praemienAnsehen: t.accountDash.aboPraemienAnsehen, praemienUnbekannt: t.accountDash.aboPraemienUnbekannt, teddyArtKlein: t.accountDash.aboTeddyArtKlein, teddyArtGross: t.accountDash.aboTeddyArtGross, aktivBadge: t.accountDash.aboAktivesLabel, nichtAktivBadge: t.accountDash.aboNichtAktivBadge, gekuendigtHinweisTemplate: t.accountDash.aboGekuendigtHinweisTemplate, kuendigenConfirm: t.accountDash.aboKuendigenConfirm, abschliessenBtn: t.accountDash.aboAbschliessenBtn, wechselnBtn: t.accountDash.aboWechselnBtn, nichtBuchbar: t.accountDash.aboNichtBuchbar, keineBenachrichtigungen: t.accountDash.aboKeineBenachrichtigungen, notifKeyLabels: { abo_abgeschlossen: t.accountDash.notifAboAbgeschlossen, abo_gewechselt: t.accountDash.notifAboGewechselt, abo_zahlung_erfolgreich: t.accountDash.notifAboZahlungErfolgreich, abo_teddy_klein_frei: t.accountDash.notifAboTeddyKleinFrei, abo_teddy_gross_frei: t.accountDash.notifAboTeddyGrossFrei, abo_bald_praemie: t.accountDash.notifAboBaldPraemie, abo_gekuendigt: t.accountDash.notifAboGekuendigt, abo_teddy_klein_eingeloest: t.accountDash.notifAboTeddyKleinEingeloest, abo_teddy_gross_eingeloest: t.accountDash.notifAboTeddyGrossEingeloest } }, deleteAccountConfirm: t.accountDash.deleteAccountConfirm, deleteAccountError: t.accountDash.deleteAccountError }}>
window.__accountDashVars = { loginPath, fallbackName, greetingTemplate, reviewedBadgeText, invoiceLang, invoiceLabels, loyaltyProgressTemplate, loyaltyRemainingOne, loyaltyRemainingOther, loyaltyUnlockedTitle, loyaltyUnlockedText, loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix, loyaltyLastRedeemed, aboLang, aboLabels, deleteAccountConfirm, deleteAccountError };
</script>
<script>
@@ -790,6 +793,7 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
import { getAccount, isLoggedIn, login, setName, logout, setUsername, setPhoto, hatBestellungBewertet, anzeigeName, treueFortschritt, aboStatus, aboAbschliessen, aboZahlungSimulieren, aboKuendigen, teddyEinloesen } from "../../../scripts/account";
import { rechnungAlsPdfHerunterladen } from "../../../scripts/invoice-pdf";
import { fuegeTeddyGratisHinzu } from "../../../scripts/cart";
import { getProduct } from "../../../data/products";
import { formatPrice } from "../../../i18n/format";
import { aboStufenKonfig } from "../../../data/abo";
const { loginPath, fallbackName, greetingTemplate, reviewedBadgeText, invoiceLang, invoiceLabels, loyaltyProgressTemplate, loyaltyRemainingOne, loyaltyRemainingOther, loyaltyUnlockedTitle, loyaltyUnlockedText, loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix, loyaltyLastRedeemed, aboLang, aboLabels, deleteAccountConfirm, deleteAccountError } = (window as any).__accountDashVars;
@@ -1010,9 +1014,57 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
} else fortschrittGrossWrap.style.display = "none";
}
setText("abo-praemien-erhalten", aboLabels.praemienErhaltenTemplate
.replace("{klein}", String(a.abo.kleinTeddyEingeloest))
.replace("{gross}", String(a.abo.grossTeddyEingeloest)));
// Bereits erhaltene Teddys namentlich auflisten (neueste zuerst).
const erhaltenBox = document.getElementById("abo-erhalten-box");
const erhaltenListe = document.getElementById("abo-erhalten-liste");
const gesamtEingeloest = a.abo.kleinTeddyEingeloest + a.abo.grossTeddyEingeloest;
setText("abo-erhalten-titel-text", gesamtEingeloest === 0 ? aboLabels.praemienKeine : aboLabels.praemienErhaltenTitel);
if (erhaltenBox) erhaltenBox.classList.toggle("is-leer", gesamtEingeloest === 0);
if (erhaltenListe) {
erhaltenListe.innerHTML = "";
const eintraege = [...a.abo.erhalteneTeddys].reverse();
eintraege.forEach((teddy) => {
// Aktueller, uebersetzter Produktname bevorzugt; der beim Einloesen gespeicherte Name
// ist nur die Rueckfallebene, falls das Produkt inzwischen umbenannt/entfernt wurde.
const produkt = getProduct(teddy.slug);
const name = produkt?.name[aboLang] ?? teddy.name;
const artLabel = teddy.art === "klein" ? aboLabels.teddyArtKlein : aboLabels.teddyArtGross;
const li = document.createElement("li");
li.className = "abo-erhalten-eintrag";
const bez = document.createElement("span");
bez.className = "abo-erhalten-name";
// Heisst das Produkt selbst schon "Kleiner Teddy", nicht "Kleiner Teddy: Kleiner Teddy"
// schreiben. Erst wenn VanVan echte Teddy-Namen hinterlegt, steht beides nebeneinander.
const nameGleichArt = name.trim().toLowerCase() === artLabel.trim().toLowerCase();
bez.textContent = name && !nameGleichArt ? `${artLabel}: ${name}` : (name || artLabel);
li.appendChild(bez);
if (teddy.datum) {
const dat = document.createElement("span");
dat.className = "abo-erhalten-datum";
const [j, m, tg] = teddy.datum.split("-");
dat.textContent = aboLabels.praemienAmTemplate.replace("{datum}", `${tg}.${m}.${j}`);
li.appendChild(dat);
}
// Direkt zum Produkt springen, damit man sofort nachsehen kann, welcher Teddy das war.
if (produkt) {
const link = document.createElement("a");
link.className = "abo-erhalten-link";
link.href = `${aboLang === "de" ? "" : "/" + aboLang}/produkt/${teddy.slug}/`;
link.textContent = aboLabels.praemienAnsehen;
li.appendChild(link);
}
erhaltenListe.appendChild(li);
});
// Aeltere Konten kennen die namentliche Liste noch nicht: fehlende Eintraege werden
// ehrlich ohne Namen ergaenzt, statt sie einfach zu verschweigen.
const fehlend = gesamtEingeloest - eintraege.length;
for (let i = 0; i < fehlend; i++) {
const li = document.createElement("li");
li.className = "abo-erhalten-eintrag abo-erhalten-eintrag-unbekannt";
li.textContent = aboLabels.praemienUnbekannt;
erhaltenListe.appendChild(li);
}
}
const gekuendigtHinweis = document.getElementById("abo-gekuendigt-hinweis");
if (gekuendigtHinweis) {
@@ -1080,8 +1132,12 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
btn.addEventListener("click", () => {
const art = btn.dataset.einloesen as "klein" | "gross" | undefined;
if (!art) return;
teddyEinloesen(art);
fuegeTeddyGratisHinzu(art);
// Erst pruefen, ob ueberhaupt eine Praemie offen ist — sonst landete der Teddy im
// Warenkorb, ohne dass er im Konto als eingeloest gezaehlt wurde (waere gratis doppelt).
const offen = aboStatus(getAccount());
if ((art === "klein" ? offen.kleinVerfuegbar : offen.grossVerfuegbar) <= 0) return;
const teddy = fuegeTeddyGratisHinzu(art);
teddyEinloesen(art, teddy);
const hinweis = document.getElementById("abo-eingeloest-hinweis");
if (hinweis) {
hinweis.style.display = "block";
+65 -9
View File
@@ -560,9 +560,12 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
</div>
</div>
<div class="abo-erhalten-chip">
<span aria-hidden="true">🧸</span>
<span id="abo-praemien-erhalten"></span>
{/* Zeigt nicht nur WIE VIELE Teddys schon eingeloest wurden, sondern WELCHE genau —
mit Name und Datum. So sieht die Kundin auf einen Blick, welchen Teddy sie schon
besitzt, und waehlt keinen doppelt. Wird per JS aus abo.erhalteneTeddys befuellt. */}
<div class="abo-erhalten-box" id="abo-erhalten-box">
<p class="abo-erhalten-titel"><span aria-hidden="true">🧸</span> <span id="abo-erhalten-titel-text"></span></p>
<ul class="abo-erhalten-liste" id="abo-erhalten-liste"></ul>
</div>
<p id="abo-gekuendigt-hinweis" class="small" style="display:none;"></p>
@@ -607,7 +610,7 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
</section>
</Layout>
<script define:vars={{ loginPath: "/en/konto/", fallbackName: "Customer", greetingTemplate: t.accountDash.greeting("{name}"), reviewedBadgeText: t.accountDash.reviewedBadge , invoiceLang: lang, invoiceLabels: { title: t.accountDash.invoiceTitle, numberLabel: t.accountDash.invoiceNumberLabel, dateLabel: t.accountDash.invoiceDateLabel, sellerLabel: t.accountDash.invoiceSellerLabel, billToLabel: t.accountDash.invoiceBillToLabel, itemLabel: t.accountDash.invoiceItemLabel, qtyLabel: t.accountDash.invoiceQtyLabel, unitPriceLabel: t.accountDash.invoiceUnitPriceLabel, sumLabel: t.accountDash.invoiceSumLabel, totalLabel: t.accountDash.orderTotal, vatNote: t.common.vatNote }, loyaltyProgressTemplate: t.accountDash.loyaltyProgressTemplate, loyaltyRemainingOne: t.accountDash.loyaltyRemainingOne, loyaltyRemainingOther: t.accountDash.loyaltyRemainingOther, loyaltyUnlockedTitle: t.accountDash.loyaltyUnlockedTitle, loyaltyUnlockedText: t.accountDash.loyaltyUnlockedText, loyaltyStatRedeemedNever: t.accountDash.loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix: t.accountDash.loyaltyStatRedeemedSuffix, loyaltyLastRedeemed: t.accountDash.loyaltyLastRedeemed, aboLang: lang, aboLabels: { nameKlein: t.accountDash.aboNameKlein, nameMittel: t.accountDash.aboNameMittel, nameGross: t.accountDash.aboNameGross, preisSuffix: t.accountDash.aboPreisSuffix, monateSuffix: t.accountDash.aboMonateSuffix, fortschrittKleinTemplate: t.accountDash.aboFortschrittKleinTemplate, fortschrittGrossTemplate: t.accountDash.aboFortschrittGrossTemplate, praemienErhaltenTemplate: t.accountDash.aboPraemienErhaltenTemplate, aktivBadge: t.accountDash.aboAktivesLabel, nichtAktivBadge: t.accountDash.aboNichtAktivBadge, gekuendigtHinweisTemplate: t.accountDash.aboGekuendigtHinweisTemplate, kuendigenConfirm: t.accountDash.aboKuendigenConfirm, abschliessenBtn: t.accountDash.aboAbschliessenBtn, wechselnBtn: t.accountDash.aboWechselnBtn, nichtBuchbar: t.accountDash.aboNichtBuchbar, keineBenachrichtigungen: t.accountDash.aboKeineBenachrichtigungen, notifKeyLabels: { abo_abgeschlossen: t.accountDash.notifAboAbgeschlossen, abo_gewechselt: t.accountDash.notifAboGewechselt, abo_zahlung_erfolgreich: t.accountDash.notifAboZahlungErfolgreich, abo_teddy_klein_frei: t.accountDash.notifAboTeddyKleinFrei, abo_teddy_gross_frei: t.accountDash.notifAboTeddyGrossFrei, abo_bald_praemie: t.accountDash.notifAboBaldPraemie, abo_gekuendigt: t.accountDash.notifAboGekuendigt, abo_teddy_klein_eingeloest: t.accountDash.notifAboTeddyKleinEingeloest, abo_teddy_gross_eingeloest: t.accountDash.notifAboTeddyGrossEingeloest } }, deleteAccountConfirm: t.accountDash.deleteAccountConfirm, deleteAccountError: t.accountDash.deleteAccountError }}>
<script define:vars={{ loginPath: "/en/konto/", fallbackName: "Customer", greetingTemplate: t.accountDash.greeting("{name}"), reviewedBadgeText: t.accountDash.reviewedBadge , invoiceLang: lang, invoiceLabels: { title: t.accountDash.invoiceTitle, numberLabel: t.accountDash.invoiceNumberLabel, dateLabel: t.accountDash.invoiceDateLabel, sellerLabel: t.accountDash.invoiceSellerLabel, billToLabel: t.accountDash.invoiceBillToLabel, itemLabel: t.accountDash.invoiceItemLabel, qtyLabel: t.accountDash.invoiceQtyLabel, unitPriceLabel: t.accountDash.invoiceUnitPriceLabel, sumLabel: t.accountDash.invoiceSumLabel, totalLabel: t.accountDash.orderTotal, vatNote: t.common.vatNote }, loyaltyProgressTemplate: t.accountDash.loyaltyProgressTemplate, loyaltyRemainingOne: t.accountDash.loyaltyRemainingOne, loyaltyRemainingOther: t.accountDash.loyaltyRemainingOther, loyaltyUnlockedTitle: t.accountDash.loyaltyUnlockedTitle, loyaltyUnlockedText: t.accountDash.loyaltyUnlockedText, loyaltyStatRedeemedNever: t.accountDash.loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix: t.accountDash.loyaltyStatRedeemedSuffix, loyaltyLastRedeemed: t.accountDash.loyaltyLastRedeemed, aboLang: lang, aboLabels: { nameKlein: t.accountDash.aboNameKlein, nameMittel: t.accountDash.aboNameMittel, nameGross: t.accountDash.aboNameGross, preisSuffix: t.accountDash.aboPreisSuffix, monateSuffix: t.accountDash.aboMonateSuffix, fortschrittKleinTemplate: t.accountDash.aboFortschrittKleinTemplate, fortschrittGrossTemplate: t.accountDash.aboFortschrittGrossTemplate, praemienErhaltenTitel: t.accountDash.aboPraemienErhaltenTitel, praemienKeine: t.accountDash.aboPraemienKeine, praemienAmTemplate: t.accountDash.aboPraemienAmTemplate, praemienAnsehen: t.accountDash.aboPraemienAnsehen, praemienUnbekannt: t.accountDash.aboPraemienUnbekannt, teddyArtKlein: t.accountDash.aboTeddyArtKlein, teddyArtGross: t.accountDash.aboTeddyArtGross, aktivBadge: t.accountDash.aboAktivesLabel, nichtAktivBadge: t.accountDash.aboNichtAktivBadge, gekuendigtHinweisTemplate: t.accountDash.aboGekuendigtHinweisTemplate, kuendigenConfirm: t.accountDash.aboKuendigenConfirm, abschliessenBtn: t.accountDash.aboAbschliessenBtn, wechselnBtn: t.accountDash.aboWechselnBtn, nichtBuchbar: t.accountDash.aboNichtBuchbar, keineBenachrichtigungen: t.accountDash.aboKeineBenachrichtigungen, notifKeyLabels: { abo_abgeschlossen: t.accountDash.notifAboAbgeschlossen, abo_gewechselt: t.accountDash.notifAboGewechselt, abo_zahlung_erfolgreich: t.accountDash.notifAboZahlungErfolgreich, abo_teddy_klein_frei: t.accountDash.notifAboTeddyKleinFrei, abo_teddy_gross_frei: t.accountDash.notifAboTeddyGrossFrei, abo_bald_praemie: t.accountDash.notifAboBaldPraemie, abo_gekuendigt: t.accountDash.notifAboGekuendigt, abo_teddy_klein_eingeloest: t.accountDash.notifAboTeddyKleinEingeloest, abo_teddy_gross_eingeloest: t.accountDash.notifAboTeddyGrossEingeloest } }, deleteAccountConfirm: t.accountDash.deleteAccountConfirm, deleteAccountError: t.accountDash.deleteAccountError }}>
window.__accountDashVars = { loginPath, fallbackName, greetingTemplate, reviewedBadgeText, invoiceLang, invoiceLabels, loyaltyProgressTemplate, loyaltyRemainingOne, loyaltyRemainingOther, loyaltyUnlockedTitle, loyaltyUnlockedText, loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix, loyaltyLastRedeemed, aboLang, aboLabels, deleteAccountConfirm, deleteAccountError };
</script>
<script>
@@ -790,6 +793,7 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
import { getAccount, isLoggedIn, login, setName, logout, setUsername, setPhoto, hatBestellungBewertet, anzeigeName, treueFortschritt, aboStatus, aboAbschliessen, aboZahlungSimulieren, aboKuendigen, teddyEinloesen } from "../../../scripts/account";
import { rechnungAlsPdfHerunterladen } from "../../../scripts/invoice-pdf";
import { fuegeTeddyGratisHinzu } from "../../../scripts/cart";
import { getProduct } from "../../../data/products";
import { formatPrice } from "../../../i18n/format";
import { aboStufenKonfig } from "../../../data/abo";
const { loginPath, fallbackName, greetingTemplate, reviewedBadgeText, invoiceLang, invoiceLabels, loyaltyProgressTemplate, loyaltyRemainingOne, loyaltyRemainingOther, loyaltyUnlockedTitle, loyaltyUnlockedText, loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix, loyaltyLastRedeemed, aboLang, aboLabels, deleteAccountConfirm, deleteAccountError } = (window as any).__accountDashVars;
@@ -1010,9 +1014,57 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
} else fortschrittGrossWrap.style.display = "none";
}
setText("abo-praemien-erhalten", aboLabels.praemienErhaltenTemplate
.replace("{klein}", String(a.abo.kleinTeddyEingeloest))
.replace("{gross}", String(a.abo.grossTeddyEingeloest)));
// Bereits erhaltene Teddys namentlich auflisten (neueste zuerst).
const erhaltenBox = document.getElementById("abo-erhalten-box");
const erhaltenListe = document.getElementById("abo-erhalten-liste");
const gesamtEingeloest = a.abo.kleinTeddyEingeloest + a.abo.grossTeddyEingeloest;
setText("abo-erhalten-titel-text", gesamtEingeloest === 0 ? aboLabels.praemienKeine : aboLabels.praemienErhaltenTitel);
if (erhaltenBox) erhaltenBox.classList.toggle("is-leer", gesamtEingeloest === 0);
if (erhaltenListe) {
erhaltenListe.innerHTML = "";
const eintraege = [...a.abo.erhalteneTeddys].reverse();
eintraege.forEach((teddy) => {
// Aktueller, uebersetzter Produktname bevorzugt; der beim Einloesen gespeicherte Name
// ist nur die Rueckfallebene, falls das Produkt inzwischen umbenannt/entfernt wurde.
const produkt = getProduct(teddy.slug);
const name = produkt?.name[aboLang] ?? teddy.name;
const artLabel = teddy.art === "klein" ? aboLabels.teddyArtKlein : aboLabels.teddyArtGross;
const li = document.createElement("li");
li.className = "abo-erhalten-eintrag";
const bez = document.createElement("span");
bez.className = "abo-erhalten-name";
// Heisst das Produkt selbst schon "Kleiner Teddy", nicht "Kleiner Teddy: Kleiner Teddy"
// schreiben. Erst wenn VanVan echte Teddy-Namen hinterlegt, steht beides nebeneinander.
const nameGleichArt = name.trim().toLowerCase() === artLabel.trim().toLowerCase();
bez.textContent = name && !nameGleichArt ? `${artLabel}: ${name}` : (name || artLabel);
li.appendChild(bez);
if (teddy.datum) {
const dat = document.createElement("span");
dat.className = "abo-erhalten-datum";
const [j, m, tg] = teddy.datum.split("-");
dat.textContent = aboLabels.praemienAmTemplate.replace("{datum}", `${tg}.${m}.${j}`);
li.appendChild(dat);
}
// Direkt zum Produkt springen, damit man sofort nachsehen kann, welcher Teddy das war.
if (produkt) {
const link = document.createElement("a");
link.className = "abo-erhalten-link";
link.href = `${aboLang === "de" ? "" : "/" + aboLang}/produkt/${teddy.slug}/`;
link.textContent = aboLabels.praemienAnsehen;
li.appendChild(link);
}
erhaltenListe.appendChild(li);
});
// Aeltere Konten kennen die namentliche Liste noch nicht: fehlende Eintraege werden
// ehrlich ohne Namen ergaenzt, statt sie einfach zu verschweigen.
const fehlend = gesamtEingeloest - eintraege.length;
for (let i = 0; i < fehlend; i++) {
const li = document.createElement("li");
li.className = "abo-erhalten-eintrag abo-erhalten-eintrag-unbekannt";
li.textContent = aboLabels.praemienUnbekannt;
erhaltenListe.appendChild(li);
}
}
const gekuendigtHinweis = document.getElementById("abo-gekuendigt-hinweis");
if (gekuendigtHinweis) {
@@ -1080,8 +1132,12 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
btn.addEventListener("click", () => {
const art = btn.dataset.einloesen as "klein" | "gross" | undefined;
if (!art) return;
teddyEinloesen(art);
fuegeTeddyGratisHinzu(art);
// Erst pruefen, ob ueberhaupt eine Praemie offen ist — sonst landete der Teddy im
// Warenkorb, ohne dass er im Konto als eingeloest gezaehlt wurde (waere gratis doppelt).
const offen = aboStatus(getAccount());
if ((art === "klein" ? offen.kleinVerfuegbar : offen.grossVerfuegbar) <= 0) return;
const teddy = fuegeTeddyGratisHinzu(art);
teddyEinloesen(art, teddy);
const hinweis = document.getElementById("abo-eingeloest-hinweis");
if (hinweis) {
hinweis.style.display = "block";
+65 -9
View File
@@ -560,9 +560,12 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
</div>
</div>
<div class="abo-erhalten-chip">
<span aria-hidden="true">🧸</span>
<span id="abo-praemien-erhalten"></span>
{/* Zeigt nicht nur WIE VIELE Teddys schon eingeloest wurden, sondern WELCHE genau —
mit Name und Datum. So sieht die Kundin auf einen Blick, welchen Teddy sie schon
besitzt, und waehlt keinen doppelt. Wird per JS aus abo.erhalteneTeddys befuellt. */}
<div class="abo-erhalten-box" id="abo-erhalten-box">
<p class="abo-erhalten-titel"><span aria-hidden="true">🧸</span> <span id="abo-erhalten-titel-text"></span></p>
<ul class="abo-erhalten-liste" id="abo-erhalten-liste"></ul>
</div>
<p id="abo-gekuendigt-hinweis" class="small" style="display:none;"></p>
@@ -607,7 +610,7 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
</section>
</Layout>
<script define:vars={{ loginPath: "/fr/konto/", fallbackName: "Cliente", greetingTemplate: t.accountDash.greeting("{name}"), reviewedBadgeText: t.accountDash.reviewedBadge , invoiceLang: lang, invoiceLabels: { title: t.accountDash.invoiceTitle, numberLabel: t.accountDash.invoiceNumberLabel, dateLabel: t.accountDash.invoiceDateLabel, sellerLabel: t.accountDash.invoiceSellerLabel, billToLabel: t.accountDash.invoiceBillToLabel, itemLabel: t.accountDash.invoiceItemLabel, qtyLabel: t.accountDash.invoiceQtyLabel, unitPriceLabel: t.accountDash.invoiceUnitPriceLabel, sumLabel: t.accountDash.invoiceSumLabel, totalLabel: t.accountDash.orderTotal, vatNote: t.common.vatNote }, loyaltyProgressTemplate: t.accountDash.loyaltyProgressTemplate, loyaltyRemainingOne: t.accountDash.loyaltyRemainingOne, loyaltyRemainingOther: t.accountDash.loyaltyRemainingOther, loyaltyUnlockedTitle: t.accountDash.loyaltyUnlockedTitle, loyaltyUnlockedText: t.accountDash.loyaltyUnlockedText, loyaltyStatRedeemedNever: t.accountDash.loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix: t.accountDash.loyaltyStatRedeemedSuffix, loyaltyLastRedeemed: t.accountDash.loyaltyLastRedeemed, aboLang: lang, aboLabels: { nameKlein: t.accountDash.aboNameKlein, nameMittel: t.accountDash.aboNameMittel, nameGross: t.accountDash.aboNameGross, preisSuffix: t.accountDash.aboPreisSuffix, monateSuffix: t.accountDash.aboMonateSuffix, fortschrittKleinTemplate: t.accountDash.aboFortschrittKleinTemplate, fortschrittGrossTemplate: t.accountDash.aboFortschrittGrossTemplate, praemienErhaltenTemplate: t.accountDash.aboPraemienErhaltenTemplate, aktivBadge: t.accountDash.aboAktivesLabel, nichtAktivBadge: t.accountDash.aboNichtAktivBadge, gekuendigtHinweisTemplate: t.accountDash.aboGekuendigtHinweisTemplate, kuendigenConfirm: t.accountDash.aboKuendigenConfirm, abschliessenBtn: t.accountDash.aboAbschliessenBtn, wechselnBtn: t.accountDash.aboWechselnBtn, nichtBuchbar: t.accountDash.aboNichtBuchbar, keineBenachrichtigungen: t.accountDash.aboKeineBenachrichtigungen, notifKeyLabels: { abo_abgeschlossen: t.accountDash.notifAboAbgeschlossen, abo_gewechselt: t.accountDash.notifAboGewechselt, abo_zahlung_erfolgreich: t.accountDash.notifAboZahlungErfolgreich, abo_teddy_klein_frei: t.accountDash.notifAboTeddyKleinFrei, abo_teddy_gross_frei: t.accountDash.notifAboTeddyGrossFrei, abo_bald_praemie: t.accountDash.notifAboBaldPraemie, abo_gekuendigt: t.accountDash.notifAboGekuendigt, abo_teddy_klein_eingeloest: t.accountDash.notifAboTeddyKleinEingeloest, abo_teddy_gross_eingeloest: t.accountDash.notifAboTeddyGrossEingeloest } }, deleteAccountConfirm: t.accountDash.deleteAccountConfirm, deleteAccountError: t.accountDash.deleteAccountError }}>
<script define:vars={{ loginPath: "/fr/konto/", fallbackName: "Cliente", greetingTemplate: t.accountDash.greeting("{name}"), reviewedBadgeText: t.accountDash.reviewedBadge , invoiceLang: lang, invoiceLabels: { title: t.accountDash.invoiceTitle, numberLabel: t.accountDash.invoiceNumberLabel, dateLabel: t.accountDash.invoiceDateLabel, sellerLabel: t.accountDash.invoiceSellerLabel, billToLabel: t.accountDash.invoiceBillToLabel, itemLabel: t.accountDash.invoiceItemLabel, qtyLabel: t.accountDash.invoiceQtyLabel, unitPriceLabel: t.accountDash.invoiceUnitPriceLabel, sumLabel: t.accountDash.invoiceSumLabel, totalLabel: t.accountDash.orderTotal, vatNote: t.common.vatNote }, loyaltyProgressTemplate: t.accountDash.loyaltyProgressTemplate, loyaltyRemainingOne: t.accountDash.loyaltyRemainingOne, loyaltyRemainingOther: t.accountDash.loyaltyRemainingOther, loyaltyUnlockedTitle: t.accountDash.loyaltyUnlockedTitle, loyaltyUnlockedText: t.accountDash.loyaltyUnlockedText, loyaltyStatRedeemedNever: t.accountDash.loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix: t.accountDash.loyaltyStatRedeemedSuffix, loyaltyLastRedeemed: t.accountDash.loyaltyLastRedeemed, aboLang: lang, aboLabels: { nameKlein: t.accountDash.aboNameKlein, nameMittel: t.accountDash.aboNameMittel, nameGross: t.accountDash.aboNameGross, preisSuffix: t.accountDash.aboPreisSuffix, monateSuffix: t.accountDash.aboMonateSuffix, fortschrittKleinTemplate: t.accountDash.aboFortschrittKleinTemplate, fortschrittGrossTemplate: t.accountDash.aboFortschrittGrossTemplate, praemienErhaltenTitel: t.accountDash.aboPraemienErhaltenTitel, praemienKeine: t.accountDash.aboPraemienKeine, praemienAmTemplate: t.accountDash.aboPraemienAmTemplate, praemienAnsehen: t.accountDash.aboPraemienAnsehen, praemienUnbekannt: t.accountDash.aboPraemienUnbekannt, teddyArtKlein: t.accountDash.aboTeddyArtKlein, teddyArtGross: t.accountDash.aboTeddyArtGross, aktivBadge: t.accountDash.aboAktivesLabel, nichtAktivBadge: t.accountDash.aboNichtAktivBadge, gekuendigtHinweisTemplate: t.accountDash.aboGekuendigtHinweisTemplate, kuendigenConfirm: t.accountDash.aboKuendigenConfirm, abschliessenBtn: t.accountDash.aboAbschliessenBtn, wechselnBtn: t.accountDash.aboWechselnBtn, nichtBuchbar: t.accountDash.aboNichtBuchbar, keineBenachrichtigungen: t.accountDash.aboKeineBenachrichtigungen, notifKeyLabels: { abo_abgeschlossen: t.accountDash.notifAboAbgeschlossen, abo_gewechselt: t.accountDash.notifAboGewechselt, abo_zahlung_erfolgreich: t.accountDash.notifAboZahlungErfolgreich, abo_teddy_klein_frei: t.accountDash.notifAboTeddyKleinFrei, abo_teddy_gross_frei: t.accountDash.notifAboTeddyGrossFrei, abo_bald_praemie: t.accountDash.notifAboBaldPraemie, abo_gekuendigt: t.accountDash.notifAboGekuendigt, abo_teddy_klein_eingeloest: t.accountDash.notifAboTeddyKleinEingeloest, abo_teddy_gross_eingeloest: t.accountDash.notifAboTeddyGrossEingeloest } }, deleteAccountConfirm: t.accountDash.deleteAccountConfirm, deleteAccountError: t.accountDash.deleteAccountError }}>
window.__accountDashVars = { loginPath, fallbackName, greetingTemplate, reviewedBadgeText, invoiceLang, invoiceLabels, loyaltyProgressTemplate, loyaltyRemainingOne, loyaltyRemainingOther, loyaltyUnlockedTitle, loyaltyUnlockedText, loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix, loyaltyLastRedeemed, aboLang, aboLabels, deleteAccountConfirm, deleteAccountError };
</script>
<script>
@@ -790,6 +793,7 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
import { getAccount, isLoggedIn, login, setName, logout, setUsername, setPhoto, hatBestellungBewertet, anzeigeName, treueFortschritt, aboStatus, aboAbschliessen, aboZahlungSimulieren, aboKuendigen, teddyEinloesen } from "../../../scripts/account";
import { rechnungAlsPdfHerunterladen } from "../../../scripts/invoice-pdf";
import { fuegeTeddyGratisHinzu } from "../../../scripts/cart";
import { getProduct } from "../../../data/products";
import { formatPrice } from "../../../i18n/format";
import { aboStufenKonfig } from "../../../data/abo";
const { loginPath, fallbackName, greetingTemplate, reviewedBadgeText, invoiceLang, invoiceLabels, loyaltyProgressTemplate, loyaltyRemainingOne, loyaltyRemainingOther, loyaltyUnlockedTitle, loyaltyUnlockedText, loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix, loyaltyLastRedeemed, aboLang, aboLabels, deleteAccountConfirm, deleteAccountError } = (window as any).__accountDashVars;
@@ -1010,9 +1014,57 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
} else fortschrittGrossWrap.style.display = "none";
}
setText("abo-praemien-erhalten", aboLabels.praemienErhaltenTemplate
.replace("{klein}", String(a.abo.kleinTeddyEingeloest))
.replace("{gross}", String(a.abo.grossTeddyEingeloest)));
// Bereits erhaltene Teddys namentlich auflisten (neueste zuerst).
const erhaltenBox = document.getElementById("abo-erhalten-box");
const erhaltenListe = document.getElementById("abo-erhalten-liste");
const gesamtEingeloest = a.abo.kleinTeddyEingeloest + a.abo.grossTeddyEingeloest;
setText("abo-erhalten-titel-text", gesamtEingeloest === 0 ? aboLabels.praemienKeine : aboLabels.praemienErhaltenTitel);
if (erhaltenBox) erhaltenBox.classList.toggle("is-leer", gesamtEingeloest === 0);
if (erhaltenListe) {
erhaltenListe.innerHTML = "";
const eintraege = [...a.abo.erhalteneTeddys].reverse();
eintraege.forEach((teddy) => {
// Aktueller, uebersetzter Produktname bevorzugt; der beim Einloesen gespeicherte Name
// ist nur die Rueckfallebene, falls das Produkt inzwischen umbenannt/entfernt wurde.
const produkt = getProduct(teddy.slug);
const name = produkt?.name[aboLang] ?? teddy.name;
const artLabel = teddy.art === "klein" ? aboLabels.teddyArtKlein : aboLabels.teddyArtGross;
const li = document.createElement("li");
li.className = "abo-erhalten-eintrag";
const bez = document.createElement("span");
bez.className = "abo-erhalten-name";
// Heisst das Produkt selbst schon "Kleiner Teddy", nicht "Kleiner Teddy: Kleiner Teddy"
// schreiben. Erst wenn VanVan echte Teddy-Namen hinterlegt, steht beides nebeneinander.
const nameGleichArt = name.trim().toLowerCase() === artLabel.trim().toLowerCase();
bez.textContent = name && !nameGleichArt ? `${artLabel}: ${name}` : (name || artLabel);
li.appendChild(bez);
if (teddy.datum) {
const dat = document.createElement("span");
dat.className = "abo-erhalten-datum";
const [j, m, tg] = teddy.datum.split("-");
dat.textContent = aboLabels.praemienAmTemplate.replace("{datum}", `${tg}.${m}.${j}`);
li.appendChild(dat);
}
// Direkt zum Produkt springen, damit man sofort nachsehen kann, welcher Teddy das war.
if (produkt) {
const link = document.createElement("a");
link.className = "abo-erhalten-link";
link.href = `${aboLang === "de" ? "" : "/" + aboLang}/produkt/${teddy.slug}/`;
link.textContent = aboLabels.praemienAnsehen;
li.appendChild(link);
}
erhaltenListe.appendChild(li);
});
// Aeltere Konten kennen die namentliche Liste noch nicht: fehlende Eintraege werden
// ehrlich ohne Namen ergaenzt, statt sie einfach zu verschweigen.
const fehlend = gesamtEingeloest - eintraege.length;
for (let i = 0; i < fehlend; i++) {
const li = document.createElement("li");
li.className = "abo-erhalten-eintrag abo-erhalten-eintrag-unbekannt";
li.textContent = aboLabels.praemienUnbekannt;
erhaltenListe.appendChild(li);
}
}
const gekuendigtHinweis = document.getElementById("abo-gekuendigt-hinweis");
if (gekuendigtHinweis) {
@@ -1080,8 +1132,12 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
btn.addEventListener("click", () => {
const art = btn.dataset.einloesen as "klein" | "gross" | undefined;
if (!art) return;
teddyEinloesen(art);
fuegeTeddyGratisHinzu(art);
// Erst pruefen, ob ueberhaupt eine Praemie offen ist — sonst landete der Teddy im
// Warenkorb, ohne dass er im Konto als eingeloest gezaehlt wurde (waere gratis doppelt).
const offen = aboStatus(getAccount());
if ((art === "klein" ? offen.kleinVerfuegbar : offen.grossVerfuegbar) <= 0) return;
const teddy = fuegeTeddyGratisHinzu(art);
teddyEinloesen(art, teddy);
const hinweis = document.getElementById("abo-eingeloest-hinweis");
if (hinweis) {
hinweis.style.display = "block";
+65 -9
View File
@@ -569,9 +569,12 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
</div>
</div>
<div class="abo-erhalten-chip">
<span aria-hidden="true">🧸</span>
<span id="abo-praemien-erhalten"></span>
{/* Zeigt nicht nur WIE VIELE Teddys schon eingeloest wurden, sondern WELCHE genau —
mit Name und Datum. So sieht die Kundin auf einen Blick, welchen Teddy sie schon
besitzt, und waehlt keinen doppelt. Wird per JS aus abo.erhalteneTeddys befuellt. */}
<div class="abo-erhalten-box" id="abo-erhalten-box">
<p class="abo-erhalten-titel"><span aria-hidden="true">🧸</span> <span id="abo-erhalten-titel-text"></span></p>
<ul class="abo-erhalten-liste" id="abo-erhalten-liste"></ul>
</div>
<p id="abo-gekuendigt-hinweis" class="small" style="display:none;"></p>
@@ -616,7 +619,7 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
</section>
</Layout>
<script define:vars={{ loginPath: "/konto/", fallbackName: "Kundin", greetingTemplate: t.accountDash.greeting("{name}"), reviewedBadgeText: t.accountDash.reviewedBadge , invoiceLang: lang, invoiceLabels: { title: t.accountDash.invoiceTitle, numberLabel: t.accountDash.invoiceNumberLabel, dateLabel: t.accountDash.invoiceDateLabel, sellerLabel: t.accountDash.invoiceSellerLabel, billToLabel: t.accountDash.invoiceBillToLabel, itemLabel: t.accountDash.invoiceItemLabel, qtyLabel: t.accountDash.invoiceQtyLabel, unitPriceLabel: t.accountDash.invoiceUnitPriceLabel, sumLabel: t.accountDash.invoiceSumLabel, totalLabel: t.accountDash.orderTotal, vatNote: t.common.vatNote }, loyaltyProgressTemplate: t.accountDash.loyaltyProgressTemplate, loyaltyRemainingOne: t.accountDash.loyaltyRemainingOne, loyaltyRemainingOther: t.accountDash.loyaltyRemainingOther, loyaltyUnlockedTitle: t.accountDash.loyaltyUnlockedTitle, loyaltyUnlockedText: t.accountDash.loyaltyUnlockedText, loyaltyStatRedeemedNever: t.accountDash.loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix: t.accountDash.loyaltyStatRedeemedSuffix, loyaltyLastRedeemed: t.accountDash.loyaltyLastRedeemed, aboLang: lang, aboLabels: { nameKlein: t.accountDash.aboNameKlein, nameMittel: t.accountDash.aboNameMittel, nameGross: t.accountDash.aboNameGross, preisSuffix: t.accountDash.aboPreisSuffix, monateSuffix: t.accountDash.aboMonateSuffix, fortschrittKleinTemplate: t.accountDash.aboFortschrittKleinTemplate, fortschrittGrossTemplate: t.accountDash.aboFortschrittGrossTemplate, praemienErhaltenTemplate: t.accountDash.aboPraemienErhaltenTemplate, aktivBadge: t.accountDash.aboAktivesLabel, nichtAktivBadge: t.accountDash.aboNichtAktivBadge, gekuendigtHinweisTemplate: t.accountDash.aboGekuendigtHinweisTemplate, kuendigenConfirm: t.accountDash.aboKuendigenConfirm, abschliessenBtn: t.accountDash.aboAbschliessenBtn, wechselnBtn: t.accountDash.aboWechselnBtn, nichtBuchbar: t.accountDash.aboNichtBuchbar, keineBenachrichtigungen: t.accountDash.aboKeineBenachrichtigungen, notifKeyLabels: { abo_abgeschlossen: t.accountDash.notifAboAbgeschlossen, abo_gewechselt: t.accountDash.notifAboGewechselt, abo_zahlung_erfolgreich: t.accountDash.notifAboZahlungErfolgreich, abo_teddy_klein_frei: t.accountDash.notifAboTeddyKleinFrei, abo_teddy_gross_frei: t.accountDash.notifAboTeddyGrossFrei, abo_bald_praemie: t.accountDash.notifAboBaldPraemie, abo_gekuendigt: t.accountDash.notifAboGekuendigt, abo_teddy_klein_eingeloest: t.accountDash.notifAboTeddyKleinEingeloest, abo_teddy_gross_eingeloest: t.accountDash.notifAboTeddyGrossEingeloest } }, deleteAccountConfirm: t.accountDash.deleteAccountConfirm, deleteAccountError: t.accountDash.deleteAccountError }}>
<script define:vars={{ loginPath: "/konto/", fallbackName: "Kundin", greetingTemplate: t.accountDash.greeting("{name}"), reviewedBadgeText: t.accountDash.reviewedBadge , invoiceLang: lang, invoiceLabels: { title: t.accountDash.invoiceTitle, numberLabel: t.accountDash.invoiceNumberLabel, dateLabel: t.accountDash.invoiceDateLabel, sellerLabel: t.accountDash.invoiceSellerLabel, billToLabel: t.accountDash.invoiceBillToLabel, itemLabel: t.accountDash.invoiceItemLabel, qtyLabel: t.accountDash.invoiceQtyLabel, unitPriceLabel: t.accountDash.invoiceUnitPriceLabel, sumLabel: t.accountDash.invoiceSumLabel, totalLabel: t.accountDash.orderTotal, vatNote: t.common.vatNote }, loyaltyProgressTemplate: t.accountDash.loyaltyProgressTemplate, loyaltyRemainingOne: t.accountDash.loyaltyRemainingOne, loyaltyRemainingOther: t.accountDash.loyaltyRemainingOther, loyaltyUnlockedTitle: t.accountDash.loyaltyUnlockedTitle, loyaltyUnlockedText: t.accountDash.loyaltyUnlockedText, loyaltyStatRedeemedNever: t.accountDash.loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix: t.accountDash.loyaltyStatRedeemedSuffix, loyaltyLastRedeemed: t.accountDash.loyaltyLastRedeemed, aboLang: lang, aboLabels: { nameKlein: t.accountDash.aboNameKlein, nameMittel: t.accountDash.aboNameMittel, nameGross: t.accountDash.aboNameGross, preisSuffix: t.accountDash.aboPreisSuffix, monateSuffix: t.accountDash.aboMonateSuffix, fortschrittKleinTemplate: t.accountDash.aboFortschrittKleinTemplate, fortschrittGrossTemplate: t.accountDash.aboFortschrittGrossTemplate, praemienErhaltenTitel: t.accountDash.aboPraemienErhaltenTitel, praemienKeine: t.accountDash.aboPraemienKeine, praemienAmTemplate: t.accountDash.aboPraemienAmTemplate, praemienAnsehen: t.accountDash.aboPraemienAnsehen, praemienUnbekannt: t.accountDash.aboPraemienUnbekannt, teddyArtKlein: t.accountDash.aboTeddyArtKlein, teddyArtGross: t.accountDash.aboTeddyArtGross, aktivBadge: t.accountDash.aboAktivesLabel, nichtAktivBadge: t.accountDash.aboNichtAktivBadge, gekuendigtHinweisTemplate: t.accountDash.aboGekuendigtHinweisTemplate, kuendigenConfirm: t.accountDash.aboKuendigenConfirm, abschliessenBtn: t.accountDash.aboAbschliessenBtn, wechselnBtn: t.accountDash.aboWechselnBtn, nichtBuchbar: t.accountDash.aboNichtBuchbar, keineBenachrichtigungen: t.accountDash.aboKeineBenachrichtigungen, notifKeyLabels: { abo_abgeschlossen: t.accountDash.notifAboAbgeschlossen, abo_gewechselt: t.accountDash.notifAboGewechselt, abo_zahlung_erfolgreich: t.accountDash.notifAboZahlungErfolgreich, abo_teddy_klein_frei: t.accountDash.notifAboTeddyKleinFrei, abo_teddy_gross_frei: t.accountDash.notifAboTeddyGrossFrei, abo_bald_praemie: t.accountDash.notifAboBaldPraemie, abo_gekuendigt: t.accountDash.notifAboGekuendigt, abo_teddy_klein_eingeloest: t.accountDash.notifAboTeddyKleinEingeloest, abo_teddy_gross_eingeloest: t.accountDash.notifAboTeddyGrossEingeloest } }, deleteAccountConfirm: t.accountDash.deleteAccountConfirm, deleteAccountError: t.accountDash.deleteAccountError }}>
window.__accountDashVars = { loginPath, fallbackName, greetingTemplate, reviewedBadgeText, invoiceLang, invoiceLabels, loyaltyProgressTemplate, loyaltyRemainingOne, loyaltyRemainingOther, loyaltyUnlockedTitle, loyaltyUnlockedText, loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix, loyaltyLastRedeemed, aboLang, aboLabels, deleteAccountConfirm, deleteAccountError };
</script>
<script>
@@ -803,6 +806,7 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
import { getAccount, isLoggedIn, login, setName, logout, setUsername, setPhoto, hatBestellungBewertet, anzeigeName, treueFortschritt, aboStatus, aboAbschliessen, aboZahlungSimulieren, aboKuendigen, teddyEinloesen } from "../../scripts/account";
import { rechnungAlsPdfHerunterladen } from "../../scripts/invoice-pdf";
import { fuegeTeddyGratisHinzu } from "../../scripts/cart";
import { getProduct } from "../../data/products";
import { formatPrice } from "../../i18n/format";
import { aboStufenKonfig } from "../../data/abo";
const { loginPath, fallbackName, greetingTemplate, reviewedBadgeText, invoiceLang, invoiceLabels, loyaltyProgressTemplate, loyaltyRemainingOne, loyaltyRemainingOther, loyaltyUnlockedTitle, loyaltyUnlockedText, loyaltyStatRedeemedNever, loyaltyStatRedeemedSuffix, loyaltyLastRedeemed, aboLang, aboLabels, deleteAccountConfirm, deleteAccountError } = (window as any).__accountDashVars;
@@ -1026,9 +1030,57 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
} else fortschrittGrossWrap.style.display = "none";
}
setText("abo-praemien-erhalten", aboLabels.praemienErhaltenTemplate
.replace("{klein}", String(a.abo.kleinTeddyEingeloest))
.replace("{gross}", String(a.abo.grossTeddyEingeloest)));
// Bereits erhaltene Teddys namentlich auflisten (neueste zuerst).
const erhaltenBox = document.getElementById("abo-erhalten-box");
const erhaltenListe = document.getElementById("abo-erhalten-liste");
const gesamtEingeloest = a.abo.kleinTeddyEingeloest + a.abo.grossTeddyEingeloest;
setText("abo-erhalten-titel-text", gesamtEingeloest === 0 ? aboLabels.praemienKeine : aboLabels.praemienErhaltenTitel);
if (erhaltenBox) erhaltenBox.classList.toggle("is-leer", gesamtEingeloest === 0);
if (erhaltenListe) {
erhaltenListe.innerHTML = "";
const eintraege = [...a.abo.erhalteneTeddys].reverse();
eintraege.forEach((teddy) => {
// Aktueller, uebersetzter Produktname bevorzugt; der beim Einloesen gespeicherte Name
// ist nur die Rueckfallebene, falls das Produkt inzwischen umbenannt/entfernt wurde.
const produkt = getProduct(teddy.slug);
const name = produkt?.name[aboLang] ?? teddy.name;
const artLabel = teddy.art === "klein" ? aboLabels.teddyArtKlein : aboLabels.teddyArtGross;
const li = document.createElement("li");
li.className = "abo-erhalten-eintrag";
const bez = document.createElement("span");
bez.className = "abo-erhalten-name";
// Heisst das Produkt selbst schon "Kleiner Teddy", nicht "Kleiner Teddy: Kleiner Teddy"
// schreiben. Erst wenn VanVan echte Teddy-Namen hinterlegt, steht beides nebeneinander.
const nameGleichArt = name.trim().toLowerCase() === artLabel.trim().toLowerCase();
bez.textContent = name && !nameGleichArt ? `${artLabel}: ${name}` : (name || artLabel);
li.appendChild(bez);
if (teddy.datum) {
const dat = document.createElement("span");
dat.className = "abo-erhalten-datum";
const [j, m, tg] = teddy.datum.split("-");
dat.textContent = aboLabels.praemienAmTemplate.replace("{datum}", `${tg}.${m}.${j}`);
li.appendChild(dat);
}
// Direkt zum Produkt springen, damit man sofort nachsehen kann, welcher Teddy das war.
if (produkt) {
const link = document.createElement("a");
link.className = "abo-erhalten-link";
link.href = `${aboLang === "de" ? "" : "/" + aboLang}/produkt/${teddy.slug}/`;
link.textContent = aboLabels.praemienAnsehen;
li.appendChild(link);
}
erhaltenListe.appendChild(li);
});
// Aeltere Konten kennen die namentliche Liste noch nicht: fehlende Eintraege werden
// ehrlich ohne Namen ergaenzt, statt sie einfach zu verschweigen.
const fehlend = gesamtEingeloest - eintraege.length;
for (let i = 0; i < fehlend; i++) {
const li = document.createElement("li");
li.className = "abo-erhalten-eintrag abo-erhalten-eintrag-unbekannt";
li.textContent = aboLabels.praemienUnbekannt;
erhaltenListe.appendChild(li);
}
}
const gekuendigtHinweis = document.getElementById("abo-gekuendigt-hinweis");
if (gekuendigtHinweis) {
@@ -1096,8 +1148,12 @@ const angekommeneBestellungen = beispielBestellungen.filter((b) => b.status ===
btn.addEventListener("click", () => {
const art = btn.dataset.einloesen as "klein" | "gross" | undefined;
if (!art) return;
teddyEinloesen(art);
fuegeTeddyGratisHinzu(art);
// Erst pruefen, ob ueberhaupt eine Praemie offen ist — sonst landete der Teddy im
// Warenkorb, ohne dass er im Konto als eingeloest gezaehlt wurde (waere gratis doppelt).
const offen = aboStatus(getAccount());
if ((art === "klein" ? offen.kleinVerfuegbar : offen.grossVerfuegbar) <= 0) return;
const teddy = fuegeTeddyGratisHinzu(art);
teddyEinloesen(art, teddy);
const hinweis = document.getElementById("abo-eingeloest-hinweis");
if (hinweis) {
hinweis.style.display = "block";