feat(SeasonSelector): implement logic to determine the current running season
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 37s

- Added a method to retrieve the current running season ID based on the current date and available season entries.
- Updated the season selection logic to default to the running season if no season is selected and `showCurrentSeason` is true.
- Enhanced localization files to include new terms related to member scopes, improving user experience across multiple languages.
This commit is contained in:
Torsten Schulz (local)
2026-04-15 11:20:21 +02:00
parent c62e91d997
commit 58012e0a44
17 changed files with 62 additions and 4 deletions

View File

@@ -124,6 +124,42 @@ export default {
});
// Methods
const getRunningSeasonId = (seasonEntries) => {
const seasonsList = Array.isArray(seasonEntries) ? seasonEntries : [];
if (!seasonsList.length) return null;
const now = new Date();
const currentYear = now.getFullYear();
// Saisonlogik in der App: Hinrunde Juli-Dez, Rueckrunde Jan-Jun
const startYear = now.getMonth() >= 6 ? currentYear : currentYear - 1;
const endYear = startYear + 1;
const expectedLabel = `${startYear}/${endYear}`;
const exact = seasonsList.find((entry) => String(entry?.season || '').trim() === expectedLabel);
if (exact?.id != null) {
return exact.id;
}
// Fallback: numerisch passend, falls Label leicht abweicht
const parsed = seasonsList
.map((entry) => {
const match = String(entry?.season || '').match(/^(\d{4})\/(\d{4})$/);
if (!match) return null;
return {
id: entry.id,
start: Number(match[1]),
end: Number(match[2])
};
})
.filter(Boolean);
const numericMatch = parsed.find((entry) => entry.start === startYear && entry.end === endYear);
if (numericMatch?.id != null) {
return numericMatch.id;
}
return null;
};
const loadSeasons = async () => {
loading.value = true;
error.value = null;
@@ -132,12 +168,14 @@ export default {
const response = await apiClient.get('/seasons');
seasons.value = response.data;
// Wenn showCurrentSeason true ist und keine Saison ausgewählt, wähle die aktuelle
// Wenn showCurrentSeason true ist und keine Saison ausgewählt, wähle die laufende Saison
if (props.showCurrentSeason && !selectedSeasonId.value && seasons.value.length > 0) {
// Die erste Saison ist die neueste (sortiert nach DESC)
selectedSeasonId.value = seasons.value[0].id;
const runningSeasonId = getRunningSeasonId(seasons.value);
const fallbackSeason = seasons.value[0];
selectedSeasonId.value = runningSeasonId ?? fallbackSeason.id;
const selectedSeason = seasons.value.find((entry) => entry.id == selectedSeasonId.value) || fallbackSeason;
emit('update:modelValue', selectedSeasonId.value);
emit('season-change', seasons.value[0]);
emit('season-change', selectedSeason);
}
} catch (err) {
console.error('Fehler beim Laden der Saisons:', err);

View File

@@ -577,6 +577,7 @@
"scopeAll": "Alle",
"scopeActive": "Aktiv",
"scopeTest": "Probe",
"scopeActiveTest": "Aktiv + Probe",
"scopeNeedsForm": "Formular ungeprüft",
"scopeActiveDataIncomplete": "Aktiv + Daten unvollständig",
"scopeDataIncomplete": "Daten unvollständig",

View File

@@ -216,6 +216,7 @@
"scopeAll": "Alle",
"scopeActive": "Aktiv",
"scopeTest": "Probe",
"scopeActiveTest": "Aktiv + Probe",
"scopeNeedsForm": "Formular ungeprüft",
"scopeInactive": "Inaktiv",
"resultsVisible": "Mitglieder sichtbar",

View File

@@ -325,6 +325,7 @@
"scopeAll": "Alle",
"scopeActive": "Aktiv",
"scopeTest": "Probe",
"scopeActiveTest": "Aktiv + Probe",
"scopeNeedsForm": "Formular ungeprüft",
"scopeActiveDataIncomplete": "Aktiv + Daten unvollständig",
"scopeDataIncomplete": "Daten unvollständig",

View File

@@ -574,6 +574,7 @@
"scopeAll": "All",
"scopeActive": "Active",
"scopeTest": "Trial",
"scopeActiveTest": "Active + trial",
"scopeNeedsForm": "Form unverified",
"scopeDataIncomplete": "Data incomplete",
"scopeInactive": "Inactive",

View File

@@ -849,6 +849,7 @@
"scopeAll": "All",
"scopeActive": "Active",
"scopeTest": "Trial",
"scopeActiveTest": "Active + trial",
"scopeNeedsForm": "Form unverified",
"scopeDataIncomplete": "Data incomplete",
"scopeInactive": "Inactive",

View File

@@ -574,6 +574,7 @@
"scopeAll": "All",
"scopeActive": "Active",
"scopeTest": "Trial",
"scopeActiveTest": "Active + trial",
"scopeNeedsForm": "Form unverified",
"scopeDataIncomplete": "Data incomplete",
"scopeInactive": "Inactive",

View File

@@ -537,6 +537,7 @@
"scopeAll": "Todos",
"scopeActive": "Activos",
"scopeTest": "Prueba",
"scopeActiveTest": "Activo + prueba",
"scopeNeedsForm": "Formulario sin verificar",
"scopeDataIncomplete": "Datos incompletos",
"scopeInactive": "Inactivos",

View File

@@ -537,6 +537,7 @@
"scopeAll": "All",
"scopeActive": "Active",
"scopeTest": "Trial",
"scopeActiveTest": "Active + trial",
"scopeNeedsForm": "Form unverified",
"scopeActiveDataIncomplete": "Aktibo + hindi kumpleto ang datos",
"scopeDataIncomplete": "Hindi kumpleto ang datos",

View File

@@ -537,6 +537,7 @@
"scopeAll": "Tous",
"scopeActive": "Actifs",
"scopeTest": "Essai",
"scopeActiveTest": "Actif + essai",
"scopeNeedsForm": "Formulaire non vérifié",
"scopeDataIncomplete": "Données incomplètes",
"scopeInactive": "Inactifs",

View File

@@ -537,6 +537,7 @@
"scopeAll": "Tutti",
"scopeActive": "Attivi",
"scopeTest": "Prova",
"scopeActiveTest": "Attivo + prova",
"scopeNeedsForm": "Modulo non verificato",
"scopeDataIncomplete": "Dati incompleti",
"scopeInactive": "Inattivi",

View File

@@ -537,6 +537,7 @@
"scopeAll": "All",
"scopeActive": "Active",
"scopeTest": "Trial",
"scopeActiveTest": "Active + trial",
"scopeNeedsForm": "Form unverified",
"scopeActiveDataIncomplete": "アクティブ + データ不完全",
"scopeDataIncomplete": "データ不完全",

View File

@@ -537,6 +537,7 @@
"scopeAll": "Wszyscy",
"scopeActive": "Aktywni",
"scopeTest": "Próba",
"scopeActiveTest": "Aktywni + próba",
"scopeNeedsForm": "Formularz niezweryfikowany",
"scopeDataIncomplete": "Niepełne dane",
"scopeInactive": "Nieaktywni",

View File

@@ -537,6 +537,7 @@
"scopeAll": "All",
"scopeActive": "Active",
"scopeTest": "Trial",
"scopeActiveTest": "Active + trial",
"scopeNeedsForm": "Form unverified",
"scopeActiveDataIncomplete": "ใช้งานอยู่ + ข้อมูลไม่ครบ",
"scopeDataIncomplete": "ข้อมูลไม่ครบ",

View File

@@ -537,6 +537,7 @@
"scopeAll": "All",
"scopeActive": "Active",
"scopeTest": "Trial",
"scopeActiveTest": "Active + trial",
"scopeNeedsForm": "Form unverified",
"scopeActiveDataIncomplete": "Aktibo + hindi kumpleto ang datos",
"scopeDataIncomplete": "Hindi kumpleto ang datos",

View File

@@ -537,6 +537,7 @@
"scopeAll": "All",
"scopeActive": "Active",
"scopeTest": "Trial",
"scopeActiveTest": "Active + trial",
"scopeNeedsForm": "Form unverified",
"scopeActiveDataIncomplete": "活跃 + 数据不完整",
"scopeDataIncomplete": "数据不完整",

View File

@@ -689,6 +689,10 @@ export default {
return false;
}
if (this.selectedMemberScope === 'activeTest' && (!member.active || !member.testMembership)) {
return false;
}
if (this.selectedMemberScope === 'inactive' && member.active) {
return false;
}
@@ -786,6 +790,7 @@ export default {
{ value: 'all', label: this.$t('members.scopeAll'), count: this.members.length },
{ value: 'active', label: this.$t('members.scopeActive'), count: this.members.filter(member => member.active && !member.testMembership).length },
{ value: 'test', label: this.$t('members.scopeTest'), count: this.members.filter(member => member.testMembership).length },
{ value: 'activeTest', label: this.$t('members.scopeActiveTest'), count: this.members.filter(member => member.active && member.testMembership).length },
{ value: 'notTraining', label: this.$t('members.scopeNotTraining'), count: this.members.filter(member => member.notInTraining).length },
{ value: 'needsForm', label: this.$t('members.scopeNeedsForm'), count: this.members.filter(member => !member.memberFormHandedOver).length },
{ value: 'activeDataIncomplete', label: this.$t('members.scopeActiveDataIncomplete'), count: this.members.filter(member => member.active && !member.testMembership && this.getMemberDataQualityIssues(member).length > 0).length },