diff --git a/sth-backend/pom.xml b/sth-backend/pom.xml index 41e8471c06b27b15d46c0b0c4ffa808a589336f8..962a3454c1b2ed33f5d841ef24ff6fb2b2d1594b 100644 --- a/sth-backend/pom.xml +++ b/sth-backend/pom.xml @@ -100,6 +100,11 @@ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> + <dependency> + <groupId>org.eclipse.angus</groupId> + <artifactId>jakarta.mail</artifactId> + <version>1.0.0</version> + </dependency> </dependencies> <build> diff --git a/sth-backend/src/main/java/hdm/mi/sthbackend/service/TournamentService.java b/sth-backend/src/main/java/hdm/mi/sthbackend/service/TournamentService.java index 0937cc9f7327ab0992c69255a6f237cf68f3ec1f..3f2e5de9f591d7dabcad3926d004e5c340f652d3 100644 --- a/sth-backend/src/main/java/hdm/mi/sthbackend/service/TournamentService.java +++ b/sth-backend/src/main/java/hdm/mi/sthbackend/service/TournamentService.java @@ -168,7 +168,7 @@ public class TournamentService { match.setWinnerTeamId(winnerTeamId); - Tournament updatedBracketTournament = assignTeamToMatch(tournament, bracketRound +1, match.getNextMatchId(), winnerTeamId); + Tournament updatedBracketTournament = assignTeamToMatch(tournament, bracketRound + 1, match.getNextMatchId(), winnerTeamId); tournamentRepository.save(updatedBracketTournament); diff --git a/sth-backend/src/test/java/hdm/mi/sthbackend/Integrationstests.java b/sth-backend/src/test/java/hdm/mi/sthbackend/endpointTest/EndpointTests.java similarity index 97% rename from sth-backend/src/test/java/hdm/mi/sthbackend/Integrationstests.java rename to sth-backend/src/test/java/hdm/mi/sthbackend/endpointTest/EndpointTests.java index 041828e570307e6c4bbee8da3958551b2887ae31..647344f045997549bf02c7a85621a59656dae1f9 100644 --- a/sth-backend/src/test/java/hdm/mi/sthbackend/Integrationstests.java +++ b/sth-backend/src/test/java/hdm/mi/sthbackend/endpointTest/EndpointTests.java @@ -1,4 +1,4 @@ -package hdm.mi.sthbackend; +package hdm.mi.sthbackend.endpointTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.jayway.jsonpath.JsonPath; @@ -26,13 +26,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @SpringBootTest @AutoConfigureMockMvc -public class Integrationstests { +public class EndpointTests { @Autowired private MockMvc mockMvc; @Autowired - private TournamentService tournamentService; - @Autowired private ITournamentRepository tournamentRepository; @Test diff --git a/sth-frontend/package-lock.json b/sth-frontend/package-lock.json index 9afe47756c44a61ab7f633f417b44e21cb01ff31..c44894f246cdd42743a73de53631e09dc514ba74 100644 --- a/sth-frontend/package-lock.json +++ b/sth-frontend/package-lock.json @@ -16,6 +16,7 @@ "react-dom": "^18.2.0", "react-router-dom": "^6.20.1", "tailwind-merge": "^2.2.0", + "use-immer": "^0.9.0", "web-vitals": "^2.1.4" }, "devDependencies": { @@ -2503,6 +2504,16 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.3.tgz", + "integrity": "sha512-pwupu3eWfouuaowscykeckFmVTpqbzW+rXFCX8rQLkZzM9ftBmU/++Ra+o+L27mz03zJTlyV4UUr+fdKNffo4A==", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", @@ -4072,6 +4083,15 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/use-immer": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/use-immer/-/use-immer-0.9.0.tgz", + "integrity": "sha512-/L+enLi0nvuZ6j4WlyK0US9/ECUtV5v9RUbtxnn5+WbtaXYUaOBoKHDNL9I5AETdurQ4rIFIj/s+Z5X80ATyKw==", + "peerDependencies": { + "immer": ">=2.0.0", + "react": "^16.8.0 || ^17.0.1 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5933,6 +5953,12 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==" }, + "immer": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.3.tgz", + "integrity": "sha512-pwupu3eWfouuaowscykeckFmVTpqbzW+rXFCX8rQLkZzM9ftBmU/++Ra+o+L27mz03zJTlyV4UUr+fdKNffo4A==", + "peer": true + }, "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", @@ -6968,6 +6994,12 @@ "picocolors": "^1.0.0" } }, + "use-immer": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/use-immer/-/use-immer-0.9.0.tgz", + "integrity": "sha512-/L+enLi0nvuZ6j4WlyK0US9/ECUtV5v9RUbtxnn5+WbtaXYUaOBoKHDNL9I5AETdurQ4rIFIj/s+Z5X80ATyKw==", + "requires": {} + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/sth-frontend/package.json b/sth-frontend/package.json index 2681dc3f8c9a60384d704c22b657cd6fa68750ce..b15bfde5bcb93d7182a548cbfa7b4e585472dee2 100644 --- a/sth-frontend/package.json +++ b/sth-frontend/package.json @@ -11,6 +11,7 @@ "react-dom": "^18.2.0", "react-router-dom": "^6.20.1", "tailwind-merge": "^2.2.0", + "use-immer": "^0.9.0", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/sth-frontend/src/features/tournament/components/Bracket.jsx b/sth-frontend/src/features/tournament/components/Bracket.jsx new file mode 100644 index 0000000000000000000000000000000000000000..20d0cfe6b1dffd90ff3992452df020fa6da9bc4c --- /dev/null +++ b/sth-frontend/src/features/tournament/components/Bracket.jsx @@ -0,0 +1,17 @@ +import BracketingRound from "./BracketingRound"; + +export default function Bracket({tournament, handleWinner}) { + const bracketRoundCount = tournament.bracket.length; + const bracketRoundComponents = []; + + for (let i = 0; i < bracketRoundCount; i++) { + + bracketRoundComponents.push(<BracketingRound key={i} tournament={tournament} handleWinner={handleWinner} index={i} />) + } + + return ( + <div className={'flex flex-row justify-center'}> + {bracketRoundComponents} + </div> + ) +} \ No newline at end of file diff --git a/sth-frontend/src/features/tournament/components/BracketingRound.jsx b/sth-frontend/src/features/tournament/components/BracketingRound.jsx index c9dd652beacffd4c1db5a7fcd210027bd3d204ea..3cf1679d38e4ad4381b71e44e5bc8164378919c6 100644 --- a/sth-frontend/src/features/tournament/components/BracketingRound.jsx +++ b/sth-frontend/src/features/tournament/components/BracketingRound.jsx @@ -1,11 +1,16 @@ import Match from "./Match"; +import {useContext, useEffect, useState} from "react"; +import {TournamentContext} from "./Tournament"; -export default function BracketingRound({bracketRound, matchesNum}) { +export default function BracketingRound({tournament, handleWinner, index }) { + const bracketRound = tournament.bracket[index] const matchComponents = []; + const matches = Object.values(bracketRound.matches); + const matchesCount = Object.keys(tournament.bracket[index].matches).length; - for (let i = 0; i < matchesNum; i++) { - matchComponents.push(<Match match={matches[i]} bracketRound={bracketRound.round} style={i + 1} key={i}/>); + for (let i = 0; i < matchesCount; i++) { + matchComponents.push(<Match key={i} tournament={tournament} handleWinner={handleWinner} style={i + 1} index={i} bracketRoundIndex={index}/>); } return( diff --git a/sth-frontend/src/features/tournament/components/BracketingTree.jsx b/sth-frontend/src/features/tournament/components/BracketingTree.jsx deleted file mode 100644 index 2986f10cbd6611f54be5b97d4eb8d8a3d9ff02d8..0000000000000000000000000000000000000000 --- a/sth-frontend/src/features/tournament/components/BracketingTree.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import BracketingRound from "./BracketingRound"; - -export default function BracketingTree({bracketRoundList, roundsNum}) { - const matches = roundsNum; - const bracketRoundComponents = []; - roundsNum = Math.log2(roundsNum) + 1; - - for (let i = 0; i < roundsNum; i++) { - const bracketRound = bracketRoundList[i] - bracketRoundComponents.push(<BracketingRound bracketRound={bracketRound} key={i} matchesNum={matches / Math.pow(2, i)} />) - } - - return ( - <div className={'flex flex-row justify-center'}> - {bracketRoundComponents} - </div> - ) -} \ No newline at end of file diff --git a/sth-frontend/src/features/tournament/components/Match.jsx b/sth-frontend/src/features/tournament/components/Match.jsx index e43b318263726bc5ff61b17179a87af3dd7e9b31..a1b3deff2fd91ce050ef85584795efe1e36947ff 100644 --- a/sth-frontend/src/features/tournament/components/Match.jsx +++ b/sth-frontend/src/features/tournament/components/Match.jsx @@ -1,45 +1,52 @@ import Team from "./Team"; -import {useContext, useState } from "react"; -import { TournamentContext } from "./Tournament"; -import {closeMatch} from "../services/tournamentService"; +import {useContext, useEffect, useState} from "react"; +import {TournamentContext} from "./Tournament"; +import {closeMatch, updateScore} from "../services/tournamentService"; -export default function Match({match, bracketRound}) { +export default function Match({tournament, handleWinner, style, index, bracketRoundIndex}) { - if(Object.keys(match.teamScores).length > 0){ - const tournament = useContext(TournamentContext); - const teams = tournament.teams + const match = Object.values(tournament.bracket[bracketRoundIndex].matches)[index]; + const teamScoresKeys = Object.keys(match.teamScores); - function handleClick(){ - closeMatch(tournament.tournamentId, bracketRound, match.matchId) + const [teamOneScore, setTeamOneScore] = useState(tournament.bracket[bracketRoundIndex].matches[match.matchId].teamScores[teamScoresKeys[0]]); + const [teamTwoScore, setTeamTwoScore] = useState(tournament.bracket[bracketRoundIndex].matches[match.matchId].teamScores[teamScoresKeys[1]]); + + useEffect(() => { + if (teamOneScore !== 0) { + (async () => { + const data = await updateScore(tournament.tournamentId, bracketRoundIndex, match.matchId, team1.teamId, teamOneScore); + })(); + } + }, [teamOneScore]); + + useEffect(() => { + if (teamTwoScore !== 0) { + (async () => { + const data = await updateScore(tournament.tournamentId, bracketRoundIndex, match.matchId, team2.teamId, teamTwoScore); + })(); } + }, [teamTwoScore]); + + + + + + const team1 = tournament.teams[teamScoresKeys[0]] + + const team2 = teamScoresKeys.length > 0 ? tournament.teams[teamScoresKeys[1]] : null; + - const uuidTeam1 = Object.keys(match.teamScores)[0]; - const uuidTeam2 = Object.keys(match.teamScores)[1]; - - const team1 = teams[uuidTeam1]; - const team2 = teams[uuidTeam2]; - - const [teamOneScore, setTeamOneScore] = useState(match.teamScores[uuidTeam1]); - const [teamTwoScore, setTeamTwoScore] = useState(match.teamScores[uuidTeam2]); - - const teamOneWinning = teamOneScore > teamTwoScore; - const teamTwoWinning = teamTwoScore > teamOneScore; - - return( - <div className={`m-2 hover:shadow-lg border-4 rounded-xl`}> - <Team name={team1.teamName} score={teamOneScore} setScore={setTeamOneScore} winning={teamOneWinning}/> - <Team name={team2.teamName} score={teamTwoScore} setScore={setTeamTwoScore} winning={teamTwoWinning}/> - <button className={"mx-auto bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"} onClick={() => {handleClick()}}>Close Match</button> </div> - ) - } - else{ - return( - <div className={`m-2 hover:shadow-lg border-4 rounded-xl`}> - <Team name={"tbd"} score={0}/> - <Team name={"tbd"} score={0}/> - </div> - ) - } + return ( + <div className={`m-2 hover:shadow-lg border-4 rounded-xl`}> + <Team name={team1?.teamName} score={teamOneScore} setScore={setTeamOneScore} + winning={teamOneScore > teamTwoScore}/> + <Team name={team2?.teamName} score={teamTwoScore} setScore={setTeamTwoScore} + winning={teamTwoScore > teamOneScore}/> + <button className={"mx-auto bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"} + onClick={() => {handleWinner(bracketRoundIndex, match.matchId)}}>Close Match + </button> + </div> + ) } \ No newline at end of file diff --git a/sth-frontend/src/features/tournament/components/Score.jsx b/sth-frontend/src/features/tournament/components/Score.jsx index e981d26c5918c4c8f7ee2c19a5c7ebc94b78dd13..954cdc2f3e071c4da23bd4713d78514350abe82b 100644 --- a/sth-frontend/src/features/tournament/components/Score.jsx +++ b/sth-frontend/src/features/tournament/components/Score.jsx @@ -2,6 +2,7 @@ import {useState} from "react"; export default function Score({score, setScore}) { + return( <div> <button className={'w-6 rounded hover:bg-gray-100 bg-gray-300 mr-1'} onClick={() => setScore(score - 1)}>-</button> diff --git a/sth-frontend/src/features/tournament/components/Team.jsx b/sth-frontend/src/features/tournament/components/Team.jsx index bb762e829932c9011db904d134a8d618f378ad93..a0e42e1034eb1984406000bbd76ace587d1b67d9 100644 --- a/sth-frontend/src/features/tournament/components/Team.jsx +++ b/sth-frontend/src/features/tournament/components/Team.jsx @@ -5,7 +5,7 @@ export default function Team({name, score, setScore, winning}) { return( <div className={'flex w-40 m-3'}> - <div className={`mr-4 rounded flex justify-center ` + (winning ? 'bg-green-300' : 'bg-gray-100')}>{name}</div> + <div className={`mr-4 rounded flex justify-center bg-grey-200` + (winning ? 'bg-green-300' : 'bg-gray-100')}>{name}</div> <Score setScore={setScore} score={score}/> </div> ) diff --git a/sth-frontend/src/features/tournament/components/Tournament.jsx b/sth-frontend/src/features/tournament/components/Tournament.jsx index bbdfaf5e4fe31fb6e537e26b302378f2c0c4ed8e..91ecf20d8f308845ae891904d5d567ee7f39c7bb 100644 --- a/sth-frontend/src/features/tournament/components/Tournament.jsx +++ b/sth-frontend/src/features/tournament/components/Tournament.jsx @@ -1,8 +1,23 @@ -import BracketingTree from "./BracketingTree"; -import {createContext, useContext} from "react"; +import Bracket from "./Bracket"; +import {createContext, useContext, useEffect, useState} from "react"; +import {closeMatch, getTournament} from "../services/tournamentService"; +import {useParams} from "react-router-dom"; +import {useImmer} from "use-immer"; + + +export default function Tournament() { + const {tournamentId} = useParams(); + + + + useEffect(() => { + + getTournament("931e982b-f2b4-4fd0-9f7a-3061953261ca") + .then((tourn) => setTournament(tourn)); + + }, []); -export default function Tournament({tournamentObject}) { const dummyTournament = { tournamentId: "7893ccf0-a5be-44ee-9a43-165815227234", @@ -14,7 +29,7 @@ export default function Tournament({tournamentObject}) { "7fdd9c6e-4cd5-4a5c-90e6-4af20601b11f": { matchId: "7fdd9c6e-4cd5-4a5c-90e6-4af20601b11f", teamScores: { - "0b7a6aef-8f92-4430-be51-a3c346923a47": 0, + "0b7a6aef-8f92-4430-be51-a3c346923a47": 1, "068d5988-fa2b-4138-b382-e35906ff2714": 0 }, winnerTeamId: null, @@ -132,15 +147,153 @@ export default function Tournament({tournamentObject}) { }, users: null } + const dummyTournament2 = { + tournamentId: "7893ccf0-a5be-44ee-9a43-165815227234", + tournamentName: "tName", + bracket: [ + { + bracketRoundId: "d67a78a4-2ad7-453f-aec7-b4bddb3b38d9", + matches: { + "a1a79990-dc86-499c-a379-174907ee8ec3": { + matchId: "a1a79990-dc86-499c-a379-174907ee8ec3", + teamScores: { + "0b7a6aef-8f92-4430-be51-a3c346923a47": 1, + "12bc6fdd-fe0b-4155-8c54-f5c6d4465275": 0 + }, + winnerTeamId: null, + comment: null, + nextMatchId: "294d9ea5-5f30-463f-a802-a0a3286aac88" + }, + "175af35c-fb3a-413c-a34d-a8f7f87e1f63": { + matchId: "175af35c-fb3a-413c-a34d-a8f7f87e1f63", + teamScores: { + "068d5988-fa2b-4138-b382-e35906ff2714": 0, + "d723e5ec-a62f-47bd-a487-db159f3f3519": 0 + }, + winnerTeamId: null, + comment: null, + nextMatchId: "294d9ea5-5f30-463f-a802-a0a3286aac88" + }, + "4ce354a4-9ad1-4fc7-b468-2e3c6f90198c": { + matchId: "4ce354a4-9ad1-4fc7-b468-2e3c6f90198c", + teamScores: { + "525159e2-0a72-472f-8f5c-7613e5b393d7": 0, + "1b276804-ee92-465e-a5b4-a275ccc1ad91": 0 + }, + winnerTeamId: null, + comment: null, + nextMatchId: "4ff71332-c358-4794-bf59-b4218404fe9a" + }, + "93cd4a27-ee2a-4cf1-bf6c-79fc41859409": { + matchId: "93cd4a27-ee2a-4cf1-bf6c-79fc41859409", + teamScores: { + "5e3f0426-e82f-460e-93fb-7a2fbb2e4d7f": 0, + "b3683dfd-182c-408c-a833-756b07eae588": 0 + }, + winnerTeamId: null, + comment: null, + nextMatchId: "4ff71332-c358-4794-bf59-b4218404fe9a" + } + }, + round: 0 + }, + { + bracketRoundId: "73295569-230f-4b5f-962c-d0b1511af08b", + matches: { + "294d9ea5-5f30-463f-a802-a0a3286aac88": { + matchId: "294d9ea5-5f30-463f-a802-a0a3286aac88", + teamScores: {}, + winnerTeamId: null, + comment: null, + nextMatchId: "1d9ce256-57fb-4e3b-b76d-3d2ffb60a465" + }, + "4ff71332-c358-4794-bf59-b4218404fe9a": { + matchId: "4ff71332-c358-4794-bf59-b4218404fe9a", + teamScores: {}, + winnerTeamId: null, + comment: null, + nextMatchId: "1d9ce256-57fb-4e3b-b76d-3d2ffb60a465" + } + }, + round: 1 + }, + { + bracketRoundId: "359c74d8-0940-4013-afdd-56725de0f156", + matches: { + "1d9ce256-57fb-4e3b-b76d-3d2ffb60a465": { + matchId: "1d9ce256-57fb-4e3b-b76d-3d2ffb60a465", + teamScores: {}, + winnerTeamId: null, + comment: null, + nextMatchId: null + } + }, + round: 2 + } + ], + teams: { + "0b7a6aef-8f92-4430-be51-a3c346923a47": { + teamId: "0b7a6aef-8f92-4430-be51-a3c346923a47", + teamName: "team3", + teamMembers: {} + }, + "525159e2-0a72-472f-8f5c-7613e5b393d7": { + teamId: "525159e2-0a72-472f-8f5c-7613e5b393d7", + teamName: "team6", + teamMembers: {} + }, + "068d5988-fa2b-4138-b382-e35906ff2714": { + teamId: "068d5988-fa2b-4138-b382-e35906ff2714", + teamName: "team2", + teamMembers: {} + }, + "d723e5ec-a62f-47bd-a487-db159f3f3519": { + teamId: "d723e5ec-a62f-47bd-a487-db159f3f3519", + teamName: "team5", + teamMembers: {} + }, + "5e3f0426-e82f-460e-93fb-7a2fbb2e4d7f": { + teamId: "5e3f0426-e82f-460e-93fb-7a2fbb2e4d7f", + teamName: "team7", + teamMembers: {} + }, + "1b276804-ee92-465e-a5b4-a275ccc1ad91": { + teamId: "1b276804-ee92-465e-a5b4-a275ccc1ad91", + teamName: "team1", + teamMembers: {} + }, + "12bc6fdd-fe0b-4155-8c54-f5c6d4465275": { + teamId: "12bc6fdd-fe0b-4155-8c54-f5c6d4465275", + teamName: "team8", + teamMembers: {} + }, + "b3683dfd-182c-408c-a833-756b07eae588": { + teamId: "b3683dfd-182c-408c-a833-756b07eae588", + teamName: "team4", + teamMembers: {} + } + }, + users: null + } - const bracketRoundList = dummyTournament.bracket; - const bracketSize = dummyTournament.bracket.length; + const [tournament, setTournament] = useImmer(null); + const handleMatchWinner = async (bracketRound, matchId) => { + const winnerId = await closeMatch(tournament.tournamentId, bracketRound, matchId) + + setTournament(tournament => { + const nextMatchId = tournament.bracket[bracketRound].matches[matchId].nextMatchId; + const formattedWinnerId = winnerId.replace(/^"|"$/g, ''); + const prevTeamScores = tournament.bracket[bracketRound + 1].matches[nextMatchId].teamScores + tournament.bracket[bracketRound + 1].matches[nextMatchId].teamScores = { ...prevTeamScores, [formattedWinnerId]: 0} + }); + } + if(!tournament) { + return <div>Loading...</div>; + } return ( <div> - <TournamentContext.Provider value={dummyTournament}> - <BracketingTree bracketRoundList={bracketRoundList} roundsNum={4}/> - </TournamentContext.Provider> + <Bracket tournament={tournament} handleWinner={handleMatchWinner} /> </div> ) } diff --git a/sth-frontend/src/features/tournament/services/tournamentService.js b/sth-frontend/src/features/tournament/services/tournamentService.js index c753f5854017d6e2ea8b8f81b733437e43678187..5e3050649936a7c5594b7bdf1c11835851d24e38 100644 --- a/sth-frontend/src/features/tournament/services/tournamentService.js +++ b/sth-frontend/src/features/tournament/services/tournamentService.js @@ -1,3 +1,5 @@ +import {HttpResponseError} from "../../../utils/errors/httpResponseError"; + const baseURL = import.meta.env.VITE_BASE_URL; async function createTournament(tournament) { @@ -25,7 +27,7 @@ async function createTournament(tournament) { throw new HttpResponseError('Bad fetch', response); } } catch (error) { - throw error; + console.error(error); } } @@ -46,18 +48,101 @@ async function closeMatch(tournamentId, bracketRound, matchId){ }; try { - console.log(`fetching ${url}`); + console.debug(`fetching ${url}`); const response = await fetch(url, options); - console.log(response) const data = await response.text() - console.log(data) if (!response.ok) { throw new HttpResponseError('Bad fetch', response); } + return data; + } catch (error) { + console.error(error); + } +} + +async function getTournament(tournamentId) { + + const url = `${baseURL}/api/v1/tournaments/${tournamentId}` + const options = { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + mode: 'cors', + credentials: 'omit' + }; + + try { + console.debug(`fetching ${url}`); + + const response = await fetch(url, options); + const data = await response.json() + + if (!response.ok) { + throw new HttpResponseError('Bad fetch', response); + } + return data; } catch (error) { - throw error; + console.error(error); } } -export { createTournament, closeMatch }; + +async function initializeTournament(tournamentId) { + + const url = `${baseURL}/api/v1/tournaments/${tournamentId}/initialize` + const options = { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + }, + mode: 'cors', + credentials: 'omit' + }; + + try { + console.debug(`fetching ${url}`); + + const response = await fetch(url, options); + const data = await response.json() + + if (!response.ok) { + throw new HttpResponseError('Bad fetch', response); + } + return data; + } catch (error) { + console.error(error); + } +} + +async function updateScore(tournamentId, bracketRound, matchId, teamId, score) { + + const url = `${baseURL}/api/v1/tournaments/${tournamentId}/bracketRounds/${bracketRound}/matches/${matchId}/teams/${teamId}/updateScore` + const options = { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({score: score}), + mode: 'cors', + credentials: 'omit' + }; + + try { + console.debug(`fetching ${url}`); + + const response = await fetch(url, options); + const data = response.body + + if (!response.ok) { + throw new HttpResponseError('Bad fetch', response); + } + return data; + } catch (error) { + console.error(error); + } +} + + +export { createTournament, closeMatch, getTournament, updateScore }; diff --git a/sth-frontend/src/utils/errors/httpResponseError.js b/sth-frontend/src/utils/errors/httpResponseError.js index 16ab9b11dc4836504b7c83f8b7a50b360db6a87a..c540703d4297f35c4d89fc8ad4a0cf2292a77259 100644 --- a/sth-frontend/src/utils/errors/httpResponseError.js +++ b/sth-frontend/src/utils/errors/httpResponseError.js @@ -4,4 +4,6 @@ class HttpResponseError extends Error { super(message); this.response = response; } -} \ No newline at end of file +} + +export {HttpResponseError} \ No newline at end of file diff --git a/sth-frontend/src/utils/router.jsx b/sth-frontend/src/utils/router.jsx index 3e390bd21244eef18347d3ba5598b3c9bc7b92b2..8204e7b1d4e4fd9894f32744aad980e0f5ff8018 100644 --- a/sth-frontend/src/utils/router.jsx +++ b/sth-frontend/src/utils/router.jsx @@ -23,6 +23,10 @@ const router = createBrowserRouter([ </EmailProvider> ) }, + { + path: "/tournament/:tournamentId", + element: <Tournament /> + }, { path: "/login", element: <LoginPage />