feat(stammdaten): crud fuer hersteller, themen und standorte

Gemeinsame CrudSection fuer die drei kleinen Stammdatentabellen; sie
unterscheiden sich nur in den Formularfeldern. Loeschen ist bewusst
blockiert, solange Sets am Hersteller oder Thema haengen - Standorte
duerfen weg, die Sammlungseintraege verlieren dann nur den Ort.

Dazu die gemeinsamen Bausteine: zod-Schemata fuer alle Formulare,
einheitliches ActionResult, Slug-Erzeugung mit deutschen Umlauten,
Geld als Cent und Datumsformatierung dd.MM.yyyy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
unknown
2026-09-06 22:46:45 +02:00
co-authored by Claude Opus 5
parent 4c78c5672b
commit af0ae039cb
18 changed files with 1254 additions and 70 deletions
@@ -0,0 +1,38 @@
'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { cn } from 'cn';
const tabs = [
{ href: '/verwaltung/hersteller', label: 'Hersteller' },
{ href: '/verwaltung/themen', label: 'Themen' },
{ href: '/verwaltung/standorte', label: 'Standorte' },
] as const;
export function VerwaltungNav() {
const pathname = usePathname();
return (
<nav className="flex gap-1 overflow-x-auto rounded-lg bg-muted p-1" aria-label="Stammdaten">
{tabs.map((tab) => {
const active = pathname === tab.href;
return (
<Link
key={tab.href}
href={tab.href}
aria-current={active ? 'page' : undefined}
className={cn(
'flex-1 whitespace-nowrap rounded-md px-3 py-2 text-center text-sm font-medium transition-colors',
active
? 'bg-background text-foreground shadow-sm'
: 'text-muted-foreground hover:text-foreground',
)}
>
{tab.label}
</Link>
);
})}
</nav>
);
}