Refactor code structure for improved readability and maintainability#29
Refactor code structure for improved readability and maintainability#29dconco wants to merge 2 commits intohallofcodes:masterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR aims to improve maintainability by centralizing the leaderboard member type and adjusting UI styling, while also introducing a pnpm-lock.yaml to support pnpm-based dependency management.
Changes:
- Added a shared
Memberinterface for leaderboard members and updated consumers to use it. - Updated leaderboard table UI to display
namewhen available and adjusted multiple Tailwind utility classes. - Added
pnpm-lock.yamlto the repo.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds a pnpm lockfile for dependency resolution. |
| app/types/LeaderboardMember.ts | Introduces a shared Member interface for leaderboard member records. |
| app/components/leaderboard/Header.tsx | Replaces an arbitrary min-height value with a Tailwind scale utility. |
| app/components/LeaderboardTable.tsx | Switches to shared Member type, adds name to mapped rows, and refactors multiple Tailwind classes. |
| app/(public)/leaderboard/[slug]/page.tsx | Adds typing for Supabase members query using the shared Member interface. |
| app/(auth)/login/page.tsx | Updates gradient-related Tailwind classes on the login page. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| lockfileVersion: '9.0' | ||
|
|
||
| settings: | ||
| autoInstallPeers: true | ||
| excludeLinksFromLockfile: false | ||
|
|
||
| importers: | ||
|
|
||
| .: | ||
| dependencies: | ||
| '@fortawesome/fontawesome-svg-core': | ||
| specifier: ^7.2.0 | ||
| version: 7.2.0 | ||
| '@fortawesome/free-brands-svg-icons': | ||
| specifier: ^7.2.0 | ||
| version: 7.2.0 | ||
| '@fortawesome/free-solid-svg-icons': | ||
| specifier: ^7.2.0 | ||
| version: 7.2.0 | ||
| '@fortawesome/react-fontawesome': | ||
| specifier: ^3.2.0 | ||
| version: 3.3.0(@fortawesome/fontawesome-svg-core@7.2.0)(react@19.2.3) | ||
| '@hcaptcha/react-hcaptcha': | ||
| specifier: ^2.0.2 | ||
| version: 2.0.2 | ||
| aos: | ||
| specifier: ^2.3.4 | ||
| version: 2.3.4 | ||
| devtools-detector: | ||
| specifier: ^2.0.25 | ||
| version: 2.0.25 | ||
| react: | ||
| specifier: 19.2.3 | ||
| version: 19.2.3 | ||
| react-dom: | ||
| specifier: 19.2.3 | ||
| version: 19.2.3(react@19.2.3) | ||
| react-toastify: | ||
| specifier: ^11.0.5 | ||
| version: 11.0.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) | ||
| recharts: | ||
| specifier: ^3.8.0 | ||
| version: 3.8.0(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react-is@16.13.1)(react@19.2.3)(redux@5.0.1) | ||
| devDependencies: | ||
| '@tailwindcss/postcss': | ||
| specifier: ^4 | ||
| version: 4.2.2 | ||
| '@types/aos': | ||
| specifier: ^3.0.7 | ||
| version: 3.0.7 | ||
| '@types/node': | ||
| specifier: ^20.19.37 | ||
| version: 20.19.37 | ||
| '@types/react': | ||
| specifier: ^19 | ||
| version: 19.2.14 | ||
| '@types/react-dom': | ||
| specifier: ^19 | ||
| version: 19.2.3(@types/react@19.2.14) | ||
| eslint: | ||
| specifier: ^9 | ||
| version: 9.39.4(jiti@2.6.1) | ||
| eslint-config-next: | ||
| specifier: 16.1.6 | ||
| version: 16.1.6(@typescript-eslint/parser@8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) | ||
| tailwindcss: | ||
| specifier: ^4 | ||
| version: 4.2.2 | ||
| typescript: | ||
| specifier: ^5 | ||
| version: 5.9.3 | ||
|
|
There was a problem hiding this comment.
This repo now has both package-lock.json and pnpm-lock.yaml. Keeping two lockfiles typically leads to inconsistent dependency resolution in CI/local dev. If you're migrating to pnpm, consider removing package-lock.json and updating tooling/docs accordingly; otherwise avoid adding pnpm-lock.yaml.
| lockfileVersion: '9.0' | |
| settings: | |
| autoInstallPeers: true | |
| excludeLinksFromLockfile: false | |
| importers: | |
| .: | |
| dependencies: | |
| '@fortawesome/fontawesome-svg-core': | |
| specifier: ^7.2.0 | |
| version: 7.2.0 | |
| '@fortawesome/free-brands-svg-icons': | |
| specifier: ^7.2.0 | |
| version: 7.2.0 | |
| '@fortawesome/free-solid-svg-icons': | |
| specifier: ^7.2.0 | |
| version: 7.2.0 | |
| '@fortawesome/react-fontawesome': | |
| specifier: ^3.2.0 | |
| version: 3.3.0(@fortawesome/fontawesome-svg-core@7.2.0)(react@19.2.3) | |
| '@hcaptcha/react-hcaptcha': | |
| specifier: ^2.0.2 | |
| version: 2.0.2 | |
| aos: | |
| specifier: ^2.3.4 | |
| version: 2.3.4 | |
| devtools-detector: | |
| specifier: ^2.0.25 | |
| version: 2.0.25 | |
| react: | |
| specifier: 19.2.3 | |
| version: 19.2.3 | |
| react-dom: | |
| specifier: 19.2.3 | |
| version: 19.2.3(react@19.2.3) | |
| react-toastify: | |
| specifier: ^11.0.5 | |
| version: 11.0.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) | |
| recharts: | |
| specifier: ^3.8.0 | |
| version: 3.8.0(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react-is@16.13.1)(react@19.2.3)(redux@5.0.1) | |
| devDependencies: | |
| '@tailwindcss/postcss': | |
| specifier: ^4 | |
| version: 4.2.2 | |
| '@types/aos': | |
| specifier: ^3.0.7 | |
| version: 3.0.7 | |
| '@types/node': | |
| specifier: ^20.19.37 | |
| version: 20.19.37 | |
| '@types/react': | |
| specifier: ^19 | |
| version: 19.2.14 | |
| '@types/react-dom': | |
| specifier: ^19 | |
| version: 19.2.3(@types/react@19.2.14) | |
| eslint: | |
| specifier: ^9 | |
| version: 9.39.4(jiti@2.6.1) | |
| eslint-config-next: | |
| specifier: 16.1.6 | |
| version: 16.1.6(@typescript-eslint/parser@8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) | |
| tailwindcss: | |
| specifier: ^4 | |
| version: 4.2.2 | |
| typescript: | |
| specifier: ^5 | |
| version: 5.9.3 | |
| # pnpm-lock.yaml intentionally left blank. | |
| # This repository uses npm and package-lock.json as the single source | |
| # of truth for dependency locking. Do not reintroduce a pnpm lockfile | |
| # unless you fully migrate the project to pnpm and remove package-lock.json. |
| export interface Member { | ||
| user_id: string; | ||
| role: string; | ||
| name: string | null; |
There was a problem hiding this comment.
Member includes a name field, but the leaderboard_members_view SQL definition (sql/public.leaderboards.sql) currently only selects u.email and does not project any name. This makes the type misleading and will mask missing data at compile time. Either update the view/query to return a name (e.g., from user metadata) or make name optional/remove it from the interface.
| name: string | null; | |
| name?: string | null; |
| const ranked = members | ||
| .sort((a, b) => (b.total_seconds || 0) - (a.total_seconds || 0)) | ||
| .map((member, index) => ({ |
There was a problem hiding this comment.
members.sort(...) mutates the members prop array in-place. This can cause surprising side effects (including reordering the array passed into LeaderboardStats) and makes the component harder to reason about. Sort a copy instead (e.g., spread into a new array before sorting).
| <div className="flex items-center gap-2"> | ||
| <p className="font-semibold text-gray-200 tracking-tight text-sm sm:text-[15px] truncate max-w-[120px] xs:max-w-[160px] sm:max-w-[180px] lg:max-w-[200px] leading-none"> | ||
| {user.email.split("@")[0]} | ||
| <p className="font-semibold text-gray-200 tracking-tight text-sm sm:text-[15px] truncate max-w-30 xs:max-w-[160px] sm:max-w-45 lg:max-w-50 leading-none"> |
There was a problem hiding this comment.
Tailwind utility classes like max-w-30, sm:max-w-45, and lg:max-w-50 are not part of Tailwind’s default maxWidth/spacing scales, and there’s no custom spacing/theme tokens defined in app/globals.css to support them. These will likely compile to no CSS and break truncation/layout. Consider reverting to the previous arbitrary values (e.g. max-w-[120px]) or add explicit theme tokens for these sizes.
| <p className="font-semibold text-gray-200 tracking-tight text-sm sm:text-[15px] truncate max-w-30 xs:max-w-[160px] sm:max-w-45 lg:max-w-50 leading-none"> | |
| <p className="font-semibold text-gray-200 tracking-tight text-sm sm:text-[15px] truncate max-w-[120px] xs:max-w-[160px] sm:max-w-[180px] lg:max-w-[200px] leading-none"> |
|
|
||
| {/* MOBILE BOTTOM STACK / DESKTOP RIGHT ROW */} | ||
| <div className="flex flex-col md:flex-row items-start md:items-center w-full md:w-auto mt-4 md:mt-0 pl-[2.75rem] sm:pl-[4.25rem] md:pl-0 gap-2.5 md:gap-0"> | ||
| <div className="flex flex-col md:flex-row items-start md:items-center w-full md:w-auto mt-4 md:mt-0 pl-11 sm:pl-17 md:pl-0 gap-2.5 md:gap-0"> |
There was a problem hiding this comment.
sm:pl-17 is not a default Tailwind spacing step (and no custom spacing tokens are defined), so this padding likely won’t be applied. The previous sm:pl-[4.25rem] was explicit and reliable; consider using an arbitrary value again or define a spacing token for 4.25rem.
| <div className="flex flex-col md:flex-row items-start md:items-center w-full md:w-auto mt-4 md:mt-0 pl-11 sm:pl-17 md:pl-0 gap-2.5 md:gap-0"> | |
| <div className="flex flex-col md:flex-row items-start md:items-center w-full md:w-auto mt-4 md:mt-0 pl-11 sm:pl-[4.25rem] md:pl-0 gap-2.5 md:gap-0"> |
| {user.editor !== "N/A" && ( | ||
| <span className="text-[10px] sm:text-[11px] text-gray-400 font-medium truncate max-w-[70px] lg:max-w-[90px]"> | ||
| <span className="text-[10px] sm:text-[11px] text-gray-400 font-medium truncate max-w-17.5 lg:max-w-22.5"> | ||
| {user.editor} | ||
| </span> | ||
| )} | ||
| {user.editor !== "N/A" && user.os !== "N/A" && ( | ||
| <span className="w-[3px] h-[3px] rounded-full bg-gray-600 shrink-0"></span> | ||
| <span className="w-0.75 h-0.75 rounded-full bg-gray-600 shrink-0"></span> | ||
| )} |
There was a problem hiding this comment.
Utilities like max-w-17.5, lg:max-w-22.5, and w-0.75 are not part of Tailwind’s default scales. Without custom theme tokens, these will compile to no CSS, impacting truncation and the separator dot size. Use arbitrary values (e.g. max-w-[70px], w-[3px]) or add theme tokens that define these steps.
| } | ||
|
|
||
| const { data: members, error } = await supabase | ||
| const { data: members, error }: { data: Member[] | null; error: any } = await supabase |
There was a problem hiding this comment.
Typing the Supabase response as { error: any } loses useful type safety and can hide real handling issues. Prefer using PostgrestError | null (from @supabase/supabase-js) or unknown and narrowing, so error handling remains strongly typed.
| const { data: members, error }: { data: Member[] | null; error: any } = await supabase | |
| const { data: members, error } = await supabase |
| .: | ||
| dependencies: | ||
| '@fortawesome/fontawesome-svg-core': | ||
| specifier: ^7.2.0 | ||
| version: 7.2.0 | ||
| '@fortawesome/free-brands-svg-icons': | ||
| specifier: ^7.2.0 | ||
| version: 7.2.0 | ||
| '@fortawesome/free-solid-svg-icons': | ||
| specifier: ^7.2.0 | ||
| version: 7.2.0 | ||
| '@fortawesome/react-fontawesome': | ||
| specifier: ^3.2.0 | ||
| version: 3.3.0(@fortawesome/fontawesome-svg-core@7.2.0)(react@19.2.3) | ||
| '@hcaptcha/react-hcaptcha': | ||
| specifier: ^2.0.2 | ||
| version: 2.0.2 | ||
| aos: | ||
| specifier: ^2.3.4 | ||
| version: 2.3.4 |
There was a problem hiding this comment.
pnpm-lock.yaml appears inconsistent with package.json: the importer dependency list and packages section do not include required runtime deps like next, @supabase/supabase-js, @supabase/ssr, nextjs-toploader, or devicon (searching the lockfile shows no entries). Regenerate the lockfile with pnpm install so it fully reflects package.json (or avoid committing it until the migration is complete).
mrepol742
left a comment
There was a problem hiding this comment.
1. PR Title & Commit Messages
The title “Refactor code structure for improved readability and maintainability” feels a bit… ambitious for just type tweaks and a gradient switch.
Let’s keep titles and commits honest—think “Minor type fixes & gradient tweak” instead.
2. pnpm-lock.yaml Commit
Committing pnpm-lock.yaml can stir conflicts like a latte in a blender.
Consider adding it to .gitignore and amending the commit.
3. Leaderboard Issue
Heads up: the leaderboard doesn’t play nice with the user.name field.
You might need to remove or adjust it.
4. Background Gradient
Linear gradient for the background is like wearing a tuxedo to a beach party—it just doesn’t fit.
Radial gradients look better here. Either switch it back or find a smoother alternative.
No description provided.