diff --git a/pages/list.js b/pages/list.js
index 07dbc80..200e412 100644
--- a/pages/list.js
+++ b/pages/list.js
@@ -1,24 +1,87 @@
import Head from 'next/head';
import React from 'react';
+import { Card, CardBody, Container } from 'reactstrap';
+import { Footer, TurniereNavigation } from '../js/CommonComponents';
import {
+ getRequest,
+ getState,
verifyCredentials
} from '../js/api';
+import '../static/everypage.css';
+
export default class ListPage extends React.Component {
componentDidMount() {
verifyCredentials();
}
-
+
render() {
return (
-
+
-
Turnie.re - Turnierliste
+
Öffentliche Turniere: turnie.re
-
Turnierliste
+
+
+
+
+
);
}
}
+
+class TournamentList extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ error: null,
+ isLoaded: false,
+ items: []
+ };
+ }
+
+ componentDidMount() {
+ getRequest(getState(), '/tournaments?type=public')
+ .then(
+ response => {
+ this.setState({
+ isLoaded: true,
+ items: response.data
+ });
+ },
+ error => {
+ this.setState({
+ isLoaded: true,
+ error
+ });
+ }
+ );
+ }
+
+ render() {
+ return (
+
+
+
+ Öffentliche Turniere
+ {this.state.items.map(item => (
+ //The code should be item.code but the api just supports it this way by now
+
+ ))}
+
+
+
+ );
+ }
+}
+
+function TournamentListEntry(props) {
+ return (
+
+ {props.name}
+
+ );
+}
diff --git a/pages/tournament.js b/pages/tournament.js
index bb01189..c3905a6 100644
--- a/pages/tournament.js
+++ b/pages/tournament.js
@@ -1,8 +1,31 @@
import Head from 'next/head';
import React from 'react';
-import '../style.css';
+import {
+ Button,
+ Card,
+ CardBody,
+ Col,
+ Container,
+ Input,
+ InputGroup,
+ InputGroupAddon,
+ ListGroup,
+ ListGroupItem,
+ Modal,
+ ModalBody,
+ ModalFooter,
+ ModalHeader,
+ Row,
+ Table
+} from 'reactstrap';
+import 'bootstrap/dist/css/bootstrap.min.css';
+import {BigImage, Footer, TurniereNavigation} from '../js/CommonComponents.js';
+import '../static/everypage.css';
+import '../static/css/tournament.css';
import {
+ getRequest,
+ getState,
verifyCredentials
} from '../js/api';
@@ -17,16 +40,345 @@ class TournamentPage extends React.Component {
}
render() {
+ // TODO: Change href-prop of the anchor tag to contain the tournament code
return (
-
-
-
Turnie.re - Turnieranzeige
-
-
Turnieranzeige
-
Code: {this.props.query.code}
+
+
+ Turnier bearbeiten
+ {props.tournament.description}
+
+
+ {props.tournament.isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'}
+
+ Turnier-Code: {props.tournament.code}
+ von {props.tournament.ownerUsername}
+
+
+
+ {props.tournament.playoffStages.map(stage =>
+ )}
+
);
}
}
-export default TournamentPage;
+function getLevelName(levelNumber) {
+ const names = ['Finale', 'Halbfinale', 'Viertelfinale', 'Achtelfinale'];
+ if(levelNumber < names.length){
+ return names[levelNumber];
+ }else {
+ return Math.pow(2, levelNumber) + 'tel-Finale';
+ }
+}
+
+function TournamentContainer(props) {
+ if (props.data === null) {
+ return
null;
+ } else {
+ return
;
+ }
+}
+
+function Stage(props) {
+ return (
+
+ {props.level}
+
+ {props.matches.map((match => (
+
+ )))}
+
+
+
);
+}
+
+class Match extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ modal: false
+ };
+ this.toggleModal = this.toggleModal.bind(this);
+ }
+
+ toggleModal() {
+ this.setState({modal: !this.state.modal});
+ }
+
+ render() {
+ let cardClass, smallMessage, borderClass;
+ //possible states: single_team not_ready not_started in_progress team1_won team2_won undecided
+ switch (this.props.match.state) {
+ case 'in_progress':
+ cardClass = 'table-warning';
+ borderClass = 'border-warning';
+ smallMessage = 'Spiel läuft';
+ break;
+ case 'team1_won':
+ 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;
+ break;
+ case 'single_team':
+ cardClass = 'table-success';
+ borderClass = 'border-success';
+ smallMessage = 'kein Gegner, Team kommt weiter';
+ break;
+ case 'not_ready':
+ smallMessage = 'Spiel kann noch nicht gestartet werden';
+ break;
+ case 'not_started':
+ smallMessage = 'Spiel kann gestartet werden';
+ break;
+ case 'undecided':
+ cardClass = 'table-success';
+ borderClass = 'border-success';
+ smallMessage = 'Spiel beendet, unentschieden';
+ break;
+ }
+ return (
+
+
+
+
+
+
+ {smallMessage}
+
+
+ );
+ }
+}
+
+function MatchModal(props) {
+ let title;
+ let actionButton = '';
+ //possible states: single_team not_ready not_started in_progress team1_won team2_won undecided
+ switch (props.match.state) {
+ case 'in_progress':
+ title = 'Spiel läuft';
+ actionButton = ;
+ break;
+ case 'team1_won':
+ title = 'Spiel beendet';
+ break;
+ case 'team2_won':
+ 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;
+ case 'undecided':
+ title = 'Spiel beendet';
+ break;
+ }
+ return (
+
+ {title}
+
+ {props.match.state === 'in_progress' ? :
+ }
+
+
+ {actionButton}
+
+
+
+ );
+}
+
+function MatchTable(props) {
+ let team1Class, team2Class;
+ //possible states: single_team not_ready not_started in_progress team1_won team2_won undecided
+ switch (props.match.state) {
+ 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';
+ break;
+ case 'single_team':
+ team2Class = 'text-muted';
+ break;
+ case 'not_ready':
+ break;
+ case 'not_started':
+ break;
+ case 'undecided':
+ break;
+ }
+ if(props.match.state === 'single_team'){
+ return (
+
+
+
+ | {props.match.team1} |
+
+
+ | kein Gegner |
+
+
+
+ );
+ } else {
+ return (
+
+
+
+ | {props.match.scoreTeam1} |
+ {props.match.team1} |
+
+
+ | {props.match.scoreTeam2} |
+ {props.match.team2} |
+
+
+
+ );
+ }
+}
+
+function EditableMatchTable(props) {
+ return (
+
+
+
+ |
+
+ |
+ {props.match.team1} |
+
+
+ |
+
+ |
+ {props.match.team2} |
+
+
+
+ );
+}
+
+class ScoreInput extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {score: this.props.score};
+ this.updateScore = this.updateScore.bind(this);
+ this.increaseScore = this.increaseScore.bind(this);
+ this.decreaseScore = this.decreaseScore.bind(this);
+ }
+
+ updateScore(event){
+ this.setState({score: event.target.value});
+ }
+
+ increaseScore(){
+ this.setState({score: Number(this.state.score) + 1});
+ }
+
+ decreaseScore(){
+ this.setState({score: Number(this.state.score) - 1});
+ }
+
+ render() {
+ return (
+
+
+
+ );
+ }
+}
+
+function convertTournament(apiTournament) {
+ let groupStage = null;
+ let playoffStages = [];
+ for (let stage of apiTournament.stages) {
+ if(stage.groups.length > 0){
+ //group stage
+ groupStage = {groups: stage.groups.map(group => convertGroup(group))};
+ }else{
+ //playoff stage
+ playoffStages.push({
+ id: stage.id,
+ level: stage.level,
+ matches: stage.matches.map(match => convertMatch(match))
+ });
+ }
+ }
+ return {
+ id: apiTournament.id,
+ code: apiTournament.code,
+ description: apiTournament.description,
+ name: apiTournament.name,
+ public: apiTournament.public,
+ ownerUsername: apiTournament.owner_username,
+ groupStage: groupStage,
+ playoffStages: playoffStages
+ };
+}
+
+function convertGroup(apiGroup) {
+ return {
+ id: apiGroup.id,
+ number: apiGroup.number,
+ scores: apiGroup.group_scores,
+ matches: apiGroup.matches.map(match => convertMatch(match))
+ };
+}
+
+function convertMatch(apiMatch) {
+ return {
+ id: apiMatch.id,
+ state: apiMatch.state,
+ team1: apiMatch.match_scores[0].team.name,
+ team2: apiMatch.match_scores[1].team.name,
+ scoreTeam1: apiMatch.match_scores[0].points,
+ scoreTeam2: apiMatch.match_scores[1].points
+ };
+}
+
+class Main extends React.Component {
+ constructor(props) {
+ super(props);
+ const code = this.props.query.code;
+ getRequest(getState(), '/tournaments/' + code)
+ .then(response => {
+ this.setState({tournament: convertTournament(response.data)});
+ })
+ .catch(() => { /* TODO: Show some kind of error or smth */ });
+ }
+
+ render() {
+ const tournamentName = this.state === null ? 'Turnier' : this.state.tournament.name;
+ return (
+
+
+
{tournamentName}: turnie.re
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Main;
diff --git a/static/css/tournament.css b/static/css/tournament.css
new file mode 100644
index 0000000..b00bdef
--- /dev/null
+++ b/static/css/tournament.css
@@ -0,0 +1,28 @@
+.stage {
+ width: 1em;
+}
+
+.lost-team {
+ text-decoration: line-through;
+}
+
+.stages > div:nth-child(odd) {
+ background-color: #f8f8f8;
+}
+
+.minw-25 {
+ min-width: 25%;
+}
+
+.match:hover {
+ box-shadow: 0 .5rem 1rem rgba(0,0,0,.15)!important;
+}
+
+.match:hover > div {
+ border-width: 3px !important;
+ margin: -2px;
+}
+
+.scoreInput {
+ width: 11rem;
+}
\ No newline at end of file