diff --git a/js/api.js b/js/api.js index d90ea5d..281ee0d 100644 --- a/js/api.js +++ b/js/api.js @@ -235,6 +235,31 @@ const reducerTournamentinfo = (state = defaultStateTournamentinfo, action) => { action.parameters.errorCallback(); }); return Object.assign({}, state, {}); + case actionTypesTournamentinfo.SUBMIT_MATCH_SCORES: + patchRequest(action.state, '/match_scores/' + action.parameters.scoreIdTeam1, { + points: action.parameters.scoreTeam1 + }).then(resp => { + storeOptionalToken(resp); + + patchRequest(action.state, '/match_scores/' + action.parameters.scoreIdTeam2, { + points: action.parameters.scoreTeam2 + }).then(resp => { + storeOptionalToken(resp); + + action.parameters.successCallback(); + }).catch(error => { + if (error.response) { + storeOptionalToken(error.response); + } + action.parameters.errorCallback(); + }); + }).catch(error => { + if (error.response) { + storeOptionalToken(error.response); + } + action.parameters.errorCallback(); + }); + return Object.assign({}, state, {}); case actionTypesTournamentinfo.END_MATCH: patchRequest(action.state, '/matches/' + action.parameters.matchId, { state: 'finished' @@ -414,6 +439,21 @@ export function endMatch(matchId, successCallback, errorCallback) { }); } +export function submitMatchScores(scoreTeam1, scoreIdTeam1, scoreTeam2, scoreIdTeam2, successCallback, errorCallback) { + __store.dispatch({ + type: actionTypesTournamentinfo.SUBMIT_MATCH_SCORES, + parameters: { + scoreTeam1: scoreTeam1, + scoreIdTeam1: scoreIdTeam1, + scoreTeam2: scoreTeam2, + scoreIdTeam2: scoreIdTeam2, + successCallback: successCallback, + errorCallback: errorCallback + }, + state: __store.getState() + }); +} + export function getState() { return __store.getState(); } diff --git a/js/components/EditableMatchTable.js b/js/components/EditableMatchTable.js index c19f883..2589354 100644 --- a/js/components/EditableMatchTable.js +++ b/js/components/EditableMatchTable.js @@ -6,13 +6,13 @@ export function EditableMatchTable(props) { - + {props.match.team1.name} - + {props.match.team2.name} @@ -24,28 +24,34 @@ class ScoreInput extends React.Component { constructor(props) { super(props); this.state = {score: this.props.score}; - this.updateScore = this.updateScore.bind(this); + this.inputScore = this.inputScore.bind(this); this.increaseScore = this.increaseScore.bind(this); this.decreaseScore = this.decreaseScore.bind(this); } - updateScore(event) { - this.setState({score: event.target.value}); + inputScore(event) { + const newScore = event.target.value; + this.setState({score: newScore}); + this.props.update(newScore); } increaseScore() { - this.setState({score: Number(this.state.score) + 1}); + const newScore = Number(this.state.score) + 1; + this.setState({score: newScore}); + this.props.update(newScore); } decreaseScore() { - this.setState({score: Number(this.state.score) - 1}); + const newScore = Number(this.state.score) - 1; + this.setState({score: newScore}); + this.props.update(newScore); } render() { return ( - diff --git a/js/components/MatchModal.js b/js/components/MatchModal.js index 9fd14a3..fd5b81f 100644 --- a/js/components/MatchModal.js +++ b/js/components/MatchModal.js @@ -1,48 +1,87 @@ import {Button, Modal, ModalBody, ModalFooter, ModalHeader} from 'reactstrap'; -import React from 'react'; +import React, {Component} from 'react'; import {EditableMatchTable} from './EditableMatchTable'; import {MatchTable} from './MatchTable'; +import {submitMatchScores} from '../api'; +import {notify} from 'react-notify-toast'; -export function MatchModal(props) { - let title; - let actionButton = ''; - let submitScoresButton = ''; - let matchTable = ; - // possible states: single_team not_ready not_started in_progress finished - switch (props.match.state) { - case 'in_progress': - title = 'Spiel läuft'; - submitScoresButton = ; - if (!props.match.allowUndecided && props.match.team1.score === props.match.team2.score) { - actionButton = ; - } else { - actionButton = ; - } - matchTable = ; - break; - case 'finished': - title = 'Spiel beendet'; - break; - case 'single_team': - title = 'kein Gegner, Team kommt weiter'; - break; - case 'not_ready': - title = 'Spiel kann noch nicht gestartet werden'; - break; - case 'not_started': - title = 'Spiel kann gestartet werden'; - actionButton = ; - break; +export class MatchModal extends Component { + constructor(props) { + super(props); + this.state = {scoreTeam1: this.props.match.team1.score, scoreTeam2: this.props.match.team2.score}; + this.updateScoreTeam1 = this.updateScoreTeam1.bind(this); + this.updateScoreTeam2 = this.updateScoreTeam2.bind(this); + this.submitScores = this.submitScores.bind(this); + this.onSubmitScoresError = this.onSubmitScoresError.bind(this); + this.onSubmitScoresSuccess = this.onSubmitScoresSuccess.bind(this); + } + + updateScoreTeam1(newScore) { + this.setState({scoreTeam1: newScore}); + } + + updateScoreTeam2(newScore) { + this.setState({scoreTeam2: newScore}); + } + + submitScores() { + const match = this.props.match; + submitMatchScores(this.state.scoreTeam1, match.team1.scoreId, this.state.scoreTeam2, match.team2.scoreId, + this.onSubmitScoresSuccess, this.onSubmitScoresError); + } + + onSubmitScoresError() { + this.props.toggle(); + notify.show('Der Spielstand konnte nicht geändert werden.', 'error', 2500); + } + + onSubmitScoresSuccess() { + this.props.toggle(); + notify.show('Der Spielstand wurde geändert.', 'success', 2000); + } + + render() { + let title; + let actionButton = ''; + let submitScoresButton = ''; + let matchTable = ; + // possible states: single_team not_ready not_started in_progress finished + switch (this.props.match.state) { + case 'in_progress': + title = 'Spiel läuft'; + submitScoresButton = ; + if (!this.props.match.allowUndecided && this.props.match.team1.score === this.props.match.team2.score) { + actionButton = ; + } else { + actionButton = ; + } + matchTable = ; + break; + case 'finished': + title = 'Spiel beendet'; + break; + case 'single_team': + title = 'kein Gegner, Team kommt weiter'; + break; + case 'not_ready': + title = 'Spiel kann noch nicht gestartet werden'; + break; + case 'not_started': + title = 'Spiel kann gestartet werden'; + actionButton = ; + break; + } + return ( + {title} + + {matchTable} + + + {submitScoresButton} + {actionButton} + + + ); } - return ( - {title} - - {matchTable} - - - {submitScoresButton} - {actionButton} - - - ); } diff --git a/js/redux/tournamentInfo.js b/js/redux/tournamentInfo.js index f5aedbe..b93f325 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', + 'SUBMIT_MATCH_SCORES': 'SUBMIT_MATCH_SCORES', 'END_MATCH': 'END_MATCH', 'REHYDRATE': 'TOURNAMENTINFO_REHYDRATE', diff --git a/pages/tournament.js b/pages/tournament.js index 575e47f..bd0de1b 100644 --- a/pages/tournament.js +++ b/pages/tournament.js @@ -129,18 +129,21 @@ function convertMatch(apiMatch, allowUndecided) { result.team1 = { name: apiMatch.match_scores[0].team.name, id: apiMatch.match_scores[0].team.id, - score: apiMatch.match_scores[0].points + score: apiMatch.match_scores[0].points, + scoreId: apiMatch.match_scores[0].id }; result.team2 = { name: apiMatch.match_scores[1].team.name, id: apiMatch.match_scores[1].team.id, - score: apiMatch.match_scores[1].points + score: apiMatch.match_scores[1].points, + scoreId: apiMatch.match_scores[1].id }; } else if (apiMatch.match_scores.length === 1) { result.team1 = { name: apiMatch.match_scores[0].team.name, id: apiMatch.match_scores[0].team.id, - score: apiMatch.match_scores[0].points + score: apiMatch.match_scores[0].points, + scoreId: apiMatch.match_scores[0].id }; result.team2 = { name: 'TBD',