diff --git a/src/components/Banner/Banner.js b/src/components/Banner/Banner.js
new file mode 100644
index 000000000..6cd8bc311
--- /dev/null
+++ b/src/components/Banner/Banner.js
@@ -0,0 +1,23 @@
+import React from 'react';
+
+function Banner({ isWinner, answer, words }) {
+ return (
+ <>
+ {isWinner ? (
+
+
+ Congratulations! Got it in
+ {" "}
+ {words.length} guesses.
+
+
+ ) : (
+
+
Sorry, the correct answer is {answer}.
+
+ )}
+ >
+ );
+}
+
+export default Banner;
diff --git a/src/components/Banner/index.js b/src/components/Banner/index.js
new file mode 100644
index 000000000..1a3d55b83
--- /dev/null
+++ b/src/components/Banner/index.js
@@ -0,0 +1,2 @@
+export * from './Banner';
+export { default } from './Banner';
diff --git a/src/components/Cell/Cell.js b/src/components/Cell/Cell.js
new file mode 100644
index 000000000..177a4879c
--- /dev/null
+++ b/src/components/Cell/Cell.js
@@ -0,0 +1,9 @@
+import React from 'react';
+
+function Cell({ letter, status }) {
+ const className = status ? `cell ${status}` : 'cell';
+
+ return {letter};
+}
+
+export default Cell;
diff --git a/src/components/Cell/index.js b/src/components/Cell/index.js
new file mode 100644
index 000000000..07cf6981b
--- /dev/null
+++ b/src/components/Cell/index.js
@@ -0,0 +1,2 @@
+export * from './Cell';
+export { default } from './Cell';
diff --git a/src/components/Game/Game.js b/src/components/Game/Game.js
index fc7615d24..176b9260b 100644
--- a/src/components/Game/Game.js
+++ b/src/components/Game/Game.js
@@ -1,7 +1,10 @@
-import React from 'react';
+import React, { useState } from 'react';
import { sample } from '../../utils';
import { WORDS } from '../../data';
+import Input from '../Input/Input';
+import PreviousWord from '../PreviousWord/PreviousWord';
+import Banner from '../Banner/Banner';
// Pick a random word on every pageload.
const answer = sample(WORDS);
@@ -9,7 +12,58 @@ const answer = sample(WORDS);
console.info({ answer });
function Game() {
- return <>Put a game here!>;
+ const [words, setWords] = useState([]);
+ const [isOver, setIsOver] = useState(false);
+ const [isWinner, setIsWinner] = useState(false);
+
+ const handleSaveWord = (input) => {
+ setWords([...words, input]);
+
+ if (answer === input.value) {
+ setIsWinner(true);
+ setIsOver(true);
+ } else if (words.length >= 5) {
+ setIsOver(true);
+ setIsWinner(false);
+ } else {
+ setIsOver(false);
+ }
+ };
+
+ const handleResetGame = () => {
+ const newGame = [];
+
+ setWords(newGame);
+ setIsOver(false);
+ window.location.reload();
+ };
+
+ return (
+ <>
+
+
+
+ {isOver ?
+ :
+ undefined
+ }
+ >
+ );
}
export default Game;
diff --git a/src/components/Guess/Guess.js b/src/components/Guess/Guess.js
new file mode 100644
index 000000000..bead1f974
--- /dev/null
+++ b/src/components/Guess/Guess.js
@@ -0,0 +1,26 @@
+import React from 'react';
+import { range } from '../../utils';
+import Cell from '../Cell/Cell';
+import { checkGuess } from '../../game-helpers';
+
+function Guess({ word, answer }) {
+ const result = checkGuess(word, answer);
+
+ return (
+
+ {
+ range(5).map(num => {
+ return (
+ |
+ );
+ })
+ }
+
+ );
+}
+
+export default Guess;
diff --git a/src/components/Guess/index.js b/src/components/Guess/index.js
new file mode 100644
index 000000000..afbf137b5
--- /dev/null
+++ b/src/components/Guess/index.js
@@ -0,0 +1,2 @@
+export * from './Guess';
+export { default } from './Guess';
diff --git a/src/components/Input/Input.js b/src/components/Input/Input.js
new file mode 100644
index 000000000..d3f81d463
--- /dev/null
+++ b/src/components/Input/Input.js
@@ -0,0 +1,42 @@
+import React, { useState } from 'react';
+
+const Input = ({ handleSaveWord, isOver }) => {
+ const [tentativeGuess, setTentativeGuess] = useState('');
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+ if (tentativeGuess.length !== 5) {
+ alert('The word must be equal to 5 letters');
+ return;
+ };
+
+ const newWord = {
+ id: crypto.randomUUID(),
+ value: tentativeGuess
+ }
+
+ handleSaveWord(newWord);
+ setTentativeGuess('');
+ };
+
+ return (
+
+ );
+};
+
+export default Input;
diff --git a/src/components/Input/index.js b/src/components/Input/index.js
new file mode 100644
index 000000000..998f66c56
--- /dev/null
+++ b/src/components/Input/index.js
@@ -0,0 +1,2 @@
+export * from './Input';
+export { default } from './Input';
\ No newline at end of file
diff --git a/src/components/PreviousWord/PreviousWord.js b/src/components/PreviousWord/PreviousWord.js
new file mode 100644
index 000000000..f1a8c9edb
--- /dev/null
+++ b/src/components/PreviousWord/PreviousWord.js
@@ -0,0 +1,18 @@
+import React from 'react';
+import Guess from '../Guess/Guess';
+import { NUM_OF_GUESSES_ALLOWED } from '../../constants';
+import { range } from '../../utils';
+
+function PreviousWord({ words, answer }) {
+ return (
+
+ {range(NUM_OF_GUESSES_ALLOWED).map(num => {
+ return (
+
+ );
+ })}
+
+ );
+}
+
+export default PreviousWord;
diff --git a/src/components/PreviousWord/index.js b/src/components/PreviousWord/index.js
new file mode 100644
index 000000000..633d27d9b
--- /dev/null
+++ b/src/components/PreviousWord/index.js
@@ -0,0 +1,2 @@
+export * from './PreviousWord';
+export { default } from './PreviousWord';
diff --git a/src/styles.css b/src/styles.css
index f54c1cfd7..820c4d8b6 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -4,7 +4,7 @@
html {
overflow-y: scroll;
- --game-spacing: 32px;
+ --game-spacing: 20px;
--header-height: 4rem;
--color-success: hsl(150deg 70% 30%);
@@ -77,17 +77,16 @@ h1 {
display: flex;
flex-direction: column;
gap: var(--game-spacing);
- padding: var(--game-spacing) 32px;
+ padding: var(--game-spacing) 15px;
margin: 0 auto;
min-width: 250px;
max-width: min(500px, 58vh, 100%);
}
.guess-results {
- flex: 1;
display: flex;
flex-direction: column;
- justify-content: center;
+ justify-content: flex-start;
}
.guess {
@@ -114,12 +113,15 @@ h1 {
.guess:first-of-type .cell:first-of-type {
--radius: 4px 0px 0px 0px;
}
+
.guess:first-of-type .cell:last-of-type {
--radius: 0px 4px 0px 0px;
}
+
.guess:last-of-type .cell:last-of-type {
--radius: 0px 0px 4px 0px;
}
+
.guess:last-of-type .cell:first-of-type {
--radius: 0px 0px 0px 4px;
}
@@ -129,11 +131,13 @@ h1 {
border-color: var(--color-success);
color: white;
}
+
.cell.incorrect {
background: var(--color-gray-300);
border-color: var(--color-gray-300);
color: white;
}
+
.cell.misplaced {
background: var(--color-warning);
border-color: var(--color-warning);
@@ -159,6 +163,7 @@ h1 {
border-radius: 4px;
padding: 8px 16px;
outline-offset: 4px;
+ outline: none;
}
.banner {
@@ -180,6 +185,7 @@ h1 {
background: var(--color-success);
color: white;
}
+
.sad.banner {
background: var(--color-error);
color: white;
@@ -208,6 +214,7 @@ h1 {
border-radius: 8px;
padding: 24px 32px;
}
+
.modal-close-btn {
position: absolute;
top: 0;
@@ -215,10 +222,19 @@ h1 {
padding: 16px;
cursor: pointer;
}
+
.modal-title {
margin-bottom: 0.5em;
}
+.restart {
+ text-align: center;
+ padding: 10px 15px;
+ background-color: var(--color-gray-300);
+ color: #fff;
+ border-radius: var(--radius);
+}
+
/*
Keyframe animations
*/
@@ -226,7 +242,8 @@ h1 {
from {
transform: translateY(100%);
}
+
to {
transform: translateY(0%);
}
-}
+}
\ No newline at end of file