dak.c2s/frontend/src/components/layout/Sidebar.tsx
CCS Admin 32cee4d30d feat: add KPI links, My Disclosures page, and extend Admin Disclosures
- Dashboard KPI cards are now clickable with role-based links
- New GutachtenStatistikPage placeholder at /gutachten-statistik
- New "Meine Freigaben" page for DAK-Mitarbeiter to view/revoke own disclosures
- Backend: GET /cases/my-disclosure-requests, PUT /cases/disclosure-requests/{id}/revoke
- Admin Disclosures page: full history with status tabs and revoke capability
- Backend: PUT /admin/disclosure-requests/{id}/revoke, default shows all statuses
- Sidebar: "Meine Freigaben" entry for dak_mitarbeiter role

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 22:19:46 +00:00

118 lines
3.5 KiB
TypeScript

import { NavLink } from 'react-router-dom'
import { useAuth } from '@/context/AuthContext'
import { cn } from '@/lib/utils'
import { Separator } from '@/components/ui/separator'
import dakLogo from '@/assets/DAK_Best-Practice-768x768.png'
import {
LayoutDashboard,
FolderOpen,
Upload,
FileEdit,
ClipboardCheck,
FileBarChart,
Users,
Mail,
History,
UserCog,
ShieldCheck,
} from 'lucide-react'
interface NavItem {
label: string
to: string
icon: React.ComponentType<{ className?: string }>
adminOnly?: boolean
mitarbeiterOnly?: boolean
}
const mainNavItems: NavItem[] = [
{ label: 'Dashboard', to: '/dashboard', icon: LayoutDashboard },
{ label: 'Fälle', to: '/cases', icon: FolderOpen },
{ label: 'Import', to: '/import', icon: Upload, adminOnly: true },
{ label: 'ICD-Eingabe', to: '/icd', icon: FileEdit, mitarbeiterOnly: true },
{ label: 'Coding', to: '/coding', icon: ClipboardCheck, adminOnly: true },
{ label: 'Berichte', to: '/reports', icon: FileBarChart },
]
const accountNavItems: NavItem[] = [
{ label: 'Kontoverwaltung', to: '/account', icon: UserCog },
{ label: 'Meine Freigaben', to: '/disclosures', icon: ShieldCheck, mitarbeiterOnly: true },
]
const adminNavItems: NavItem[] = [
{ label: 'Freigabe-Anfragen', to: '/admin/disclosures', icon: ShieldCheck },
{ label: 'Benutzer', to: '/admin/users', icon: Users },
{ label: 'Einladungen', to: '/admin/invitations', icon: Mail },
{ label: 'Audit-Log', to: '/admin/audit', icon: History },
]
function NavItemLink({ item }: { item: NavItem }) {
const Icon = item.icon
return (
<NavLink
to={item.to}
className={({ isActive }) =>
cn(
'flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors',
isActive
? 'bg-primary text-primary-foreground'
: 'text-muted-foreground hover:bg-accent hover:text-accent-foreground'
)
}
>
<Icon className="h-4 w-4 shrink-0" />
<span>{item.label}</span>
</NavLink>
)
}
export function Sidebar({ className }: { className?: string }) {
const { user, isAdmin } = useAuth()
const filterItems = (items: NavItem[]) =>
items.filter((item) => {
if (item.adminOnly && !isAdmin) return false
if (item.mitarbeiterOnly && user?.role !== 'dak_mitarbeiter') return false
return true
})
const visibleMainItems = filterItems(mainNavItems)
const visibleAccountItems = filterItems(accountNavItems)
return (
<aside className={cn('flex h-full flex-col gap-4 p-4', className)}>
<NavLink to="/dashboard" className="flex items-center justify-center px-3 py-2">
<img src={dakLogo} alt="DAK Gesundheit" className="h-18 w-auto" />
</NavLink>
<nav className="flex flex-col gap-1">
{visibleMainItems.map((item) => (
<NavItemLink key={item.to} item={item} />
))}
</nav>
<Separator />
<nav className="flex flex-col gap-1">
{visibleAccountItems.map((item) => (
<NavItemLink key={item.to} item={item} />
))}
</nav>
{isAdmin && (
<>
<Separator />
<div className="px-3 py-1">
<span className="text-xs font-semibold uppercase text-muted-foreground tracking-wider">
Administration
</span>
</div>
<nav className="flex flex-col gap-1">
{adminNavItems.map((item) => (
<NavItemLink key={item.to} item={item} />
))}
</nav>
</>
)}
</aside>
)
}