feat(MatchReportApiDialog, ScheduleLayoutShell, ScheduleView): enhance lineup management and layout improvements
- Updated MatchReportApiDialog.vue to improve lineup tab accessibility based on team status. - Enhanced player selection filtering to ensure only valid players are displayed in lineups. - Modified ScheduleLayoutShell.vue to adjust overflow properties for better layout handling. - Improved ScheduleView.vue with new methods for sorting matches by date and combining league matches, enhancing match display and user experience. - Added sticky header styling for better visibility in match lists.
This commit is contained in:
@@ -27,15 +27,15 @@
|
||||
<span>{{ $t('matchReportApi.general') }}</span>
|
||||
</button>
|
||||
|
||||
<button class="section-btn" :class="{ active: activeSection === 'homeLineup', certified: isHomeLineupCertified, disabled: teamNotAppeared === 'home' }"
|
||||
@click="setActiveSection('homeLineup')" :disabled="teamNotAppeared === 'home'">
|
||||
<button class="section-btn" :class="{ active: activeSection === 'homeLineup', certified: isHomeLineupCertified, disabled: !canOpenLineupTab('home') }"
|
||||
@click="setActiveSection('homeLineup')" :disabled="!canOpenLineupTab('home')">
|
||||
<div class="section-icon">👥</div>
|
||||
<span>{{ $t('matchReportApi.homeLineup') }}</span>
|
||||
<span v-if="isHomeLineupCertified" class="certified-badge">✓</span>
|
||||
</button>
|
||||
|
||||
<button class="section-btn" :class="{ active: activeSection === 'guestLineup', certified: isGuestLineupCertified, disabled: teamNotAppeared === 'guest' }"
|
||||
@click="setActiveSection('guestLineup')" :disabled="teamNotAppeared === 'guest'">
|
||||
<button class="section-btn" :class="{ active: activeSection === 'guestLineup', certified: isGuestLineupCertified, disabled: !canOpenLineupTab('guest') }"
|
||||
@click="setActiveSection('guestLineup')" :disabled="!canOpenLineupTab('guest')">
|
||||
<div class="section-icon">👥</div>
|
||||
<span>{{ $t('matchReportApi.guestLineup') }}</span>
|
||||
<span v-if="isGuestLineupCertified" class="certified-badge">✓</span>
|
||||
@@ -160,7 +160,7 @@
|
||||
<div v-if="meetingDetails && meetingDetails.teamLineupHomePlayers" class="lineup-section">
|
||||
<h4>{{ $t('matchReportApi.selectedPlayers') }}</h4>
|
||||
<div class="players-grid">
|
||||
<div v-for="player in meetingDetails.teamLineupHomePlayers.filter(p => p.isSelected)"
|
||||
<div v-for="player in meetingDetails.teamLineupHomePlayers.filter(p => p.isSelected && p.nuLigaPersonId > 0)"
|
||||
:key="player.nuLigaPersonId" class="player-card selected">
|
||||
<div class="player-main" @click="togglePlayerSelection(player, 'home')">
|
||||
<div class="player-name">{{ player.firstname }} {{ player.lastname }}</div>
|
||||
@@ -254,7 +254,7 @@
|
||||
<div v-if="meetingDetails && meetingDetails.teamLineupGuestPlayers" class="lineup-section">
|
||||
<h4>{{ $t('matchReportApi.selectedPlayers') }}</h4>
|
||||
<div class="players-grid">
|
||||
<div v-for="player in meetingDetails.teamLineupGuestPlayers.filter(p => p.isSelected)"
|
||||
<div v-for="player in meetingDetails.teamLineupGuestPlayers.filter(p => p.isSelected && p.nuLigaPersonId > 0)"
|
||||
:key="player.nuLigaPersonId" class="player-card selected">
|
||||
<div class="player-main" @click="togglePlayerSelection(player, 'guest')">
|
||||
<div class="player-name">{{ player.firstname }} {{ player.lastname }}</div>
|
||||
@@ -849,7 +849,7 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
if (this.teamNotAppeared !== null) {
|
||||
return false;
|
||||
}
|
||||
return this.canOpenNextStages;
|
||||
return this.areBothLineupsCertified();
|
||||
},
|
||||
canOpenCompletionStage() {
|
||||
if (this.isMatchCompleted) {
|
||||
@@ -869,6 +869,12 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
|
||||
// Spezielle Behandlung für Braunschweiger System
|
||||
if (matrixConfig && typeof matrixConfig === 'object' && matrixConfig.matrices) {
|
||||
const serverMatrix = this.getBraunschweigerServerMatrix();
|
||||
if (Array.isArray(serverMatrix) && serverMatrix.length > 0) {
|
||||
console.log('🎯 Braunschweiger System: verwende Server-Matrix', serverMatrix);
|
||||
return serverMatrix;
|
||||
}
|
||||
|
||||
const homePlayerCount = this.getEffectivePlayerCount('home');
|
||||
const guestPlayerCount = this.getEffectivePlayerCount('guest');
|
||||
|
||||
@@ -876,6 +882,7 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
const playerCountKey = `${homePlayerCount}-${guestPlayerCount}`;
|
||||
|
||||
console.log(`🎯 Braunschweiger System: ${homePlayerCount} vs ${guestPlayerCount} → Key: ${playerCountKey}`);
|
||||
this.logBraunschweigerDebugSnapshot(`Matrix-Auswahl ${playerCountKey}`);
|
||||
|
||||
// Verwende spezifische Matrix oder Fallback
|
||||
return matrixConfig.matrices[playerCountKey] || matrixConfig.default || [];
|
||||
@@ -950,7 +957,7 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
}
|
||||
|
||||
if (newValue === 'home') {
|
||||
this.isHomeLineupCertified = false;
|
||||
this.setLineupCertificationState('home', false);
|
||||
this.homePin = '';
|
||||
this.finalHomePin = '';
|
||||
this.activeSection = 'completion';
|
||||
@@ -958,7 +965,7 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
}
|
||||
|
||||
if (newValue === 'guest') {
|
||||
this.isGuestLineupCertified = false;
|
||||
this.setLineupCertificationState('guest', false);
|
||||
this.guestPin = '';
|
||||
this.finalGuestPin = '';
|
||||
this.activeSection = 'completion';
|
||||
@@ -971,6 +978,41 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
logBraunschweigerDebugSnapshot(context, payload = this.meetingDetails) {
|
||||
if (!payload || typeof payload !== 'object') {
|
||||
console.log(`[Braunschweiger Debug] ${context}: keine Daten`);
|
||||
return;
|
||||
}
|
||||
|
||||
const summarizeTeam = (teamKey) => {
|
||||
const players = Array.isArray(payload[teamKey]) ? payload[teamKey] : [];
|
||||
return players.map(player => ({
|
||||
id: player?.nuLigaPersonId ?? null,
|
||||
name: [player?.firstname || player?.firstName || '', player?.lastname || player?.lastName || ''].filter(Boolean).join(' ').trim(),
|
||||
selected: Boolean(player?.isSelected),
|
||||
positionSingle: player?.positionSingle ?? null,
|
||||
positionDouble: player?.positionDouble ?? null,
|
||||
positions: Array.isArray(player?.positions) ? [...player.positions] : []
|
||||
}));
|
||||
};
|
||||
|
||||
const matches = Array.isArray(payload.matches)
|
||||
? payload.matches.slice(0, 10).map((match, index) => ({
|
||||
index: index + 1,
|
||||
homePlayer: match?.homePlayer ?? '',
|
||||
guestPlayer: match?.guestPlayer ?? '',
|
||||
matchNumber: match?.matchNumber ?? null
|
||||
}))
|
||||
: [];
|
||||
|
||||
console.log(`[Braunschweiger Debug] ${context}`, {
|
||||
playMode: payload.playMode || this.meetingData?.playMode || this.meetingData?.matchSystem || this.meetingData?.system || null,
|
||||
homePlayers: summarizeTeam('teamLineupHomePlayers'),
|
||||
guestPlayers: summarizeTeam('teamLineupGuestPlayers'),
|
||||
matches
|
||||
});
|
||||
},
|
||||
|
||||
getFriendlySubmitErrorMessage(message) {
|
||||
const normalized = (message || '').toString();
|
||||
|
||||
@@ -1696,7 +1738,9 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
const result = await response.json();
|
||||
|
||||
if (result?.object) {
|
||||
this.meetingDetails = JSON.parse(JSON.stringify(result.object));
|
||||
const hydratedResult = JSON.parse(JSON.stringify(result.object));
|
||||
this.applyCurrentLineupStateToPayload(hydratedResult);
|
||||
this.meetingDetails = hydratedResult;
|
||||
this.meetingData = {
|
||||
...(this.meetingData || {}),
|
||||
...JSON.parse(JSON.stringify(result.object))
|
||||
@@ -1773,6 +1817,12 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
matchData.guestPin = this.finalGuestPin.trim();
|
||||
}
|
||||
|
||||
const signature = this.ensureSignatureContainer(matchData);
|
||||
if (signature) {
|
||||
signature.lineupSignatureHome = this.isHomeLineupCertified ? 'confirmed' : '';
|
||||
signature.lineupSignatureGuest = this.isGuestLineupCertified ? 'confirmed' : '';
|
||||
}
|
||||
|
||||
// Zwischenstände dürfen nie als bereits freigegeben an nuscore zurückgeschickt werden.
|
||||
matchData.isCompleted = finalizeReport;
|
||||
|
||||
@@ -1786,7 +1836,10 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
matchData.playerCountHome = this.getSelectedPlayerCount('home');
|
||||
matchData.playerCountGuest = this.getSelectedPlayerCount('guest');
|
||||
|
||||
// 1.1 Player-Positionen aktualisieren (Einzel + Doppel Positionen erfassen)
|
||||
// 1.1 Lokalen Aufstellungszustand in den Payload übernehmen
|
||||
this.applyCurrentLineupStateToPayload(matchData);
|
||||
|
||||
// 1.2 Player-Positionen aktualisieren (Einzel + Doppel Positionen erfassen)
|
||||
this.updatePlayerPositions(matchData);
|
||||
|
||||
// 2. Zeitangaben aktualisieren
|
||||
@@ -1920,8 +1973,11 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
// Verwende positionSingle falls verfügbar, sonst rank für Einzel-Position
|
||||
const singlePos = player.positionSingle || player.rank;
|
||||
if (singlePos) {
|
||||
player.positionSingle = singlePos;
|
||||
positions.push(`E${singlePos}`);
|
||||
}
|
||||
} else {
|
||||
player.positionSingle = null;
|
||||
}
|
||||
|
||||
// Doppel-Position NUR hinzufügen wenn Spieler Doppel-Position hat
|
||||
@@ -1944,8 +2000,11 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
// Verwende positionSingle falls verfügbar, sonst rank für Einzel-Position
|
||||
const singlePos = player.positionSingle || player.rank;
|
||||
if (singlePos) {
|
||||
player.positionSingle = singlePos;
|
||||
positions.push(`E${singlePos}`);
|
||||
}
|
||||
} else {
|
||||
player.positionSingle = null;
|
||||
}
|
||||
|
||||
// Doppel-Position NUR hinzufügen wenn Spieler Doppel-Position hat
|
||||
@@ -1961,16 +2020,62 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
console.log('✅ Player-Positionen aktualisiert');
|
||||
},
|
||||
|
||||
applyCurrentLineupStateToPayload(target) {
|
||||
if (!target || typeof target !== 'object' || !this.meetingDetails) {
|
||||
return;
|
||||
}
|
||||
|
||||
const copyTeamState = (teamKey) => {
|
||||
if (!Array.isArray(this.meetingDetails[teamKey]) || !Array.isArray(target[teamKey])) {
|
||||
return;
|
||||
}
|
||||
|
||||
const localByPersonId = new Map(
|
||||
this.meetingDetails[teamKey]
|
||||
.filter(player => player && player.nuLigaPersonId != null)
|
||||
.map(player => [String(player.nuLigaPersonId), player])
|
||||
);
|
||||
|
||||
target[teamKey] = target[teamKey].map((player) => {
|
||||
if (!player || player.nuLigaPersonId == null) {
|
||||
return player;
|
||||
}
|
||||
|
||||
const localPlayer = localByPersonId.get(String(player.nuLigaPersonId));
|
||||
if (!localPlayer) {
|
||||
return player;
|
||||
}
|
||||
|
||||
return {
|
||||
...player,
|
||||
isSelected: Boolean(localPlayer.isSelected),
|
||||
positionSingle: localPlayer.isSelected ? (localPlayer.positionSingle || null) : null,
|
||||
positionDouble: localPlayer.isSelected ? (localPlayer.positionDouble || null) : null,
|
||||
positions: Array.isArray(localPlayer.positions) ? [...localPlayer.positions] : []
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
copyTeamState('teamLineupHomePlayers');
|
||||
copyTeamState('teamLineupGuestPlayers');
|
||||
|
||||
const signature = this.ensureSignatureContainer(target);
|
||||
if (signature) {
|
||||
signature.lineupSignatureHome = this.isHomeLineupCertified ? 'confirmed' : '';
|
||||
signature.lineupSignatureGuest = this.isGuestLineupCertified ? 'confirmed' : '';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Zähle die ausgewählten Spieler für ein Team
|
||||
getSelectedPlayerCount(team) {
|
||||
try {
|
||||
if (team === 'home') {
|
||||
const homePlayers = this.meetingDetails?.teamLineupHomePlayers || this.teamLineupHomePlayers || [];
|
||||
return homePlayers.filter(p => p.isSelected === true).length;
|
||||
return homePlayers.filter(p => p.isSelected === true && p.nuLigaPersonId > 0).length;
|
||||
} else if (team === 'guest') {
|
||||
const guestPlayers = this.meetingDetails?.teamLineupGuestPlayers || this.teamLineupGuestPlayers || [];
|
||||
return guestPlayers.filter(p => p.isSelected === true).length;
|
||||
return guestPlayers.filter(p => p.isSelected === true && p.nuLigaPersonId > 0).length;
|
||||
}
|
||||
return 0;
|
||||
} catch (error) {
|
||||
@@ -2006,6 +2111,32 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
}
|
||||
},
|
||||
|
||||
formatMatchPlayerName(player) {
|
||||
if (!player || typeof player !== 'object') {
|
||||
return '';
|
||||
}
|
||||
return [player.firstname || player.firstName || '', player.lastname || player.lastName || '']
|
||||
.filter(Boolean)
|
||||
.join(' ')
|
||||
.trim();
|
||||
},
|
||||
|
||||
formatMeetingMatchSide(match, side) {
|
||||
if (!match || typeof match !== 'object') {
|
||||
return '';
|
||||
}
|
||||
|
||||
const firstPlayer = side === 'home' ? match.playerA1 : match.playerB1;
|
||||
const secondPlayer = side === 'home' ? match.playerA2 : match.playerB2;
|
||||
const firstName = this.formatMatchPlayerName(firstPlayer);
|
||||
const secondName = this.formatMatchPlayerName(secondPlayer);
|
||||
|
||||
if (firstName && secondName) {
|
||||
return `${firstName} / ${secondName}`;
|
||||
}
|
||||
return firstName || secondName || '';
|
||||
},
|
||||
|
||||
getMatchCountForPlayMode(playMode) {
|
||||
// Bestimme Anzahl der Spiele basierend auf Spielsystem
|
||||
switch (playMode) {
|
||||
@@ -2083,6 +2214,7 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
if (detailsResponse.ok) {
|
||||
this.meetingDetails = await detailsResponse.json();
|
||||
console.log('[nuscore] /meetingdetails response:', this.meetingDetails);
|
||||
this.logBraunschweigerDebugSnapshot('Server /meetingdetails');
|
||||
}
|
||||
} catch (detailsError) {
|
||||
console.warn('⚠️ Detaillierte Meeting-Daten konnten nicht geladen werden:', detailsError);
|
||||
@@ -2166,6 +2298,21 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
const src = sourceMatches[i] || {};
|
||||
const dst = this.results[i];
|
||||
|
||||
const resolvedHomeName = this.formatMeetingMatchSide(src, 'home');
|
||||
const resolvedGuestName = this.formatMeetingMatchSide(src, 'guest');
|
||||
const fallbackHomeName = typeof src.homePlayer === 'string' ? src.homePlayer.trim() : '';
|
||||
const fallbackGuestName = typeof src.guestPlayer === 'string' ? src.guestPlayer.trim() : '';
|
||||
|
||||
if (typeof src.name === 'string' && src.name.trim() !== '') {
|
||||
dst.label = src.name.trim();
|
||||
}
|
||||
if (resolvedHomeName || fallbackHomeName) {
|
||||
dst.homeName = resolvedHomeName || fallbackHomeName;
|
||||
}
|
||||
if (resolvedGuestName || fallbackGuestName) {
|
||||
dst.guestName = resolvedGuestName || fallbackGuestName;
|
||||
}
|
||||
|
||||
if (!dst.sets || !Array.isArray(dst.sets)) {
|
||||
this.$set(dst, 'sets', ['', '', '', '', '']);
|
||||
}
|
||||
@@ -2233,6 +2380,36 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
}
|
||||
},
|
||||
|
||||
ensureSignatureContainer(target) {
|
||||
if (!target || typeof target !== 'object') {
|
||||
return null;
|
||||
}
|
||||
if (!target.signature || typeof target.signature !== 'object') {
|
||||
target.signature = {};
|
||||
}
|
||||
return target.signature;
|
||||
},
|
||||
|
||||
setLineupCertificationState(team, certified) {
|
||||
const teamSuffix = team === 'home' ? 'Home' : 'Guest';
|
||||
const signatureField = `lineupSignature${teamSuffix}`;
|
||||
const signatureValue = certified ? 'confirmed' : '';
|
||||
|
||||
if (team === 'home') {
|
||||
this.isHomeLineupCertified = certified;
|
||||
} else {
|
||||
this.isGuestLineupCertified = certified;
|
||||
}
|
||||
|
||||
[this.meetingDetails, this.meetingData].forEach((source) => {
|
||||
const signature = this.ensureSignatureContainer(source);
|
||||
if (!signature) {
|
||||
return;
|
||||
}
|
||||
signature[signatureField] = signatureValue;
|
||||
});
|
||||
},
|
||||
|
||||
normalizeCertificationValue(value) {
|
||||
if (typeof value === 'boolean') return value;
|
||||
if (typeof value === 'number') {
|
||||
@@ -2351,6 +2528,13 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
});
|
||||
return {
|
||||
matches,
|
||||
signature: this.meetingDetails.signature ? { ...this.meetingDetails.signature } : undefined,
|
||||
teamLineupHomePlayers: Array.isArray(this.meetingDetails.teamLineupHomePlayers)
|
||||
? JSON.parse(JSON.stringify(this.meetingDetails.teamLineupHomePlayers))
|
||||
: undefined,
|
||||
teamLineupGuestPlayers: Array.isArray(this.meetingDetails.teamLineupGuestPlayers)
|
||||
? JSON.parse(JSON.stringify(this.meetingDetails.teamLineupGuestPlayers))
|
||||
: undefined,
|
||||
homePin: this.meetingDetails.homePin,
|
||||
guestPin: this.meetingDetails.guestPin,
|
||||
startDate: this.meetingData?.startDate ?? this.match?.startDate,
|
||||
@@ -2385,6 +2569,15 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
if (Array.isArray(matchData.matches)) {
|
||||
this.meetingDetails.matches = matchData.matches;
|
||||
}
|
||||
if (matchData.signature && typeof matchData.signature === 'object') {
|
||||
this.meetingDetails.signature = { ...(this.meetingDetails.signature || {}), ...matchData.signature };
|
||||
}
|
||||
if (Array.isArray(matchData.teamLineupHomePlayers)) {
|
||||
this.meetingDetails.teamLineupHomePlayers = matchData.teamLineupHomePlayers;
|
||||
}
|
||||
if (Array.isArray(matchData.teamLineupGuestPlayers)) {
|
||||
this.meetingDetails.teamLineupGuestPlayers = matchData.teamLineupGuestPlayers;
|
||||
}
|
||||
if (matchData.homePin != null) this.meetingDetails.homePin = matchData.homePin;
|
||||
if (matchData.guestPin != null) this.meetingDetails.guestPin = matchData.guestPin;
|
||||
if (matchData.startDate != null && this.meetingData) this.meetingData.startDate = matchData.startDate;
|
||||
@@ -2404,7 +2597,7 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
const pos = parseInt(token.replace(/[^0-9]/g, '')); // 1 oder 2
|
||||
const key = side === 'home' ? 'teamLineupHomePlayers' : 'teamLineupGuestPlayers';
|
||||
const list = (this.meetingDetails && this.meetingDetails[key]) ? this.meetingDetails[key] : [];
|
||||
const pair = list.filter(p => p.positionDouble === pos);
|
||||
const pair = list.filter(p => p.positionDouble === pos && p.nuLigaPersonId > 0);
|
||||
const n = (p) => [p.firstname || p.firstName || '', p.lastname || p.lastName || ''].filter(Boolean).join(' ').trim();
|
||||
|
||||
// Wenn ein Doppel-Paar gefunden wurde, verwende es
|
||||
@@ -2419,7 +2612,7 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
|
||||
// Falls kein Doppel gefunden, verwende die entsprechenden Spieler basierend auf der Position
|
||||
if (pair.length === 0) {
|
||||
const selectedPlayers = list.filter(p => p.isSelected);
|
||||
const selectedPlayers = list.filter(p => p.isSelected && p.nuLigaPersonId > 0);
|
||||
|
||||
|
||||
// Versuche verschiedene Sortierungen
|
||||
@@ -2476,7 +2669,7 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
const list = (this.meetingDetails && this.meetingDetails[key]) ? this.meetingDetails[key] : [];
|
||||
|
||||
// Prüfe zuerst, ob überhaupt genügend Spieler für diese Position vorhanden sind
|
||||
const selectedPlayers = list.filter(p => p.isSelected);
|
||||
const selectedPlayers = list.filter(p => p.isSelected && p.nuLigaPersonId > 0);
|
||||
|
||||
// Für Braunschweiger System: 2er-Mannschaften werden als 3er-Mannschaften gewertet
|
||||
let effectivePlayerCount = selectedPlayers.length;
|
||||
@@ -3290,6 +3483,7 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
this.meetingDetails[teamKey].forEach(player => {
|
||||
if (player.nuLigaPersonId > 0) {
|
||||
player.positions = [];
|
||||
player.positionSingle = null;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -3297,6 +3491,7 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
sortedByRank.forEach((player, index) => {
|
||||
const playerIndex = this.meetingDetails[teamKey].findIndex(p => p.nuLigaPersonId === player.nuLigaPersonId);
|
||||
if (playerIndex !== -1) {
|
||||
this.meetingDetails[teamKey][playerIndex].positionSingle = index + 1;
|
||||
this.meetingDetails[teamKey][playerIndex].positions = [`E${index + 1}`];
|
||||
}
|
||||
});
|
||||
@@ -3425,10 +3620,10 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
if (isValid) {
|
||||
// Aufstellung zertifizieren
|
||||
if (team === 'home') {
|
||||
this.isHomeLineupCertified = true;
|
||||
this.setLineupCertificationState('home', true);
|
||||
this.originalHomePin = pin; // Ursprüngliche PIN speichern
|
||||
} else {
|
||||
this.isGuestLineupCertified = true;
|
||||
this.setLineupCertificationState('guest', true);
|
||||
this.originalGuestPin = pin; // Ursprüngliche PIN speichern
|
||||
}
|
||||
|
||||
@@ -3707,6 +3902,69 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
}
|
||||
},
|
||||
|
||||
formatLineupPositionLabel(position, side) {
|
||||
if (typeof position !== 'string') {
|
||||
return '';
|
||||
}
|
||||
|
||||
const trimmedPosition = position.trim().toUpperCase();
|
||||
if (!trimmedPosition) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (trimmedPosition.startsWith('D')) {
|
||||
return `${side === 'home' ? 'DA' : 'DB'}${trimmedPosition.slice(1)}`;
|
||||
}
|
||||
|
||||
if (trimmedPosition.startsWith('E')) {
|
||||
return `${side === 'home' ? 'A' : 'B'}${trimmedPosition.slice(1)}`;
|
||||
}
|
||||
|
||||
return trimmedPosition;
|
||||
},
|
||||
getBraunschweigerServerMatrix() {
|
||||
const mapFormationsToLabels = (formations) => {
|
||||
if (!Array.isArray(formations) || formations.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return formations
|
||||
.map((formation) => {
|
||||
const homeLabel = this.formatLineupPositionLabel(formation?.homeLineupPosition, 'home');
|
||||
const guestLabel = this.formatLineupPositionLabel(formation?.guestLineupPosition, 'guest');
|
||||
|
||||
if (homeLabel && guestLabel) {
|
||||
return `${homeLabel} – ${guestLabel}`;
|
||||
}
|
||||
|
||||
if (typeof formation?.displayString === 'string' && formation.displayString.trim() !== '') {
|
||||
return formation.displayString.trim();
|
||||
}
|
||||
|
||||
return '';
|
||||
})
|
||||
.filter(Boolean);
|
||||
};
|
||||
|
||||
const meetingPlayModeFormations = mapFormationsToLabels(this.meetingDetails?.meetingPlayMode?.matchFormations);
|
||||
if (meetingPlayModeFormations && meetingPlayModeFormations.length > 0) {
|
||||
return meetingPlayModeFormations;
|
||||
}
|
||||
|
||||
const homePlayerCount = this.getEffectivePlayerCount('home');
|
||||
const guestPlayerCount = this.getEffectivePlayerCount('guest');
|
||||
const optionalMode = Array.isArray(this.meetingDetails?.optionalPlayModes)
|
||||
? this.meetingDetails.optionalPlayModes.find(mode =>
|
||||
Number(mode?.homePlayersCount) === Number(homePlayerCount) &&
|
||||
Number(mode?.guestPlayersCount) === Number(guestPlayerCount) &&
|
||||
Array.isArray(mode?.matchFormations) &&
|
||||
mode.matchFormations.length > 0
|
||||
)
|
||||
: null;
|
||||
|
||||
return mapFormationsToLabels(optionalMode?.matchFormations);
|
||||
},
|
||||
|
||||
|
||||
// Hole aktuellen Spielmodus (für Validierungen)
|
||||
getPlayThrough() {
|
||||
@@ -3886,10 +4144,10 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
console.log('✅ PIN erfolgreich - entsperre Aufstellung und wechsle Tab');
|
||||
|
||||
if (requiresHomePin) {
|
||||
this.isHomeLineupCertified = false;
|
||||
this.setLineupCertificationState('home', false);
|
||||
}
|
||||
if (requiresGuestPin) {
|
||||
this.isGuestLineupCertified = false;
|
||||
this.setLineupCertificationState('guest', false);
|
||||
}
|
||||
|
||||
const targetSection = requiresHomePin ? 'homeLineup' : 'guestLineup';
|
||||
@@ -3907,8 +4165,23 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
return team === 'home' ? this.isHomeLineupCertified : this.isGuestLineupCertified;
|
||||
},
|
||||
|
||||
areBothLineupsCertified() {
|
||||
return this.isHomeLineupCertified && this.isGuestLineupCertified;
|
||||
},
|
||||
|
||||
// Prüfe ob Aufstellung-Tab geöffnet werden kann
|
||||
canOpenLineupTab(team) {
|
||||
if ((team === 'home' && this.teamNotAppeared === 'home') ||
|
||||
(team === 'guest' && this.teamNotAppeared === 'guest')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const isTeamCertified = team === 'home' ? this.isHomeLineupCertified : this.isGuestLineupCertified;
|
||||
|
||||
if (isTeamCertified) {
|
||||
return this.areBothLineupsCertified();
|
||||
}
|
||||
|
||||
if (team === 'home') {
|
||||
return !this.isHomeLineupCertified;
|
||||
} else {
|
||||
@@ -3927,10 +4200,12 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr
|
||||
return;
|
||||
}
|
||||
|
||||
if ((section === 'homeLineup' && this.isHomeLineupCertified) ||
|
||||
(section === 'guestLineup' && this.isGuestLineupCertified)) {
|
||||
this.openPinModal(section);
|
||||
return;
|
||||
if (section === 'homeLineup' || section === 'guestLineup') {
|
||||
const team = section === 'homeLineup' ? 'home' : 'guest';
|
||||
|
||||
if (!this.canOpenLineupTab(team)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.activeSection = section;
|
||||
|
||||
@@ -213,7 +213,7 @@ export default {
|
||||
gap: 1rem;
|
||||
min-height: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.schedule-static-chrome {
|
||||
@@ -278,13 +278,15 @@ export default {
|
||||
align-items: stretch;
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.schedule-sidebar {
|
||||
width: 280px;
|
||||
flex: 0 0 280px;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.schedule-sidebar-card {
|
||||
@@ -300,6 +302,7 @@ export default {
|
||||
overflow-y: auto;
|
||||
margin-top: 0.75rem;
|
||||
padding-right: 0.25rem;
|
||||
max-height: calc(100vh - 300px);
|
||||
}
|
||||
|
||||
.schedule-team-list {
|
||||
@@ -408,6 +411,7 @@ export default {
|
||||
min-height: auto;
|
||||
height: auto;
|
||||
overflow: visible;
|
||||
max-height: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -428,7 +428,7 @@ export default {
|
||||
},
|
||||
leagueTeamOptions() {
|
||||
const ownTeamName = this.selectedTeam?.name;
|
||||
return Array.from(new Set(this.allLeagueMatches.flatMap(match => [
|
||||
return Array.from(new Set(this.getCombinedLeagueMatches().flatMap(match => [
|
||||
match.homeTeam?.name,
|
||||
match.guestTeam?.name
|
||||
].filter(Boolean))))
|
||||
@@ -507,6 +507,47 @@ export default {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
sortMatchesByDateTime(matches) {
|
||||
if (!Array.isArray(matches)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const toTimestamp = (match) => {
|
||||
if (!match?.date) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
const dateValue = new Date(match.date);
|
||||
if (isNaN(dateValue.getTime())) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
const timeString = typeof match.time === 'string' ? match.time : '';
|
||||
const [hours, minutes] = timeString.split(':').map((value) => parseInt(value, 10));
|
||||
|
||||
if (!Number.isNaN(hours)) {
|
||||
dateValue.setHours(hours, Number.isNaN(minutes) ? 0 : minutes, 0, 0);
|
||||
} else {
|
||||
dateValue.setHours(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
return dateValue.getTime();
|
||||
};
|
||||
|
||||
return [...matches].sort((a, b) => {
|
||||
const diff = toTimestamp(a) - toTimestamp(b);
|
||||
if (diff !== 0) {
|
||||
return diff;
|
||||
}
|
||||
|
||||
const homeA = a?.homeTeam?.name || '';
|
||||
const homeB = b?.homeTeam?.name || '';
|
||||
const guestA = a?.guestTeam?.name || '';
|
||||
const guestB = b?.guestTeam?.name || '';
|
||||
|
||||
return `${homeA} ${guestA}`.localeCompare(`${homeB} ${guestB}`);
|
||||
});
|
||||
},
|
||||
getResultClass(match) {
|
||||
if (!match.isCompleted) {
|
||||
return '';
|
||||
@@ -972,13 +1013,29 @@ export default {
|
||||
const response = await apiClient.get(`/matches/leagues/${this.currentClub}/matches/${leagueId}?scope=all`);
|
||||
this.allLeagueMatches = response.data;
|
||||
},
|
||||
getCombinedLeagueMatches() {
|
||||
const combined = [...(this.allLeagueMatches || []), ...(this.ownLeagueMatches || [])];
|
||||
const seenIds = new Set();
|
||||
|
||||
const uniqueMatches = combined.filter((match) => {
|
||||
const key = match?.id ?? `${match?.date || ''}-${match?.time || ''}-${match?.homeTeam?.name || ''}-${match?.guestTeam?.name || ''}`;
|
||||
if (seenIds.has(key)) {
|
||||
return false;
|
||||
}
|
||||
seenIds.add(key);
|
||||
return true;
|
||||
});
|
||||
|
||||
return this.sortMatchesByDateTime(uniqueMatches);
|
||||
},
|
||||
applyLeagueMatchScope() {
|
||||
if (!this.selectedTeam) {
|
||||
return;
|
||||
}
|
||||
const ownTeamName = this.selectedTeam.name;
|
||||
const combinedLeagueMatches = this.getCombinedLeagueMatches();
|
||||
if (this.leagueMatchScope === 'all') {
|
||||
this.matches = this.allLeagueMatches;
|
||||
this.matches = combinedLeagueMatches;
|
||||
return;
|
||||
}
|
||||
if (this.leagueMatchScope === 'other') {
|
||||
@@ -986,7 +1043,7 @@ export default {
|
||||
this.selectedComparisonTeamName = this.leagueTeamOptions[0];
|
||||
}
|
||||
this.matches = this.selectedComparisonTeamName
|
||||
? this.allLeagueMatches.filter(match =>
|
||||
? combinedLeagueMatches.filter(match =>
|
||||
match.homeTeam?.name === this.selectedComparisonTeamName ||
|
||||
match.guestTeam?.name === this.selectedComparisonTeamName
|
||||
)
|
||||
@@ -994,8 +1051,8 @@ export default {
|
||||
return;
|
||||
}
|
||||
this.matches = this.ownLeagueMatches.length > 0
|
||||
? this.ownLeagueMatches
|
||||
: this.allLeagueMatches.filter(match =>
|
||||
? this.sortMatchesByDateTime(this.ownLeagueMatches)
|
||||
: combinedLeagueMatches.filter(match =>
|
||||
match.homeTeam?.name === ownTeamName || match.guestTeam?.name === ownTeamName
|
||||
);
|
||||
},
|
||||
@@ -1016,7 +1073,7 @@ export default {
|
||||
try {
|
||||
const seasonParam = this.selectedSeasonId ? `?seasonid=${this.selectedSeasonId}` : '';
|
||||
const response = await apiClient.get(`/matches/leagues/${this.currentClub}/matches${seasonParam}`);
|
||||
this.matches = response.data;
|
||||
this.matches = this.sortMatchesByDateTime(response.data);
|
||||
} catch (error) {
|
||||
this.showInfo(this.$t('messages.error'), this.$t('schedule.errorLoadingOverallSchedule'), '', 'error');
|
||||
this.matches = [];
|
||||
@@ -1034,12 +1091,12 @@ export default {
|
||||
const response = await apiClient.get(`/matches/leagues/${this.currentClub}/matches${seasonParam}`);
|
||||
// Filtere nur Erwachsenenligen (keine Jugendligen)
|
||||
const allMatches = response.data;
|
||||
this.matches = allMatches.filter(match => {
|
||||
this.matches = this.sortMatchesByDateTime(allMatches.filter(match => {
|
||||
const leagueName = match.leagueDetails?.name || '';
|
||||
// Prüfe, ob es eine Jugendliga ist (J, M, Jugend im Namen)
|
||||
const isYouth = /[JM]\d|jugend/i.test(leagueName);
|
||||
return !isYouth;
|
||||
});
|
||||
}));
|
||||
} catch (error) {
|
||||
this.showInfo(this.$t('messages.error'), this.$t('schedule.errorLoadingAdultSchedule'), '', 'error');
|
||||
this.matches = [];
|
||||
@@ -1295,6 +1352,7 @@ export default {
|
||||
const idx = this.matches.findIndex(m => m.id === payload.matchId);
|
||||
if (idx !== -1) {
|
||||
this.matches.splice(idx, 1, payload.match);
|
||||
this.matches = this.sortMatchesByDateTime(this.matches);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1314,6 +1372,7 @@ export default {
|
||||
if (d.startDate) m.startDate = d.startDate;
|
||||
if (d.endDate) m.endDate = d.endDate;
|
||||
this.matches.splice(idx, 1, m);
|
||||
this.matches = this.sortMatchesByDateTime(this.matches);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2110,6 +2169,10 @@ li {
|
||||
background: linear-gradient(180deg, rgba(47, 122, 95, 0.08), rgba(47, 122, 95, 0.03));
|
||||
padding: 14px;
|
||||
margin-bottom: 12px;
|
||||
position: sticky;
|
||||
top: 12px;
|
||||
z-index: 5;
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
|
||||
.league-match-scope-header {
|
||||
|
||||
Reference in New Issue
Block a user