diff --git a/js/api.js b/js/api.js index 8c83999..d90ea5d 100644 --- a/js/api.js +++ b/js/api.js @@ -235,6 +235,19 @@ const reducerTournamentinfo = (state = defaultStateTournamentinfo, action) => { action.parameters.errorCallback(); }); return Object.assign({}, state, {}); + case actionTypesTournamentinfo.END_MATCH: + patchRequest(action.state, '/matches/' + action.parameters.matchId, { + state: 'finished' + }).then(resp => { + storeOptionalToken(resp); + action.parameters.successCallback(resp.data.winner); + }).catch(error => { + if (error.response) { + storeOptionalToken(error.response); + } + action.parameters.errorCallback(); + }); + return Object.assign({}, state, {}); case actionTypesTournamentinfo.CLEAR: return Object.assign({}, state, {}); @@ -389,6 +402,18 @@ export function startMatch(matchId, successCallback, errorCallback) { }); } +export function endMatch(matchId, successCallback, errorCallback) { + __store.dispatch({ + type: actionTypesTournamentinfo.END_MATCH, + parameters: { + matchId: matchId, + successCallback: successCallback, + errorCallback: errorCallback + }, + state: __store.getState() + }); +} + export function getState() { return __store.getState(); } diff --git a/js/components/Match.js b/js/components/Match.js index 4b083fa..ebf91a7 100644 --- a/js/components/Match.js +++ b/js/components/Match.js @@ -12,7 +12,7 @@ import { Table } from 'reactstrap'; import React from 'react'; -import {startMatch} from '../api'; +import {endMatch, startMatch} from '../api'; import {notify} from 'react-notify-toast'; @@ -21,12 +21,16 @@ export class Match extends React.Component { super(props); this.state = { modal: false, - matchState: this.props.match.state + match: this.props.match }; this.toggleModal = this.toggleModal.bind(this); this.startMatch = this.startMatch.bind(this); this.onStartMatchSuccess = this.onStartMatchSuccess.bind(this); this.onStartMatchError = this.onStartMatchError.bind(this); + this.endMatch = this.endMatch.bind(this); + this.onEndMatchSuccess = this.onEndMatchSuccess.bind(this); + this.onEndMatchError = this.onEndMatchError.bind(this); + this.getMatchFinishedMessage = this.getMatchFinishedMessage.bind(this); } toggleModal() { @@ -38,11 +42,13 @@ export class Match extends React.Component { } startMatch() { - startMatch(this.props.match.id, this.onStartMatchSuccess, this.onStartMatchError); + startMatch(this.state.match.id, this.onStartMatchSuccess, this.onStartMatchError); } onStartMatchSuccess() { - this.setState({matchState: 'in_progress'}); + const updatedMatch = this.state.match; + updatedMatch.state = 'in_progress'; + this.setState({match: updatedMatch}); this.toggleModal(); } @@ -51,26 +57,52 @@ export class Match extends React.Component { notify.show('Das Match konnte nicht gestartet werden.', 'error', 3000); } + endMatch() { + endMatch(this.state.match.id, this.onEndMatchSuccess, this.onEndMatchError); + } + + onEndMatchSuccess(winner) { + const updatedMatch = this.state.match; + updatedMatch.state = 'finished'; + updatedMatch.winnerTeamId = winner === null ? null : winner.id; + this.setState({match: updatedMatch}); + this.toggleModal(); + } + + onEndMatchError() { + this.toggleModal(); + notify.show('Das Match konnte nicht beendet werden.', 'error', 3000); + } + + getMatchFinishedMessage() { + const match = this.state.match; + if (match.winnerTeamId === null) { + return 'Spiel beendet, unentschieden'; + } + if (match.winnerTeamId === match.team1.id) { + return 'Gewinner: ' + match.team1.name; + } + if (match.winnerTeamId === match.team2.id) { + return 'Gewinner: ' + match.team2.name; + } + return 'Spiel beendet'; + } + render() { let cardClass; let smallMessage; let borderClass; - // possible states: single_team not_ready not_started in_progress team1_won team2_won undecided - switch (this.state.matchState) { + // possible states: single_team not_ready not_started in_progress finished + switch (this.state.match.state) { case 'in_progress': cardClass = 'table-warning'; borderClass = 'border-warning'; smallMessage = 'Spiel läuft'; break; - case 'team1_won': + case 'finished': cardClass = 'table-success'; borderClass = 'border-success'; - smallMessage = 'Gewinner: ' + this.props.match.team1; - break; - case 'team2_won': - cardClass = 'table-success'; - borderClass = 'border-success'; - smallMessage = 'Gewinner: ' + this.props.match.team2; + smallMessage = this.getMatchFinishedMessage(); break; case 'single_team': cardClass = 'table-success'; @@ -83,21 +115,16 @@ export class Match extends React.Component { case 'not_started': smallMessage = 'Spiel kann gestartet werden'; break; - case 'undecided': - cardClass = 'table-success'; - borderClass = 'border-success'; - smallMessage = 'Spiel beendet, unentschieden'; - break; } return (
- + {smallMessage} - +
); } } @@ -105,16 +132,13 @@ export class Match extends React.Component { function MatchModal(props) { let title; let actionButton = ''; - // possible states: single_team not_ready not_started in_progress team1_won team2_won undecided + // possible states: single_team not_ready not_started in_progress finished switch (props.match.state) { case 'in_progress': title = 'Spiel läuft'; - actionButton = ; + actionButton = ; break; - case 'team1_won': - title = 'Spiel beendet'; - break; - case 'team2_won': + case 'finished': title = 'Spiel beendet'; break; case 'single_team': @@ -127,15 +151,12 @@ function MatchModal(props) { title = 'Spiel kann gestartet werden'; actionButton = ; break; - case 'undecided': - title = 'Spiel beendet'; - break; } return ( {title} - {props.match.state === 'in_progress' ? : - } + {props.matchState === 'in_progress' ? : + } {actionButton} @@ -147,17 +168,22 @@ function MatchModal(props) { function MatchTable(props) { let team1Class; let team2Class; - // possible states: single_team not_ready not_started in_progress team1_won team2_won undecided - switch (props.match.state) { + // possible states: single_team not_ready not_started in_progress finished + switch (props.matchState) { case 'in_progress': break; - case 'team1_won': - team1Class = 'font-weight-bold'; - team2Class = 'lost-team'; - break; - case 'team2_won': - team1Class = 'lost-team'; - team2Class = 'font-weight-bold'; + case 'finished': + if (props.match.winnerTeamId === undefined) { + break; + } + if (props.winnerTeamId === props.match.team1.id) { + team1Class = 'font-weight-bold'; + team2Class = 'lost-team'; + } + if (props.winnerTeamId === props.match.team2.id) { + team1Class = 'lost-team'; + team2Class = 'font-weight-bold'; + } break; case 'single_team': team2Class = 'text-muted'; @@ -166,14 +192,12 @@ function MatchTable(props) { break; case 'not_started': break; - case 'undecided': - break; } if (props.match.state === 'single_team') { return ( - + @@ -184,12 +208,12 @@ function MatchTable(props) { return (
{props.match.team1}{props.match.team1.name}
kein Gegner
- - + + - - + +
{props.match.scoreTeam1}{props.match.team1}{props.match.team1.score}{props.match.team1.name}
{props.match.scoreTeam2}{props.match.team2}{props.match.team2.score}{props.match.team2.name}
); @@ -201,15 +225,15 @@ function EditableMatchTable(props) { - + - {props.match.team1} + {props.match.team1.name} - + - {props.match.team2} + {props.match.team2.name} ); diff --git a/js/redux/tournamentInfo.js b/js/redux/tournamentInfo.js index 8a1f1df..f5aedbe 100644 --- a/js/redux/tournamentInfo.js +++ b/js/redux/tournamentInfo.js @@ -9,6 +9,7 @@ export const actionTypesTournamentinfo = { 'MODIFY_TOURNAMENT_ERROR': 'MODIFY_TOURNAMENT_ERROR', 'START_MATCH': 'START_MATCH', + 'END_MATCH': 'END_MATCH', 'REHYDRATE': 'TOURNAMENTINFO_REHYDRATE', 'CLEAR': 'TOURNAMENTINFO_CLEAR' diff --git a/pages/tournament.js b/pages/tournament.js index 8cf898c..a7bc42e 100644 --- a/pages/tournament.js +++ b/pages/tournament.js @@ -121,24 +121,42 @@ function convertGroup(apiGroup) { function convertMatch(apiMatch) { const result = { - id: apiMatch.id, state: apiMatch.state + id: apiMatch.id, state: apiMatch.state, winnerTeamId: apiMatch.winner === null ? null : apiMatch.winner.id }; if (apiMatch.match_scores.length === 2) { - result.team1 = apiMatch.match_scores[0].team.name; - result.scoreTeam1 = apiMatch.match_scores[0].points; - result.team2 = apiMatch.match_scores[1].team.name; - result.scoreTeam2 = apiMatch.match_scores[1].points; + result.team1 = { + name: apiMatch.match_scores[0].team.name, + id: apiMatch.match_scores[0].team.id, + score: apiMatch.match_scores[0].points + }; + result.team2 = { + name: apiMatch.match_scores[1].team.name, + id: apiMatch.match_scores[1].team.id, + score: apiMatch.match_scores[1].points + }; } else if (apiMatch.match_scores.length === 1) { - result.team1 = apiMatch.match_scores[0].team.name; - result.scoreTeam1 = apiMatch.match_scores[0].points; - result.team2 = 'TBD'; - result.scoreTeam2 = 0; + result.team1 = { + name: apiMatch.match_scores[0].team.name, + id: apiMatch.match_scores[0].team.id, + score: apiMatch.match_scores[0].points + }; + result.team2 = { + name: 'TBD', + id: null, + score: 0 + }; } else { - result.team1 = 'TBD'; - result.scoreTeam1 = 0; - result.team2 = 'TBD'; - result.scoreTeam2 = 0; + result.team1 = { + name: 'TBD', + id: null, + score: 0 + }; + result.team2 = { + name: 'TBD', + id: null, + score: 0 + }; } return result;