diff --git a/package-lock.json b/package-lock.json index c205fc57..6cf00c18 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,16 @@ "name": "project1-bootcamp", "version": "0.1.0", "dependencies": { + "bootstrap": "^5.2.2", + "classnames": "^2.3.2", "react": "^18.1.0", + "react-bootstrap": "^2.6.0", "react-dom": "^18.1.0", + "react-router-dom": "^6.4.3", "react-scripts": "5.0.1" + }, + "devDependencies": { + "gh-pages": "^4.0.0" } }, "node_modules/@ampproject/remapping": { @@ -1764,11 +1771,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", - "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.1.tgz", + "integrity": "sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==", "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.10" }, "engines": { "node": ">=6.9.0" @@ -2866,6 +2873,65 @@ } } }, + "node_modules/@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.3.0.tgz", + "integrity": "sha512-yNqUDuOVZIUGP81R87BJVi/ZUZp/nYOBXbPsRe7oltJOfErQZD+UezMpw4vM2KRz18cURffvmC8tJ6JTeyDtaQ==", + "dependencies": { + "@babel/runtime": "^7.6.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "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/@restart/hooks": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.7.tgz", + "integrity": "sha512-ZbjlEHcG+FQtpDPHd7i4FzNNvJf2enAwZfJbpM8CW7BhmOAbsHpZe3tsHwfQUrBuyrxWqPYp2x5UMnilWcY22A==", + "dependencies": { + "dequal": "^2.0.2" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.4.1.tgz", + "integrity": "sha512-J7wFOx2DcmkBqCqiZgDsggLO7faiNh4Nv1/v80FmbRgP+MYpwaVDKKXLC69DA4+ejgNIsBP5ORtC74EZqO1j8A==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@popperjs/core": "^2.11.5", + "@react-aria/ssr": "^3.2.0", + "@restart/hooks": "^0.4.7", + "@types/warning": "^3.0.0", + "dequal": "^2.0.2", + "dom-helpers": "^5.2.0", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -3387,6 +3453,11 @@ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==" }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, "node_modules/@types/q": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", @@ -3402,6 +3473,24 @@ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, + "node_modules/@types/react": { + "version": "18.0.25", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.25.tgz", + "integrity": "sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -3415,6 +3504,11 @@ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + }, "node_modules/@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -3450,6 +3544,11 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" }, + "node_modules/@types/warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", + "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + }, "node_modules/@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -4121,6 +4220,15 @@ "node": ">=8" } }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/array.prototype.flat": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", @@ -4635,6 +4743,24 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, + "node_modules/bootstrap": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.2.tgz", + "integrity": "sha512-dEtzMTV71n6Fhmbg4fYJzQsw1N29hJKO1js5ackCgIpDcGid2ETMGC6zwSYw09v05Y+oRdQ9loC54zB1La3hHQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "@popperjs/core": "^2.11.6" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4891,6 +5017,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "node_modules/clean-css": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz", @@ -5586,6 +5717,11 @@ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" }, + "node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -5698,6 +5834,14 @@ "node": ">= 0.8" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -5829,6 +5973,15 @@ "utila": "~0.4" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -5950,6 +6103,12 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.131.tgz", "integrity": "sha512-oi3YPmaP87hiHn0c4ePB67tXaF+ldGhxvZnT19tW9zX6/Ej+pLN0Afja5rQ6S+TND7I9EuwQTT8JYn1k7R7rrw==" }, + "node_modules/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==", + "dev": true + }, "node_modules/emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -7073,6 +7232,32 @@ "node": ">=10" } }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "dev": true, + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/filesize": { "version": "8.0.7", "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", @@ -7508,6 +7693,94 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gh-pages": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-4.0.0.tgz", + "integrity": "sha512-p8S0T3aGJc68MtwOcZusul5qPSNZCalap3NWbhRUZYu1YOdp+EjZ+4kPmRM8h3NNRdqw00yuevRjlkuSzCn7iQ==", + "dev": true, + "dependencies": { + "async": "^2.6.1", + "commander": "^2.18.0", + "email-addresses": "^3.0.1", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + }, + "bin": { + "gh-pages": "bin/gh-pages.js", + "gh-pages-clean": "bin/gh-pages-clean.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gh-pages/node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gh-pages/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/gh-pages/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/gh-pages/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gh-pages/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/gh-pages/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -8057,6 +8330,14 @@ "node": ">= 0.4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -11470,6 +11751,36 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -12790,6 +13101,23 @@ "react-is": "^16.13.1" } }, + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, + "node_modules/prop-types-extra/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -12965,6 +13293,35 @@ "node": ">=14" } }, + "node_modules/react-bootstrap": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.6.0.tgz", + "integrity": "sha512-WnDgN6PR8WZKo2Og5J8EafFi4BsABjc96lNuMNfksrgiPDCw18/woWQCNhAeHFZQWTQ/PijkOrQ9ncTWwO//AA==", + "dependencies": { + "@babel/runtime": "^7.17.2", + "@restart/hooks": "^0.4.6", + "@restart/ui": "^1.4.1", + "@types/react-transition-group": "^4.4.4", + "classnames": "^2.3.1", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.2", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "@types/react": ">=16.14.8", + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -13104,6 +13461,11 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -13112,6 +13474,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", @@ -13184,6 +13576,21 @@ } } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -13247,9 +13654,9 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.10", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz", + "integrity": "sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==" }, "node_modules/regenerator-transform": { "version": "0.15.0", @@ -14216,6 +14623,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", @@ -14680,6 +15099,18 @@ "node": ">=8" } }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -14816,6 +15247,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -14994,6 +15439,14 @@ "makeerror": "1.0.12" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/watchpack": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", @@ -17044,11 +17497,11 @@ } }, "@babel/runtime": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", - "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.1.tgz", + "integrity": "sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==", "requires": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.10" } }, "@babel/runtime-corejs3": { @@ -17810,6 +18263,48 @@ "source-map": "^0.7.3" } }, + "@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==" + }, + "@react-aria/ssr": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.3.0.tgz", + "integrity": "sha512-yNqUDuOVZIUGP81R87BJVi/ZUZp/nYOBXbPsRe7oltJOfErQZD+UezMpw4vM2KRz18cURffvmC8tJ6JTeyDtaQ==", + "requires": { + "@babel/runtime": "^7.6.2" + } + }, + "@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==" + }, + "@restart/hooks": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.7.tgz", + "integrity": "sha512-ZbjlEHcG+FQtpDPHd7i4FzNNvJf2enAwZfJbpM8CW7BhmOAbsHpZe3tsHwfQUrBuyrxWqPYp2x5UMnilWcY22A==", + "requires": { + "dequal": "^2.0.2" + } + }, + "@restart/ui": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.4.1.tgz", + "integrity": "sha512-J7wFOx2DcmkBqCqiZgDsggLO7faiNh4Nv1/v80FmbRgP+MYpwaVDKKXLC69DA4+ejgNIsBP5ORtC74EZqO1j8A==", + "requires": { + "@babel/runtime": "^7.18.3", + "@popperjs/core": "^2.11.5", + "@react-aria/ssr": "^3.2.0", + "@restart/hooks": "^0.4.7", + "@types/warning": "^3.0.0", + "dequal": "^2.0.2", + "dom-helpers": "^5.2.0", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + } + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -18201,6 +18696,11 @@ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==" }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, "@types/q": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", @@ -18216,6 +18716,24 @@ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, + "@types/react": { + "version": "18.0.25", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.25.tgz", + "integrity": "sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", + "requires": { + "@types/react": "*" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -18229,6 +18747,11 @@ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + }, "@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -18264,6 +18787,11 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" }, + "@types/warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", + "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + }, "@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -18750,6 +19278,12 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true + }, "array.prototype.flat": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", @@ -19142,6 +19676,12 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, + "bootstrap": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.2.tgz", + "integrity": "sha512-dEtzMTV71n6Fhmbg4fYJzQsw1N29hJKO1js5ackCgIpDcGid2ETMGC6zwSYw09v05Y+oRdQ9loC54zB1La3hHQ==", + "requires": {} + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -19318,6 +19858,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" }, + "classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "clean-css": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz", @@ -19809,6 +20354,11 @@ } } }, + "csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + }, "damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -19889,6 +20439,11 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, "destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -19990,6 +20545,15 @@ "utila": "~0.4" } }, + "dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "requires": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -20080,6 +20644,12 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.131.tgz", "integrity": "sha512-oi3YPmaP87hiHn0c4ePB67tXaF+ldGhxvZnT19tW9zX6/Ej+pLN0Afja5rQ6S+TND7I9EuwQTT8JYn1k7R7rrw==" }, + "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==", + "dev": true + }, "emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -20909,6 +21479,23 @@ } } }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "dev": true + }, + "filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "dev": true, + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + } + }, "filesize": { "version": "8.0.7", "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", @@ -21202,6 +21789,77 @@ "get-intrinsic": "^1.1.1" } }, + "gh-pages": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-4.0.0.tgz", + "integrity": "sha512-p8S0T3aGJc68MtwOcZusul5qPSNZCalap3NWbhRUZYu1YOdp+EjZ+4kPmRM8h3NNRdqw00yuevRjlkuSzCn7iQ==", + "dev": true, + "requires": { + "async": "^2.6.1", + "commander": "^2.18.0", + "email-addresses": "^3.0.1", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -21600,6 +22258,14 @@ "side-channel": "^1.0.4" } }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -24068,6 +24734,27 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, "pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -24892,6 +25579,22 @@ } } }, + "prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "requires": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -25009,6 +25712,25 @@ "whatwg-fetch": "^3.6.2" } }, + "react-bootstrap": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.6.0.tgz", + "integrity": "sha512-WnDgN6PR8WZKo2Og5J8EafFi4BsABjc96lNuMNfksrgiPDCw18/woWQCNhAeHFZQWTQ/PijkOrQ9ncTWwO//AA==", + "requires": { + "@babel/runtime": "^7.17.2", + "@restart/hooks": "^0.4.6", + "@restart/ui": "^1.4.1", + "@types/react-transition-group": "^4.4.4", + "classnames": "^2.3.1", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.2", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + } + }, "react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -25114,11 +25836,33 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, "react-refresh": { "version": "0.11.0", "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", @@ -25174,6 +25918,17 @@ "workbox-webpack-plugin": "^6.4.1" } }, + "react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "requires": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + } + }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -25224,9 +25979,9 @@ } }, "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.10", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz", + "integrity": "sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==" }, "regenerator-transform": { "version": "0.15.0", @@ -25940,6 +26695,15 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", @@ -26286,6 +27050,15 @@ "punycode": "^2.1.1" } }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -26389,6 +27162,17 @@ "which-boxed-primitive": "^1.0.2" } }, + "uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "requires": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + } + }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -26524,6 +27308,14 @@ "makeerror": "1.0.12" } }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "watchpack": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", diff --git a/package.json b/package.json index a100866d..137158c0 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,20 @@ { "name": "project1-bootcamp", "version": "0.1.0", + "homepage": "http://gggaryteo.github.io/", "private": true, "dependencies": { + "bootstrap": "^5.2.2", + "classnames": "^2.3.2", "react": "^18.1.0", + "react-bootstrap": "^2.6.0", "react-dom": "^18.1.0", + "react-router-dom": "^6.4.3", "react-scripts": "5.0.1" }, "scripts": { + "predeploy": "npm run build", + "deploy": "gh-pages -d build", "start": "react-scripts start", "build": "react-scripts build" }, @@ -27,5 +34,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "gh-pages": "^4.0.0" } } diff --git a/public/PokemonPics/Bulbasaur.png b/public/PokemonPics/Bulbasaur.png new file mode 100644 index 00000000..6d5ce51f Binary files /dev/null and b/public/PokemonPics/Bulbasaur.png differ diff --git a/public/PokemonPics/Charmander.png b/public/PokemonPics/Charmander.png new file mode 100644 index 00000000..bfaba624 Binary files /dev/null and b/public/PokemonPics/Charmander.png differ diff --git a/public/PokemonPics/Clefairy.png b/public/PokemonPics/Clefairy.png new file mode 100644 index 00000000..0b5c9d88 Binary files /dev/null and b/public/PokemonPics/Clefairy.png differ diff --git a/public/PokemonPics/Cubone.png b/public/PokemonPics/Cubone.png new file mode 100644 index 00000000..47bc3b62 Binary files /dev/null and b/public/PokemonPics/Cubone.png differ diff --git a/public/PokemonPics/Diglett.png b/public/PokemonPics/Diglett.png new file mode 100644 index 00000000..42a009dc Binary files /dev/null and b/public/PokemonPics/Diglett.png differ diff --git a/public/PokemonPics/Ditto.png b/public/PokemonPics/Ditto.png new file mode 100644 index 00000000..f8c8e863 Binary files /dev/null and b/public/PokemonPics/Ditto.png differ diff --git a/public/PokemonPics/Eevee.png b/public/PokemonPics/Eevee.png new file mode 100644 index 00000000..53f67679 Binary files /dev/null and b/public/PokemonPics/Eevee.png differ diff --git a/public/PokemonPics/Meowth.png b/public/PokemonPics/Meowth.png new file mode 100644 index 00000000..112bcd27 Binary files /dev/null and b/public/PokemonPics/Meowth.png differ diff --git a/public/PokemonPics/Pichu.png b/public/PokemonPics/Pichu.png new file mode 100644 index 00000000..99911c33 Binary files /dev/null and b/public/PokemonPics/Pichu.png differ diff --git a/public/PokemonPics/Pikachu.png b/public/PokemonPics/Pikachu.png new file mode 100644 index 00000000..9338abc3 Binary files /dev/null and b/public/PokemonPics/Pikachu.png differ diff --git a/public/PokemonPics/Psyduck.png b/public/PokemonPics/Psyduck.png new file mode 100644 index 00000000..a2c1350d Binary files /dev/null and b/public/PokemonPics/Psyduck.png differ diff --git a/public/PokemonPics/Slowpoke.png b/public/PokemonPics/Slowpoke.png new file mode 100644 index 00000000..1fb8a107 Binary files /dev/null and b/public/PokemonPics/Slowpoke.png differ diff --git a/public/PokemonPics/Snorlax.png b/public/PokemonPics/Snorlax.png new file mode 100644 index 00000000..d11dd37b Binary files /dev/null and b/public/PokemonPics/Snorlax.png differ diff --git a/public/PokemonPics/Squirtle.png b/public/PokemonPics/Squirtle.png new file mode 100644 index 00000000..6ec3b244 Binary files /dev/null and b/public/PokemonPics/Squirtle.png differ diff --git a/public/PokemonPics/Totodile.png b/public/PokemonPics/Totodile.png new file mode 100644 index 00000000..6e5877a0 Binary files /dev/null and b/public/PokemonPics/Totodile.png differ diff --git a/public/PokemonPics/Wobbuffet.png b/public/PokemonPics/Wobbuffet.png new file mode 100644 index 00000000..1739761f Binary files /dev/null and b/public/PokemonPics/Wobbuffet.png differ diff --git a/public/PokemonPics/YouWonTheGame.png b/public/PokemonPics/YouWonTheGame.png new file mode 100644 index 00000000..c7c26e02 Binary files /dev/null and b/public/PokemonPics/YouWonTheGame.png differ diff --git a/public/PokemonPics/background.jpg b/public/PokemonPics/background.jpg new file mode 100644 index 00000000..540468cc Binary files /dev/null and b/public/PokemonPics/background.jpg differ diff --git a/public/PokemonPics/logo.png b/public/PokemonPics/logo.png new file mode 100644 index 00000000..bba7cca9 Binary files /dev/null and b/public/PokemonPics/logo.png differ diff --git a/public/PokemonPics/pokeball.png b/public/PokemonPics/pokeball.png new file mode 100644 index 00000000..10496b4d Binary files /dev/null and b/public/PokemonPics/pokeball.png differ diff --git a/public/PokemonPics/sparkle.png b/public/PokemonPics/sparkle.png new file mode 100644 index 00000000..1259410f Binary files /dev/null and b/public/PokemonPics/sparkle.png differ diff --git a/public/PokemonPics/won.png b/public/PokemonPics/won.png new file mode 100644 index 00000000..888d4ee3 Binary files /dev/null and b/public/PokemonPics/won.png differ diff --git a/src/App.css b/src/App.css index 97b7c578..cc147123 100644 --- a/src/App.css +++ b/src/App.css @@ -1,19 +1,24 @@ -.App { - text-align: center; +@import url("https://fonts.googleapis.com/css2?family=Caveat:wght@500&family=Noto+Sans&family=Roboto&display=swap"); +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: "Noto Sans", sans-serif; } -.App-logo { - height: 40vmin; - pointer-events: none; +body { + width: 100%; + min-height: 100vh; + background: url("/public/PokemonPics/background.jpg"); } -.App-header { - background-color: #282c34; +.game-container { + width: 100vw; min-height: 100vh; - display: flex; - flex-direction: column; align-items: center; justify-content: center; - font-size: calc(10px + 2vmin); - color: white; + text-align: center; + display: grid; + grid-template-columns: 1fr; + grid-template-rows: auto 1fr auto; } diff --git a/src/App.js b/src/App.js index 4a6f800f..fa6dd717 100644 --- a/src/App.js +++ b/src/App.js @@ -1,17 +1,39 @@ import React from "react"; -import logo from "./logo.png"; import "./App.css"; +import {Routes, Route} from 'react-router-dom'; +import Game from "./Components/Game"; +import Leaderboard from "./Components/Leaderboard"; class App extends React.Component { + constructor(props){ + super(props) + this.state = { + scoreboard: [ + { easy: "easy", score: 0 }, + { medium: "medium", score: 0 }, + { hard: "hard", score: 0 }, + ], + }; + } + render() { return ( -
-
- logo -

- Edit src/App.js and save to reload. -

-
+
+ + + +
+ } + /> + + } + /> +
); } diff --git a/src/Components/Card.css b/src/Components/Card.css new file mode 100644 index 00000000..8303e0bd --- /dev/null +++ b/src/Components/Card.css @@ -0,0 +1,65 @@ +.card { + position: relative; + width: 200px; + height: 200px; + cursor: pointer; +} +.card.flipped .front { + transform: rotateY(0deg); + transition-delay: 0.2s; +} +.card.flipped .back { + transform: rotateY(90deg); + transition-delay: 0s; +} +.card .front, .card .back { + border: 4px solid #3cc8dc; + border-radius: 6px; +} +.card .front { + position: absolute; + transform: rotateY(90deg); + width: 100%; + height: auto; + padding: 24.5% 20%; + transition: all ease 0.2s; + background: white; +} +.card .back { + width: 100%; + height: 100%; + padding: 30%; + transform: rotateY(0deg); + transition: all ease 0.2s; + transition-delay: 0.2s; + background: #d7f5fa; + opacity: 0.9; +} + +.card.matched .xmassparkle { + animation: sparkle 1s; +} +.card .xmassparkle { + position: absolute; + width: 20%; + z-index: 1; + top: -1rem; + left: -1rem; + opacity: 0; + transition: all ease 0.3s; +} +@keyframes sparkle { + 0% { + top: 1rem; + left: 1rem; + opacity: 0; + } + 50% { + top: -1rem; + left: -1rem; + opacity: 1; + } + 100% { + opacity: 0; + } +} diff --git a/src/Components/Card.js b/src/Components/Card.js new file mode 100644 index 00000000..d6103988 --- /dev/null +++ b/src/Components/Card.js @@ -0,0 +1,28 @@ +import React from "react"; +import "./Card.css"; + +export default class Card extends React.Component { + render() { + const { img, matched } = this.props.card; + return ( +
+ sparkle + card front + {} + : () => this.props.handleClick(this.props.card) + } + src={"PokemonPics/pokeball.png"} + alt="card back" + /> +
+ ); + } +} \ No newline at end of file diff --git a/src/Components/Game.css b/src/Components/Game.css new file mode 100644 index 00000000..1e38deee --- /dev/null +++ b/src/Components/Game.css @@ -0,0 +1,55 @@ +@import url("https://fonts.googleapis.com/css2?family=Caveat:wght@500&family=Noto+Sans&family=Roboto&display=swap"); + +.card-grid { + display: grid; + grid-gap: 20px; + margin: auto; +} +.card-grid .moves { + grid-column: 1 / span 1; + text-align: left; + font-size: 1.5rem; + font-weight: bold; +} +.card-grid button { + grid-column: -2 / span 1; + width: 200px; + margin: 0; +} +.card-grid.easy { + max-width: 900px; + grid-template-columns: repeat(4, 1fr); +} +.card-grid.medium { + max-width: 1100px; + grid-template-columns: repeat(5, 1fr); +} +.card-grid.hard { + max-width: 1500px; + grid-template-columns: repeat(7, 1fr); +} + +audio:hover, +audio:focus, +audio:active { + -webkit-box-shadow: 15px 15px 20px rgba(0, 0, 0, 0.4); + -moz-box-shadow: 15px 15px 20px rgba(0, 0, 0, 0.4); + box-shadow: 15px 15px 20px rgba(0, 0, 0, 0.4); + -webkit-transform: scale(1.05); + -moz-transform: scale(1.05); + transform: scale(1.05); +} + +audio { + margin-top: 15px; + -webkit-transition: all 0.5s linear; + -moz-transition: all 0.5s linear; + -o-transition: all 0.5s linear; + transition: all 0.5s linear; + -moz-box-shadow: 2px 2px 4px 0px #006773; + -webkit-box-shadow: 2px 2px 4px 0px #006773; + box-shadow: 2px 2px 4px 0px #006773; + -moz-border-radius: 7px 7px 7px 7px; + -webkit-border-radius: 7px 7px 7px 7px; + border-radius: 7px 7px 7px 7px; +} diff --git a/src/Components/Game.js b/src/Components/Game.js new file mode 100644 index 00000000..adaa7d36 --- /dev/null +++ b/src/Components/Game.js @@ -0,0 +1,245 @@ +import React from "react"; +import "../Components/Game.css" +import Header from "./Header"; +import Menu from "../Components/Menu"; +import Card from "../Components/Card"; +import Overlay from "../Components/Overlay"; +import { makeDeck } from "../helpers"; +import ChristmasMP3 from "../Sound/christmasmedley.mp3"; +import Timer from "../Components/Timer"; +import {Link} from "react-router-dom" + +class Game extends React.Component { + constructor(props) { + super(props); + + this.state = { + difficulty: "", + moves: 0, + cardOne: null, + cardTwo: null, + disabled: false, + cards: [], + gameOver: false, + }; + this.setDifficulty = this.setDifficulty.bind(this); + } + + timerMethod = (property, value) => { + this.setState( + { + [property]: value, + }, + () => console.log(this.state.gameOver) + ); + }; + + // shuffleCards = () => { + // const numberOfCards = gameMode[this.state.difficulty].numCards; + // console.log(this.state.difficulty); + // const randomCards = []; + // const listIndex = []; + + // while (randomCards.length < numberOfCards) { + // const random = Math.floor(Math.random() * cardImgs.length); + + // if (listIndex.includes(random)) { + // continue; + // } + // listIndex.push(random); + + // Need pairs of the same card to match in the game + // randomCards.push({ + // id: Math.random(), + // matched: false, + // ...cardImgs[random], + // }); + // randomCards.push({ + // id: Math.random(), + // matched: false, + // ...cardImgs[random], + // }); + // } + // randomCards.sort((a, b) => a.id - b.id); + // this.setState({ + // cards: randomCards, + // }); + // }; + + componentDidUpdate() { + console.log(this.hasWon); + if (this.state.gameOver === false) { + if (this.hasWon) { + this.setState( + { + gameOver: true, + }, + () => console.log(this.state.gameOver) + ); + } + } + } + // If Cards do not match, turn back the cards and moves++ + + resetTurn = () => { + this.setState({ + cardOne: null, + cardTwo: null, + moves: this.state.moves + 1, + disabled: false, + }); + }; + + evaluateMatch = () => { + if (this.state.cardOne.img === this.state.cardTwo.img) { + console.log(this.state.cardOne.id); + console.log(this.state.cardTwo.id); + let cardOne = { ...this.state.cardOne, matched: true }; + console.log(cardOne); + let indexOne = this.state.cards.findIndex( + (card) => card.id === this.state.cardOne.id + ); + console.log(indexOne); + let cardTwo = { ...this.state.cardTwo, matched: true }; + console.log(cardTwo); + let indexTwo = this.state.cards.findIndex( + (card) => card.id === this.state.cardTwo.id + ); + console.log(indexTwo); + console.log(this.state.cards); + this.state.cards.splice(indexOne, 1, cardOne); + this.state.cards.splice(indexTwo, 1, cardTwo); + this.setState({ + cards: this.state.cards, + cardOne: null, + cardTwo: null, + }); + } else { + this.timerID = setTimeout(() => { + this.resetTurn(); + }, 1000); + } + }; + + isFlipped = (card) => { + return ( + card.id === this.state.cardOne?.id || + card.id === this.state.cardTwo?.id || + card.matched + ); + }; + + handleClick = (card) => { + if (this.state.cardOne) { + console.log(this.state.cardOne); + if (card.id !== this.state.cardOne.id) { + this.setState( + { + cardTwo: card, + }, + () => { + this.evaluateMatch(); + } + ); + } + } else { + this.setState( + { + cardOne: card, + }, + () => console.log(this.state.cardOne) + ); + } + }; + + handleBackToMenu = () => { + // If every card matches: + // 1. Check to see if there's any objects/items in the localStorage + // 2. if it does, you getItem from localStorage, unstringify, parse it, and you push the new Game into the existing set of array + // 3. if it doesn't, you stringify a new object and add it into the local storage. + + if (this.state.cards.every((card) => card.matched)) { + let previous = localStorage.getItem("storeGames"); + previous = JSON.parse(previous); + if (previous && previous.length > 0) { + let Game = { + difficulty: this.state.difficulty, + moves: this.state.moves, + }; + previous.push(Game); + console.log(previous); + let storeGames = JSON.stringify(previous); + localStorage.setItem("storeGames", storeGames); + } else { + let Game = [ + { + difficulty: this.state.difficulty, + moves: this.state.moves, + }, + ]; + let storeGames = JSON.stringify([...Game]); + localStorage.setItem("storeGames", storeGames); + console.log(storeGames); + } + } + // Reset State + this.setState({ + cards: [], + difficulty: "", + moves: 0, + }); + }; + + setDifficulty(getDifficulty) { + this.setState({ + difficulty: getDifficulty, + cards: makeDeck(getDifficulty), + });; + } + + + render() { + this.hasWon = this.state.cards.length + ? this.state.cards.every((card) => card.matched) + : false; + + return ( + <> +
+
+
+
+ {!this.state.difficulty && } + + {this.state.difficulty && ( + <> +
+
Moves: {this.state.moves}
+ + + {this.state.cards.map((card) => ( + + ))} +
+ + )} +
+ {this.hasWon && } + {!this.state.difficulty && } + + ); + } +} + +export default Game; diff --git a/src/Components/Header.css b/src/Components/Header.css new file mode 100644 index 00000000..12cb35a6 --- /dev/null +++ b/src/Components/Header.css @@ -0,0 +1,33 @@ +@import url('https://fonts.googleapis.com/css2?family=Luckiest+Guy&family=Roboto:wght@400;700&display=swap'); + +header { + width: 100%; +} + +.slogan { + font-family: "Luckiest Guy", Roboto; + margin-top: -1rem; + font-size: 30px; + text-align: center; + margin-top: 10px; + margin-bottom: 20px; + animation: color-change 1s infinite; +} + +@keyframes color-change { + 0% { color: red; } + 50% { color: green; } + 100% { color: red; } +} + +.center-img { + display:flex; + align-items: center; + justify-content: center; + margin-top: 3rem; +} + +img { + width: 400px; + height: auto; +} \ No newline at end of file diff --git a/src/Components/Header.js b/src/Components/Header.js new file mode 100644 index 00000000..e7d3f6c3 --- /dev/null +++ b/src/Components/Header.js @@ -0,0 +1,16 @@ +import React from "react"; +import "./Header.css"; + +export default class Header extends React.Component { + + render(){ + return ( +
+
+ logo +
+

Christmas Edition - Gotta match 'em all!

+
+ ); + } +} diff --git a/src/Components/Leaderboard.css b/src/Components/Leaderboard.css new file mode 100644 index 00000000..c45f320a --- /dev/null +++ b/src/Components/Leaderboard.css @@ -0,0 +1,44 @@ +@import url('https://fonts.googleapis.com/css2?family=Luckiest+Guy&family=Roboto:wght@400;700&display=swap'); + +.leaderboard-header{ + font-family: "Luckiest Guy", Roboto; + font-size: 65px; + margin-top: 20px; + color: #FFDE00; + text-align: center; + -webkit-text-stroke: 3px #3B4CCA; +} + +h2 { + font-family: "Luckiest Guy", Roboto; + text-align: center; + margin-top: 20px; + animation: color-change 1s infinite; +} + +@keyframes color-change { + 0% { color: red; } + 50% { color: rgb(60, 0, 255); } + 100% { color: red; } +} + + +.data-container { + display: flex; + justify-content: center; + align-items: center; + width: 400px; + margin-top: 30px; + font-weight: bold; + border-style: solid; +} + +.center-data { + display: flex; + justify-content: center; +} + +.center-button { + display: flex; + justify-content: center; +} \ No newline at end of file diff --git a/src/Components/Leaderboard.js b/src/Components/Leaderboard.js new file mode 100644 index 00000000..3cfc80b7 --- /dev/null +++ b/src/Components/Leaderboard.js @@ -0,0 +1,51 @@ +import React, { Component } from "react"; +import './Leaderboard.css' +import { Link } from "react-router-dom"; + +export default class Leaderboard extends Component { + constructor(props) { + super(props); + this.state = { + myGame: [], + }; + } + + componentDidMount() { + let currenlyStoredGames = localStorage.getItem("storeGames"); + console.log(currenlyStoredGames); + let parsedCurrentlyStoredGames = JSON.parse(currenlyStoredGames); + console.log(parsedCurrentlyStoredGames); + if (parsedCurrentlyStoredGames === null) { + parsedCurrentlyStoredGames = []; + } + this.setState({ + myGame: parsedCurrentlyStoredGames, + }); + } + + render() { + return ( + <> +

Single Player Leaderboard 😢

+ {this.state.myGame && this.state.myGame.length > 0 ? ( + this.state.myGame.map((data, index) => ( +
+
+

+ {data.difficulty.toUpperCase()} LEVEL - YOU TOOK {data.moves} MOVES +

+
+
+ )) + ) : ( +

No Games Yet

+ )} +
+ + + +
+ + ); + } +} diff --git a/src/Components/Menu.css b/src/Components/Menu.css new file mode 100644 index 00000000..715a5850 --- /dev/null +++ b/src/Components/Menu.css @@ -0,0 +1,50 @@ +.menu { + display: flex; + align-items: center; + justify-content: space-between; + flex-direction: column; +} +.description p { + margin-top: 1rem; + font-size: 2rem; + font-weight: bold; + text-align: center; +} + +.starter-poke { + width: 150px; +} + +button { + width: 300px; + background-color: #d7f5fa; + border: 4px solid #3cc8dc; + border-radius: 6px; + margin: 2rem 0; + padding: 0.5rem 0; + font-family: sans-serif; + font-size: 1.2rem; + font-weight: bold; + letter-spacing: 4px; + cursor: pointer; + transition: all ease 0.2s; +} +button:hover { + transform: scale(1.1); +} + +.blue { + background-color: #d7f5fa; + border: 4px solid #3cc8dc; +} + +.green { + background-color: #70e0bb; + border: 4px solid #378e8e; +} + +.red { + background-color: #fe9441; + border: 4px solid #e53800; +} + diff --git a/src/Components/Menu.js b/src/Components/Menu.js new file mode 100644 index 00000000..ffd37c07 --- /dev/null +++ b/src/Components/Menu.js @@ -0,0 +1,42 @@ +import React from "react"; +import "./Menu.css"; + +export default class Menu extends React.Component { + render() { + return ( +
+
+ Bulbasaur + Bulbasaur + Squirtle +

Please select a difficulty to start!

+
+ + + + +
+ ); + } +} diff --git a/src/Components/Overlay.css b/src/Components/Overlay.css new file mode 100644 index 00000000..2ed8dbc6 --- /dev/null +++ b/src/Components/Overlay.css @@ -0,0 +1,8 @@ +.overlay-container { + position: absolute; + width: 100%; + height: 100vh; + background-color: rgba(0, 0, 0, 0.5); + display: grid; + place-items: center; +} \ No newline at end of file diff --git a/src/Components/Overlay.js b/src/Components/Overlay.js new file mode 100644 index 00000000..158eac5d --- /dev/null +++ b/src/Components/Overlay.js @@ -0,0 +1,17 @@ +import React from 'react'; +import "./Overlay.css"; + +export default class Overlay extends React.Component{ + render(){ + return( +
+
+ winmessage +
+ +
+
+
+ ) + } +} \ No newline at end of file diff --git a/src/Components/Timer.css b/src/Components/Timer.css new file mode 100644 index 00000000..1edc6138 --- /dev/null +++ b/src/Components/Timer.css @@ -0,0 +1,4 @@ +h3 { + font-family: "Noto Sans", sans-serif; + font-size: 25px; +} \ No newline at end of file diff --git a/src/Components/Timer.js b/src/Components/Timer.js new file mode 100644 index 00000000..b6628272 --- /dev/null +++ b/src/Components/Timer.js @@ -0,0 +1,62 @@ +import React from "react"; +import './Timer.css' + +export default class Timer extends React.Component { + constructor(props) { + super(props); + + this.state = { + minutes: 0, + seconds: 0, + gameOver: false, + }; + } + + componentDidMount() { + if ( + this.props.difficulty === "easy" || + this.props.difficulty === "medium" || + this.props.difficulty === "hard" + ) { + this.setState({ + minutes: 2, + seconds: 45, + }); + } + + this.timerID = setInterval(() => { + if (this.state.seconds > 0) { + this.setState({ + seconds: this.state.seconds - 1 + }) + } + if (this.state.seconds === 0) { + if (this.state.minutes === 0) { + clearInterval(this.timerID) + this.props.timerMethod('gameOver', true) + } else { + this.setState({ + minutes: this.state.minutes - 1, + seconds: 59 + }) + } + } + + }, 1000) + } + + componentWillUnmount(){ + clearInterval(this.timerID) + } + + render() { + const {minutes, seconds} = this.state + return ( +
+ {(!this.props.hasWon && !this.props.gameOver) &&

Timer - {minutes} : {seconds < 10 ? `0${seconds}` : seconds}

} + {this.props.hasWon &&

You Won!

} + {(minutes === 0 && seconds === 0) &&

Game over!

} +
+ ) + } +} \ No newline at end of file diff --git a/src/Sound/christmasmedley.mp3 b/src/Sound/christmasmedley.mp3 new file mode 100644 index 00000000..9e5f19e8 Binary files /dev/null and b/src/Sound/christmasmedley.mp3 differ diff --git a/src/helpers.js b/src/helpers.js new file mode 100644 index 00000000..1baefd1d --- /dev/null +++ b/src/helpers.js @@ -0,0 +1,67 @@ +const lodash = require("lodash"); + +const gameMode = { + easy: { numCards: 12, gridColumns: 4 }, + medium: { numCards: 20, gridColumns: 5 }, + hard: { numCards: 28, gridColumns: 7 }, +}; + +const pokemonNames = [ + "Bulbasaur", + "Charmander", + "Clefairy", + "Cubone", + "Diglett", + "Ditto", + "Eevee", + "Meowth", + "Pichu", + "Pikachu", + "Psyduck", + "Slowpoke", + "Snorlax", + "Squirtle", + "Totodile", + "Wobbuffet", +]; + +function shuffleCards(deck) { + let currentIndex = 0; + while (currentIndex < deck.length) { + let randomIndex = Math.floor(Math.random() * deck.length); + let a = deck[randomIndex]; + let b = deck[currentIndex]; + [a, b] = [b, a]; + deck[currentIndex] = b; + deck[randomIndex] = a; + currentIndex++; + } + return deck; +} + +export function makeDeck(difficulty) { + let deck = []; + for (let i = 0; i < pokemonNames.length; i++) { + deck.push({ + id: i, + matched: false, + img: `/PokemonPics/${pokemonNames[i]}.png`, + }); + } + shuffleCards(deck); + console.log("Deck: ", deck); + let newDeck = deck.slice(-1 * (gameMode[difficulty].numCards / 2)); + console.log(newDeck); + // duplicate array + let duplicatedDeck = []; + for (let j = 0; j < gameMode[difficulty].numCards; j++) { + // Deep Clone Array so that it wont reference the same object + // and produce the same id + let card = lodash.cloneDeep(newDeck[Math.floor(j / 2)]); + card.id = j; + duplicatedDeck.push(card); + } + console.log(duplicatedDeck); + duplicatedDeck = shuffleCards(duplicatedDeck); + return duplicatedDeck; +} \ No newline at end of file diff --git a/src/index.css b/src/index.css deleted file mode 100644 index 4a1df4db..00000000 --- a/src/index.css +++ /dev/null @@ -1,13 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; -} diff --git a/src/index.js b/src/index.js index 31508db1..4208d0eb 100644 --- a/src/index.js +++ b/src/index.js @@ -1,11 +1,13 @@ import React from "react"; import ReactDOM from "react-dom/client"; -import "./index.css"; import App from "./App"; +import { BrowserRouter } from "react-router-dom" const root = ReactDOM.createRoot(document.getElementById("root")); root.render( - + + + );