feat(tournament): add participant gave-up functionality and UI updates
- Implemented setParticipantGaveUp and setExternalParticipantGaveUp methods in tournamentController to handle participant resignation. - Updated ExternalTournamentParticipant and TournamentMember models to include a gaveUp field for tracking resignation status. - Enhanced tournamentRoutes to include new endpoints for updating gave-up status. - Modified TournamentGroupsTab and TournamentParticipantsTab components to display and manage gave-up status visually. - Added localization strings for "gave up" and related hints in German. - Updated TournamentResultsTab to reflect gave-up status in match results.
This commit is contained in:
@@ -128,7 +128,7 @@
|
||||
<tr v-for="(pl, idx) in groupRankings[group.groupId]" :key="pl.id">
|
||||
<td><strong>G{{ String.fromCharCode(96 + group.groupNumber) }}{{ idx + 1 }}</strong></td>
|
||||
<td>{{ pl.position }}.</td>
|
||||
<td><span v-if="pl.seeded" class="seeded-star">★</span>{{ pl.name }}</td>
|
||||
<td><span v-if="pl.seeded" class="seeded-star">★</span>{{ pl.name }}<span v-if="pl.gaveUp" class="gave-up-badge" :title="$t('tournaments.gaveUpHint')">{{ $t('tournaments.gaveUp') }}</span></td>
|
||||
<td>{{ (pl.matchesWon || 0) * 2 }}:{{ (pl.matchesLost || 0) * 2 }}</td>
|
||||
<td>{{ pl.setsWon }}:{{ pl.setsLost }}</td>
|
||||
<td>
|
||||
@@ -513,5 +513,13 @@ export default {
|
||||
.merge-pools-actions {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.gave-up-badge {
|
||||
margin-left: 0.35rem;
|
||||
padding: 0.1rem 0.35rem;
|
||||
font-size: 0.75rem;
|
||||
background: #f8d7da;
|
||||
color: #721c24;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="participant-seeded-cell">{{ $t('tournaments.seeded') }}</th>
|
||||
<th class="participant-gave-up-cell">{{ $t('tournaments.gaveUp') }}</th>
|
||||
<th class="participant-name">{{ $t('tournaments.name') }}</th>
|
||||
<th v-if="allowsExternal" class="participant-gender-cell">{{ $t('members.gender') }}</th>
|
||||
<th v-if="allowsExternal" class="participant-club-cell">{{ $t('tournaments.club') }}</th>
|
||||
@@ -110,6 +111,11 @@
|
||||
<input type="checkbox" :checked="participant.seeded" @change="$emit('update-participant-seeded', participant, $event)" />
|
||||
</label>
|
||||
</td>
|
||||
<td class="participant-gave-up-cell">
|
||||
<label class="gave-up-checkbox-label" :title="$t('tournaments.gaveUpHint')">
|
||||
<input type="checkbox" :checked="participant.gaveUp" @change="$emit('update-participant-gave-up', participant, $event)" />
|
||||
</label>
|
||||
</td>
|
||||
<td class="participant-name">
|
||||
<template v-if="participant.member">
|
||||
{{ participant.member.firstName || $t('tournaments.unknown') }}
|
||||
@@ -168,6 +174,7 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="participant-seeded-cell">{{ $t('tournaments.seeded') }}</th>
|
||||
<th class="participant-gave-up-cell">{{ $t('tournaments.gaveUp') }}</th>
|
||||
<th class="participant-name">{{ $t('tournaments.name') }}</th>
|
||||
<th v-if="allowsExternal" class="participant-gender-cell">{{ $t('members.gender') }}</th>
|
||||
<th v-if="allowsExternal" class="participant-club-cell">{{ $t('tournaments.club') }}</th>
|
||||
@@ -186,6 +193,11 @@
|
||||
<input type="checkbox" :checked="participant.seeded" @change="$emit('update-participant-seeded', participant, $event)" />
|
||||
</label>
|
||||
</td>
|
||||
<td class="participant-gave-up-cell">
|
||||
<label class="gave-up-checkbox-label" :title="$t('tournaments.gaveUpHint')">
|
||||
<input type="checkbox" :checked="participant.gaveUp" @change="$emit('update-participant-gave-up', participant, $event)" />
|
||||
</label>
|
||||
</td>
|
||||
<td class="participant-name">
|
||||
<template v-if="participant.member">
|
||||
{{ participant.member.firstName || $t('tournaments.unknown') }}
|
||||
@@ -422,6 +434,7 @@ export default {
|
||||
'update:newExternalParticipant',
|
||||
'add-external-participant',
|
||||
'update-participant-seeded',
|
||||
'update-participant-gave-up',
|
||||
'update-participant-group',
|
||||
'update-participant-class',
|
||||
'remove-participant',
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
<template v-if="m.result === 'BYE'">
|
||||
BYE
|
||||
</template>
|
||||
<template v-else-if="matchHasGaveUp(m)">
|
||||
<span class="result-text gave-up-result">{{ formatResult(m) }}</span>
|
||||
<span v-if="m.player1?.gaveUp && m.player2?.gaveUp" class="gave-up-badge-small">({{ $t('tournaments.gaveUp') }})</span>
|
||||
</template>
|
||||
<template v-else-if="!m.isFinished">
|
||||
<template v-for="r in m.tournamentResults" :key="r.set">
|
||||
<template v-if="isEditing(m, r.set)">
|
||||
@@ -86,10 +90,15 @@
|
||||
{{ getSetsString(m) }}
|
||||
</td>
|
||||
<td>
|
||||
<button v-if="!m.isFinished" @click="$emit('finish-match', m)">Abschließen</button>
|
||||
<button v-else @click="$emit('reopen-match', m)" class="btn-correct">Korrigieren</button>
|
||||
<button v-if="!m.isFinished && !m.isActive" @click.stop="$emit('set-match-active', m, true)" class="btn-live" title="Als laufend markieren">▶️</button>
|
||||
<button v-if="!m.isFinished && m.isActive" @click.stop="$emit('set-match-active', m, false)" class="btn-live active" title="Laufend-Markierung entfernen">⏸️</button>
|
||||
<template v-if="matchHasGaveUp(m)">
|
||||
<span class="no-edit-hint">{{ $t('tournaments.gaveUp') }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button v-if="!m.isFinished" @click="$emit('finish-match', m)">Abschließen</button>
|
||||
<button v-else @click="$emit('reopen-match', m)" class="btn-correct">Korrigieren</button>
|
||||
<button v-if="!m.isFinished && !m.isActive" @click.stop="$emit('set-match-active', m, true)" class="btn-live" title="Als laufend markieren">▶️</button>
|
||||
<button v-if="!m.isFinished && m.isActive" @click.stop="$emit('set-match-active', m, false)" class="btn-live active" title="Laufend-Markierung entfernen">⏸️</button>
|
||||
</template>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -502,6 +511,9 @@ export default {
|
||||
isLastResult(match, result) {
|
||||
const arr = match.tournamentResults || [];
|
||||
return arr.length > 0 && arr[arr.length - 1].set === result.set;
|
||||
},
|
||||
matchHasGaveUp(match) {
|
||||
return match.gaveUpMatch || match.player1?.gaveUp || match.player2?.gaveUp;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -555,6 +567,19 @@ export default {
|
||||
color: #856404 !important;
|
||||
}
|
||||
|
||||
.gave-up-result {
|
||||
color: #626262;
|
||||
}
|
||||
.gave-up-badge-small {
|
||||
margin-left: 0.25rem;
|
||||
font-size: 0.8rem;
|
||||
color: #721c24;
|
||||
}
|
||||
.no-edit-hint {
|
||||
font-size: 0.85rem;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.active-match:hover {
|
||||
background-color: #ffe69c !important;
|
||||
}
|
||||
|
||||
@@ -595,6 +595,8 @@
|
||||
"noPlacementsYet": "Noch keine Platzierungen vorhanden.",
|
||||
"participants": "Teilnehmer",
|
||||
"seeded": "Gesetzt",
|
||||
"gaveUp": "Aufgegeben",
|
||||
"gaveUpHint": "Spieler hat aufgegeben – alle Spiele zählen für den Gegner (11:0) bzw. 0:0 bei beiden aufgegeben.",
|
||||
"club": "Verein",
|
||||
"class": "Klasse",
|
||||
"group": "Gruppe",
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
@update:newExternalParticipant="newExternalParticipant = $event"
|
||||
@add-external-participant="addExternalParticipant()"
|
||||
@update-participant-seeded="updateParticipantSeeded"
|
||||
@update-participant-gave-up="updateParticipantGaveUp"
|
||||
@update-participant-group="updateParticipantGroup"
|
||||
@update-participant-class="updateParticipantClass"
|
||||
@remove-participant="removeParticipant"
|
||||
@@ -485,6 +486,7 @@ export default {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
seeded: p.seeded || false,
|
||||
gaveUp: p.gaveUp || false,
|
||||
position: p.position || 0,
|
||||
points: p.points || 0,
|
||||
setsWon: p.setsWon || 0,
|
||||
@@ -1233,6 +1235,7 @@ export default {
|
||||
this.participants = (Array.isArray(pRes.data) ? pRes.data : []).map(p => ({
|
||||
...p,
|
||||
seeded: p.seeded || false,
|
||||
gaveUp: p.gaveUp || false,
|
||||
groupNumber: p.groupId ? (groupIdToNumberMap[p.groupId] || null) : null
|
||||
}));
|
||||
|
||||
@@ -1275,6 +1278,7 @@ export default {
|
||||
this.externalParticipants = (Array.isArray(allExternalParticipants) ? allExternalParticipants : []).map(p => ({
|
||||
...p,
|
||||
seeded: p.seeded || false,
|
||||
gaveUp: p.gaveUp || false,
|
||||
isExternal: true,
|
||||
groupNumber: p.groupId ? (groupIdToNumberMap[p.groupId] || null) : null
|
||||
}));
|
||||
@@ -2297,6 +2301,21 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
async updateParticipantGaveUp(participant, event) {
|
||||
const gaveUp = event.target.checked;
|
||||
participant.gaveUp = gaveUp;
|
||||
try {
|
||||
if (this.allowsExternal && participant.isExternal) {
|
||||
await apiClient.put(`/tournament/external-participant/${this.currentClub}/${this.selectedDate}/${participant.id}/gave-up`, { gaveUp });
|
||||
} else {
|
||||
await apiClient.put(`/tournament/participant/${this.currentClub}/${this.selectedDate}/${participant.id}/gave-up`, { gaveUp });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Aktualisieren des Aufgabe-Status:', error);
|
||||
await this.loadTournamentData();
|
||||
}
|
||||
},
|
||||
|
||||
async updateParticipantGroup(participant, event) {
|
||||
const value = event.target.value;
|
||||
const groupNumber = value === '' || value === 'null' ? null : parseInt(value);
|
||||
@@ -3467,7 +3486,9 @@ button {
|
||||
|
||||
/* Synchronisiere Spaltenbreiten zwischen Header und Body */
|
||||
.participants-table-header .participant-seeded-cell,
|
||||
.participants-table-body .participant-seeded-cell {
|
||||
.participants-table-body .participant-seeded-cell,
|
||||
.participants-table-header .participant-gave-up-cell,
|
||||
.participants-table-body .participant-gave-up-cell {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
@@ -3500,10 +3521,17 @@ button {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.participant-seeded-cell {
|
||||
.participant-seeded-cell,
|
||||
.participant-gave-up-cell {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.gave-up-checkbox-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.seeded-checkbox-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user