feat(ClubTeam): add planned league name field and localization updates
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 34s

- Introduced a new field for planned league name in the ClubTeam model, allowing for better team categorization.
- Updated create and update club team endpoints to handle the new planned league name field.
- Enhanced the PDF generation feature to include planned league name in the output.
- Improved localization files across multiple languages to incorporate new terms related to the planned league, ensuring a consistent user experience.
- Updated the TeamManagementView to display and edit the planned league name, enhancing user interaction.
This commit is contained in:
Torsten Schulz (local)
2026-04-02 08:17:13 +02:00
parent 9454761e34
commit 68b8455340
21 changed files with 143 additions and 22 deletions

View File

@@ -78,7 +78,8 @@ class PDFGenerator {
'pdfGenerator.teamGenderLabel': 'Team Geschlecht:',
'pdfGenerator.teamAgeGroupLabel': 'Team Altersklasse:',
'pdfGenerator.generatedAt': 'Erstellt:',
'pdfGenerator.lineupQttr': '(Q)TTR'
'pdfGenerator.lineupQttr': '(Q)TTR',
'pdfGenerator.plannedLeagueLabel': 'Geplante Spielklasse:'
};
return fallbacks[key] || key;
});

View File

@@ -907,6 +907,9 @@
"exportLineupPdf": "Aufstellung als PDF",
"lineupPdfEmpty": "Es sind keine Spieler in der Aufstellung PDF kann nicht erstellt werden.",
"lineupPdfFilePrefix": "Aufstellung",
"plannedLeague": "Geplante Spielklasse",
"plannedLeaguePlaceholder": "z.B. Bezirksliga, nach nächster Meldung …",
"plannedLeagueHint": "Optional. Unabhängig von der gemeldeten Liga (MyTischtennis).",
"lineupSaveError": "Mannschaftsmeldung konnte nicht gespeichert werden.",
"lineupValidationTooLargeGap": "{higher} hat mehr als 30 QTTR Punkte Vorsprung vor {lower}. Diese Reihenfolge bitte korrigieren.",
"firstHalf": "Vorrunde",
@@ -924,6 +927,7 @@
"teamGenderLabel": "Team Geschlecht:",
"teamAgeGroupLabel": "Team Altersklasse:",
"generatedAt": "Erstellt:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "Geplante Spielklasse:"
}
}

View File

@@ -591,6 +591,9 @@
"exportLineupPdf": "Aufstellung als PDF",
"lineupPdfEmpty": "Es sind keine Spieler in der Aufstellung PDF kann nicht erstellt werden.",
"lineupPdfFilePrefix": "Aufstellung",
"plannedLeague": "Geplante Spielklasse",
"plannedLeaguePlaceholder": "z.B. Bezirksliga, nach nächster Meldung …",
"plannedLeagueHint": "Optional. Unabhängig von der gemeldeten Liga (MyTischtennis).",
"lineupSaveError": "Mannschaftsmeldung konnte nicht gespeichert werden.",
"lineupValidationTooLargeGap": "{higher} hat mehr als 30 QTTR Punkte Vorsprung vor {lower}. Diese Reihenfolge bitte korrigieren.",
"firstHalf": "Vorrunde",
@@ -608,6 +611,7 @@
"teamGenderLabel": "Team Geschlecht:",
"teamAgeGroupLabel": "Team Altersklasse:",
"generatedAt": "Erstellt:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "Geplante Spielklasse:"
}
}

View File

@@ -1336,6 +1336,9 @@
"teamName": "Team-Name",
"teamNamePlaceholder": "z.B. Herren 1, Damen 2",
"league": "Spielklasse",
"plannedLeague": "Geplante Spielklasse",
"plannedLeaguePlaceholder": "z.B. Bezirksliga, nach nächster Meldung …",
"plannedLeagueHint": "Optional. Unabhängig von der gemeldeten Liga (MyTischtennis).",
"team": "Team",
"teamId": "Team-ID",
"groupId": "Gruppen-ID",
@@ -2361,6 +2364,7 @@
"teamGenderLabel": "Team Geschlecht:",
"teamAgeGroupLabel": "Team Altersklasse:",
"generatedAt": "Erstellt:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "Geplante Spielklasse:"
}
}

View File

@@ -907,6 +907,9 @@
"exportLineupPdf": "Export line-up as PDF",
"lineupPdfEmpty": "No players in the line-up cannot create PDF.",
"lineupPdfFilePrefix": "Line-up",
"plannedLeague": "Planned league",
"plannedLeaguePlaceholder": "e.g. district league, after next registration …",
"plannedLeagueHint": "Optional. Independent of the registered league (MyTischtennis).",
"lineupSaveError": "Team line-up could not be saved.",
"lineupValidationTooLargeGap": "{higher} is more than 30 QTTR points ahead of {lower}. Please correct this order.",
"firstHalf": "First half",
@@ -924,6 +927,7 @@
"teamGenderLabel": "Team gender:",
"teamAgeGroupLabel": "Team age group:",
"generatedAt": "Generated:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "Planned league:"
}
}

View File

@@ -1027,6 +1027,9 @@
"teamName": "Team name",
"teamNamePlaceholder": "e.g. Men 1, Women 2",
"league": "League",
"plannedLeague": "Planned league",
"plannedLeaguePlaceholder": "e.g. district league, after next registration …",
"plannedLeagueHint": "Optional. Independent of the registered league (MyTischtennis).",
"team": "Team",
"teamId": "Team ID",
"groupId": "Group ID",
@@ -1177,6 +1180,7 @@
"teamGenderLabel": "Team gender:",
"teamAgeGroupLabel": "Team age group:",
"generatedAt": "Generated:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "Planned league:"
}
}

View File

@@ -907,6 +907,9 @@
"exportLineupPdf": "Export line-up as PDF",
"lineupPdfEmpty": "No players in the line-up cannot create PDF.",
"lineupPdfFilePrefix": "Lineup",
"plannedLeague": "Planned league",
"plannedLeaguePlaceholder": "e.g. district league, after next registration …",
"plannedLeagueHint": "Optional. Independent of the registered league (MyTischtennis).",
"lineupSaveError": "Team line-up could not be saved.",
"lineupValidationTooLargeGap": "{higher} is more than 30 QTTR points ahead of {lower}. Please correct this order.",
"firstHalf": "First half",
@@ -924,6 +927,7 @@
"teamGenderLabel": "Team gender:",
"teamAgeGroupLabel": "Team age group:",
"generatedAt": "Generated:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "Planned league:"
}
}

View File

@@ -874,6 +874,9 @@
"exportLineupPdf": "Exportar alineación como PDF",
"lineupPdfEmpty": "No hay jugadores en la alineación no se puede crear el PDF.",
"lineupPdfFilePrefix": "Alineacion",
"plannedLeague": "Liga prevista",
"plannedLeaguePlaceholder": "p. ej. liga regional, tras la próxima inscripción …",
"plannedLeagueHint": "Opcional. Independiente de la liga registrada (MyTischtennis).",
"lineupSaveError": "No se pudo guardar la alineación del equipo.",
"lineupValidationTooLargeGap": "{higher} tiene más de 30 puntos QTTR de ventaja sobre {lower}. Corrige este orden.",
"firstHalf": "Primera vuelta",
@@ -891,6 +894,7 @@
"teamGenderLabel": "Género del equipo:",
"teamAgeGroupLabel": "Categoría de edad del equipo:",
"generatedAt": "Generado:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "Liga prevista:"
}
}

View File

@@ -874,6 +874,9 @@
"exportLineupPdf": "I-export ang line-up bilang PDF",
"lineupPdfEmpty": "Walang manlalaro sa line-up hindi makagawa ng PDF.",
"lineupPdfFilePrefix": "Line-up",
"plannedLeague": "Plano na liga",
"plannedLeaguePlaceholder": "hal. district league, pagkatapos ng susunod na rehistro …",
"plannedLeagueHint": "Opsyonal. Hiwalay sa nakarehistrong liga (MyTischtennis).",
"lineupSaveError": "Hindi mai-save ang line-up ng koponan.",
"lineupValidationTooLargeGap": "Mahigit 30 QTTR points ang lamang ni {higher} kay {lower}. Pakitama ang ayos na ito.",
"firstHalf": "Unang yugto",
@@ -891,6 +894,7 @@
"teamGenderLabel": "Kasarian ng koponan:",
"teamAgeGroupLabel": "Age group ng koponan:",
"generatedAt": "Nilikha:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "Plano na liga:"
}
}

View File

@@ -874,6 +874,9 @@
"exportLineupPdf": "Exporter la composition en PDF",
"lineupPdfEmpty": "Aucun joueur dans la composition impossible de créer le PDF.",
"lineupPdfFilePrefix": "Composition",
"plannedLeague": "Ligue prévue",
"plannedLeaguePlaceholder": "ex. ligue de district, après la prochaine inscription …",
"plannedLeagueHint": "Facultatif. Indépendant de la ligue enregistrée (MyTischtennis).",
"lineupSaveError": "La composition de léquipe na pas pu être enregistrée.",
"lineupValidationTooLargeGap": "{higher} a plus de 30 points QTTR davance sur {lower}. Veuillez corriger cet ordre.",
"firstHalf": "Phase aller",
@@ -891,6 +894,7 @@
"teamGenderLabel": "Genre déquipe :",
"teamAgeGroupLabel": "Catégorie dâge déquipe :",
"generatedAt": "Créé le :",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "Ligue prévue :"
}
}

View File

@@ -874,6 +874,9 @@
"exportLineupPdf": "Esporta formazione come PDF",
"lineupPdfEmpty": "Nessun giocatore in formazione impossibile creare il PDF.",
"lineupPdfFilePrefix": "Formazione",
"plannedLeague": "Campionato previsto",
"plannedLeaguePlaceholder": "es. campionato di zona, dopo la prossima iscrizione …",
"plannedLeagueHint": "Facoltativo. Indipendente dal campionato registrato (MyTischtennis).",
"lineupSaveError": "Impossibile salvare la formazione della squadra.",
"lineupValidationTooLargeGap": "{higher} ha più di 30 punti QTTR di vantaggio su {lower}. Correggi questo ordine.",
"firstHalf": "Girone dandata",
@@ -891,6 +894,7 @@
"teamGenderLabel": "Genere squadra:",
"teamAgeGroupLabel": "Categoria età squadra:",
"generatedAt": "Creato:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "Campionato previsto:"
}
}

View File

@@ -874,6 +874,9 @@
"exportLineupPdf": "メンバー表をPDFで出力",
"lineupPdfEmpty": "登録プレイヤーがいないためPDFを作成できません。",
"lineupPdfFilePrefix": "メンバー表",
"plannedLeague": "予定リーグ",
"plannedLeaguePlaceholder": "例:地区リーグ、次回登録後 …",
"plannedLeagueHint": "任意。登録済みリーグMyTischtennisとは別です。",
"lineupSaveError": "チーム登録を保存できませんでした。",
"lineupValidationTooLargeGap": "{higher} は {lower} より 30 QTTR ポイント以上高いです。この順序を修正してください。",
"firstHalf": "前期",
@@ -891,6 +894,7 @@
"teamGenderLabel": "チーム性別:",
"teamAgeGroupLabel": "チーム年齢区分:",
"generatedAt": "作成日時:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "予定リーグ:"
}
}

View File

@@ -874,6 +874,9 @@
"exportLineupPdf": "Eksport składu do PDF",
"lineupPdfEmpty": "Brak zawodników w składzie nie można utworzyć PDF.",
"lineupPdfFilePrefix": "Sklad",
"plannedLeague": "Planowana klasa rozgrywkowa",
"plannedLeaguePlaceholder": "np. klasa okręgowa, po następnej deklaracji …",
"plannedLeagueHint": "Opcjonalnie. Niezależnie od zgłoszonej ligi (MyTischtennis).",
"lineupSaveError": "Nie udało się zapisać zgłoszenia drużyny.",
"lineupValidationTooLargeGap": "{higher} ma ponad 30 punktów QTTR przewagi nad {lower}. Popraw tę kolejność.",
"firstHalf": "Pierwsza runda",
@@ -891,6 +894,7 @@
"teamGenderLabel": "Płeć drużyny:",
"teamAgeGroupLabel": "Kategoria wiekowa drużyny:",
"generatedAt": "Utworzono:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "Planowana liga:"
}
}

View File

@@ -874,6 +874,9 @@
"exportLineupPdf": "ส่งออกรายชื่อเป็น PDF",
"lineupPdfEmpty": "ไม่มีผู้เล่นในรายชื่อ ไม่สามารถสร้าง PDF ได้",
"lineupPdfFilePrefix": "รายชื่อทีม",
"plannedLeague": "ลีกที่วางแผน",
"plannedLeaguePlaceholder": "เช่น ลีกในเขต หลังการลงทะเบียนครั้งถัดไป …",
"plannedLeagueHint": "ไม่บังคับ แยกจากลีกที่ลงทะเบียนแล้ว (MyTischtennis)",
"lineupSaveError": "ไม่สามารถบันทึกรายชื่อทีมได้",
"lineupValidationTooLargeGap": "{higher} มีคะแนน QTTR มากกว่า {lower} เกิน 30 คะแนน กรุณาแก้ไขลำดับนี้",
"firstHalf": "ครึ่งแรก",
@@ -891,6 +894,7 @@
"teamGenderLabel": "เพศทีม:",
"teamAgeGroupLabel": "กลุ่มอายุของทีม:",
"generatedAt": "สร้างเมื่อ:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "ลีกที่วางแผน:"
}
}

View File

@@ -874,6 +874,9 @@
"exportLineupPdf": "I-export ang line-up bilang PDF",
"lineupPdfEmpty": "Walang manlalaro sa line-up hindi makagawa ng PDF.",
"lineupPdfFilePrefix": "Line-up",
"plannedLeague": "Plano na liga",
"plannedLeaguePlaceholder": "hal. district league, pagkatapos ng susunod na rehistro …",
"plannedLeagueHint": "Opsyonal. Hiwalay sa nakarehistrong liga (MyTischtennis).",
"lineupSaveError": "Hindi mai-save ang line-up ng koponan.",
"lineupValidationTooLargeGap": "Mahigit 30 QTTR points ang lamang ni {higher} kay {lower}. Pakitama ang ayos na ito.",
"firstHalf": "Unang yugto",
@@ -891,6 +894,7 @@
"teamGenderLabel": "Kasarian ng koponan:",
"teamAgeGroupLabel": "Age group ng koponan:",
"generatedAt": "Nilikha:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "Plano na liga:"
}
}

View File

@@ -874,6 +874,9 @@
"exportLineupPdf": "导出阵容为 PDF",
"lineupPdfEmpty": "阵容中没有球员,无法生成 PDF。",
"lineupPdfFilePrefix": "阵容",
"plannedLeague": "计划联赛",
"plannedLeaguePlaceholder": "例如:地区联赛,下次报名后 …",
"plannedLeagueHint": "选填。与已报名联赛MyTischtennis无关。",
"lineupSaveError": "无法保存队伍报名。",
"lineupValidationTooLargeGap": "{higher} 比 {lower} 高出超过 30 个 QTTR 积分。请更正这个顺序。",
"firstHalf": "上半程",
@@ -891,6 +894,7 @@
"teamGenderLabel": "球队性别:",
"teamAgeGroupLabel": "球队年龄组:",
"generatedAt": "生成时间:",
"lineupQttr": "(Q)TTR"
"lineupQttr": "(Q)TTR",
"plannedLeagueLabel": "计划联赛:"
}
}

View File

@@ -96,6 +96,10 @@
<span class="settings-summary-label">{{ t('teamManagement.league') }}</span>
<strong>{{ teamToEdit.league ? teamToEdit.league.name : t('teamManagement.noLeague') }}</strong>
</div>
<div class="settings-summary-card">
<span class="settings-summary-label">{{ t('teamManagement.plannedLeague') }}</span>
<strong>{{ teamToEdit.plannedLeagueName?.trim() ? teamToEdit.plannedLeagueName : '' }}</strong>
</div>
<div class="settings-summary-card">
<span class="settings-summary-label">{{ t('teamManagement.season') }}</span>
<strong>{{ teamToEdit.season?.season || t('teamManagement.seasonUnknown') }}</strong>
@@ -125,6 +129,12 @@
</select>
</label>
<label class="settings-field-span-2">
<span>{{ t('teamManagement.plannedLeague') }}:</span>
<input type="text" v-model="newPlannedLeagueName" :placeholder="t('teamManagement.plannedLeaguePlaceholder')" maxlength="512" autocomplete="off">
<span class="field-hint">{{ t('teamManagement.plannedLeagueHint') }}</span>
</label>
<label>
<span>{{ t('teamManagement.teamGender') }}:</span>
<select v-model="newTeamGender">
@@ -580,6 +590,7 @@ export default {
const newLeagueId = ref('');
const newTeamGender = ref('open');
const newTeamAgeGroup = ref('adult');
const newPlannedLeagueName = ref('');
const selectedSeasonId = ref(null);
const currentSeason = ref(null);
const teamDocuments = ref([]);
@@ -962,6 +973,7 @@ export default {
newLeagueId.value = '';
newTeamGender.value = 'open';
newTeamAgeGroup.value = 'adult';
newPlannedLeagueName.value = '';
activeEditorSection.value = 'basic';
};
@@ -1005,7 +1017,8 @@ export default {
leagueId: newLeagueId.value || null,
seasonId: selectedSeasonId.value,
teamGender: newTeamGender.value,
teamAgeGroup: newTeamAgeGroup.value
teamAgeGroup: newTeamAgeGroup.value,
plannedLeagueName: newPlannedLeagueName.value.trim() || null
};
if (teamToEdit.value) {
@@ -1026,6 +1039,7 @@ export default {
teamToEdit.value = newTeam;
newTeamName.value = newTeam.name;
newLeagueId.value = newTeam.leagueId || '';
newPlannedLeagueName.value = newTeam.plannedLeagueName || '';
teamFormIsOpen.value = true; // Formular bleibt offen für weitere Bearbeitung
}
} catch (error) {
@@ -1037,6 +1051,7 @@ export default {
teamToEdit.value = team;
newTeamName.value = team.name;
newLeagueId.value = team.leagueId || '';
newPlannedLeagueName.value = team.plannedLeagueName || '';
newTeamGender.value = getConfiguredTeamGender(team);
newTeamAgeGroup.value = getConfiguredTeamAgeGroup(team);
teamFormIsOpen.value = true;
@@ -1818,13 +1833,18 @@ export default {
const introLines = [
`${t('pdfGenerator.clubLabel')} ${clubName}`,
`${t('pdfGenerator.teamNameLabel')} ${team?.name || ''}`,
`${t('pdfGenerator.leagueLabel')} ${leagueName}`,
`${t('pdfGenerator.leagueLabel')} ${leagueName}`
];
if (team?.plannedLeagueName?.trim()) {
introLines.push(`${t('pdfGenerator.plannedLeagueLabel')} ${team.plannedLeagueName.trim()}`);
}
introLines.push(
`${t('pdfGenerator.seasonLabel')} ${seasonLabel}`,
`${t('pdfGenerator.periodLabel')} ${halfLabel}`,
`${t('pdfGenerator.teamGenderLabel')} ${labelTeamGender(effectiveTeamGender.value)}`,
`${t('pdfGenerator.teamAgeGroupLabel')} ${labelAgeGroup(effectiveTeamAgeGroup.value)}`,
`${t('pdfGenerator.generatedAt')} ${new Date().toLocaleString()}`
];
);
const tableHead = [[
'#',
t('teamManagement.player'),
@@ -2200,6 +2220,7 @@ export default {
newLeagueId,
newTeamGender,
newTeamAgeGroup,
newPlannedLeagueName,
selectedSeasonId,
currentSeason,
teamDocuments,
@@ -2897,6 +2918,23 @@ export default {
gap: 0.9rem;
}
.settings-form-grid label.settings-field-span-2 {
grid-column: 1 / -1;
}
.settings-form-grid .field-hint {
display: block;
font-size: 0.8rem;
color: var(--text-muted);
margin-top: 0.25rem;
line-height: 1.35;
}
.settings-form-grid label.settings-field-span-2 input {
width: 100%;
min-width: 0;
}
.mytt-status-label {
font-weight: 600;
color: var(--text-color);