mirror of
https://github.com/crocofied/CoreControl.git
synced 2025-12-17 15:36:50 +00:00
Sidebar
This commit is contained in:
parent
9b4d2e9735
commit
ec8c5ffc03
@ -30,7 +30,7 @@ export async function POST(request: NextRequest) {
|
||||
return NextResponse.json({ error: "User not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
return NextResponse.json({ message: "Valid" }, { status: 200 });
|
||||
return NextResponse.json({ message: "Valid", username: user.username, name: user.name }, { status: 200 });
|
||||
|
||||
} catch (error: any) {
|
||||
return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
|
||||
|
||||
@ -1,9 +1,20 @@
|
||||
"use client";
|
||||
|
||||
import Sidebar from "@/components/Sidebar";
|
||||
|
||||
export default function DashboardPage() {
|
||||
interface DashboardPageProps {
|
||||
username: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default function DashboardPage({ username, name }: DashboardPageProps) {
|
||||
return (
|
||||
<div>
|
||||
<h1>Dashboard</h1>
|
||||
<Sidebar username={username} fullName={name}>
|
||||
<main>
|
||||
<h1>Dashboard</h1>
|
||||
</main>
|
||||
</Sidebar>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -11,6 +11,8 @@ import Cookies from "js-cookie";
|
||||
export default function Dashboard() {
|
||||
const router = useRouter();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [username, setUsername] = useState("");
|
||||
const [name, setName] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
const init = async () => {
|
||||
@ -23,6 +25,8 @@ export default function Dashboard() {
|
||||
Cookies.remove("token");
|
||||
router.push("/");
|
||||
} else {
|
||||
setUsername(response.data.username);
|
||||
setName(response.data.name);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
@ -32,6 +36,6 @@ export default function Dashboard() {
|
||||
if (loading) {
|
||||
return <Loading />;
|
||||
} else {
|
||||
return <DashboardPage />;
|
||||
return <DashboardPage username={username} name={name} />;
|
||||
}
|
||||
}
|
||||
182
components/Sidebar.tsx
Normal file
182
components/Sidebar.tsx
Normal file
@ -0,0 +1,182 @@
|
||||
"use client"
|
||||
|
||||
import type React from "react"
|
||||
|
||||
import { useState } from "react"
|
||||
import Link from "next/link"
|
||||
import {
|
||||
Home,
|
||||
Globe,
|
||||
Server,
|
||||
Layout,
|
||||
Clock,
|
||||
PenToolIcon as Tool,
|
||||
Settings,
|
||||
LogOut,
|
||||
ChevronDown,
|
||||
Menu,
|
||||
} from "lucide-react"
|
||||
import packageJson from "@/package.json"
|
||||
import Image from "next/image"
|
||||
import Cookies from "js-cookie"
|
||||
import { useRouter } from "next/navigation"
|
||||
|
||||
interface SidebarProps {
|
||||
children: React.ReactNode
|
||||
username: string
|
||||
fullName: string
|
||||
}
|
||||
|
||||
export default function Sidebar({ children, username, fullName }: SidebarProps) {
|
||||
const router = useRouter()
|
||||
const [isProfileOpen, setIsProfileOpen] = useState(false)
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
|
||||
|
||||
const initials = useState(() => {
|
||||
const nameToUse = fullName || username
|
||||
|
||||
return nameToUse
|
||||
.split(" ")
|
||||
.filter((part) => part.length > 0)
|
||||
.map((part) => part[0])
|
||||
.join("")
|
||||
.toUpperCase()
|
||||
.substring(0, 2)
|
||||
})[0]
|
||||
|
||||
const logout = () => {
|
||||
Cookies.remove("token")
|
||||
router.push("/")
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col md:flex-row min-h-screen w-full bg-base-100">
|
||||
{/* Mobile menu button */}
|
||||
<div className="md:hidden flex items-center p-4 bg-base-200 border-b">
|
||||
<button onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} className="btn btn-square btn-ghost">
|
||||
<Menu size={24} />
|
||||
</button>
|
||||
<span className="ml-2 text-xl font-bold">CoreControl</span>
|
||||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
<aside
|
||||
className={`
|
||||
bg-base-200 text-base-content md:flex md:flex-col
|
||||
${isMobileMenuOpen ? "block" : "hidden"} md:block
|
||||
w-full md:w-72 md:h-screen md:sticky md:top-0 md:left-0
|
||||
relative
|
||||
`}
|
||||
>
|
||||
{/* Top section with logo and title */}
|
||||
<div className="hidden md:block">
|
||||
<div className="p-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<Image src="/logo.png" alt="Logo" width={60} height={60} className="rounded-lg" />
|
||||
<div>
|
||||
<h2 className="text-xl font-bold">CoreControl</h2>
|
||||
<p className="text-sm opacity-70">v{packageJson.version}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Navigation menu - scrollable if needed */}
|
||||
<div className="overflow-y-auto" style={{ height: "calc(100vh - 160px)" }}>
|
||||
<ul className="menu menu-md p-4 w-full">
|
||||
<li className="w-full">
|
||||
<Link href="/dashboard" className="flex items-center w-full justify-start px-3 py-2">
|
||||
<Home size={18} />
|
||||
<span>Home</span>
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li className="menu-title mt-4">
|
||||
<span>Resources</span>
|
||||
</li>
|
||||
<li className="w-full">
|
||||
<Link href="/dashboard/sites" className="flex items-center w-full justify-start px-3 py-2">
|
||||
<Globe size={18} />
|
||||
<span>Sites</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li className="w-full">
|
||||
<Link href="/dashboard/servers" className="flex items-center w-full justify-start px-3 py-2">
|
||||
<Server size={18} />
|
||||
<span>Servers</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li className="w-full">
|
||||
<Link href="/dashboard/applications" className="flex items-center w-full justify-start px-3 py-2">
|
||||
<Layout size={18} />
|
||||
<span>Applications</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li className="w-full">
|
||||
<Link href="/dashboard/uptime" className="flex items-center w-full justify-start px-3 py-2">
|
||||
<Clock size={18} />
|
||||
<span>Uptime Pages</span>
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li className="menu-title mt-4">
|
||||
<span>System</span>
|
||||
</li>
|
||||
<li className="w-full">
|
||||
<Link href="/dashboard/maintenance" className="flex items-center w-full justify-start px-3 py-2">
|
||||
<Tool size={18} />
|
||||
<span>Maintenance</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li className="w-full">
|
||||
<Link href="/dashboard/settings" className="flex items-center w-full justify-start px-3 py-2">
|
||||
<Settings size={18} />
|
||||
<span>Settings</span>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* User profile fixed at bottom */}
|
||||
<div className="p-4 border-t border-base-300 absolute bottom-0 left-0 w-full bg-base-200">
|
||||
<div className="relative">
|
||||
<button
|
||||
onClick={() => setIsProfileOpen(!isProfileOpen)}
|
||||
className="flex items-center gap-3 w-full p-2 rounded-lg hover:bg-base-300 transition-colors"
|
||||
>
|
||||
<div className="flex items-center justify-center w-10 h-10 rounded-full bg-primary text-primary-content">
|
||||
<span className="inline-flex items-center justify-center" style={{ lineHeight: 1 }}>
|
||||
{initials}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<p className="font-medium">{username}</p>
|
||||
<p className="text-sm opacity-70">{fullName}</p>
|
||||
</div>
|
||||
<ChevronDown size={16} className={`transition-transform ${isProfileOpen ? "rotate-180" : ""}`} />
|
||||
</button>
|
||||
|
||||
{isProfileOpen && (
|
||||
<div className="absolute bottom-full mb-2 left-0 w-full bg-base-100 rounded-lg shadow-lg border border-base-300 overflow-hidden">
|
||||
<ul className="menu p-0 w-full">
|
||||
<li className="w-full">
|
||||
<button
|
||||
onClick={() => logout()}
|
||||
className="flex items-center text-error w-full rounded-none px-4 py-3 justify-start"
|
||||
>
|
||||
<LogOut size={16} />
|
||||
<span>Logout</span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{/* Main content */}
|
||||
<main className="flex-1 p-4 md:p-6 overflow-auto">{children}</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
BIN
public/logo.png
Normal file
BIN
public/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
Loading…
x
Reference in New Issue
Block a user