Merge branch 'httv'
This commit is contained in:
@@ -135,11 +135,35 @@ class TrainingStatsController {
|
||||
// Nach Gesamtteilnahme absteigend sortieren
|
||||
stats.sort((a, b) => b.participationTotal - a.participationTotal);
|
||||
|
||||
// Trainingstage mit Teilnehmerzahlen abrufen (letzte 12 Monate, absteigend sortiert)
|
||||
const trainingDays = await DiaryDate.findAll({
|
||||
where: {
|
||||
clubId: parseInt(clubId),
|
||||
date: {
|
||||
[Op.gte]: twelveMonthsAgo
|
||||
}
|
||||
},
|
||||
include: [{
|
||||
model: Participant,
|
||||
as: 'participantList',
|
||||
attributes: ['id']
|
||||
}],
|
||||
order: [['date', 'DESC']]
|
||||
});
|
||||
|
||||
// Formatiere Trainingstage mit Teilnehmerzahl
|
||||
const formattedTrainingDays = trainingDays.map(day => ({
|
||||
id: day.id,
|
||||
date: day.date,
|
||||
participantCount: day.participantList ? day.participantList.length : 0
|
||||
}));
|
||||
|
||||
// Zusätzliche Metadaten mit Trainingsanzahl zurückgeben
|
||||
res.json({
|
||||
members: stats,
|
||||
trainingsCount12Months,
|
||||
trainingsCount3Months
|
||||
trainingsCount3Months,
|
||||
trainingDays: formattedTrainingDays
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
|
||||
@@ -19,8 +19,43 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="members-table-container">
|
||||
<table class="members-table">
|
||||
<!-- Trainingstage-Tabelle (standardmäßig aufgeklappt) -->
|
||||
<div class="collapsible-section">
|
||||
<div class="section-header" @click="toggleTrainingDays">
|
||||
<h3>Trainingstage (letzte 12 Monate)</h3>
|
||||
<span class="toggle-icon">{{ showTrainingDays ? '▼' : '▶' }}</span>
|
||||
</div>
|
||||
<div v-if="showTrainingDays" class="section-content">
|
||||
<div class="training-days-container">
|
||||
<table class="training-days-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Datum</th>
|
||||
<th>Wochentag</th>
|
||||
<th>Teilnehmer</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="day in trainingDays" :key="day.id">
|
||||
<td>{{ formatDate(day.date) }}</td>
|
||||
<td>{{ getWeekday(day.date) }}</td>
|
||||
<td>{{ day.participantCount }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mitglieder-Tabelle (standardmäßig eingeklappt) -->
|
||||
<div class="collapsible-section">
|
||||
<div class="section-header" @click="toggleMembers">
|
||||
<h3>Mitglieder-Teilnahmen</h3>
|
||||
<span class="toggle-icon">{{ showMembers ? '▼' : '▶' }}</span>
|
||||
</div>
|
||||
<div v-if="showMembers" class="section-content">
|
||||
<div class="members-table-container">
|
||||
<table class="members-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th @click="sortBy('name')" class="sortable-header">
|
||||
@@ -74,6 +109,8 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal für Mitgliedsdetails -->
|
||||
<div v-if="showDetailsModal" class="modal">
|
||||
@@ -169,11 +206,14 @@ export default {
|
||||
activeMembers: [],
|
||||
trainingsCount12Months: 0,
|
||||
trainingsCount3Months: 0,
|
||||
trainingDays: [],
|
||||
showDetailsModal: false,
|
||||
selectedMember: {},
|
||||
loading: false,
|
||||
sortField: 'name',
|
||||
sortDirection: 'asc'
|
||||
sortDirection: 'asc',
|
||||
showTrainingDays: true,
|
||||
showMembers: false
|
||||
};
|
||||
},
|
||||
|
||||
@@ -204,6 +244,7 @@ export default {
|
||||
this.activeMembers = response.data.members || [];
|
||||
this.trainingsCount12Months = response.data.trainingsCount12Months || 0;
|
||||
this.trainingsCount3Months = response.data.trainingsCount3Months || 0;
|
||||
this.trainingDays = response.data.trainingDays || [];
|
||||
} catch (error) {
|
||||
// Kein Alert - es ist normal, dass nicht alle Daten verfügbar sind
|
||||
} finally {
|
||||
@@ -211,6 +252,20 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
toggleTrainingDays() {
|
||||
this.showTrainingDays = !this.showTrainingDays;
|
||||
},
|
||||
|
||||
toggleMembers() {
|
||||
this.showMembers = !this.showMembers;
|
||||
},
|
||||
|
||||
getWeekday(dateString) {
|
||||
const date = new Date(dateString);
|
||||
const weekdays = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'];
|
||||
return weekdays[date.getDay()];
|
||||
},
|
||||
|
||||
showMemberDetails(member) {
|
||||
this.selectedMember = member;
|
||||
this.showDetailsModal = true;
|
||||
@@ -300,12 +355,84 @@ export default {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.members-table-container {
|
||||
.collapsible-section {
|
||||
background: white;
|
||||
border-radius: var(--border-radius-large);
|
||||
box-shadow: var(--shadow-light);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border-color);
|
||||
margin-bottom: 1.5rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
padding: 1.25rem 1.5rem;
|
||||
background: var(--bg-light);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.section-header:hover {
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.section-header:hover h3 {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.section-header h3 {
|
||||
margin: 0;
|
||||
font-size: 1.125rem;
|
||||
color: var(--text-primary);
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.toggle-icon {
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.section-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.training-days-container {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.training-days-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.training-days-table th,
|
||||
.training-days-table td {
|
||||
padding: 1rem;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.training-days-table th {
|
||||
background: var(--bg-light);
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.training-days-table tbody tr:hover {
|
||||
background: var(--bg-light);
|
||||
}
|
||||
|
||||
.training-days-table tbody tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.members-table-container {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.members-table {
|
||||
|
||||
Reference in New Issue
Block a user