started tournament implementation

This commit is contained in:
Torsten Schulz
2025-02-24 16:21:43 +01:00
parent 9442e3683b
commit df41720b50
14 changed files with 906 additions and 15 deletions

View File

@@ -0,0 +1,133 @@
import tournamentService from "../services/tournamentService.js";
export const getTournaments = async (req, res) => {
const { authcode: token } = req.headers;
const clubId = req.params.clubId;
try {
const tournaments = await tournamentService.getTournaments(token, clubId);
res.status(200).json(tournaments);
} catch (error) {
console.log(error);
res.status(500).json({ error: error.message });
}
};
export const addTournament = async (req, res) => {
const { authcode: token } = req.headers;
const { clubId, tournamentName, date } = req.body;
try {
const tournament = await tournamentService.addTournament(token, clubId, tournamentName, date);
res.status(200).json(tournament);
} catch (error) {
console.log(error);
res.status(500).json({ error: error.message });
}
}
export const addParticipant = async (req, res) => {
const { authcode: token } = req.headers;
const { clubId, tournamentId, participant: participantId } = req.body;
try {
await tournamentService.addParticipant(token, clubId, tournamentId, participantId);
const participants = await tournamentService.getParticipants(token, clubId, tournamentId);
res.status(200).json(participants);
} catch (error) {
console.log(error);
res.status(500).json({ error: error.message });
}
}
export const getParticipants = async (req, res) => {
const { authcode: token } = req.headers;
const { clubId, tournamentId } = req.body;
try {
const participants = await tournamentService.getParticipants(token, clubId, tournamentId);
res.status(200).json(participants);
} catch (error) {
console.log(error);
res.status(500).json({ error: error.message });
}
}
export const setModus = async (req, res) => {
const { authcode: token } = req.headers;
const { clubId, tournamentId, type, numberOfGroups } = req.body;
try {
await tournamentService.setModus(token, clubId, tournamentId, type, numberOfGroups);
} catch (error) {
console.log(error);
res.status(500).json({ error: error.message });
}
}
export const createGroups = async (req, res) => {
const { authcode: token } = req.headers;
const { clubId, tournamentId } = req.body;
try {
await tournamentService.createGroups(token, clubId, tournamentId);
} catch (error) {
console.log(error);
res.status(500).json({ error: error.message });
}
}
export const fillGroups = async (req, res) => {
const { authcode: token } = req.headers;
const { clubId, tournamentId } = req.body;
try {
const updatedMembers = await tournamentService.fillGroups(token, clubId, tournamentId);
res.status(200).json(updatedMembers);
} catch (error) {
console.log(error);
res.status(500).json({ error: error.message });
}
}
export const getGroups = async (req, res) => {
const { authcode: token } = req.headers;
const { clubId, tournamentId } = req.query;
try {
const groups = await tournamentService.getGroupsWithParticipants(token, clubId, tournamentId);
res.status(200).json(groups);
} catch (error) {
console.log(error);
res.status(500).json({ error: error.message });
}
};
export const getTournament = async (req, res) => {
const { authcode: token } = req.headers;
const { clubId, tournamentId } = req.params;
try {
const tournament = await tournamentService.getTournament(token, clubId, tournamentId);
res.status(200).json(tournament);
} catch (error) {
console.log(error);
res.status(500).json({ error: error.message });
}
}
export const getTournamentMatches = async (req, res) => {
const { authcode: token } = req.headers;
const { clubId, tournamentId } = req.params;
try {
const matches = await tournamentService.getTournamentMatches(token, clubId, tournamentId);
res.status(200).json(matches);
} catch (error) {
console.log(error);
res.status(500).json({ error: error.message });
}
}
export const addMatchResult = async (req, res) => {
const { authcode: token } = req.headers;
const { clubId, tournamentId, matchId, result } = req.body;
try {
await tournamentService.addMatchResult(token, clubId, tournamentId, matchId, result);
res.status(200).json({ message: "Result added successfully" });
} catch (error) {
console.error(error);
res.status(500).json({ error: error.message });
}
};

View File

@@ -0,0 +1,37 @@
import { DataTypes } from 'sequelize';
import sequelize from '../database.js';
const Tournament = sequelize.define('Tournament', {
name: {
type: DataTypes.STRING,
allowNull: false,
},
date: {
type: DataTypes.DATEONLY,
allowNull: false,
},
type: {
type: DataTypes.STRING,
allowNull: false,
},
bestOfEndroundSize: {
type: DataTypes.INTEGER,
allowNull: false,
},
numberOfGroups: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 0,
},
clubId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 1
}
}, {
underscored: true,
tableName: 'tournament',
timestamps: true,
});
export default Tournament;

View File

@@ -0,0 +1,21 @@
import { DataTypes } from 'sequelize';
import sequelize from '../database.js';
const TournamentGroup = sequelize.define('TournamentGroup', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
tournamentId : {
type: DataTypes.INTEGER,
allowNull: false
},
}, {
underscored: true,
tableName: 'tournament_group',
timestamps: true,
});
export default TournamentGroup;

View File

@@ -0,0 +1,31 @@
import { DataTypes } from 'sequelize';
import sequelize from '../database.js';
const TournamentMatch = sequelize.define('TournamentMatch', {
tournamentId: {
type: DataTypes.INTEGER,
allowNull: false,
},
groupId: {
type: DataTypes.INTEGER,
allowNull: true,
},
round: {
type: DataTypes.STRING,
allowNull: false,
},
player1Id: {
type: DataTypes.INTEGER,
allowNull: false,
},
player2Id: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {
underscored: true,
tableName: 'tournament_match',
timestamps: true,
});
export default TournamentMatch;

View File

@@ -0,0 +1,26 @@
import { DataTypes } from 'sequelize';
import sequelize from '../database.js';
const TournamentMember = sequelize.define('TournamentMember', {
tournamentId: {
type: DataTypes.INTEGER,
autoIncrement: false,
allowNull: true
},
groupId : {
type: DataTypes.INTEGER,
autoIncrement: false,
allowNull: true
},
clubMemberId: {
type: DataTypes.INTEGER,
autoIncrement: false,
allowNull: false
}
}, {
underscored: true,
tableName: 'tournament_member',
timestamps: true,
});
export default TournamentMember;

View File

@@ -0,0 +1,24 @@
import { DataTypes } from 'sequelize';
import sequelize from '../database.js';
const TournamentResult = sequelize.define('TournamentResult', {
matchId: {
type: DataTypes.INTEGER,
allowNull: false,
},
set: {
type: DataTypes.INTEGER,
},
pointsPlayer1: {
type: DataTypes.INTEGER,
},
pointsPlayer2: {
type: DataTypes.INTEGER,
},
}, {
underscored: true,
tableName: 'tournament_result',
timestamps: true,
});
export default TournamentResult;

View File

@@ -21,6 +21,11 @@ import Season from './Season.js';
import Location from './Location.js';
import Group from './Group.js';
import GroupActivity from './GroupActivity.js';
import Tournament from './Tournament.js';
import TournamentGroup from './TournamentGroup.js';
import TournamentMember from './TournamentMember.js';
import TournamentMatch from './TournamentMatch.js';
import TournamentResult from './TournamentResult.js';
User.hasMany(Log, { foreignKey: 'userId' });
Log.belongsTo(User, { foreignKey: 'userId' });
@@ -114,6 +119,43 @@ DiaryDateTag.belongsTo(DiaryTag, { foreignKey: 'tagId', as: 'tag' });
DiaryMemberTag.belongsTo(DiaryDate, { foreignKey: 'diaryDateId', as: 'diaryDates' });
DiaryDate.hasMany(DiaryMemberTag, { foreignKey: 'diaryDateId', as: 'diaryMemberTags' });
Tournament.belongsTo(Club, { foreignKey: 'clubId', as: 'tournamentclub' });
Club.hasMany(Tournament, { foreignKey: 'clubId', as: 'tournaments' });
TournamentGroup.belongsTo(Tournament, { foreignKey: 'tournamentId', as: 'tournaments' });
Tournament.hasMany(TournamentGroup, { foreignKey: 'tournamentId', as: 'tournamentGroups' });
TournamentMember.belongsTo(TournamentGroup, {
foreignKey: 'groupId',
targetKey: 'id',
as: 'group',
constraints: false
});
TournamentGroup.hasMany(TournamentMember, {
foreignKey: 'groupId',
as: 'tournamentGroupMembers'
});
TournamentMember.belongsTo(Member, { foreignKey: 'clubMemberId', as: 'member' });
Member.hasMany(TournamentMember, { foreignKey: 'clubMemberId', as: 'tournamentGroupMembers' });
TournamentMember.belongsTo(Tournament, { foreignKey: 'tournamentId', as: 'tournament' });
Tournament.hasMany(TournamentMember, { foreignKey: 'tournamentId', as: 'tournamentMembers' });
TournamentMatch.belongsTo(Tournament, { foreignKey: 'tournamentId', as: 'tournament' });
Tournament.hasMany(TournamentMatch, { foreignKey: 'tournamentId', as: 'tournamentMatches' });
TournamentMatch.belongsTo(TournamentGroup, { foreignKey: 'groupId', as: 'group' });
TournamentGroup.hasMany(TournamentMatch, { foreignKey: 'groupId', as: 'tournamentMatches' });
TournamentResult.belongsTo(TournamentMatch, { foreignKey: 'matchId', as: 'match' });
TournamentMatch.hasMany(TournamentResult, { foreignKey: 'matchId', as: 'tournamentResults' });
TournamentMatch.belongsTo(TournamentMember, { foreignKey: 'player1Id', as: 'player1' });
TournamentMatch.belongsTo(TournamentMember, { foreignKey: 'player2Id', as: 'player2' });
TournamentMember.hasMany(TournamentMatch, { foreignKey: 'player1Id', as: 'player1Matches' });
TournamentMember.hasMany(TournamentMatch, { foreignKey: 'player2Id', as: 'player2Matches' });
export {
User,
Log,
@@ -137,4 +179,9 @@ export {
Team,
Group,
GroupActivity,
Tournament,
TournamentGroup,
TournamentMember,
TournamentMatch,
TournamentResult,
};

View File

@@ -0,0 +1,31 @@
import express from 'express';
import {
getTournaments,
addTournament,
addParticipant,
getParticipants,
setModus,
createGroups,
fillGroups,
getGroups,
getTournament,
getTournamentMatches,
addMatchResult,
} from '../controllers/tournamentController.js';
import { authenticate } from '../middleware/authMiddleware.js';
const router = express.Router();
router.post('/participant', authenticate, addParticipant);
router.post('/participants', authenticate, getParticipants);
router.post('/modus', authenticate, setModus);
router.put('/groups', authenticate, createGroups);
router.post('/groups', authenticate, fillGroups);
router.get('/groups', authenticate, getGroups);
router.post('/match/result', authenticate, addMatchResult);
router.get('/matches/:clubId/:tournamentId', authenticate, getTournamentMatches);
router.get('/:clubId/:tournamentId', authenticate, getTournament);
router.get('/:clubId', authenticate, getTournaments);
router.post('/', authenticate, addTournament);
export default router;

View File

@@ -7,7 +7,12 @@ import {
User, Log, Club, UserClub, Member, DiaryDate, Participant, Activity, MemberNote,
DiaryNote, DiaryTag, MemberDiaryTag, DiaryDateTag, DiaryMemberNote, DiaryMemberTag,
PredefinedActivity, DiaryDateActivity, Match, League, Team, Group,
GroupActivity
GroupActivity,
Tournament,
TournamentGroup,
TournamentMatch,
TournamentResult,
TournamentMember
} from './models/index.js';
import authRoutes from './routes/authRoutes.js';
import clubRoutes from './routes/clubRoutes.js';
@@ -27,6 +32,7 @@ import Location from './models/Location.js';
import groupRoutes from './routes/groupRoutes.js';
import diaryDateTagRoutes from './routes/diaryDateTagRoutes.js';
import sessionRoutes from './routes/sessionRoutes.js';
import tournamentRoutes from './routes/tournamentRoutes.js';
const app = express();
const port = process.env.PORT || 3000;
@@ -53,6 +59,7 @@ app.use('/api/matches', matchRoutes);
app.use('/api/group', groupRoutes);
app.use('/api/diarydatetags', diaryDateTagRoutes);
app.use('/api/session', sessionRoutes);
app.use('/api/tournament', tournamentRoutes);
app.use(express.static(path.join(__dirname, '../frontend/dist')));
@@ -88,6 +95,11 @@ app.get('*', (req, res) => {
await Match.sync({ alter: true });
await Group.sync({ alter: true });
await GroupActivity.sync({ alter: true });
await Tournament.sync({ alter: true });
await TournamentGroup.sync({ alter: true });
await TournamentMember.sync({ alter: true });
await TournamentMatch.sync({ alter: true });
await TournamentResult.sync({ alter: true });
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);

View File

@@ -0,0 +1,249 @@
import Club from "../models/Club.js";
import Member from "../models/Member.js";
import Tournament from "../models/Tournament.js";
import TournamentGroup from "../models/TournamentGroup.js";
import TournamentMatch from "../models/TournamentMatch.js";
import TournamentMember from "../models/TournamentMember.js";
import { checkAccess } from '../utils/userUtils.js';
class TournamentService {
async getTournaments(userToken, clubId) {
await checkAccess(userToken, clubId);
const tournaments = await Tournament.findAll(
{
where: { clubId },
order: [['date', 'DESC']],
attributes: ['id', 'name', 'date']
}
);
return JSON.parse(JSON.stringify(tournaments));
}
async addTournament(userToken, clubId, tournamentName, date) {
await checkAccess(userToken, clubId);
const club = await Club.findByPk(clubId);
await Tournament.create({
name: tournamentName,
date: date,
clubId: club.id,
bestOfEndroundSize: 0,
type: '',
name: '',
});
return await this.getTournaments(userToken, clubId);
}
async addParticipant(token, clubId, tournamentId, participantId) {
await checkAccess(token, clubId);
const tournament = await Tournament.findByPk(tournamentId);
if (!tournament || tournament.clubId != clubId) {
throw new Error('Tournament not found');
}
const participant = TournamentMember.findAll({
where: { tournamentId: tournamentId, groupId: participantId, clubMemberId: participantId },
});
if (participant) {
throw new Error('Participant already exists');
}
await TournamentMember.create({
tournamentId: tournamentId,
groupId: participantId,
clubMemberId: participantId,
});
}
async getParticipants(token, clubId, tournamentId) {
await checkAccess(token, clubId);
const tournament = await Tournament.findByPk(tournamentId);
if (!tournament || tournament.clubId != clubId) {
throw new Error('Tournament not found');
}
return await TournamentMember.findAll({
where: {
tournamentId: tournamentId,
},
include: [
{
model: Member,
as: 'member',
attributes: ['id', 'lastName', 'firstName'],
order: [['firstName', 'ASC'], ['lastName', 'ASC']],
}
]
});
}
async setModus(token, clubId, tournamentId, type, numberOfGroups) {
await checkAccess(token, clubId);
const tournament = await Tournament.findByPk(tournamentId);
if (!tournament || tournament.clubId != clubId) {
throw new Error('Tournament not found');
}
await tournament.update({ type, numberOfGroups });
}
async createGroups(token, clubId, tournamentId) {
await checkAccess(token, clubId);
const tournament = await Tournament.findByPk(tournamentId);
if (!tournament || tournament.clubId != clubId) {
throw new Error('Tournament not found');
}
const existingGroups = await TournamentGroup.findAll({ where: { tournamentId } });
const desiredGroupCount = tournament.numberOfGroups;
if (existingGroups.length < desiredGroupCount) {
const missingGroups = desiredGroupCount - existingGroups.length;
for (let i = 0; i < missingGroups; i++) {
await TournamentGroup.create({ tournamentId });
}
} else if (existingGroups.length > desiredGroupCount) {
existingGroups.sort((a, b) => a.id - b.id);
const groupsToRemove = existingGroups.slice(desiredGroupCount);
for (const group of groupsToRemove) {
await group.destroy();
}
}
}
async fillGroups(token, clubId, tournamentId) {
await checkAccess(token, clubId);
const tournament = await Tournament.findByPk(tournamentId);
if (!tournament || tournament.clubId != clubId) {
throw new Error('Tournament not found');
}
const groups = await TournamentGroup.findAll({ where: { tournamentId } });
if (!groups || groups.length === 0) {
throw new Error('No groups available. Please create groups first.');
}
const members = await TournamentMember.findAll({ where: { tournamentId } });
if (!members || members.length === 0) {
throw new Error('No tournament members found.');
}
await TournamentMatch.destroy({ where: { tournamentId } });
const shuffledMembers = [...members];
for (let i = shuffledMembers.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffledMembers[i], shuffledMembers[j]] = [shuffledMembers[j], shuffledMembers[i]];
}
const numberOfGroups = groups.length;
for (let i = 0; i < shuffledMembers.length; i++) {
const groupAssignment = groups[i % numberOfGroups].id;
await shuffledMembers[i].update({ groupId: groupAssignment });
}
for (const group of groups) {
const groupMembers = await TournamentMember.findAll({ where: { groupId: group.id } });
for (let i = 0; i < groupMembers.length; i++) {
for (let j = i + 1; j < groupMembers.length; j++) {
await TournamentMatch.create({
tournamentId: tournamentId,
groupId: group.id,
round: 'group',
player1Id: groupMembers[i].id,
player2Id: groupMembers[j].id,
});
}
}
}
return await TournamentMember.findAll({ where: { tournamentId } });
}
async getGroups(token, clubId, tournamentId) {
await checkAccess(token, clubId);
const tournament = await Tournament.findByPk(tournamentId);
if (!tournament || tournament.clubId != clubId) {
throw new Error('Tournament not found');
}
const groups = await TournamentGroup.findAll({ where: { tournamentId } });
return groups;
}
async getGroupsWithParticipants(token, clubId, tournamentId) {
await checkAccess(token, clubId);
const tournament = await Tournament.findByPk(tournamentId);
if (!tournament || tournament.clubId != clubId) {
throw new Error('Tournament not found');
}
const groups = await TournamentGroup.findAll({
where: { tournamentId },
include: [
{
model: TournamentMember,
as: 'tournamentGroupMembers',
required: false,
include: [
{
model: Member,
as: 'member',
attributes: ['id', 'firstName', 'lastName']
}
]
}
],
order: [['id', 'ASC']]
});
return groups.map(group => ({
groupId: group.id,
participants: group.tournamentGroupMembers.map(p => ({
id: p.id,
name: `${p.member.firstName} ${p.member.lastName}`
}))
}));
}
async getTournament(token, clubId, tournamentId) {
await checkAccess(token, clubId);
const tournament = await Tournament.findOne({
where: { id: tournamentId, clubId },
});
if (!tournament) {
throw new Error('Tournament not found');
}
return tournament;
}
async getTournamentMatches(token, clubId, tournamentId) {
await checkAccess(token, clubId);
const tournament = await Tournament.findOne({
where: { id: tournamentId, clubId },
});
if (!tournament) {
throw new Error('Tournament not found');
}
const matches = await TournamentMatch.findAll({
where: { tournamentId },
include: [
{
model: TournamentMember,
as: 'player1',
include: {
model: Member,
as: 'member',
}
},
{
model: TournamentMember,
as: 'player2',
include: {
model: Member,
as: 'member',
}
}
],
order: [['id', 'ASC']]
});
return matches;
}
async addMatchResult(token, clubId, tournamentId, matchId, result) {
await checkAccess(token, clubId);
const match = await TournamentMatch.findByPk(matchId);
if (!match || match.tournamentId != tournamentId) {
throw new Error("Match not found or doesn't belong to this tournament");
}
match.result = result;
await match.save();
}
}
export default new TournamentService();

View File

@@ -22,6 +22,7 @@
<a href="/diary">Tagebuch</a>
<a href="/pending-approvals">Freigaben</a>
<a href="/schedule">Spielpläne</a>
<a href="/tournaments">Turniere</a>
</div>
<div class="logout-btn">

View File

@@ -9,6 +9,7 @@ import MembersView from './views/MembersView.vue';
import DiaryView from './views/DiaryView.vue';
import PendingApprovalsView from './views/PendingApprovalsView.vue';
import ScheduleView from './views/ScheduleView.vue';
import TournamentsView from './views/TournamentsView.vue';
const routes = [
{ path: '/register', component: Register },
@@ -21,6 +22,7 @@ const routes = [
{ path: '/diary', component: DiaryView },
{ path: '/pending-approvals', component: PendingApprovalsView},
{ path: '/schedule', component: ScheduleView},
{ path: '/tournaments', component: TournamentsView },
];
const router = createRouter({

View File

@@ -1004,23 +1004,11 @@ export default {
},
playBellSound() {
this.bellSound.play()
.then(() => {
console.log("Bell sound played successfully");
})
.catch(error => {
console.error("Error playing bell sound:", error);
});
this.bellSound.play();
},
playThumbSound() {
this.thumbSound.play()
.then(() => {
console.log("Thumb sound played successfully");
})
.catch(error => {
console.error("Error playing thumb sound:", error);
});
this.thumbSound.play();
},
calculateIntermediateTimes() {

View File

@@ -0,0 +1,289 @@
<template>
<div>
<h2>Turnier</h2>
<div>
<div>
<h3>Datum</h3>
<div>
<select v-model="selectedDate">
<option value="new">Neues Turnier</option>
<option v-for="date in dates" :key="date.id" :value="date.id">
{{ new Date(date.date).toLocaleDateString('de-DE', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
}) }}
</option>
</select>
</div>
<template v-if="selectedDate === 'new'">
<div>
<input type="date" v-model="newDate" />
<button @click="createTournament">Erstellen</button>
</div>
</template>
<template v-else>
<div>
<h3>Turnier</h3>
<div>
<div>
<label>
<input type="checkbox" v-model="isGroupTournament">
Spielen in Gruppen
</label>
</div>
<div>
<h4>Teilnehmer</h4>
<ul>
<li v-for="participant in participants" :key="participant.id">
{{ participant.member.firstName }} {{ participant.member.lastName }}
</li>
</ul>
<select v-model="selectedMember">
<option v-for="member in clubMembers" :key="member.id" :value="member.id">
{{ member.firstName }} {{ member.lastName }}
</option>
</select>
<button type="button" @click="addParticipant">Hinzufügen</button>
</div>
<div v-if="isGroupTournament && participants.length > 1">
<label>
Anzahl Gruppen:
<input type="number" v-model="numberOfGroups">
</label>
<button @click="createGroups">Gruppen erstellen</button>
<button @click="randomizeGroups">Zufällig verteilen</button>
</div>
<div v-if="groups && groups.length > 0">
<h4>Gruppen</h4>
<ul class="groupoverview">
<li v-for="group in groups" :key="group.groupId">
<h4>Gruppe {{ group.groupId }}</h4>
<table>
<thead>
<tr>
<th>Spielername</th>
<th>Bilanz</th>
</tr>
</thead>
<tbody>
<tr v-for="participant in group.participants" :key="participant.id">
<td>{{ participant.name }}</td>
<td></td>
</tr>
</tbody>
</table>
</li>
</ul>
<div>
<table>
<thead>
<tr>
<th>&nbsp;</th>
<th>Begegnung</th>
<th>Sätze</th>
<th>Ergebnis</th>
</tr>
</thead>
<tbody>
<tr v-for="match in matches" :key="match.id">
<td>{{ match.groupId ? "Gr " + match.groupId : match.round }}</td>
<td>{{ getPlayerName(match.player1) }} - {{ getPlayerName(match.player2) }}</td>
<td><input size="5" type="text" v-model="match.result" @keyup.enter="saveMatchResult(match, match.result)" /></td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import apiClient from '../apiClient';
export default {
name: 'TournamentsView',
computed: {
...mapGetters(['isAuthenticated', 'currentClub', 'clubs']),
},
data() {
return {
selectedDate: 'new',
newDate: '',
dates: [],
participants: [],
selectedMember: null,
clubMembers: [],
numberOfGroups: 1,
isGroupTournament: false,
groups: [],
matches: [],
};
},
watch: {
selectedDate: async function (newVal) {
if (newVal !== 'new') {
try {
const groupResponse = await apiClient.get(`/tournament/${this.currentClub}/${newVal}`);
this.isGroupTournament = groupResponse.data.type === 'groups';
const participantsResponse = await apiClient.post('/tournament/participants', {
clubId: this.currentClub,
tournamentId: newVal,
});
this.participants = participantsResponse.data;
} catch (error) {
console.error(error);
}
await this.fetchGroups();
}
},
isGroupTournament: async function (newVal) {
if (newVal) {
this.numberOfGroups = 2;
} else {
this.numberOfGroups = 1;
}
await apiClient.post('/tournament/modus', {
clubId: this.currentClub,
tournamentId: this.selectedDate,
type: newVal ? 'groups' : 'bestOf',
numberOfGroups: this.numberOfGroups,
});
},
numberOfGroups: async function (newVal) {
await apiClient.post('/tournament/modus', {
clubId: this.currentClub,
tournamentId: this.selectedDate,
type: this.isGroupTournament ? 'groups' : 'bestOf',
numberOfGroups: newVal,
});
}
},
async created() {
if (!this.isAuthenticated) {
this.$router.push('/login');
return;
}
try {
const responseDates = await apiClient.get(`/tournament/${this.currentClub}`);
this.dates = responseDates.data;
} catch (error) {
console.error('Error fetching tournaments:', error);
}
try {
const responseMembers = await apiClient.get(`/clubmembers/get/${this.currentClub}/false`);
this.clubMembers = responseMembers.data;
} catch (error) {
console.error('Error fetching club members:', error);
}
},
methods: {
async createTournament() {
try {
const response = await apiClient.post('/tournament', {
clubId: this.currentClub,
name: this.newDate,
date: this.newDate,
});
this.dates = response.data;
this.newDate = '';
} catch (error) {
console.error('Error creating tournament:', error);
}
},
async addParticipant() {
try {
const response = await apiClient.post('/tournament/participant', {
clubId: this.currentClub,
tournamentId: this.selectedDate,
participant: this.selectedMember,
});
this.participants = response.data;
} catch (error) {
console.error('Error adding participant:', error);
}
},
async createGroups() {
await apiClient.put('/tournament/groups', {
clubId: this.currentClub,
tournamentId: this.selectedDate,
});
await this.fetchGroups();
},
async randomizeGroups() {
try {
const response = await apiClient.post('/tournament/groups', {
clubId: this.currentClub,
tournamentId: this.selectedDate,
});
} catch (error) {
console.error('Error randomizing groups:', error);
}
await this.fetchGroups();
},
async fetchGroups() {
try {
const response = await apiClient.get('/tournament/groups', {
params: {
clubId: this.currentClub,
tournamentId: this.selectedDate
}
});
this.groups = response.data;
const matchesResponse = await apiClient.get(`/tournament/matches/${this.currentClub}/${this.selectedDate}`);
this.matches = matchesResponse.data;
console.log(this.matches);
} catch (error) {
console.error('Error fetching groups:', error);
}
},
getPlayerName(player) {
return player.member.firstName + ' ' + player.member.lastName;
},
async saveMatchResult(match, result) {
try {
await apiClient.post('/tournament/match/result', {
clubId: this.currentClub,
tournamentId: this.selectedDate,
matchId: match.matchId,
result: result,
});
match.result = result; // Aktualisiere das Match in der UI
} catch (error) {
console.error('Error saving match result:', error);
}
}
},
};
</script>
<style scoped>
.tournaments {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
.groupoverview {
display: flex;
flex-direction: row;
align-items: baseline;
justify-content: left;
padding: 0;
}
.groupoverview li {
list-style-type: none;
margin: 0;
padding: 0;
}
</style>