'use client';
import { useEffect, useState } from 'react';
import AudioPlayer from './AudioPlayer';
import GuessInput from './GuessInput';
import Statistics from './Statistics';
import { useGameState } from '../lib/gameState';
interface GameProps {
dailyPuzzle: {
id: number;
audioUrl: string;
songId: number;
title: string;
artist: string;
coverImage: string | null;
} | null;
}
const UNLOCK_STEPS = [2, 4, 7, 11, 16, 30, 60];
export default function Game({ dailyPuzzle }: GameProps) {
const { gameState, statistics, addGuess } = useGameState();
const [hasWon, setHasWon] = useState(false);
const [hasLost, setHasLost] = useState(false);
const [shareText, setShareText] = useState('Share Result');
useEffect(() => {
if (gameState && dailyPuzzle) {
setHasWon(gameState.isSolved);
setHasLost(gameState.isFailed);
}
}, [gameState, dailyPuzzle]);
if (!dailyPuzzle) return (
No Puzzle Available
Could not generate a daily puzzle.
Please ensure there are songs in the database.
Go to Admin Dashboard
);
if (!gameState) return Loading state...
;
const handleGuess = (song: any) => {
if (song.id === dailyPuzzle.songId) {
addGuess(song.title, true);
setHasWon(true);
} else {
addGuess(song.title, false);
if (gameState.guesses.length + 1 >= 7) {
setHasLost(true);
}
}
};
const unlockedSeconds = UNLOCK_STEPS[Math.min(gameState.guesses.length, 6)];
const handleShare = () => {
let emojiGrid = '';
const totalGuesses = 7;
// Build the grid
for (let i = 0; i < totalGuesses; i++) {
if (i < gameState.guesses.length) {
// If this was the winning guess (last one and won)
if (hasWon && i === gameState.guesses.length - 1) {
emojiGrid += '🟩';
} else {
// Wrong or skipped
emojiGrid += '⬛';
}
} else {
// Unused attempts
emojiGrid += '⬜';
}
}
const speaker = hasWon ? '🔉' : '🔇';
const text = `Hördle #${dailyPuzzle.id}\n\n${speaker}${emojiGrid}\n\n#Hördle #Music\n\nhttps://hoerdle.elpatron.me`;
// Fallback method for copying to clipboard
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand('copy');
setShareText('Copied!');
setTimeout(() => setShareText('Share Result'), 2000);
} catch (err) {
console.error('Failed to copy:', err);
setShareText('Copy failed');
setTimeout(() => setShareText('Share Result'), 2000);
} finally {
document.body.removeChild(textarea);
}
};
return (
Hördle #{dailyPuzzle.id}
Attempt {gameState.guesses.length + 1} / 7
{unlockedSeconds}s unlocked
{gameState.guesses.map((guess, i) => {
const isCorrect = hasWon && i === gameState.guesses.length - 1;
return (
#{i + 1}
{isCorrect ? 'Correct!' : guess}
);
})}
{!hasWon && !hasLost && (
<>
>
)}
{hasWon && (
You won!
Come back tomorrow for a new song.
{/* Song Details */}
{dailyPuzzle.coverImage && (

)}
{dailyPuzzle.title}
{dailyPuzzle.artist}
{statistics &&
}
)}
{hasLost && (
Game Over
The song was:
{/* Song Details */}
{dailyPuzzle.coverImage && (

)}
{dailyPuzzle.title}
{dailyPuzzle.artist}
{statistics &&
}
)}
);
}