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

+50
View File
@@ -0,0 +1,50 @@
"use client";
import { useTransition } from "react";
import { useRouter } from "next/navigation";
import { locales, localeLabels, type Locale } from "@/i18n/config";
import { setLocaleAction } from "@/i18n/actions";
import { useI18n } from "@/i18n/i18n-provider";
/**
* Iteriert ueber locales aus i18n/config.ts statt DE/EN fest zu verdrahten —
* eine dritte Sprache erscheint hier automatisch, sobald sie dort ergaenzt
* wird, ohne diese Komponente anzufassen.
*/
export function LanguageSwitcher({ className = "" }: { className?: string }) {
const { locale } = useI18n();
const router = useRouter();
const [isPending, startTransition] = useTransition();
function handleChange(next: Locale) {
if (next === locale || isPending) return;
startTransition(async () => {
const formData = new FormData();
formData.set("locale", next);
await setLocaleAction(formData);
router.refresh();
});
}
return (
<div className={`flex items-center gap-1 text-xs ${className}`} role="group" aria-label="Sprache wählen / Choose language">
{locales.map((code, i) => (
<span key={code} className="flex items-center">
{i > 0 ? <span className="text-ink/30 mx-1" aria-hidden="true">/</span> : null}
<button
type="button"
onClick={() => handleChange(code)}
disabled={isPending}
aria-current={code === locale}
title={localeLabels[code]}
className={`uppercase tracking-wide transition-colors disabled:opacity-50 ${
code === locale ? "text-forest font-medium" : "text-ink/50 hover:text-forest"
}`}
>
{code}
</button>
</span>
))}
</div>
);
}