From ba02b25cba5fde2f65f58a7ba452a96ff633ed5f Mon Sep 17 00:00:00 2001 From: Schalli Date: Fri, 26 Jun 2026 08:34:19 +0200 Subject: [PATCH] refactor(ui): restructure sidebar and admin navigation - Sidebar: remove footer (user info, settings, locale switcher), remove admin section, make category headers static with per-category collapse toggle - Header dropdown: replace inline admin links with single "Administrator" entry - Admin section: dedicated layout with AdminSidebar (mirrors Settings pattern) at /admin/* - Disable self-delete button in user management (backend already rejects with 403) Co-Authored-By: Claude Sonnet 4.6 --- apps/web/src/app/(portal)/admin/layout.tsx | 41 +++++ .../web/src/app/(portal)/admin/users/page.tsx | 3 +- .../src/components/admin/admin-sidebar.tsx | 97 +++++++++++ apps/web/src/components/layout/header.tsx | 25 +++ apps/web/src/components/layout/sidebar.tsx | 153 ++++++------------ apps/web/src/messages/de.json | 7 + apps/web/src/messages/en.json | 7 + 7 files changed, 229 insertions(+), 104 deletions(-) create mode 100644 apps/web/src/app/(portal)/admin/layout.tsx create mode 100644 apps/web/src/components/admin/admin-sidebar.tsx diff --git a/apps/web/src/app/(portal)/admin/layout.tsx b/apps/web/src/app/(portal)/admin/layout.tsx new file mode 100644 index 0000000..afa4c11 --- /dev/null +++ b/apps/web/src/app/(portal)/admin/layout.tsx @@ -0,0 +1,41 @@ +'use client'; + +import Link from 'next/link'; +import { useTranslations } from 'next-intl'; +import { AdminSidebar } from '@/components/admin/admin-sidebar'; + +export default function AdminLayout({ + children, +}: { + children: React.ReactNode; +}) { + const t = useTranslations('settings'); + + return ( +
+ +
+ + + + + {t('backToDashboard')} + + {children} +
+
+ ); +} diff --git a/apps/web/src/app/(portal)/admin/users/page.tsx b/apps/web/src/app/(portal)/admin/users/page.tsx index 5fbe6ff..ec85774 100644 --- a/apps/web/src/app/(portal)/admin/users/page.tsx +++ b/apps/web/src/app/(portal)/admin/users/page.tsx @@ -253,7 +253,8 @@ export default function AdminUsersPage() { diff --git a/apps/web/src/components/admin/admin-sidebar.tsx b/apps/web/src/components/admin/admin-sidebar.tsx new file mode 100644 index 0000000..0f4cbf5 --- /dev/null +++ b/apps/web/src/components/admin/admin-sidebar.tsx @@ -0,0 +1,97 @@ +'use client'; + +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import { useTranslations } from 'next-intl'; +import { useAuthStore } from '@/lib/stores/auth-store'; + +export function AdminSidebar() { + const t = useTranslations('header'); + const pathname = usePathname(); + const user = useAuthStore((s) => s.user); + const isSuperAdmin = user?.role === 'SUPER_ADMIN'; + + const items = [ + { + label: t('admin.users'), + href: '/admin/users', + show: true, + icon: ( + + + + + + + ), + }, + { + label: t('admin.tenants'), + href: '/admin/tenants', + show: isSuperAdmin, + icon: ( + + + + + ), + }, + { + label: t('admin.modules'), + href: '/admin/modules', + show: true, + icon: ( + + + + + + ), + }, + { + label: t('admin.ldap'), + href: '/admin/ldap', + show: true, + icon: ( + + + + + + ), + }, + ]; + + return ( + + ); +} diff --git a/apps/web/src/components/layout/header.tsx b/apps/web/src/components/layout/header.tsx index 878bd99..4d1badd 100644 --- a/apps/web/src/components/layout/header.tsx +++ b/apps/web/src/components/layout/header.tsx @@ -7,6 +7,7 @@ import { useSidebarStore } from '@/lib/stores/sidebar-store'; import { useAuthStore } from '@/lib/stores/auth-store'; import { fetchCurrentUser, logout } from '@/lib/auth-actions'; import { ThemeToggle } from '@/components/theme-toggle'; +import { usePathname } from 'next/navigation'; export function Header() { const t = useTranslations(); @@ -15,6 +16,9 @@ export function Header() { const { user, setUser } = useAuthStore(); const [dropdownOpen, setDropdownOpen] = useState(false); const dropdownRef = useRef(null); + const pathname = usePathname(); + + const isAdmin = user?.role === 'ADMIN' || user?.role === 'SUPER_ADMIN'; // Fetch current user on mount to populate auth store useEffect(() => { @@ -154,7 +158,28 @@ export function Header() { + {/* Administration link */} + {isAdmin && ( +
+ setDropdownOpen(false)} + className={`flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors ${ + pathname.startsWith('/admin') + ? 'bg-muted text-foreground font-medium' + : 'text-foreground hover:bg-muted' + }`} + > + + + + {tHeader('admin.label')} + +
+ )} + {/* Logout button */} +
- - {categoriesOpen && ( -
- {activeModules.length === 0 ? ( -
- {t('categories.empty')} -
- ) : filteredCategories.length === 0 ? ( -
- {t('noResults')} -
- ) : ( -
    - {filteredCategories.map(([category, mods]) => ( -
  • - - - +
    + {t('categories.label')} +
    +
    + {activeModules.length === 0 ? ( +
    + {t('categories.empty')} +
    + ) : filteredCategories.length === 0 ? ( +
    + {t('noResults')} +
    + ) : ( +
      + {filteredCategories.map(([category, mods]) => ( +
    • + + {openCategories.has(category) && (
        {mods.map((mod) => (
      • @@ -172,69 +174,15 @@ export function Sidebar() {
      • ))}
      -
    • - ))} -
    - )} -
    - )} + )} +
  • + ))} +
+ )} +
)} - - {isAdmin && ( -
- {!isCollapsed && ( -
- {t('admin')} -
- )} -
    -
  • - - - - - - - - {!isCollapsed && {t('users')}} - -
  • - {isSuperAdmin && ( -
  • - - - - - - {!isCollapsed && {t('tenants')}} - -
  • - )} -
  • - - - - - - - {!isCollapsed && {t('modules')}} - -
  • -
  • - - - - - - - {!isCollapsed && {t('ldap')}} - -
  • -
-
- )}
@@ -250,7 +198,6 @@ export function Sidebar() {
-
); diff --git a/apps/web/src/messages/de.json b/apps/web/src/messages/de.json index e2a814c..917f6a9 100644 --- a/apps/web/src/messages/de.json +++ b/apps/web/src/messages/de.json @@ -69,6 +69,13 @@ }, "settings": "Einstellungen", "logout": "Abmelden", + "admin": { + "label": "Administrator", + "users": "Benutzer", + "tenants": "Mandanten", + "modules": "Module", + "ldap": "LDAP" + }, "role": { "SUPER_ADMIN": "Super-Admin", "ADMIN": "Admin", diff --git a/apps/web/src/messages/en.json b/apps/web/src/messages/en.json index 6deef92..112cd3b 100644 --- a/apps/web/src/messages/en.json +++ b/apps/web/src/messages/en.json @@ -69,6 +69,13 @@ }, "settings": "Settings", "logout": "Sign Out", + "admin": { + "label": "Administration", + "users": "Users", + "tenants": "Tenants", + "modules": "Modules", + "ldap": "LDAP" + }, "role": { "SUPER_ADMIN": "Super Admin", "ADMIN": "Admin",