feat(delegations): UI fuer Berechtigungs-Delegationen — Modul 2/16 des UI-Backlogs

Backend existierte vollstaendig (5 Endpoints: list/create/update/delete/
active-check, delegations:read/write seit Audit-Fix im Katalog), Frontend
hatte 0% Abdeckung. Modul folgt dem Approvals-Muster (Modul 1):

- api/delegations.ts: TanStack-Hooks (useDelegations mit direction-Filter,
useActiveDelegations, create/update/delete-Mutations mit Cache-Invalidierung)
- pages/Delegations.tsx: Richtungstabs (alle/von mir/an mich), Karten mit
  Phasen-Badges (aktiv/geplant/abgelaufen/inaktiv), Erstellen-Dialog mit
  Empfaenger-Picker (useUsers, sich selbst ausschliessend), Start/Ende-
  Datetime, Scope-Toggle (alle Berechtigungen), Aktivieren/Deaktivieren,
  Loeschen mit Confirm — Aktionen hinter delegations:write gegated
- Route /delegations (PermissionRoute delegations:read) — als Core-Route
  bewusst statisch registriert (Phase-Q-Regel: nur Plugin-Routen laufen
  ueber Manifeste) Sidebar-Entry order 92 (ArrowRightLeft-Icon)
- i18n delegations.* + nav.delegations de/en

Verifikation: Vitest 9/9 (Rendering, Tabs, Phasen, Permission-Gating,
Create-Flow, Toggle, Delete) · tsc exit 0 · production build exit 0.
This commit is contained in:
Agent Zero
2026-09-13 09:17:17 +02:00
parent b58c96ff71
commit 36771d471d
7 changed files with 752 additions and 3 deletions
+2 -1
View File
@@ -3,7 +3,7 @@ import clsx from 'clsx';
import { NavLink, useLocation, useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { useUIStore } from '@/store/uiStore';
import { ChevronRight, FileText, Home, Settings, Users, ArrowLeft , CheckCircle2 } from 'lucide-react';
import { ArrowLeft, ArrowRightLeft, CheckCircle2, ChevronRight, FileText, Home, Settings, Users } from 'lucide-react';
import { usePluginStore } from '@/store/pluginStore';
// Curated icon map — avoids `import * as LucideIcons` which loads ALL icons and causes OOM in tests
import {
@@ -56,6 +56,7 @@ const singleItems: NavSingleItem[] = [
{ to: '/dashboard', labelKey: 'nav.dashboard', icon: <Home className="w-5 h-5 flex-shrink-0" aria-hidden="true" strokeWidth={2} />, order: 0 },
{ to: '/system-dashboard', labelKey: 'nav.systemDashboard', icon: <Activity className="w-5 h-5 flex-shrink-0" aria-hidden="true" strokeWidth={2} />, order: 90 },
{ to: '/approvals', labelKey: 'nav.approvals', icon: <CheckCircle2 className="w-5 h-5 flex-shrink-0" aria-hidden="true" strokeWidth={2} />, order: 91 },
{ to: '/delegations', labelKey: 'nav.delegations', icon: <ArrowRightLeft className="w-5 h-5 flex-shrink-0" aria-hidden="true" strokeWidth={2} />, order: 92 },
];
const bottomItems: NavSingleItem[] = [];