diff --git a/package-lock.json b/package-lock.json index 46aea217..d186a875 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4565,6 +4565,11 @@ "minimalistic-crypto-utils": "^1.0.0" } }, + "email-addresses": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz", + "integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==" + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -5528,6 +5533,30 @@ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "optional": true }, + "filename-reserved-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz", + "integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=" + }, + "filenamify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz", + "integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=", + "requires": { + "filename-reserved-regex": "^1.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + } + }, + "filenamify-url": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/filenamify-url/-/filenamify-url-1.0.0.tgz", + "integrity": "sha1-syvYExnvWGO3MHi+1Q9GpPeXX1A=", + "requires": { + "filenamify": "^1.0.0", + "humanize-url": "^1.0.0" + } + }, "filesize": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.0.1.tgz", @@ -5883,6 +5912,38 @@ "assert-plus": "^1.0.0" } }, + "gh-pages": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-2.2.0.tgz", + "integrity": "sha512-c+yPkNOPMFGNisYg9r4qvsMIjVYikJv7ImFOhPIVPt0+AcRUamZ7zkGRLHz7FKB0xrlZ+ddSOJsZv9XAFVXLmA==", + "requires": { + "async": "^2.6.1", + "commander": "^2.18.0", + "email-addresses": "^3.0.1", + "filenamify-url": "^1.0.0", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -6318,6 +6379,15 @@ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, + "humanize-url": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/humanize-url/-/humanize-url-1.0.1.tgz", + "integrity": "sha1-9KuZ4NKIF0yk4eUEB8VfuuRk7/8=", + "requires": { + "normalize-url": "^1.0.0", + "strip-url-auth": "^1.0.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -12512,6 +12582,19 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==" }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "strip-url-auth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-url-auth/-/strip-url-auth-1.0.1.tgz", + "integrity": "sha1-IrD6OkE4WzO+PzMVUbu4N/oM164=" + }, "style-loader": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", @@ -12912,6 +12995,14 @@ "punycode": "^2.1.0" } }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "ts-pnp": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.6.tgz", diff --git a/package.json b/package.json index de451c95..ecd3a8c3 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,12 @@ "name": "exquisite-react", "version": "0.1.0", "private": true, + "homepage": "https://peachmakkoli.github.io/exquisite-react/", "dependencies": { "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", + "gh-pages": "^2.2.0", "react": "^16.13.1", "react-dom": "^16.13.1", "react-scripts": "3.4.1" @@ -14,6 +16,8 @@ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", + "predeploy": "npm run build", + "deploy": "gh-pages -d build", "eject": "react-scripts eject" }, "eslintConfig": { diff --git a/src/components/FinalPoem.css b/src/components/FinalPoem.css index 67dda943..b166c17a 100644 --- a/src/components/FinalPoem.css +++ b/src/components/FinalPoem.css @@ -19,3 +19,7 @@ .FinalPoem__poem { border-bottom: 2px gray dashed; } + +.FinalPoem__hide { + display: none; +} diff --git a/src/components/FinalPoem.js b/src/components/FinalPoem.js index d516184e..847bedad 100644 --- a/src/components/FinalPoem.js +++ b/src/components/FinalPoem.js @@ -1,20 +1,43 @@ import React from 'react'; +import PropTypes from 'prop-types'; import './FinalPoem.css'; -const FinalPoem = (props) => { +const FinalPoem = ({ submissions, onButtonClickCallback, revealPoem }) => { + const finalPoem = submissions.map(submission =>

The {submission.adj1} {submission.noun1} {submission.adv} {submission.verb} the {submission.adj2} {submission.noun2}.

); return (
-
+

Final Poem

- + {finalPoem}
-
- +
+
); -} +}; + +FinalPoem.propTypes = { + submissions: PropTypes.arrayOf( + PropTypes.shape({ + key: PropTypes.number.isRequired, + adj1: PropTypes.string.isRequired, + noun1: PropTypes.string.isRequired, + adv: PropTypes.string.isRequired, + verb: PropTypes.string.isRequired, + adj2: PropTypes.string.isRequired, + noun2: PropTypes.string.isRequired, + }) + ), + onButtonClickCallback: PropTypes.func.isRequired, + revealPoem: PropTypes.bool.isRequired, +}; export default FinalPoem; diff --git a/src/components/Game.js b/src/components/Game.js index ad27105b..4e543149 100644 --- a/src/components/Game.js +++ b/src/components/Game.js @@ -13,6 +13,27 @@ const Game = () => { } }).join(" "); + const [ player, setPlayer ] = useState(1); + const [ playerSubmission, setPlayerSubmission ] = useState(null); + const [ submissionList, setSubmissionList ] = useState([]); + const [ revealPoem, setRevealPoem ] = useState(false); + + const onLineSubmitCallback = (formInput) => { + const newSubmissionList = [...submissionList]; + newSubmissionList.push({ + key: player, + ...formInput, + }); + + setSubmissionList(newSubmissionList); + setPlayerSubmission(formInput); + setPlayer(player+1); + }; + + const onButtonClickCallback = () => { + setRevealPoem(true); + }; + return (

Game

@@ -25,15 +46,15 @@ const Game = () => { { exampleFormat }

- + - + - +
); -} +}; const FIELDS = [ diff --git a/src/components/PlayerSubmissionForm.css b/src/components/PlayerSubmissionForm.css index 7cded5d9..795b9881 100644 --- a/src/components/PlayerSubmissionForm.css +++ b/src/components/PlayerSubmissionForm.css @@ -12,6 +12,19 @@ justify-content: space-around; } +.PlayerSubmissionForm__poem-inputs div { + display: flex; + align-content: center; +} + +.PlayerSubmissionForm__poem-inputs label { + display: none; +} + +.PlayerSubmissionForm__input-invalid { + background-color: lightpink; +} + .PlayerSubmissionForm__submit { display: flex; justify-content: center; diff --git a/src/components/PlayerSubmissionForm.js b/src/components/PlayerSubmissionForm.js index ba19e6ef..7858f18e 100644 --- a/src/components/PlayerSubmissionForm.js +++ b/src/components/PlayerSubmissionForm.js @@ -1,31 +1,166 @@ import React, { useState } from 'react'; +import PropTypes from 'prop-types'; import './PlayerSubmissionForm.css'; -const PlayerSubmissionForm = () => { - return ( -
-

Player Submission Form for Player #{ }

+const PlayerSubmissionForm = ({ player, onLineSubmitCallback, revealPoem }) => { -
+ const [ fieldInput, setFieldInput ] = useState({ + adj1: '', + noun1: '', + adv: '', + verb: '', + adj2: '', + noun2: '', + }); -
+ const isValid = (field) => { + if (field === '') return "PlayerSubmissionForm__input-invalid"; + }; // helper function for changing input background color if field is empty - { - // Put your form inputs here... We've put in one below as an example - } - + const onInputChange = (event) => { + const { name, value } = event.target; + const newFieldInput = { + ...fieldInput, + [name]: value, + }; + + setFieldInput(newFieldInput); + }; -
+ const onFormSubmit = (event) => { + event.preventDefault(); + + const checkFields = (fields) => { + for (const key in fields) { + if (fields[key] === '') { + return false; + }; + }; + return true; + }; // helper function that prevents submission before all the fields have been filled -
- -
-
-
- ); -} + if (checkFields(fieldInput)) { + onLineSubmitCallback(fieldInput); // send data back to Game + setFieldInput({ + adj1: '', + noun1: '', + adv: '', + verb: '', + adj2: '', + noun2: '', + }); + }; + }; + + if (revealPoem) { + return null; + } else { + return ( +
+

Player Submission Form for Player #{player}

+ +
+ +
+ +
+ The +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ the +
+ +
+ + +
+ +
+ + +
+ +
+ . +
+ +
+ +
+ +
+
+
+ ); + }; +}; + +PlayerSubmissionForm.propTypes = { + player: PropTypes.number.isRequired, + onLineSubmitCallback: PropTypes.func.isRequired, + revealPoem: PropTypes.bool.isRequired, +}; export default PlayerSubmissionForm; diff --git a/src/components/RecentSubmission.js b/src/components/RecentSubmission.js index 663da34b..7177eade 100644 --- a/src/components/RecentSubmission.js +++ b/src/components/RecentSubmission.js @@ -1,13 +1,23 @@ import React from 'react'; +import PropTypes from 'prop-types'; import './RecentSubmission.css'; -const RecentSubmission = (props) => { - return ( -
-

The Most Recent Submission

-

{ }

-
- ); -} +const RecentSubmission = ({ submission, revealPoem }) => { + if (!submission || revealPoem) { // if submission is null, the code on line 11 will throw a TypeError + return null; + } else { + return ( +
+

The Most Recent Submission

+

The {submission.adj1} {submission.noun1} {submission.adv} {submission.verb} the {submission.adj2} {submission.noun2}.

+
+ ); + }; +}; + +RecentSubmission.propTypes = { + submission: PropTypes.objectOf(PropTypes.string.isRequired), + revealPoem: PropTypes.bool.isRequired, +}; export default RecentSubmission;