diff --git a/apps/web/src/components/round-transition.tsx b/apps/web/src/components/round-transition.tsx
new file mode 100644
index 0000000..3e4bef9
--- /dev/null
+++ b/apps/web/src/components/round-transition.tsx
@@ -0,0 +1,80 @@
+import { useEffect, useState } from "react"
+import { createPortal } from "react-dom"
+import { AnimatePresence, motion } from "framer-motion"
+
+const VISIBLE_MS = 1100 // durée d'affichage avant le wipe de sortie
+
+/**
+ * Transition "WarioWare" jouée entre les manches : wipe coloré plein écran,
+ * sunburst qui tourne, gros numéro de question qui rebondit, puis sortie.
+ * Montée avec une `key` qui change → rejoue à chaque manche.
+ */
+export function RoundTransition({ index }: { index: number }) {
+ const [show, setShow] = useState(true)
+
+ useEffect(() => {
+ const t = setTimeout(() => setShow(false), VISIBLE_MS)
+ return () => clearTimeout(t)
+ }, [])
+
+ return createPortal(
+
+ {show && (
+
+
+
+
+
+ Question
+
+
+ {index + 1}
+
+
+ PRÊT ?!
+
+
+
+ )}
+ ,
+ document.body
+ )
+}
diff --git a/apps/web/src/pages/room.tsx b/apps/web/src/pages/room.tsx
index dc109ba..79e8212 100644
--- a/apps/web/src/pages/room.tsx
+++ b/apps/web/src/pages/room.tsx
@@ -7,12 +7,14 @@ import { GameEndView } from "@/components/game-end-view"
import { PlayerCards } from "@/components/player-cards"
import { RoomCode } from "@/components/room-code"
import { Boom } from "@/components/boom"
+import { RoundTransition } from "@/components/round-transition"
export function RoomPage({ code }: { code: string }) {
const snapshot = useRoomStore((s) => s.snapshot)
const playerId = useRoomStore((s) => s.playerId)
const connected = useRoomStore((s) => s.connected)
const boomKey = useRoomStore((s) => s.boomKey)
+ const roundKey = useRoomStore((s) => s.roundKey)
const voteProgress = useRoomStore((s) => s.voteProgress)
// Pas de snapshot pour ce code (accès direct / refresh) : retour à l'accueil.
@@ -61,6 +63,9 @@ export function RoomPage({ code }: { code: string }) {
{boomKey > 0 && }
+ {roundKey > 0 && (
+
+ )}
)
}
diff --git a/apps/web/src/store/room.ts b/apps/web/src/store/room.ts
index b1ca21e..70c7cb1 100644
--- a/apps/web/src/store/room.ts
+++ b/apps/web/src/store/room.ts
@@ -39,6 +39,8 @@ interface RoomState {
finalScores: PlayerScore[] | null
/** Compteur d'explosions : incrémenté à chaque fin de manche au timer (boom à 0). */
boomKey: number
+ /** Compteur de manches : incrémenté à chaque round:start (transition WarioWare). */
+ roundKey: number
createRoom: (playerName: string) => Promise
joinRoom: (roomCode: string, playerName: string) => Promise
@@ -61,6 +63,7 @@ export const useRoomStore = create((set, get) => ({
myChoiceIndex: null,
finalScores: null,
boomKey: 0,
+ roundKey: 0,
createRoom: (playerName) =>
new Promise((resolve, reject) => {
@@ -131,6 +134,7 @@ export const useRoomStore = create((set, get) => ({
myChoiceIndex: null,
finalScores: null,
boomKey: 0,
+ roundKey: 0,
}),
}))
@@ -141,7 +145,7 @@ socket.on("room:state", (snapshot) => useRoomStore.setState({ snapshot }))
socket.on("error", (error) => useRoomStore.setState({ lastError: error }))
socket.on("round:start", (payload) =>
- useRoomStore.setState({
+ useRoomStore.setState((s) => ({
round: {
type: payload.type,
djId: payload.djId,
@@ -151,7 +155,8 @@ socket.on("round:start", (payload) =>
voteProgress: null,
reveal: null,
myChoiceIndex: null,
- })
+ roundKey: s.roundKey + 1,
+ }))
)
socket.on("round:voteAck", (voteProgress) =>
useRoomStore.setState({ voteProgress })