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); -