From b9e044de996878565a9351beeb7d79b9f68c6311 Mon Sep 17 00:00:00 2001 From: fuomag9 <1580624+fuomag9@users.noreply.github.com> Date: Sun, 22 Mar 2026 11:38:35 +0100 Subject: [PATCH] feat: rewrite dashboard layout with shadcn Sheet + Tailwind sidebar Co-Authored-By: Claude Sonnet 4.6 --- app/(dashboard)/DashboardLayoutClient.tsx | 355 +++++++++------------- 1 file changed, 143 insertions(+), 212 deletions(-) diff --git a/app/(dashboard)/DashboardLayoutClient.tsx b/app/(dashboard)/DashboardLayoutClient.tsx index 4e438fd9..28c9a447 100644 --- a/app/(dashboard)/DashboardLayoutClient.tsx +++ b/app/(dashboard)/DashboardLayoutClient.tsx @@ -1,37 +1,19 @@ "use client"; -import { ReactNode, useState, useEffect } from "react"; +import { ReactNode, useState } from "react"; import Link from "next/link"; import { usePathname, useRouter } from "next/navigation"; +import { useTheme } from "next-themes"; import { - AppBar, - Avatar, - Box, - Button, - Divider, - Drawer, - List, - ListItemButton, - ListItemIcon, - ListItemText, - Stack, - Toolbar, - Typography, - useTheme, - useMediaQuery, - IconButton -} from "@mui/material"; -import MenuIcon from "@mui/icons-material/Menu"; -import DashboardIcon from "@mui/icons-material/Dashboard"; -import SwapHorizIcon from "@mui/icons-material/SwapHoriz"; -import BarChartIcon from "@mui/icons-material/BarChart"; -import VpnKeyIcon from "@mui/icons-material/VpnKey"; -import SecurityIcon from "@mui/icons-material/Security"; -import SettingsIcon from "@mui/icons-material/Settings"; -import HistoryIcon from "@mui/icons-material/History"; -import GppBadIcon from "@mui/icons-material/GppBad"; -import CableIcon from "@mui/icons-material/Cable"; -import LogoutIcon from "@mui/icons-material/Logout"; + LayoutDashboard, ArrowLeftRight, Cable, KeyRound, ShieldCheck, + ShieldOff, BarChart2, History, Settings, LogOut, Menu, Sun, Moon, +} from "lucide-react"; +import { Sheet, SheetContent } from "@/src/components/ui/sheet"; +import { Button } from "@/src/components/ui/button"; +import { Avatar, AvatarFallback, AvatarImage } from "@/src/components/ui/avatar"; +import { Separator } from "@/src/components/ui/separator"; +import { ScrollArea } from "@/src/components/ui/scroll-area"; +import { cn } from "@/src/lib/utils"; type User = { id: string; @@ -41,204 +23,153 @@ type User = { }; const NAV_ITEMS = [ - { href: "/", label: "Overview", icon: DashboardIcon }, - { href: "/proxy-hosts", label: "Proxy Hosts", icon: SwapHorizIcon }, - { href: "/l4-proxy-hosts", label: "L4 Proxy Hosts", icon: CableIcon }, - { href: "/access-lists", label: "Access Lists", icon: VpnKeyIcon }, - { href: "/certificates", label: "Certificates", icon: SecurityIcon }, - { href: "/waf", label: "WAF", icon: GppBadIcon }, - { href: "/analytics", label: "Analytics", icon: BarChartIcon }, - { href: "/audit-log", label: "Audit Log", icon: HistoryIcon }, - { href: "/settings", label: "Settings", icon: SettingsIcon }, + { href: "/", label: "Overview", icon: LayoutDashboard }, + { href: "/proxy-hosts", label: "Proxy Hosts", icon: ArrowLeftRight }, + { href: "/l4-proxy-hosts", label: "L4 Proxy Hosts", icon: Cable }, + { href: "/access-lists", label: "Access Lists", icon: KeyRound }, + { href: "/certificates", label: "Certificates", icon: ShieldCheck }, + { href: "/waf", label: "WAF", icon: ShieldOff }, + { href: "/analytics", label: "Analytics", icon: BarChart2 }, + { href: "/audit-log", label: "Audit Log", icon: History }, + { href: "/settings", label: "Settings", icon: Settings }, ] as const; -const DRAWER_WIDTH = 260; -const APP_BAR_HEIGHT = 48; +function ThemeToggle() { + const { theme, setTheme } = useTheme(); + return ( + + ); +} -export default function DashboardLayoutClient({ user, children }: { user: User; children: ReactNode }) { - const [mobileOpen, setMobileOpen] = useState(false); - const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down("md")); - const pathname = usePathname(); +function NavContent({ pathname, user, onNavigate }: { + pathname: string; + user: User; + onNavigate?: () => void; +}) { const router = useRouter(); - const handleDrawerToggle = () => { - setMobileOpen(!mobileOpen); - }; + return ( +
+ {/* Logo */} +
+

Caddy Proxy

+

Manager

+
- useEffect(() => { - if (isMobile) setMobileOpen(false); - }, [pathname, isMobile]); + {/* Nav items */} + + + - const drawerContent = ( - - - - Caddy Proxy - - - Manager - - - - - {NAV_ITEMS.map((item) => { - const selected = pathname === item.href; - const Icon = item.icon; - return ( - - - - - - - ); - })} - - - - - router.push("/profile")} - sx={{ - gap: 2, - px: 1, - mb: 2, - py: 1, - borderRadius: 1, - color: "text.primary" - }} + {/* Footer */} +
+ +
- - - ); - - return ( - - {isMobile && ( - - - - - - - Caddy Proxy Manager - - - - )} - - - - {drawerContent} - - - - - - {children} - - - +
+
+ ); +} + +export default function DashboardLayoutClient({ user, children }: { user: User; children: ReactNode }) { + const [mobileOpen, setMobileOpen] = useState(false); + const pathname = usePathname(); + const router = useRouter(); + + return ( +
+ {/* Desktop sidebar — fixed, hidden on mobile */} + + + {/* Mobile top bar */} +
+ + Caddy Proxy Manager +
+ + +
+
+ + {/* Mobile Sheet drawer */} + + + setMobileOpen(false)} /> + + + + {/* Main content */} +
+
+ {/* Theme toggle for desktop — top-right corner */} +
+ +
+ {children} +
+
+
); }