From 3bdb720e4ad6837433630ca342734e8240776246 Mon Sep 17 00:00:00 2001 From: syntaxbullet Date: Thu, 2 Apr 2026 13:29:14 +0200 Subject: [PATCH] feat(panel): migrate to React Router, role-based layout and routing Replace useState-based page switching with react-router-dom Routes. Layout now renders admin or player nav items based on user.role. Add stub pages for PlayerDashboard, GameLobby, and GameRoom. Co-Authored-By: Claude Opus 4.6 (1M context) --- panel/src/App.tsx | 173 ++++++++++--------- panel/src/components/Layout.tsx | 247 ++++++++++++++-------------- panel/src/games/GameLobby.tsx | 3 + panel/src/games/GameRoom.tsx | 3 + panel/src/pages/PlayerDashboard.tsx | 3 + 5 files changed, 234 insertions(+), 195 deletions(-) create mode 100644 panel/src/games/GameLobby.tsx create mode 100644 panel/src/games/GameRoom.tsx create mode 100644 panel/src/pages/PlayerDashboard.tsx diff --git a/panel/src/App.tsx b/panel/src/App.tsx index 99dc6de..dfd2b11 100644 --- a/panel/src/App.tsx +++ b/panel/src/App.tsx @@ -1,91 +1,114 @@ -import { useState } from "react"; +import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom"; import { useAuth } from "./lib/useAuth"; import { Loader2 } from "lucide-react"; -import Layout, { type Page } from "./components/Layout"; +import Layout from "./components/Layout"; import Dashboard from "./pages/Dashboard"; import Settings from "./pages/Settings"; import Users from "./pages/Users"; import Items from "./pages/Items"; import PlaceholderPage from "./pages/PlaceholderPage"; +import NotEnrolled from "./pages/NotEnrolled"; +import PlayerDashboard from "./pages/PlayerDashboard"; +import { GameLobby } from "./games/GameLobby"; +import { GameRoom } from "./games/GameRoom"; const placeholders: Record = { - users: { - title: "Users", - description: "Search, view, and manage user accounts, balances, XP, levels, and inventories.", - }, - items: { - title: "Items", - description: "Create, edit, and manage game items with icons, rarities, and pricing.", - }, - classes: { - title: "Classes", - description: "Manage academy classes, assign Discord roles, and track class balances.", - }, - quests: { - title: "Quests", - description: "Configure quests with trigger events, targets, and XP/balance rewards.", - }, - lootdrops: { - title: "Lootdrops", - description: "View active lootdrops, spawn new drops, and manage lootdrop history.", - }, - moderation: { - title: "Moderation", - description: "Review moderation cases — warnings, timeouts, kicks, bans — and manage appeals.", - }, - transactions: { - title: "Transactions", - description: "Browse the economy transaction log with filtering by user, type, and date.", - }, - settings: { - title: "Settings", - description: "Configure bot settings for economy, leveling, commands, and guild preferences.", - }, + classes: { + title: "Classes", + description: "Manage academy classes, assign Discord roles, and track class balances.", + }, + quests: { + title: "Quests", + description: "Configure quests with trigger events, targets, and XP/balance rewards.", + }, + lootdrops: { + title: "Lootdrops", + description: "View active lootdrops, spawn new drops, and manage lootdrop history.", + }, + moderation: { + title: "Moderation", + description: "Review moderation cases — warnings, timeouts, kicks, bans — and manage appeals.", + }, + transactions: { + title: "Transactions", + description: "Browse the economy transaction log with filtering by user, type, and date.", + }, + leaderboards: { + title: "Leaderboards", + description: "View top players by level, wealth, and net worth.", + }, }; -export default function App() { - const { loading, user, logout } = useAuth(); - const [page, setPage] = useState("dashboard"); +function AppRoutes() { + const { loading, user, enrolled, logout } = useAuth(); + + if (loading) { + return ( +
+ +
+ ); + } + + if (!user && !enrolled) { + return ; + } + + if (!user) { + return ( +
+
+
Aurora
+

Welcome to Aurora

+ + Sign in with Discord + +
+
+ ); + } - if (loading) { return ( -
- -
- ); - } + + + } /> - if (!user) { - return ( -
-
-
Aurora
-

Admin Panel

- - Sign in with Discord - -

Authorized administrators only

-
-
- ); - } + {/* Player routes */} + } /> + } /> - return ( - - {page === "dashboard" ? ( - - ) : page === "users" ? ( - - ) : page === "items" ? ( - - ) : page === "settings" ? ( - - ) : ( - - )} - - ); + {/* Game routes (both roles) */} + } /> + } /> + + {/* Admin routes */} + {user.role === "admin" && ( + <> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + )} + + } /> +
+
+ ); +} + +export default function App() { + return ( + + + + ); } diff --git a/panel/src/components/Layout.tsx b/panel/src/components/Layout.tsx index 2aeeae0..f4231d2 100644 --- a/panel/src/components/Layout.tsx +++ b/panel/src/components/Layout.tsx @@ -1,140 +1,147 @@ import { - LayoutDashboard, - Users, - Package, - Shield, - Scroll, - Gift, - ArrowLeftRight, - GraduationCap, - Settings, - LogOut, - ChevronLeft, - ChevronRight, + LayoutDashboard, + Users, + Package, + Shield, + Scroll, + Gift, + ArrowLeftRight, + GraduationCap, + Settings, + LogOut, + ChevronLeft, + ChevronRight, + Gamepad2, + Trophy, } from "lucide-react"; import { useState } from "react"; +import { useLocation, useNavigate } from "react-router-dom"; import { cn } from "../lib/utils"; import type { AuthUser } from "../lib/useAuth"; -export type Page = - | "dashboard" - | "users" - | "items" - | "classes" - | "quests" - | "lootdrops" - | "moderation" - | "transactions" - | "settings"; +interface NavItem { + path: string; + label: string; + icon: React.ComponentType<{ className?: string }>; +} -const navItems: { page: Page; label: string; icon: React.ComponentType<{ className?: string }> }[] = [ - { page: "dashboard", label: "Dashboard", icon: LayoutDashboard }, - { page: "users", label: "Users", icon: Users }, - { page: "items", label: "Items", icon: Package }, - { page: "classes", label: "Classes", icon: GraduationCap }, - { page: "quests", label: "Quests", icon: Scroll }, - { page: "lootdrops", label: "Lootdrops", icon: Gift }, - { page: "moderation", label: "Moderation", icon: Shield }, - { page: "transactions", label: "Transactions", icon: ArrowLeftRight }, - { page: "settings", label: "Settings", icon: Settings }, +const adminNavItems: NavItem[] = [ + { path: "/admin", label: "Dashboard", icon: LayoutDashboard }, + { path: "/admin/users", label: "Users", icon: Users }, + { path: "/admin/items", label: "Items", icon: Package }, + { path: "/admin/classes", label: "Classes", icon: GraduationCap }, + { path: "/admin/quests", label: "Quests", icon: Scroll }, + { path: "/admin/lootdrops", label: "Lootdrops", icon: Gift }, + { path: "/admin/moderation", label: "Moderation", icon: Shield }, + { path: "/admin/transactions", label: "Transactions", icon: ArrowLeftRight }, + { path: "/admin/settings", label: "Settings", icon: Settings }, + { path: "/games", label: "Games", icon: Gamepad2 }, +]; + +const playerNavItems: NavItem[] = [ + { path: "/dashboard", label: "Dashboard", icon: LayoutDashboard }, + { path: "/games", label: "Games", icon: Gamepad2 }, + { path: "/leaderboards", label: "Leaderboards", icon: Trophy }, ]; export default function Layout({ - user, - logout, - currentPage, - onNavigate, - children, + user, + logout, + children, }: { - user: AuthUser; - logout: () => Promise; - currentPage: Page; - onNavigate: (page: Page) => void; - children: React.ReactNode; + user: AuthUser; + logout: () => Promise; + children: React.ReactNode; }) { - const [collapsed, setCollapsed] = useState(false); + const [collapsed, setCollapsed] = useState(false); + const location = useLocation(); + const navigate = useNavigate(); - const avatarUrl = user.avatar - ? `https://cdn.discordapp.com/avatars/${user.discordId}/${user.avatar}.png?size=64` - : null; + const navItems = user.role === "admin" ? adminNavItems : playerNavItems; - return ( -
- {/* Sidebar */} - - {/* Main content */} -
-
- {children} + + +
+ {!collapsed && ( +
+ {avatarUrl ? ( + {user.username} + ) : ( +
+ {user.username[0]?.toUpperCase()} +
+ )} +
+
{user.username}
+
+
+ )} +
+ + +
+
+ + +
+
+ {children} +
+
-
-
- ); + ); } diff --git a/panel/src/games/GameLobby.tsx b/panel/src/games/GameLobby.tsx new file mode 100644 index 0000000..136198c --- /dev/null +++ b/panel/src/games/GameLobby.tsx @@ -0,0 +1,3 @@ +export function GameLobby() { + return
Game Lobby — loading...
; +} diff --git a/panel/src/games/GameRoom.tsx b/panel/src/games/GameRoom.tsx new file mode 100644 index 0000000..67edbad --- /dev/null +++ b/panel/src/games/GameRoom.tsx @@ -0,0 +1,3 @@ +export function GameRoom({ userId }: { userId: string }) { + return
Game Room — loading...
; +} diff --git a/panel/src/pages/PlayerDashboard.tsx b/panel/src/pages/PlayerDashboard.tsx new file mode 100644 index 0000000..3f57011 --- /dev/null +++ b/panel/src/pages/PlayerDashboard.tsx @@ -0,0 +1,3 @@ +export default function PlayerDashboard({ userId }: { userId: string }) { + return
Player Dashboard — loading...
; +}