feat(PDFGenerator): add team lineup PDF generation and localization updates
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 35s

- Implemented a new feature to generate a PDF for team lineups, including detailed information such as club name, team name, league, season, gender, and age group.
- Enhanced localization files across multiple languages to include new terms related to the PDF generation feature, ensuring a consistent user experience.
- Updated the TeamManagementView to include a button for downloading the lineup as a PDF, improving accessibility for users.
This commit is contained in:
Torsten Schulz (local)
2026-04-02 08:07:38 +02:00
parent fd02655be4
commit 9454761e34
18 changed files with 337 additions and 2 deletions

View File

@@ -0,0 +1,10 @@
-- club_team: Felder wie backend/models/ClubTeam.js (teamGender, teamAgeGroup)
-- Fehlen in der DB -> SequelizeDatabaseError ER_BAD_FIELD_ERROR bei getClubTeams.
ALTER TABLE `club_team`
ADD COLUMN `team_gender` ENUM('open', 'female') NOT NULL DEFAULT 'open'
COMMENT 'Geschlecht Team (offen / nur weiblich)'
AFTER `my_tischtennis_team_id`,
ADD COLUMN `team_age_group` ENUM('adult', 'J19', 'J17', 'J15', 'J13', 'J11') NOT NULL DEFAULT 'adult'
COMMENT 'Altersklasse Mannschaft'
AFTER `team_gender`;

View File

@@ -68,7 +68,17 @@ class PDFGenerator {
'pdfGenerator.result': 'Ergebnis',
'pdfGenerator.status': 'Status',
'pdfGenerator.placement': 'Platzierung',
'pdfGenerator.competitionName': 'Konkurrenz'
'pdfGenerator.competitionName': 'Konkurrenz',
'pdfGenerator.teamLineupTitle': 'Mannschaftsaufstellung',
'pdfGenerator.clubLabel': 'Verein:',
'pdfGenerator.teamNameLabel': 'Mannschaft:',
'pdfGenerator.leagueLabel': 'Spielklasse:',
'pdfGenerator.seasonLabel': 'Saison:',
'pdfGenerator.periodLabel': 'Meldung für:',
'pdfGenerator.teamGenderLabel': 'Team Geschlecht:',
'pdfGenerator.teamAgeGroupLabel': 'Team Altersklasse:',
'pdfGenerator.generatedAt': 'Erstellt:',
'pdfGenerator.lineupQttr': '(Q)TTR'
};
return fallbacks[key] || key;
});
@@ -1510,6 +1520,43 @@ class PDFGenerator {
}
}
/**
* Mannschaftsaufstellung: Titel, Meta-Zeilen (bereits übersetzt) und Spielertabelle.
* @param {object} options
* @param {string} [options.title]
* @param {string[]} [options.introLines]
* @param {string[][]} options.tableHead - Eine Kopfzeile: [ [col1, col2, …] ]
* @param {string[][]} options.tableBody
*/
addTeamLineup({ title, introLines, tableHead, tableBody }) {
const pdfTitle = title || this.t('pdfGenerator.teamLineupTitle');
this.cursorY = this.margin;
this.pdf.setFont('helvetica', 'bold');
this.pdf.setFontSize(15);
this.pdf.text(pdfTitle, this.margin, this.cursorY);
this.cursorY += 9;
this.pdf.setFont('helvetica', 'normal');
this.pdf.setFontSize(10);
const maxW = 210 - this.margin * 2;
for (const line of introLines || []) {
const lines = this.pdf.splitTextToSize(String(line), maxW);
lines.forEach((ln) => {
this.pdf.text(ln, this.margin, this.cursorY);
this.cursorY += 5;
});
}
this.cursorY += 3;
autoTable(this.pdf, {
startY: this.cursorY,
margin: { left: this.margin, right: this.margin },
head: tableHead,
body: tableBody,
theme: 'grid',
styles: { fontSize: 10, cellPadding: 2, overflow: 'linebreak' },
headStyles: { fillColor: [220, 220, 220], textColor: 0, halign: 'left', fontStyle: 'bold' }
});
}
}
export default PDFGenerator;

View File

@@ -904,11 +904,26 @@
"selectedLineup": "Gemeldete Spieler",
"availableLineupMembers": "Verfügbare Spieler",
"lineupEmpty": "Noch keine Spieler für diese Mannschaft gemeldet.",
"exportLineupPdf": "Aufstellung als PDF",
"lineupPdfEmpty": "Es sind keine Spieler in der Aufstellung PDF kann nicht erstellt werden.",
"lineupPdfFilePrefix": "Aufstellung",
"lineupSaveError": "Mannschaftsmeldung konnte nicht gespeichert werden.",
"lineupValidationTooLargeGap": "{higher} hat mehr als 30 QTTR Punkte Vorsprung vor {lower}. Diese Reihenfolge bitte korrigieren.",
"firstHalf": "Vorrunde",
"firstHalfFull": "Vorrunde (Juli - Dezember)",
"secondHalf": "Rückrunde",
"secondHalfFull": "Rückrunde (ab 1. Januar)"
},
"pdfGenerator": {
"teamLineupTitle": "Mannschaftsaufstellung",
"clubLabel": "Verein:",
"teamNameLabel": "Mannschaft:",
"leagueLabel": "Spielklasse:",
"seasonLabel": "Saison:",
"periodLabel": "Meldung für:",
"teamGenderLabel": "Team Geschlecht:",
"teamAgeGroupLabel": "Team Altersklasse:",
"generatedAt": "Erstellt:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -588,11 +588,26 @@
"selectedLineup": "Gemeldete Spieler",
"availableLineupMembers": "Verfügbare Spieler",
"lineupEmpty": "Noch keine Spieler für diese Mannschaft gemeldet.",
"exportLineupPdf": "Aufstellung als PDF",
"lineupPdfEmpty": "Es sind keine Spieler in der Aufstellung PDF kann nicht erstellt werden.",
"lineupPdfFilePrefix": "Aufstellung",
"lineupSaveError": "Mannschaftsmeldung konnte nicht gespeichert werden.",
"lineupValidationTooLargeGap": "{higher} hat mehr als 30 QTTR Punkte Vorsprung vor {lower}. Diese Reihenfolge bitte korrigieren.",
"firstHalf": "Vorrunde",
"firstHalfFull": "Vorrunde (Juli - Dezember)",
"secondHalf": "Rückrunde",
"secondHalfFull": "Rückrunde (ab 1. Januar)"
},
"pdfGenerator": {
"teamLineupTitle": "Mannschaftsaufstellung",
"clubLabel": "Verein:",
"teamNameLabel": "Mannschaft:",
"leagueLabel": "Spielklasse:",
"seasonLabel": "Saison:",
"periodLabel": "Meldung für:",
"teamGenderLabel": "Team Geschlecht:",
"teamAgeGroupLabel": "Team Altersklasse:",
"generatedAt": "Erstellt:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -1360,6 +1360,9 @@
"selectedLineup": "Gemeldete Spieler",
"availableLineupMembers": "Verfügbare Spieler",
"lineupEmpty": "Noch keine Spieler für diese Mannschaft gemeldet.",
"exportLineupPdf": "Aufstellung als PDF",
"lineupPdfEmpty": "Es sind keine Spieler in der Aufstellung PDF kann nicht erstellt werden.",
"lineupPdfFilePrefix": "Aufstellung",
"lineupUnsavedChanges": "Ungespeicherte Änderungen in der Mannschaftsmeldung.",
"lineupSaved": "Mannschaftsmeldung gespeichert.",
"lineupSaveError": "Mannschaftsmeldung konnte nicht gespeichert werden.",
@@ -2348,6 +2351,16 @@
"result": "Ergebnis",
"status": "Status",
"placement": "Platzierung",
"competitionName": "Konkurrenz"
"competitionName": "Konkurrenz",
"teamLineupTitle": "Mannschaftsaufstellung",
"clubLabel": "Verein:",
"teamNameLabel": "Mannschaft:",
"leagueLabel": "Spielklasse:",
"seasonLabel": "Saison:",
"periodLabel": "Meldung für:",
"teamGenderLabel": "Team Geschlecht:",
"teamAgeGroupLabel": "Team Altersklasse:",
"generatedAt": "Erstellt:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -904,11 +904,26 @@
"selectedLineup": "Selected players",
"availableLineupMembers": "Available players",
"lineupEmpty": "No players have been assigned to this team yet.",
"exportLineupPdf": "Export line-up as PDF",
"lineupPdfEmpty": "No players in the line-up cannot create PDF.",
"lineupPdfFilePrefix": "Line-up",
"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",
"firstHalfFull": "First half (July - December)",
"secondHalf": "Second half",
"secondHalfFull": "Second half (from 1 January)"
},
"pdfGenerator": {
"teamLineupTitle": "Team line-up",
"clubLabel": "Club:",
"teamNameLabel": "Team:",
"leagueLabel": "League:",
"seasonLabel": "Season:",
"periodLabel": "Registration for:",
"teamGenderLabel": "Team gender:",
"teamAgeGroupLabel": "Team age group:",
"generatedAt": "Generated:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -1051,6 +1051,9 @@
"selectedLineup": "Selected players",
"availableLineupMembers": "Available players",
"lineupEmpty": "No players have been assigned to this team yet.",
"exportLineupPdf": "Export line-up as PDF",
"lineupPdfEmpty": "No players in the line-up cannot create PDF.",
"lineupPdfFilePrefix": "Line-up",
"lineupUnsavedChanges": "There are unsaved changes in the team line-up.",
"lineupSaved": "Team line-up saved.",
"lineupSaveError": "Team line-up could not be saved.",
@@ -1163,5 +1166,17 @@
"invalidMimeType": "{label} has an unexpected MIME type: {type}.",
"fileTooLargeTitle": "File too large",
"fileTooLarge": "{label} must not exceed 10 MB."
},
"pdfGenerator": {
"teamLineupTitle": "Team line-up",
"clubLabel": "Club:",
"teamNameLabel": "Team:",
"leagueLabel": "League:",
"seasonLabel": "Season:",
"periodLabel": "Registration for:",
"teamGenderLabel": "Team gender:",
"teamAgeGroupLabel": "Team age group:",
"generatedAt": "Generated:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -904,11 +904,26 @@
"selectedLineup": "Selected players",
"availableLineupMembers": "Available players",
"lineupEmpty": "No players have been assigned to this team yet.",
"exportLineupPdf": "Export line-up as PDF",
"lineupPdfEmpty": "No players in the line-up cannot create PDF.",
"lineupPdfFilePrefix": "Lineup",
"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",
"firstHalfFull": "First half (July - December)",
"secondHalf": "Second half",
"secondHalfFull": "Second half (from 1 January)"
},
"pdfGenerator": {
"teamLineupTitle": "Team line-up",
"clubLabel": "Club:",
"teamNameLabel": "Team:",
"leagueLabel": "League:",
"seasonLabel": "Season:",
"periodLabel": "Registration for:",
"teamGenderLabel": "Team gender:",
"teamAgeGroupLabel": "Team age group:",
"generatedAt": "Generated:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -871,11 +871,26 @@
"selectedLineup": "Jugadores inscritos",
"availableLineupMembers": "Jugadores disponibles",
"lineupEmpty": "Todavía no se ha inscrito ningún jugador para este equipo.",
"exportLineupPdf": "Exportar alineación como PDF",
"lineupPdfEmpty": "No hay jugadores en la alineación no se puede crear el PDF.",
"lineupPdfFilePrefix": "Alineacion",
"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",
"firstHalfFull": "Primera vuelta (julio - diciembre)",
"secondHalf": "Segunda vuelta",
"secondHalfFull": "Segunda vuelta (desde el 1 de enero)"
},
"pdfGenerator": {
"teamLineupTitle": "Alineación del equipo",
"clubLabel": "Club:",
"teamNameLabel": "Equipo:",
"leagueLabel": "Liga:",
"seasonLabel": "Temporada:",
"periodLabel": "Inscripción para:",
"teamGenderLabel": "Género del equipo:",
"teamAgeGroupLabel": "Categoría de edad del equipo:",
"generatedAt": "Generado:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -871,11 +871,26 @@
"selectedLineup": "Napiling manlalaro",
"availableLineupMembers": "Magagamit na manlalaro",
"lineupEmpty": "Wala pang manlalarong itinalaga sa koponang ito.",
"exportLineupPdf": "I-export ang line-up bilang PDF",
"lineupPdfEmpty": "Walang manlalaro sa line-up hindi makagawa ng PDF.",
"lineupPdfFilePrefix": "Line-up",
"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",
"firstHalfFull": "Unang yugto (Hulyo - Disyembre)",
"secondHalf": "Ikalawang yugto",
"secondHalfFull": "Ikalawang yugto (mula Enero 1)"
},
"pdfGenerator": {
"teamLineupTitle": "Line-up ng koponan",
"clubLabel": "Club:",
"teamNameLabel": "Koponan:",
"leagueLabel": "Liga:",
"seasonLabel": "Season:",
"periodLabel": "Registration para sa:",
"teamGenderLabel": "Kasarian ng koponan:",
"teamAgeGroupLabel": "Age group ng koponan:",
"generatedAt": "Nilikha:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -871,11 +871,26 @@
"selectedLineup": "Joueurs inscrits",
"availableLineupMembers": "Joueurs disponibles",
"lineupEmpty": "Aucun joueur na encore été inscrit pour cette équipe.",
"exportLineupPdf": "Exporter la composition en PDF",
"lineupPdfEmpty": "Aucun joueur dans la composition impossible de créer le PDF.",
"lineupPdfFilePrefix": "Composition",
"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",
"firstHalfFull": "Phase aller (juillet - décembre)",
"secondHalf": "Phase retour",
"secondHalfFull": "Phase retour (à partir du 1er janvier)"
},
"pdfGenerator": {
"teamLineupTitle": "Composition de léquipe",
"clubLabel": "Club :",
"teamNameLabel": "Équipe :",
"leagueLabel": "Ligue :",
"seasonLabel": "Saison :",
"periodLabel": "Inscription pour :",
"teamGenderLabel": "Genre déquipe :",
"teamAgeGroupLabel": "Catégorie dâge déquipe :",
"generatedAt": "Créé le :",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -871,11 +871,26 @@
"selectedLineup": "Giocatori schierati",
"availableLineupMembers": "Giocatori disponibili",
"lineupEmpty": "Nessun giocatore è ancora stato assegnato a questa squadra.",
"exportLineupPdf": "Esporta formazione come PDF",
"lineupPdfEmpty": "Nessun giocatore in formazione impossibile creare il PDF.",
"lineupPdfFilePrefix": "Formazione",
"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",
"firstHalfFull": "Girone dandata (luglio - dicembre)",
"secondHalf": "Girone di ritorno",
"secondHalfFull": "Girone di ritorno (dal 1° gennaio)"
},
"pdfGenerator": {
"teamLineupTitle": "Formazione della squadra",
"clubLabel": "Società:",
"teamNameLabel": "Squadra:",
"leagueLabel": "Campionato:",
"seasonLabel": "Stagione:",
"periodLabel": "Iscrizione per:",
"teamGenderLabel": "Genere squadra:",
"teamAgeGroupLabel": "Categoria età squadra:",
"generatedAt": "Creato:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -871,11 +871,26 @@
"selectedLineup": "登録済み選手",
"availableLineupMembers": "利用可能な選手",
"lineupEmpty": "このチームにはまだ選手が登録されていません。",
"exportLineupPdf": "メンバー表をPDFで出力",
"lineupPdfEmpty": "登録プレイヤーがいないためPDFを作成できません。",
"lineupPdfFilePrefix": "メンバー表",
"lineupSaveError": "チーム登録を保存できませんでした。",
"lineupValidationTooLargeGap": "{higher} は {lower} より 30 QTTR ポイント以上高いです。この順序を修正してください。",
"firstHalf": "前期",
"firstHalfFull": "前期7月 - 12月",
"secondHalf": "後期",
"secondHalfFull": "後期1月1日以降"
},
"pdfGenerator": {
"teamLineupTitle": "チーム登録メンバー",
"clubLabel": "クラブ:",
"teamNameLabel": "チーム:",
"leagueLabel": "リーグ:",
"seasonLabel": "シーズン:",
"periodLabel": "登録対象:",
"teamGenderLabel": "チーム性別:",
"teamAgeGroupLabel": "チーム年齢区分:",
"generatedAt": "作成日時:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -871,11 +871,26 @@
"selectedLineup": "Zgłoszeni zawodnicy",
"availableLineupMembers": "Dostępni zawodnicy",
"lineupEmpty": "Do tej drużyny nie zgłoszono jeszcze żadnych zawodników.",
"exportLineupPdf": "Eksport składu do PDF",
"lineupPdfEmpty": "Brak zawodników w składzie nie można utworzyć PDF.",
"lineupPdfFilePrefix": "Sklad",
"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",
"firstHalfFull": "Pierwsza runda (lipiec - grudzień)",
"secondHalf": "Druga runda",
"secondHalfFull": "Druga runda (od 1 stycznia)"
},
"pdfGenerator": {
"teamLineupTitle": "Skład drużyny",
"clubLabel": "Klub:",
"teamNameLabel": "Drużyna:",
"leagueLabel": "Liga:",
"seasonLabel": "Sezon:",
"periodLabel": "Zgłoszenie na:",
"teamGenderLabel": "Płeć drużyny:",
"teamAgeGroupLabel": "Kategoria wiekowa drużyny:",
"generatedAt": "Utworzono:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -871,11 +871,26 @@
"selectedLineup": "ผู้เล่นที่ขึ้นทะเบียน",
"availableLineupMembers": "ผู้เล่นที่พร้อมใช้งาน",
"lineupEmpty": "ยังไม่มีการกำหนดผู้เล่นให้ทีมนี้",
"exportLineupPdf": "ส่งออกรายชื่อเป็น PDF",
"lineupPdfEmpty": "ไม่มีผู้เล่นในรายชื่อ ไม่สามารถสร้าง PDF ได้",
"lineupPdfFilePrefix": "รายชื่อทีม",
"lineupSaveError": "ไม่สามารถบันทึกรายชื่อทีมได้",
"lineupValidationTooLargeGap": "{higher} มีคะแนน QTTR มากกว่า {lower} เกิน 30 คะแนน กรุณาแก้ไขลำดับนี้",
"firstHalf": "ครึ่งแรก",
"firstHalfFull": "ครึ่งแรก (กรกฎาคม - ธันวาคม)",
"secondHalf": "ครึ่งหลัง",
"secondHalfFull": "ครึ่งหลัง (ตั้งแต่ 1 มกราคม)"
},
"pdfGenerator": {
"teamLineupTitle": "รายชื่อทีม",
"clubLabel": "สโมสร:",
"teamNameLabel": "ทีม:",
"leagueLabel": "ลีก:",
"seasonLabel": "ฤดูกาล:",
"periodLabel": "ลงทะเบียนสำหรับ:",
"teamGenderLabel": "เพศทีม:",
"teamAgeGroupLabel": "กลุ่มอายุของทีม:",
"generatedAt": "สร้างเมื่อ:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -871,11 +871,26 @@
"selectedLineup": "Napiling manlalaro",
"availableLineupMembers": "Magagamit na manlalaro",
"lineupEmpty": "Wala pang manlalarong itinalaga sa koponang ito.",
"exportLineupPdf": "I-export ang line-up bilang PDF",
"lineupPdfEmpty": "Walang manlalaro sa line-up hindi makagawa ng PDF.",
"lineupPdfFilePrefix": "Line-up",
"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",
"firstHalfFull": "Unang yugto (Hulyo - Disyembre)",
"secondHalf": "Ikalawang yugto",
"secondHalfFull": "Ikalawang yugto (mula Enero 1)"
},
"pdfGenerator": {
"teamLineupTitle": "Line-up ng koponan",
"clubLabel": "Club:",
"teamNameLabel": "Koponan:",
"leagueLabel": "Liga:",
"seasonLabel": "Season:",
"periodLabel": "Registration para sa:",
"teamGenderLabel": "Kasarian ng koponan:",
"teamAgeGroupLabel": "Age group ng koponan:",
"generatedAt": "Nilikha:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -871,11 +871,26 @@
"selectedLineup": "已报名球员",
"availableLineupMembers": "可用球员",
"lineupEmpty": "这支队伍还没有报名任何球员。",
"exportLineupPdf": "导出阵容为 PDF",
"lineupPdfEmpty": "阵容中没有球员,无法生成 PDF。",
"lineupPdfFilePrefix": "阵容",
"lineupSaveError": "无法保存队伍报名。",
"lineupValidationTooLargeGap": "{higher} 比 {lower} 高出超过 30 个 QTTR 积分。请更正这个顺序。",
"firstHalf": "上半程",
"firstHalfFull": "上半程7月 - 12月",
"secondHalf": "下半程",
"secondHalfFull": "下半程1月1日起"
},
"pdfGenerator": {
"teamLineupTitle": "球队阵容",
"clubLabel": "俱乐部:",
"teamNameLabel": "球队:",
"leagueLabel": "联赛:",
"seasonLabel": "赛季:",
"periodLabel": "报名阶段:",
"teamGenderLabel": "球队性别:",
"teamAgeGroupLabel": "球队年龄组:",
"generatedAt": "生成时间:",
"lineupQttr": "(Q)TTR"
}
}

View File

@@ -233,6 +233,9 @@
</select>
</label>
</div>
<button type="button" @click="downloadLineupPdf" :disabled="!selectedTeamLineupMembers.length" class="btn-sm" :title="t('teamManagement.exportLineupPdf')">
📄 {{ t('teamManagement.exportLineupPdf') }}
</button>
<button @click="loadClubMembers(); loadTeamLineup();" :disabled="loadingLineupMembers || loadingTeamLineup" class="btn-sm">
{{ (loadingLineupMembers || loadingTeamLineup) ? '⏳' : '🔄' }} {{ t('teamManagement.refreshStats') }}
</button>
@@ -531,6 +534,7 @@ import ConfirmDialog from '../components/ConfirmDialog.vue';
import TeamListCard from '../components/team/TeamListCard.vue';
import TeamManagementOverview from '../components/team/TeamManagementOverview.vue';
import { buildInfoConfig, buildConfirmConfig } from '../utils/dialogUtils.js';
import PDFGenerator from '../components/PDFGenerator.js';
export default {
name: 'TeamManagementView',
@@ -1800,6 +1804,56 @@ export default {
}
};
const downloadLineupPdf = () => {
const members = selectedTeamLineupMembers.value;
if (!members.length) {
showInfo(t('messages.info'), t('teamManagement.lineupPdfEmpty'), '', 'info');
return;
}
const team = teamToEdit.value;
const clubName = store.getters.currentClubName || '';
const seasonLabel = team?.season?.season || currentSeason.value?.season || t('teamManagement.seasonUnknown');
const leagueName = team?.league?.name || t('teamManagement.noLeague');
const halfLabel = lineupHalfOptions.value.find((o) => o.value === selectedLineupHalf.value)?.label || '';
const introLines = [
`${t('pdfGenerator.clubLabel')} ${clubName}`,
`${t('pdfGenerator.teamNameLabel')} ${team?.name || ''}`,
`${t('pdfGenerator.leagueLabel')} ${leagueName}`,
`${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'),
t('members.ageGroup'),
t('pdfGenerator.lineupQttr'),
t('teamManagement.eligibility')
]];
const tableBody = members.map((member, index) => [
String(index + 1),
`${member.firstName || ''} ${member.lastName || ''}`.trim(),
String(member.memberAgeGroupLabel || ''),
String(member.lineupRatingLabel || ''),
String(member.eligibilityLabel || '')
]);
const pdfGenerator = new PDFGenerator(20, 10, t);
pdfGenerator.addTeamLineup({
title: t('pdfGenerator.teamLineupTitle'),
introLines,
tableHead,
tableBody
});
const safe = (s) => String(s || '')
.replace(/[<>:"/\\|?*\u0000-\u001f]/g, '_')
.replace(/\s+/g, '_')
.slice(0, 80);
const filename = `${t('teamManagement.lineupPdfFilePrefix')}_${safe(team?.name)}_${new Date().toISOString().slice(0, 10)}.pdf`;
pdfGenerator.save(filename);
};
const persistTeamLineupAssignments = async (nextAssignments, validationMessage = '') => {
if (!teamToEdit.value?.id || savingTeamLineup.value) {
return false;
@@ -2220,6 +2274,7 @@ export default {
refreshPlayerStats,
loadClubMembers,
loadTeamLineup,
downloadLineupPdf,
addMemberToLineup,
removeMemberFromLineup,
moveLineupMember,