Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/bracket viewer #226

Closed
wants to merge 0 commits into from
Closed

Conversation

thornxyz
Copy link
Contributor

@thornxyz thornxyz commented Jan 8, 2025

rewritten bracket routes, changed backend schema for brackets so that rendering works.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced tournament bracket creation and management
    • Simplified bracket submission and retrieval process
  • Bug Fixes

    • Improved input validation for tournament brackets
    • Updated data model for more consistent bracket representation
  • Style

    • Added custom styling for number input fields
    • Refined layout for bracket-related components
  • Refactor

    • Streamlined API endpoints for brackets
    • Modernized module syntax and component structure

Copy link

vercel bot commented Jan 8, 2025

@thornxyz is attempting to deploy a commit to the blaze's projects Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

coderabbitai bot commented Jan 8, 2025

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

app/api/brackets/route.js

Oops! Something went wrong! :(

ESLint: 9.17.0

ESLint couldn't find an eslint.config.(js|mjs|cjs) file.

From ESLint v9.0.0, the default configuration file is now eslint.config.js.
If you are using a .eslintrc.* file, please follow the migration guide
to update your configuration file to the new format:

https://eslint.org/docs/latest/use/configure/migration-guide

If you still have problems after following the migration guide, please stop by
https://eslint.org/chat/help to chat with the team.

Walkthrough

This pull request introduces significant changes to the bracket management system across multiple files. The modifications simplify the bracket creation and retrieval processes by removing complex validation and management layers. The data model for brackets has been restructured, with changes to how teams, tournament names, and bracket properties are handled. The front-end components have been updated to work with the new data structure, including modifications to the bracket creation, viewing, and listing components.

Changes

File Change Summary
app/api/brackets/route.js Simplified POST and GET functions, removing zod validation and user-specific filtering
app/bracket/[id]/page.js Updated component to use new bracket properties like tournament_name and teams
app/bracket/bracket.jsx New Bracket component with enhanced tournament stage rendering
app/bracket/create/page.js Removed previous implementation
app/bracket/create/page.jsx Refactored bracket creation logic with new API submission
app/bracket/styles.css Added custom styles for team name display and number input
components/BracketList.jsx Updated tournament name rendering
model/Bracket.js Transitioned to ES6 module syntax and simplified bracket schema

Sequence Diagram

sequenceDiagram
    participant User
    participant BracketCreatePage
    participant BracketsAPI
    participant Database

    User->>BracketCreatePage: Enter tournament details
    BracketCreatePage->>BracketsAPI: Submit bracket data
    BracketsAPI->>Database: Save new bracket
    Database-->>BracketsAPI: Confirmation
    BracketsAPI-->>BracketCreatePage: Success response
    BracketCreatePage->>User: Display bracket
Loading

Possibly related PRs

Suggested labels

backend, frontend

Suggested reviewers

  • dinxsh

Poem

🐰 Brackets dance, a digital delight,
Code refactored with rabbit's might!
Teams aligned, schemas clean,
A tournament's path now clearly seen.
Hop along the coding trail,
Where brackets never, ever fail! 🏆


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (10)
app/api/brackets/route.js (2)

24-31: Enhance error response structure for better client-side handling

The error response currently returns a generic message. For improved client-side error handling, consider adding an error code or more specific details that can help the client application respond appropriately.


40-40: Avoid logging sensitive data in production

The console.log(newBracket); statement may expose sensitive information in the server logs. It's advisable to remove this logging statement or ensure that it doesn't log sensitive data, especially in a production environment.

Apply this diff to remove the console log:

-       console.log(newBracket);
app/bracket/create/page.jsx (4)

90-97: Avoid duplicate success messages

Both sendBrackets and onTeamSubmit display a success toast upon bracket creation. This results in duplicate success messages to the user.

Consider removing the success toast from one of the functions. For example, remove it from onTeamSubmit:

        // toast.success("Bracket created successfully");

135-147: Correct 'aria-label' attribute for accessibility

The attribute arial-label is incorrect. It should be aria-label to comply with accessibility standards.

Apply this diff to correct the attribute:

              <Button
                variant="ghost"
                onClick={() => {
                  bracketCreated
                    ? setBracketCreated(false)
                    : router.push("/bracket");
                }}
                className="mr-auto"
-               arial-label="back-button"
+               aria-label="back-button"
              >
                <FaArrowLeftLong className="size-5 m-0" />
              </Button>

263-276: Correct 'aria-label' attribute and ensure consistency

In the submit button, the attribute arial-label is misspelled and inconsistent with the back button. Ensure aria-label is correctly spelled and used consistently.

Apply this diff to correct the attribute:

                  <Button
                    type="submit"
                    disabled={showBrackets}
-                   arial-label="submit-team-btn"
+                   aria-label="submit-team-btn"
                    className="w-full md:w-1/6 lg:w-1/6"
                  >
                    Submit
                  </Button>

123-123: Remove commented-out console log statement

There's a commented-out console.log statement that isn't necessary. Removing it will help keep the code clean and maintainable.

Apply this diff to remove the commented code:

-       // console.log("Bracket Info", JSON.stringify(info, null, 2));
app/bracket/[id]/page.js (2)

51-52: Ensure 'bracket' data is available before destructuring

When destructuring bracket, there's a risk of an error if bracket is null or undefined. Even though loading and error states are handled, it's good practice to safeguard against unexpected null values.

Ensure bracket is not null before destructuring:

      if (!bracket) {
+       return <div>No bracket data available.</div>;
      }

      const { tournament_name, format, consolationFinal, grandFinalType, teams } =
        bracket;

59-61: Consider adding fallback text for missing tournament name

If tournament_name is undefined, it might cause rendering issues. Adding a fallback can improve user experience.

Apply this diff to add a fallback:

            <h2 className="font-black text-3xl" id="tournament_heading">
-             {tournament_name}
+             {tournament_name || "Tournament"}
            </h2>
app/bracket/bracket.jsx (1)

58-60: Improve window object check.

The window object check could be more robust by checking for bracketsViewer.

Enhance the check:

-if (typeof window === "undefined" || !stageData) return;
+if (typeof window === "undefined" || !window.bracketsViewer || !stageData) return;
model/Bracket.js (1)

9-13: Add format-specific validation.

The format validation could include specific rules for each elimination type.

Consider adding custom validation:

 format: {
   type: String,
   enum: ["single_elimination", "double_elimination"],
   required: true,
+  validate: {
+    validator: function(v) {
+      if (v === "double_elimination" && this.teams.length < 8) {
+        return false;
+      }
+      return true;
+    },
+    message: "Double elimination requires at least 8 teams"
+  }
 },
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dadf858 and f92d605.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (9)
  • app/api/brackets/route.js (2 hunks)
  • app/bracket/[id]/page.js (3 hunks)
  • app/bracket/bracket.jsx (1 hunks)
  • app/bracket/create/page.js (0 hunks)
  • app/bracket/create/page.jsx (7 hunks)
  • app/bracket/styles.css (1 hunks)
  • app/createBracket/styles.css (0 hunks)
  • components/BracketList.jsx (1 hunks)
  • model/Bracket.js (1 hunks)
💤 Files with no reviewable changes (2)
  • app/bracket/create/page.js
  • app/createBracket/styles.css
✅ Files skipped from review due to trivial changes (1)
  • app/bracket/styles.css
🔇 Additional comments (2)
app/bracket/create/page.jsx (1)

76-103: ⚠️ Potential issue

Ensure numeric values are correctly parsed and validated

In the onTeamSubmit function, the values parameter representing the number of teams is received as a string. This can lead to issues when performing numeric comparisons and operations.

Apply this diff to parse and validate the number of teams:

      function onTeamSubmit(values) {
+       const numTeams = parseInt(values, 10);
+       if (isNaN(numTeams) || numTeams < 4) {
          toast.error("Number of teams must be greater than 4");
          return;
        }

-       const teams = Array.from({ length: values }, (_, i) => `Team${i + 1}`);
+       const teams = Array.from({ length: numTeams }, (_, i) => `Team${i + 1}`);

        const res = { ...bracketInfo, teams };
        setInfo(res);

        sendBrackets({
          tournament_name: res.tournament_name,
          format: res.format,
          consolationFinal: res.consolationFinal,
          grandFinalType: res.grandFinalType,
          teams: res.teams,
        });

        if (!showBrackets) {
          setShowBrackets(true);
        }

      }

Likely invalid or redundant comment.

components/BracketList.jsx (1)

71-71: LGTM! Property name aligned with schema.

The change from tournamentName to tournament_name correctly aligns with the updated schema in model/Bracket.js.

Let's verify all tournament name references are consistently updated:

✅ Verification successful

Property name correctly aligned with Bracket model, but inconsistent naming conventions detected

The change from tournamentName to tournament_name in BracketList.jsx is correct as it aligns with the Bracket model's schema. However, there are two different naming conventions being used across the codebase:

  • Bracket-related components use snake_case (tournament_name)
  • Tournament-related components use camelCase (tournamentName)

While this doesn't affect functionality as they're separate models, consider standardizing the naming convention in future refactoring.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining instances of 'tournamentName'
rg -i "tournamentName" --type js --type jsx

Length of output: 71


Script:

#!/bin/bash
# Search for any remaining instances of both naming conventions
rg -i "tournament[_]?name" --type-add 'jsx:*.{jsx,js}' --type jsx -C 2

# Specific pattern search for object property access
ast-grep --pattern 'tournamentName'
ast-grep --pattern 'tournament_name'

Length of output: 20453

Comment on lines 17 to 32
if (
!tournament_name ||
!format ||
!grandFinalType ||
!teams ||
teams.length < 4
) {
return NextResponse.json(
{
error:
"Invalid input: Ensure all fields are filled and at least 4 teams are provided.",
},
{ status: 400 },
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider including 'consolationFinal' in input validation

Currently, the input validation checks for the presence of tournament_name, format, grandFinalType, and teams, but it overlooks consolationFinal. If consolationFinal is a required field or holds significance in bracket creation, it should be validated to prevent unexpected behavior.

Apply this diff to include consolationFinal in the validation:

        if (
          !tournament_name ||
          !format ||
          !grandFinalType ||
+         typeof consolationFinal !== 'boolean' ||
          !teams ||
          teams.length < 4
        ) {
          return NextResponse.json(
            {
              error:
                "Invalid input: Ensure all fields are filled and at least 4 teams are provided.",
            },
            { status: 400 },
          );
        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (
!tournament_name ||
!format ||
!grandFinalType ||
!teams ||
teams.length < 4
) {
return NextResponse.json(
{
error:
"Invalid input: Ensure all fields are filled and at least 4 teams are provided.",
},
{ status: 400 },
);
}
if (
!tournament_name ||
!format ||
!grandFinalType ||
typeof consolationFinal !== 'boolean' ||
!teams ||
teams.length < 4
) {
return NextResponse.json(
{
error:
"Invalid input: Ensure all fields are filled and at least 4 teams are provided.",
},
{ status: 400 },
);
}

Comment on lines 73 to 74
const brackets = await Bracket.find();
return NextResponse.json(brackets, { status: 200 });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Filter brackets based on user authorization

In the GET function, all brackets are fetched and returned regardless of the authenticated user. If brackets are user-specific or access should be restricted, consider modifying the query to filter brackets based on the user's session.

Apply this diff to filter brackets by the authenticated user:

        const brackets = await Bracket.find({
+         userId: session.user.id,
        });
        return NextResponse.json(brackets, { status: 200 });

Ensure that the Bracket model includes a userId field to associate brackets with users.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 61 to 78
// const bracketsViewerNode = document.querySelector(".brackets-viewer");
// bracketsViewerNode?.replaceChildren();

// window.bracketsViewer.onMatchClicked = async (match) => {
// console.log("Match clicked", match);
// try {
// await manager.update.match({
// id: match.id,
// opponent1: { score: 5 },
// opponent2: { score: 7, result: "win" },
// });
// } catch (error) {
// console.error("Error during match update:", error);
// }
// const tourneyData2 = await manager.get.currentMatches(0);
// const tourneyData = await manager.get.stageData(0);
// setStageData(tourneyData);
// };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove or implement commented code.

The commented match click handler should either be implemented or removed.

If the match click functionality is needed, implement it. Otherwise, remove the commented code.

Comment on lines 116 to 120
function removeBracket() {
storage.reset();
manager.reset;
router.push("/bracket");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix typo in reset function.

The manager.reset call is missing parentheses, making it ineffective.

Fix the typo:

 function removeBracket() {
   storage.reset();
-  manager.reset;
+  manager.reset();
   router.push("/bracket");
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function removeBracket() {
storage.reset();
manager.reset;
router.push("/bracket");
}
function removeBracket() {
storage.reset();
manager.reset();
router.push("/bracket");
}

Comment on lines 108 to 110
useEffect(() => {
rendering();
}, []);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add cleanup to useEffect.

The useEffect hook should clean up resources on unmount to prevent memory leaks.

Add cleanup:

 useEffect(() => {
   rendering();
+  return () => {
+    storage.reset();
+    manager.reset();
+  };
 }, []);

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 13 to 14
const storage = new InMemoryDatabase();
const manager = new BracketsManager(storage);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Move storage and manager inside component.

Global instances of InMemoryDatabase and BracketsManager could cause memory leaks and state conflicts between different bracket instances.

Move these instances inside the component:

-const storage = new InMemoryDatabase();
-const manager = new BracketsManager(storage);

export default function Bracket({...}) {
+  const storage = new InMemoryDatabase();
+  const manager = new BracketsManager(storage);
   ...
}

Committable suggestion skipped: line range outside the PR's diff.

model/Bracket.js Outdated
Comment on lines 23 to 48
teams: {
type: [String], // Array of team names
required: true,
validate: {
validator: function (arr) {
return arr.length >= 4; // Ensure at least 4 teams
},
message: "Number of teams must be at least 4.",
},
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance teams validation.

The teams array validation could be more robust by ensuring non-empty and unique team names.

Add additional validations:

 teams: {
   type: [String],
   required: true,
   validate: [
     {
       validator: function (arr) {
-        return arr.length >= 4;
+        return arr.length >= 4 && 
+          arr.every(team => team.trim().length > 0) &&
+          new Set(arr).size === arr.length;
       },
-      message: "Number of teams must be at least 4.",
+      message: "Must have at least 4 unique, non-empty team names.",
     }
   ],
 },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
teams: {
type: [String], // Array of team names
required: true,
validate: {
validator: function (arr) {
return arr.length >= 4; // Ensure at least 4 teams
},
message: "Number of teams must be at least 4.",
},
},
teams: {
type: [String], // Array of team names
required: true,
validate: {
validator: function (arr) {
return arr.length >= 4 &&
arr.every(team => team.trim().length > 0) &&
new Set(arr).size === arr.length;
},
message: "Must have at least 4 unique, non-empty team names.",
},
},

model/Bracket.js Outdated
Comment on lines 18 to 30
grandFinalType: {
type: String,
enum: ["simple", "double"],
required: true,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add conditional validation for grandFinalType.

The grandFinalType should only be required when using double elimination format.

Update the validation:

 grandFinalType: {
   type: String,
   enum: ["simple", "double"],
-  required: true,
+  required: function() {
+    return this.format === "double_elimination";
+  },
 },

Committable suggestion skipped: line range outside the PR's diff.

@dinxsh dinxsh self-requested a review January 8, 2025 17:17
@dinxsh
Copy link
Owner

dinxsh commented Jan 8, 2025

could you look at the suggestions by @CodeRabbit and make changes @thornxyz

Copy link
Contributor

coderabbitai bot commented Jan 8, 2025

@dinxsh: i've previously provided several suggestions for improvements in this pr. here are the key areas that need attention:

  1. error handling improvements in the api routes
  2. accessibility fixes (correcting aria-label attributes)
  3. code cleanup (removing console logs and commented code)
  4. enhanced validation for bracket formats
  5. security considerations (avoiding sensitive data logging)

once @thornxyz makes the suggested changes, i'll review them in the next iteration.

🔗 analysis chain

🏁 scripts executed

the following scripts were executed for the analysis:

script:

#!/bin/bash
# get pr review comments
gh pr view 226 --json reviews

length of output: 11237

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@thornxyz thornxyz closed this Jan 9, 2025
@thornxyz thornxyz force-pushed the fix/bracket_viewer branch from f92d605 to 2837699 Compare January 9, 2025 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants