feat: Wabenhain Honig-Shop Anwendung

Vollstaendige Next.js/Prisma-E-Commerce-Anwendung fuer eine Imkerei:
Shop, Warenkorb, Stripe-Checkout, Kundenkonto mit 2FA, Admin-Bereich
(Produkte, Ernten, Chargen, Bestellungen, Gutscheine, admin-editierbare
Website-Inhalte), i18n (DE/EN), Rate-Limiting/CSP/Audit-Log-Haertung,
PostgreSQL- und MySQL-Unterstuetzung ueber austauschbare Prisma-
Treiber-Adapter, Unit-/Komponenten-/E2E-Tests.
This commit is contained in:
Nick Szaunig committed 2026-08-17 14:30:28 +02:00
1 parent 5c76fcc266
commit c7927f2883
240 files changed
+26096 -137

No files matched your search

+59
View File
@@ -0,0 +1,59 @@
"use server";
import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";
import { prisma } from "@/lib/prisma";
import { logAdminAction } from "@/lib/audit-log";
import { CONTENT_REGISTRY } from "@/lib/content-registry";
import { requireAdmin } from "./_shared";
/**
* Generisch fuer alle drei Inhalts-Gruppen (Firmendaten/Homepage/Rechtstexte)
* — jede Gruppen-Form sendet nur ihre eigenen Feldnamen, diese Action
* verarbeitet einfach, was tatsaechlich in formData vorhanden ist. Nicht
* lokalisierte Felder kommen als "{key}", lokalisierte als "de::{key}" /
* "en::{key}" (siehe admin/inhalte/page.tsx).
*/
export async function updateSiteContentAction(formData: FormData): Promise<void> {
const admin = await requireAdmin();
const group = String(formData.get("group") ?? "");
const updates: { key: string; valueDe: string; valueEn: string | null }[] = [];
for (const def of CONTENT_REGISTRY) {
if (def.localized) {
const de = formData.get(`de::${def.key}`);
const en = formData.get(`en::${def.key}`);
if (de === null && en === null) continue;
updates.push({
key: def.key,
valueDe: String(de ?? ""),
valueEn: String(en ?? ""),
});
} else {
const value = formData.get(def.key);
if (value === null) continue;
updates.push({ key: def.key, valueDe: String(value), valueEn: null });
}
}
await prisma.$transaction(
updates.map((u) =>
prisma.siteContent.upsert({
where: { key: u.key },
create: { key: u.key, valueDe: u.valueDe, valueEn: u.valueEn },
update: { valueDe: u.valueDe, valueEn: u.valueEn },
})
)
);
await logAdminAction(admin, {
action: "site_content.update",
entityType: "SiteContent",
entityId: group || undefined,
detail: `${updates.length} Feld(er)`,
});
revalidatePath("/", "layout");
redirect("/admin/inhalte?saved=1");
}