diff --git a/client/src/pages/Game/Game.jsx b/client/src/pages/Game/Game.jsx index b7bfd40..548bb0c 100644 --- a/client/src/pages/Game/Game.jsx +++ b/client/src/pages/Game/Game.jsx @@ -84,7 +84,17 @@ export const Game = () => { }, "round-results": (results) => { setPhase("results"); - setScores(results.scores); + const scoresWithNames = {}; + Object.entries(results.scores).forEach(([userId, score]) => { + const user = connectedUsers.find(u => u.id === userId); + scoresWithNames[userId] = { + score: score, + name: user?.name || results.playerNames?.[userId] || "Player" + }; + }); + + setScores(scoresWithNames); + if (!currentSong) { setCurrentSong(results.selectedSong); } @@ -149,7 +159,7 @@ export const Game = () => { } return () => cleanupFunctions.forEach(cleanup => cleanup()); - }, [socket, on, send, role, currentSong, phase, connected]); + }, [socket, on, send, role, currentSong, phase, connected, connectedUsers]); useEffect(() => { if (timerIntervalRef.current) clearInterval(timerIntervalRef.current); @@ -435,18 +445,24 @@ export const Game = () => {

Punktestand

- {Object.entries(scores).map(([userId, score]) => { - const user = connectedUsers.find(u => u.id === userId) || { name: 'Unbekannt' }; + {Object.entries(scores).map(([userId, scoreData]) => { + const isCurrentUser = userId === socket?.id; + const isHost = connectedUsers.find(u => u.id === "user1")?.id === userId; + const playerName = typeof scoreData === 'object' ? + scoreData.name : + (connectedUsers.find(u => u.id === userId)?.name || "Player"); + const playerScore = typeof scoreData === 'object' ? scoreData.score : scoreData; + return ( -
+
- {user.id === (socket?.id || "you") && "👉 "} - {user.name} - {userId === connectedUsers.find(u => u.id === "user1")?.id && ( + {isCurrentUser && "👉 "} + {playerName} + {isHost && ( )} - {score} + {playerScore}
); })} diff --git a/client/src/pages/Game/styles.sass b/client/src/pages/Game/styles.sass index 7b8f0d5..0adf8f6 100644 --- a/client/src/pages/Game/styles.sass +++ b/client/src/pages/Game/styles.sass @@ -1,6 +1,6 @@ @import "@/common/styles/colors" -// Main layout improvements + .game-page display: flex flex-direction: column @@ -40,7 +40,6 @@ min-width: 0 margin-right: 20px - // Redesigned chat panel .chat-panel width: 280px height: 100% @@ -162,7 +161,6 @@ &:active transform: translateY(0) -// Game header improvements .game-header display: flex justify-content: space-between @@ -197,7 +195,6 @@ margin-right: 8px color: $yellow -// Improved button styles .submit-guess-button, .next-round-button, button:not(.send-button) background: linear-gradient(135deg, $purple, $blue) color: #fff @@ -244,7 +241,6 @@ cursor: not-allowed background: linear-gradient(135deg, #777, #555) -// Content component improvements .waiting-phase text-align: center padding: 100px 0 @@ -274,45 +270,29 @@ display: flex flex-direction: row align-items: center - background: rgba(255, 255, 255, 0.08) - padding: 25px - border-radius: 20px - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3) + background: rgba(40, 40, 60, 0.85) + padding: 20px + border-radius: 15px + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4) backdrop-filter: blur(10px) - background: rgba(255, 255, 255, 0.08) - padding: 25px - border-radius: 20px - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3) - backdrop-filter: blur(10px) - border: 1px solid rgba(255, 255, 255, 0.2) + border: 1px solid rgba(255, 255, 255, 0.15) max-width: 500px margin: 20px auto transition: all 0.3s ease &:hover transform: translateY(-5px) - border-color: rgba(255, 255, 255, 0.4) - box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4), 0 0 30px rgba(255, 255, 255, 0.1) + border-color: rgba(255, 255, 255, 0.3) + box-shadow: 0 15px 40px rgba(0, 0, 0, 0.5), 0 0 30px rgba(255, 255, 255, 0.1) img width: 120px height: 120px object-fit: cover - border-radius: 15px + border-radius: 8px margin-right: 20px box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5) - - .song-info - text-align: left - - .song-names - font-size: 24px - color: $white - margin-bottom: 10px - - .song-description - font-size: 16px - color: rgba(255, 255, 255, 0.7) + border: 2px solid rgba(255, 255, 255, 0.2) .music-controls margin-top: 30px @@ -799,4 +779,266 @@ .song-embedded-player width: 100% height: auto - aspect-ratio: 16 / 9 \ No newline at end of file + aspect-ratio: 16 / 9 + +.results-phase + display: flex + flex-direction: column + align-items: center + width: 100% + + h3 + margin-bottom: 30px + font-size: 28px + color: $white + text-shadow: 0 2px 15px rgba(255, 255, 255, 0.3) + + .round-results + width: 100% + max-width: 600px + display: flex + flex-direction: column + align-items: center + + .composer-results, .guesser-results + width: 100% + margin-bottom: 20px + text-align: center + + p + font-size: 18px + margin-bottom: 15px + color: $white + + .correct-song + margin-top: 10px + position: relative + overflow: visible + z-index: 5 + + &:before + content: "" + position: absolute + top: -30px + left: -30px + right: -30px + bottom: -30px + background: rgba(20, 20, 40, 0.2) + border-radius: 40px + filter: blur(40px) + z-index: -1 + + .song-card.highlight + position: relative + transform: scale(1.05) + background: linear-gradient(135deg, rgba(40, 40, 60, 0.9), rgba(30, 30, 50, 0.95)) + border: 2px solid $yellow + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4), 0 0 50px rgba(255, 255, 0, 0.2) + backdrop-filter: blur(30px) + padding: 25px + transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) + -webkit-backdrop-filter: blur(30px) + background: rgba(35, 35, 50, 0.5) + border-radius: 18px + + &:hover + transform: translateY(-8px) scale(1.08) + box-shadow: 0 15px 40px rgba(0, 0, 0, 0.5), 0 0 60px rgba(255, 255, 0, 0.3), inset 0 0 50px rgba(255, 255, 255, 0.08) + + &:after + content: "✓" + position: absolute + top: -15px + right: -15px + width: 40px + height: 40px + background: linear-gradient(135deg, $yellow, darken($yellow, 15%)) + color: #000 + border-radius: 50% + border: 3px solid rgba(0, 0, 0, 0.5) + display: flex + align-items: center + justify-content: center + font-size: 20px + font-weight: bold + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.4), 0 0 20px rgba(255, 255, 0, 0.5) + animation: pulse-highlight 2s infinite alternate ease-in-out + + &:before + content: "" + position: absolute + inset: 0 + background: linear-gradient(135deg, rgba(80, 80, 120, 0.3), rgba(30, 30, 60, 0.8)) + border-radius: 18px + z-index: -1 + opacity: 0.8 + + img + width: 130px + height: 130px + border-radius: 14px + box-shadow: 0 10px 25px rgba(0, 0, 0, 0.6) + border: 3px solid rgba(255, 255, 255, 0.3) + transform: rotate(-2deg) + transition: all 0.5s ease, border-radius 0.3s ease + + &:hover + transform: rotate(0deg) scale(1.05) + border-color: rgba(255, 255, 0, 0.6) + border-radius: 12px + + .song-info + margin-left: 25px + + .song-names + font-size: 26px + font-weight: bold + color: $white + text-shadow: 0 2px 10px rgba(255, 255, 255, 0.5) + margin-bottom: 10px + background: linear-gradient(90deg, $white, rgba(255,255,255,0.7)) + -webkit-background-clip: text + background-clip: text + -webkit-text-fill-color: transparent + + .song-description + font-size: 18px + color: rgba(255, 255, 255, 0.8) + text-shadow: 0 1px 5px rgba(0, 0, 0, 0.7) + + .guess-result + margin: 20px 0 + padding: 15px 20px + border-radius: 16px + font-size: 18px + font-weight: bold + animation: bounce-in 0.5s ease-out + + &.correct + background: linear-gradient(135deg, rgba(50, 200, 100, 0.8), rgba(40, 160, 80, 0.8)) + color: white + box-shadow: 0 4px 20px rgba(50, 200, 100, 0.4) + + &.incorrect + background: linear-gradient(135deg, rgba(220, 60, 60, 0.8), rgba(180, 40, 40, 0.8)) + color: white + box-shadow: 0 4px 20px rgba(220, 60, 60, 0.4) + + .scoreboard + width: 100% + background: rgba(40, 40, 60, 0.6) + backdrop-filter: blur(10px) + border-radius: 20px + padding: 20px + margin-bottom: 20px + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3) + border: 1px solid rgba(255, 255, 255, 0.1) + margin-top: 5px + + h4 + text-align: center + font-size: 22px + color: $white + margin-top: 10px + margin-bottom: 10px + padding-bottom: 8px + + .scores + display: flex + flex-direction: column + gap: 8px + + .score-entry + display: flex + justify-content: space-between + align-items: center + padding: 12px 15px + border-radius: 14px + background: rgba(255, 255, 255, 0.1) + transition: all 0.2s ease + + &:hover + background: rgba(255, 255, 255, 0.15) + transform: translateY(-2px) + + &.current-user + background: rgba(102, 204, 255, 0.2) + border-left: 3px solid $blue + + .player-name + display: flex + align-items: center + font-weight: 500 + color: $white + font-size: 16px + + .host-icon + color: $yellow + margin-left: 8px + filter: drop-shadow(0 0 5px rgba(255, 255, 0, 0.5)) + + .player-score + background: rgba(255, 255, 255, 0.2) + padding: 5px 12px + border-radius: 20px + font-weight: bold + font-size: 18px + color: $yellow + min-width: 40px + text-align: center + position: relative + overflow: hidden + + &:after + content: "" + position: absolute + top: -50% + left: -50% + width: 200% + height: 200% + background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 0%, transparent 70%) + opacity: 0 + transition: opacity 0.5s ease + + &.highlighted + animation: score-highlight 1s ease + + .next-round-button + margin-top: 10px + padding: 15px 30px + font-size: 18px + + .waiting-message + margin-top: 20px + font-style: italic + color: rgba(255, 255, 255, 0.7) + +@keyframes score-highlight + 0% + transform: scale(1) + background: rgba(255, 255, 0, 0.8) + color: #000 + 50% + transform: scale(1.2) + 100% + transform: scale(1) + background: rgba(255, 255, 255, 0.2) + color: $yellow + +@keyframes bounce-in + 0% + opacity: 0 + transform: scale(0.8) + 50% + transform: scale(1.05) + 100% + opacity: 1 + transform: scale(1) + +@keyframes pulse-highlight + 0%, 100% + transform: scale(1) + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.4), 0 0 20px rgba(255, 255, 0, 0.3) + 50% + transform: scale(1.1) + box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5), 0 0 30px rgba(255, 255, 0, 0.6) \ No newline at end of file diff --git a/server/controller/game.js b/server/controller/game.js index 6aeedfa..09ba7a2 100644 --- a/server/controller/game.js +++ b/server/controller/game.js @@ -187,11 +187,17 @@ const getRoundResults = (roomId) => { const gameState = gameStates[roomId]; if (!gameState) return {round: 0, scores: {}, guessResults: {}, selectedSong: null}; + const playerNames = {}; + Object.keys(gameState.scores).forEach(userId => { + playerNames[userId] = roomController.getUserName(userId) || "Player"; + }); + return { round: gameState.round, selectedSong: gameState.selectedSong, guessResults: gameState.guessResults, - scores: gameState.scores + scores: gameState.scores, + playerNames: playerNames }; };