feat: Add statistics tracking and fix clipboard API
- Add personal statistics with badges for each attempt count - Track solved puzzles per attempt (1-6) and failed attempts - Display statistics after game completion - Fix clipboard API issue with fallback method - Add footer with attribution
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import AudioPlayer from './AudioPlayer';
|
||||
import GuessInput from './GuessInput';
|
||||
import Statistics from './Statistics';
|
||||
import { useGameState } from '../lib/gameState';
|
||||
|
||||
interface GameProps {
|
||||
@@ -16,7 +17,7 @@ interface GameProps {
|
||||
const UNLOCK_STEPS = [2, 4, 7, 11, 16, 30];
|
||||
|
||||
export default function Game({ dailyPuzzle }: GameProps) {
|
||||
const { gameState, addGuess } = useGameState();
|
||||
const { gameState, statistics, addGuess } = useGameState();
|
||||
const [hasWon, setHasWon] = useState(false);
|
||||
const [hasLost, setHasLost] = useState(false);
|
||||
const [shareText, setShareText] = useState('Share Result');
|
||||
@@ -68,10 +69,25 @@ export default function Game({ dailyPuzzle }: GameProps) {
|
||||
const speaker = hasWon ? '🔉' : '🔇';
|
||||
const text = `Hördle #${dailyPuzzle.id}\n\n${speaker}${emojiGrid}\n\n#Hördle #Music\n\nhttps://hoerdle.elpatron.me`;
|
||||
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
// 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 (
|
||||
@@ -123,6 +139,7 @@ export default function Game({ dailyPuzzle }: GameProps) {
|
||||
<div className="message-box success">
|
||||
<h2 style={{ fontSize: '1.5rem', fontWeight: 'bold', marginBottom: '0.5rem' }}>You won!</h2>
|
||||
<p>Come back tomorrow for a new song.</p>
|
||||
{statistics && <Statistics statistics={statistics} />}
|
||||
<button onClick={handleShare} className="btn-primary" style={{ marginTop: '1rem' }}>
|
||||
{shareText}
|
||||
</button>
|
||||
@@ -133,6 +150,7 @@ export default function Game({ dailyPuzzle }: GameProps) {
|
||||
<div className="message-box failure">
|
||||
<h2 style={{ fontSize: '1.5rem', fontWeight: 'bold', marginBottom: '0.5rem' }}>Game Over</h2>
|
||||
<p>The song was hidden.</p>
|
||||
{statistics && <Statistics statistics={statistics} />}
|
||||
<button onClick={handleShare} className="btn-primary" style={{ marginTop: '1rem' }}>
|
||||
{shareText}
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user