Enhance match management functionality by adding player selection capabilities. Introduce new endpoints for updating match players and retrieving player match statistics in matchController and matchService. Update Match model to include fields for players ready, planned, and played. Modify frontend components to support player selection dialog, allowing users to manage player statuses effectively. Improve UI for better user experience and data visibility.

This commit is contained in:
Torsten Schulz (local)
2025-10-16 21:09:13 +02:00
parent e0d56ddadd
commit ea3cca563b
8 changed files with 919 additions and 125 deletions

View File

@@ -241,6 +241,9 @@ class MatchService {
guestMatchPoints: match.guestMatchPoints || 0,
isCompleted: match.isCompleted || false,
pdfUrl: match.pdfUrl,
playersReady: match.playersReady || [],
playersPlanned: match.playersPlanned || [],
playersPlayed: match.playersPlayed || [],
homeTeam: { name: 'Unbekannt' },
guestTeam: { name: 'Unbekannt' },
location: { name: 'Unbekannt', address: '', city: '', zip: '' },
@@ -353,6 +356,9 @@ class MatchService {
guestMatchPoints: match.guestMatchPoints || 0,
isCompleted: match.isCompleted || false,
pdfUrl: match.pdfUrl,
playersReady: match.playersReady || [],
playersPlanned: match.playersPlanned || [],
playersPlayed: match.playersPlayed || [],
homeTeam: { name: 'Unbekannt' },
guestTeam: { name: 'Unbekannt' },
location: { name: 'Unbekannt', address: '', city: '', zip: '' },
@@ -430,6 +436,118 @@ class MatchService {
}
}
async updateMatchPlayers(userToken, matchId, playersReady, playersPlanned, playersPlayed) {
// Find the match and verify access
const match = await Match.findByPk(matchId, {
include: [
{ model: Club, as: 'club' }
]
});
if (!match) {
throw new HttpError(404, 'Match not found');
}
await checkAccess(userToken, match.clubId);
// Update player arrays
await match.update({
playersReady: playersReady || [],
playersPlanned: playersPlanned || [],
playersPlayed: playersPlayed || []
});
return {
id: match.id,
playersReady: match.playersReady,
playersPlanned: match.playersPlanned,
playersPlayed: match.playersPlayed
};
}
async getPlayerMatchStats(userToken, clubId, leagueId, seasonId) {
await checkAccess(userToken, clubId);
// Get all matches for this league/season
const matches = await Match.findAll({
where: {
clubId: clubId,
leagueId: leagueId
},
attributes: ['id', 'date', 'playersPlayed']
});
// Get all members
const Member = (await import('../models/Member.js')).default;
const members = await Member.findAll({
where: { clubId: clubId, active: true },
attributes: ['id', 'firstName', 'lastName']
});
// Calculate stats
const stats = {};
const now = new Date();
// Saison startet am 1. Juli
const seasonStart = new Date();
seasonStart.setMonth(6, 1); // 1. Juli
seasonStart.setHours(0, 0, 0, 0);
if (seasonStart > now) {
seasonStart.setFullYear(seasonStart.getFullYear() - 1);
}
// Vorrunde: 1. Juli bis 31. Dezember
const firstHalfEnd = new Date(seasonStart.getFullYear(), 11, 31, 23, 59, 59, 999); // 31. Dezember
// Rückrunde startet am 1. Januar (im Jahr nach Saisonstart)
const secondHalfStart = new Date(seasonStart.getFullYear() + 1, 0, 1, 0, 0, 0, 0); // 1. Januar
for (const member of members) {
stats[member.id] = {
memberId: member.id,
firstName: member.firstName,
lastName: member.lastName,
totalSeason: 0,
totalFirstHalf: 0,
totalSecondHalf: 0
};
}
for (const match of matches) {
// Parse playersPlayed if it's a JSON string
let playersPlayed = match.playersPlayed;
if (typeof playersPlayed === 'string') {
try {
playersPlayed = JSON.parse(playersPlayed);
} catch (e) {
continue;
}
}
if (!playersPlayed || !Array.isArray(playersPlayed) || playersPlayed.length === 0) {
continue;
}
const matchDate = new Date(match.date);
const isInSeason = matchDate >= seasonStart;
const isInFirstHalf = matchDate >= seasonStart && matchDate <= firstHalfEnd;
const isInSecondHalf = matchDate >= secondHalfStart;
for (const playerId of playersPlayed) {
if (stats[playerId]) {
if (isInSeason) stats[playerId].totalSeason++;
if (isInFirstHalf) stats[playerId].totalFirstHalf++;
if (isInSecondHalf) stats[playerId].totalSecondHalf++;
}
}
}
// Convert to array, filter out players with 0 matches, and sort by totalSeason descending
return Object.values(stats)
.filter(player => player.totalSeason > 0)
.sort((a, b) => b.totalSeason - a.totalSeason);
}
}
export default new MatchService();