add error message and fix guess status logic
This commit is contained in:
parent
a33d1c08de
commit
099b46849c
4 changed files with 57 additions and 16 deletions
14
src/App.tsx
14
src/App.tsx
|
@ -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}
|
||||||
|
|
30
src/components/alerts/Alert.tsx
Normal file
30
src/components/alerts/Alert.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
};
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue