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,38 @@
|
||||
import Link from "next/link";
|
||||
import type { SponsorshipAdminStrings } from "@/i18n/sponsorship/admin";
|
||||
|
||||
export type SponsorshipSection = "overview" | "offers" | "subscriptions" | "loyalty";
|
||||
|
||||
const SECTIONS: { key: SponsorshipSection; href: string }[] = [
|
||||
{ key: "overview", href: "/admin/patenschaften" },
|
||||
{ key: "offers", href: "/admin/patenschaften/angebote" },
|
||||
{ key: "subscriptions", href: "/admin/patenschaften/abos" },
|
||||
{ key: "loyalty", href: "/admin/patenschaften/treuestufen" },
|
||||
];
|
||||
|
||||
/**
|
||||
* Unternavigation des Bereichs. Die Seitenleiste fuehrt mit einem Eintrag
|
||||
* "Patenschaften" hierher; die vier Teile liegen als Reiter darunter — so
|
||||
* bleibt die Seitenleiste kurz, und es gibt dort nie zwei aktive Eintraege.
|
||||
*/
|
||||
export function SponsorshipTabs({ active, labels }: { active: SponsorshipSection; labels: SponsorshipAdminStrings["tabs"] }) {
|
||||
return (
|
||||
<nav aria-label={labels.ariaLabel} className="mb-6 flex gap-1 overflow-x-auto border-b border-ink/10">
|
||||
{SECTIONS.map((section) => {
|
||||
const selected = section.key === active;
|
||||
return (
|
||||
<Link
|
||||
key={section.key}
|
||||
href={section.href}
|
||||
aria-current={selected ? "page" : undefined}
|
||||
className={`-mb-px whitespace-nowrap border-b-2 px-4 py-2 text-sm transition-colors ${
|
||||
selected ? "border-heading text-heading" : "border-transparent text-ink/60 hover:text-heading"
|
||||
}`}
|
||||
>
|
||||
{labels[section.key]}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user