+
+
+
Games
+
Browse and create game rooms
+
+
+
+
+
+
+ {gameTypes.map(g => (
+
+ ))}
+
+
+
+
+ Active Rooms
+ ({activeRooms.length})
+
+ {activeRooms.length === 0 ? (
+
+ No active rooms. Create one to get started!
+
+ ) : (
+
+ {activeRooms.map(room => {
+ const plugin = gameUIRegistry.get(room.gameSlug);
+ return (
+
+
+
{plugin?.icon ?? "๐ฎ"}
+
+
{room.gameName}
+
+
+ {room.status === "waiting" ? "Waiting" : "Playing"}
+
+ {room.playerCount}/{room.maxPlayers} players
+ {room.spectatorCount > 0 && ยท ๐ {room.spectatorCount}}
+
+
+
+
+
+ );
+ })}
+
+ )}
+
+
+ {showCreate && (
+
setShowCreate(false)}>
+
e.stopPropagation()}>
+
Create a Room
+
+ {gameTypes.map(g => (
+
+ ))}
+
+
+
+
+ )}
+
+ );
}
diff --git a/panel/src/games/GameRoom.tsx b/panel/src/games/GameRoom.tsx
index 67edbad..15ab19e 100644
--- a/panel/src/games/GameRoom.tsx
+++ b/panel/src/games/GameRoom.tsx
@@ -1,3 +1,118 @@
+import { useParams, useNavigate } from "react-router-dom";
+import { useGameRoom } from "../lib/useGameRoom";
+import { gameUIRegistry } from "./registry";
+import { Loader2 } from "lucide-react";
+import "./chess";
+
export function GameRoom({ userId }: { userId: string }) {
- return Game Room โ loading...
;
+ const { gameSlug, roomId } = useParams<{ gameSlug: string; roomId: string }>();
+ const navigate = useNavigate();
+ const {
+ gameState, players, spectators, roomStatus,
+ isSpectator, gameOver, error, sendAction, leaveRoom,
+ } = useGameRoom(roomId!, userId);
+
+ const plugin = gameSlug ? gameUIRegistry.get(gameSlug) : undefined;
+
+ if (!plugin) {
+ return (
+
+
+
+
{plugin.icon}
+
+
{plugin.name}
+
+
+ {roomStatus === "waiting" ? "Waiting" : roomStatus === "playing" ? "Playing" : "Finished"}
+
+ {isSpectator && Spectating}
+ ๐ {spectators.length}
+
+
+
+
+
+
+ {error && (
+
+ {error}
+
+ )}
+
+ {gameOver && (
+
+
+ {gameOver.winner
+ ? `Winner: ${players.find(p => p.discordId === gameOver.winner)?.username ?? gameOver.winner}`
+ : "Draw!"}
+
+
Reason: {gameOver.reason}
+
+ )}
+
+ {roomStatus === "waiting" && (
+
+
+ Waiting for players ({players.length}/2)
+
+
+ Share this URL to invite: {window.location.href}
+
+
+ )}
+
+ {(roomStatus === "playing" || roomStatus === "finished") && gameState && (
+
+ )}
+
+ );
}