diff --git a/package-lock.json b/package-lock.json index 6101d748c38737fb49175abbb7645e7fd9ffa6b3..230177f9b511a7d9887b896a9b41213bc7344d57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,8 +13,12 @@ "@testing-library/user-event": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-scripts": "5.0.1", + "react-router-dom": "^6.4.3", + "react-scripts": "^5.0.1", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "typescript": "^4.8.4" } }, "node_modules/@adobe/css-tools": { @@ -3085,6 +3089,14 @@ } } }, + "node_modules/@remix-run/router": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz", + "integrity": "sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q==", + "engines": { + "node": ">=14" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -14142,6 +14154,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.3.tgz", + "integrity": "sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==", + "dependencies": { + "@remix-run/router": "1.0.3" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.3.tgz", + "integrity": "sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==", + "dependencies": { + "@remix-run/router": "1.0.3", + "react-router": "6.4.3" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -15816,7 +15858,6 @@ "version": "4.8.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -19029,6 +19070,11 @@ "source-map": "^0.7.3" } }, + "@remix-run/router": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz", + "integrity": "sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q==" + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -26915,6 +26961,23 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" }, + "react-router": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.3.tgz", + "integrity": "sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==", + "requires": { + "@remix-run/router": "1.0.3" + } + }, + "react-router-dom": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.3.tgz", + "integrity": "sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==", + "requires": { + "@remix-run/router": "1.0.3", + "react-router": "6.4.3" + } + }, "react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -28154,8 +28217,7 @@ "typescript": { "version": "4.8.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "peer": true + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==" }, "unbox-primitive": { "version": "1.0.2", diff --git a/package.json b/package.json index 0e344a92b982dbaee66a5f375b492209a30be5d7..6fea90829acf3ccb3569d738bb240abb65f913df 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "@testing-library/user-event": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-scripts": "5.0.1", + "react-router-dom": "^6.4.3", + "react-scripts": "^5.0.1", "web-vitals": "^2.1.4" }, "scripts": { @@ -34,5 +35,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "typescript": "^4.8.4" } } diff --git a/src/App.js b/src/App.js index 37845757234ccb68531c10cf7a2ffc589c47e342..aea0b29fe12d17438339d42481a3bb2158454b7d 100644 --- a/src/App.js +++ b/src/App.js @@ -1,24 +1,13 @@ -import logo from './logo.svg'; import './App.css'; +import React from "react"; +import { Routes, Route } from 'react-router-dom'; +import Home from './pages/Home'; function App() { return ( - <div className="App"> - <header className="App-header"> - <img src={logo} className="App-logo" alt="logo" /> - <p> - Edit <code>src/App.js</code> and save to reload. - </p> - <a - className="App-link" - href="https://reactjs.org" - target="_blank" - rel="noopener noreferrer" - > - Learn React - </a> - </header> - </div> + <Routes> + <Route path="/" element={<Home />} /> + </Routes> ); } diff --git a/src/components/CharBox.js b/src/components/CharBox.js new file mode 100644 index 0000000000000000000000000000000000000000..dbf5f1ce6ec5a228f09890fd1eab0f12e6bcb4d6 --- /dev/null +++ b/src/components/CharBox.js @@ -0,0 +1,83 @@ +import React from "react"; +// import { Answer } from "../constant/Answer"; + +export default function CharBox(props) { + + let correctBox = { + backgroundColor: "green", + color: "white", + width: "50px", + height: "50px", + display: "inline-block", + textAlign: "center", + verticalAlign: "middle", + lineHeight: "50px", + margin: "5px", + border: "1px solid black" + }; + + let missplacedBox = { + backgroundColor: "yellow", + color: "black", + width: "50px", + height: "50px", + display: "inline-block", + textAlign: "center", + verticalAlign: "middle", + lineHeight: "50px", + margin: "5px", + border: "1px solid black" + }; + + let wrongBox = { + backgroundColor: "red", + color: "white", + width: "50px", + height: "50px", + display: "inline-block", + textAlign: "center", + verticalAlign: "middle", + lineHeight: "50px", + margin: "5px", + border: "1px solid black" + }; + + let defaultBox = { + backgroundColor: "white", + color: "black", + width: "50px", + height: "50px", + display: "inline-block", + textAlign: "center", + verticalAlign: "middle", + lineHeight: "50px", + margin: "5px", + border: "1px solid black" + }; + + const [charState, setCharState] = React.useState(props.char); + const [boxStyle, setBoxStyle] = React.useState(defaultBox); + + const changeBoxStyle = (answer) => { + if (answer === "Correct") { + return correctBox; + } else if (answer === "Misplaced") { + return missplacedBox; + } else if (answer === "Wrong") { + return wrongBox; + } + return defaultBox; + } + + React.useEffect(() => { + // console.log(props); + setCharState(props.char); + setBoxStyle(changeBoxStyle(props.answer)); + }, [props]); // eslint-disable-line react-hooks/exhaustive-deps + + return ( + <div style={boxStyle}> + {charState.toUpperCase()} + </div> + ); +} \ No newline at end of file diff --git a/src/components/WordBox.js b/src/components/WordBox.js new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/components/WordInput.js b/src/components/WordInput.js new file mode 100644 index 0000000000000000000000000000000000000000..ca15a6ca03f22887255c3f28c6b65912b5f52d87 --- /dev/null +++ b/src/components/WordInput.js @@ -0,0 +1,57 @@ +import React from "react"; +import { validateInput } from "../helpers/validateInput"; +import CharBox from "./CharBox"; + +const WordInput = () => { + + const [word, setWord] = React.useState([]); + const [charBox, setCharBox] = React.useState([]); + + React.useEffect(() => { + const charBoxes = []; + for (let i = 0; i < 5; i++) { + charBoxes.push(<CharBox char=""/>); + } + setCharBox(charBoxes); + }, []); + + document.onkeyup = function(e) { + if (e.key.length === 1){ + if (e.key.match(/[a-z]/i)) { + if (word.length >= 5) { + return; + } else { + setCharBox(prevState => { + const newState = [...prevState]; + newState[word.length] = <CharBox char={e.key} />; + return newState; + }); + setWord([...word, e.key]); } + } + } else { + if (e.key === "Enter") { + setCharBox([]); + + validateInput(word, "hello").flatMap((e, idx) => { + setCharBox(prevState => [...prevState, <CharBox char={word[idx]} answer={e} />]); + return charBox; + }); + } else if (e.key === "Backspace" && word.length > 0) { + setWord([...word.slice(0,-1)]); + setCharBox(prevState => { + const newState = [...prevState]; + newState[word.length-1] = <CharBox char={""} />; + return newState; + }); + } + } + } + + return ( + <div className="word-input"> + {charBox} + </div> + ); +} + +export default WordInput; \ No newline at end of file diff --git a/src/helpers/validateInput.js b/src/helpers/validateInput.js new file mode 100644 index 0000000000000000000000000000000000000000..23fc32089babc3dc914f784b3585f4aa98bb8c08 --- /dev/null +++ b/src/helpers/validateInput.js @@ -0,0 +1,28 @@ +export function validateInput(input, actual) { + let initInput = input.split(""); + let evaluateInput = actual.split(""); + + const mappedInput = initInput.map((e, idx) => { + if (e === actual[idx]) { + evaluateInput.splice(idx, 1); + return "Correct"; + } else { + const filteredActual = evaluateInput.map((elementActual, idxActual) => { + if (elementActual === e) { + return [elementActual, idxActual]; + } else { + return undefined; + } + }).filter(x => x); + + if (filteredActual.length === 0) { + return "Wrong"; + } else if (e === filteredActual[0][0]) { + evaluateInput.splice(filteredActual[0][1], 1) + return "Misplaced"; + } + } + }); + + return mappedInput; +} diff --git a/src/index.js b/src/index.js index d563c0fb10ba0e42724b21286eb546ee4e5734fc..6b77f63149f7a854d6959148bda4e5c6fc7c1b49 100644 --- a/src/index.js +++ b/src/index.js @@ -1,17 +1,11 @@ import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css'; +import ReactDOM from 'react-dom/client'; import App from './App'; -import reportWebVitals from './reportWebVitals'; +import { BrowserRouter } from 'react-router-dom'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( - <React.StrictMode> + <BrowserRouter> <App /> - </React.StrictMode> + </BrowserRouter> ); - -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); diff --git a/src/pages/Home.js b/src/pages/Home.js new file mode 100644 index 0000000000000000000000000000000000000000..cb1d732eed24a739935e0b99668027dc5482dfdd --- /dev/null +++ b/src/pages/Home.js @@ -0,0 +1,17 @@ +import logo from '../logo.svg'; +import React from 'react'; +import WordInput from '../components/WordInput'; + +export default function Home() { + const wordBoxes = []; + for (let i = 0; i < 1; i++) { + wordBoxes.push(<WordInput />); + } + + return ( + <div className="App"> + <h1>Simple Wordle</h1> + {wordBoxes} + </div> + ); +} \ No newline at end of file