add error message and fix guess status logic

This commit is contained in:
Hannah Park 2022-01-09 21:34:50 -05:00
parent a33d1c08de
commit 099b46849c
4 changed files with 57 additions and 16 deletions

View file

@ -1,15 +1,16 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Alert } from "./components/alerts/Alert";
import { Grid } from "./components/grid/Grid"; import { Grid } from "./components/grid/Grid";
import { Keyboard } from "./components/keyboard/Keyboard"; import { Keyboard } from "./components/keyboard/Keyboard";
import { WinModal } from "./components/win-modal/WinModal"; import { WinModal } from "./components/win-modal/WinModal";
import { getGuessStatuses } from "./lib/statuses"; import { isWordInWordList, isWinningWord } from "./lib/words";
import { solution, isWordInWordList, isWinningWord } from "./lib/words";
function App() { function App() {
const [guesses, setGuesses] = useState<string[]>([]); const [guesses, setGuesses] = useState<string[]>([]);
const [currentGuess, setCurrentGuess] = useState(""); const [currentGuess, setCurrentGuess] = useState("");
const [isGameWon, setIsGameWon] = useState(false); const [isGameWon, setIsGameWon] = useState(false);
const [isWinModalOpen, setIsWinModalOpen] = useState(false); const [isWinModalOpen, setIsWinModalOpen] = useState(false);
const [isWordNotFoundAlertOpen, setIsWordNotFoundAlertOpen] = useState(false);
useEffect(() => { useEffect(() => {
if (isGameWon) { if (isGameWon) {
@ -29,8 +30,10 @@ function App() {
const onEnter = () => { const onEnter = () => {
if (!isWordInWordList(currentGuess)) { if (!isWordInWordList(currentGuess)) {
return console.error("not in word list"); setIsWordNotFoundAlertOpen(true);
// TODO add messaging for user setTimeout(() => {
setIsWordNotFoundAlertOpen(false);
}, 2000);
} }
if (currentGuess.length === 5 && guesses.length < 6 && !isGameWon) { if (currentGuess.length === 5 && guesses.length < 6 && !isGameWon) {
if (isWinningWord(currentGuess)) { if (isWinningWord(currentGuess)) {
@ -42,7 +45,8 @@ function App() {
}; };
return ( return (
<div> <div className="py-8 max-w-7xl mx-auto sm:px-6 lg:px-8">
<Alert message="Word not found" isOpen={isWordNotFoundAlertOpen} />
<Grid guesses={guesses} currentGuess={currentGuess} /> <Grid guesses={guesses} currentGuess={currentGuess} />
<Keyboard <Keyboard
onChar={onChar} onChar={onChar}

View file

@ -0,0 +1,30 @@
import { Fragment } from "react";
import { Transition } from "@headlessui/react";
type Props = {
isOpen: boolean;
message: string;
};
export const Alert = ({ isOpen, message }: Props) => {
return (
<Transition
show={isOpen}
as={Fragment}
enter="ease-out duration-300 transition"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="absolute top-2.5 left-1/2 transform -translate-x-1/2 max-w-sm w-full bg-rose-200 shadow-lg rounded-lg pointer-events-auto ring-1 ring-black ring-opacity-5 overflow-hidden">
<div className="p-4">
<p className="text-sm text-center font-medium text-gray-900">
{message}
</p>
</div>
</div>
</Transition>
);
};

View file

@ -12,7 +12,7 @@ export const Grid = ({ guesses, currentGuess }: Props) => {
guesses.length < 5 ? Array.from(Array(5 - guesses.length)) : []; guesses.length < 5 ? Array.from(Array(5 - guesses.length)) : [];
return ( return (
<> <div className="pb-6">
{guesses.map((guess, i) => ( {guesses.map((guess, i) => (
<CompletedRow key={i} guess={guess} /> <CompletedRow key={i} guess={guess} />
))} ))}
@ -20,6 +20,6 @@ export const Grid = ({ guesses, currentGuess }: Props) => {
{empties.map((_, i) => ( {empties.map((_, i) => (
<EmptyRow key={i} /> <EmptyRow key={i} />
))} ))}
</> </div>
); );
}; };

View file

@ -59,21 +59,27 @@ export const getStatuses = (
export const getGuessStatuses = (guess: string): CharStatus[] => { export const getGuessStatuses = (guess: string): CharStatus[] => {
const splitSolution = solution.split(""); const splitSolution = solution.split("");
const solutionCharsTaken = splitSolution.map((x) => false); const splitGuess = guess.split("");
const statuses: CharStatus[] = []; const solutionCharsTaken = splitSolution.map((_) => false);
guess.split("").forEach((letter, i) => { const statuses: CharStatus[] = Array.from(Array(guess.length));
// handle the correct case
// handle all correct cases first
splitGuess.forEach((letter, i) => {
if (letter === splitSolution[i]) { if (letter === splitSolution[i]) {
statuses.push("correct"); statuses[i] = "correct";
solutionCharsTaken[i] = true; solutionCharsTaken[i] = true;
return; return;
} }
});
splitGuess.forEach((letter, i) => {
if (statuses[i]) return;
// handles the absent case
if (!splitSolution.includes(letter)) { if (!splitSolution.includes(letter)) {
statuses.push("absent"); // handles the absent case
statuses[i] = "absent";
return; return;
} }
@ -81,12 +87,13 @@ export const getGuessStatuses = (guess: string): CharStatus[] => {
const indexOfPresentChar = splitSolution.findIndex( const indexOfPresentChar = splitSolution.findIndex(
(x, index) => x === letter && !solutionCharsTaken[index] (x, index) => x === letter && !solutionCharsTaken[index]
); );
if (indexOfPresentChar > -1) { if (indexOfPresentChar > -1) {
statuses.push("present"); statuses[i] = "present";
solutionCharsTaken[indexOfPresentChar] = true; solutionCharsTaken[indexOfPresentChar] = true;
return; return;
} else { } else {
statuses.push("absent"); statuses[i] = "absent";
return; return;
} }
}); });