From beb4169b03e0edfd7f95034dfd5b044a68402c41 Mon Sep 17 00:00:00 2001 From: Agent Zero Date: Thu, 30 Jul 2026 20:02:28 +0200 Subject: [PATCH] feat: start page after login with workspace grid, login redirect to /start --- .../src/components/layout/StartLayout.tsx | 28 ++++ frontend/src/pages/Login.tsx | 2 +- frontend/src/pages/StartPage.tsx | 137 ++++++++++++++++++ frontend/src/routes/index.tsx | 14 +- 4 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 frontend/src/components/layout/StartLayout.tsx create mode 100644 frontend/src/pages/StartPage.tsx diff --git a/frontend/src/components/layout/StartLayout.tsx b/frontend/src/components/layout/StartLayout.tsx new file mode 100644 index 0000000..76b94cb --- /dev/null +++ b/frontend/src/components/layout/StartLayout.tsx @@ -0,0 +1,28 @@ +/** + * Start layout — TopBar + StartPage, no Sidebar. + * Used for the /start route after login. + */ + +import React from 'react'; +import { TopBar } from './TopBar'; +import { ToastContainer } from '@/components/ui/Toast'; +import { PluginRegistry } from '@/components/plugins/PluginRegistry'; +import { ErrorBoundary } from '@/components/ErrorBoundary'; +import { Outlet } from 'react-router-dom'; + +export function StartLayout() { + return ( +
+ +
+ +
+ + + +
+
+ +
+ ); +} diff --git a/frontend/src/pages/Login.tsx b/frontend/src/pages/Login.tsx index 0f35983..9b4a033 100644 --- a/frontend/src/pages/Login.tsx +++ b/frontend/src/pages/Login.tsx @@ -37,7 +37,7 @@ export function LoginPage() { try { await loginMutation.mutateAsync(data); addToast({ type: 'success', message: t('auth.login') + ' erfolgreich' }); - navigate('/dashboard'); + navigate('/start'); } catch (error: any) { const msg = error.message || t('auth.loginFailed'); setSubmitError(msg); diff --git a/frontend/src/pages/StartPage.tsx b/frontend/src/pages/StartPage.tsx new file mode 100644 index 0000000..56ccdd5 --- /dev/null +++ b/frontend/src/pages/StartPage.tsx @@ -0,0 +1,137 @@ +/** + * Start page — shown after login. + * 2-column layout: left menu, right grid with workspace tiles. + */ + +import React from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { useAuthStore } from '@/store/authStore'; +import { Settings, HelpCircle, LayoutGrid, ArrowRight, Plus } from 'lucide-react'; + +// Workspace tile definition +interface WorkspaceTile { + id: string; + name: string; + description: string; + icon: React.ReactNode; + color: string; + path: string; +} + +const DEFAULT_WORKSPACES: WorkspaceTile[] = [ + { + id: 'main', + name: 'Haupt-Workspace', + description: 'Kontakte, Kalender, Mail und mehr', + icon: , + color: 'from-blue-500 to-blue-600', + path: '/dashboard', + }, +]; + +export function StartPage() { + const { t } = useTranslation(); + const navigate = useNavigate(); + const user = useAuthStore((state) => state.user); + + const menuItems = [ + { id: 'workspaces', label: 'Workspaces', icon: , active: true }, + { id: 'settings', label: 'Einstellungen', icon: , onClick: () => navigate('/settings') }, + { id: 'help', label: 'Hilfe', icon: , onClick: () => window.open('/docs', '_blank') }, + ]; + + return ( +
+ {/* Left column — menu */} + + + {/* Right column — workspace grid */} +
+
+
+

Willkommen{user?.first_name ? `, ${user.first_name}` : ''}!

+

Wähle einen Workspace aus

+
+ + {/* Masonry-style grid */} +
+ {DEFAULT_WORKSPACES.map((ws) => ( + + ))} + + {/* Add workspace placeholder */} + +
+
+
+
+ ); +} diff --git a/frontend/src/routes/index.tsx b/frontend/src/routes/index.tsx index 67cacbb..cd0d7d1 100644 --- a/frontend/src/routes/index.tsx +++ b/frontend/src/routes/index.tsx @@ -1,6 +1,7 @@ import React, { Suspense } from 'react'; import { createBrowserRouter, RouterProvider } from 'react-router-dom'; import { AppShell } from '@/components/layout/AppShell'; +import { StartLayout } from '@/components/layout/StartLayout'; import { ProtectedRoute } from './ProtectedRoute'; import { ProtectedRoute as PermissionRoute } from '@/components/common/ProtectedRoute'; import { LoginPage } from '@/pages/Login'; @@ -65,6 +66,7 @@ const SettingsWebhooksPage = React.lazy(() => import('@/pages/SettingsWebhooks') const SettingsBackupPage = React.lazy(() => import('@/pages/SettingsBackup').then(m => ({ default: m.SettingsBackupPage }))); const SettingsRechtePage = React.lazy(() => import('@/pages/SettingsRechte').then(m => ({ default: m.SettingsRechtePage }))); const NoAccessPage = React.lazy(() => import('@/pages/NoAccessPage').then(m => ({ default: m.NoAccessPage }))); +const StartPage = React.lazy(() => import('@/pages/StartPage').then(m => ({ default: m.StartPage }))); /** Centered spinner fallback for lazy-loaded routes */ function PageLoader() { @@ -125,6 +127,16 @@ const router = createBrowserRouter([ path: '/kein-zugriff', element: {withSuspense()}, }, + { + element: ( + + + + ), + children: [ + { path: '/start', element: withSuspense() }, + ], + }, { element: ( @@ -132,7 +144,7 @@ const router = createBrowserRouter([ ), children: [ - { path: '/', element: withSuspense() }, + { path: '/', element: }, { path: '/dashboard', element: withSuspense() }, { path: '/contacts', element: {withSuspense()} }, { path: '/contacts/:id', element: {withSuspense()} },