Update result & scoreboard UI
This commit is contained in:
parent
c31b7e35b6
commit
e633a5e004
@ -84,7 +84,17 @@ export const Game = () => {
|
|||||||
},
|
},
|
||||||
"round-results": (results) => {
|
"round-results": (results) => {
|
||||||
setPhase("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) {
|
if (!currentSong) {
|
||||||
setCurrentSong(results.selectedSong);
|
setCurrentSong(results.selectedSong);
|
||||||
}
|
}
|
||||||
@ -149,7 +159,7 @@ export const Game = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return () => cleanupFunctions.forEach(cleanup => cleanup());
|
return () => cleanupFunctions.forEach(cleanup => cleanup());
|
||||||
}, [socket, on, send, role, currentSong, phase, connected]);
|
}, [socket, on, send, role, currentSong, phase, connected, connectedUsers]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (timerIntervalRef.current) clearInterval(timerIntervalRef.current);
|
if (timerIntervalRef.current) clearInterval(timerIntervalRef.current);
|
||||||
@ -435,18 +445,24 @@ export const Game = () => {
|
|||||||
<div className="scoreboard">
|
<div className="scoreboard">
|
||||||
<h4>Punktestand</h4>
|
<h4>Punktestand</h4>
|
||||||
<div className="scores">
|
<div className="scores">
|
||||||
{Object.entries(scores).map(([userId, score]) => {
|
{Object.entries(scores).map(([userId, scoreData]) => {
|
||||||
const user = connectedUsers.find(u => u.id === userId) || { name: 'Unbekannt' };
|
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 (
|
return (
|
||||||
<div key={userId} className="score-entry">
|
<div key={userId} className={`score-entry ${isCurrentUser ? 'current-user' : ''}`}>
|
||||||
<span className="player-name">
|
<span className="player-name">
|
||||||
{user.id === (socket?.id || "you") && "👉 "}
|
{isCurrentUser && "👉 "}
|
||||||
{user.name}
|
{playerName}
|
||||||
{userId === connectedUsers.find(u => u.id === "user1")?.id && (
|
{isHost && (
|
||||||
<FontAwesomeIcon icon={faCrown} className="host-icon" />
|
<FontAwesomeIcon icon={faCrown} className="host-icon" />
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
<span className="player-score">{score}</span>
|
<span className="player-score">{playerScore}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
@import "@/common/styles/colors"
|
@import "@/common/styles/colors"
|
||||||
|
|
||||||
// Main layout improvements
|
|
||||||
.game-page
|
.game-page
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
@ -40,7 +40,6 @@
|
|||||||
min-width: 0
|
min-width: 0
|
||||||
margin-right: 20px
|
margin-right: 20px
|
||||||
|
|
||||||
// Redesigned chat panel
|
|
||||||
.chat-panel
|
.chat-panel
|
||||||
width: 280px
|
width: 280px
|
||||||
height: 100%
|
height: 100%
|
||||||
@ -162,7 +161,6 @@
|
|||||||
&:active
|
&:active
|
||||||
transform: translateY(0)
|
transform: translateY(0)
|
||||||
|
|
||||||
// Game header improvements
|
|
||||||
.game-header
|
.game-header
|
||||||
display: flex
|
display: flex
|
||||||
justify-content: space-between
|
justify-content: space-between
|
||||||
@ -197,7 +195,6 @@
|
|||||||
margin-right: 8px
|
margin-right: 8px
|
||||||
color: $yellow
|
color: $yellow
|
||||||
|
|
||||||
// Improved button styles
|
|
||||||
.submit-guess-button, .next-round-button, button:not(.send-button)
|
.submit-guess-button, .next-round-button, button:not(.send-button)
|
||||||
background: linear-gradient(135deg, $purple, $blue)
|
background: linear-gradient(135deg, $purple, $blue)
|
||||||
color: #fff
|
color: #fff
|
||||||
@ -244,7 +241,6 @@
|
|||||||
cursor: not-allowed
|
cursor: not-allowed
|
||||||
background: linear-gradient(135deg, #777, #555)
|
background: linear-gradient(135deg, #777, #555)
|
||||||
|
|
||||||
// Content component improvements
|
|
||||||
.waiting-phase
|
.waiting-phase
|
||||||
text-align: center
|
text-align: center
|
||||||
padding: 100px 0
|
padding: 100px 0
|
||||||
@ -274,45 +270,29 @@
|
|||||||
display: flex
|
display: flex
|
||||||
flex-direction: row
|
flex-direction: row
|
||||||
align-items: center
|
align-items: center
|
||||||
background: rgba(255, 255, 255, 0.08)
|
background: rgba(40, 40, 60, 0.85)
|
||||||
padding: 25px
|
padding: 20px
|
||||||
border-radius: 20px
|
border-radius: 15px
|
||||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3)
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4)
|
||||||
backdrop-filter: blur(10px)
|
backdrop-filter: blur(10px)
|
||||||
background: rgba(255, 255, 255, 0.08)
|
border: 1px solid rgba(255, 255, 255, 0.15)
|
||||||
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)
|
|
||||||
max-width: 500px
|
max-width: 500px
|
||||||
margin: 20px auto
|
margin: 20px auto
|
||||||
transition: all 0.3s ease
|
transition: all 0.3s ease
|
||||||
|
|
||||||
&:hover
|
&:hover
|
||||||
transform: translateY(-5px)
|
transform: translateY(-5px)
|
||||||
border-color: rgba(255, 255, 255, 0.4)
|
border-color: rgba(255, 255, 255, 0.3)
|
||||||
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4), 0 0 30px rgba(255, 255, 255, 0.1)
|
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.5), 0 0 30px rgba(255, 255, 255, 0.1)
|
||||||
|
|
||||||
img
|
img
|
||||||
width: 120px
|
width: 120px
|
||||||
height: 120px
|
height: 120px
|
||||||
object-fit: cover
|
object-fit: cover
|
||||||
border-radius: 15px
|
border-radius: 8px
|
||||||
margin-right: 20px
|
margin-right: 20px
|
||||||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5)
|
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5)
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.2)
|
||||||
.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)
|
|
||||||
|
|
||||||
.music-controls
|
.music-controls
|
||||||
margin-top: 30px
|
margin-top: 30px
|
||||||
@ -800,3 +780,265 @@
|
|||||||
width: 100%
|
width: 100%
|
||||||
height: auto
|
height: auto
|
||||||
aspect-ratio: 16 / 9
|
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)
|
@ -187,11 +187,17 @@ const getRoundResults = (roomId) => {
|
|||||||
const gameState = gameStates[roomId];
|
const gameState = gameStates[roomId];
|
||||||
if (!gameState) return {round: 0, scores: {}, guessResults: {}, selectedSong: null};
|
if (!gameState) return {round: 0, scores: {}, guessResults: {}, selectedSong: null};
|
||||||
|
|
||||||
|
const playerNames = {};
|
||||||
|
Object.keys(gameState.scores).forEach(userId => {
|
||||||
|
playerNames[userId] = roomController.getUserName(userId) || "Player";
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
round: gameState.round,
|
round: gameState.round,
|
||||||
selectedSong: gameState.selectedSong,
|
selectedSong: gameState.selectedSong,
|
||||||
guessResults: gameState.guessResults,
|
guessResults: gameState.guessResults,
|
||||||
scores: gameState.scores
|
scores: gameState.scores,
|
||||||
|
playerNames: playerNames
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user