push newest version

This commit is contained in:
2025-11-20 17:59:34 +01:00
parent c0e2df2430
commit 97ccd7bfbf
21 changed files with 3978 additions and 65 deletions

View File

@@ -1,14 +1,32 @@
import { Link, useLocation } from 'react-router-dom'
import { Link, useLocation, useNavigate } from 'react-router-dom'
import { useAuth } from '../contexts/AuthContext'
import { useState, useEffect } from 'react'
const Sidebar = ({ isOpen, setIsOpen }) => {
const location = useLocation()
const navigate = useNavigate()
const { user, logout } = useAuth()
const [expandedMenus, setExpandedMenus] = useState({})
const menuItems = [
{ path: '/', label: 'Home', icon: '🏠' },
{ path: '/spaces', label: 'Spaces', icon: '📁' },
{ path: '/audit-logs', label: 'Audit Log', icon: '📋' },
{ path: '/impressum', label: 'Impressum', icon: '' },
]
// Settings mit Unterpunkten
const settingsMenu = {
label: 'Settings',
icon: '⚙️',
path: '/settings',
subItems: [
{ path: '/settings/users', label: 'User', icon: '👥' },
]
}
const profileItem = { path: '/profile', label: 'Profil', icon: '👤' }
const isActive = (path) => {
if (path === '/') {
return location.pathname === '/'
@@ -16,6 +34,27 @@ const Sidebar = ({ isOpen, setIsOpen }) => {
return location.pathname.startsWith(path)
}
const toggleMenu = (menuPath) => {
setExpandedMenus(prev => ({
...prev,
[menuPath]: !prev[menuPath]
}))
}
const isMenuExpanded = (menuPath) => {
return expandedMenus[menuPath] || false
}
// Automatisch Settings-Menü expandieren, wenn auf einer Settings-Seite
useEffect(() => {
if (location.pathname.startsWith('/settings')) {
setExpandedMenus(prev => ({
...prev,
'/settings': true
}))
}
}, [location.pathname])
return (
<>
{/* Overlay for mobile */}
@@ -63,8 +102,8 @@ const Sidebar = ({ isOpen, setIsOpen }) => {
</div>
</button>
</div>
<nav className="px-2 py-4 overflow-hidden">
<ul className="space-y-2">
<nav className="px-2 py-4 overflow-hidden flex flex-col h-[calc(100%-4rem)]">
<ul className="space-y-2 flex-1">
{menuItems.map((item) => (
<li key={item.path}>
<Link
@@ -87,7 +126,104 @@ const Sidebar = ({ isOpen, setIsOpen }) => {
</Link>
</li>
))}
{/* Settings Menu mit Unterpunkten */}
<li>
<button
onClick={() => isOpen && toggleMenu(settingsMenu.path)}
className={`w-full flex items-center px-3 py-3 rounded-lg transition-all duration-200 ${
isActive(settingsMenu.path)
? 'bg-slate-700 text-white font-semibold shadow-md'
: 'text-slate-300 hover:bg-slate-700/50 hover:text-white'
}`}
title={!isOpen ? settingsMenu.label : ''}
>
<span className={`text-xl flex-shrink-0 ${isOpen ? 'mr-3' : 'mx-auto'}`}>
{settingsMenu.icon}
</span>
{isOpen && (
<>
<span className="whitespace-nowrap overflow-hidden">
{settingsMenu.label}
</span>
<svg
className={`w-4 h-4 ml-auto flex-shrink-0 transition-transform duration-200 ${
isMenuExpanded(settingsMenu.path) ? 'rotate-90' : ''
}`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</>
)}
</button>
{isOpen && isMenuExpanded(settingsMenu.path) && settingsMenu.subItems && (
<ul className="ml-4 mt-1 space-y-1">
{settingsMenu.subItems.map((subItem) => (
<li key={subItem.path}>
<Link
to={subItem.path}
className={`flex items-center px-3 py-2 rounded-lg transition-all duration-200 ${
isActive(subItem.path)
? 'bg-slate-600 text-white font-semibold'
: 'text-slate-400 hover:bg-slate-700/50 hover:text-slate-200'
}`}
>
<span className="text-lg flex-shrink-0 mr-2">
{subItem.icon}
</span>
<span className="whitespace-nowrap overflow-hidden">
{subItem.label}
</span>
</Link>
</li>
))}
</ul>
)}
</li>
</ul>
{/* Profil-Eintrag und Logout am unteren Ende */}
<div className="mt-auto pt-2 border-t border-slate-700/50 space-y-2">
<Link
to={profileItem.path}
className={`flex items-center px-3 py-3 rounded-lg transition-all duration-200 ${
isActive(profileItem.path)
? 'bg-slate-700 text-white font-semibold shadow-md'
: 'text-slate-300 hover:bg-slate-700/50 hover:text-white'
}`}
title={!isOpen ? (user?.username || profileItem.label) : ''}
>
<span className={`text-xl flex-shrink-0 ${isOpen ? 'mr-3' : 'mx-auto'}`}>
{profileItem.icon}
</span>
{isOpen && (
<span className="whitespace-nowrap overflow-hidden">
{user?.username || profileItem.label}
</span>
)}
</Link>
<button
onClick={() => {
logout()
navigate('/login')
}}
className={`w-full flex items-center px-3 py-3 rounded-lg transition-all duration-200 text-slate-300 hover:bg-red-600/20 hover:text-red-400 ${
isOpen ? '' : 'justify-center'
}`}
title={!isOpen ? 'Abmelden' : ''}
>
<span className={`text-xl flex-shrink-0 ${isOpen ? 'mr-3' : ''}`}>
🚪
</span>
{isOpen && (
<span className="whitespace-nowrap overflow-hidden">
Abmelden
</span>
)}
</button>
</div>
</nav>
</aside>
</>