feat: Implement initial Caddy panel UI with new pages, components, and styling, along with updated dependencies.

This commit is contained in:
BLACK
2025-12-08 22:47:42 +01:00
parent ea8e3a5f7c
commit 774432b720
38 changed files with 3124 additions and 250 deletions

View File

@@ -0,0 +1,21 @@
.container {
display: flex;
min-height: 100vh;
background-color: var(--bg-app);
}
.main {
flex: 1;
display: flex;
flex-direction: column;
overflow-y: auto;
height: 100vh;
}
.content {
flex: 1;
padding: var(--spacing-xl);
max-width: 1400px;
margin: 0 auto;
width: 100%;
}

View File

@@ -0,0 +1,15 @@
import { Sidebar } from "./Sidebar";
import styles from "./AppLayout.module.css";
export function AppLayout({ children }: { children: React.ReactNode }) {
return (
<div className={styles.container}>
<Sidebar />
<main className={styles.main}>
<div className={styles.content}>
{children}
</div>
</main>
</div>
);
}

View File

@@ -0,0 +1,100 @@
.sidebar {
width: 260px;
height: 100vh;
background-color: var(--bg-surface);
border-right: 1px solid var(--border-color);
display: flex;
flex-direction: column;
padding: var(--spacing-md);
flex-shrink: 0;
}
.header {
padding: var(--spacing-sm) var(--spacing-sm) var(--spacing-xl);
}
.logo {
display: flex;
align-items: center;
gap: var(--spacing-md);
font-weight: 700;
font-size: 1.25rem;
color: var(--text-main);
letter-spacing: -0.02em;
}
.logoIcon {
color: var(--color-primary);
}
.nav {
display: flex;
flex-direction: column;
gap: var(--spacing-xs);
flex: 1;
}
.link {
display: flex;
align-items: center;
gap: var(--spacing-md);
padding: var(--spacing-md);
border-radius: var(--radius-md);
color: var(--text-muted);
transition: all 0.2s ease;
font-weight: 500;
}
.link:hover {
background-color: var(--bg-surface-hover);
color: var(--text-main);
}
.active {
background-color: var(--bg-surface-active);
color: var(--color-primary);
}
.footer {
padding-top: var(--spacing-md);
border-top: 1px solid var(--border-color);
}
.status {
display: flex;
align-items: center;
gap: var(--spacing-sm);
font-size: 0.875rem;
color: var(--text-muted);
}
.statusDot {
width: 8px;
height: 8px;
background-color: var(--status-success);
border-radius: 50%;
box-shadow: 0 0 8px rgba(34, 197, 94, 0.4);
}
.notificationWrapper {
position: relative;
display: flex;
align-items: center;
}
.notificationBadge {
position: absolute;
top: -4px;
right: -4px;
background-color: var(--status-error);
color: white;
font-size: 0.625rem;
font-weight: 700;
min-width: 14px;
height: 14px;
border-radius: 7px;
display: flex;
align-items: center;
justify-content: center;
padding: 0 3px;
}

View File

@@ -0,0 +1,81 @@
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import {
LayoutDashboard,
Network,
ShieldCheck,
FileText,
Settings,
Globe,
Code,
Package,
Bell,
Server
} from "lucide-react";
import clsx from "clsx";
import styles from "./Sidebar.module.css";
const MENU_ITEMS = [
{ label: "Dashboard", href: "/", icon: LayoutDashboard },
{ label: "Einstellungen", href: "/settings", icon: Settings },
{ label: "Domains", href: "/domains", icon: Globe },
{ label: "Proxy Regeln", href: "/proxy", icon: Network },
{ label: "Zertifikate", href: "/certs", icon: ShieldCheck },
{ label: "Logs", href: "/logs", icon: FileText },
{ label: "API Explorer", href: "/api", icon: Code },
{ label: "Plugins", href: "/plugins", icon: Package },
];
export function Sidebar() {
const pathname = usePathname();
return (
<aside className={styles.sidebar}>
<div className={styles.header}>
<div className={styles.logo}>
<Server className={styles.logoIcon} size={28} />
<span>CaddyPanel</span>
</div>
</div>
<nav className={styles.nav}>
{MENU_ITEMS.map((item) => {
const Icon = item.icon;
const isActive = pathname === item.href;
return (
<Link
key={item.href}
href={item.href}
className={clsx(styles.link, isActive && styles.active)}
>
<Icon size={20} />
<span>{item.label}</span>
</Link>
);
})}
</nav>
<div className={styles.footer}>
<Link
href="/notifications"
className={clsx(styles.link, pathname === "/notifications" && styles.active)}
style={{ marginBottom: 'var(--spacing-md)' }}
>
<div className={styles.notificationWrapper}>
<Bell size={20} />
<span className={styles.notificationBadge}>3</span>
</div>
<span>Benachrichtigungen</span>
</Link>
<div className={styles.status}>
<div className={styles.statusDot} />
<span>System Online</span>
</div>
</div>
</aside>
);
}