feat(help): help page with tree navigation, 6 help articles, routes in StartLayout
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
import React, { useState } from 'react';
|
||||
import { NavLink, Outlet, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useUIStore } from '@/store/uiStore';
|
||||
import { ChevronRight, ChevronDown, BookOpen, Users, Calendar, Mail, FolderOpen, Settings, Shield, Zap, Bot } from 'lucide-react';
|
||||
|
||||
interface HelpNode {
|
||||
title: string;
|
||||
path?: string;
|
||||
icon?: React.ReactNode;
|
||||
children?: HelpNode[];
|
||||
}
|
||||
|
||||
const HELP_TREE: HelpNode[] = [
|
||||
{
|
||||
title: 'Erste Schritte',
|
||||
icon: <BookOpen className="w-4 h-4" />,
|
||||
children: [
|
||||
{ title: 'Willkommen', path: '/help/welcome' },
|
||||
{ title: 'Login & Anmeldung', path: '/help/login' },
|
||||
{ title: 'Navigation', path: '/help/navigation' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Kontakte',
|
||||
icon: <Users className="w-4 h-4" />,
|
||||
children: [
|
||||
{ title: 'Kontakte verwalten', path: '/help/contacts' },
|
||||
{ title: 'Kontaktpersonen', path: '/help/contact-persons' },
|
||||
{ title: 'Import & Export', path: '/help/import-export' },
|
||||
{ title: 'Duplikate finden', path: '/help/dedup' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Kalender',
|
||||
icon: <Calendar className="w-4 h-4" />,
|
||||
children: [
|
||||
{ title: 'Termine erstellen', path: '/help/calendar' },
|
||||
{ title: 'Kanban-Ansicht', path: '/help/calendar-kanban' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'E-Mail',
|
||||
icon: <Mail className="w-4 h-4" />,
|
||||
children: [
|
||||
{ title: 'Postfach einrichten', path: '/help/mail-setup' },
|
||||
{ title: 'Mails verwalten', path: '/help/mail-usage' },
|
||||
{ title: 'Signaturen & Vorlagen', path: '/help/mail-signatures' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Dateien (DMS)',
|
||||
icon: <FolderOpen className="w-4 h-4" />,
|
||||
children: [
|
||||
{ title: 'Dateien hochladen', path: '/help/dms-upload' },
|
||||
{ title: 'Ordner & Berechtigungen', path: '/help/dms-folders' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Einstellungen',
|
||||
icon: <Settings className="w-4 h-4" />,
|
||||
children: [
|
||||
{ title: 'Stammdaten', path: '/help/settings-stammdaten' },
|
||||
{ title: 'Benutzerverwaltung', path: '/help/settings-users' },
|
||||
{ title: 'Rollen & Rechte', path: '/help/settings-roles' },
|
||||
{ title: 'Plugins', path: '/help/settings-plugins' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Sicherheit',
|
||||
icon: <Shield className="w-4 h-4" />,
|
||||
children: [
|
||||
{ title: 'Passwörter', path: '/help/security-passwords' },
|
||||
{ title: 'Datenschutz (DSGVO)', path: '/help/security-gdpr' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Automation & KI',
|
||||
icon: <Bot className="w-4 h-4" />,
|
||||
children: [
|
||||
{ title: 'KI-Assistent', path: '/help/ai-assistant' },
|
||||
{ title: 'Workflows', path: '/help/workflows' },
|
||||
{ title: 'Automation', path: '/help/automation' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
function TreeItem({ node, depth }: { node: HelpNode; depth: number }) {
|
||||
const [expanded, setExpanded] = useState(depth < 1);
|
||||
const hasChildren = node.children && node.children.length > 0;
|
||||
const paddingLeft = depth * 16 + 12;
|
||||
|
||||
if (hasChildren) {
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
onClick={() => setExpanded(!expanded)}
|
||||
className="w-full flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium text-secondary-700 hover:bg-secondary-100 transition-colors min-h-touch"
|
||||
style={{ paddingLeft }}
|
||||
aria-expanded={expanded}
|
||||
>
|
||||
{expanded ? <ChevronDown className="w-3.5 h-3.5 flex-shrink-0" /> : <ChevronRight className="w-3.5 h-3.5 flex-shrink-0" />}
|
||||
{node.icon}
|
||||
<span>{node.title}</span>
|
||||
</button>
|
||||
{expanded && (
|
||||
<div>
|
||||
{node.children!.map((child) => (
|
||||
<TreeItem key={child.path || child.title} node={child} depth={depth + 1} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<NavLink
|
||||
to={node.path!}
|
||||
className={({ isActive }) =>
|
||||
`flex items-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors min-h-touch ${
|
||||
isActive
|
||||
? 'bg-primary-100 text-primary-700 font-medium'
|
||||
: 'text-secondary-600 hover:bg-secondary-100 hover:text-secondary-900'
|
||||
}`
|
||||
}
|
||||
style={{ paddingLeft: paddingLeft + 20 }}
|
||||
>
|
||||
{node.icon}
|
||||
<span>{node.title}</span>
|
||||
</NavLink>
|
||||
);
|
||||
}
|
||||
|
||||
export function HelpPage() {
|
||||
const { t } = useTranslation();
|
||||
const sidebarOpen = useUIStore((state) => state.sidebarOpen);
|
||||
|
||||
return (
|
||||
<div className="flex h-full overflow-hidden" data-testid="help-page">
|
||||
<aside className={`${sidebarOpen ? 'w-64 border-r border-secondary-200' : 'w-0'} flex-shrink-0 min-h-[calc(100vh-4rem)] transition-all duration-200 overflow-hidden`}>
|
||||
<div className="w-64 flex-shrink-0 p-4">
|
||||
<h1 className="text-xl font-bold text-secondary-900 mb-4">Hilfe</h1>
|
||||
<nav className="space-y-0.5 overflow-y-auto" role="navigation" aria-label="Hilfe Navigation">
|
||||
{HELP_TREE.map((node) => (
|
||||
<TreeItem key={node.title} node={node} depth={0} />
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
<main className="flex-1 p-6 overflow-y-auto" data-testid="help-content">
|
||||
<Outlet />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user