diff --git a/.github/workflows/generateCheck.sh b/.github/workflows/generateCheck.sh index 0f98e9cb..f073a72c 100755 --- a/.github/workflows/generateCheck.sh +++ b/.github/workflows/generateCheck.sh @@ -1,14 +1,16 @@ +files=$(npx prettier . -l) +status=$? if [ $status == 0 ]; then - echo "## Formatting Check passed 🥳" >>$GITHUB_STEP_SUMMARY - echo "All files are formatted correctly" >>$GITHUB_STEP_SUMMARY - exit 0 + echo "## Formatting Check passed 🥳" >>$GITHUB_STEP_SUMMARY + echo "All files are formatted correctly" >>$GITHUB_STEP_SUMMARY + exit 0 else - echo "## Formatting Check Failed 😅" >>$GITHUB_STEP_SUMMARY - echo "Please run prettier using \`npx prettier . --write\` in order to format your code" >>$GITHUB_STEP_SUMMARY - echo "### Files with bad formatting:" >>$GITHUB_STEP_SUMMARY - for file in $files; do - echo "- $file" >>$GITHUB_STEP_SUMMARY - echo "::error file=$file::$file not formatted correctly" - done - exit 1 + echo "## Formatting Check Failed 😅" >>$GITHUB_STEP_SUMMARY + echo "Please run prettier using \`npx prettier . --write\` in order to format your code" >>$GITHUB_STEP_SUMMARY + echo "### Files with bad formatting:" >>$GITHUB_STEP_SUMMARY + for file in $files; do + echo "- $file" >>$GITHUB_STEP_SUMMARY + echo "::error file=$file::$file not formatted correctly" + done + exit 1 fi diff --git a/.github/workflows/prettierCheck.yml b/.github/workflows/prettierCheck.yml index e642ea75..d248dbe9 100644 --- a/.github/workflows/prettierCheck.yml +++ b/.github/workflows/prettierCheck.yml @@ -11,14 +11,6 @@ jobs: node-version: 18 cache: 'npm' - name: Run npm install - run: | - mv package.json package.json.bak - npm i --no-save prettier prettier-plugin-tailwindcss - mv package.json.bak package.json - - name: Run prettier - run: | - files=`npx prettier . -l` || st=$? && st=$? - echo status=`echo $st`>>"$GITHUB_ENV" - echo files=`echo $files`>> "$GITHUB_ENV" - - name: generate errors/summary + run: npm ci + - name: Run prettier & generate problems run: .github/workflows/generateCheck.sh diff --git a/.prettierrc.js b/.prettierrc.js deleted file mode 100644 index 08a34d3b..00000000 --- a/.prettierrc.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - printWidth: 80, - semi: true, - singleQuote: true, - tabWidth: 2, - trailingComma: 'all', - useTabs: false, - plugins: ['prettier-plugin-tailwindcss'], -}; diff --git a/.prettierrc.mjs b/.prettierrc.mjs new file mode 100644 index 00000000..b7128a21 --- /dev/null +++ b/.prettierrc.mjs @@ -0,0 +1,16 @@ +/** + * @see https://prettier.io/docs/en/configuration.html + * @type {import("prettier").Config} + */ +const config = { + printWidth: 80, + semi: true, + singleQuote: true, + tabWidth: 2, + trailingComma: 'all', + useTabs: false, + bracketSameLine: false, + plugins: ['prettier-plugin-tailwindcss'], +}; + +export default config; diff --git a/README.md b/README.md index a8df8cb9..d547e0a1 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,12 @@ $$; Currently, drizzle does not automatically create enums for you. You will have to create them manually. This [link](https://orm.drizzle.team/docs/column-types/pg#enum) should give you a good idea of how to create enums in postgres. -
+ +
+Tag View + there is a sql query in `src/server/db/tagView.sql` that you need to run in order for tags to work properly. + This query sets up a view that queries the different tags from clubs and orders them by how many clubs have those tags in descending order. +

Once you have added the `DATABASE_URL` to your `.env` file, and have all the necessary extensions as well as enums, you will need to run the following commands to create the tables in your database. diff --git a/package-lock.json b/package-lock.json index a6f9515e..c9037fd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@auth/drizzle-adapter": "^0.3.2", "@hookform/resolvers": "^3.3.2", + "@next/third-parties": "^14.2.15", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", @@ -22,7 +23,6 @@ "@trpc/client": "^11.0.0-rc.340", "@trpc/react-query": "^11.0.0-rc.340", "@trpc/server": "^11.0.0-rc.340", - "@vercel/analytics": "^1.3.1", "date-fns": "^2.30.0", "dotenv": "^16.0.3", "drizzle-orm": "^0.28.5", @@ -30,9 +30,9 @@ "next": "^14.2.2", "next-auth": "^4.23.0", "postgres": "^3.3.5", - "react": "18.2.0", + "react": "^18.2.0", "react-day-picker": "^8.9.1", - "react-dom": "18.2.0", + "react-dom": "^18.2.0", "react-hook-form": "^7.48.2", "superjson": "^1.13.1", "zod": "^3.22.4" @@ -44,8 +44,8 @@ "@types/eslint": "^8.44.2", "@types/jest": "^29.5.5", "@types/node": "^18.16.0", - "@types/react": "^18.2.20", - "@types/react-dom": "^18.2.7", + "@types/react": "^18.2.79", + "@types/react-dom": "^18.2.25", "@typescript-eslint/eslint-plugin": "^6.3.0", "@typescript-eslint/parser": "^6.3.0", "autoprefixer": "^10.4.14", @@ -54,7 +54,7 @@ "dotenv-cli": "^7.3.0", "drizzle-kit": "^0.19.13", "eslint": "^8.47.0", - "eslint-config-next": "^13.5.4", + "eslint-config-next": "^14.2.1", "eslint-config-prettier": "^8.5.0", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-react": "^7.29.4", @@ -1284,6 +1284,96 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1724,54 +1814,49 @@ "integrity": "sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==" }, "node_modules/@next/eslint-plugin-next": { - "version": "13.5.5", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.5.5.tgz", - "integrity": "sha512-S/32s4S+SCOpW58lHKdmILAAPRdnsSei7Y3L1oZSoe5Eh0QSlzbG1nYyIpnpwWgz3T7qe3imdq7cJ6Hf29epRA==", + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.1.tgz", + "integrity": "sha512-Fp+mthEBjkn8r9qd6o4JgxKp0IDEzW0VYHD8ZC05xS5/lFNwHKuOdr2kVhWG7BQCO9L6eeepshM1Wbs2T+LgSg==", "dev": true, "dependencies": { - "glob": "7.1.7" - } - }, - "node_modules/@next/eslint-plugin-next/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "glob": "10.3.10" } }, "node_modules/@next/eslint-plugin-next/node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@next/eslint-plugin-next/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@next/swc-darwin-arm64": { @@ -1909,6 +1994,19 @@ "node": ">= 10" } }, + "node_modules/@next/third-parties": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/third-parties/-/third-parties-14.2.15.tgz", + "integrity": "sha512-15CvipE1p1GtlzVfbDfXPrAGIhzJJe75Yy6+GIBRTd36lu95BegRsUJwCxJYoKz47Q09stcU2gJDMduMGqrikw==", + "license": "MIT", + "dependencies": { + "third-party-capital": "1.0.20" + }, + "peerDependencies": { + "next": "^13.0.0 || ^14.0.0", + "react": "^18.2.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1952,6 +2050,16 @@ "url": "https://github.com/sponsors/panva" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@radix-ui/primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", @@ -2980,31 +3088,24 @@ "devOptional": true }, "node_modules/@types/react": { - "version": "18.2.28", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.28.tgz", - "integrity": "sha512-ad4aa/RaaJS3hyGz0BGegdnSRXQBkd1CCYDCdNjBPg90UUpLgo+WlJqb9fMYUxtehmzF3PJaTWqRZjko6BRzBg==", + "version": "18.2.79", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.79.tgz", + "integrity": "sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==", "devOptional": true, "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.13.tgz", - "integrity": "sha512-eJIUv7rPP+EC45uNYp/ThhSpE16k22VJUknt5OLoH9tbXoi8bMhwLf5xRuWMywamNbWzhrSmU7IBJfPup1+3fw==", + "version": "18.2.25", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.25.tgz", + "integrity": "sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==", "devOptional": true, "dependencies": { "@types/react": "*" } }, - "node_modules/@types/scheduler": { - "version": "0.16.4", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.4.tgz", - "integrity": "sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==", - "devOptional": true - }, "node_modules/@types/semver": { "version": "7.5.3", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", @@ -3221,26 +3322,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@vercel/analytics": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.3.1.tgz", - "integrity": "sha512-xhSlYgAuJ6Q4WQGkzYTLmXwhYl39sWjoMA3nHxfkvG+WdBT25c563a7QhwwKivEOZtPJXifYHR1m2ihoisbWyA==", - "dependencies": { - "server-only": "^0.0.1" - }, - "peerDependencies": { - "next": ">= 13", - "react": "^18 || ^19" - }, - "peerDependenciesMeta": { - "next": { - "optional": true - }, - "react": { - "optional": true - } - } - }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -5488,14 +5569,14 @@ } }, "node_modules/eslint-config-next": { - "version": "13.5.5", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.5.5.tgz", - "integrity": "sha512-kQr/eevFyzeVt0yCKTchQp3MTIx8ZmBsAKLW+7bzmAXHcf2vvxIqAt2N/afb9SZpuXXhSb/8yrKQGVUVpYmafQ==", + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.1.tgz", + "integrity": "sha512-BgD0kPCWMlqoItRf3xe9fG0MqwObKfVch+f2ccwDpZiCJA8ghkz2wrASH+bI6nLZzGcOJOpMm1v1Q1euhfpt4Q==", "dev": true, "dependencies": { - "@next/eslint-plugin-next": "13.5.5", + "@next/eslint-plugin-next": "14.2.1", "@rushstack/eslint-patch": "^1.3.3", - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.28.1", @@ -6260,6 +6341,34 @@ "is-callable": "^1.1.3" } }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -7569,6 +7678,24 @@ "set-function-name": "^2.0.1" } }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -8871,6 +8998,15 @@ "node": ">= 6" } }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -9498,6 +9634,31 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -10658,11 +10819,6 @@ "optional": true, "peer": true }, - "node_modules/server-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", - "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==" - }, "node_modules/set-function-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", @@ -10919,6 +11075,36 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/string-width/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -11011,6 +11197,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -11335,6 +11534,12 @@ "node": ">=0.8" } }, + "node_modules/third-party-capital": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/third-party-capital/-/third-party-capital-1.0.20.tgz", + "integrity": "sha512-oB7yIimd8SuGptespDAZnNkzIz+NWaJCu2RMsbs4Wmp9zSDUM8Nhi3s2OOcqYuv3mN4hitXc8DVx+LyUmbUDiA==", + "license": "ISC" + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -11971,6 +12176,24 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 012bd751..1c4b94b2 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "dependencies": { "@auth/drizzle-adapter": "^0.3.2", "@hookform/resolvers": "^3.3.2", + "@next/third-parties": "^14.2.15", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", @@ -27,7 +28,6 @@ "@trpc/client": "^11.0.0-rc.340", "@trpc/react-query": "^11.0.0-rc.340", "@trpc/server": "^11.0.0-rc.340", - "@vercel/analytics": "^1.3.1", "date-fns": "^2.30.0", "dotenv": "^16.0.3", "drizzle-orm": "^0.28.5", @@ -35,9 +35,9 @@ "next": "^14.2.2", "next-auth": "^4.23.0", "postgres": "^3.3.5", - "react": "18.2.0", + "react": "^18.2.0", "react-day-picker": "^8.9.1", - "react-dom": "18.2.0", + "react-dom": "^18.2.0", "react-hook-form": "^7.48.2", "superjson": "^1.13.1", "zod": "^3.22.4" @@ -49,8 +49,8 @@ "@types/eslint": "^8.44.2", "@types/jest": "^29.5.5", "@types/node": "^18.16.0", - "@types/react": "^18.2.20", - "@types/react-dom": "^18.2.7", + "@types/react": "^18.2.79", + "@types/react-dom": "^18.2.25", "@typescript-eslint/eslint-plugin": "^6.3.0", "@typescript-eslint/parser": "^6.3.0", "autoprefixer": "^10.4.14", @@ -59,7 +59,7 @@ "dotenv-cli": "^7.3.0", "drizzle-kit": "^0.19.13", "eslint": "^8.47.0", - "eslint-config-next": "^13.5.4", + "eslint-config-next": "^14.2.1", "eslint-config-prettier": "^8.5.0", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-react": "^7.29.4", diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx index 44259a53..1b0b80fb 100644 --- a/src/app/about/page.tsx +++ b/src/app/about/page.tsx @@ -1,4 +1,4 @@ -import Header from '@src/components/BaseHeader'; +import Header from '@src/components/header/BaseHeader'; import type { Metadata } from 'next'; export const metadata: Metadata = { @@ -14,40 +14,67 @@ export const metadata: Metadata = { }; const About = () => { + const teamMembers = [ + { name: 'Ethan Bickel', position: 'Project Lead' }, + { name: 'Braeden Kotko', position: 'Engineer' }, + { name: 'Connor Harris', position: 'Engineer' }, + { name: 'Jonathan Le', position: 'Engineer' }, + { name: 'Alex Vazquez', position: 'Engineer' }, + { name: 'Ishaan Gupta', position: 'Engineer' }, + { name: 'Ritvik Thota', position: 'Engineer' }, + ]; + const recruits = [ + { name: 'Jordan Joelson', position: 'Engineer' }, + { name: 'Mansi Cherukupally', position: 'Engineer' }, + { name: 'Aryav Rastogi', position: 'Engineer' }, + { name: 'Sreevasan Siasubramanian', position: 'Engineer' }, + { name: 'Ninad Sudarsanam', position: 'Engineer' }, + { name: 'Shivesh Gupta', position: 'Engineer' }, + { name: 'Natalia Sekulic', position: 'Engineer' }, + { name: 'Mamoun Elmamoun', position: 'Engineer' }, + { name: 'Chloe Alzaga', position: 'Engineer' }, + { name: 'Joshua Perez', position: 'Engineer' }, + { name: 'Ankith Ganji', position: 'Engineer' }, + { name: 'Valeria Gallardo', position: 'Designer' }, + { name: 'Waseef Kabir', position: 'Designer' }, + { name: 'Ved Mahant', position: 'Designer' }, + ]; return (
-

- About us -

- Project Jupiter + About Jupiter

-

Our Goal

+

- Jupiter is a user-friendly platform that can be utilized by students - to seamlessly join school clubs. This tool allows students to browse - through the list of available clubs, their activities, and - objectives, all in one place. Students can easily sign up for clubs - that interest them and receive real-time updates on events, - meetings, and other activities organized by the clubs. The platform - also enables club leaders to manage and promote their clubs more - efficiently, keeping members informed about important details and - facilitating communication between members. + Jupiter is a platform being developed by nebula labs in order to + help students find organizations and events on and around campus.
+ You're able to track organizations you're interested in, + find new organizations, and keep up to date on events you want to + attend.
- Jupiter comes with several features that make it an ideal tool for - school club management. For instance, the platform provides a - comprehensive dashboard that enables club leaders to track - attendance, monitor club performance, and collect feedback from - members. The tool also integrates with the school's social - media pages and website, making it easy for students to discover - clubs that match their interests. With Jupiter, students can easily - find and join clubs, and club leaders can manage their clubs more - effectively, leading to more successful and fulfilling club - experiences for everyone involved. + For organizations we offer a better way to keep your info up to + date, and for people well suited for your organization to find out + about you and your events. +

+

+ If you're interested in contributing to Jupiter check out the{' '} + + Nebula Discord + + , or our{' '} + + Github +

@@ -55,18 +82,36 @@ const About = () => { Our Team
- {Array.from({ length: 8 }).map((_, key) => ( + {teamMembers.map((member, key) => (

- Name + {member.name}

-

Position

+

{member.position}

))}
+
+

+ Recruits +

+
+ {recruits.map((member, key) => ( +
+

+ {member.name} +

+

{member.position}

+
+ ))} +
+
diff --git a/src/app/admin/carousel/add/page.tsx b/src/app/admin/carousel/add/page.tsx index f609d74c..3da1d6ea 100644 --- a/src/app/admin/carousel/add/page.tsx +++ b/src/app/admin/carousel/add/page.tsx @@ -1,12 +1,12 @@ -import AddOrg from '@src/components/admin/AddOrg'; +import AddClub from '@src/components/admin/AddClub'; export default function Page() { return (

- Add Orgs to Carousel + Add Clubs to Carousel

- +
); } diff --git a/src/app/admin/orgs/[id]/page.tsx b/src/app/admin/clubs/[id]/page.tsx similarity index 72% rename from src/app/admin/orgs/[id]/page.tsx rename to src/app/admin/clubs/[id]/page.tsx index f6bba3fc..06626949 100644 --- a/src/app/admin/orgs/[id]/page.tsx +++ b/src/app/admin/clubs/[id]/page.tsx @@ -1,5 +1,5 @@ -import ApprovedOrg from '@src/components/admin/ApprovedOrg'; -import OtherOrgStatus from '@src/components/admin/OtherOrgStatus'; +import ApprovedClub from '@src/components/admin/ApprovedClub'; +import OtherClubStatus from '@src/components/admin/OtherClubStatus'; import { db } from '@src/server/db'; import { eq } from 'drizzle-orm'; import { notFound } from 'next/navigation'; @@ -16,9 +16,9 @@ export default async function Page({ params: { id } }: Props) {

{org.name}

{org.approved === 'approved' ? ( - + ) : ( - + )}
); diff --git a/src/app/admin/orgs/page.tsx b/src/app/admin/clubs/page.tsx similarity index 51% rename from src/app/admin/orgs/page.tsx rename to src/app/admin/clubs/page.tsx index d2fc79b8..c6558454 100644 --- a/src/app/admin/orgs/page.tsx +++ b/src/app/admin/clubs/page.tsx @@ -1,11 +1,11 @@ -import OrgTable from '@src/components/admin/OrgTable'; +import ClubTable from '@src/components/admin/ClubTable'; import { api } from '@src/trpc/server'; export default async function Page() { - const clubs = await api.admin.allOrgs(); + const clubs = await api.admin.allClubs(); return (
- +
); } diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index ba693fa0..372a0741 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -8,10 +8,10 @@ export default function Page() {
- Manage Orgs + Manage Clubs { +const ClubPage = async ({ params }: { params: { id: string } }) => { const club = await api.club.getDirectoryInfo({ id: params.id }); if (!club) return ; @@ -16,15 +16,15 @@ const OrganizationPage = async ({ params }: { params: { id: string } }) => {
- - - + + +
); }; -export default OrganizationPage; +export default ClubPage; export async function generateMetadata({ params, diff --git a/src/components/CreateContactSelector.tsx b/src/app/directory/create/CreateContactSelector.tsx similarity index 99% rename from src/components/CreateContactSelector.tsx rename to src/app/directory/create/CreateContactSelector.tsx index cfd09ed7..2d0735c5 100644 --- a/src/components/CreateContactSelector.tsx +++ b/src/app/directory/create/CreateContactSelector.tsx @@ -16,7 +16,7 @@ import { Website, Youtube, type logoProps, -} from './ContactIcons'; +} from '@src/icons/ContactIcons'; import { type Control, type UseFormRegister, diff --git a/src/components/OfficerSelector.tsx b/src/app/directory/create/OfficerSelector.tsx similarity index 97% rename from src/components/OfficerSelector.tsx rename to src/app/directory/create/OfficerSelector.tsx index 230828fa..05c07ef5 100644 --- a/src/components/OfficerSelector.tsx +++ b/src/app/directory/create/OfficerSelector.tsx @@ -7,7 +7,7 @@ import { type FieldErrors, } from 'react-hook-form'; import { type z } from 'zod'; -import { UserSearchBar } from './SearchBar'; +import { UserSearchBar } from '@src/components/searchBar/UserSearchBar'; type OfficerSelectorProps = { control: Control>; diff --git a/src/app/directory/create/createForm.tsx b/src/app/directory/create/createForm.tsx index b9342196..e9c89543 100644 --- a/src/app/directory/create/createForm.tsx +++ b/src/app/directory/create/createForm.tsx @@ -1,8 +1,8 @@ 'use client'; /* eslint-disable @typescript-eslint/no-misused-promises */ import { zodResolver } from '@hookform/resolvers/zod'; -import ContactSelector from '@src/components/CreateContactSelector'; -import OfficerSelector from '@src/components/OfficerSelector'; +import ContactSelector from '@src/app/directory/create/CreateContactSelector'; +import OfficerSelector from '@src/app/directory/create/OfficerSelector'; import { api } from '@src/trpc/react'; import { createClubSchema } from '@src/utils/formSchemas'; import { useRouter } from 'next/navigation'; diff --git a/src/app/directory/create/page.tsx b/src/app/directory/create/page.tsx index da5b2791..819bc121 100644 --- a/src/app/directory/create/page.tsx +++ b/src/app/directory/create/page.tsx @@ -1,4 +1,4 @@ -import Header from '@src/components/BaseHeader'; +import Header from '@src/components/header/BaseHeader'; import CreateClubForm from './createForm'; import { getServerAuthSession } from '@src/server/auth'; import { redirect } from 'next/navigation'; diff --git a/src/app/directory/search/ClubSearch.tsx b/src/app/directory/search/ClubSearch.tsx new file mode 100644 index 00000000..3845275f --- /dev/null +++ b/src/app/directory/search/ClubSearch.tsx @@ -0,0 +1,39 @@ +'use client'; +import { api } from '@src/trpc/react'; +import type { SelectClub as Club } from '@src/server/db/models'; +import { type Session } from 'next-auth'; +import ClubCard from '@src/components/club/ClubCard'; + +interface ClubSearchComponentProps { + userSearch: string; + session: Session | null; +} + +export const ClubSearchComponent = ({ + userSearch, + session, +}: ClubSearchComponentProps) => { + const { data } = api.club.byNameNoLimit.useQuery( + { name: userSearch }, + { enabled: !!userSearch }, + ); + + if (!data) { + return

; + } + if (data.length === 0) { + return ( +

+ No Search Results Found +
+ ); + } + + return ( +
+ {data.map((club: Club) => ( + + ))} +
+ ); +}; diff --git a/src/app/directory/search/page.tsx b/src/app/directory/search/page.tsx new file mode 100644 index 00000000..8542f9b8 --- /dev/null +++ b/src/app/directory/search/page.tsx @@ -0,0 +1,24 @@ +import Header from '@src/components/header/BaseHeader'; +import { ClubSearchComponent } from './ClubSearch'; +import { getServerAuthSession } from '@src/server/auth'; + +type Params = { + searchParams: { [key: string]: string | undefined }; +}; + +const clubSearch = async (props: Params) => { + const { searchParams } = props; + const userSearch = searchParams['search'] || ''; + const session = await getServerAuthSession(); + + return ( +
+
+
+ +
+
+ ); +}; + +export default clubSearch; diff --git a/src/components/RegisterButton.tsx b/src/app/event/[id]/RegisterButton.tsx similarity index 100% rename from src/components/RegisterButton.tsx rename to src/app/event/[id]/RegisterButton.tsx diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 405c6452..9943eb68 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -1,4 +1,4 @@ -import { EventHeader } from '@src/components/BaseHeader'; +import { EventHeader } from '@src/components/header/BaseHeader'; import { db } from '@src/server/db'; import { and, eq } from 'drizzle-orm'; import { type Metadata } from 'next'; @@ -8,7 +8,7 @@ import Image from 'next/image'; import CountdownTimer from './CountdownTimer'; import Link from 'next/link'; import { getServerAuthSession } from '@src/server/auth'; -import RegisterButton from '@src/components/RegisterButton'; +import RegisterButton from '@src/app/event/[id]/RegisterButton'; type Params = { params: { id: string } }; diff --git a/src/app/events/eventView.tsx b/src/app/events/eventView.tsx index dfaed368..49493e86 100644 --- a/src/app/events/eventView.tsx +++ b/src/app/events/eventView.tsx @@ -1,75 +1,33 @@ -'use server'; -import { GridIcon, ListIcon } from '@src/icons/Icons'; -import EventCard from '@src/components/events/EventCard'; -import EventSidebar from '@src/components/events/EventSidebar'; -import { type RouterOutputs } from '@src/trpc/shared'; -import Link from 'next/link'; +'use client'; +import DateBrowser from '@src/components/events/DateBrowser'; +import { type eventParamsSchema } from '@src/utils/eventFilter'; +import useSyncedSearchParams from '@src/utils/useSyncedSearchParams'; +import { type ReactNode } from 'react'; type Props = { - events: RouterOutputs['event']['findByFilters']['events']; - params: Record; + children: ReactNode; + searchParams: eventParamsSchema; }; -const EventView = ({ events, params }: Props) => { - const view = (params?.view ?? 'list') as 'list' | 'grid'; - +const EventView = ({ children, searchParams }: Props) => { + const [params, setParams] = useSyncedSearchParams(searchParams, '/events'); return (
-
-

Events

-
- -
- -
-

List view

- - -
- -
-

Grid view

- +
+

+ Events +

+
+
-
- +
- {events.map((event) => { - return ; - })} + {children}
diff --git a/src/app/events/page.tsx b/src/app/events/page.tsx index bb5935e2..79bc45dd 100644 --- a/src/app/events/page.tsx +++ b/src/app/events/page.tsx @@ -1,27 +1,10 @@ -import { EventHeader } from '@src/components/BaseHeader'; -import { type filterState } from '@src/components/events/EventSidebar'; +import { EventHeader } from '@src/components/header/BaseHeader'; import { api } from '@src/trpc/server'; -import { type z } from 'zod'; -import { type findByFilterSchema } from '@src/server/api/routers/event'; import EventView from './eventView'; import { type Metadata } from 'next'; +import { eventParamsSchema } from '@src/utils/eventFilter'; +import EventCard from '@src/components/events/EventCard'; -function getStartTime( - filterState: filterState, -): z.infer['startTime'] { - switch (filterState.filter) { - case 'Upcoming Events': - return { type: 'now' }; - case 'Last weeks events': - return { type: 'distance', options: { days: -7 } }; - case 'Last month events': - return { type: 'distance', options: { days: -30 } }; - case 'pick': - return filterState.date - ? { type: 'range', options: filterState.date } - : { type: 'now' }; - } -} export const metadata: Metadata = { title: 'Events - Jupiter', description: 'Get connected on campus.', @@ -33,48 +16,23 @@ export const metadata: Metadata = { description: 'Get connected on campus.', }, }; -type searchPams = Partial< - Omit & { - date: string | string[] | undefined; - clubs: string | string[] | undefined; - view: 'list' | 'grid' | undefined; - } ->; -const Events = async ({ searchParams }: { searchParams: searchPams }) => { - const filters = { - filter: searchParams.filter ?? 'Upcoming Events', - date: - searchParams.filter === 'pick' - ? searchParams.date - ? Array.isArray(searchParams.date) - ? { - from: searchParams.date[0] - ? new Date(Number.parseInt(searchParams.date[0])) - : undefined, - to: searchParams.date[1] - ? new Date(Number.parseInt(searchParams.date[1])) - : undefined, - } - : { from: new Date(Number.parseInt(searchParams.date)) } - : undefined - : undefined, - clubs: searchParams.clubs - ? Array.isArray(searchParams.clubs) - ? searchParams.clubs - : [searchParams.clubs] - : [], - order: searchParams.order ?? 'soon', - types: searchParams.types ?? [], - }; - const { events } = await api.event.findByFilters({ - startTime: getStartTime(filters), - club: filters.clubs, - order: filters.order, +const Events = async ({ + searchParams, +}: { + searchParams: (typeof eventParamsSchema)['_input']; +}) => { + const parsed = eventParamsSchema.parse(searchParams); + const { events } = await api.event.findByDate({ + date: parsed.date, }); return (
- + + {events.map((event) => { + return ; + })} +
); }; diff --git a/src/app/feedback/page.tsx b/src/app/feedback/page.tsx index 38feaa5d..069ed2f9 100644 --- a/src/app/feedback/page.tsx +++ b/src/app/feedback/page.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import Header from '@src/components/BaseHeader'; +import Header from '@src/components/header/BaseHeader'; import { type Metadata } from 'next'; import Form from '@src/app/feedback/Form'; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 504ac436..52a741a0 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -4,10 +4,10 @@ import { Inter } from 'next/font/google'; import { headers } from 'next/headers'; import { TRPCReactProvider } from '@src/trpc/react'; -import Sidebar from '@src/components/Sidebar'; +import Sidebar from '@src/components/nav/Sidebar'; import { type Metadata } from 'next'; -import { Analytics } from '@vercel/analytics/react'; +import { GoogleAnalytics } from '@next/third-parties/google'; const inter = Inter({ subsets: ['latin'], @@ -48,7 +48,7 @@ export default function RootLayout({
{children}
- + ); diff --git a/src/app/manage/[clubId]/(dashboard)/layout.tsx b/src/app/manage/[clubId]/(dashboard)/layout.tsx index 6879ec2b..478e2375 100644 --- a/src/app/manage/[clubId]/(dashboard)/layout.tsx +++ b/src/app/manage/[clubId]/(dashboard)/layout.tsx @@ -1,5 +1,5 @@ -import Header from '@src/components/BaseHeader'; -import BackButton from '@src/components/BlueBackButton'; +import Header from '@src/components/header/BaseHeader'; +import { BlueBackButton } from '@src/components/backButton'; import { getServerAuthSession } from '@src/server/auth'; import { api } from '@src/trpc/server'; import { signInRoute } from '@src/utils/redirect'; @@ -30,7 +30,7 @@ const Layout = async ({
- +

{club.name}

diff --git a/src/app/manage/[clubId]/create/CreateEventForm.tsx b/src/app/manage/[clubId]/create/CreateEventForm.tsx index 70168b22..bd09638c 100644 --- a/src/app/manage/[clubId]/create/CreateEventForm.tsx +++ b/src/app/manage/[clubId]/create/CreateEventForm.tsx @@ -1,130 +1,199 @@ -'use client' +'use client'; -import { useEffect, useState } from "react"; -import { type SelectClub } from "@src/server/db/models"; -import { createEventSchema } from "@src/utils/formSchemas"; -import { useForm } from "react-hook-form"; -import { api } from "@src/trpc/react"; -import { type z } from "zod"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { useRouter } from "next/navigation"; -import { UploadIcon } from "@src/icons/Icons"; -import EventCardPreview from "./EventCardPreview"; -import TimeSelect from "./TimeSelect"; -import { type RouterOutputs } from "@src/trpc/shared"; +import { useEffect, useState } from 'react'; +import { type SelectClub } from '@src/server/db/models'; +import { createEventSchema } from '@src/utils/formSchemas'; +import { useForm } from 'react-hook-form'; +import { api } from '@src/trpc/react'; +import { type z } from 'zod'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { useRouter } from 'next/navigation'; +import { UploadIcon } from '@src/icons/Icons'; +import EventCardPreview from './EventCardPreview'; +import TimeSelect from './TimeSelect'; +import { type RouterOutputs } from '@src/trpc/shared'; -const CreateEventForm = ({ clubId, officerClubs }: { clubId: string, officerClubs: SelectClub[]}) => { - const { - register, - handleSubmit, - watch, - setValue, - getValues, - } = useForm>({ - resolver: zodResolver(createEventSchema), - defaultValues: { - clubId: clubId, - }, - mode: "onSubmit", - }); - const router = useRouter(); - const [watchDescription, watchStartTime] = watch(['description', 'startTime']); - const [eventPreview, setEventPreview] = useState({ - name: "", - clubId, - description: "", - location: "", - liked: false, - id: "", - startTime: new Date(Date.now()), - endTime: new Date(Date.now()), - club: officerClubs.filter((v) => v.id == clubId)[0]!, - }); - useEffect(() => { - const subscription = watch((data, info) => { - const { name, clubId, description, location, startTime, endTime } = data; - const club = officerClubs.find((val) => val.id == data.clubId); - if (club) { - setEventPreview({ - name: name || "", - clubId: clubId || "", - description: description || "", - location: location || "", - liked: false, - id: "", - startTime: startTime?.toString() === "" || startTime == undefined ? new Date(Date.now()) : new Date(startTime), - endTime: endTime?.toString() === "" || endTime?.toString() == "Invalid Date" || !endTime ? new Date(Date.now()) : new Date(endTime), - club, - }); - } - if (info.name == "clubId") { - router.replace(`/manage/${data.clubId}/create`); - } - }); - return () => subscription.unsubscribe(); - }, [router, watch, officerClubs]); +const CreateEventForm = ({ + clubId, + officerClubs, +}: { + clubId: string; + officerClubs: SelectClub[]; +}) => { + const { register, handleSubmit, watch, setValue, getValues, control } = + useForm>({ + resolver: zodResolver(createEventSchema), + defaultValues: { + clubId: clubId, + }, + mode: 'onSubmit', + }); + const router = useRouter(); + const [watchDescription, watchStartTime] = watch([ + 'description', + 'startTime', + ]); + const [loading, setLoading] = useState(false); + const [eventPreview, setEventPreview] = useState< + RouterOutputs['event']['findByFilters']['events'][number] + >({ + name: '', + clubId, + description: '', + location: '', + liked: false, + id: '', + startTime: new Date(Date.now()), + endTime: new Date(Date.now()), + club: officerClubs.filter((v) => v.id == clubId)[0]!, + }); + useEffect(() => { + const subscription = watch((data, info) => { + const { name, clubId, description, location, startTime, endTime } = data; + const club = officerClubs.find((val) => val.id == data.clubId); + if (club) { + setEventPreview({ + name: name || '', + clubId: clubId || '', + description: description || '', + location: location || '', + liked: false, + id: '', + startTime: + startTime?.toString() === '' || startTime === undefined + ? new Date(Date.now()) + : new Date(startTime), + endTime: + endTime?.toString() === '' || + endTime?.toString() === 'Invalid Date' || + !endTime + ? new Date(Date.now()) + : new Date(endTime), + club, + }); + } + if (info.name == 'clubId') { + router.replace(`/manage/${data.clubId}/create`); + } + }); + return () => subscription.unsubscribe(); + }, [router, watch, officerClubs]); - const createMutation = api.event.create.useMutation({ - onSuccess: () => { location.reload(); } - }) + const createMutation = api.event.create.useMutation({ + onSuccess: (data) => { + if (data) { + router.push(`/event/${data}`); + } + }, + onError: () => { + setLoading(false); + }, + }); - const onSubmit = handleSubmit((data: z.infer) => { - if (!createMutation.isPending) { - createMutation.mutate(data); - } - }); + const onSubmit = handleSubmit((data: z.infer) => { + if (!createMutation.isPending && !loading) { + setLoading(true); + createMutation.mutate(data); + } + }); - return (
void onSubmit(e)} className="w-full flex flex-row flex-wrap justify-start gap-10 overflow-x-clip text-[#4D5E80] pb-4"> -
-
- Create Club Event for -
- -
-
-
-

Event Picture

-

Drag or choose file to upload

-
- -

JPEG, PNG, or SVG

-
-
-
-

Event Details

-
- - -
-
- - -
-
-
- -

{watchDescription && watchDescription.length} of 1000 Characters used

-
-