From 4f90108165994b38310123e481a8ab44d9857daf Mon Sep 17 00:00:00 2001 From: jacoblurie29 Date: Sat, 28 Oct 2023 18:33:23 -0500 Subject: [PATCH] Rotating leaderboard display --- components/hacker/Leaderboard.tsx | 37 ++++++++++++++++-- next.config.js | 6 +++ package.json | 5 +++ pages/api/leaderboard.ts | 4 +- pages/event.tsx | 2 +- yarn.lock | 63 +++++++++++++++++++++---------- 6 files changed, 91 insertions(+), 26 deletions(-) diff --git a/components/hacker/Leaderboard.tsx b/components/hacker/Leaderboard.tsx index 1174fa2a..00fb137f 100644 --- a/components/hacker/Leaderboard.tsx +++ b/components/hacker/Leaderboard.tsx @@ -1,19 +1,46 @@ import { UserData, TeamData } from '../../types/database'; import { RequestType, useCustomSWR } from '../../utils/request-utils'; import styles from '../../styles/hacker/Table.module.css'; +import { useEffect, useState } from 'react'; interface LeaderboardData extends Omit { team: TeamData; } -const Leaderboard = () => { +const Leaderboard = ({ limit = 10, isRotating = false }: { limit?: number; isRotating?: boolean }) => { + const [currentPage, setCurrentPage] = useState(1); + const [totalPages, setTotalPages] = useState(1); + const [currentLeaderboardData, setCurrentLeaderboardData] = useState(undefined); + // Leaderboard data const { data: leaderboardData, error: leaderboardError } = useCustomSWR({ - url: '/api/leaderboard', + url: `/api/leaderboard?limit=${limit}`, method: RequestType.GET, errorMessage: 'Failed to get list of hackers on the leaderboard.', }); + // start a timer that updates the leaderboard every 5 seconds + useEffect(() => { + if (isRotating) { + const interval = setInterval(() => { + if (currentPage === totalPages) { + setCurrentPage(1); + } else { + setCurrentPage(currentPage + 1); + } + }, 5000); + + return () => clearInterval(interval); + } + }, [currentPage, isRotating, totalPages]); + + useEffect(() => { + if (leaderboardData) { + setCurrentLeaderboardData(leaderboardData.slice((currentPage - 1) * 10, currentPage * 10)); + setTotalPages(Math.floor(leaderboardData.length / 15)); + } + }, [leaderboardData, currentPage]); + return (
Points Leaderboard @@ -22,21 +49,23 @@ const Leaderboard = () => {
{leaderboardError ? (
Failed to load data.
- ) : !leaderboardData ? ( + ) : !currentLeaderboardData ? (
Loading...
) : (
+ - {leaderboardData?.map(entry => ( + {currentLeaderboardData?.map((entry, index) => ( + diff --git a/next.config.js b/next.config.js index b861f178..feeb57c2 100644 --- a/next.config.js +++ b/next.config.js @@ -12,6 +12,12 @@ module.exports = { ); } + // add fallback + config.resolve.fallback = { + child_process: false, + fs: false, + }; + return config; }, experimental: { nftTracing: true }, diff --git a/package.json b/package.json index 7f9ae2a8..a7127af8 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@types/prompt-sync": "^4.2.2", "antd": "^5.9.4", "copy-webpack-plugin": "^11.0.0", + "cron": "^3.1.5", "csv-writer": "^1.6.0", "dayjs": "^1.11.10", "dotenv": "^16.0.2", @@ -49,6 +50,7 @@ "@types/faker": "^5.5.8", "@types/luxon": "^3.0.1", "@types/mongodb": "^4.0.7", + "@types/node-cron": "^3.0.10", "@types/react": "17.0.43", "@types/react-highlight-words": "^0.16.4", "eslint": "8.24.0", @@ -58,5 +60,8 @@ "prettier": "^2.6.2", "typescript": "4.8.3", "typescript-plugin-css-modules": "^5.0.1" + }, + "browser": { + "child_process": false } } diff --git a/pages/api/leaderboard.ts b/pages/api/leaderboard.ts index 20ab7b3f..bdeb3475 100644 --- a/pages/api/leaderboard.ts +++ b/pages/api/leaderboard.ts @@ -12,9 +12,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< await dbConnect(); switch (req.method) { case 'GET': + const limit = parseInt(req.query.limit as string) || 10; + const users = await User.find({ nfcPoints: { $exists: true } }) .sort({ nfcPoints: -1 }) - .limit(10) + .limit(limit) .populate('team') .select('name nfcPoints team'); diff --git a/pages/event.tsx b/pages/event.tsx index 4a2504d8..0a2762b0 100644 --- a/pages/event.tsx +++ b/pages/event.tsx @@ -184,7 +184,7 @@ const EventScreen = () => {
- +
) : ( diff --git a/yarn.lock b/yarn.lock index a219705c..ebc7f26a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1249,7 +1249,7 @@ "@inquirer/checkbox@^1.4.0": version "1.4.0" - resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-1.4.0.tgz#9e583188be55f22ed624d2829421a3354d3d8c1a" + resolved "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-1.4.0.tgz" integrity sha512-7YcekwCvMTjrgjUursrH6AGZUSPw7gKPMvp0VhM3iq9mL46a7AeCfOTQTW0UPeiIfWmZK8wHyAD6wIhfDyLHpw== dependencies: "@inquirer/core" "^5.1.0" @@ -1260,7 +1260,7 @@ "@inquirer/confirm@^2.0.14": version "2.0.14" - resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-2.0.14.tgz#b87fcdf218d0ce687bd021623e091d3a80744e9e" + resolved "https://registry.npmjs.org/@inquirer/confirm/-/confirm-2.0.14.tgz" integrity sha512-Elzo5VX5lO1q9xy8CChDtDQNVLaucufdZBAM12qdfX1L3NQ+TypnZytGmWDXHBTpBTwuhEuwxNvUw7B0HCURkw== dependencies: "@inquirer/core" "^5.1.0" @@ -1269,7 +1269,7 @@ "@inquirer/core@^5.1.0": version "5.1.0" - resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-5.1.0.tgz#2e3f6abf1dee93eae60cd85a5168c52400f73c9c" + resolved "https://registry.npmjs.org/@inquirer/core/-/core-5.1.0.tgz" integrity sha512-EVnific72BhMOMo8mElvrYhGFWJZ73X6j0I+fITIPTsdAz6Z9A3w3csKy+XaH87/5QAEIQHR7RSCVXvQpIqNdQ== dependencies: "@inquirer/type" "^1.1.5" @@ -1289,7 +1289,7 @@ "@inquirer/editor@^1.2.12": version "1.2.12" - resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-1.2.12.tgz#3dfa72253e8a9d915b43f3c8dbc8df85e3c627ff" + resolved "https://registry.npmjs.org/@inquirer/editor/-/editor-1.2.12.tgz" integrity sha512-Y7zXQqcglPbbPkx0DPwx6HQFstJR5uex4hoQprjpdxSj8+Bf04+Og6mK/FNxoQbPvoNecegtmMGxDC+hVcMJZA== dependencies: "@inquirer/core" "^5.1.0" @@ -1299,7 +1299,7 @@ "@inquirer/expand@^1.1.13": version "1.1.13" - resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-1.1.13.tgz#921d36274c0b143f7bf6cefb42f002be9cd1646f" + resolved "https://registry.npmjs.org/@inquirer/expand/-/expand-1.1.13.tgz" integrity sha512-/+7CGCa7iyJIpli0NtukEAjSI7+wGgjYzsByLVSSAk3U696ZlCCP6iPtsWx6d1qfmaMmCzejcjylOj6OAeu4bA== dependencies: "@inquirer/core" "^5.1.0" @@ -1309,7 +1309,7 @@ "@inquirer/input@^1.2.13": version "1.2.13" - resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-1.2.13.tgz#27ee5826e2988735a78f50510c9652d2ef29e39a" + resolved "https://registry.npmjs.org/@inquirer/input/-/input-1.2.13.tgz" integrity sha512-gALuvSpZRYfqygPjlYWodMZ4TXwALvw7Pk4tRFhE1oMN79rLVlg88Z/X6JCUh+uV2qLaxxgbeP+cgPWTvuWsCg== dependencies: "@inquirer/core" "^5.1.0" @@ -1318,7 +1318,7 @@ "@inquirer/password@^1.1.13": version "1.1.13" - resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-1.1.13.tgz#b7f0a0f7feed90e01630a9df4a14eab09697fcd6" + resolved "https://registry.npmjs.org/@inquirer/password/-/password-1.1.13.tgz" integrity sha512-6STGbL4Vm6ohE2yDBOSENCpCeywnvPux5psZVpvblGDop1oPiZkdsVI+NhsA0c4BE6YT0fNVK8Oqxf5Dgt5k7g== dependencies: "@inquirer/input" "^1.2.13" @@ -1328,7 +1328,7 @@ "@inquirer/prompts@^3.0.4": version "3.2.0" - resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-3.2.0.tgz#8f4feaa81560d22e77b55c676e9296a108daf5b1" + resolved "https://registry.npmjs.org/@inquirer/prompts/-/prompts-3.2.0.tgz" integrity sha512-sfT7eDoveChXr8iIfwUYkoVBjUcKqXluhjM0EVhRhN59ZuJCc5DAdnuKwaFXomwESDoN0f+2zHy+MpxUg+EZuQ== dependencies: "@inquirer/checkbox" "^1.4.0" @@ -1343,7 +1343,7 @@ "@inquirer/rawlist@^1.2.13": version "1.2.13" - resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-1.2.13.tgz#e74f003d417add415fea8c349d186eef7cda5032" + resolved "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-1.2.13.tgz" integrity sha512-f+bASrCY2x2F90MrBYX7nUSetL6FsVLfskhGWEyVwj6VIXzc9T878z3v7KU3V10D1trWrCVHOdeqEcbnO68yhg== dependencies: "@inquirer/core" "^5.1.0" @@ -1352,7 +1352,7 @@ "@inquirer/select@^1.3.0": version "1.3.0" - resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-1.3.0.tgz#00dfa5068bea85bffeb7aa7c402407bb590c8cd4" + resolved "https://registry.npmjs.org/@inquirer/select/-/select-1.3.0.tgz" integrity sha512-3sL5odCDYI+i+piAFqFa5ULDUKEpc0U1zEY4Wm6gjP6nMAHWM8r1UzMlpQXCyHny91Tz+oeSLeKinAde0z6R7w== dependencies: "@inquirer/core" "^5.1.0" @@ -1395,7 +1395,7 @@ "@next/swc-darwin-arm64@12.2.5": version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.5.tgz#31b1c3c659d54be546120c488a1e1bad21c24a1d" + resolved "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.5.tgz" integrity sha512-VOPWbO5EFr6snla/WcxUKtvzGVShfs302TEMOtzYyWni6f9zuOetijJvVh9CCTzInnXAZMtHyNhefijA4HMYLg== "@next/swc-darwin-x64@12.2.5": @@ -1445,7 +1445,7 @@ "@next/swc-win32-x64-msvc@12.2.5": version "12.2.5" - resolved "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.5.tgz" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.5.tgz#20fed129b04a0d3f632c6d0de135345bb623b1e4" integrity sha512-7h5/ahY7NeaO2xygqVrSG/Y8Vs4cdjxIjowTZ5W6CKoTKn7tmnuxlUc2h74x06FKmbhAd9agOjr/AOKyxYYm9Q== "@nodelib/fs.scandir@2.1.5": @@ -1836,6 +1836,11 @@ resolved "https://registry.npmjs.org/@types/luxon/-/luxon-3.0.1.tgz" integrity sha512-/LAvk1cMOJt0ghzMFrZEvByUhsiEfeeT2IF53Le+Ki3A538yEL9pRZ7a6MuCxdrYK+YNqNIDmrKU/r2nnw04zQ== +"@types/luxon@~3.3.0": + version "3.3.3" + resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-3.3.3.tgz#b2e20a9536f91ab3e6e7895c91883e1a7ad49a6e" + integrity sha512-/BJF3NT0pRMuxrenr42emRUF67sXwcZCd+S1ksG/Fcf9O7C3kKCY4uJSbKBE4KDUIYr3WMsvfmWD8hRjXExBJQ== + "@types/mongodb@^4.0.7": version "4.0.7" resolved "https://registry.npmjs.org/@types/mongodb/-/mongodb-4.0.7.tgz" @@ -1845,14 +1850,19 @@ "@types/mute-stream@^0.0.2": version "0.0.2" - resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.2.tgz#5a011b17307364e48591ac6829a8e40e1c10c6b0" + resolved "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.2.tgz" integrity sha512-FpiGjk6+IOrN0lZEfUUjdra1csU1VxwYFj4S0Zj+TJpu5x5mZW30RkEZojTadrNZHNmpCHgoE62IQZAH0OeuIA== dependencies: "@types/node" "*" +"@types/node-cron@^3.0.10": + version "3.0.10" + resolved "https://registry.npmjs.org/@types/node-cron/-/node-cron-3.0.10.tgz" + integrity sha512-8thdLSpV7na8+bsmiyMH/KKQWOBg4WmoLInlGxWz7JJn8Mie+53QWaygSlc7f/AsMsCB5bBTVjoueAU6tRutTw== + "@types/node@*", "@types/node@^20.8.2": version "20.8.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.9.tgz#646390b4fab269abce59c308fc286dcd818a2b08" + resolved "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz" integrity sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg== dependencies: undici-types "~5.26.4" @@ -1873,7 +1883,7 @@ "@types/prompt-sync@^4.2.2": version "4.2.2" - resolved "https://registry.yarnpkg.com/@types/prompt-sync/-/prompt-sync-4.2.2.tgz#df2bc03694ac28f15fb3d5f64356b6e6a1243d2a" + resolved "https://registry.npmjs.org/@types/prompt-sync/-/prompt-sync-4.2.2.tgz" integrity sha512-S8GBVdrchd7egtwrWtnhzZ3mFKgwlFpOCsiemzYgd5Bg75SwR5RquDlE7G4ijPbbNtAATpdn/Km3u5PEAnTsAw== "@types/prop-types@*": @@ -2025,7 +2035,7 @@ ansi-escapes@^4.3.2: ansi-regex@^4.1.0: version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz" integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== ansi-regex@^5.0.1: @@ -2440,6 +2450,14 @@ core-js-pure@^3.20.2: resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.23.2.tgz" integrity sha512-t6u7H4Ff/yZNk+zqTr74UjCcZ3k8ApBryeLLV4rYQd9aF3gqmjjGjjR44ENfeBMH8VVvSynIjAJ0mUuFhzQtrA== +cron@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cron/-/cron-3.1.5.tgz#ccd24a6b368e03842925a45972229c6ba336a3e2" + integrity sha512-e/ivHUhSZVvF5PUqgj7dzQ96KqAhK1/peMDr5Mmfm/vEho01/O+ySJnhTBJ2JPvFEWXpjLESIJBke0ZpZ7r7FA== + dependencies: + "@types/luxon" "~3.3.0" + luxon "~3.4.0" + cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" @@ -2887,7 +2905,7 @@ external-editor@^3.1.0: faker@^6.6.6: version "6.6.6" - resolved "https://registry.yarnpkg.com/faker/-/faker-6.6.6.tgz#e9529da0109dca4c7c5dbfeaadbd9234af943033" + resolved "https://registry.npmjs.org/faker/-/faker-6.6.6.tgz" integrity sha512-9tCqYEDHI5RYFQigXFwF1hnCwcWCOJl/hmll0lr5D2Ljjb0o4wphb69wikeJDz5qCEzXCoPvG6ss5SDP6IfOdg== fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: @@ -3628,6 +3646,11 @@ luxon@^3.0.3: resolved "https://registry.npmjs.org/luxon/-/luxon-3.0.3.tgz" integrity sha512-+EfHWnF+UT7GgTnq5zXg3ldnTKL2zdv7QJgsU5bjjpbH17E3qi/puMhQyJVYuCq+FRkogvB5WB6iVvUr+E4a7w== +luxon@~3.4.0: + version "3.4.3" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.4.3.tgz#8ddf0358a9492267ffec6a13675fbaab5551315d" + integrity sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg== + make-dir@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" @@ -4155,7 +4178,7 @@ pretty-format@^3.8.0: prompt-sync@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/prompt-sync/-/prompt-sync-4.2.0.tgz#0198f73c5b70e3b03e4b9033a50540a7c9a1d7f4" + resolved "https://registry.npmjs.org/prompt-sync/-/prompt-sync-4.2.0.tgz" integrity sha512-BuEzzc5zptP5LsgV5MZETjDaKSWfchl5U9Luiu8SKp7iZWD5tZalOxvNcZRwv+d2phNFr8xlbxmFNcRKfJOzJw== dependencies: strip-ansi "^5.0.0" @@ -4917,7 +4940,7 @@ string.prototype.trimstart@^1.0.5: strip-ansi@^5.0.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" @@ -5152,7 +5175,7 @@ unbox-primitive@^1.0.2: undici-types@~5.26.4: version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== universal-github-app-jwt@^1.1.1:
Rank Name Team Points
{(currentPage - 1) * 10 + index + 1} {entry.name} {entry.team?.name} {entry.nfcPoints}