Erlaube das Hinzufügen von Teilnehmern ohne Klasse und normalisiere die Anzahl der Gruppen auf mindestens 1 in der Turnierverwaltung

This commit is contained in:
Torsten Schulz (local)
2025-12-13 12:25:17 +01:00
parent 0c28b12978
commit e83bc250a8
5 changed files with 316 additions and 83 deletions

View File

@@ -44,7 +44,13 @@
<div v-else class="groups-per-class">
<label>
{{ $t('tournaments.numberOfGroups') }}:
<input type="number" :value="numberOfGroups" @input="$emit('update:numberOfGroups', parseInt($event.target.value))" min="1" @change="$emit('group-count-change')" />
<input
type="number"
:value="numberOfGroups"
min="1"
@input="$emit('update:numberOfGroups', Math.max(1, parseInt($event.target.value || '1', 10) || 1))"
@change="$emit('group-count-change')"
/>
</label>
</div>

View File

@@ -1045,7 +1045,11 @@ export default {
this.currentTournamentDate = tournament.date || '';
this.currentWinningSets = tournament.winningSets || 3;
this.isGroupTournament = tournament.type === 'groups';
this.numberOfGroups = tournament.numberOfGroups;
// Defensive: Backend/DB kann (historisch/UI-default) 0/null liefern.
// Für gruppenbasierte Turniere ohne Klassen brauchen wir hier aber eine sinnvolle Zahl,
// sonst sendet die UI später wieder `0` an `/tournament/groups`.
const loadedGroups = Number(tournament.numberOfGroups);
this.numberOfGroups = Number.isFinite(loadedGroups) && loadedGroups > 0 ? loadedGroups : 1;
this.advancingPerGroup = tournament.advancingPerGroup;
// Prüfe, ob es einen Trainingstag für das Turnierdatum gibt
@@ -1429,6 +1433,9 @@ export default {
}, {});
const r = await apiClient.post('/tournament/participant', {
clubId: this.currentClub,
// Wenn ohne Klasse hinzugefügt wird, braucht das Backend die Turnier-ID.
// (Bei klassengebundenen Teilnehmern ist sie optional, schadet aber nicht.)
tournamentId: this.selectedDate,
classId: classId,
participant: this.selectedMember
});
@@ -1464,8 +1471,10 @@ export default {
async createGroups() {
try {
// Wenn Klassen vorhanden sind, verwende groupsPerClass
if (this.tournamentClasses.length > 0) {
// Wenn Klassen vorhanden sind, verwende groupsPerClass.
// Achtung: Auch für "Ohne Klasse" (selectedViewClass='__none__') ist das der richtige Pfad,
// sonst fällt die UI in den alten Fallback und sendet `numberOfGroups` (häufig 1).
if (this.tournamentClasses.length > 0 || this.selectedViewClass === '__none__') {
await apiClient.post('/tournament/groups/create', {
clubId: this.currentClub,
tournamentId: this.selectedDate,
@@ -1473,10 +1482,11 @@ export default {
});
} else {
// Fallback: Verwende numberOfGroups wie bisher
const desired = Math.max(1, parseInt(String(this.numberOfGroups), 10) || 1);
await apiClient.put('/tournament/groups', {
clubId: this.currentClub,
tournamentId: this.selectedDate,
numberOfGroups: this.numberOfGroups
numberOfGroups: desired
});
}
await this.loadTournamentData();
@@ -1666,11 +1676,12 @@ export default {
async onModusChange() {
const type = this.isGroupTournament ? 'groups' : 'knockout';
const desired = Math.max(1, parseInt(String(this.numberOfGroups), 10) || 1);
await apiClient.post('/tournament/modus', {
clubId: this.currentClub,
tournamentId: this.selectedDate,
type,
numberOfGroups: this.numberOfGroups,
numberOfGroups: desired,
advancingPerGroup: this.advancingPerGroup
});
await this.loadTournamentData();
@@ -1725,7 +1736,8 @@ export default {
async onGroupCountChange() {
// Wenn Klassen vorhanden sind, speichere groupsPerClass, sonst numberOfGroups
if (this.tournamentClasses.length > 0) {
// Hinweis: Bei "Ohne Klasse" wird groupsPerClass['null'] genutzt, auch wenn Klassen existieren.
if (this.tournamentClasses.length > 0 || this.selectedViewClass === '__none__') {
// Speichere groupsPerClass für die aktuelle Klasse
// Die Werte sind bereits in this.groupsPerClass gespeichert durch den setter von groupsPerClassInput
// Wir müssen nichts speichern, da groupsPerClass nur lokal verwendet wird
@@ -1733,11 +1745,12 @@ export default {
return;
} else {
// Fallback: Verwende numberOfGroups wie bisher
const desired = Math.max(1, parseInt(String(this.numberOfGroups), 10) || 1);
await apiClient.post('/tournament/modus', {
clubId: this.currentClub,
tournamentId: this.selectedDate,
type: this.isGroupTournament ? 'groups' : 'knockout',
numberOfGroups: this.numberOfGroups
numberOfGroups: desired
});
await this.loadTournamentData();
}
@@ -2407,6 +2420,7 @@ export default {
}
await apiClient.post('/tournament/participant', {
clubId: this.currentClub,
tournamentId: this.selectedDate,
classId: classId,
participant: participant.clubMemberId
});