diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1286ad9..d8f4ac2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,7 +13,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v2 with: - node-version: '16' + node-version: "16" - name: Install dependencies run: npm install @@ -21,4 +21,4 @@ jobs: - name: Run Prettier run: npm run format - working-directory: ./api \ No newline at end of file + working-directory: ./api diff --git a/README.md b/README.md index ad2b7a2..12c6e52 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# PennsylvaniaWomenWork \ No newline at end of file +# PennsylvaniaWomenWork diff --git a/api/package-lock.json b/api/package-lock.json index a3dc1d6..b1ed01f 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -10,13 +10,11 @@ "license": "ISC", "dependencies": { "@sendgrid/mail": "^8.1.4", - "axios": "^1.7.7", "cors": "^2.8.5", "dotenv": "^16.4.5", - "express": "^4.21.1", + "express": "^4.21.0", "mongodb": "^6.9.0", "mongoose": "^8.4.1", - "nodemon": "^3.1.7", "ts-node-dev": "^2.0.0", "uuid": "^10.0.0" }, @@ -316,21 +314,6 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -453,17 +436,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -550,14 +522,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -716,38 +680,6 @@ "node": ">= 0.8" } }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -850,14 +782,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -928,11 +852,6 @@ "node": ">=0.10.0" } }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1288,54 +1207,6 @@ "node": ">= 0.6" } }, - "node_modules/nodemon": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz", - "integrity": "sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==", - "dependencies": { - "chokidar": "^3.5.2", - "debug": "^4", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^7.5.3", - "simple-update-notifier": "^2.0.0", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/nodemon/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -1447,16 +1318,6 @@ "node": ">= 0.10" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -1564,17 +1425,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/send": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", @@ -1668,17 +1518,6 @@ "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" }, - "node_modules/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -1728,17 +1567,6 @@ "node": ">=0.10.0" } }, - "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/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -1769,14 +1597,6 @@ "node": ">=0.6" } }, - "node_modules/touch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", - "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, "node_modules/tr46": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", @@ -1906,11 +1726,6 @@ "node": ">=14.17" } }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" - }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", @@ -2256,21 +2071,6 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "requires": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2359,14 +2159,6 @@ "readdirp": "~3.6.0" } }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2432,11 +2224,6 @@ "gopd": "^1.0.1" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -2558,21 +2345,6 @@ "unpipe": "~1.0.0" } }, - "follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==" - }, - "form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2640,11 +2412,6 @@ "get-intrinsic": "^1.1.3" } }, - "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==" - }, "has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -2691,11 +2458,6 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2903,38 +2665,6 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, - "nodemon": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz", - "integrity": "sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==", - "requires": { - "chokidar": "^3.5.2", - "debug": "^4", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^7.5.3", - "simple-update-notifier": "^2.0.0", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "dependencies": { - "debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "requires": { - "ms": "^2.1.3" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3006,16 +2736,6 @@ "ipaddr.js": "1.9.1" } }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" - }, "punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3081,11 +2801,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" - }, "send": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", @@ -3163,14 +2878,6 @@ "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" }, - "simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "requires": { - "semver": "^7.5.3" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -3208,14 +2915,6 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==" }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -3234,11 +2933,6 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, - "touch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", - "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==" - }, "tr46": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", @@ -3314,11 +3008,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==" }, - "undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" - }, "undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", diff --git a/api/package.json b/api/package.json index 850c9b6..de25796 100644 --- a/api/package.json +++ b/api/package.json @@ -9,20 +9,18 @@ "dev": "nodemon ./src/server.ts", "test": "echo \"Error: no test specified\" && exit 1", "prettier": "prettier --single-quote --write 'src/**/*.{js,ts}'", - "format": "prettier --check" + "format": "prettier --check ." }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "@sendgrid/mail": "^8.1.4", - "axios": "^1.7.7", "cors": "^2.8.5", "dotenv": "^16.4.5", - "express": "^4.21.1", + "express": "^4.21.0", "mongodb": "^6.9.0", "mongoose": "^8.4.1", - "nodemon": "^3.1.7", "ts-node-dev": "^2.0.0", "uuid": "^10.0.0" }, diff --git a/api/src/config/db.ts b/api/src/config/db.ts index 6c21f0e..553460f 100644 --- a/api/src/config/db.ts +++ b/api/src/config/db.ts @@ -1,18 +1,17 @@ -import mongoose from 'mongoose' -import dotenv from 'dotenv' -import path from 'path' +import mongoose from "mongoose"; +import dotenv from "dotenv"; +import path from "path"; -dotenv.config({ path: path.resolve(__dirname, '../../.env') }); +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); // Connect to MongoDB const dbConnect = async () => { - try { - await mongoose.connect(process.env.MONGO_URI as string, { - }) - console.log("Connected to MongoDB") - } catch (error) { - console.error(error) - } -} + try { + await mongoose.connect(process.env.MONGO_URI as string, {}); + console.log("Connected to MongoDB"); + } catch (error) { + console.error(error); + } +}; -export default dbConnect \ No newline at end of file +export default dbConnect; diff --git a/api/src/controllers/workshopController.ts b/api/src/controllers/workshopController.ts index 248c831..8fd36c4 100644 --- a/api/src/controllers/workshopController.ts +++ b/api/src/controllers/workshopController.ts @@ -1,39 +1,39 @@ // NO POPULATE VERSION -import { Request, Response } from 'express'; -import { Workshop } from '../model/Workshop'; +import { Request, Response } from "express"; +import { Workshop } from "../model/Workshop"; export const createWorkshop = async (req: Request, res: Response) => { - try { - const { mentorId, menteeId, textContent } = req.body; - - const newWorkshop = new Workshop({ - mentor: mentorId, - mentee: menteeId, - textContent, - }); - - const savedWorkshop = await newWorkshop.save(); - res.status(201).json(savedWorkshop); - } catch (error) { - res.status(500).json({ message: 'Error creating workshop', error }); - } + try { + const { mentorId, menteeId, textContent } = req.body; + + const newWorkshop = new Workshop({ + mentor: mentorId, + mentee: menteeId, + textContent, + }); + + const savedWorkshop = await newWorkshop.save(); + res.status(201).json(savedWorkshop); + } catch (error) { + res.status(500).json({ message: "Error creating workshop", error }); + } }; export const getWorkshop = async (req: Request, res: Response) => { - try { - const { id } = req.params; - - const workshop = await Workshop.findById(id); - - if (!workshop) { - return res.status(404).json({ message: 'Workshop not found' }); - } - - res.status(200).json(workshop); - } catch (error) { - res.status(500).json({ message: 'Error retrieving workshop', error }); + try { + const { id } = req.params; + + const workshop = await Workshop.findById(id); + + if (!workshop) { + return res.status(404).json({ message: "Workshop not found" }); } + + res.status(200).json(workshop); + } catch (error) { + res.status(500).json({ message: "Error retrieving workshop", error }); + } }; // POPULATE VERSION (if details of mentor/mentee objects are needed on the frontend like name or picture) @@ -44,13 +44,13 @@ export const getWorkshop = async (req: Request, res: Response) => { // export const createWorkshop = async (req: Request, res: Response) => { // try { // const { mentorId, menteeId, textContent } = req.body; - + // const newWorkshop = new Workshop({ // mentor: mentorId, // mentee: menteeId, // textContent, // }); - + // const savedWorkshop = await newWorkshop.save(); // res.status(201).json(savedWorkshop); // } catch (error) { @@ -61,15 +61,15 @@ export const getWorkshop = async (req: Request, res: Response) => { // export const getWorkshop = async (req: Request, res: Response) => { // try { // const { id } = req.params; - + // const workshop = await Workshop.findById(id) // .populate('mentor') // Populate full user details for mentor // .populate('mentee'); // Populate full user details for mentee - + // if (!workshop) { // return res.status(404).json({ message: 'Workshop not found' }); // } - + // res.status(200).json(workshop); // } catch (error) { // res.status(500).json({ message: 'Error retrieving workshop', error }); diff --git a/api/src/model/Workshop.ts b/api/src/model/Workshop.ts index 54a188b..a425719 100644 --- a/api/src/model/Workshop.ts +++ b/api/src/model/Workshop.ts @@ -1,12 +1,12 @@ -import mongoose, { Schema, Document } from "mongoose" +import mongoose, { Schema, Document } from "mongoose"; // interface interface IWorkshop extends Document { - mentor: Schema.Types.ObjectId // TODO: add mentor type - mentee: Schema.Types.ObjectId // TODO: add mentee type - textContent: string - createdAt: Date + mentor: Schema.Types.ObjectId; // TODO: add mentor type + mentee: Schema.Types.ObjectId; // TODO: add mentee type + textContent: string; + createdAt: Date; - updateContent(newContent: string): Promise + updateContent(newContent: string): Promise; } // workshop schema @@ -15,16 +15,16 @@ const WorkshopSchema: Schema = new Schema({ mentee: { type: Schema.Types.ObjectId, ref: "User", required: true }, textContent: { type: String, required: true }, createdAt: { type: Date, default: Date.now }, -}) +}); // update text content of the workshop WorkshopSchema.methods.updateContent = async function ( - newContent: string + newContent: string, ): Promise { - this.textContent = newContent - await this.save() -} + this.textContent = newContent; + await this.save(); +}; // mongoose model -const Workshop = mongoose.model("Workshop", WorkshopSchema) -export { Workshop, IWorkshop } +const Workshop = mongoose.model("Workshop", WorkshopSchema); +export { Workshop, IWorkshop }; diff --git a/api/src/routes/index.ts b/api/src/routes/index.ts index 8520ab4..4bf9a11 100644 --- a/api/src/routes/index.ts +++ b/api/src/routes/index.ts @@ -1,13 +1,9 @@ -import user from "./user" -import express from 'express'; -import workshopRoutes from './workshop'; // Import workshop routes +import user from "./user"; +import express from "express"; +import workshop from "./workshop"; // Import workshop routes -export { user } - -const router = express.Router(); -router.use('/workshops', workshopRoutes); // Use workshop routes - -export default router; +// export { workshops } +export { user, workshop }; // import express, { Request, Response, Application } from "express" // import cors from "cors" diff --git a/api/src/routes/user.ts b/api/src/routes/user.ts index 0c938fb..ecfa60e 100644 --- a/api/src/routes/user.ts +++ b/api/src/routes/user.ts @@ -1,17 +1,76 @@ import express from "express"; +import mongoose from "mongoose"; +import dbConnect from "../config/db"; import sgMail from "@sendgrid/mail"; const router = express.Router(); -const axios = require("axios").default; -router.use(express.json()); +// Call the dbConnect function to connect to MongoDB +dbConnect(); +// User schema definition +const userSchema = new mongoose.Schema({ + firstName: String, + lastName: String, + username: String, + email: String, + role: { type: String, enum: ["mentor", "mentee", "admin"], required: true }, + workshopIDs: [String], // For mentors only + menteeInfo: [String], // For mentors only + meetingSchedule: [String], // For mentees only + mentorData: String, // For mentees only +}); + +const User = mongoose.model("User", userSchema); + +// Route to create a new user +router.post("/create-user", async (req: any, res: any) => { + const { + firstName, + lastName, + username, + email, + role, + workshopIDs, + menteeInfo, + meetingSchedule, + mentorData, + } = req.body; + + if (!firstName || !lastName || !username || !email || !role) { + return res.status(400).json({ message: "Missing required fields" }); + } + + // Create a new user based on role + const newUser = new User({ + firstName, + lastName, + username, + email, + role, + workshopIDs: role === "mentor" ? workshopIDs : undefined, + menteeInfo: role === "mentor" ? menteeInfo : undefined, + meetingSchedule: role === "mentee" ? meetingSchedule : undefined, + mentorData: role === "mentee" ? mentorData : undefined, + }); + + try { + const savedUser = await newUser.save(); + res + .status(201) + .json({ message: "User created successfully", user: savedUser }); + } catch (error) { + res.status(400).json({ message: "Failed to create user", error }); + } +}); + +// Test route to check if the API is working router.post("/test", async (req: any, res: any) => { - console.log("Received group data:") - const {name} = req.body; + console.log("Received group data:"); + const { name } = req.body; - return res.status(200).json(name) -}) + return res.status(200).json({ name }); +}); router.post("/send-email", async (req: any, res: any) => { try { diff --git a/api/src/routes/workshop.ts b/api/src/routes/workshop.ts index dbe6f3a..4fa779c 100644 --- a/api/src/routes/workshop.ts +++ b/api/src/routes/workshop.ts @@ -1,17 +1,55 @@ -// NO POPULATE VERSION +import express from "express"; +import mongoose from "mongoose"; +import dbConnect from "../config/db"; // Import the dbConnect function -import express from 'express'; -import { createWorkshop, getWorkshop } from '../controllers/workshopController'; +import { createWorkshop, getWorkshop } from "../controllers/workshopController"; const router = express.Router(); -router.post('/workshops', createWorkshop); -// router.get('/workshops/:id', getWorkshop); -router.get('/workshops/:id', async (req: express.Request, res: express.Response) => { - await getWorkshop(req, res); +// Call the dbConnect function to connect to MongoDB +dbConnect(); + +// Workshop schema definition (name and S3 bucket ID) +const workshopIDSchema = new mongoose.Schema({ + name: String, + s3ID: String, }); -export default router; +const Workshop = mongoose.model("WorkshopID", workshopIDSchema); + +// Route to create a new workshop +router.post("/create-workshop", async (req: any, res: any) => { + const { name, s3id } = req.body; + + if (!name || !s3id) { + return res.status(400).json({ message: "Missing required fields" }); + } + + // Create a new workshop + const newWorkshop = new Workshop({ + name, + s3id, + }); + + try { + const savedWorkshop = await newWorkshop.save(); + res.status(201).json({ + message: "Workshop created successfully", + WorkshopID: savedWorkshop, + }); + } catch (error) { + res.status(401).json({ message: "Failed to create workshop", error }); + } +}); + +// router.post("/workshops", createWorkshop) +// router.get('/workshops/:id', getWorkshop); +router.get( + "/workshops/:id", + async (req: express.Request, res: express.Response) => { + await getWorkshop(req, res); + }, +); // POPULATE VERSION (if details of mentor/mentee objects are needed on the frontend like name or picture) @@ -24,3 +62,6 @@ export default router; // router.get('/workshops/:id', getWorkshop); // export default router; + +export default router; +// NO POPULATE VERSION diff --git a/api/src/server.ts b/api/src/server.ts index 5d3fa12..cd7a639 100644 --- a/api/src/server.ts +++ b/api/src/server.ts @@ -1,9 +1,6 @@ import express from "express"; import bodyParser from "body-parser"; import connectDB from "./config/db"; -import dotenv from "dotenv"; - -dotenv.config(); import * as routes from "./routes/index"; @@ -15,5 +12,8 @@ app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use("/user", routes.user); +app.use("/workshop", routes.workshop); + +connectDB(); app.listen(process.env.PORT || 8000, () => console.log("Server running...")); diff --git a/api/tsconfig.json b/api/tsconfig.json index 6a6679e..66debcc 100644 --- a/api/tsconfig.json +++ b/api/tsconfig.json @@ -13,7 +13,7 @@ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ /* Language and Environment */ - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ @@ -27,7 +27,7 @@ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ + "module": "commonjs" /* Specify what module code is generated. */, // "rootDir": "./", /* Specify the root folder within your source files. */ // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ @@ -79,12 +79,12 @@ // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ + "strict": true /* Enable all strict type-checking options. */, // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ @@ -107,6 +107,8 @@ /* Completeness */ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */, + "moduleResolution": "node", + "typeRoots": ["./node_modules/@types"] } } diff --git a/app/public/index.html b/app/public/index.html index aa069f2..e65acb3 100644 --- a/app/public/index.html +++ b/app/public/index.html @@ -1,4 +1,4 @@ - + diff --git a/app/src/App.test.tsx b/app/src/App.test.tsx index 2a68616..d76787e 100644 --- a/app/src/App.test.tsx +++ b/app/src/App.test.tsx @@ -1,8 +1,8 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; +import React from "react"; +import { render, screen } from "@testing-library/react"; +import App from "./App"; -test('renders learn react link', () => { +test("renders learn react link", () => { render(); const linkElement = screen.getByText(/learn react/i); expect(linkElement).toBeInTheDocument(); diff --git a/app/src/App.tsx b/app/src/App.tsx index 839c179..acc3ce2 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -1,9 +1,9 @@ -import React, { type ReactElement } from "react" -import { BrowserRouter as Router, Routes, Route } from "react-router-dom" -import Home from "./pages/Home" -import MentorDashboard from "./pages/MentorDashboard" -import CreateWorkshop from "./pages/CreateWorkshop" -import CreateMeeting from "./pages/CreateMeeting" +import React, { type ReactElement } from "react"; +import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; +import Home from "./pages/Home"; +import MentorDashboard from "./pages/MentorDashboard"; +import CreateWorkshop from "./pages/CreateWorkshop"; +import CreateMeeting from "./pages/CreateMeeting"; function App(): ReactElement { return (
@@ -17,7 +17,7 @@ function App(): ReactElement {
- ) + ); } -export default App +export default App; diff --git a/app/src/api.ts b/app/src/api.ts index c7ae4b3..b68ffce 100644 --- a/app/src/api.ts +++ b/app/src/api.ts @@ -1,6 +1,6 @@ export const api: any = { get: async (route: string): Promise => { - const url = `${process.env.REACT_APP_API_URL as string}${route}` + const url = `${process.env.REACT_APP_API_URL as string}${route}`; return await fetch(url, { method: "GET", @@ -8,24 +8,24 @@ export const api: any = { }) .then(async (res) => { if (!res.ok) { - throw new Error("Network response was not ok") + throw new Error("Network response was not ok"); } - const json = await res.json() + const json = await res.json(); const response = { data: json, status: res.status, - } + }; - return response + return response; }) .catch((err) => { - console.error("Error fetching data: ", err) - throw err - }) + console.error("Error fetching data: ", err); + throw err; + }); }, post: async (route: string, payload: any): Promise => { - const url = `${process.env.REACT_APP_API_URL as string}${route}` + const url = `${process.env.REACT_APP_API_URL as string}${route}`; return await fetch(url, { method: "POST", @@ -36,22 +36,22 @@ export const api: any = { }) .then(async (res) => { if (!res.ok) { - throw new Error("Network response was not ok") + throw new Error("Network response was not ok"); } - const json = await res.json() + const json = await res.json(); return { data: json, status: res.status, - } + }; }) .catch((err) => { - console.error("Error posting data: ", err) - throw err - }) + console.error("Error posting data: ", err); + throw err; + }); }, put: async (route: string, data: any): Promise => { - const url = `${process.env.REACT_APP_API_URL as string}${route}` + const url = `${process.env.REACT_APP_API_URL as string}${route}`; return await fetch(url, { method: "PUT", @@ -63,21 +63,21 @@ export const api: any = { body: data, }) .then(async (res) => { - const json = await res.json() + const json = await res.json(); const response = { data: json, status: res.status, - } - return response + }; + return response; }) .catch((err) => { - console.error("Error posting data: ", err) - throw err - }) + console.error("Error posting data: ", err); + throw err; + }); }, delete: async (route: string, data: any): Promise => { - const url = `${process.env.REACT_APP_API_URL as string}${route}` + const url = `${process.env.REACT_APP_API_URL as string}${route}`; return await fetch(url, { method: "DELETE", @@ -89,19 +89,19 @@ export const api: any = { }) .then(async (res) => { if (!res.ok) { - throw new Error("Network response was not ok") + throw new Error("Network response was not ok"); } - const json = await res.json() + const json = await res.json(); const response = { data: json, status: res.status, - } + }; - return response + return response; }) .catch((err) => { - console.error("Error deleting data: ", err) - throw err - }) + console.error("Error deleting data: ", err); + throw err; + }); }, -} +}; diff --git a/app/src/components/AsyncSubmit.tsx b/app/src/components/AsyncSubmit.tsx index c968f5e..7414bc7 100644 --- a/app/src/components/AsyncSubmit.tsx +++ b/app/src/components/AsyncSubmit.tsx @@ -1,5 +1,5 @@ -import React, { type ReactElement } from "react" -import { Spinner } from "react-bootstrap" +import React, { type ReactElement } from "react"; +import { Spinner } from "react-bootstrap"; const AsyncSubmit = (props: { loading: boolean }): ReactElement => { return ( @@ -10,7 +10,7 @@ const AsyncSubmit = (props: { loading: boolean }): ReactElement => { )} - ) -} + ); +}; -export default AsyncSubmit +export default AsyncSubmit; diff --git a/app/src/components/Icon.tsx b/app/src/components/Icon.tsx index 4c1c3c8..6d615ec 100644 --- a/app/src/components/Icon.tsx +++ b/app/src/components/Icon.tsx @@ -3,22 +3,22 @@ */ // eslint-disable-next-line @typescript-eslint/consistent-type-imports -import React, { FC } from "react" +import React, { FC } from "react"; interface IconProps { - glyph: string - regular?: boolean - size?: string + glyph: string; + regular?: boolean; + size?: string; } const Icon: FC = ({ glyph, regular = false, size = "" }) => { - const iconClass = `fa${regular ? "r" : "s"} fa-${glyph}` + const iconClass = `fa${regular ? "r" : "s"} fa-${glyph}`; return ( - ) -} + ); +}; -export default Icon +export default Icon; diff --git a/app/src/components/Modal.tsx b/app/src/components/Modal.tsx index 722bcf4..dfd9935 100644 --- a/app/src/components/Modal.tsx +++ b/app/src/components/Modal.tsx @@ -2,15 +2,15 @@ This component is a modal that can be used to display information to the user. */ -import React, { type ReactElement } from "react" -import Icon from "./Icon" +import React, { type ReactElement } from "react"; +import Icon from "./Icon"; interface ModalProps { - header?: string - subheader?: string - body?: ReactElement - large?: boolean - action?: () => void + header?: string; + subheader?: string; + body?: ReactElement; + large?: boolean; + action?: () => void; } const Modal = (props: ModalProps): ReactElement => { @@ -19,7 +19,7 @@ const Modal = (props: ModalProps): ReactElement => {
@@ -36,7 +36,7 @@ const Modal = (props: ModalProps): ReactElement => {
{props.body}
- ) -} + ); +}; -export default Modal +export default Modal; diff --git a/app/src/components/Navbar.tsx b/app/src/components/Navbar.tsx index cc91215..f0f8ef6 100644 --- a/app/src/components/Navbar.tsx +++ b/app/src/components/Navbar.tsx @@ -1,15 +1,15 @@ -import react, { type ReactElement } from "react" -import { useNavigate } from "react-router-dom" +import react, { type ReactElement } from "react"; +import { useNavigate } from "react-router-dom"; const Navbar = (): ReactElement => { - const navigate = useNavigate() + const navigate = useNavigate(); return ( <>
{ - navigate("/home") + navigate("/home"); }} className="Navbar-body-logo" >
@@ -17,7 +17,7 @@ const Navbar = (): ReactElement => {
{ - navigate("/home") + navigate("/home"); }} > Home @@ -25,7 +25,7 @@ const Navbar = (): ReactElement => {
{ - navigate("/mentor") + navigate("/mentor"); }} > Mentor @@ -33,7 +33,7 @@ const Navbar = (): ReactElement => {
{ - navigate("/create-workshop") + navigate("/create-workshop"); }} > Create Workshop @@ -41,7 +41,7 @@ const Navbar = (): ReactElement => {
{ - navigate("/create-meeting") + navigate("/create-meeting"); }} > Create Meeting @@ -50,7 +50,7 @@ const Navbar = (): ReactElement => {
- ) -} + ); +}; -export default Navbar +export default Navbar; diff --git a/app/src/index.css b/app/src/index.css index ec2585e..4a1df4d 100644 --- a/app/src/index.css +++ b/app/src/index.css @@ -1,13 +1,13 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + 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', + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/app/src/index.tsx b/app/src/index.tsx index 1e0f6f6..cf4e546 100644 --- a/app/src/index.tsx +++ b/app/src/index.tsx @@ -1,17 +1,19 @@ -import React from "react" -import ReactDOM from "react-dom/client" -import "./styles/main.scss" -import App from "./App" -import reportWebVitals from "./reportWebVitals" +import React from "react"; +import ReactDOM from "react-dom/client"; +import "./styles/main.scss"; +import App from "./App"; +import reportWebVitals from "./reportWebVitals"; -const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement) +const root = ReactDOM.createRoot( + document.getElementById("root") as HTMLElement, +); root.render( - -) + , +); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals() +reportWebVitals(); diff --git a/app/src/pages/CreateGroup.tsx b/app/src/pages/CreateGroup.tsx index 03ac124..ff9fa0d 100644 --- a/app/src/pages/CreateGroup.tsx +++ b/app/src/pages/CreateGroup.tsx @@ -1,28 +1,28 @@ -import React, { type ReactElement, useState } from "react" -import Navbar from "../components/Navbar" -import AsyncSubmit from "../components/AsyncSubmit" -import { api } from "../api" -import { useNavigate } from "react-router-dom" -import * as yup from "yup" -import { Formik, Form, Field } from "formik" +import React, { type ReactElement, useState } from "react"; +import Navbar from "../components/Navbar"; +import AsyncSubmit from "../components/AsyncSubmit"; +import { api } from "../api"; +import { useNavigate } from "react-router-dom"; +import * as yup from "yup"; +import { Formik, Form, Field } from "formik"; interface GroupFormValues { - groupName: string - groupDescription: string - groupMemberEmail: string + groupName: string; + groupDescription: string; + groupMemberEmail: string; } const initialValues: GroupFormValues = { groupName: "", groupDescription: "", groupMemberEmail: "", -} +}; const CreateGroup = (): ReactElement => { - const [isLoading, setIsLoading] = useState(false) - const [success, setSuccess] = useState(false) - const [members, setMembers] = useState([]) - const navigate = useNavigate() + const [isLoading, setIsLoading] = useState(false); + const [success, setSuccess] = useState(false); + const [members, setMembers] = useState([]); + const navigate = useNavigate(); const validationSchema = yup.object().shape({ groupName: yup.string().required("Please enter a group name"), @@ -35,47 +35,47 @@ const CreateGroup = (): ReactElement => { "Please enter an email or add a group member", function (value) { // Validate only if there's no value and no members added - return value !== "" || members.length > 0 - } + return value !== "" || members.length > 0; + }, ), - }) + }); const handleSubmit = async (values: GroupFormValues, { resetForm }: any) => { - setIsLoading(true) + setIsLoading(true); // Construct the group data to send to the backend const groupData = { groupName: values.groupName, groupDescription: values.groupDescription, members: members, // Use the members state array - } + }; - console.log("Sending group data:", groupData) // Optional: Log the data being sent + console.log("Sending group data:", groupData); // Optional: Log the data being sent try { // Send POST request to the /create-group endpoint - const response = await api.post("/create-group/:", groupData) + const response = await api.post("/create-group/:", groupData); - console.log("Group created successfully:", response.data) - setSuccess(true) // Set success state to true - resetForm() // Reset the form after successful submission - setMembers([]) // Clear the members array as well + console.log("Group created successfully:", response.data); + setSuccess(true); // Set success state to true + resetForm(); // Reset the form after successful submission + setMembers([]); // Clear the members array as well } catch (error) { console.error( "Error creating group:", - (error as any).response?.data || (error as any).message - ) + (error as any).response?.data || (error as any).message, + ); } finally { - setIsLoading(false) // Reset loading state + setIsLoading(false); // Reset loading state } - } + }; const addMember = (email: string, resetField: () => void) => { if (email && !members.includes(email)) { - setMembers([...members, email]) - resetField() // Clear the email input field + setMembers([...members, email]); + resetField(); // Clear the email input field } - } + }; return ( <> @@ -148,8 +148,8 @@ const CreateGroup = (): ReactElement => { className="Button Button-color--purple-1000 Margin-left--10" onClick={() => { addMember(values.groupMemberEmail, () => - setFieldValue("groupMemberEmail", "") - ) + setFieldValue("groupMemberEmail", ""), + ); }} > Add @@ -195,7 +195,7 @@ const CreateGroup = (): ReactElement => {
- ) -} + ); +}; -export default CreateGroup +export default CreateGroup; diff --git a/app/src/pages/CreateMeeting.tsx b/app/src/pages/CreateMeeting.tsx index 0854af2..5cdf493 100644 --- a/app/src/pages/CreateMeeting.tsx +++ b/app/src/pages/CreateMeeting.tsx @@ -1,66 +1,66 @@ -import React, { useState } from "react" -import { Formik, Form, Field, FieldArray } from "formik" -import Navbar from "../components/Navbar" -import * as Yup from "yup" +import React, { useState } from "react"; +import { Formik, Form, Field, FieldArray } from "formik"; +import Navbar from "../components/Navbar"; +import * as Yup from "yup"; const CreateMeeting = () => { - const initialValues = { - meeting: "", - notes: "", - } - const validationSchema = Yup.object().shape({ - meeting: Yup.string().required("Please enter a meeting name"), - notes: Yup.string().required("Please enter meeting notes"), - }) - const handleSubmit = (values: any) => { - console.log(values) - } - return ( - <> - -

Create Meeting

- - {({ values, errors, touched, isSubmitting }) => ( -
-
- - - {errors.meeting && touched.meeting && ( -
{errors.meeting}
- )} -
-
- - - {errors.notes && touched.notes && ( -
{errors.notes}
- )} -
- -
- )} -
- - ) - } - - export default CreateMeeting \ No newline at end of file + const initialValues = { + meeting: "", + notes: "", + }; + const validationSchema = Yup.object().shape({ + meeting: Yup.string().required("Please enter a meeting name"), + notes: Yup.string().required("Please enter meeting notes"), + }); + const handleSubmit = (values: any) => { + console.log(values); + }; + return ( + <> + +

Create Meeting

+ + {({ values, errors, touched, isSubmitting }) => ( +
+
+ + + {errors.meeting && touched.meeting && ( +
{errors.meeting}
+ )} +
+
+ + + {errors.notes && touched.notes && ( +
{errors.notes}
+ )} +
+ +
+ )} +
+ + ); +}; + +export default CreateMeeting; diff --git a/app/src/pages/CreateWorkshop.tsx b/app/src/pages/CreateWorkshop.tsx index 3e02e76..fa1e61d 100644 --- a/app/src/pages/CreateWorkshop.tsx +++ b/app/src/pages/CreateWorkshop.tsx @@ -1,25 +1,25 @@ -import React from "react" -import { Formik, Form, Field } from "formik" -import * as Yup from "yup" -import Navbar from "../components/Navbar" +import React from "react"; +import { Formik, Form, Field } from "formik"; +import * as Yup from "yup"; +import Navbar from "../components/Navbar"; const CreateWorkshop = () => { // Initial form values const initialValues = { name: "", description: "", - } + }; // Validation schema using Yup const validationSchema = Yup.object().shape({ name: Yup.string().required("Name is required"), description: Yup.string().required("Description is required"), - }) + }); // Handle form submission const handleSubmit = (values: any) => { - console.log(values) - } + console.log(values); + }; return ( <> @@ -71,7 +71,7 @@ const CreateWorkshop = () => { )} - ) -} + ); +}; -export default CreateWorkshop +export default CreateWorkshop; diff --git a/app/src/pages/Home.tsx b/app/src/pages/Home.tsx index 41d9e5d..b57d475 100644 --- a/app/src/pages/Home.tsx +++ b/app/src/pages/Home.tsx @@ -1,18 +1,18 @@ -import React, { useState } from "react" -import { Formik, Form, Field, FieldArray } from "formik" -import * as yup from "yup" -import Navbar from "../components/Navbar" -import AsyncSubmit from "../components/AsyncSubmit" -import { useNavigate } from "react-router-dom" -import Modal from "../components/Modal" +import React, { useState } from "react"; +import { Formik, Form, Field, FieldArray } from "formik"; +import * as yup from "yup"; +import Navbar from "../components/Navbar"; +import AsyncSubmit from "../components/AsyncSubmit"; +import { useNavigate } from "react-router-dom"; +import Modal from "../components/Modal"; const Home = () => { - const [isModal, setIsModal] = useState(false) - const navigate = useNavigate() - const [isLoading, setIsLoading] = useState(false) - const [success, setSuccess] = useState(false) - const [selection, setSelection] = useState("Equally") // Default to "Equally" - const [errorMessage, setErrorMessage] = useState("") + const [isModal, setIsModal] = useState(false); + const navigate = useNavigate(); + const [isLoading, setIsLoading] = useState(false); + const [success, setSuccess] = useState(false); + const [selection, setSelection] = useState("Equally"); // Default to "Equally" + const [errorMessage, setErrorMessage] = useState(""); const initialValues = { item: "", @@ -23,7 +23,7 @@ const Home = () => { { name: "Jane", selected: false, splitValue: undefined }, { name: "Doe", selected: false, splitValue: undefined }, ], - } + }; const validationSchema = yup.object().shape({ item: yup.string().required("Please enter an item or activity"), @@ -32,50 +32,50 @@ const Home = () => { .positive("Cost must be a positive number") .required("Please enter the cost"), date: yup.string().required("Please select a date"), - }) + }); const handleSubmit = async (values: any, { resetForm }: any) => { - setIsLoading(true) - setErrorMessage("") // Clear error message at the start of submission + setIsLoading(true); + setErrorMessage(""); // Clear error message at the start of submission try { // Initialize a variable to hold the breakdown for each member - let memberBreakdown: { name: string; amountDue: any }[] = [] + let memberBreakdown: { name: string; amountDue: any }[] = []; // Calculate total amount owed based on the selection method - const totalCost = values.cost + const totalCost = values.cost; const selectedMembers = values.members.filter( - (member: { selected: any }) => member.selected - ) + (member: { selected: any }) => member.selected, + ); if (selection === "Equally") { // Split the total cost equally between the selected members - const amountPerMember = totalCost / selectedMembers.length + const amountPerMember = totalCost / selectedMembers.length; selectedMembers.forEach((member: { name: any }) => { memberBreakdown.push({ name: member.name, amountDue: amountPerMember, - }) - }) + }); + }); } else if (selection === "By Percent") { // Split the total cost based on the percentage provided for each selected member selectedMembers.forEach((member: { splitValue: number; name: any }) => { - const percentage = member.splitValue || 0 // default to 0 if no percentage provided - const amountDue = (percentage / 100) * totalCost + const percentage = member.splitValue || 0; // default to 0 if no percentage provided + const amountDue = (percentage / 100) * totalCost; memberBreakdown.push({ name: member.name, amountDue: amountDue, - }) - }) + }); + }); } else if (selection === "Manual") { // Use the manual amounts provided for each selected member selectedMembers.forEach((member: { splitValue: number; name: any }) => { - const amountDue = member.splitValue || 0 // default to 0 if no amount provided + const amountDue = member.splitValue || 0; // default to 0 if no amount provided memberBreakdown.push({ name: member.name, amountDue: amountDue, - }) - }) + }); + }); } // Package the final data to submit @@ -84,60 +84,62 @@ const Home = () => { totalCost: totalCost, date: values.date, memberBreakdown: memberBreakdown, - } + }; - console.log("Submitting data:", finalData) - setSuccess(true) - setErrorMessage("") // Ensure error message is cleared on success - resetForm() + console.log("Submitting data:", finalData); + setSuccess(true); + setErrorMessage(""); // Ensure error message is cleared on success + resetForm(); } catch (error) { - console.error("Error submitting:", error) + console.error("Error submitting:", error); } finally { - setIsLoading(false) + setIsLoading(false); } - } + }; // Custom validation logic to check split values const validateForm = (values: { members: any[]; cost: number }) => { - let errors = {} - let totalSplitValue = 0 + let errors = {}; + let totalSplitValue = 0; // Custom validation based on the selection if (selection !== "Equally") { - let membersSelected = values.members.filter((member) => member.selected) + let membersSelected = values.members.filter((member) => member.selected); if (membersSelected.length === 0) { - setErrorMessage("Please select at least one member.") - return errors + setErrorMessage("Please select at least one member."); + return errors; } membersSelected.forEach((member) => { if (!member.splitValue) { setErrorMessage( - "Please provide a split value for all selected members." - ) - return errors + "Please provide a split value for all selected members.", + ); + return errors; } totalSplitValue += - selection === "By Percent" ? member.splitValue : member.splitValue - }) + selection === "By Percent" ? member.splitValue : member.splitValue; + }); // Check if the split values sum up correctly if (selection === "By Percent" && totalSplitValue !== 100) { - setErrorMessage("The total percentage split must add up to 100%.") - return errors + setErrorMessage("The total percentage split must add up to 100%."); + return errors; } if (selection === "Manual" && totalSplitValue !== values.cost) { - setErrorMessage("The total split values must add up to the total cost.") - return errors + setErrorMessage( + "The total split values must add up to the total cost.", + ); + return errors; } } // If no error, clear the error message - setErrorMessage("") - return errors - } + setErrorMessage(""); + return errors; + }; return ( <> @@ -206,7 +208,7 @@ const Home = () => { : "Button Button-color--green-1000" } onClick={() => { - setSelection("Equally") + setSelection("Equally"); }} > Equally @@ -218,7 +220,7 @@ const Home = () => { : "Button Button-color--green-1000" } onClick={() => { - setSelection("By Percent") + setSelection("By Percent"); }} > By Percent @@ -230,7 +232,7 @@ const Home = () => { : "Button Button-color--green-1000" } onClick={() => { - setSelection("Manual") + setSelection("Manual"); }} > Manual @@ -312,7 +314,7 @@ const Home = () => {

Home

{ - navigate("/create-group") + navigate("/create-group"); }} className="Button Button-color--dark-1000" > @@ -320,14 +322,14 @@ const Home = () => {
{ - setIsModal(true) + setIsModal(true); }} className="Button Button-color--dark-1000 Margin-top--10" > Open Modal
- ) -} + ); +}; -export default Home +export default Home; diff --git a/app/src/pages/MentorDashboard.tsx b/app/src/pages/MentorDashboard.tsx index 8abe82f..6f2b98c 100644 --- a/app/src/pages/MentorDashboard.tsx +++ b/app/src/pages/MentorDashboard.tsx @@ -1,5 +1,5 @@ -import React, { useState } from "react" -import Navbar from "../components/Navbar" +import React, { useState } from "react"; +import Navbar from "../components/Navbar"; const MentorDashboard = () => { return ( @@ -10,7 +10,7 @@ const MentorDashboard = () => {
Example Button
- ) -} + ); +}; -export default MentorDashboard +export default MentorDashboard; diff --git a/app/src/reportWebVitals.ts b/app/src/reportWebVitals.ts index 49a2a16..5fa3583 100644 --- a/app/src/reportWebVitals.ts +++ b/app/src/reportWebVitals.ts @@ -1,8 +1,8 @@ -import { ReportHandler } from 'web-vitals'; +import { ReportHandler } from "web-vitals"; const reportWebVitals = (onPerfEntry?: ReportHandler) => { if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { getCLS(onPerfEntry); getFID(onPerfEntry); getFCP(onPerfEntry); diff --git a/app/src/setupTests.ts b/app/src/setupTests.ts index 8f2609b..1dd407a 100644 --- a/app/src/setupTests.ts +++ b/app/src/setupTests.ts @@ -2,4 +2,4 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; +import "@testing-library/jest-dom"; diff --git a/app/src/styles/_components.scss b/app/src/styles/_components.scss index 89959b6..f79bd2b 100644 --- a/app/src/styles/_components.scss +++ b/app/src/styles/_components.scss @@ -1,124 +1,123 @@ .Navbar { + display: flex; + flex-direction: column; + z-index: var(--pww-z-50); + + &-body { display: flex; - flex-direction: column; - z-index: var(--pww-z-50); - - &-body { - display: flex; - flex-direction: row; - align-items: center; - background-color: var(--pww-color-light-1000); - padding: 10px 32px; - box-shadow: var(--pww-shadow-dark); - - &-logo { - font-size: var(--pww-font-size-30); - font-weight: 900; - background-image: url('../assets/logo.png'); - background-size: contain; /* Ensure the entire logo fits within the defined area */ - background-repeat: no-repeat; /* Prevent repeating */ - background-position: center; /* Center the logo within its container */ - width: 125px; - height: 75px; /* Adjust height based on the image’s aspect ratio */ - } - - &-link { - color: var(--pww-color-dark-1000); - cursor: pointer; - font-size: var(--pww-font-size-16); - - &:hover { - color: var(--pww-color-teal-1000); - } - } + flex-direction: row; + align-items: center; + background-color: var(--pww-color-light-1000); + padding: 10px 32px; + box-shadow: var(--pww-shadow-dark); + + &-logo { + font-size: var(--pww-font-size-30); + font-weight: 900; + background-image: url("../assets/logo.png"); + background-size: contain; /* Ensure the entire logo fits within the defined area */ + background-repeat: no-repeat; /* Prevent repeating */ + background-position: center; /* Center the logo within its container */ + width: 125px; + height: 75px; /* Adjust height based on the image’s aspect ratio */ + } + + &-link { + color: var(--pww-color-dark-1000); + cursor: pointer; + font-size: var(--pww-font-size-16); + + &:hover { + color: var(--pww-color-teal-1000); + } } + } } .Modal-overlay { - background-color: rgba(0, 0, 0, .4); - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: var(--pww-z-100); - overflow: hidden; + background-color: rgba(0, 0, 0, 0.4); + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: var(--pww-z-100); + overflow: hidden; } .Modal { - position: fixed; - padding: 20px; - width: 400px; - z-index: var(--pww-z-1000); - top: 10%; - left: 50%; - margin-left: -200px; - background-color: var(--pww-color-light-1000); - border-radius: var(--pww-border-radius-8); - border: 1px solid rgba(var(--dark), var(--opacity-tint)); + position: fixed; + padding: 20px; + width: 400px; + z-index: var(--pww-z-1000); + top: 10%; + left: 50%; + margin-left: -200px; + background-color: var(--pww-color-light-1000); + border-radius: var(--pww-border-radius-8); + border: 1px solid rgba(var(--dark), var(--opacity-tint)); - &-large { - width: 700px; - margin-left: -350px; - max-height: 700px; - } + &-large { + width: 700px; + margin-left: -350px; + max-height: 700px; + } - &-close { - display: flex; - justify-content: right; - - .Icon { - font-size: var(--pww-font-size-16); - margin-left: auto; - - &:hover { - cursor: pointer; - color: var(--pww-color-red-1000); - } - } - } + &-close { + display: flex; + justify-content: right; - &-header { - font-size: var(--pww-font-size-24); - margin-bottom: 10px; - } + .Icon { + font-size: var(--pww-font-size-16); + margin-left: auto; - &-subtitle { - color: var(--pww-color-dark-700); - font-size: var(--pww-font-size-16); - border-bottom: 1px solid var(--pww-color-dark-700); - padding-bottom: 10px; - margin-bottom: 20px; + &:hover { + cursor: pointer; + color: var(--pww-color-red-1000); } - - &-content { - border-radius: var(--pww-border-radius-16); - color: var(--pww-color-dark-800); - z-index: 5; - height: fit-content; - max-height: 600px; - overflow-y: auto; - padding: 10px; } + } - &-tab { - cursor: pointer; - display: flex; - - &-item { - width: 70px; - padding-bottom: 5px; - text-align: center; - border-bottom: 1px solid var(--pww-color-light-600); - &-selected { - color: var(--pww-color-light-1000); - border-bottom: 3px solid var(--pww-color-light-1000); - } - - &:hover { - color: var(--pww-color-light-1000); - } - } + &-header { + font-size: var(--pww-font-size-24); + margin-bottom: 10px; + } + + &-subtitle { + color: var(--pww-color-dark-700); + font-size: var(--pww-font-size-16); + border-bottom: 1px solid var(--pww-color-dark-700); + padding-bottom: 10px; + margin-bottom: 20px; + } + + &-content { + border-radius: var(--pww-border-radius-16); + color: var(--pww-color-dark-800); + z-index: 5; + height: fit-content; + max-height: 600px; + overflow-y: auto; + padding: 10px; + } + + &-tab { + cursor: pointer; + display: flex; + + &-item { + width: 70px; + padding-bottom: 5px; + text-align: center; + border-bottom: 1px solid var(--pww-color-light-600); + &-selected { + color: var(--pww-color-light-1000); + border-bottom: 3px solid var(--pww-color-light-1000); + } + + &:hover { + color: var(--pww-color-light-1000); + } } + } } - diff --git a/app/src/styles/_formik.scss b/app/src/styles/_formik.scss index 0c58f64..40134bb 100644 --- a/app/src/styles/_formik.scss +++ b/app/src/styles/_formik.scss @@ -1,60 +1,60 @@ .Form { - color: var(--pww-color-dark-900); - - &-container { - width: 100%; - max-width: 600px; // Adjust max-width based on your layout - padding: 20px; - margin: 0 auto; // Center the form container + color: var(--pww-color-dark-900); + + &-container { + width: 100%; + max-width: 600px; // Adjust max-width based on your layout + padding: 20px; + margin: 0 auto; // Center the form container + } + + &-group { + display: flex; + flex-direction: column; + margin-bottom: 10px; + + label { + margin-bottom: 4px; + font-size: var(--pww-font-size-14); + color: var(--pww-color-dark-1000); + font-weight: var(--pww-font-weight-bold); } - &-group { - display: flex; - flex-direction: column; - margin-bottom: 10px; - - label { - margin-bottom: 4px; - font-size: var(--pww-font-size-14); - color: var(--pww-color-dark-1000); - font-weight: var(--pww-font-weight-bold); - } - - input, - select { - border-radius: var(--pww-border-radius-8); - border: none; - background-color: var(--pww-color-dark-50); - color: var(--pww-color-dark-700); - font-family: 'Exo 2', sans-serif; - font-size: var(--pww-font-size-14); - padding: 8px; - // width: 100%; // Ensure inputs fit within the container - box-sizing: border-box; // Include padding and border in width calculation - position: relative; - } - - &-toggle { - cursor: pointer; - margin: -30px 10px 0 auto; - z-index: var(--pww-z-100); - color: var(--pww-color-dark-700); - - &:hover { - color: var(--pww-color-dark-900); - } - } + input, + select { + border-radius: var(--pww-border-radius-8); + border: none; + background-color: var(--pww-color-dark-50); + color: var(--pww-color-dark-700); + font-family: "Exo 2", sans-serif; + font-size: var(--pww-font-size-14); + padding: 8px; + // width: 100%; // Ensure inputs fit within the container + box-sizing: border-box; // Include padding and border in width calculation + position: relative; } - &-error { - margin-top: 10px; - color: var(--pww-color-red-1000); - font-size: var(--pww-font-size-12); - } + &-toggle { + cursor: pointer; + margin: -30px 10px 0 auto; + z-index: var(--pww-z-100); + color: var(--pww-color-dark-700); - &-success { - margin-top: 10px; - color: var(--pww-color-green-1000); - font-size: var(--pww-font-size-12); + &:hover { + color: var(--pww-color-dark-900); + } } + } + + &-error { + margin-top: 10px; + color: var(--pww-color-red-1000); + font-size: var(--pww-font-size-12); + } + + &-success { + margin-top: 10px; + color: var(--pww-color-green-1000); + font-size: var(--pww-font-size-12); + } } diff --git a/app/src/styles/_utilities.scss b/app/src/styles/_utilities.scss index 3d202e1..0f590c0 100644 --- a/app/src/styles/_utilities.scss +++ b/app/src/styles/_utilities.scss @@ -1,7 +1,11 @@ @each $name, $color in $palette { @each $alpha in $alphas { - .Text-color--#{$name}-#{$alpha} { color: var(--pww-color-#{$name}-#{$alpha}); } - .Background-color--#{$name}-#{$alpha} { background-color: var(--pww-color-#{$name}-#{$alpha}); } + .Text-color--#{$name}-#{$alpha} { + color: var(--pww-color-#{$name}-#{$alpha}); + } + .Background-color--#{$name}-#{$alpha} { + background-color: var(--pww-color-#{$name}-#{$alpha}); + } .Background-colorHover--#{$name}-#{$alpha} { cursor: pointer; @@ -13,7 +17,6 @@ } } - .Text-colorHover--#{$name}-#{$alpha} { cursor: pointer; @@ -22,7 +25,9 @@ } } - .Border-color--#{$name}-#{$alpha} { border-color: var(--pww-color-#{$name}-#{$alpha}); } + .Border-color--#{$name}-#{$alpha} { + border-color: var(--pww-color-#{$name}-#{$alpha}); + } } } @@ -30,9 +35,9 @@ .Text-fontSize--#{$fontSize} { font-size: #{$fontSize}px; - // @include media("<=tablet") { - // font-size: #{$fontSize - 2}px; - // } + // @include media("<=tablet") { + // font-size: #{$fontSize - 2}px; + // } } // .Text-fontSize--#{$fontSize}--ltDesktop { @@ -130,13 +135,28 @@ } @each $margin in $margins { - .Margin--#{$margin} { margin: #{$margin}px; } - .Margin-left--#{$margin} { margin-left: #{$margin}px; } - .Margin-top--#{$margin} { margin-top: #{$margin}px; } - .Margin-right--#{$margin} { margin-right: #{$margin}px; } - .Margin-bottom--#{$margin} { margin-bottom: #{$margin}px; } - .Margin-x--#{$margin} { margin: 0 #{$margin}px; } - .Margin-y--#{$margin} { margin-top: #{$margin}px; margin-bottom: #{$margin}px; } + .Margin--#{$margin} { + margin: #{$margin}px; + } + .Margin-left--#{$margin} { + margin-left: #{$margin}px; + } + .Margin-top--#{$margin} { + margin-top: #{$margin}px; + } + .Margin-right--#{$margin} { + margin-right: #{$margin}px; + } + .Margin-bottom--#{$margin} { + margin-bottom: #{$margin}px; + } + .Margin-x--#{$margin} { + margin: 0 #{$margin}px; + } + .Margin-y--#{$margin} { + margin-top: #{$margin}px; + margin-bottom: #{$margin}px; + } // @include media(" 50, var(--pww-color-dark-1000), var(--pww-color-light-1000)); + @return if( + lightness($color) > 50, + var(--pww-color-dark-1000), + var(--pww-color-light-1000) + ); // @return if(true, var(--pww-color-dark-1000), var(--pww-color-light-1000)); } @@ -71,7 +76,7 @@ $zIndex: -10 -5 0 5 10 50 100 1000; --pww-z-#{$zIndex}: #{$zIndex}; } - --pww-shadow-dark: var(--pww-color-dark-50) 0px 7px 15px 0px; + --pww-shadow-dark: var(--pww-color-dark-50) 0px 7px 15px 0px; --pww-shadow-ambient: var(--pww-color-dark-100) 0px 15px 35px 0px; } @@ -80,30 +85,34 @@ $weights: 25 50 100 200 300 400 500 600 700 800 900 !default; // defines more variables for the app @mixin root-palette($palette) { - @each $name, $color in $palette { - --#{$name}: #{red($color)}, #{green($color)}, #{blue($color)}; - --#{$name}-dark: #{red(saturate($color, 20))}, #{green(saturate($color, 20))}, #{blue(saturate($color, 20))}; - --#{$name}-light: #{red(lighten($color, 20))}, #{green(lighten($color, 20))}, #{blue(lighten($color, 20))}; - } + @each $name, $color in $palette { + --#{$name}: #{red($color)}, #{green($color)}, #{blue($color)}; + --#{$name}-dark: #{red(saturate($color, 20))}, + #{green(saturate($color, 20))}, #{blue(saturate($color, 20))}; + --#{$name}-light: #{red(lighten($color, 20))}, #{green(lighten($color, 20))}, + #{blue(lighten($color, 20))}; } - - @mixin root-property($property, $base, $factors) { - @for $i from 1 through length($factors) { - --#{$property}-#{$i - 1}: #{$base * nth($factors, $i)}; - } +} + +@mixin root-property($property, $base, $factors) { + @for $i from 1 through length($factors) { + --#{$property}-#{$i - 1}: #{$base * nth($factors, $i)}; } - - @mixin root-color($name, $color) { - @each $weight in $weights { - --color-#{$name}-#{$weight}: #{lighten($color, math.div((1000 - $weight), 10))}; - } +} + +@mixin root-color($name, $color) { + @each $weight in $weights { + --color-#{$name}-#{$weight}: #{lighten( + $color, + math.div((1000 - $weight), 10) + )}; } - - @mixin utility($palette, $prefix, $attribute) { - @each $name, $color in $palette { - .#{$prefix}-#{$name} { - #{$attribute}: #{$color}; - } +} + +@mixin utility($palette, $prefix, $attribute) { + @each $name, $color in $palette { + .#{$prefix}-#{$name} { + #{$attribute}: #{$color}; } } - +} diff --git a/app/src/styles/_widget.scss b/app/src/styles/_widget.scss index 96fdd20..3df1273 100644 --- a/app/src/styles/_widget.scss +++ b/app/src/styles/_widget.scss @@ -1,47 +1,47 @@ .FormWidget { - display: flex; - justify-content: center; - margin-top: 5%; + display: flex; + justify-content: center; + margin-top: 5%; - &-body { - width: 30%; - height: fit-content; + &-body { + width: 30%; + height: fit-content; - // &-logo { - // display: block; - // background-image: url('../assets/pww-Logo-White.png'); - // background-size: contain; - // background-repeat: no-repeat; - // height: 60px; - // width: auto; - // margin: 56px 0 40px 20px; - // } + // &-logo { + // display: block; + // background-image: url('../assets/pww-Logo-White.png'); + // background-size: contain; + // background-repeat: no-repeat; + // height: 60px; + // width: auto; + // margin: 56px 0 40px 20px; + // } - &-content { - padding: 56px 48px; - box-shadow: var(--pww-shadow-ambient); - background-color: var(--pww-color-dark-1000); - border-radius: var(--pww-border-radius-8); - } + &-content { + padding: 56px 48px; + box-shadow: var(--pww-shadow-ambient); + background-color: var(--pww-color-dark-1000); + border-radius: var(--pww-border-radius-8); } + } } .SuccessWidget { - display: flex; - justify-content: center; - align-items: center; - height: 100vh; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; - &-body { - width: 30%; - height: fit-content; - } + &-body { + width: 30%; + height: fit-content; + } - &-icon { - width: 100; - display: flex; - justify-content: center; - color: var(--pww-color-yellow-1000); - font-size: var(--pww-font-size-72); - } -} \ No newline at end of file + &-icon { + width: 100; + display: flex; + justify-content: center; + color: var(--pww-color-yellow-1000); + font-size: var(--pww-font-size-72); + } +} diff --git a/app/src/styles/main.scss b/app/src/styles/main.scss index a1bc20b..3de83af 100644 --- a/app/src/styles/main.scss +++ b/app/src/styles/main.scss @@ -1,53 +1,53 @@ // Imports for all of the external libraries -@import url('https://fonts.googleapis.com/css?family=Rubik'); -@import url('https://pro.fontawesome.com/releases/v5.10.0/css/all.css'); +@import url("https://fonts.googleapis.com/css?family=Rubik"); +@import url("https://pro.fontawesome.com/releases/v5.10.0/css/all.css"); -@import '~bootstrap/scss/bootstrap-utilities.scss'; -@import '~bootstrap/scss/bootstrap-grid.scss'; +@import "~bootstrap/scss/bootstrap-utilities.scss"; +@import "~bootstrap/scss/bootstrap-grid.scss"; // Include modular style files -@import 'animate.css'; -@import 'components'; -@import 'variables'; -@import 'utilities'; -@import 'widget'; -@import 'formik'; +@import "animate.css"; +@import "components"; +@import "variables"; +@import "utilities"; +@import "widget"; +@import "formik"; :root { // define colors - @include root-palette($palette); - - --text-on-dark: var(--pww-color-light-1000); - --text-on-light: var(--pww-color-dark-1000); - - --transition-duration: 0.15s; - - --border-radius: 4rem; - --box-shadow: 0 0 3rem rgba(var(--dark), .1); - --line-height: 1.5em; - - --container-padding: 2rem; - } - - // Fonts - html, - body { - font-family: 'Quattrocento'; - margin: 0; - } - - // default settings for the body - body { - font-size: var(--pww-font-size-4); - background-color: var(--pww-color-blue-100); - color: var(--pww-color-dark-1000); - } - - // Background Colors - .app { - min-height: 100vh; - display: flex; - flex-direction: column; - color: var(--pww-color-dark-1000); - font-weight: 100; - } \ No newline at end of file + @include root-palette($palette); + + --text-on-dark: var(--pww-color-light-1000); + --text-on-light: var(--pww-color-dark-1000); + + --transition-duration: 0.15s; + + --border-radius: 4rem; + --box-shadow: 0 0 3rem rgba(var(--dark), 0.1); + --line-height: 1.5em; + + --container-padding: 2rem; +} + +// Fonts +html, +body { + font-family: "Quattrocento"; + margin: 0; +} + +// default settings for the body +body { + font-size: var(--pww-font-size-4); + background-color: var(--pww-color-blue-100); + color: var(--pww-color-dark-1000); +} + +// Background Colors +.app { + min-height: 100vh; + display: flex; + flex-direction: column; + color: var(--pww-color-dark-1000); + font-weight: 100; +} diff --git a/app/tsconfig.json b/app/tsconfig.json index a273b0c..9d379a3 100644 --- a/app/tsconfig.json +++ b/app/tsconfig.json @@ -1,11 +1,7 @@ { "compilerOptions": { "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, @@ -20,7 +16,5 @@ "noEmit": true, "jsx": "react-jsx" }, - "include": [ - "src" - ] + "include": ["src"] }