From 68f14eb5d651b8a9003bf66c2aea7d30b565b3dd Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Sat, 28 Mar 2026 11:15:38 +0100 Subject: [PATCH] feat(TournamentConfigTab, TournamentResultsTab): enhance stage configuration and knockout actions - Added ensureStageConfigurationPersisted method to validate and save stage advancements, ensuring proper configuration before advancing stages. - Updated advanceStage method to call ensureStageConfigurationPersisted, improving the flow of tournament advancement. - Introduced primary action buttons in TournamentResultsTab for starting and resetting knockout rounds, enhancing user interaction during tournament management. - Styled results-primary-actions for better visibility and usability in the results tab. --- .../tournament/TournamentConfigTab.vue | 49 +++++++++++++++++-- .../tournament/TournamentResultsTab.vue | 33 +++++++++++++ 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/tournament/TournamentConfigTab.vue b/frontend/src/components/tournament/TournamentConfigTab.vue index 10271ebd..302ee3e3 100644 --- a/frontend/src/components/tournament/TournamentConfigTab.vue +++ b/frontend/src/components/tournament/TournamentConfigTab.vue @@ -1962,6 +1962,33 @@ export default { this.stageConfig.error = e?.message || String(e); } }, + async ensureStageConfigurationPersisted(existingAdvancements = null) { + const advancements = Array.isArray(existingAdvancements) ? existingAdvancements : null; + if (advancements && advancements.length > 0) return; + + const { stages, advancements: builtAdvancements } = this.buildPayload(); + if (!Array.isArray(builtAdvancements) || builtAdvancements.length === 0) { + throw new Error(this.$t('tournaments.stageConfigLoadError')); + } + + for (const adv of builtAdvancements) { + const hasPools = Array.isArray(adv?.config?.pools) && adv.config.pools.length > 0; + if (!hasPools) { + const label = `${adv.fromStageIndex}→${adv.toStageIndex}`; + throw new Error(this.$t('tournaments.atLeastOnePoolRule', { label })); + } + } + + const saveRes = await apiClient.put('/tournament/stages', { + clubId: Number(this.clubId), + tournamentId: Number(this.tournamentId), + stages, + advancements: builtAdvancements, + }); + if (saveRes.status >= 400) { + throw new Error(saveRes.data?.error || this.$t('messages.saveFailed')); + } + }, async advanceStage(fromStageIndex, toStageIndex) { this.stageConfig.error = null; this.stageConfig.success = null; @@ -1973,14 +2000,28 @@ export default { tournamentId: Number(this.tournamentId) } }); - const stages = Array.isArray(getRes?.data?.stages) ? getRes.data.stages : []; - const normalized = stages.map(s => ({ + const advancements = Array.isArray(getRes?.data?.advancements) ? getRes.data.advancements : []; + + // Alte Turniere haben teilweise Stages, aber noch keine gespeicherten Advancements. + // Dann ziehen wir die Konfiguration vor dem eigentlichen Start automatisch nach. + await this.ensureStageConfigurationPersisted(advancements); + + const refreshedRes = advancements.length > 0 + ? getRes + : await apiClient.get('/tournament/stages', { + params: { + clubId: Number(this.clubId), + tournamentId: Number(this.tournamentId) + } + }); + const refreshedStages = Array.isArray(refreshedRes?.data?.stages) ? refreshedRes.data.stages : []; + const refreshedNormalized = refreshedStages.map(s => ({ stageIndex: Number(s.stageIndex ?? s.index ?? s.id), stageId: Number(s.id ?? s.stageId ?? s.stageIndex), type: s.type || s.targetType || s.target })); - const from = normalized.find(s => s.stageIndex === Number(fromStageIndex)); - const to = normalized.find(s => s.stageIndex === Number(toStageIndex)); + const from = refreshedNormalized.find(s => s.stageIndex === Number(fromStageIndex)); + const to = refreshedNormalized.find(s => s.stageIndex === Number(toStageIndex)); const payload = { clubId: Number(this.clubId), diff --git a/frontend/src/components/tournament/TournamentResultsTab.vue b/frontend/src/components/tournament/TournamentResultsTab.vue index e8df15a6..84a7e5b5 100644 --- a/frontend/src/components/tournament/TournamentResultsTab.vue +++ b/frontend/src/components/tournament/TournamentResultsTab.vue @@ -14,6 +14,27 @@ {{ liveMatchCount }} {{ $t('tournaments.statusLive') }} {{ finishedMatchCount }} {{ $t('tournaments.statusFinished') }} +
+ + +