diff --git a/public/admin/config.yml b/public/admin/config.yml
index e634d86..0db4062 100644
--- a/public/admin/config.yml
+++ b/public/admin/config.yml
@@ -348,3 +348,57 @@ collections:
- { label: IBAN, name: iban, widget: string, required: false, hint: "z.B. DE12 3456 7890 1234 5678 90" }
- { label: BIC, name: bic, widget: string, required: false }
- { label: Bank (Name), name: bank, widget: string, required: false }
+
+ - name: abo-einstellungen
+ label: "đ Abo-System"
+ icon: card_membership
+ files:
+ - name: einstellungen
+ label: "Abo-Stufen, Rabatte & Regeln"
+ file: src/content/abo-einstellungen.json
+ description: >
+ Preise, Rabatthöhen und Verhaltensregeln fĂŒr das monatliche Abo-System (siehe
+ scripts/account.ts + data/abo.ts). Ănderungen gelten ab dem nĂ€chsten Deploy fĂŒr alle
+ Kund:innen. Die eigentlichen Kundendaten (wer welches Abo hat, Zahlungsstand,
+ freigeschaltete PrÀmien) liegen NICHT hier, sondern pro Kundenkonto (Phase 1: im
+ Browser der jeweiligen Person, Phase 2: in einer echten Datenbank) â hier werden nur
+ die grundsÀtzlichen Konditionen festgelegt, zu denen JEDES Abo lÀuft.
+ fields:
+ - label: "Kleines Abo"
+ name: klein
+ widget: object
+ fields:
+ - { label: "Preis pro Monat (âŹ)", name: preis, widget: number, value_type: float, step: 0.01 }
+ - { label: "Rabatt auf jede Bestellung (%)", name: rabattProzent, widget: number, value_type: int, min: 0, max: 100 }
+ - label: "Mittleres Abo"
+ name: mittel
+ widget: object
+ fields:
+ - { label: "Preis pro Monat (âŹ)", name: preis, widget: number, value_type: float, step: 0.01 }
+ - { label: "Rabatt auf jede Bestellung (%)", name: rabattProzent, widget: number, value_type: int, min: 0, max: 100 }
+ - label: "GroĂes Abo"
+ name: gross
+ widget: object
+ fields:
+ - { label: "Preis pro Monat (âŹ)", name: preis, widget: number, value_type: float, step: 0.01 }
+ - { label: "Rabatt auf jede Bestellung (%)", name: rabattProzent, widget: number, value_type: int, min: 0, max: 100 }
+ - label: "Abo-Rabatt mit anderen Rabatten kombinierbar (Gutschein/Partnercode/Treuebonus)?"
+ name: kombinierbarMitAnderenRabatten
+ widget: boolean
+ default: false
+ hint: "Aus: Bei aktivem Abo gilt NUR der Abo-Rabatt, andere Rabatte werden fĂŒr diese Bestellung ignoriert. An: alle Rabatte werden zusammengezĂ€hlt."
+ - label: "Versand bei Teddy-PrÀmie ebenfalls kostenlos?"
+ name: versandKostenlosBeiPraemie
+ widget: boolean
+ default: false
+ hint: "Aus: FĂŒr den kostenlosen Teddy gelten die normalen Versandregeln des Shops."
+ - label: "Bei Wiederanmeldung nach vollstÀndigem Auslaufen: bisherige Laufzeit fortsetzen?"
+ name: fortsetzungBeiWiederanmeldung
+ widget: boolean
+ default: false
+ hint: "Aus: Der MonatszĂ€hler fĂŒr die nĂ€chste PrĂ€mie beginnt bei einer Wiederanmeldung wieder bei 0. An: er lĂ€uft dort weiter, wo er beim Auslaufen stand. Bereits eingelöste/freigeschaltete Teddys gehen NIE verloren, unabhĂ€ngig von dieser Einstellung."
+ - label: "Monate aus verschiedenen Abo-Stufen beim Wechsel zusammenzÀhlen?"
+ name: monateUeberStufenZusammenzaehlen
+ widget: boolean
+ default: false
+ hint: "Aus (empfohlen): Beim Wechsel in eine andere Stufe beginnt der MonatszĂ€hler fĂŒr die nĂ€chste PrĂ€mie bei 0. An: die bisher gesammelten Monate werden in die neue Stufe ĂŒbernommen."
diff --git a/src/content/abo-einstellungen.json b/src/content/abo-einstellungen.json
new file mode 100644
index 0000000..56f668a
--- /dev/null
+++ b/src/content/abo-einstellungen.json
@@ -0,0 +1,9 @@
+{
+ "klein": { "preis": 4.99, "rabattProzent": 5 },
+ "mittel": { "preis": 9.99, "rabattProzent": 10 },
+ "gross": { "preis": 19.99, "rabattProzent": 20 },
+ "kombinierbarMitAnderenRabatten": false,
+ "versandKostenlosBeiPraemie": false,
+ "fortsetzungBeiWiederanmeldung": false,
+ "monateUeberStufenZusammenzaehlen": false
+}
diff --git a/src/content/products/grosser-teddy.json b/src/content/products/grosser-teddy.json
new file mode 100644
index 0000000..d2591c6
--- /dev/null
+++ b/src/content/products/grosser-teddy.json
@@ -0,0 +1,26 @@
+{
+ "slug": "grosser-teddy",
+ "name": {
+ "de": "GroĂer Teddy",
+ "en": "Large Teddy",
+ "ch": "Grosse Teddy",
+ "fr": "Grand ours en peluche"
+ },
+ "artikelnummer": "PRAEMIE-TEDDY-GROSS",
+ "kategorie": "diy-plushies",
+ "preis": 24.9,
+ "bestand": 999,
+ "beschreibung": {
+ "de": "Unser handgemachter groĂer Teddy â als Dankeschön-PrĂ€mie im Abo-System kostenlos einlösbar, sobald du den passenden Meilenstein erreicht hast.",
+ "en": "Our handmade large teddy â redeemable for free as a subscription reward once you reach the matching milestone.",
+ "ch": "Ăise vo Hang gmachti grossi Teddy â als Dankeschön-PrĂ€mie im Abo-System gratis ilösbar, sobald du dr passendi Meilestei erreicht hesch.",
+ "fr": "Notre grand ours en peluche fait main â Ă Ă©changer gratuitement comme rĂ©compense d'abonnement une fois le palier atteint."
+ },
+ "material": "Baumwollstoff, FĂŒllwatte OEKO-TEX",
+ "groesse": "ca. 30 cm",
+ "lieferzeit": "2â4 Werktage",
+ "badges": [
+ "handgemacht"
+ ],
+ "bilder": []
+}
diff --git a/src/content/products/kleiner-teddy.json b/src/content/products/kleiner-teddy.json
new file mode 100644
index 0000000..0fac6dd
--- /dev/null
+++ b/src/content/products/kleiner-teddy.json
@@ -0,0 +1,26 @@
+{
+ "slug": "kleiner-teddy",
+ "name": {
+ "de": "Kleiner Teddy",
+ "en": "Small Teddy",
+ "ch": "Chline Teddy",
+ "fr": "Petit ours en peluche"
+ },
+ "artikelnummer": "PRAEMIE-TEDDY-KLEIN",
+ "kategorie": "diy-plushies",
+ "preis": 12.9,
+ "bestand": 999,
+ "beschreibung": {
+ "de": "Unser handgemachter kleiner Teddy â als Dankeschön-PrĂ€mie im Abo-System kostenlos einlösbar, sobald du den passenden Meilenstein erreicht hast.",
+ "en": "Our handmade small teddy â redeemable for free as a subscription reward once you reach the matching milestone.",
+ "ch": "Ăise vo Hang gmachti chlini Teddy â als Dankeschön-PrĂ€mie im Abo-System gratis ilösbar, sobald du dr passendi Meilestei erreicht hesch.",
+ "fr": "Notre petit ours en peluche fait main â Ă Ă©changer gratuitement comme rĂ©compense d'abonnement une fois le palier atteint."
+ },
+ "material": "Baumwollstoff, FĂŒllwatte OEKO-TEX",
+ "groesse": "ca. 16 cm",
+ "lieferzeit": "2â4 Werktage",
+ "badges": [
+ "handgemacht"
+ ],
+ "bilder": []
+}
diff --git a/src/data/abo.ts b/src/data/abo.ts
new file mode 100644
index 0000000..6d9501d
--- /dev/null
+++ b/src/data/abo.ts
@@ -0,0 +1,85 @@
+// Abo-System: Preise/Rabatte/Verhaltensregeln kommen aus dem Adminbereich (Decap CMS, siehe
+// public/admin/config.yml â "đ Abo-System" â src/content/abo-einstellungen.json). Reine,
+// zustandslose Berechnungsfunktionen â der eigentliche Konto-Zustand (welches Abo, wie viele
+// bezahlte Monate, freigeschaltete PrÀmien) lebt in scripts/account.ts.
+
+// @ts-ignore -- JSON-Import, zur Build-Zeit von Astro/Vite aufgelöst
+import raw from "../content/abo-einstellungen.json";
+
+export type AboStufe = "klein" | "mittel" | "gross";
+
+export interface AboStufenKonfig {
+ preis: number;
+ rabattProzent: number;
+}
+
+export interface AboEinstellungen {
+ klein: AboStufenKonfig;
+ mittel: AboStufenKonfig;
+ gross: AboStufenKonfig;
+ kombinierbarMitAnderenRabatten: boolean;
+ versandKostenlosBeiPraemie: boolean;
+ fortsetzungBeiWiederanmeldung: boolean;
+ monateUeberStufenZusammenzaehlen: boolean;
+}
+
+export const aboEinstellungen = raw as AboEinstellungen;
+
+export function aboStufenKonfig(stufe: AboStufe): AboStufenKonfig {
+ return aboEinstellungen[stufe];
+}
+
+export const ABO_STUFEN: AboStufe[] = ["klein", "mittel", "gross"];
+
+/** Wie viele Teddy-PrÀmien welcher Art bei X durchgehend bezahlten Monaten in dieser Stufe
+ * INSGESAMT freigeschaltet sein mĂŒssten (kumulativ, nicht nur "neu diesen Monat"):
+ * - Klein-Abo: 1 kleiner Teddy pro volles Jahr.
+ * - Mittel-Abo: 1 groĂer Teddy pro volles Jahr.
+ * - GroĂ-Abo: 1 kleiner Teddy alle 6 Monate UND zusĂ€tzlich 1 groĂer Teddy pro volles Jahr
+ * (nach 6 Monaten: 1 klein · nach 12: 2 klein + 1 groà · nach 18: 3 klein · nach 24: 4 klein + 2 groĂ). */
+export function teddyMeilensteine(stufe: AboStufe, monate: number): { klein: number; gross: number } {
+ if (monate <= 0) return { klein: 0, gross: 0 };
+ if (stufe === "klein") return { klein: Math.floor(monate / 12), gross: 0 };
+ if (stufe === "mittel") return { klein: 0, gross: Math.floor(monate / 12) };
+ return { klein: Math.floor(monate / 6), gross: Math.floor(monate / 12) };
+}
+
+/** Wie viele Monate fehlen noch bis zum jeweils nĂ€chsten Meilenstein (fĂŒr die
+ * Fortschrittsanzeige im Kundenkonto), null wenn diese Stufe die PrÀmienart gar nicht kennt. */
+export function naechsteMeilensteine(stufe: AboStufe, monate: number): { klein: number | null; gross: number | null } {
+ const kleinIntervall = stufe === "gross" ? 6 : stufe === "klein" ? 12 : null;
+ const grossIntervall = stufe === "klein" ? null : 12;
+ return {
+ klein: kleinIntervall ? kleinIntervall - (monate % kleinIntervall) : null,
+ gross: grossIntervall ? grossIntervall - (monate % grossIntervall) : null,
+ };
+}
+
+/** Ein Abo ist aktiv, solange der aktuell bezahlte Abrechnungszeitraum noch nicht abgelaufen
+ * ist â reiner Datumsvergleich zur echten, aktuellen Uhrzeit (lĂ€uft also automatisch ab, ganz
+ * ohne Cronjob/Backend), genau wie befristete Produkt-Rabatte (siehe data/rabatt.ts). Gilt
+ * bewusst UNABHĂNGIG davon, ob das Abo schon gekĂŒndigt wurde â gekĂŒndigte Abos behalten ihre
+ * Vorteile bis zum Ende der bezahlten Laufzeit. */
+export function aboAktuellAktiv(bezahltBisDatum: string | null): boolean {
+ if (!bezahltBisDatum) return false;
+ return new Date() <= new Date(`${bezahltBisDatum}T23:59:59`);
+}
+
+/** Heutiges Datum als lokales Kalenderdatum (NICHT ĂŒber toISOString(), das auf UTC umrechnet und
+ * in Zeitzonen östlich von UTC nachts kurzzeitig das falsche â gestrige â Datum liefern wĂŒrde). */
+export function heutigesDatumISO(): string {
+ const heute = new Date();
+ const jahr = heute.getFullYear();
+ const monat = String(heute.getMonth() + 1).padStart(2, "0");
+ const tag = String(heute.getDate()).padStart(2, "0");
+ return `${jahr}-${monat}-${tag}`;
+}
+
+/** Rechnet rein kalendarisch in UTC (bewusst NICHT ĂŒber lokale Zeit + toISOString() gemischt â
+ * das wĂŒrde je nach Zeitzone des GerĂ€ts bei jedem Aufruf einen Tag "verlieren" und sich ĂŒber
+ * viele Monate hinweg zu einem spĂŒrbaren Datumsfehler aufsummieren; mit reinem UTC-Rechnen ist
+ * das Ergebnis unabhÀngig von der Zeitzone des Kunden immer exakt). */
+export function addMonateISO(datumISO: string, monate: number): string {
+ const [jahr, monat, tag] = datumISO.split("-").map(Number);
+ return new Date(Date.UTC(jahr, monat - 1 + monate, tag)).toISOString().slice(0, 10);
+}
diff --git a/src/i18n/ui.ts b/src/i18n/ui.ts
index 3650954..ed0d281 100644
--- a/src/i18n/ui.ts
+++ b/src/i18n/ui.ts
@@ -180,6 +180,8 @@ export const ui = {
loyaltyBannerText: "WÀhle unten den Artikel aus, auf den du 20 % Rabatt erhÀltst.",
loyaltySelectLabel: "FĂŒr 20 % Treuebonus auswĂ€hlen",
loyaltySelectedLabel: "đ -20 % Treuebonus angewendet",
+ gratisPraemie: "Gratis-PrÀmie aus deinem Abo",
+ aboDiscount: "đ« Abo-Rabatt",
},
checkout: {
eyebrow: "Checkout", title: "Bestellung abschlieĂen",
@@ -238,6 +240,49 @@ export const ui = {
loyaltyUnlockedText: "Du hast zehn Bestellungen abgeschlossen und erhÀltst bei deiner nÀchsten Bestellung 20 % Rabatt auf einen Artikel deiner Wahl.",
loyaltyGoToCart: "Artikel im Warenkorb auswĂ€hlen â",
loyaltyExplainer: "Es zÀhlen nur vollstÀndig abgeschlossene und bezahlte Bestellungen. Nach der Einlösung beginnt dein Fortschritt wieder bei null.",
+ statAbo: "Mein Abo",
+ aboHeaderBtn: "đ« Mein Abo verwalten",
+ aboTitle: "đ« Mein Abo",
+ aboIntro: "Sichere dir dauerhaften Rabatt auf jede Bestellung und hol dir kostenlose Teddys als Dankeschön â automatisch, jeden Monat.",
+ aboNameKlein: "Kleines Abo", aboNameMittel: "Mittleres Abo", aboNameGross: "GroĂes Abo",
+ aboPreisSuffix: "/ Monat",
+ aboVorteilKlein: "5 % Rabatt auf jede Bestellung. Nach jedem vollen Abo-Jahr: 1 kleiner Teddy gratis.",
+ aboVorteilMittel: "10 % Rabatt auf jede Bestellung. Nach jedem vollen Abo-Jahr: 1 groĂer Teddy gratis.",
+ aboVorteilGross: "20 % Rabatt auf jede Bestellung. Alle 6 Monate ein kleiner Teddy, nach jedem vollen Jahr zusĂ€tzlich ein groĂer Teddy.",
+ aboAbschliessenBtn: "Abo abschlieĂen",
+ aboAktivesLabel: "â Dein aktuelles Abo",
+ aboWechselnBtn: "Zu diesem Abo wechseln",
+ aboStatusTitle: "Dein Abo-Status",
+ aboFieldStufe: "Abo-Stufe", aboFieldPreis: "Monatlicher Preis", aboFieldRabatt: "Enthaltener Rabatt",
+ aboFieldStart: "Startdatum", aboFieldNaechsteZahlung: "NĂ€chste Zahlung", aboFieldLaufzeit: "Bisherige Laufzeit",
+ aboMonateSuffix: "Monate",
+ aboFortschrittKleinTemplate: "𧞠Noch {n} Monat(e) bis zum nÀchsten kleinen Teddy",
+ aboFortschrittGrossTemplate: "đ§ž Noch {n} Monat(e) bis zum nĂ€chsten groĂen Teddy",
+ aboPraemienErhaltenTemplate: "Bereits erhalten: {klein}Ă kleiner Teddy, {gross}Ă groĂer Teddy",
+ aboPraemienVerfuegbarTitle: "đ VerfĂŒgbare PrĂ€mien",
+ aboKeinePraemienVerfuegbar: "Aktuell keine PrĂ€mie zum Einlösen verfĂŒgbar.",
+ aboEinloesenBtn: "Jetzt einlösen",
+ aboEinloesenKleinLabel: "Kleiner Teddy", aboEinloesenGrossLabel: "GroĂer Teddy",
+ aboEingeloestHinweis: "đ§ž In den Warenkorb gelegt!",
+ aboZahlungSimBtn: "Monatszahlung simulieren (Demo)",
+ aboZahlungSimHinweis: "Phase 1: Es gibt noch keine echte wiederkehrende Zahlung im Hintergrund. Mit diesem Knopf testest du, was bei der nÀchsten erfolgreichen Monatsabbuchung passiert.",
+ aboKuendigenBtn: "Abo kĂŒndigen",
+ aboKuendigenConfirm: "Abo wirklich kĂŒndigen? Deine Vorteile bleiben bis zum Ende der bezahlten Laufzeit aktiv.",
+ aboGekuendigtHinweisTemplate: "GekĂŒndigt am {datum}. Deine Vorteile bleiben bis zum Ende der bezahlten Laufzeit aktiv, danach endet dein Abo automatisch.",
+ aboWechselTitle: "Zu einem anderen Abo wechseln",
+ aboBenachrichtigungenTitle: "đ Benachrichtigungen",
+ aboKeineBenachrichtigungen: "Noch keine Benachrichtigungen.",
+ aboNichtAktivBadge: "âž Rabatt pausiert",
+ aboExplainer: "Alle Angaben werden aktuell sicher auf diesem GerĂ€t gespeichert (Phase 1). Eine gerĂ€teĂŒbergreifende Datenbank folgt mit der echten Zahlungsanbindung in Phase 2.",
+ notifAboAbgeschlossen: "Dein Abo wurde erfolgreich abgeschlossen â willkommen! đ",
+ notifAboGewechselt: "Du hast erfolgreich in ein anderes Abo gewechselt ({stufe}).",
+ notifAboZahlungErfolgreich: "Deine monatliche Abo-Zahlung war erfolgreich. â
",
+ notifAboTeddyKleinFrei: "𧞠Neue PrÀmie freigeschaltet: ein kleiner Teddy wartet auf dich!",
+ notifAboTeddyGrossFrei: "đ§ž Neue PrĂ€mie freigeschaltet: ein groĂer Teddy wartet auf dich!",
+ notifAboBaldPraemie: "đ§ž Fast geschafft â nĂ€chsten Monat wartet deine nĂ€chste Teddy-PrĂ€mie!",
+ notifAboGekuendigt: "Du hast dein Abo gekĂŒndigt. Deine Vorteile bleiben bis zum Ende der bezahlten Laufzeit aktiv.",
+ notifAboTeddyKleinEingeloest: "đ§ž Kleiner Teddy eingelöst â er liegt jetzt kostenlos in deinem Warenkorb.",
+ notifAboTeddyGrossEingeloest: "đ§ž GroĂer Teddy eingelöst â er liegt jetzt kostenlos in deinem Warenkorb.",
noOpenOrders: "Aktuell keine offenen Sendungen â alle Bestellungen sind schon angekommen. đ",
noArrivedOrders: "Noch keine angekommenen Bestellungen â hier erscheinen deine Bestellungen, sobald sie geliefert wurden.",
ordersTitle: "đŠ Meine Bestellungen",
@@ -431,6 +476,8 @@ export const ui = {
loyaltyBannerText: "Pick the item below that you'd like 20% off.",
loyaltySelectLabel: "Select for 20% loyalty reward",
loyaltySelectedLabel: "đ -20% loyalty reward applied",
+ gratisPraemie: "Free reward from your subscription",
+ aboDiscount: "đ« Subscription discount",
},
checkout: {
eyebrow: "Checkout", title: "Complete your order",
@@ -489,6 +536,49 @@ export const ui = {
loyaltyUnlockedText: "You've completed ten orders and get 20% off an item of your choice on your next order.",
loyaltyGoToCart: "Choose item in cart â",
loyaltyExplainer: "Only fully completed and paid orders count. After redemption your progress starts again from zero.",
+ statAbo: "My Subscription",
+ aboHeaderBtn: "đ« Manage my subscription",
+ aboTitle: "đ« My Subscription",
+ aboIntro: "Get a permanent discount on every order and free teddies as a thank-you â automatically, every month.",
+ aboNameKlein: "Small plan", aboNameMittel: "Medium plan", aboNameGross: "Large plan",
+ aboPreisSuffix: "/ month",
+ aboVorteilKlein: "5% off every order. After each full subscription year: 1 small teddy for free.",
+ aboVorteilMittel: "10% off every order. After each full subscription year: 1 large teddy for free.",
+ aboVorteilGross: "20% off every order. A small teddy every 6 months, plus a large teddy after every full year.",
+ aboAbschliessenBtn: "Subscribe",
+ aboAktivesLabel: "â Your current plan",
+ aboWechselnBtn: "Switch to this plan",
+ aboStatusTitle: "Your subscription status",
+ aboFieldStufe: "Plan", aboFieldPreis: "Monthly price", aboFieldRabatt: "Included discount",
+ aboFieldStart: "Start date", aboFieldNaechsteZahlung: "Next payment", aboFieldLaufzeit: "Duration so far",
+ aboMonateSuffix: "months",
+ aboFortschrittKleinTemplate: "đ§ž {n} more month(s) until your next small teddy",
+ aboFortschrittGrossTemplate: "đ§ž {n} more month(s) until your next large teddy",
+ aboPraemienErhaltenTemplate: "Already received: {klein}Ă small teddy, {gross}Ă large teddy",
+ aboPraemienVerfuegbarTitle: "đ Available rewards",
+ aboKeinePraemienVerfuegbar: "No reward available to redeem right now.",
+ aboEinloesenBtn: "Redeem now",
+ aboEinloesenKleinLabel: "Small teddy", aboEinloesenGrossLabel: "Large teddy",
+ aboEingeloestHinweis: "đ§ž Added to your cart!",
+ aboZahlungSimBtn: "Simulate monthly payment (demo)",
+ aboZahlungSimHinweis: "Phase 1: there is no real recurring payment running in the background yet. Use this button to test what happens on the next successful monthly payment.",
+ aboKuendigenBtn: "Cancel subscription",
+ aboKuendigenConfirm: "Really cancel your subscription? Your benefits stay active until the end of the paid period.",
+ aboGekuendigtHinweisTemplate: "Cancelled on {datum}. Your benefits stay active until the end of the paid period, then your subscription ends automatically.",
+ aboWechselTitle: "Switch to a different plan",
+ aboBenachrichtigungenTitle: "đ Notifications",
+ aboKeineBenachrichtigungen: "No notifications yet.",
+ aboNichtAktivBadge: "âž Discount paused",
+ aboExplainer: "All data is currently stored securely on this device (Phase 1). A cross-device database follows with real payment integration in Phase 2.",
+ notifAboAbgeschlossen: "Your subscription was successfully set up â welcome! đ",
+ notifAboGewechselt: "You successfully switched to a different plan ({stufe}).",
+ notifAboZahlungErfolgreich: "Your monthly subscription payment was successful. â
",
+ notifAboTeddyKleinFrei: "đ§ž New reward unlocked: a small teddy is waiting for you!",
+ notifAboTeddyGrossFrei: "đ§ž New reward unlocked: a large teddy is waiting for you!",
+ notifAboBaldPraemie: "đ§ž Almost there â your next teddy reward is waiting next month!",
+ notifAboGekuendigt: "You cancelled your subscription. Your benefits stay active until the end of the paid period.",
+ notifAboTeddyKleinEingeloest: "đ§ž Small teddy redeemed â it's now in your cart for free.",
+ notifAboTeddyGrossEingeloest: "đ§ž Large teddy redeemed â it's now in your cart for free.",
noOpenOrders: "No open shipments right now â every order has already arrived. đ",
noArrivedOrders: "No delivered orders yet â your orders will appear here once they've arrived.",
ordersTitle: "đŠ My orders",
@@ -682,6 +772,8 @@ export const ui = {
loyaltyBannerText: "WĂ€hl unde dr Artikel us, uf dĂ€ du 20 % Rabatt ĂŒbercho.",
loyaltySelectLabel: "FĂŒr 20 % Treuebonus uswĂ€hle",
loyaltySelectedLabel: "đ -20 % Treuebonus aagwĂ€ndet",
+ gratisPraemie: "GratisprÀmie us dim Abo",
+ aboDiscount: "đ« Abo-Rabatt",
},
checkout: {
eyebrow: "Checkout", title: "Bschtellig abschliesse",
@@ -740,6 +832,49 @@ export const ui = {
loyaltyUnlockedText: "Du hesch zĂ€h Bstellige abgschlosse und ĂŒbercho bi dinere nĂ€chschte Bstellig 20 % Rabatt uf en Artikel dinere Wahl.",
loyaltyGoToCart: "Artikel im Warenchorb uswĂ€hle â",
loyaltyExplainer: "Es zelle nume vollstÀndig abgschlosseni und bezahlti Bstellige. Nach dr Ilösig fangt din Fortschritt wieder bi null a.",
+ statAbo: "Mis Abo",
+ aboHeaderBtn: "đ« Mis Abo verwalte",
+ aboTitle: "đ« Mis Abo",
+ aboIntro: "Sicher dir en dauerhafte Rabatt uf jedi Bstellig und hol dir gratis Teddys als Dankeschön â automatisch, jede Monet.",
+ aboNameKlein: "Chliises Abo", aboNameMittel: "Mittleres Abo", aboNameGross: "Grosses Abo",
+ aboPreisSuffix: "/ Monet",
+ aboVorteilKlein: "5 % Rabatt uf jedi Bstellig. Nach jedem volle Abo-Jahr: 1 chliine Teddy gratis.",
+ aboVorteilMittel: "10 % Rabatt uf jedi Bstellig. Nach jedem volle Abo-Jahr: 1 grosse Teddy gratis.",
+ aboVorteilGross: "20 % Rabatt uf jedi Bstellig. Alli 6 Monet en chliine Teddy, nach jedem volle Jahr zuesÀtzlich en grosse Teddy.",
+ aboAbschliessenBtn: "Abo abschliesse",
+ aboAktivesLabel: "â Dis aktuells Abo",
+ aboWechselnBtn: "Zu dem Abo wechsle",
+ aboStatusTitle: "Din Abo-Status",
+ aboFieldStufe: "Abo-Stufe", aboFieldPreis: "Monetliche Priis", aboFieldRabatt: "Enthaltene Rabatt",
+ aboFieldStart: "Startdatum", aboFieldNaechsteZahlung: "NĂ€chschti Zahlig", aboFieldLaufzeit: "Bisherigi Laufziit",
+ aboMonateSuffix: "Monet",
+ aboFortschrittKleinTemplate: "𧞠No {n} Monet bis zum nÀchschte chliine Teddy",
+ aboFortschrittGrossTemplate: "𧞠No {n} Monet bis zum nÀchschte grosse Teddy",
+ aboPraemienErhaltenTemplate: "Scho erhalte: {klein}Ă chliine Teddy, {gross}Ă grosse Teddy",
+ aboPraemienVerfuegbarTitle: "đ VerfĂŒegbari PrĂ€mie",
+ aboKeinePraemienVerfuegbar: "Momentan kei PrĂ€mie zum Ilöse verfĂŒegbar.",
+ aboEinloesenBtn: "Jetzt ilöse",
+ aboEinloesenKleinLabel: "Chliine Teddy", aboEinloesenGrossLabel: "Grosse Teddy",
+ aboEingeloestHinweis: "đ§ž In Warechorb gleit!",
+ aboZahlungSimBtn: "Monetszahlig simuliere (Demo)",
+ aboZahlungSimHinweis: "Phase 1: Es git no kei echti wiederkehrendi Zahlig im Hintergrund. Mit dem Chnopf teschtisch, was bi dr nÀchschte erfolgriiche Monetsabbuechig passiert.",
+ aboKuendigenBtn: "Abo kĂŒndige",
+ aboKuendigenConfirm: "Abo wĂŒrklich kĂŒndige? Dini Vorteil bliibed bis am Ăndi vo dr bezahlte Laufziit aktiv.",
+ aboGekuendigtHinweisTemplate: "KĂŒndet am {datum}. Dini Vorteil bliibed bis am Ăndi vo dr bezahlte Laufziit aktiv, dernah Ă€ndet dis Abo automatisch.",
+ aboWechselTitle: "Zu emene andere Abo wechsle",
+ aboBenachrichtigungenTitle: "đ Benachrichtigunge",
+ aboKeineBenachrichtigungen: "No kei Benachrichtigunge.",
+ aboNichtAktivBadge: "âž Rabatt pausiert",
+ aboExplainer: "Alli Aagabe werded aktuell sicher uf dem GerĂ€t gspeicheret (Phase 1). Ă gerĂ€teĂŒbergriifendi Datebank chunt mit dr echte Zahligs-Aabindig i Phase 2.",
+ notifAboAbgeschlossen: "Dis Abo isch erfolgriich abgschlosse worde â willkomme! đ",
+ notifAboGewechselt: "Du bisch erfolgriich in es anders Abo gwechslet ({stufe}).",
+ notifAboZahlungErfolgreich: "Dini monetlichi Abo-Zahlig isch erfolgriich gsi. â
",
+ notifAboTeddyKleinFrei: "𧞠Nöii PrÀmie freigschaltet: en chliine Teddy wartet uf dich!",
+ notifAboTeddyGrossFrei: "𧞠Nöii PrÀmie freigschaltet: en grosse Teddy wartet uf dich!",
+ notifAboBaldPraemie: "đ§ž Fasch gschafft â nĂ€chschte Monet wartet dini nĂ€chschti Teddy-PrĂ€mie!",
+ notifAboGekuendigt: "Du hesch dis Abo kĂŒndet. Dini Vorteil bliibed bis am Ăndi vo dr bezahlte Laufziit aktiv.",
+ notifAboTeddyKleinEingeloest: "đ§ž Chliine Teddy ilöst â er liit jetzt gratis in dim Warechorb.",
+ notifAboTeddyGrossEingeloest: "đ§ž Grosse Teddy ilöst â er liit jetzt gratis in dim Warechorb.",
noOpenOrders: "Momentan kei offni SĂ€ndige â alli Bstellige sind scho aacho. đ",
noArrivedOrders: "No kei aacho Bstellige â da erschine dini Bstellige, sobald sie glifert worde sind.",
ordersTitle: "đŠ Mini Bstellige",
@@ -933,6 +1068,8 @@ export const ui = {
loyaltyBannerText: "Choisissez ci-dessous l'article sur lequel vous voulez -20 %.",
loyaltySelectLabel: "Choisir pour la récompense fidélité de 20 %",
loyaltySelectedLabel: "đ RĂ©compense fidĂ©litĂ© de -20 % appliquĂ©e",
+ gratisPraemie: "Récompense gratuite de votre abonnement",
+ aboDiscount: "đ« Remise d'abonnement",
},
checkout: {
eyebrow: "Paiement", title: "Finaliser la commande",
@@ -991,6 +1128,49 @@ export const ui = {
loyaltyUnlockedText: "Vous avez validé dix commandes et bénéficiez de 20 % de réduction sur l'article de votre choix lors de votre prochaine commande.",
loyaltyGoToCart: "Choisir l'article dans le panier â",
loyaltyExplainer: "Seules les commandes entiÚrement finalisées et payées comptent. AprÚs utilisation, votre progression repart de zéro.",
+ statAbo: "Mon abonnement",
+ aboHeaderBtn: "đ« GĂ©rer mon abonnement",
+ aboTitle: "đ« Mon abonnement",
+ aboIntro: "Profitez d'une remise permanente sur chaque commande et d'oursons en peluche gratuits en cadeau â automatiquement, chaque mois.",
+ aboNameKlein: "Petit abonnement", aboNameMittel: "Abonnement moyen", aboNameGross: "Grand abonnement",
+ aboPreisSuffix: "/ mois",
+ aboVorteilKlein: "5 % de remise sur chaque commande. AprÚs chaque année d'abonnement complÚte : 1 petit ours en peluche offert.",
+ aboVorteilMittel: "10 % de remise sur chaque commande. AprÚs chaque année d'abonnement complÚte : 1 grand ours en peluche offert.",
+ aboVorteilGross: "20 % de remise sur chaque commande. Un petit ours tous les 6 mois, et un grand ours en plus aprÚs chaque année complÚte.",
+ aboAbschliessenBtn: "S'abonner",
+ aboAktivesLabel: "â Votre abonnement actuel",
+ aboWechselnBtn: "Passer Ă cet abonnement",
+ aboStatusTitle: "Statut de votre abonnement",
+ aboFieldStufe: "Formule", aboFieldPreis: "Prix mensuel", aboFieldRabatt: "Remise incluse",
+ aboFieldStart: "Date de début", aboFieldNaechsteZahlung: "Prochain paiement", aboFieldLaufzeit: "Durée jusqu'ici",
+ aboMonateSuffix: "mois",
+ aboFortschrittKleinTemplate: "đ§ž Encore {n} mois avant votre prochain petit ours",
+ aboFortschrittGrossTemplate: "đ§ž Encore {n} mois avant votre prochain grand ours",
+ aboPraemienErhaltenTemplate: "Déjà reçus : {klein}à petit ours, {gross}à grand ours",
+ aboPraemienVerfuegbarTitle: "đ RĂ©compenses disponibles",
+ aboKeinePraemienVerfuegbar: "Aucune récompense à échanger pour le moment.",
+ aboEinloesenBtn: "Ăchanger maintenant",
+ aboEinloesenKleinLabel: "Petit ours", aboEinloesenGrossLabel: "Grand ours",
+ aboEingeloestHinweis: "𧞠Ajouté à votre panier !",
+ aboZahlungSimBtn: "Simuler le paiement mensuel (démo)",
+ aboZahlungSimHinweis: "Phase 1 : il n'y a pas encore de vrai paiement récurrent en arriÚre-plan. Ce bouton permet de tester ce qui se passe lors du prochain paiement mensuel réussi.",
+ aboKuendigenBtn: "Résilier l'abonnement",
+ aboKuendigenConfirm: "Résilier vraiment l'abonnement ? Vos avantages restent actifs jusqu'à la fin de la période payée.",
+ aboGekuendigtHinweisTemplate: "Résilié le {datum}. Vos avantages restent actifs jusqu'à la fin de la période payée, puis votre abonnement se termine automatiquement.",
+ aboWechselTitle: "Passer Ă une autre formule",
+ aboBenachrichtigungenTitle: "đ Notifications",
+ aboKeineBenachrichtigungen: "Pas encore de notifications.",
+ aboNichtAktivBadge: "âž Remise suspendue",
+ aboExplainer: "Toutes les données sont actuellement stockées en sécurité sur cet appareil (Phase 1). Une base de données multi-appareils suivra avec le vrai paiement en Phase 2.",
+ notifAboAbgeschlossen: "Votre abonnement a Ă©tĂ© souscrit avec succĂšs â bienvenue ! đ",
+ notifAboGewechselt: "Vous ĂȘtes passĂ©(e) avec succĂšs Ă un autre abonnement ({stufe}).",
+ notifAboZahlungErfolgreich: "Votre paiement mensuel d'abonnement a Ă©tĂ© effectuĂ© avec succĂšs. â
",
+ notifAboTeddyKleinFrei: "𧞠Nouvelle récompense débloquée : un petit ours vous attend !",
+ notifAboTeddyGrossFrei: "𧞠Nouvelle récompense débloquée : un grand ours vous attend !",
+ notifAboBaldPraemie: "đ§ž Presque au but â votre prochaine rĂ©compense en peluche arrive le mois prochain !",
+ notifAboGekuendigt: "Vous avez résilié votre abonnement. Vos avantages restent actifs jusqu'à la fin de la période payée.",
+ notifAboTeddyKleinEingeloest: "đ§ž Petit ours Ă©changĂ© â il est maintenant gratuit dans votre panier.",
+ notifAboTeddyGrossEingeloest: "đ§ž Grand ours Ă©changĂ© â il est maintenant gratuit dans votre panier.",
noOpenOrders: "Aucun envoi en cours pour le moment â toutes les commandes sont dĂ©jĂ arrivĂ©es. đ",
noArrivedOrders: "Aucune commande livrĂ©e pour le moment â vos commandes apparaĂźtront ici dĂšs qu'elles seront arrivĂ©es.",
ordersTitle: "đŠ Mes commandes",
diff --git a/src/pages/ch/checkout/index.astro b/src/pages/ch/checkout/index.astro
index d57fcc9..856a614 100644
--- a/src/pages/ch/checkout/index.astro
+++ b/src/pages/ch/checkout/index.astro
@@ -173,20 +173,19 @@ const t = useTranslations(lang);
-