Sidebar: Chat als Unterpunkt von Kunden mit Zahl der ungelesenen Nachrichten
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
717a3323fa
commit
005875d970
7 files changed
+187
-17
No files matched your search
+37
-17
@@ -16,10 +16,27 @@ import {
|
||||
IconLayoutSidebarLeftCollapse,
|
||||
IconLayoutSidebarLeftExpand,
|
||||
IconExternalLink,
|
||||
IconMessages,
|
||||
} from '@tabler/icons-react'
|
||||
import { openProjectAdmin } from '../lib/employeeAdminApi'
|
||||
import { serverpulsApi } from '../lib/serverpulsApi'
|
||||
import { startsCollapsed } from '../lib/sidebar'
|
||||
import { buildNavLinks } from '../lib/navLinks'
|
||||
import { useChatUnread } from '../hooks/useChatUnread'
|
||||
|
||||
const ICONS = {
|
||||
tickets: <IconTicket />,
|
||||
planboard: <IconCalendar />,
|
||||
projects: <IconFolders />,
|
||||
services: <IconLayoutGrid />,
|
||||
customers: <IconUsers />,
|
||||
chat: <IconMessages />,
|
||||
leads: <IconTargetArrow />,
|
||||
finance: <IconReportMoney />,
|
||||
legal: <IconScale />,
|
||||
serverpuls: <IconActivityHeartbeat />,
|
||||
admin: <IconSettings />,
|
||||
}
|
||||
|
||||
export default function Sidebar() {
|
||||
const { user, logout, isAdmin } = useAuth()
|
||||
@@ -28,6 +45,7 @@ export default function Sidebar() {
|
||||
const [collapsed, setCollapsed] = useState(() => startsCollapsed())
|
||||
const [switching, setSwitching] = useState(false)
|
||||
const [pulseLevel, setPulseLevel] = useState('ok')
|
||||
const chatUnread = useChatUnread()
|
||||
|
||||
// Serverpuls-Punkt: nur Admins, beim Laden und alle 5 Minuten; Fehler bleiben still
|
||||
useEffect(() => {
|
||||
@@ -53,20 +71,8 @@ export default function Sidebar() {
|
||||
navigate('/login')
|
||||
}
|
||||
|
||||
// Eine flache Liste: fuer ein kleines Team reichen acht Eintraege ohne Gruppen
|
||||
const links = [
|
||||
{ label: 'Tickets', href: '/tickets', icon: <IconTicket /> },
|
||||
{ label: 'Planboard', href: '/planboard', icon: <IconCalendar /> },
|
||||
{ label: 'Projekte', href: '/projects', icon: <IconFolders /> },
|
||||
{ label: 'Services', href: '/services', icon: <IconLayoutGrid /> },
|
||||
{ label: 'Kunden', href: '/customers', icon: <IconUsers /> },
|
||||
// Leads liegen auf Eis (Lead-Automatik gestoppt 2026-09-30): grau, nicht klickbar
|
||||
{ label: 'Leads', href: '/leads', icon: <IconTargetArrow />, paused: true },
|
||||
...(isAdmin ? [{ label: 'Finanzen', href: '/finance', also: '/finanzen', icon: <IconReportMoney /> }] : []),
|
||||
{ label: 'Rechtliches', href: '/rechtliches', icon: <IconScale /> },
|
||||
...(isAdmin ? [{ label: 'Serverpuls', href: '/serverpuls', icon: <IconActivityHeartbeat />, dot: pulseLevel }] : []),
|
||||
...(isAdmin ? [{ label: 'Admin', href: '/admin', icon: <IconSettings /> }] : []),
|
||||
]
|
||||
// Eintraege und Unterpunkte (Kunden -> Chat) aus lib/navLinks.js, Icons ueber key
|
||||
const links = buildNavLinks({ isAdmin, pulseLevel, chatUnread })
|
||||
|
||||
const isActive = (href) =>
|
||||
location.pathname === href || location.pathname.startsWith(href + '/')
|
||||
@@ -92,7 +98,7 @@ export default function Sidebar() {
|
||||
title={`${link.label} (pausiert)`}
|
||||
aria-disabled="true"
|
||||
>
|
||||
{link.icon}
|
||||
{ICONS[link.key]}
|
||||
<span className="side-link-label">{link.label}</span>
|
||||
</span>
|
||||
) : (
|
||||
@@ -102,7 +108,7 @@ export default function Sidebar() {
|
||||
className={`side-link ${isLinkActive(link) ? 'active' : ''}`}
|
||||
title={link.label}
|
||||
>
|
||||
{link.icon}
|
||||
{ICONS[link.key]}
|
||||
<span className="side-link-label">{link.label}</span>
|
||||
{link.dot && link.dot !== 'ok' && (
|
||||
<span
|
||||
@@ -112,7 +118,21 @@ export default function Sidebar() {
|
||||
/>
|
||||
)}
|
||||
</Link>
|
||||
))}
|
||||
)).flatMap((item, i) => [
|
||||
item,
|
||||
...(links[i].children || []).map((child) => (
|
||||
<Link
|
||||
key={child.href}
|
||||
to={child.href}
|
||||
className={`side-link side-sublink ${isActive(child.href) ? 'active' : ''}`}
|
||||
title={child.count > 0 ? `${child.label} (${child.count} ungelesen)` : child.label}
|
||||
>
|
||||
{ICONS[child.key]}
|
||||
<span className="side-link-label">{child.label}</span>
|
||||
{child.count > 0 && <span className="side-count">{child.count}</span>}
|
||||
</Link>
|
||||
)),
|
||||
])}
|
||||
<button
|
||||
type="button"
|
||||
className="side-link side-link-button"
|
||||
|
||||
Reference in new issue
Block a user