Phase 1 Complete by Claude Code

This commit is contained in:
2026-02-16 22:32:28 +02:00
parent 19c069949d
commit 5e2d4b6b1b
20 changed files with 692 additions and 32 deletions

View File

@@ -1 +1,28 @@
// TODO: Header component
import { useAuth } from "../auth/AuthContext";
export default function Header() {
const { user, logout } = useAuth();
return (
<header className="bg-white border-b border-gray-200 px-6 py-3 flex items-center justify-between">
<h2 className="text-lg font-semibold text-gray-800">
BellSystems Admin Panel
</h2>
<div className="flex items-center gap-4">
<span className="text-sm text-gray-600">
{user?.name}
<span className="ml-2 px-2 py-0.5 bg-gray-100 text-gray-500 text-xs rounded-full">
{user?.role}
</span>
</span>
<button
onClick={logout}
className="text-sm text-red-600 hover:text-red-800 transition-colors"
>
Sign out
</button>
</div>
</header>
);
}

View File

@@ -1 +1,17 @@
// TODO: Main layout wrapper
import { Outlet } from "react-router-dom";
import Header from "./Header";
import Sidebar from "./Sidebar";
export default function MainLayout() {
return (
<div className="flex min-h-screen bg-gray-100">
<Sidebar />
<div className="flex-1 flex flex-col">
<Header />
<main className="flex-1 p-6">
<Outlet />
</main>
</div>
</div>
);
}

View File

@@ -1 +1,42 @@
// TODO: Navigation menu
import { NavLink } from "react-router-dom";
import { useAuth } from "../auth/AuthContext";
const navItems = [
{ to: "/", label: "Dashboard", roles: null },
{ to: "/melodies", label: "Melodies", roles: ["superadmin", "melody_editor", "viewer"] },
{ to: "/devices", label: "Devices", roles: ["superadmin", "device_manager", "viewer"] },
{ to: "/users", label: "Users", roles: ["superadmin", "user_manager", "viewer"] },
{ to: "/mqtt", label: "MQTT", roles: ["superadmin", "device_manager", "viewer"] },
];
export default function Sidebar() {
const { hasRole } = useAuth();
const visibleItems = navItems.filter(
(item) => item.roles === null || hasRole(...item.roles)
);
return (
<aside className="w-56 bg-gray-900 text-white min-h-screen p-4">
<div className="text-xl font-bold mb-8 px-2">BellSystems</div>
<nav className="space-y-1">
{visibleItems.map((item) => (
<NavLink
key={item.to}
to={item.to}
end={item.to === "/"}
className={({ isActive }) =>
`block px-3 py-2 rounded-md text-sm transition-colors ${
isActive
? "bg-gray-700 text-white"
: "text-gray-300 hover:bg-gray-800 hover:text-white"
}`
}
>
{item.label}
</NavLink>
))}
</nav>
</aside>
);
}