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) {
setShowYearModal(true);
}
} else {
// Reset states when gameState is null (e.g., during loading)
setHasWon(false);
setHasLost(false);
}
}, [gameState, dailyPuzzle]);
@@ -163,6 +167,10 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
</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) => {
if (isProcessingGuess) return;
@@ -176,6 +184,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
if (song.id === dailyPuzzle.songId) {
addGuess(song.title, true);
setHasWon(true);
// gameState.isSolved will be updated by useGameState
// Track puzzle solved event
if (typeof window !== 'undefined' && window.plausible) {
window.plausible('puzzle_solved', {
@@ -196,6 +205,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
if (gameState.guesses.length + 1 >= maxAttempts) {
setHasLost(true);
setHasWon(false);
// gameState.isFailed will be updated by useGameState
// Track puzzle lost event
if (typeof window !== 'undefined' && window.plausible) {
window.plausible('puzzle_solved', {
@@ -236,6 +246,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
if (gameState.guesses.length + 1 >= maxAttempts) {
setHasLost(true);
setHasWon(false);
// gameState.isFailed will be updated by useGameState
// Track puzzle lost event
if (typeof window !== 'undefined' && window.plausible) {
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
setHasLost(true);
setHasWon(false);
// gameState.isFailed will be updated by useGameState
// Track puzzle lost event
if (typeof window !== 'undefined' && window.plausible) {
window.plausible('puzzle_solved', {
@@ -409,19 +421,19 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
if (i < gameState.guesses.length) {
if (gameState.guesses[i] === 'SKIPPED') {
emojiGrid += '⬛';
} else if (hasWon && i === gameState.guesses.length - 1) {
} else if (isSolved && i === gameState.guesses.length - 1) {
emojiGrid += '🟩';
} else {
emojiGrid += '🟥';
}
} else {
// If game is lost, fill remaining slots with black squares
emojiGrid += hasLost ? '⬛' : '⬜';
emojiGrid += isFailed ? '⬛' : '⬜';
}
}
const speaker = hasWon ? '🔉' : '🔇';
const bonusStar = (hasWon && gameState.yearGuessed && dailyPuzzle.releaseYear && gameState.scoreBreakdown.some(item => item.reason === 'Bonus: Correct Year')) ? '⭐' : '';
const speaker = isSolved ? '🔉' : '🔇';
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` : '';
// 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}
unlockedSeconds={unlockedSeconds}
startTime={dailyPuzzle.startTime}
autoPlay={lastAction === 'SKIP' || (lastAction === 'GUESS' && !hasWon && !hasLost)}
autoPlay={lastAction === 'SKIP' || (lastAction === 'GUESS' && !isSolved && !isFailed)}
onReplay={addReplay}
onHasPlayedChange={setHasPlayedAudio}
/>
@@ -543,7 +555,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
<div className="guess-list">
{gameState.guesses.map((guess, i) => {
const isCorrect = hasWon && i === gameState.guesses.length - 1;
const isCorrect = isSolved && i === gameState.guesses.length - 1;
return (
<div key={i} className="guess-item">
<span className="guess-number">#{i + 1}</span>
@@ -555,7 +567,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
})}
</div>
{!hasWon && !hasLost && (
{!isSolved && !isFailed && (
<>
<div id="tour-input">
<GuessInput onGuess={handleGuess} disabled={isProcessingGuess} />
@@ -586,13 +598,13 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
</>
)}
{(hasWon || hasLost) && (
<div className={`message-box ${hasWon ? 'success' : 'failure'}`}>
{(isSolved || isFailed) && (
<div className={`message-box ${isSolved ? 'success' : 'failure'}`}>
<h2 style={{ fontSize: '1.5rem', fontWeight: 'bold', marginBottom: '0.5rem' }}>
{hasWon ? t('won') : t('lost')}
{isSolved ? t('won') : t('lost')}
</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}
</div>
@@ -610,7 +622,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
</ul>
</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' }}>
<img