mirror of
https://github.com/randyjc/Rahoot.git
synced 2026-03-13 20:15:35 +01:00
adding new clients view for manager page
This commit is contained in:
@@ -60,6 +60,7 @@ export interface ServerToClientEvents {
|
||||
}) => void
|
||||
"manager:newPlayer": (_player: Player) => void
|
||||
"manager:removePlayer": (_playerId: string) => void
|
||||
"manager:players": (_players: Player[]) => void
|
||||
"manager:errorMessage": (_message: string) => void
|
||||
"manager:playerKicked": (_playerId: string) => void
|
||||
"manager:quizzLoaded": (_quizz: QuizzWithId) => void
|
||||
@@ -77,6 +78,7 @@ export interface ClientToServerEvents {
|
||||
"manager:abortQuiz": (_message: MessageGameId) => void
|
||||
"manager:pauseCooldown": (_message: MessageGameId) => void
|
||||
"manager:resumeCooldown": (_message: MessageGameId) => void
|
||||
"manager:endGame": (_message: MessageGameId) => void
|
||||
"manager:skipQuestionIntro": (_message: MessageGameId) => void
|
||||
"manager:nextQuestion": (_message: MessageGameId) => void
|
||||
"manager:deleteQuizz": (_message: { id: string }) => void
|
||||
|
||||
@@ -234,6 +234,10 @@ io.on("connection", (socket) => {
|
||||
withGame(gameId, socket, (game) => game.resumeCooldown(socket))
|
||||
)
|
||||
|
||||
socket.on("manager:endGame", ({ gameId }) =>
|
||||
withGame(gameId, socket, (game) => game.endGame(socket, registry))
|
||||
)
|
||||
|
||||
socket.on("manager:nextQuestion", ({ gameId }) =>
|
||||
withGame(gameId, socket, (game) => game.nextRound(socket))
|
||||
)
|
||||
@@ -281,6 +285,7 @@ io.on("connection", (socket) => {
|
||||
game.players = game.players.filter((p) => p.id !== socket.id)
|
||||
|
||||
io.to(game.manager.id).emit("manager:removePlayer", player.id)
|
||||
io.to(game.manager.id).emit("manager:players", game.players)
|
||||
io.to(game.gameId).emit("game:totalPlayers", game.players.length)
|
||||
|
||||
console.log(`Removed player ${player.username} from game ${game.gameId}`)
|
||||
@@ -290,6 +295,7 @@ io.on("connection", (socket) => {
|
||||
|
||||
player.connected = false
|
||||
io.to(game.gameId).emit("game:totalPlayers", game.players.length)
|
||||
io.to(game.manager.id).emit("manager:players", game.players)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -236,6 +236,7 @@ class Game {
|
||||
this.players.push(playerData)
|
||||
|
||||
this.io.to(this.manager.id).emit("manager:newPlayer", playerData)
|
||||
this.io.to(this.manager.id).emit("manager:players", this.players)
|
||||
this.io.to(this.gameId).emit("game:totalPlayers", this.players.length)
|
||||
|
||||
socket.emit("game:successJoin", this.gameId)
|
||||
@@ -260,6 +261,7 @@ class Game {
|
||||
.to(player.id)
|
||||
.emit("game:reset", "You have been kicked by the manager")
|
||||
this.io.to(this.manager.id).emit("manager:playerKicked", player.id)
|
||||
this.io.to(this.manager.id).emit("manager:players", this.players)
|
||||
|
||||
this.io.to(this.gameId).emit("game:totalPlayers", this.players.length)
|
||||
}
|
||||
@@ -273,6 +275,7 @@ class Game {
|
||||
} else {
|
||||
this.reconnectPlayer(socket)
|
||||
}
|
||||
this.io.to(this.manager.id).emit("manager:players", this.players)
|
||||
}
|
||||
|
||||
private reconnectManager(socket: Socket) {
|
||||
@@ -338,6 +341,7 @@ class Game {
|
||||
this.playerStatus.delete(oldSocketId)
|
||||
this.playerStatus.set(socket.id, oldStatus)
|
||||
}
|
||||
this.io.to(this.manager.id).emit("manager:players", this.players)
|
||||
|
||||
socket.emit("player:successReconnect", {
|
||||
gameId: this.gameId,
|
||||
@@ -697,6 +701,16 @@ class Game {
|
||||
this.tempOldLeaderboard = null
|
||||
this.persist()
|
||||
}
|
||||
|
||||
endGame(socket: Socket, registry: typeof Registry.prototype) {
|
||||
if (socket.id !== this.manager.id) {
|
||||
return
|
||||
}
|
||||
this.started = false
|
||||
this.abortCooldown()
|
||||
this.io.to(this.gameId).emit("game:reset", "Game ended by manager")
|
||||
registry.removeGame(this.gameId)
|
||||
}
|
||||
}
|
||||
|
||||
export default Game
|
||||
|
||||
@@ -26,6 +26,7 @@ const ManagerGame = () => {
|
||||
useManagerStore()
|
||||
const { setQuestionStates } = useQuestionStore()
|
||||
const [cooldownPaused, setCooldownPaused] = useState(false)
|
||||
const { players } = useManagerStore()
|
||||
|
||||
useEvent("game:status", ({ name, data }) => {
|
||||
if (name in GAME_STATE_COMPONENTS_MANAGER) {
|
||||
@@ -56,6 +57,18 @@ const ManagerGame = () => {
|
||||
toast.error(message)
|
||||
})
|
||||
|
||||
useEvent("manager:newPlayer", (player) => {
|
||||
setPlayers((prev) => [...prev.filter((p) => p.id !== player.id), player])
|
||||
})
|
||||
|
||||
useEvent("manager:removePlayer", (playerId) => {
|
||||
setPlayers((prev) => prev.filter((p) => p.id !== playerId))
|
||||
})
|
||||
|
||||
useEvent("manager:players", (players) => {
|
||||
setPlayers(players)
|
||||
})
|
||||
|
||||
useEvent("game:cooldownPause", (isPaused) => {
|
||||
setCooldownPaused(isPaused)
|
||||
})
|
||||
@@ -102,6 +115,11 @@ const ManagerGame = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleEndGame = () => {
|
||||
if (!gameId) return
|
||||
socket?.emit("manager:endGame", { gameId })
|
||||
}
|
||||
|
||||
let component = null
|
||||
|
||||
switch (status?.name) {
|
||||
@@ -155,6 +173,8 @@ const ManagerGame = () => {
|
||||
showPause={
|
||||
status?.name === STATUS.SHOW_QUESTION || status?.name === STATUS.SELECT_ANSWER
|
||||
}
|
||||
onEnd={handleEndGame}
|
||||
players={players}
|
||||
manager
|
||||
>
|
||||
{component}
|
||||
|
||||
@@ -18,6 +18,8 @@ type Props = PropsWithChildren & {
|
||||
onPause?: () => void
|
||||
paused?: boolean
|
||||
showPause?: boolean
|
||||
onEnd?: () => void
|
||||
players?: { id: string; username: string; connected: boolean }[]
|
||||
manager?: boolean
|
||||
}
|
||||
|
||||
@@ -28,6 +30,8 @@ const GameWrapper = ({
|
||||
onPause,
|
||||
paused,
|
||||
showPause,
|
||||
onEnd,
|
||||
players,
|
||||
manager,
|
||||
}: Props) => {
|
||||
const { isConnected } = useSocket()
|
||||
@@ -97,8 +101,37 @@ const GameWrapper = ({
|
||||
{paused ? "Resume" : "Pause"}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{manager && onEnd && (
|
||||
<Button className="self-end bg-red-600 px-4" onClick={onEnd}>
|
||||
End game
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{manager && players && players.length > 0 && (
|
||||
<div className="mx-4 mb-2 rounded-md bg-white/90 p-3 text-sm shadow">
|
||||
<div className="mb-1 text-xs font-semibold uppercase text-gray-600">
|
||||
Players ({players.length})
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{players.map((p) => (
|
||||
<span
|
||||
key={p.id}
|
||||
className={clsx(
|
||||
"rounded border px-2 py-1 font-semibold",
|
||||
p.connected
|
||||
? "border-green-500 text-green-700"
|
||||
: "border-gray-300 text-gray-500",
|
||||
)}
|
||||
>
|
||||
{p.username || p.id} {p.connected ? "" : "(disc.)"}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{children}
|
||||
|
||||
{!manager && (
|
||||
|
||||
Reference in New Issue
Block a user