diff --git a/.github/workflows/jsdoc.yaml b/.github/workflows/jsdoc.yaml new file mode 100644 index 0000000..562103b --- /dev/null +++ b/.github/workflows/jsdoc.yaml @@ -0,0 +1,26 @@ +name: JSDoc to GH Pages + +on: + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v2 + + - name: Build + uses: andstor/jsdoc-action@v1 + with: + source_dir: ./frontend-next + output_dir: ./jsdoc + template: minami + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./jsdoc \ No newline at end of file diff --git a/frontend-next/.eslintrc.json b/frontend-next/.eslintrc.json index 6b2f9c6..471d759 100644 --- a/frontend-next/.eslintrc.json +++ b/frontend-next/.eslintrc.json @@ -4,6 +4,6 @@ "no-unused-vars": ["warn", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false }], "jsx-a11y/alt-text": "off", "@next/next/no-img-element": "off", - "no-console": "on", + "no-console": 1 } } diff --git a/frontend-next/package-lock.json b/frontend-next/package-lock.json index e31d9a5..acc54de 100644 --- a/frontend-next/package-lock.json +++ b/frontend-next/package-lock.json @@ -8,7 +8,11 @@ "name": "chatmaps", "version": "0.1.0", "dependencies": { + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", "@headlessui/react": "^1.7.18", + "@mui/icons-material": "^5.15.14", + "@mui/material": "^5.15.14", "firebase": "^10.6.0", "next": "^14.1.0", "pigeon-maps": "^0.21.3", @@ -48,11 +52,127 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dependencies": { + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dependencies": { + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/runtime": { "version": "7.24.1", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", - "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -60,6 +180,152 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "dependencies": { + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/react": { + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", + "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, + "node_modules/@emotion/styled": { + "version": "11.11.5", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz", + "integrity": "sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/is-prop-valid": "^1.2.2", + "@emotion/serialize": "^1.1.4", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -601,6 +867,40 @@ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.5.tgz", "integrity": "sha512-eSkJsnhBWv5kCTSU1tSUVl9mpFu+5NXXunZc83le8GMjMlsWwQArSc7cJJ4yl+aDFY0NGLi0AjZWMn1axOrkRg==" }, + "node_modules/@floating-ui/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", + "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==", + "dependencies": { + "@floating-ui/utils": "^0.2.1" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", + "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", + "dependencies": { + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz", + "integrity": "sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==", + "dependencies": { + "@floating-ui/dom": "^1.6.1" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", + "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" + }, "node_modules/@grpc/grpc-js": { "version": "1.9.14", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.14.tgz", @@ -771,6 +1071,261 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mui/base": { + "version": "5.0.0-beta.40", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz", + "integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@floating-ui/react-dom": "^2.0.8", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.14.tgz", + "integrity": "sha512-on75VMd0XqZfaQW+9pGjSNiqW+ghc5E2ZSLRBXwcXl/C4YzjfyjrLPhrEpKnR9Uym9KXBvxrhoHfPcczYHweyA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.14.tgz", + "integrity": "sha512-vj/51k7MdFmt+XVw94sl30SCvGx6+wJLsNYjZRgxhS6y3UtnWnypMOsm3Kmg8TN+P0dqwsjy4/fX7B1HufJIhw==", + "dependencies": { + "@babel/runtime": "^7.23.9" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.14.tgz", + "integrity": "sha512-kEbRw6fASdQ1SQ7LVdWR5OlWV3y7Y54ZxkLzd6LV5tmz+NpO3MJKZXSfgR0LHMP7meKsPiMm4AuzV0pXDpk/BQ==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/base": "5.0.0-beta.40", + "@mui/core-downloads-tracker": "^5.15.14", + "@mui/system": "^5.15.14", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^18.2.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/@mui/private-theming": { + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.14.tgz", + "integrity": "sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.15.14", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz", + "integrity": "sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.11.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.14.tgz", + "integrity": "sha512-auXLXzUaCSSOLqJXmsAaq7P96VPRXg2Rrz6OHNV7lr+kB8lobUF+/N84Vd9C4G/wvCXYPs5TYuuGBRhcGbiBGg==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.15.14", + "@mui/styled-engine": "^5.15.14", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz", + "integrity": "sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.14.tgz", + "integrity": "sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@types/prop-types": "^15.7.11", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/@next/env": { "version": "14.1.4", "resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.4.tgz", @@ -965,6 +1520,15 @@ "node": ">=14" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -1072,6 +1636,33 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" + }, + "node_modules/@types/react": { + "version": "18.2.74", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.74.tgz", + "integrity": "sha512-9AEqNZZyBx8OdZpxzQlaFEVCSFUM2YXJH46yPOiOpm078k6ZLOCcuAzGum/zK8YBwY+dbahVNbHrbgrAwIRlqw==", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@typescript-eslint/parser": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", @@ -1548,6 +2139,20 @@ "dequal": "^2.0.3" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1654,7 +2259,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -1791,6 +2395,14 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/clsx": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", + "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1822,6 +2434,34 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1848,6 +2488,11 @@ "node": ">=4" } }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -2007,6 +2652,15 @@ "node": ">=6.0.0" } }, + "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/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2038,6 +2692,14 @@ "node": ">=10.13.0" } }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-abstract": { "version": "1.23.2", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", @@ -2208,7 +2870,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -2718,6 +3379,11 @@ "node": ">=8" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -2849,7 +3515,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3141,7 +3806,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -3149,6 +3813,14 @@ "node": ">= 0.4" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/http-parser-js": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", @@ -3172,7 +3844,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -3239,6 +3910,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, "node_modules/is-async-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", @@ -3310,7 +3986,6 @@ "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, "dependencies": { "hasown": "^2.0.0" }, @@ -3664,6 +4339,11 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3755,8 +4435,7 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/locate-path": { "version": "6.0.0", @@ -3992,7 +4671,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4178,7 +4856,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -4186,6 +4863,23 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4216,8 +4910,7 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { "version": "1.10.1", @@ -4248,7 +4941,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -4467,7 +5159,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -4592,8 +5283,22 @@ "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==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "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/read-cache": { "version": "1.0.0", @@ -4640,8 +5345,7 @@ "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", @@ -4673,7 +5377,6 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -4690,7 +5393,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "engines": { "node": ">=4" } @@ -4959,6 +5661,14 @@ "node": ">=8" } }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", @@ -5182,6 +5892,11 @@ } } }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -5220,7 +5935,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -5301,6 +6015,14 @@ "node": ">=0.8" } }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/frontend-next/package.json b/frontend-next/package.json index f7091b2..03da846 100644 --- a/frontend-next/package.json +++ b/frontend-next/package.json @@ -9,7 +9,11 @@ "lint": "next lint" }, "dependencies": { + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", "@headlessui/react": "^1.7.18", + "@mui/icons-material": "^5.15.14", + "@mui/material": "^5.15.14", "firebase": "^10.6.0", "next": "^14.1.0", "pigeon-maps": "^0.21.3", diff --git a/frontend-next/src/app/app/page.js b/frontend-next/src/app/app/page.js index 75d60e3..b8a6c96 100644 --- a/frontend-next/src/app/app/page.js +++ b/frontend-next/src/app/app/page.js @@ -1,28 +1,31 @@ "use client"; // System Imports import { useState, useEffect } from "react"; + +// Dependencies +import { useGeolocated } from "react-geolocated"; + +// Firebase Imports import { auth, database } from "../../../firebase-config"; import { ref, onValue } from "firebase/database"; import { useAuthState } from "react-firebase-hooks/auth" -import { useGeolocated } from "react-geolocated"; -// Header Import +// Component Imports import { Header } from "../../components/app/header"; +import { HomePage } from "../../components/app/page/home"; +import { Sidebar } from "../../components/app/sidebar/home"; -// Main Tab Imports -import { MainTabHome } from "../../components/app/main_tab/home"; - -// Sidebar Imports -import { Home_Sidebar } from "../../components/app/sidebar/home"; - -// Contains most everything for the app homepage +/** +* Contains most everything for the app homepage +* @returns {Object} Home Page +*/ function Home() { - // It's time to document and change these awful variable names // State variables for app page - const [user, setUser] = useState(null); + const [user, setUser] = useState(null); // user data const [loadingLoc, setLoadingLoc] = useState(true); // location variable loading, true = loading, false = finished loading - const [authUser, loading] = useAuthState(auth) + const [authUser] = useAuthState(auth) // auth user object (used to obtain other user object) + // Authentication Verification / Redirection if Profile Data not Filled out useEffect(() => { if (authUser) { onValue(ref(database, `users/${authUser.uid}`), (userData) => { @@ -36,14 +39,15 @@ function Home() { } }, [authUser]) - const { coords } = - useGeolocated({ - positionOptions: { - enableHighAccuracy: false, - }, - userDecisionTimeout: 5000, - }); + // Gets current location + const { coords } = useGeolocated({ + positionOptions: { + enableHighAccuracy: false, + }, + userDecisionTimeout: 5000, + }); + // If theres a location, go ahead and show location based stuff useEffect(() => { if (coords) { setLoadingLoc(false); @@ -64,15 +68,15 @@ function Home() { {/* Main Page Section */}
{!loadingLoc && ( - + )} {loadingLoc && ( - + )}
{/* Sidebar (Right Side of Page) */} - { if (authUser) { onValue(ref(database, `users/${authUser.uid}`), (userData) => { @@ -36,7 +37,7 @@ function Home() { } }, [authUser]) - + // Users URL params to load proper chatroom, then logs the user into that room useEffect(() => { if (user) { const searchParams = new URLSearchParams(document.location.search); @@ -82,11 +83,11 @@ function Home() { /> {/* Main Page Section */}
- +
{/* Sidebar (Right Side of Page) */} - @@ -95,4 +96,4 @@ function Home() { ); } -export default Home; \ No newline at end of file +export default Chat; \ No newline at end of file diff --git a/frontend-next/src/app/login/page.js b/frontend-next/src/app/login/page.js index 29885e0..567afac 100644 --- a/frontend-next/src/app/login/page.js +++ b/frontend-next/src/app/login/page.js @@ -1,27 +1,27 @@ "use client"; -import { useForm, Form } from "react-hook-form"; -import { useRouter } from "next/navigation"; +// System Imports import "../globals.css"; +import { useForm, Form } from "react-hook-form"; +import Link from "next/link" +import { useRouter } from "next/navigation"; -// Firebase imports +// Firebase Imports import { auth } from "../../../firebase-config"; -import { - setPersistence, - signInWithEmailAndPassword, - indexedDBLocalPersistence, -} from "firebase/auth"; +import {setPersistence,signInWithEmailAndPassword,indexedDBLocalPersistence } from "firebase/auth"; +/** + * Login Page + * @returns {Object} Login Page +*/ function Login() { var router = useRouter(); - //var { register, handleSubmit } = useForm(); - var { - register, - control, - setError, - handleSubmit, - formState: { errors, isSubmitting, isSubmitted }, - } = useForm(); + var {register,control,setError,handleSubmit,formState: { errors, isSubmitting, isSubmitted },} = useForm(); + /** + * Logs into Firebase authentication + * @param {JSON} data - User Login Data (data.email, data.password) + * @returns {void} + */ function authenticate(data) { setPersistence(auth, indexedDBLocalPersistence).then(() => { signInWithEmailAndPassword(auth, data.email, data.password).then( @@ -46,9 +46,9 @@ function Login() {
- + - + Chat with friends!

Login

@@ -109,7 +109,7 @@ function Login() { Log In
- Need an account? Sign Up + Need an account? Sign Up
diff --git a/frontend-next/src/app/onboarding/page.js b/frontend-next/src/app/onboarding/page.js index 0d994cc..9ab96fa 100644 --- a/frontend-next/src/app/onboarding/page.js +++ b/frontend-next/src/app/onboarding/page.js @@ -1,11 +1,19 @@ "use client"; +// System Imports import "../globals.css"; import { useForm } from "react-hook-form"; import { useRouter } from "next/navigation"; + +// Firebase Imports import { ref, set } from "firebase/database"; import { auth, database } from "../../../firebase-config"; import { onAuthStateChanged } from "firebase/auth"; +/** + * Creates user data in Firebase DB + * @param {JSON} data - User data to be stored in Firebase DB ( from form ) + * @return {Boolean} - True if user data is stored, False if user data is not stored + */ function createUser(data) { onAuthStateChanged(auth, (user) => { if (user.uid) { @@ -20,6 +28,10 @@ function createUser(data) { }); } +/** + * Onboarding Page + * @returns {Object} - Onboarding Page + */ function Onboarding() { var router = useRouter(); var { register, handleSubmit } = useForm(); diff --git a/frontend-next/src/app/page.js b/frontend-next/src/app/page.js index dee3a1c..cf91df4 100644 --- a/frontend-next/src/app/page.js +++ b/frontend-next/src/app/page.js @@ -1,14 +1,19 @@ "use client"; import { useState, useEffect } from "react"; - +import Link from "next/link" import { auth, database } from "../../firebase-config"; import { ref, get } from "firebase/database"; +import { useGeolocated } from "react-geolocated"; import { onAuthStateChanged } from "firebase/auth"; +/** + * Home Page + * @returns {Object} - Home Page + */ function Home() { - const [isLoadingLoc, setLoadingLoc] = useState(true); - const [roomCount, setRoomCount] = useState(null); - const [isAuthenticated, setAuth] = useState(false); + const [isLoadingLoc, setLoadingLoc] = useState(true); // is location loading? + const [roomCount, setRoomCount] = useState(null); // local room count + const [isAuthenticated, setAuth] = useState(false); // is user authenticated? // Authentication useEffect(() => { @@ -21,29 +26,36 @@ function Home() { }); }, []); + // Grab Location + const { coords } = useGeolocated({ + positionOptions: { + enableHighAccuracy: false, + }, + userDecisionTimeout: 5000, + }); + + // Update room count on location fix useEffect(() => { - if ("geolocation" in navigator) { - // Retrieve latitude & longitude coordinates from `navigator.geolocation` Web API - navigator.geolocation.getCurrentPosition(({ coords }) => { - var path = - String(coords.latitude.toFixed(2)).replace(".", "") + - "/" + - String(coords.longitude.toFixed(2)).replace(".", ""); - get(ref(database, `/rooms/${path}`)).then((snapshot) => { - if (snapshot.exists()) { - var count = 0; - for (var room in snapshot.val()) { - count += 1; - } - setRoomCount(count); - } else { - setRoomCount(0); + if (coords) { + var path = + String(coords.latitude.toFixed(2)).replace(".", "") + + "/" + + String(coords.longitude.toFixed(2)).replace(".", ""); + get(ref(database, `/rooms/${path}`)).then((snapshot) => { + if (snapshot.exists()) { + var count = 0; + for (var room in snapshot.val()) { + count += 1; } - setLoadingLoc(false); - }); + setRoomCount(count); + } else { + setRoomCount(0); + } + setLoadingLoc(false); }); } - }); + }, [coords]) + return (
@@ -53,24 +65,24 @@ function Home() {
{!isAuthenticated && ( )} {isAuthenticated && ( - - - + + + )} {!isLoadingLoc && roomCount == 1 && (
diff --git a/frontend-next/src/app/register/page.js b/frontend-next/src/app/register/page.js index 6aba36d..aa8ec4e 100644 --- a/frontend-next/src/app/register/page.js +++ b/frontend-next/src/app/register/page.js @@ -1,17 +1,21 @@ "use client"; -import { useRouter } from "next/navigation"; -import { useForm, Form } from "react-hook-form"; +// System Imports import "../globals.css"; import { useState } from "react"; +import { useRouter } from "next/navigation"; +import { useForm, Form } from "react-hook-form"; +import Link from "next/link" -import { - createUserWithEmailAndPassword, - signInWithEmailAndPassword, - setPersistence, - indexedDBLocalPersistence, -} from "firebase/auth"; +// Firebase Imports +import {createUserWithEmailAndPassword,signInWithEmailAndPassword,setPersistence,indexedDBLocalPersistence,} from "firebase/auth"; import { auth } from "../../../firebase-config"; +/** + * Signs up user in Firebase Authentication + * @param {JSON} data - User signup data (data.email, data.password) + * @returns {Boolean} - True if user is signed up, False if user is not signed up + * @async + */ async function Signup(data) { var userCredential = await createUserWithEmailAndPassword( auth, @@ -21,7 +25,7 @@ async function Signup(data) { if (userCredential.user) { setPersistence(auth, indexedDBLocalPersistence).then(() => { signInWithEmailAndPassword(auth, data.email, data.password).then( - (res) => { + () => { return true; } ); @@ -30,7 +34,10 @@ async function Signup(data) { return false; } } - +/** + * Register Page + * @returns {Object} - Registration Page + */ function Register() { var router = useRouter(); var { @@ -45,6 +52,10 @@ function Register() { return data.password === data.passwordCheck; }; + /** + * Form onSubmit Handler + * @params {JSON} data - Form data + */ function onSubmit({ data }) { if (passwordMatch(data)) { setPasswordMismatch(false); @@ -61,9 +72,9 @@ function Register() {
- + - + Chat with friends!

Register

@@ -110,7 +121,7 @@ function Register() { Register
- Have an account? Log In + Have an account? Login
diff --git a/frontend-next/src/app/user/[stub]/page.js b/frontend-next/src/app/user/[stub]/page.js index 17bc135..b7f0d46 100644 --- a/frontend-next/src/app/user/[stub]/page.js +++ b/frontend-next/src/app/user/[stub]/page.js @@ -15,13 +15,15 @@ import { Interest } from "../../../components/app/profile/Interest"; // Header Import import { Header } from "../../../components/app/header"; -// User Profile Page +/** + * User Profile Page + * @param {URLSearchParams} params - URL Parameters + * @returns {Object} - User Profile Page + */ function UserProfile({ params }) { - // It's time to document and change these awful variable names - // State variables for app page - const [profileData, setProfileData] = useState(null); - const [isAuthenticated, setIsAuthenticated] = useState(false); - const [user, setUser] = useState(null); + const [profileData, setProfileData] = useState(null); // Profile Data + const [isAuthenticated, setIsAuthenticated] = useState(false); // Determines if user is authenticated + const [user, setUser] = useState(null); // User Data const [userInterestArray, setUserInterestArray] = useState(null); // Array of user's interests const [userRoomsArray, setUserRoomsArray] = useState(null); // Array of user's rooms const [isOwner, setIsOwner] = useState(false); // Determines if user is owner of profile @@ -120,12 +122,12 @@ function UserProfile({ params }) { }} className="w-[120px] p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full text-center" > - Edit Profile{" "} + Edit Profile )} {!isOwner && ( - Add Friend{" "} + Add Friend )}
diff --git a/frontend-next/src/components/app/datatypes.js b/frontend-next/src/components/app/datatypes.js index ab5469d..93f2afe 100644 --- a/frontend-next/src/components/app/datatypes.js +++ b/frontend-next/src/components/app/datatypes.js @@ -1,3 +1,5 @@ +import Link from "next/link" + // Colors for Messages const userColors = [ "#ff80ed", @@ -24,6 +26,11 @@ let dateOptions = { minute: "2-digit", }; +/** + * Generates Color based on string hash + * @param {String} user_str - Username / String for hashing + * @returns {String} - Color Hex Code Index in userColors + */ const generateColor = (user_str) => { // hashes username for consistent colors, maybe all functionality to pick color later let hash = 0; @@ -34,19 +41,22 @@ const generateColor = (user_str) => { return index; }; -// Chat Message + +/** + * Chat Message Object + * @props {JSON} chatObj - Chat Object + * @returns {Object} - Chat Message Component + */ export function Chat({ chatObj }) { return (
- + {chatObj.user} - + : {chatObj.body}
@@ -57,29 +67,22 @@ export function Chat({ chatObj }) { ); } -// System Chat Message -export function SystemMessage({ chatObj }) { - const generateColor = (user_str) => { - // hashes username for consistent colors, maybe all functionality to pick color later - let hash = 0; - for (let i = 0; i < user_str.length; i++) { - hash = user_str.charCodeAt(i) + (hash * 32 - hash); - } - const index = Math.abs(hash) % userColors.length; - return index; - }; +/** + * System Chat Message Object + * @prop {JSON} chatObj - Chat Object + * @returns {Object} - System Chat Message Component + */ +export function SystemMessage({ chatObj }) { return (
- + {chatObj.user} - + {" "} has {chatObj.body} the room.
@@ -90,31 +93,38 @@ export function SystemMessage({ chatObj }) { ); } -// Member for Active/Room members in sidebar +/** + * Member Object for Sidebar + * @prop {JSON} memberObj - Member Object + * @returns {Object} - Member Component + */ export function Member({ memberObj }) { return ( - +
{memberObj.username}
-
+ ); } -// Chat Room Object for myRooms and Nearby in sidebar +/** + * Chat Room Object for Sidebar + * @prop {JSON} roomObj - Room Object + * @returns {Object} - Chat Room Component + */ export function ChatRoomSidebar({ roomObj }) { return ( -
location.href = "/chat?room=" + roomObj.path + "/" + roomObj.name + "-" + roomObj.timestamp} - className="border-[black] border-1 shadow-lg p-2 m-2 rounded-lg cursor-pointer" - > -
-
{roomObj.name}
-
{roomObj.description}
-
+
+ +
+
{roomObj.name}
+
{roomObj.description}
+
+
); } // This will be removed once dateOptions is no longer used in this file -export { dateOptions }; +export { dateOptions }; \ No newline at end of file diff --git a/frontend-next/src/components/app/header.js b/frontend-next/src/components/app/header.js index f6605f7..29dc01b 100644 --- a/frontend-next/src/components/app/header.js +++ b/frontend-next/src/components/app/header.js @@ -1,14 +1,20 @@ -import { auth, database } from "../../../firebase-config"; +// System Imports +import Link from "next/link" + +// Firebase Imports +import { database } from "../../../firebase-config"; import { ref, set, remove } from "firebase/database"; -import { signOut } from "firebase/auth"; -import { Popover } from "@headlessui/react"; +// Component Imports +import { NotificationPanel } from "./notifications/notifications"; +import { ProfilePanel } from "./profile/ProfilePanel" -function logout() { - signOut(auth); -} - -// Closes chat room +/** + * Closes Open Chat Room + * @param {JSON} roomObj - Room Object + * @param {JSON} user - User Object + * @returns {void} + */ function closeChatRoom(roomObj, user) { var path = roomObj.path + "/" + roomObj.name + "-" + roomObj.timestamp; var payload = { @@ -26,10 +32,14 @@ function closeChatRoom(roomObj, user) { payload ); remove(ref(database, `/rooms/${path}/users/online/${user.uid}`)); - location.href = "/app"; } -// Adds room to myRooms +/** + * Adds Chat Room to My Rooms + * @param {JSON} chatRoomObj - Chat Room Object + * @param {JSON} user - User Object + * @returns {void} + */ function addToMyRooms(chatRoomObj, user) { set( ref( @@ -50,7 +60,12 @@ function addToMyRooms(chatRoomObj, user) { set(ref(database, `/rooms/${path}/users/all/${user.uid}`), user); } -// Deletes saved room from myRooms +/** + * Removes Chat Room from My Rooms + * @param {JSON} chatRoomObj - Chat Room Object + * @param {JSON} user - User Object + * @returns {void} + */ function removeFromMyRooms(chatRoomObj, user) { var path = chatRoomObj.path + "/" + chatRoomObj.name + "-" + chatRoomObj.timestamp; @@ -63,12 +78,14 @@ function removeFromMyRooms(chatRoomObj, user) { remove(ref(database, `/rooms/${path}/users/all/${user.uid}`)); } -export function Header({ - mainTab, - chatRoomObj, - user, -}) { - +/** + * Header Component + * @prop {String} mainTab - Main Tab + * @prop {JSON} chatRoomObj - Chat Room Object + * @prop {JSON} user - User Object + */ +export function Header({mainTab,chatRoomObj,user,}) { + if (mainTab == "chat") { var roomName = chatRoomObj.name + "-" + chatRoomObj.timestamp; if (user.rooms != null && roomName in user.rooms) { @@ -83,9 +100,9 @@ export function Header({ return (
- + - +
{mainTab == "chat" && isMyRoom == false && ( @@ -111,50 +128,22 @@ export function Header({ )} {mainTab == "chat" && ( - { closeChatRoom(chatRoomObj, user); }} + href="/app" className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center" > Close Chat - + )} - - -
-
{user.firstName}
-
- -
-
-
+ {/* Notifications Panel */} + - - - - - -
+ {/*Profile Dropdown */} +
); diff --git a/frontend-next/src/components/app/map/geo.js b/frontend-next/src/components/app/map/geo.js index 5e621ee..f5e3182 100644 --- a/frontend-next/src/components/app/map/geo.js +++ b/frontend-next/src/components/app/map/geo.js @@ -1,8 +1,14 @@ import { Map, Marker, ZoomControl } from "pigeon-maps"; -// Map module for main page and chat room sidebar (and eventually user profile) -// Constructs Map and Markers -// TODO: Need to get rest of marker handling here or in marker file. +/** + * Geo Component for Wrapping Map + * @constructor + * @prop {JSON} loc - Location Object {latitude, longitude} + * @prop {Number} zoom - Zoom Level + * @prop {Boolean} locMarker - Show Location Marker + * @prop {Markers[]} markers - Array of Markers + * @returns {Map} - Geo Component (As Map) + */ export function Geo({ loc, zoom, locMarker, markers }) { if (loc) { return ( diff --git a/frontend-next/src/components/app/notifications/notifications.js b/frontend-next/src/components/app/notifications/notifications.js index e69de29..08bfcaf 100644 --- a/frontend-next/src/components/app/notifications/notifications.js +++ b/frontend-next/src/components/app/notifications/notifications.js @@ -0,0 +1,101 @@ +// System Imports +import { Popover } from "@headlessui/react"; + +// Icon Imports +import NotificationsIcon from '@mui/icons-material/Notifications'; +import NotificationsPausedIcon from '@mui/icons-material/NotificationsPaused'; +import CloseIcon from '@mui/icons-material/Close'; + +// Firebase Imports +import { database } from "../../../../firebase-config"; +import { ref, set, remove } from "firebase/database"; + +/** + * Notification Object + * @constructor + * @prop {user.notification} data - Notification data + * @returns {Notification} - Notification Component + */ +function Notification({data}) { + return ( +
+
+
{removeNotification(data.id)}}>
+
+
+ {data.title}
+ {data.byline}
+
+
+ ) +} + +/** + * Removes Notification + * @param {String} ruser - Receiving user UID (User Whose Notifications are being removed) + * @param {String} dataID - Notification ID + * @returns {void} + */ +function removeNotification(ruser, dataID) { + remove(ref(database, `/user/${ruser}/notifications/${dataID}`)) +} + +/** +* Creates New Notification +* @param {String} title - Title of the notification +* @param {String} byline - Byline of the notification +* @param {String} action - Action to perform (friend request [fr], more to come) +* @param {String} suser - Sending user UID +* @param {String} ruser - Receiving user UID +* @returns {void} +*/ +function createNotification(title, byline, action, suser, ruser) { + var timestamp = new Date().getTime(); + var payload = { + title: title, + byline: byline, + action: action, + suser: suser, + ruser: ruser + }; + set(ref(database, `/user/${ruser}/notifications/${timestamp}-${suser}`), payload); +} + +/** + * Notification Panel + * @constructor + * @prop {user} user - User object (from Firebase) + * @returns {NotificationPanel} - Notification Panel Component + */ +export function NotificationPanel({user}) { + var notificationsMap = [] + if (user.notification) { + for (var notificationPackage in user.notification) { + notificationsMap.push() + } + var isNotifications = true + } else { + var isNotifications = false + } + + return ( + + +
+ +
+
+ + +
+ {isNotifications && notificationsMap} + {!isNotifications && +
+ All caught up! +
+ } +
+
+
+ ) +} \ No newline at end of file diff --git a/frontend-next/src/components/app/main_tab/chat.js b/frontend-next/src/components/app/page/chat.js similarity index 83% rename from frontend-next/src/components/app/main_tab/chat.js rename to frontend-next/src/components/app/page/chat.js index 28d6cae..63b8442 100644 --- a/frontend-next/src/components/app/main_tab/chat.js +++ b/frontend-next/src/components/app/page/chat.js @@ -1,11 +1,20 @@ -import { Chat, SystemMessage } from "../datatypes"; -import { useState } from "react"; +// Dependency Imports import { Form, useForm } from "react-hook-form"; + +// Firebase Imports import { ref, set } from "firebase/database"; import { database } from "../../../../firebase-config"; -// Chatroom Module for Primary Tab -export function MainTabChatRoom({ roomObj, user }) { +// Component Imports +import { Chat, SystemMessage } from "../datatypes"; + +/** + * Chat Room Component + * @prop {JSON} roomObj - Room Object + * @prop {JSON} user - User Object + * @returns {Object} - Chat Room Component + */ +export function ChatRoom({ roomObj, user }) { var { register, control, reset, handleSubmit } = useForm(); // Message updater @@ -30,6 +39,11 @@ export function MainTabChatRoom({ roomObj, user }) { } var chats = chatsArr.reverse(); + /** + * Send Message in Chatroom + * @param {JSON} data - Message data to send (from form) + * @returns {void} + */ function sendMessage(data) { reset(); var payload = { diff --git a/frontend-next/src/components/app/main_tab/home.js b/frontend-next/src/components/app/page/home.js similarity index 55% rename from frontend-next/src/components/app/main_tab/home.js rename to frontend-next/src/components/app/page/home.js index ce93d35..1fbf3fa 100644 --- a/frontend-next/src/components/app/main_tab/home.js +++ b/frontend-next/src/components/app/page/home.js @@ -1,7 +1,11 @@ import { Geo } from "../map/geo"; -// Module for Welcome Message on main tab landing page -function WelcomeMessage({ user }) { +/** + * Module for Welcome Message on main tab landing page + * @prop {JSON} user - User Object + * @returns {Object} - Welcome Message Component + */ + function WelcomeMessage({ user }) { return (
@@ -12,8 +16,14 @@ function WelcomeMessage({ user }) { ); } -// Primary App Landing Page -export function MainTabHome({ loc, markers, user }) { +/** + * Primary App Landing Page + * @prop {JSON} loc - Location Object {latitude, longitude} + * @prop {Markers[]} markers - Array of Markers + * @prop {JSON} user - User Object + * @returns {Object} - Home Page Component + */ +export function HomePage({ loc, markers, user }) { return ( <> diff --git a/frontend-next/src/components/app/profile/Interest.js b/frontend-next/src/components/app/profile/Interest.js index ef5c28d..f2c9cb3 100644 --- a/frontend-next/src/components/app/profile/Interest.js +++ b/frontend-next/src/components/app/profile/Interest.js @@ -1,5 +1,8 @@ -// Interests for Profile -// Making this its own file since we could do a bit more with this in the future +/** + * Interest for Profile + * @prop {String} interest - Interest item + * @returns {Object} - Interest Component + */ export function Interest({ interest }) { return (
diff --git a/frontend-next/src/components/app/profile/ProfileEdit.js b/frontend-next/src/components/app/profile/ProfileEdit.js index 5efe0bd..5845302 100644 --- a/frontend-next/src/components/app/profile/ProfileEdit.js +++ b/frontend-next/src/components/app/profile/ProfileEdit.js @@ -1,9 +1,19 @@ +// System Imports import { useForm, Form } from "react-hook-form"; -import { database, storage } from "../../../../firebase-config"; -import { ref as sRef, getDownloadURL } from "firebase/storage"; -import { ref, update } from "firebase/database"; -import { uploadBytes } from "firebase/storage"; +// Firebase Imports +import { database, storage } from "../../../../firebase-config"; +import { ref as sRef, getDownloadURL,uploadBytes } from "firebase/storage"; +import { ref, update } from "firebase/database"; + + +/** + * Profile Edit Component + * @prop {JSON} profileData - Profile Data + * @prop {JSON} user - User Object + * @prop {Function} onSave - Save Function + * @returns {Object} - Profile Edit Component + */ export function ProfileEdit({ profileData, user, onSave }) { var { register, control } = useForm(); @@ -11,9 +21,11 @@ export function ProfileEdit({ profileData, user, onSave }) { onSave(false); }; - // Handles clicking save button + /** + * Handles clicking save button + * @prop {JSON} data - Data to save + */ function save({ data }) { - // Profile pic handling if (data.pfp[0]) { // image stuff diff --git a/frontend-next/src/components/app/profile/ProfilePanel.js b/frontend-next/src/components/app/profile/ProfilePanel.js new file mode 100644 index 0000000..4df9d11 --- /dev/null +++ b/frontend-next/src/components/app/profile/ProfilePanel.js @@ -0,0 +1,57 @@ +// System Imports +import { Popover } from "@headlessui/react"; +import Link from "next/link" + +// Firebase Imports +import { auth } from "../../../../firebase-config"; +import { signOut } from "firebase/auth"; + +/** + * Logs out from Firebase Authentication + * @returns {void} + */ +function logout() { + signOut(auth); +} + +/** + * Profile Panel Component + * @prop {JSON} user - User Object + * @returns {Object} - Profile Panel Component + */ +export function ProfilePanel({user}) { + return ( + + +
+
{user.firstName}
+
+ +
+
+
+ + +
+ + View Profile + + + Sign Out + +
+
+
+ ) +} \ No newline at end of file diff --git a/frontend-next/src/components/app/profile/ProfileRoom.js b/frontend-next/src/components/app/profile/ProfileRoom.js index 80e6268..796978f 100644 --- a/frontend-next/src/components/app/profile/ProfileRoom.js +++ b/frontend-next/src/components/app/profile/ProfileRoom.js @@ -1,7 +1,15 @@ +// System Imports import { Geo } from "../map/geo"; +import Link from "next/link" + +// Component Imports import { dateOptions } from "../datatypes"; -// Display of Rooms on user profile +/** + * Profile Room Component + * @prop {JSON} room - Room Object + * @returns {Object} - Profile Room Component + */ export function ProfileRoom({ room }) { return (
@@ -18,14 +26,14 @@ export function ProfileRoom({ room }) {
Created on {new Date(room.timestamp).toLocaleString(dateOptions)}
- Open Room - +
); diff --git a/frontend-next/src/components/app/sidebar/chat.js b/frontend-next/src/components/app/sidebar/chat.js index bb3f25d..a32d24a 100644 --- a/frontend-next/src/components/app/sidebar/chat.js +++ b/frontend-next/src/components/app/sidebar/chat.js @@ -1,11 +1,14 @@ +// Component Imports import { Geo } from "../map/geo"; - import { Member } from "../datatypes" // Sidebar when in a Chatrooms -export function Chat_Sidebar({ - chatRoomObj, -}) { +/** + * Sidebar while in Chatroom + * @prop {JSON} chatRoomObj - Chatroom Object + * @returns {Object} - Sidebar Component + */ +export function Sidebar({chatRoomObj}) { // Active users list if ( chatRoomObj.hasOwnProperty("users") && diff --git a/frontend-next/src/components/app/sidebar/home.js b/frontend-next/src/components/app/sidebar/home.js index dbfce0b..2bd9180 100644 --- a/frontend-next/src/components/app/sidebar/home.js +++ b/frontend-next/src/components/app/sidebar/home.js @@ -1,15 +1,31 @@ +// System Imports import { Form, useForm } from "react-hook-form"; -import { database } from "../../../../firebase-config"; -import { ref, set, get } from "firebase/database"; import { useEffect, useState } from "react"; -import { ChatRoomSidebar } from "../datatypes"; -// Sidebar on Home Page, with various functionality (create, nearby, my rooms) +// Dependency Imports +import { Tab } from '@headlessui/react' -// CreateRoom Module for Sidebar Create Tab +// Firebase Imports +import { database } from "../../../../firebase-config"; +import { ref, set, get } from "firebase/database"; + +// Component Imports +import { ChatRoomSidebar } from "../datatypes"; + + +/** + * Create Room Component for /app Sidebar + * @prop {JSON} loc - Location Object (latitude, longitude) + * @returns {Object} - Create Room Component + */ function CreateRoom({ loc }) { var { register, control, reset, handleSubmit } = useForm(); + /** + * Creates Room in Firebase DB + * @prop {JSON} data - Room Data + * @returns {void} + */ function createRoom(data) { reset(); var path = @@ -50,12 +66,24 @@ function CreateRoom({ loc }) { ); } -export function Home_Sidebar({ - user, - location, - loadingLoc -}) { - const [tab, setTab] = useState("rooms"); +/** + * Joins class names together for Tailwind CSS + * @param {...String} classes - Class names + * @returns {String} - Class names (joined) + */ +function classNames(...classes) { + return classes.filter(Boolean).join(' ') +} + +/** + * App Page Sidebar Component + * @prop {JSON} user - User Object + * @prop {JSON} location - Location Object (latitude, longitude) + * @prop {Boolean} loadingLoc - Loading Location State + * @returns {Object} - App Page Sidebar Component + */ +export function Sidebar({user,location,loadingLoc}) { + const [tab, setTab] = useState("nearby"); const [nearbyArr, setNearbyArr] = useState([]) const [nearbyArrReady, setNearbyArrReady] = useState(false) @@ -98,71 +126,60 @@ export function Home_Sidebar({ return (
-
-
-
{ - setTab("nearby"); - }} - > - Nearby -
-
{ - setTab("rooms"); - }} - > - My Rooms -
-
{ - setTab("create"); - }} - > - Create -
-
-
- {tab == "nearby" && ( -
-
- {!nearbyArr && !loadingLoc && ( + + + + classNames( + 'w-[31%]', + selected + ? 'bg-cyan-500 text-white font-bold shadow hover:bg-white/[0.6] hover:text-black' + : 'hover:bg-cyan-500/[0.6] hover:text-white hover:font-bold' + )} defaultIndex={1}>Nearby + + classNames( + 'w-[31%]', + selected + ? 'bg-cyan-500 text-white font-bold shadow hover:bg-white/[0.6] hover:text-black' + : 'hover:bg-cyan-500/[0.6] hover:text-white hover:font-bold' + )}>My Rooms + + classNames( + 'w-[31%]', + selected + ? 'bg-cyan-500 text-white font-bold shadow hover:bg-white/[0.6] hover:text-black' + : 'hover:bg-cyan-500/[0.6] hover:text-white hover:font-bold' + )}>Create + + + +
- No Nearby Rooms -
- Create One? + {!nearbyArr && !loadingLoc && ( +
+ No Nearby Rooms +
+ Create One? +
+ )} + {loadingLoc &&
Loading...
} + {nearbyArrReady && nearbyArr}
- )} +
+
+ +
+
+ {!myRoomArr &&
No User Saved Rooms
} + {myRoomArr} +
+
+
+ + {!loadingLoc && } {loadingLoc &&
Loading...
} - {nearbyArrReady && nearbyArr} -
-
- )} - {tab == "rooms" && ( -
-
- {!myRoomArr &&
No User Saved Rooms
} - {myRoomArr} -
-
- )} - {tab == "create" && !loadingLoc && } - {tab == "create" && loadingLoc &&
Loading...
} + + +
);