Fix: Zeige Ergebnis statt Solve/Give Up Button bei bereits abgeschlossenen Rätseln

- Verwende gameState.isSolved/isFailed direkt für UI-Logik
- Behebt Problem, dass Solve/Give Up Button bei zurückkehrenden Rätseln angezeigt wurde
- isSolved/isFailed werden jetzt direkt aus gameState gelesen für sofortige Konsistenz
This commit is contained in:
Hördle Bot
2026-01-24 13:00:51 +01:00
parent 6be813fb00
commit 2a99f545ef

View File

@@ -96,6 +96,10 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
if (gameState.isSolved && !gameState.yearGuessed && dailyPuzzle?.releaseYear) { if (gameState.isSolved && !gameState.yearGuessed && dailyPuzzle?.releaseYear) {
setShowYearModal(true); setShowYearModal(true);
} }
} else {
// Reset states when gameState is null (e.g., during loading)
setHasWon(false);
setHasLost(false);
} }
}, [gameState, dailyPuzzle]); }, [gameState, dailyPuzzle]);
@@ -164,6 +168,10 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
); );
if (!gameState) return <div>{t('loadingState')}</div>; if (!gameState) return <div>{t('loadingState')}</div>;
// Use gameState directly for isSolved/isFailed to ensure consistency when returning to completed puzzles
const isSolved = gameState?.isSolved ?? hasWon;
const isFailed = gameState?.isFailed ?? hasLost;
const handleGuess = (song: any) => { const handleGuess = (song: any) => {
if (isProcessingGuess) return; if (isProcessingGuess) return;
// Prevent guessing if already solved or failed // Prevent guessing if already solved or failed
@@ -176,6 +184,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
if (song.id === dailyPuzzle.songId) { if (song.id === dailyPuzzle.songId) {
addGuess(song.title, true); addGuess(song.title, true);
setHasWon(true); setHasWon(true);
// gameState.isSolved will be updated by useGameState
// Track puzzle solved event // Track puzzle solved event
if (typeof window !== 'undefined' && window.plausible) { if (typeof window !== 'undefined' && window.plausible) {
window.plausible('puzzle_solved', { window.plausible('puzzle_solved', {
@@ -196,6 +205,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
if (gameState.guesses.length + 1 >= maxAttempts) { if (gameState.guesses.length + 1 >= maxAttempts) {
setHasLost(true); setHasLost(true);
setHasWon(false); setHasWon(false);
// gameState.isFailed will be updated by useGameState
// Track puzzle lost event // Track puzzle lost event
if (typeof window !== 'undefined' && window.plausible) { if (typeof window !== 'undefined' && window.plausible) {
window.plausible('puzzle_solved', { window.plausible('puzzle_solved', {
@@ -236,6 +246,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
if (gameState.guesses.length + 1 >= maxAttempts) { if (gameState.guesses.length + 1 >= maxAttempts) {
setHasLost(true); setHasLost(true);
setHasWon(false); setHasWon(false);
// gameState.isFailed will be updated by useGameState
// Track puzzle lost event // Track puzzle lost event
if (typeof window !== 'undefined' && window.plausible) { if (typeof window !== 'undefined' && window.plausible) {
window.plausible('puzzle_solved', { window.plausible('puzzle_solved', {
@@ -260,6 +271,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
giveUp(); // Ensure game is marked as failed and score reset to 0 giveUp(); // Ensure game is marked as failed and score reset to 0
setHasLost(true); setHasLost(true);
setHasWon(false); setHasWon(false);
// gameState.isFailed will be updated by useGameState
// Track puzzle lost event // Track puzzle lost event
if (typeof window !== 'undefined' && window.plausible) { if (typeof window !== 'undefined' && window.plausible) {
window.plausible('puzzle_solved', { window.plausible('puzzle_solved', {
@@ -409,19 +421,19 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
if (i < gameState.guesses.length) { if (i < gameState.guesses.length) {
if (gameState.guesses[i] === 'SKIPPED') { if (gameState.guesses[i] === 'SKIPPED') {
emojiGrid += '⬛'; emojiGrid += '⬛';
} else if (hasWon && i === gameState.guesses.length - 1) { } else if (isSolved && i === gameState.guesses.length - 1) {
emojiGrid += '🟩'; emojiGrid += '🟩';
} else { } else {
emojiGrid += '🟥'; emojiGrid += '🟥';
} }
} else { } else {
// If game is lost, fill remaining slots with black squares // If game is lost, fill remaining slots with black squares
emojiGrid += hasLost ? '⬛' : '⬜'; emojiGrid += isFailed ? '⬛' : '⬜';
} }
} }
const speaker = hasWon ? '🔉' : '🔇'; const speaker = isSolved ? '🔉' : '🔇';
const bonusStar = (hasWon && gameState.yearGuessed && dailyPuzzle.releaseYear && gameState.scoreBreakdown.some(item => item.reason === 'Bonus: Correct Year')) ? '⭐' : ''; const bonusStar = (isSolved && gameState.yearGuessed && dailyPuzzle.releaseYear && gameState.scoreBreakdown.some(item => item.reason === 'Bonus: Correct Year')) ? '⭐' : '';
const genreText = genre ? `${isSpecial ? t('special') : t('genre')}: ${genre}\n` : ''; const genreText = genre ? `${isSpecial ? t('special') : t('genre')}: ${genre}\n` : '';
// Use current domain from window.location to support both hoerdle.de and hördle.de // Use current domain from window.location to support both hoerdle.de and hördle.de
@@ -534,7 +546,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
src={dailyPuzzle.audioUrl} src={dailyPuzzle.audioUrl}
unlockedSeconds={unlockedSeconds} unlockedSeconds={unlockedSeconds}
startTime={dailyPuzzle.startTime} startTime={dailyPuzzle.startTime}
autoPlay={lastAction === 'SKIP' || (lastAction === 'GUESS' && !hasWon && !hasLost)} autoPlay={lastAction === 'SKIP' || (lastAction === 'GUESS' && !isSolved && !isFailed)}
onReplay={addReplay} onReplay={addReplay}
onHasPlayedChange={setHasPlayedAudio} onHasPlayedChange={setHasPlayedAudio}
/> />
@@ -543,7 +555,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
<div className="guess-list"> <div className="guess-list">
{gameState.guesses.map((guess, i) => { {gameState.guesses.map((guess, i) => {
const isCorrect = hasWon && i === gameState.guesses.length - 1; const isCorrect = isSolved && i === gameState.guesses.length - 1;
return ( return (
<div key={i} className="guess-item"> <div key={i} className="guess-item">
<span className="guess-number">#{i + 1}</span> <span className="guess-number">#{i + 1}</span>
@@ -555,7 +567,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
})} })}
</div> </div>
{!hasWon && !hasLost && ( {!isSolved && !isFailed && (
<> <>
<div id="tour-input"> <div id="tour-input">
<GuessInput onGuess={handleGuess} disabled={isProcessingGuess} /> <GuessInput onGuess={handleGuess} disabled={isProcessingGuess} />
@@ -586,13 +598,13 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
</> </>
)} )}
{(hasWon || hasLost) && ( {(isSolved || isFailed) && (
<div className={`message-box ${hasWon ? 'success' : 'failure'}`}> <div className={`message-box ${isSolved ? 'success' : 'failure'}`}>
<h2 style={{ fontSize: '1.5rem', fontWeight: 'bold', marginBottom: '0.5rem' }}> <h2 style={{ fontSize: '1.5rem', fontWeight: 'bold', marginBottom: '0.5rem' }}>
{hasWon ? t('won') : t('lost')} {isSolved ? t('won') : t('lost')}
</h2> </h2>
<div style={{ fontSize: '2rem', fontWeight: 'bold', margin: '1rem 0', color: hasWon ? 'var(--success)' : 'var(--danger)' }}> <div style={{ fontSize: '2rem', fontWeight: 'bold', margin: '1rem 0', color: isSolved ? 'var(--success)' : 'var(--danger)' }}>
{t('score')}: {gameState.score} {t('score')}: {gameState.score}
</div> </div>
@@ -610,7 +622,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
</ul> </ul>
</details> </details>
<p>{hasWon ? t('comeBackTomorrow') : t('theSongWas')}</p> <p>{isSolved ? t('comeBackTomorrow') : t('theSongWas')}</p>
<div style={{ margin: '1.5rem 0', padding: '1rem', background: 'rgba(255,255,255,0.5)', borderRadius: '0.5rem', display: 'flex', flexDirection: 'column', alignItems: 'center' }}> <div style={{ margin: '1.5rem 0', padding: '1rem', background: 'rgba(255,255,255,0.5)', borderRadius: '0.5rem', display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<img <img