Paperless enthält 0 Dokumente, der Upload wurde nie benutzt. Weg sind: die Seite Dokumente (alte Links führen zu den Tickets), der Menüpunkt, der Reiter Dokumente in Ticketkarte und Kundenseite, der Upload-Dialog (legte Dateien zusätzlich ungelesen im Appwrite-Bucket ab), das Feld "Paperless-Korrespondent" und das Abzeichen "Docs", auf dem Dashboard die Kachel Dokumente und "Dokument hochladen", im API-Client die Paperless-Aufrufe. Gespeicherte Daten bleiben unverändert; die Paperless-Routen im Backend ticket-integrations sind nicht angefasst. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
119 lines
3.8 KiB
React
119 lines
3.8 KiB
React
import { useState } from 'react'
|
|
import { Link, useLocation, useNavigate } from 'react-router-dom'
|
|
import { useAuth } from '../context/AuthContext'
|
|
import {
|
|
IconTicket,
|
|
IconUsers,
|
|
IconTargetArrow,
|
|
IconReportMoney,
|
|
IconFolders,
|
|
IconCalendar,
|
|
IconRoute,
|
|
IconLayoutDashboard,
|
|
IconSettings,
|
|
IconLogout,
|
|
IconLayoutSidebarLeftCollapse,
|
|
IconLayoutSidebarLeftExpand,
|
|
} from '@tabler/icons-react'
|
|
|
|
export default function Sidebar() {
|
|
const { user, logout, isAdmin } = useAuth()
|
|
const navigate = useNavigate()
|
|
const location = useLocation()
|
|
const [collapsed, setCollapsed] = useState(false)
|
|
|
|
const handleLogout = async () => {
|
|
await logout()
|
|
navigate('/login')
|
|
}
|
|
|
|
const groups = [
|
|
{
|
|
label: 'Betrieb',
|
|
links: [
|
|
{ label: 'Tickets', href: '/tickets', icon: <IconTicket /> },
|
|
{ label: 'Planboard', href: '/planboard', icon: <IconCalendar /> },
|
|
{ label: 'Roadmaps', href: '/roadmaps', icon: <IconRoute /> },
|
|
{ label: 'Projekte', href: '/projects', icon: <IconFolders /> },
|
|
],
|
|
},
|
|
{
|
|
label: 'CRM',
|
|
links: [
|
|
{ label: 'Kunden', href: '/customers', icon: <IconUsers /> },
|
|
{ label: 'Leads', href: '/leads', icon: <IconTargetArrow /> },
|
|
],
|
|
},
|
|
{
|
|
label: 'Finanzen',
|
|
links: [{ label: 'Finanzen', href: '/finance', icon: <IconReportMoney /> }],
|
|
},
|
|
{
|
|
label: 'Auswertung',
|
|
links: [
|
|
{ label: 'Dashboard', href: '/dashboard', icon: <IconLayoutDashboard /> },
|
|
],
|
|
},
|
|
{
|
|
label: 'System',
|
|
links: [
|
|
...(isAdmin ? [{ label: 'Admin', href: '/admin', icon: <IconSettings /> }] : []),
|
|
],
|
|
},
|
|
]
|
|
|
|
const isActive = (href) =>
|
|
location.pathname === href || location.pathname.startsWith(href + '/')
|
|
|
|
return (
|
|
<aside className={`side ${collapsed ? 'collapsed' : ''}`}>
|
|
<div className="side-head">
|
|
<Link to="/" className="side-logo" title="Webklar">W</Link>
|
|
<div className="side-brand">
|
|
Webklar
|
|
<small>Ticket-Plattform</small>
|
|
</div>
|
|
</div>
|
|
|
|
<nav className="side-nav">
|
|
{/* Gruppen ohne Eintrag (System fuer Nicht-Admins) nicht anzeigen */}
|
|
{groups.filter((group) => group.links.length > 0).map((group) => (
|
|
<div className="side-group" key={group.label}>
|
|
<div className="side-group-label">{group.label}</div>
|
|
{group.links.map((link) => (
|
|
<Link
|
|
key={link.href}
|
|
to={link.href}
|
|
className={`side-link ${isActive(link.href) ? 'active' : ''}`}
|
|
title={link.label}
|
|
>
|
|
{link.icon}
|
|
<span className="side-link-label">{link.label}</span>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
))}
|
|
</nav>
|
|
|
|
<div className="side-foot">
|
|
{user && (
|
|
<div className="side-link" title={user.name || user.email} style={{ cursor: 'default' }}>
|
|
<div className="side-logo" style={{ width: 28, height: 28, fontSize: 12, background: 'linear-gradient(135deg,#667eea,#764ba2)' }}>
|
|
{(user.name || user.email || '?').charAt(0).toUpperCase()}
|
|
</div>
|
|
<span className="side-link-label text-ellipsis">{user.name || user.email}</span>
|
|
</div>
|
|
)}
|
|
<button className="side-toggle" onClick={handleLogout} title="Logout">
|
|
<IconLogout size={20} />
|
|
<span className="side-link-label">Logout</span>
|
|
</button>
|
|
<button className="side-toggle" onClick={() => setCollapsed((c) => !c)} title="Menue ein-/ausklappen">
|
|
{collapsed ? <IconLayoutSidebarLeftExpand size={20} /> : <IconLayoutSidebarLeftCollapse size={20} />}
|
|
<span className="side-link-label">Einklappen</span>
|
|
</button>
|
|
</div>
|
|
</aside>
|
|
)
|
|
}
|