feat: Bienenpatenschaft mit Urkunde, Abo, Medaillen und 3D-Konto
Setzt Teilprojekte 1-5 der Spec 2026-10-16 um: - Urkunden-Engine (lib/certificate): ein Layout fuer PDF, Vorschau und 3D-Textur, Vorlage classic@1, eingebettete OFL-Schriften, Testmatrix - Einmal-Patenschaft ueber Traegerprodukte (Kategorie PATENSCHAFT), Paket wird im Checkout in Patenschaft (Regelsatz) und Honig aufgeteilt, Kontopflicht, rein digitale Bestellungen (FulfillmentMethod DIGITAL) - Ausstellung nach Zahlung idempotent, Wiederholung im App-Prozess (instrumentation + background-jobs), Ablage in CERTIFICATE_DIR - Verkaufsseite /patenschaft mit Konfigurator und Live-Vorschau, Warenkorb mit Schluessel je Position - Kundenkonto: 3D-Ansicht von Urkunde und Medaille, Downloads, ZIP, Uebertragung per befristetem Einmal-Link, Treuestufen bis VIP - Admin: Angebote, Patenschaften, Druck, Korrektur mit Revisionen, Abos, Erntefenster, Deckung, SEPA-Frist, Treuestufen - Abo ueber Stripe Billing: Lieferung erst nach bezahlten Monaten, SEPA-Neukunden-Frist und Rueckbuchungsschutz, Honigreservierung, Kuendigungsbutton, Monatsrechnungen, Stripe-Einrichtungsskript Startangebote werden inaktiv angelegt; Livebetrieb erst nach Freigabe. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
dcb578f062
commit
f227aeb8f9
269 files changed
+28054
-141
No files matched your search
@@ -0,0 +1,307 @@
|
||||
import type { Locale } from "@/i18n/config";
|
||||
import type { SubscriptionStatus } from "@/generated/prisma/client";
|
||||
|
||||
/**
|
||||
* Texte des Abos: Dankeseite nach dem Abschluss, Abo-Seite im Konto mit
|
||||
* Kuendigungsknopf (§ 312k BGB) und die oeffentliche Seite
|
||||
* /vertraege-kuendigen. Eigenes Modul wie die uebrigen Patenschaftstexte,
|
||||
* damit parallele Teile sich nicht in die Quere kommen. Ansprache: du.
|
||||
*
|
||||
* Die Beschriftungen "Verträge hier kündigen" und "Jetzt kündigen" sind vom
|
||||
* Gesetz vorgegeben (§ 312k Abs. 2 BGB) und duerfen nicht umformuliert werden.
|
||||
*/
|
||||
export interface AboStrings {
|
||||
footerLink: string;
|
||||
status: Record<SubscriptionStatus, string>;
|
||||
thanks: {
|
||||
metaTitle: string;
|
||||
activeTitle: string;
|
||||
activeText: string;
|
||||
processingTitle: string;
|
||||
processingText: string;
|
||||
notCompletedTitle: string;
|
||||
notCompletedText: string;
|
||||
toSubscription: string;
|
||||
toAccount: string;
|
||||
backToOffer: string;
|
||||
};
|
||||
detail: {
|
||||
metaTitle: string;
|
||||
back: string;
|
||||
title: (offer: string) => string;
|
||||
beeLine: (bee: string) => string;
|
||||
contractNumber: string;
|
||||
statusLabel: string;
|
||||
monthlyPrice: string;
|
||||
nextCharge: string;
|
||||
endsOn: string;
|
||||
paidMonths: string;
|
||||
progressTitle: string;
|
||||
progress: (paid: number, required: number) => string;
|
||||
progressHarvest: (paid: number, required: number) => string;
|
||||
sepaHoldNote: string;
|
||||
deliveriesTitle: string;
|
||||
deliveriesEmpty: string;
|
||||
deliveryPrepared: (date: string, jars: number) => string;
|
||||
deliveryDeferred: (date: string) => string;
|
||||
delinquentNote: string;
|
||||
paymentTitle: string;
|
||||
paymentText: string;
|
||||
paymentButton: string;
|
||||
paymentUnavailable: string;
|
||||
cancelTitle: string;
|
||||
cancelText: string;
|
||||
cancelButton: string;
|
||||
cancelledNote: (date: string) => string;
|
||||
endedNote: (date: string) => string;
|
||||
certificateLink: string;
|
||||
cancelDone: (date: string) => string;
|
||||
cancelFailed: string;
|
||||
};
|
||||
confirm: {
|
||||
metaTitle: string;
|
||||
title: string;
|
||||
intro: string;
|
||||
kindLabel: string;
|
||||
kindValue: string;
|
||||
contractLabel: string;
|
||||
effectiveLabel: string;
|
||||
effectiveValue: (date: string) => string;
|
||||
confirmationLabel: string;
|
||||
confirmationValue: (email: string) => string;
|
||||
submit: string;
|
||||
back: string;
|
||||
};
|
||||
publicPage: {
|
||||
metaTitle: string;
|
||||
title: string;
|
||||
intro: string;
|
||||
accountHint: string;
|
||||
nameLabel: string;
|
||||
emailLabel: string;
|
||||
emailHint: string;
|
||||
referenceLabel: string;
|
||||
referenceHint: string;
|
||||
messageLabel: string;
|
||||
requiredNote: string;
|
||||
startButton: string;
|
||||
reviewHeading: string;
|
||||
reviewIntro: string;
|
||||
confirmButton: string;
|
||||
editButton: string;
|
||||
submitting: string;
|
||||
successHeading: string;
|
||||
receivedAtLabel: string;
|
||||
successMailSent: string;
|
||||
successMailFailed: string;
|
||||
errorMessage: string;
|
||||
rateLimited: string;
|
||||
invalid: string;
|
||||
};
|
||||
}
|
||||
|
||||
const de: AboStrings = {
|
||||
footerLink: "Verträge hier kündigen",
|
||||
status: {
|
||||
AUSSTEHEND: "Abschluss offen",
|
||||
AKTIV: "Aktiv",
|
||||
IM_VERZUG: "Zahlung offen",
|
||||
GEKUENDIGT: "Gekündigt",
|
||||
BEENDET: "Beendet",
|
||||
},
|
||||
thanks: {
|
||||
metaTitle: "Abo abgeschlossen",
|
||||
activeTitle: "Danke für dein Abo!",
|
||||
activeText: "Dein Abo ist aktiv – die Urkunde erscheint nach der ersten Zahlung in deinem Konto.",
|
||||
processingTitle: "Deine Zahlung wird geprüft",
|
||||
processingText:
|
||||
"Dein Abo ist abgeschlossen. Bei Lastschrift dauert die Bestätigung der Bank einige Tage – die Urkunde erscheint nach der ersten Zahlung in deinem Konto.",
|
||||
notCompletedTitle: "Das Abo wurde nicht abgeschlossen",
|
||||
notCompletedText: "Es wurde nichts abgebucht. Du kannst es jederzeit erneut versuchen.",
|
||||
toSubscription: "Zum Abo",
|
||||
toAccount: "Zu meiner Patenschaft",
|
||||
backToOffer: "Zurück zur Patenschaft",
|
||||
},
|
||||
detail: {
|
||||
metaTitle: "Mein Abo",
|
||||
back: "Zurück zur Patenschaft",
|
||||
title: (offer) => `Abo „${offer}“`,
|
||||
beeLine: (bee) => `Patenbiene ${bee}`,
|
||||
contractNumber: "Vertragsnummer",
|
||||
statusLabel: "Status",
|
||||
monthlyPrice: "Monatlicher Betrag",
|
||||
nextCharge: "Nächste Abbuchung",
|
||||
endsOn: "Endet am",
|
||||
paidMonths: "Bezahlte Monate",
|
||||
progressTitle: "Bis zur nächsten Honiglieferung",
|
||||
progress: (paid, required) => `${paid} von ${required} Monaten bezahlt`,
|
||||
progressHarvest: (paid, required) =>
|
||||
`${paid} von ${required} Monaten bezahlt – geliefert wird im nächsten Erntefenster`,
|
||||
sepaHoldNote:
|
||||
"Bei Lastschrift zählt die erste Zahlung erst nach acht Wochen für die Lieferung, weil die Bank sie so lange zurückholen kann.",
|
||||
deliveriesTitle: "Honiglieferungen",
|
||||
deliveriesEmpty: "Noch keine Lieferung – der Honig kommt, sobald genug Monate bezahlt sind.",
|
||||
deliveryPrepared: (date, jars) => `${date}: ${jars} Gläser, in Vorbereitung oder unterwegs`,
|
||||
deliveryDeferred: (date) => `${date}: zurückgestellt – wir melden uns bei dir`,
|
||||
delinquentNote:
|
||||
"Eine Zahlung ist offen. Solange sie nicht ausgeglichen ist, ruhen die Honiglieferungen.",
|
||||
paymentTitle: "Zahlungsart",
|
||||
paymentText: "Du kannst deine Zahlungsart sicher bei unserem Zahlungsdienstleister Stripe ändern.",
|
||||
paymentButton: "Zahlungsart ändern",
|
||||
paymentUnavailable: "Das Ändern der Zahlungsart ist gerade nicht möglich. Bitte versuche es später erneut.",
|
||||
cancelTitle: "Kündigen",
|
||||
cancelText: "Das Abo ist monatlich kündbar und endet zum Ende des bezahlten Monats.",
|
||||
cancelButton: "Verträge hier kündigen",
|
||||
cancelledNote: (date) => `Gekündigt – das Abo endet am ${date}. Danach wird nichts mehr abgebucht.`,
|
||||
endedNote: (date) => `Das Abo ist am ${date} beendet. Urkunde, Medaille und Downloads bleiben in deinem Konto.`,
|
||||
certificateLink: "Zur Urkunde",
|
||||
cancelDone: (date) => `Deine Kündigung ist eingegangen. Das Abo endet am ${date}. Eine Bestätigung ist per Mail unterwegs.`,
|
||||
cancelFailed: "Die Kündigung konnte gerade nicht verarbeitet werden. Bitte versuche es erneut oder nutze die Seite „Verträge hier kündigen“.",
|
||||
},
|
||||
confirm: {
|
||||
metaTitle: "Kündigung bestätigen",
|
||||
title: "Kündigung bestätigen",
|
||||
intro: "Bitte prüfe deine Angaben. Mit dem Klick auf „Jetzt kündigen“ ist die Kündigung erklärt.",
|
||||
kindLabel: "Art der Kündigung",
|
||||
kindValue: "Ordentliche Kündigung zum nächstmöglichen Zeitpunkt",
|
||||
contractLabel: "Vertrag",
|
||||
effectiveLabel: "Wirksam zum",
|
||||
effectiveValue: (date) => `${date} (Ende des bezahlten Monats)`,
|
||||
confirmationLabel: "Bestätigung an",
|
||||
confirmationValue: (email) => email,
|
||||
submit: "Jetzt kündigen",
|
||||
back: "Abbrechen",
|
||||
},
|
||||
publicPage: {
|
||||
metaTitle: "Verträge hier kündigen",
|
||||
title: "Verträge hier kündigen",
|
||||
intro:
|
||||
"Hier kündigst du dein Abo der Bienenpatenschaft ohne Anmeldung. Die Kündigung wirkt zum Ende des bezahlten Monats. Du bekommst sofort eine Eingangsbestätigung per Mail.",
|
||||
accountHint: "Mit Kundenkonto geht es auch direkt dort: Konto → Patenschaft → Abo.",
|
||||
nameLabel: "Vor- und Nachname *",
|
||||
emailLabel: "E-Mail-Adresse *",
|
||||
emailHint: "Die Adresse deines Kundenkontos – dorthin geht die Bestätigung.",
|
||||
referenceLabel: "Vertragsnummer *",
|
||||
referenceHint: "Die Patenschaftsnummer von der Urkunde (WH-P-…) oder die Vertragsnummer aus deinem Konto.",
|
||||
messageLabel: "Nachricht (optional)",
|
||||
requiredNote: "* Pflichtangaben",
|
||||
startButton: "Verträge hier kündigen",
|
||||
reviewHeading: "Kündigung bestätigen",
|
||||
reviewIntro: "Bitte prüfe deine Angaben. Mit dem Klick auf „Jetzt kündigen“ ist die Kündigung erklärt.",
|
||||
confirmButton: "Jetzt kündigen",
|
||||
editButton: "Angaben ändern",
|
||||
submitting: "Wird gesendet …",
|
||||
successHeading: "Deine Kündigung ist eingegangen",
|
||||
receivedAtLabel: "Eingegangen am",
|
||||
successMailSent: "Wir haben dir eine Eingangsbestätigung per Mail geschickt.",
|
||||
successMailFailed:
|
||||
"Die Bestätigungsmail konnte gerade nicht versendet werden. Deine Kündigung ist trotzdem eingegangen; bitte bewahre diese Seite als Nachweis auf.",
|
||||
errorMessage: "Deine Kündigung konnte nicht gesendet werden. Bitte versuche es erneut oder schreib uns eine Mail.",
|
||||
rateLimited: "Zu viele Anfragen. Bitte versuche es später erneut oder schreib uns eine Mail.",
|
||||
invalid: "Bitte überprüfe deine Angaben.",
|
||||
},
|
||||
};
|
||||
|
||||
const en: AboStrings = {
|
||||
footerLink: "Cancel contracts here",
|
||||
status: {
|
||||
AUSSTEHEND: "Sign-up pending",
|
||||
AKTIV: "Active",
|
||||
IM_VERZUG: "Payment outstanding",
|
||||
GEKUENDIGT: "Cancelled",
|
||||
BEENDET: "Ended",
|
||||
},
|
||||
thanks: {
|
||||
metaTitle: "Subscription confirmed",
|
||||
activeTitle: "Thank you for subscribing!",
|
||||
activeText: "Your subscription is active – the certificate appears in your account after the first payment.",
|
||||
processingTitle: "Your payment is being confirmed",
|
||||
processingText:
|
||||
"Your subscription is set up. With direct debit, the bank takes a few days to confirm – the certificate appears in your account after the first payment.",
|
||||
notCompletedTitle: "The subscription was not completed",
|
||||
notCompletedText: "Nothing has been charged. You can try again at any time.",
|
||||
toSubscription: "View subscription",
|
||||
toAccount: "My sponsorship",
|
||||
backToOffer: "Back to bee sponsorship",
|
||||
},
|
||||
detail: {
|
||||
metaTitle: "My subscription",
|
||||
back: "Back to sponsorship",
|
||||
title: (offer) => `Subscription “${offer}”`,
|
||||
beeLine: (bee) => `Sponsored bee ${bee}`,
|
||||
contractNumber: "Contract number",
|
||||
statusLabel: "Status",
|
||||
monthlyPrice: "Monthly amount",
|
||||
nextCharge: "Next charge",
|
||||
endsOn: "Ends on",
|
||||
paidMonths: "Paid months",
|
||||
progressTitle: "Until the next honey delivery",
|
||||
progress: (paid, required) => `${paid} of ${required} months paid`,
|
||||
progressHarvest: (paid, required) => `${paid} of ${required} months paid – delivered in the next harvest window`,
|
||||
sepaHoldNote:
|
||||
"With direct debit, the first payment only counts towards a delivery after eight weeks, because the bank can reverse it until then.",
|
||||
deliveriesTitle: "Honey deliveries",
|
||||
deliveriesEmpty: "No delivery yet – the honey comes as soon as enough months are paid.",
|
||||
deliveryPrepared: (date, jars) => `${date}: ${jars} jars, being prepared or on the way`,
|
||||
deliveryDeferred: (date) => `${date}: on hold – we will get in touch`,
|
||||
delinquentNote: "A payment is outstanding. Honey deliveries are paused until it is settled.",
|
||||
paymentTitle: "Payment method",
|
||||
paymentText: "You can change your payment method securely with our payment provider Stripe.",
|
||||
paymentButton: "Change payment method",
|
||||
paymentUnavailable: "Changing the payment method is not possible right now. Please try again later.",
|
||||
cancelTitle: "Cancel",
|
||||
cancelText: "The subscription can be cancelled monthly and ends at the end of the paid month.",
|
||||
cancelButton: "Cancel contracts here",
|
||||
cancelledNote: (date) => `Cancelled – the subscription ends on ${date}. Nothing will be charged afterwards.`,
|
||||
endedNote: (date) => `The subscription ended on ${date}. Your certificate, medal and downloads remain in your account.`,
|
||||
certificateLink: "View certificate",
|
||||
cancelDone: (date) => `We have received your cancellation. The subscription ends on ${date}. A confirmation is on its way by email.`,
|
||||
cancelFailed: "The cancellation could not be processed right now. Please try again or use the “Cancel contracts here” page.",
|
||||
},
|
||||
confirm: {
|
||||
metaTitle: "Confirm cancellation",
|
||||
title: "Confirm cancellation",
|
||||
intro: "Please check your details. Clicking “Cancel now” submits your cancellation.",
|
||||
kindLabel: "Type of cancellation",
|
||||
kindValue: "Ordinary cancellation at the earliest possible date",
|
||||
contractLabel: "Contract",
|
||||
effectiveLabel: "Effective on",
|
||||
effectiveValue: (date) => `${date} (end of the paid month)`,
|
||||
confirmationLabel: "Confirmation to",
|
||||
confirmationValue: (email) => email,
|
||||
submit: "Cancel now",
|
||||
back: "Back",
|
||||
},
|
||||
publicPage: {
|
||||
metaTitle: "Cancel contracts here",
|
||||
title: "Cancel contracts here",
|
||||
intro:
|
||||
"Cancel your bee sponsorship subscription here without logging in. The cancellation takes effect at the end of the paid month. You receive a confirmation of receipt by email right away.",
|
||||
accountHint: "With a customer account you can also do this directly there: Account → Sponsorship → Subscription.",
|
||||
nameLabel: "First and last name *",
|
||||
emailLabel: "Email address *",
|
||||
emailHint: "The address of your customer account – the confirmation goes there.",
|
||||
referenceLabel: "Contract number *",
|
||||
referenceHint: "The sponsorship number from the certificate (WH-P-…) or the contract number from your account.",
|
||||
messageLabel: "Message (optional)",
|
||||
requiredNote: "* Required",
|
||||
startButton: "Cancel contracts here",
|
||||
reviewHeading: "Confirm cancellation",
|
||||
reviewIntro: "Please check your details. Clicking “Cancel now” submits your cancellation.",
|
||||
confirmButton: "Cancel now",
|
||||
editButton: "Edit details",
|
||||
submitting: "Sending …",
|
||||
successHeading: "We have received your cancellation",
|
||||
receivedAtLabel: "Received on",
|
||||
successMailSent: "We have sent you a confirmation of receipt by email.",
|
||||
successMailFailed:
|
||||
"The confirmation email could not be sent right now. Your cancellation has still been received; please keep this page as proof.",
|
||||
errorMessage: "Your cancellation could not be sent. Please try again or email us.",
|
||||
rateLimited: "Too many requests. Please try again later or email us.",
|
||||
invalid: "Please check your details.",
|
||||
},
|
||||
};
|
||||
|
||||
export function getAboStrings(locale: Locale): AboStrings {
|
||||
return locale === "en" ? en : de;
|
||||
}
|
||||
Reference in new issue
Block a user