Fix guessing phase

This commit is contained in:
2025-03-01 00:40:01 +01:00
parent 87fc9a2f39
commit a3daab2f84
6 changed files with 285 additions and 44 deletions

View File

@@ -19,6 +19,7 @@ export const Game = () => {
const [selectedSong, setSelectedSong] = useState(null);
const [guessResult, setGuessResult] = useState(null);
const [isHost, setIsHost] = useState(false);
const [hasGuessed, setHasGuessed] = useState(false);
const [messages, setMessages] = useState([]);
const [inputValue, setInputValue] = useState("");
@@ -48,9 +49,10 @@ export const Game = () => {
setTimeLeft(data.timeRemaining);
},
"guessing-phase-started": (data) => {
console.log("Guessing phase started:", data);
setPhase("guessing");
setTimeLeft(data.timeRemaining);
setSongOptions(data.songOptions);
setSongOptions(data.songOptions || []);
},
"guess-result": (result) => {
setGuessResult(result.isCorrect);
@@ -94,6 +96,13 @@ export const Game = () => {
console.log("Received frequency update:", data.frequency);
setFrequency(data.frequency);
}
},
"phase-changed": (data) => {
console.log("Phase changed:", data);
setPhase(data.phase);
if (data.timeRemaining) {
setTimeLeft(data.timeRemaining);
}
}
};
@@ -143,8 +152,21 @@ export const Game = () => {
const handleSongSelect = useCallback((song) => {
setSelectedSong(song);
send("submit-guess", { songId: song.id });
}, [send]);
}, []);
const handleSubmitGuess = useCallback(() => {
if (!selectedSong || phase !== 'guessing') return;
console.log("Submitting guess:", selectedSong.id);
send("submit-guess", { songId: selectedSong.id });
setMessages(prev => [...prev, {
system: true,
text: `Du hast "${selectedSong.title}" von ${selectedSong.artist} gewählt.`
}]);
setHasGuessed(true);
}, [selectedSong, send, phase]);
const handleNextRound = useCallback(() => {
send("next-round");
@@ -212,23 +234,54 @@ export const Game = () => {
<p>Die Rater versuchen nun, deinen Song zu erraten...</p>
</div>
) : (
<div className="song-options">
<div className="song-selection">
<p className="instruction">Welchen Song hat der Komponist gespielt?</p>
<div className="song-grid">
{songOptions.map(song => (
<div
key={song.id}
className={`song-option ${selectedSong?.id === song.id ? 'selected' : ''}`}
onClick={() => handleSongSelect(song)}
>
<img src={song.coverUrl} alt={song.title} />
<div className="song-details">
<div className="song-title">{song.title}</div>
<div className="song-artist">{song.artist}</div>
</div>
{songOptions.length === 0 ? (
<div className="loading-songs">
<p>Lade Songoptionen...</p>
</div>
) : (
<>
<div className="song-grid">
{songOptions.map(song => (
<div
key={song.id}
className={`song-option ${selectedSong?.id === song.id ? 'selected' : ''} ${hasGuessed ? 'disabled' : ''}`}
onClick={() => !hasGuessed && handleSongSelect(song)}
>
<div className="song-image">
<img src={song.coverUrl} alt={song.title} />
{selectedSong?.id === song.id && (
<div className="selection-indicator">
<FontAwesomeIcon icon="fa-solid fa-check-circle" />
</div>
)}
</div>
<div className="song-details">
<div className="song-title">{song.title}</div>
<div className="song-artist">{song.artist}</div>
</div>
</div>
))}
</div>
))}
</div>
<div className="guess-actions">
{hasGuessed ? (
<p className="guess-submitted">Deine Antwort wurde eingereicht!</p>
) : (
<button
className={`submit-guess-button ${!selectedSong ? 'disabled' : ''}`}
onClick={handleSubmitGuess}
disabled={!selectedSong}
>
<FontAwesomeIcon icon="fa-solid fa-paper-plane" />
Antwort einreichen
</button>
)}
</div>
</>
)}
</div>
)}
</div>

View File

@@ -187,6 +187,14 @@ export const MusicSlider = ({ isReadOnly = false, onFrequencyChange, frequency:
};
}, []);
useEffect(() => {
return () => {
if (isPlaying) {
stopAudio();
}
};
}, [isPlaying]);
return (
<div className={`otamatone-container ${isReadOnly ? 'read-only' : ''}`}>
<div

View File

@@ -332,34 +332,124 @@
grid-template-columns: repeat(3, 1fr)
gap: 20px
margin-top: 20px
animation: fade-in 0.5s ease-out
@media (max-width: 768px)
grid-template-columns: repeat(2, 1fr)
@media (max-width: 500px)
grid-template-columns: 1fr
.song-option
background: rgba(255, 255, 255, 0.1)
border-radius: 15px
overflow: hidden
cursor: pointer
transition: all 0.3s ease
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)
border: 2px solid transparent
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2)
&:hover
transform: translateY(-5px)
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3)
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3), 0 0 20px rgba(255, 255, 255, 0.1)
background: rgba(255, 255, 255, 0.15)
&.selected
border: 2px solid $yellow
box-shadow: 0 0 20px rgba(255, 255, 0, 0.5)
box-shadow: 0 0 20px rgba(255, 255, 0, 0.5), 0 10px 30px rgba(0, 0, 0, 0.3)
background: rgba(255, 255, 255, 0.2)
img
width: 100%
height: 120px
object-fit: cover
.song-image
position: relative
overflow: hidden
img
width: 100%
height: 150px
object-fit: cover
transition: transform 0.3s ease
.selected &
transform: scale(1.05)
.selection-indicator
position: absolute
top: 10px
right: 10px
background-color: $yellow
color: #000
width: 30px
height: 30px
border-radius: 50%
display: flex
align-items: center
justify-content: center
box-shadow: 0 0 15px rgba(255, 255, 0, 0.7)
animation: pulse 1.5s infinite ease-in-out
.song-details
padding: 10px
padding: 15px
.song-title
font-weight: bold
font-size: 16px
font-size: 18px
color: #fff
margin-bottom: 5px
.song-artist
font-size: 14px
color: rgba(255, 255, 255, 0.8)
.guess-actions
margin-top: 30px
text-align: center
animation: fade-in 0.5s ease-out 0.2s both
.submit-guess-button
background: linear-gradient(135deg, $purple, $blue)
color: #fff
border: none
border-radius: 10px
padding: 12px 25px
font-size: 16px
font-weight: bold
cursor: pointer
transition: all 0.3s ease
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3)
display: inline-flex
align-items: center
justify-content: center
svg
margin-right: 8px
&:hover:not(.disabled)
transform: translateY(-3px)
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4), 0 0 20px rgba(102, 204, 255, 0.4)
&:active:not(.disabled)
transform: translateY(-1px)
&.disabled
opacity: 0.5
cursor: not-allowed
background: linear-gradient(135deg, #999, #666)
.selection-hint
margin-top: 10px
color: rgba(255, 255, 255, 0.7)
font-size: 14px
font-style: italic
.loading-songs
text-align: center
padding: 40px
color: $white
p
font-size: 18px
opacity: 0.8
animation: pulse 1.5s infinite ease-in-out
@keyframes subtle-text-glow
0%, 100%
@@ -417,4 +507,20 @@
filter: drop-shadow(0 0 15px rgba(255, 255, 255, 0.7))
50%
transform: translateY(-10px) scale(1.05) rotate(1deg)
filter: drop-shadow(0 0 25px rgba(255, 255, 255, 0.9)) drop-shadow(0 0 50px rgba(102, 204, 255, 0.6))
filter: drop-shadow(0 0 25px rgba(255, 255, 255, 0.9)) drop-shadow(0 0 50px rgba(102, 204, 255, 0.6))
@keyframes fade-in
0%
opacity: 0
transform: translateY(20px)
100%
opacity: 1
transform: translateY(0)
@keyframes pulse
0%, 100%
opacity: 0.8
transform: scale(1)
50%
opacity: 1
transform: scale(1.05)