From 7479a1dcad7248471d1f64bc7474176b7346ef07 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 7 Aug 2024 19:39:04 +0530 Subject: [PATCH] style: bracket generator page improved ui and styling of bracket page --- app/bracket/page.js | 19 +- components/TournamentBracket.jsx | 561 +++++++------------------------ package-lock.json | 112 +----- 3 files changed, 146 insertions(+), 546 deletions(-) diff --git a/app/bracket/page.js b/app/bracket/page.js index 9af63d1..6425c21 100644 --- a/app/bracket/page.js +++ b/app/bracket/page.js @@ -1,14 +1,15 @@ import TournamentBracket from "../../components/TournamentBracket"; -import BracketList from "../../components/BracketList"; const BracketPage = () => { - return ( -
-

Tournament Manager

- - -
- ); + return ( +
+

+ Tournament Manager +

+ + +
+ ); }; -export default BracketPage; \ No newline at end of file +export default BracketPage; diff --git a/components/TournamentBracket.jsx b/components/TournamentBracket.jsx index c8f55e6..846a0de 100644 --- a/components/TournamentBracket.jsx +++ b/components/TournamentBracket.jsx @@ -1,39 +1,14 @@ "use client"; -import React, { useState, useEffect } from "react"; -import html2canvas from "html2canvas"; +import React, { useState } from "react"; import { generateBracket } from "../lib/generateBracket"; const TournamentBracket = () => { - const [tournaments, setTournaments] = useState([]); - const [selectedTournament, setSelectedTournament] = useState(""); const [tournamentName, setTournamentName] = useState(""); const [tournamentType, setTournamentType] = useState("single"); const [participants, setParticipants] = useState(["", ""]); const [bracket, setBracket] = useState([]); const [isSetup, setIsSetup] = useState(false); - const [isSaving, setIsSaving] = useState(false); - const [isLoading, setIsLoading] = useState(true); - - useEffect(() => { - const fetchTournaments = async () => { - setIsLoading(true); - try { - const response = await fetch("/api/tournaments"); - if (!response.ok) { - throw new Error("Failed to fetch tournaments"); - } - const data = await response.json(); - setTournaments(data.tournaments); - } catch (error) { - console.error("Error fetching tournaments:", error); - } finally { - setIsLoading(false); - } - }; - - fetchTournaments(); - }, []); const handleAddParticipant = () => { setParticipants([...participants, ""]); @@ -52,10 +27,6 @@ const TournamentBracket = () => { const handleSubmit = (e) => { e.preventDefault(); - if (!selectedTournament) { - alert("Please select a tournament."); - return; - } const validParticipants = participants.filter((p) => p.trim() !== ""); if (validParticipants.length < 2) { alert("Please enter at least 2 participants."); @@ -82,110 +53,41 @@ const TournamentBracket = () => { setBracket(newBracket); }; - const saveBracketAsImage = async () => { - setIsSaving(true); - try { - const bracketElement = document.getElementById("tournament-bracket"); - const canvas = await html2canvas(bracketElement); - const imageData = canvas.toDataURL("image/png"); - await saveBracketToDatabase(imageData); - alert("Bracket saved successfully!"); - } catch (error) { - console.error("Error saving bracket:", error); - alert("Failed to save bracket. Please try again."); - } finally { - setIsSaving(false); - } - }; - - const saveBracketToDatabase = async (imageData) => { - try { - const response = await fetch("/api/brackets", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - tournamentId: selectedTournament, - bracketName: tournamentName, - bracketImage: imageData, - bracketData: JSON.stringify(bracket), - }), - }); - - if (!response.ok) { - throw new Error("Failed to save bracket"); - } - - const data = await response.json(); - console.log("Save response:", data); - } catch (error) { - console.error("Error saving to database:", error); - throw error; - } - }; - if (!isSetup) { return ( -
-

+
+

Tournament Setup

- {isLoading ? ( -

Loading tournaments...

- ) : ( -
-
- - -
-
- - setTournamentName(e.target.value)} - className="w-full px-3 py-2 rounded-md bg-gray-700 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-purple-500" - required - /> -
-
- - -
-
- + + +
+ + setTournamentName(e.target.value)} + className="w-full mt-2 px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-purple-500 transition-all duration-300" + required + /> +
+ +
+ + +
+ +
+ + +
{participants.map((participant, index) => (
{ onChange={(e) => handleParticipantChange(index, e.target.value) } - className="flex-grow px-3 py-2 rounded-l-md bg-gray-700 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-purple-500" + className="w-10 md:w-full flex-grow px-3 py-2 rounded-l-md border focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder={`Participant ${index + 1}`} /> +
))} -
+ - - )} +
+ + +
); } return ( -
-

- {tournamentName} -

-
+
+

{tournamentName}

+ +
{bracket.map((round, roundIndex) => { + // Calculate the total number of teams based on the first round const totalTeams = bracket[0].length * 2; + + // Adjust spacing based on number of teams const getSpacing = () => { if (totalTeams === 4) return 100; if (totalTeams === 8) return 100; if (totalTeams === 16) return 120; - return 60; + return 60; // Default for other cases }; + const spacing = getSpacing(); return ( @@ -248,9 +156,10 @@ const TournamentBracket = () => { className="flex flex-col min-w-[250px] relative" style={{ marginTop: `${roundIndex * spacing}px` }} > -

+

Round {roundIndex + 1}

+ {round.map((match, matchIndex) => (
{ : `${16 + roundIndex * spacing}px`, }} > -
+
handleWinner(roundIndex, matchIndex, match.player1) @@ -275,11 +184,12 @@ const TournamentBracket = () => { > {match.player1 || "TBD"}
+
handleWinner(roundIndex, matchIndex, match.player2) @@ -294,286 +204,71 @@ const TournamentBracket = () => { ); })}
-
); }; export default TournamentBracket; -// "use client"; - -// import React, { useState, useEffect } from "react"; -// import { generateBracket } from "../lib/generateBracket"; - -// const TournamentBracket = () => { -// const [tournamentName, setTournamentName] = useState(""); -// const [tournamentType, setTournamentType] = useState("single"); -// const [participants, setParticipants] = useState(["", ""]); -// const [bracket, setBracket] = useState([]); -// const [isSetup, setIsSetup] = useState(false); - -// const handleAddParticipant = () => { -// setParticipants([...participants, ""]); -// }; - -// const handleRemoveParticipant = (index) => { -// const newParticipants = participants.filter((_, i) => i !== index); -// setParticipants(newParticipants); -// }; - -// const handleParticipantChange = (index, value) => { -// const newParticipants = [...participants]; -// newParticipants[index] = value; -// setParticipants(newParticipants); -// }; - -// const handleSubmit = (e) => { -// e.preventDefault(); -// const validParticipants = participants.filter((p) => p.trim() !== ""); -// if (validParticipants.length < 2) { -// alert("Please enter at least 2 participants."); -// return; -// } -// setBracket(generateBracket(validParticipants)); -// setIsSetup(true); -// }; - -// const handleWinner = (roundIndex, matchIndex, winner) => { -// const newBracket = [...bracket]; -// newBracket[roundIndex][matchIndex].winner = winner; - -// if (roundIndex + 1 < newBracket.length) { -// const nextMatchIndex = Math.floor(matchIndex / 2); -// const isFirstMatch = matchIndex % 2 === 0; -// if (isFirstMatch) { -// newBracket[roundIndex + 1][nextMatchIndex].player1 = winner; -// } else { -// newBracket[roundIndex + 1][nextMatchIndex].player2 = winner; -// } -// } - -// setBracket(newBracket); -// }; - -// if (!isSetup) { -// return ( -//
-//

-// Tournament Setup -//

-//
-//
-// -// setTournamentName(e.target.value)} -// className="w-full px-3 py-2 rounded-md bg-gray-700 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-purple-500" -// required -// /> -//
-//
-// -// -//
-//
-// -// {participants.map((participant, index) => ( -//
-// -// handleParticipantChange(index, e.target.value) -// } -// className="flex-grow px-3 py-2 rounded-l-md bg-gray-700 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-purple-500" -// placeholder={`Participant ${index + 1}`} -// /> -// -//
-// ))} -// -//
-// -//
-//
-// ); -// } - -// return ( -//
-//

-// {tournamentName} -//

-//
-// {bracket.map((round, roundIndex) => { -// // Calculate the total number of teams based on the first round -// const totalTeams = bracket[0].length * 2; - -// // Adjust spacing based on number of teams -// const getSpacing = () => { -// if (totalTeams === 4) return 100; -// if (totalTeams === 8) return 100; -// if (totalTeams === 16) return 120; -// return 60; // Default for other cases -// }; - -// const spacing = getSpacing(); - -// return ( -//
-//

-// Round {roundIndex + 1} -//

-// {round.map((match, matchIndex) => ( -//
-//
-//
-// handleWinner(roundIndex, matchIndex, match.player1) -// } -// > -// {match.player1 || "TBD"} -//
-//
-// handleWinner(roundIndex, matchIndex, match.player2) -// } -// > -// {match.player2 || "TBD"} -//
-//
-//
-// ))} -//
-// ); -// })} -//
-//
-// ); -// }; - -// export default TournamentBracket; - -// /** -// * return ( -//
-//

-// {tournamentName} -//

-//
-// {bracket.map((round, roundIndex) => ( -//
-//

-// Round {roundIndex + 1} -//

-// {round.map((match, matchIndex) => ( -//
-//
-//
-// handleWinner(roundIndex, matchIndex, match.player1) -// } -// > -// {match.player1 || "TBD"} -//
-//
-// handleWinner(roundIndex, matchIndex, match.player2) -// } -// > -// {match.player2 || "TBD"} -//
-//
-// {roundIndex < bracket.length - 1 && ( -// <> -//
-// {matchIndex % 2 === 0 && ( -//
-// )} -// {matchIndex % 2 === 1 && ( -//
-// )} -// -// )} -//
-// ))} -//
-// ))} -//
-//
-// ); -// */ +/** + * return ( +
+

+ {tournamentName} +

+
+ {bracket.map((round, roundIndex) => ( +
+

+ Round {roundIndex + 1} +

+ {round.map((match, matchIndex) => ( +
+
+
+ handleWinner(roundIndex, matchIndex, match.player1) + } + > + {match.player1 || "TBD"} +
+
+ handleWinner(roundIndex, matchIndex, match.player2) + } + > + {match.player2 || "TBD"} +
+
+ {roundIndex < bracket.length - 1 && ( + <> +
+ {matchIndex % 2 === 0 && ( +
+ )} + {matchIndex % 2 === 1 && ( +
+ )} + + )} +
+ ))} +
+ ))} +
+
+ ); + */ diff --git a/package-lock.json b/package-lock.json index 30d2b39..14acf3c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "@hookform/resolvers": "^3.7.0", "@material-tailwind/react": "^2.1.9", "@portabletext/react": "^3.0.18", - "@prisma/client": "^5.16.1", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-icons": "^1.3.0", @@ -22,7 +21,6 @@ "@tabler/icons": "^1.115.0", "@tabler/icons-react": "^3.11.0", "@types/bcrypt": "^5.0.2", - "axios": "^1.7.3", "bcrypt": "^5.1.1", "bcryptjs": "^2.4.3", "class-variance-authority": "^0.7.0", @@ -38,13 +36,11 @@ "next-sanity": "^9.4.2", "next-themes": "^0.3.0", "nextjs-toploader": "^1.6.12", - "prisma": "^5.16.1", "react": "^18", "react-dom": "^18", "react-hook-form": "^7.52.1", "react-icons": "^5.2.1", "resend": "^3.4.0", - "swr": "^2.2.5", "tailwind-merge": "^2.4.0", "tailwindcss-animate": "^1.0.7", "usehooks-ts": "^3.1.0", @@ -3459,63 +3455,6 @@ "node": "^14.13.1 || >=16.0.0 || >=18.0.0" } }, - "node_modules/@prisma/client": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.16.1.tgz", - "integrity": "sha512-wM9SKQjF0qLxdnOZIVAIMKiz6Hu7vDt4FFAih85K1dk/Rr2mdahy6d3QP41K62N9O0DJJA//gUDA3Mp49xsKIg==", - "hasInstallScript": true, - "engines": { - "node": ">=16.13" - }, - "peerDependencies": { - "prisma": "*" - }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - } - } - }, - "node_modules/@prisma/debug": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.16.1.tgz", - "integrity": "sha512-JsNgZAg6BD9RInLSrg7ZYzo11N7cVvYArq3fHGSD89HSgtN0VDdjV6bib7YddbcO6snzjchTiLfjeTqBjtArVQ==" - }, - "node_modules/@prisma/engines": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.16.1.tgz", - "integrity": "sha512-KkyF3eIUtBIyp5A/rJHCtwQO18OjpGgx18PzjyGcJDY/+vNgaVyuVd+TgwBgeq6NLdd1XMwRCI+58vinHsAdfA==", - "hasInstallScript": true, - "dependencies": { - "@prisma/debug": "5.16.1", - "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", - "@prisma/fetch-engine": "5.16.1", - "@prisma/get-platform": "5.16.1" - } - }, - "node_modules/@prisma/engines-version": { - "version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303.tgz", - "integrity": "sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw==" - }, - "node_modules/@prisma/fetch-engine": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.16.1.tgz", - "integrity": "sha512-oOkjaPU1lhcA/Rvr4GVfd1NLJBwExgNBE36Ueq7dr71kTMwy++a3U3oLd2ZwrV9dj9xoP6LjCcky799D9nEt4w==", - "dependencies": { - "@prisma/debug": "5.16.1", - "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", - "@prisma/get-platform": "5.16.1" - } - }, - "node_modules/@prisma/get-platform": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.16.1.tgz", - "integrity": "sha512-R4IKnWnMkR2nUAbU5gjrPehdQYUUd7RENFD2/D+xXTNhcqczp0N+WEGQ3ViyI3+6mtVcjjNIMdnUTNyu3GxIgA==", - "dependencies": { - "@prisma/debug": "5.16.1" - } - }, "node_modules/@radix-ui/number": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", @@ -6015,7 +5954,8 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "peer": true }, "node_modules/available-typed-arrays": { "version": "1.0.7", @@ -6041,16 +5981,6 @@ "node": ">=4" } }, - "node_modules/axios": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz", - "integrity": "sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw==", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/axobject-query": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", @@ -6736,6 +6666,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "peer": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -7585,6 +7516,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "peer": true, "engines": { "node": ">=0.4.0" } @@ -8932,6 +8864,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -11254,6 +11187,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "peer": true, "engines": { "node": ">= 0.6" } @@ -11262,6 +11196,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -12929,21 +12864,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prisma": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.16.1.tgz", - "integrity": "sha512-Z1Uqodk44diztImxALgJJfNl2Uisl9xDRvqybMKEBYJLNKNhDfAHf+ZIJbZyYiBhLMbKU9cYGdDVG5IIXEnL2Q==", - "hasInstallScript": true, - "dependencies": { - "@prisma/engines": "5.16.1" - }, - "bin": { - "prisma": "build/index.js" - }, - "engines": { - "node": ">=16.13" - } - }, "node_modules/prismjs": { "version": "1.27.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", @@ -13009,11 +12929,6 @@ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -14994,18 +14909,6 @@ "react": ">=17.0" } }, - "node_modules/swr": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/swr/-/swr-2.2.5.tgz", - "integrity": "sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==", - "dependencies": { - "client-only": "^0.0.1", - "use-sync-external-store": "^1.2.0" - }, - "peerDependencies": { - "react": "^16.11.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -15765,6 +15668,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "peer": true, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" }