From 8a9c1ae6a9cd8d5a661bef833b9d35aa94589701 Mon Sep 17 00:00:00 2001 From: Schalli Date: Wed, 24 Jun 2026 11:23:47 +0200 Subject: [PATCH] feat(05-01): settings shell, header link, and i18n keys for dashboard phase - Create settings/layout.tsx with SettingsSidebar and back-to-dashboard link - Create settings/page.tsx with redirect to /settings/dashboard - Create settings-sidebar.tsx with Widgets and Calendar nav items, aria-current - Add Settings link in header user dropdown (gear icon, before logout) - Add settings namespace (DE+EN) with all category and action keys - Add widgets namespace (DE+EN) with all widget names, descriptions, error states - Add header.settings key ("Einstellungen"/"Settings") Co-Authored-By: Claude Sonnet 4.6 --- apps/web/src/app/(portal)/settings/layout.tsx | 47 ++++++++++++++ apps/web/src/app/(portal)/settings/page.tsx | 8 +++ apps/web/src/components/layout/header.tsx | 26 ++++++++ .../components/settings/settings-sidebar.tsx | 64 +++++++++++++++++++ apps/web/src/messages/de.json | 43 +++++++++++++ apps/web/src/messages/en.json | 43 +++++++++++++ 6 files changed, 231 insertions(+) create mode 100644 apps/web/src/app/(portal)/settings/layout.tsx create mode 100644 apps/web/src/app/(portal)/settings/page.tsx create mode 100644 apps/web/src/components/settings/settings-sidebar.tsx diff --git a/apps/web/src/app/(portal)/settings/layout.tsx b/apps/web/src/app/(portal)/settings/layout.tsx new file mode 100644 index 0000000..37fd430 --- /dev/null +++ b/apps/web/src/app/(portal)/settings/layout.tsx @@ -0,0 +1,47 @@ +'use client'; + +import Link from 'next/link'; +import { useTranslations } from 'next-intl'; +import { SettingsSidebar } from '@/components/settings/settings-sidebar'; + +/** + * Settings nested layout (D-19, D-20). + * Renders within the portal AppShell, adding its own sub-sidebar on the left. + * Back-to-dashboard link at top of content area per UI-SPEC. + */ +export default function SettingsLayout({ + children, +}: { + children: React.ReactNode; +}) { + const t = useTranslations('settings'); + + return ( +
+ +
+ {/* Back to Dashboard link */} + + + + + {t('backToDashboard')} + + {children} +
+
+ ); +} diff --git a/apps/web/src/app/(portal)/settings/page.tsx b/apps/web/src/app/(portal)/settings/page.tsx new file mode 100644 index 0000000..e820358 --- /dev/null +++ b/apps/web/src/app/(portal)/settings/page.tsx @@ -0,0 +1,8 @@ +import { redirect } from 'next/navigation'; + +/** + * Settings index page — redirects to /settings/dashboard (the default category). + */ +export default function SettingsPage() { + redirect('/settings/dashboard'); +} diff --git a/apps/web/src/components/layout/header.tsx b/apps/web/src/components/layout/header.tsx index 1267158..878bd99 100644 --- a/apps/web/src/components/layout/header.tsx +++ b/apps/web/src/components/layout/header.tsx @@ -1,6 +1,7 @@ 'use client'; import { useEffect, useRef, useState } from 'react'; +import Link from 'next/link'; import { useTranslations } from 'next-intl'; import { useSidebarStore } from '@/lib/stores/sidebar-store'; import { useAuthStore } from '@/lib/stores/auth-store'; @@ -128,6 +129,31 @@ export function Header() { )} + {/* Settings link */} +
+ setDropdownOpen(false)} + className="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm text-foreground hover:bg-muted transition-colors" + > + + + + + {tHeader('settings')} + +
+ {/* Logout button */}