146 lines
5.1 KiB
TypeScript
146 lines
5.1 KiB
TypeScript
import { NavLink } from 'react-router-dom';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { useAuth } from '../../context/AuthContext';
|
|
import { gdprApi } from '../../services/api';
|
|
import {
|
|
LayoutDashboard,
|
|
Users,
|
|
FileText,
|
|
LogOut,
|
|
Settings,
|
|
Code,
|
|
Database,
|
|
ClipboardList,
|
|
MessageSquare,
|
|
AlertCircle,
|
|
Shield,
|
|
FileCheck,
|
|
UserCircle,
|
|
Gauge,
|
|
} from 'lucide-react';
|
|
|
|
export default function Sidebar() {
|
|
const { user, logout, hasPermission, isCustomer, isCustomerPortal, developerMode } = useAuth();
|
|
|
|
// Prüfe ob Vollmachten vorhanden sind (nur für Portal-Kunden)
|
|
const { data: authData } = useQuery({
|
|
queryKey: ['my-authorizations'],
|
|
queryFn: () => gdprApi.getMyAuthorizations(),
|
|
enabled: isCustomerPortal,
|
|
staleTime: 60_000,
|
|
});
|
|
|
|
const hasAuthorizations = (authData?.data?.length ?? 0) > 0;
|
|
|
|
const navItems = [
|
|
{ to: '/', icon: LayoutDashboard, label: 'Dashboard', show: true, end: true },
|
|
{ to: '/my-profile', icon: UserCircle, label: 'Meine Daten', show: isCustomerPortal },
|
|
{ to: '/customers', icon: Users, label: 'Kunden', show: hasPermission('customers:read') && !isCustomer },
|
|
{ to: '/contracts', icon: FileText, label: 'Verträge', show: hasPermission('contracts:read'), end: true },
|
|
{ to: '/contracts/cockpit', icon: AlertCircle, label: 'Vertrags-Cockpit', show: hasPermission('contracts:read') && !isCustomer },
|
|
{ to: '/tasks', icon: isCustomer ? MessageSquare : ClipboardList, label: isCustomer ? 'Support-Anfragen' : 'Aufgaben', show: hasPermission('contracts:read') },
|
|
{ to: '/my-meters', icon: Gauge, label: 'Zählerstände', show: isCustomerPortal },
|
|
{ to: '/privacy', icon: Shield, label: 'Datenschutz', show: isCustomerPortal },
|
|
{ to: '/authorizations', icon: FileCheck, label: 'Vollmachten', show: isCustomerPortal && hasAuthorizations },
|
|
];
|
|
|
|
const developerItems = [
|
|
{ to: '/developer/database', icon: Database, label: 'Datenbankstruktur' },
|
|
];
|
|
|
|
return (
|
|
<aside className="w-64 bg-gray-900 text-white min-h-screen flex flex-col">
|
|
<div className="p-4 border-b border-gray-800">
|
|
<h1 className="text-xl font-bold">OpenCRM</h1>
|
|
</div>
|
|
|
|
<nav className="flex-1 p-4 overflow-y-auto">
|
|
<ul className="space-y-2">
|
|
{navItems
|
|
.filter((item) => item.show)
|
|
.map((item) => (
|
|
<li key={item.to}>
|
|
<NavLink
|
|
to={item.to}
|
|
end={item.end}
|
|
className={({ isActive }) =>
|
|
`flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${
|
|
isActive
|
|
? 'bg-blue-600 text-white'
|
|
: 'text-gray-300 hover:bg-gray-800'
|
|
}`
|
|
}
|
|
>
|
|
<item.icon className="w-5 h-5" />
|
|
{item.label}
|
|
</NavLink>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
|
|
{/* Entwicklermodus-Menü */}
|
|
{developerMode && hasPermission('developer:access') && (
|
|
<>
|
|
<div className="mt-6 mb-2 px-4">
|
|
<p className="text-xs font-semibold text-gray-500 uppercase tracking-wider flex items-center gap-2">
|
|
<Code className="w-3 h-3" />
|
|
Entwickler
|
|
</p>
|
|
</div>
|
|
<ul className="space-y-2">
|
|
{developerItems.map((item) => (
|
|
<li key={item.to}>
|
|
<NavLink
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${
|
|
isActive
|
|
? 'bg-purple-600 text-white'
|
|
: 'text-purple-300 hover:bg-gray-800'
|
|
}`
|
|
}
|
|
>
|
|
<item.icon className="w-5 h-5" />
|
|
{item.label}
|
|
</NavLink>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</>
|
|
)}
|
|
|
|
{/* Einstellungen */}
|
|
<div className="mt-6 pt-6 border-t border-gray-800">
|
|
<NavLink
|
|
to="/settings"
|
|
className={({ isActive }) =>
|
|
`flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${
|
|
isActive
|
|
? 'bg-blue-600 text-white'
|
|
: 'text-gray-300 hover:bg-gray-800'
|
|
}`
|
|
}
|
|
>
|
|
<Settings className="w-5 h-5" />
|
|
Einstellungen
|
|
</NavLink>
|
|
</div>
|
|
</nav>
|
|
|
|
<div className="p-4 border-t border-gray-800">
|
|
<div className="mb-4 text-sm">
|
|
<p className="text-gray-400">Angemeldet als</p>
|
|
<p className="font-medium">{user?.firstName} {user?.lastName}</p>
|
|
</div>
|
|
<button
|
|
onClick={logout}
|
|
className="flex items-center gap-3 w-full px-4 py-2 text-gray-300 hover:bg-gray-800 rounded-lg transition-colors"
|
|
>
|
|
<LogOut className="w-5 h-5" />
|
|
Abmelden
|
|
</button>
|
|
</div>
|
|
</aside>
|
|
);
|
|
}
|