import { InformationCircleIcon, ChartBarIcon, SunIcon, } from '@heroicons/react/outline' import { useState, useEffect } from 'react' import { Alert } from './components/alerts/Alert' import { Grid } from './components/grid/Grid' import { Keyboard } from './components/keyboard/Keyboard' import { AboutModal } from './components/modals/AboutModal' import { InfoModal } from './components/modals/InfoModal' import { StatsModal } from './components/modals/StatsModal' import { GAME_TITLE, WIN_MESSAGES, GAME_COPIED_MESSAGE, ABOUT_GAME_MESSAGE, NOT_ENOUGH_LETTERS_MESSAGE, WORD_NOT_FOUND_MESSAGE, CORRECT_WORD_MESSAGE, } from './constants/strings' import { isWordInWordList, isWinningWord, solution } from './lib/words' import { addStatsForCompletedGame, loadStats } from './lib/stats' import { loadGameStateFromLocalStorage, saveGameStateToLocalStorage, } from './lib/localStorage' import './App.css' const ALERT_TIME_MS = 2000 function App() { const prefersDarkMode = window.matchMedia( '(prefers-color-scheme: dark)' ).matches const [currentGuess, setCurrentGuess] = useState('') const [isGameWon, setIsGameWon] = useState(false) const [isInfoModalOpen, setIsInfoModalOpen] = useState(false) const [isAboutModalOpen, setIsAboutModalOpen] = useState(false) const [isNotEnoughLetters, setIsNotEnoughLetters] = useState(false) const [isStatsModalOpen, setIsStatsModalOpen] = useState(false) const [isWordNotFoundAlertOpen, setIsWordNotFoundAlertOpen] = useState(false) const [isGameLost, setIsGameLost] = useState(false) const [isDarkMode, setIsDarkMode] = useState( localStorage.getItem('theme') ? localStorage.getItem('theme') === 'dark' : prefersDarkMode ? true : false ) const [successAlert, setSuccessAlert] = useState('') const [guesses, setGuesses] = useState(() => { const loaded = loadGameStateFromLocalStorage() if (loaded?.solution !== solution) { return [] } const gameWasWon = loaded.guesses.includes(solution) if (gameWasWon) { setIsGameWon(true) } if (loaded.guesses.length === 6 && !gameWasWon) { setIsGameLost(true) } return loaded.guesses }) const [stats, setStats] = useState(() => loadStats()) useEffect(() => { if (isDarkMode) { document.documentElement.classList.add('dark') } else { document.documentElement.classList.remove('dark') } }, [isDarkMode]) const handleDarkMode = (isDark: boolean) => { setIsDarkMode(isDark) localStorage.setItem('theme', isDark ? 'dark' : 'light') } useEffect(() => { saveGameStateToLocalStorage({ guesses, solution }) }, [guesses]) useEffect(() => { if (isGameWon) { setSuccessAlert( WIN_MESSAGES[Math.floor(Math.random() * WIN_MESSAGES.length)] ) setTimeout(() => { setSuccessAlert('') setIsStatsModalOpen(true) }, ALERT_TIME_MS) } if (isGameLost) { setTimeout(() => { setIsStatsModalOpen(true) }, ALERT_TIME_MS) } }, [isGameWon, isGameLost]) const onChar = (value: string) => { if (currentGuess.length < 5 && guesses.length < 6 && !isGameWon) { setCurrentGuess(`${currentGuess}${value}`) } } const onDelete = () => { setCurrentGuess(currentGuess.slice(0, -1)) } const onEnter = () => { if (isGameWon || isGameLost) { return } if (!(currentGuess.length === 5)) { setIsNotEnoughLetters(true) return setTimeout(() => { setIsNotEnoughLetters(false) }, ALERT_TIME_MS) } if (!isWordInWordList(currentGuess)) { setIsWordNotFoundAlertOpen(true) return setTimeout(() => { setIsWordNotFoundAlertOpen(false) }, ALERT_TIME_MS) } const winningWord = isWinningWord(currentGuess) if (currentGuess.length === 5 && guesses.length < 6 && !isGameWon) { setGuesses([...guesses, currentGuess]) setCurrentGuess('') if (winningWord) { setStats(addStatsForCompletedGame(stats, guesses.length)) return setIsGameWon(true) } if (guesses.length === 5) { setStats(addStatsForCompletedGame(stats, guesses.length + 1)) setIsGameLost(true) } } } return (

{GAME_TITLE}

handleDarkMode(!isDarkMode)} /> setIsInfoModalOpen(true)} /> setIsStatsModalOpen(true)} />
setIsInfoModalOpen(false)} /> setIsStatsModalOpen(false)} guesses={guesses} gameStats={stats} isGameLost={isGameLost} isGameWon={isGameWon} handleShare={() => { setSuccessAlert(GAME_COPIED_MESSAGE) return setTimeout(() => setSuccessAlert(''), ALERT_TIME_MS) }} /> setIsAboutModalOpen(false)} />
) } export default App