Implement shadcn/ui + Tailwind CSS UI layer

- Design token system via CSS custom properties (light/dark mode)
- Theme context hook + ThemeToggle component
- AppShell + collapsible Sidebar replace inline Nav
- LoginPage redesigned: two-column grid with hero panel
- shadcn/ui Button and Input components
- Tailwind config wired to CSS variable tokens
- All pages de-Nav'd; PrivateRoute/AdminRoute wrap with AppShell
- TypeScript passes clean (npm run typecheck)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-04-17 12:32:06 +02:00
parent 9e2e4ec338
commit c3f87706ee
26 changed files with 1263 additions and 89 deletions
+7 -2
View File
@@ -2,6 +2,7 @@ import { Routes, Route, Navigate } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import { useAuth } from "./hooks/useAuth";
import { getMe } from "./api/client";
import AppShell from "./components/AppShell";
import LoginPage from "./pages/LoginPage";
import DashboardPage from "./pages/DashboardPage";
import ProfilePage from "./pages/ProfilePage";
@@ -13,7 +14,11 @@ import AIAdminSettingsPage from "./pages/AIAdminSettingsPage";
function PrivateRoute({ children }: { children: React.ReactNode }) {
const { token } = useAuth();
return token ? <>{children}</> : <Navigate to="/login" replace />;
return token ? (
<AppShell>{children}</AppShell>
) : (
<Navigate to="/login" replace />
);
}
function AdminRoute({ children }: { children: React.ReactNode }) {
@@ -25,7 +30,7 @@ function AdminRoute({ children }: { children: React.ReactNode }) {
if (isLoading) return null;
// Redirect to /login (not /) so the route appears not to exist
if (!user?.is_admin) return <Navigate to="/login" replace />;
return <>{children}</>;
return <AppShell>{children}</AppShell>;
}
export default function App() {