Added groups to diary

This commit is contained in:
Torsten Schulz
2024-10-21 18:21:43 +02:00
parent 47fa81e190
commit f230b73273
17 changed files with 589 additions and 218 deletions

View File

@@ -6,12 +6,17 @@ class PDFGenerator {
this.pdf = new jsPDF('p', 'mm', 'a4');
this.margin = margin;
this.columnGap = columnGap;
this.pageHeight = 295 - margin * 2;
this.pageHeight = 297 - margin * 2;
this.columnWidth = (210 - margin * 2 - columnGap) / 2;
this.position = margin;
this.yPos = this.position;
this.xPos = margin;
this.isLeftColumn = true;
this.COLUMN_START_TIME = margin;
this.COLUMN_ACTIVITY = margin + 30;
this.COLUMN_GROUP = margin + 100;
this.COLUMN_DURATION = margin + 150;
this.LINE_HEIGHT = 7;
}
async addSchedule(element) {
@@ -38,52 +43,7 @@ class PDFGenerator {
this.isLeftColumn = true;
}
addHeader(title) {
this.pdf.setFontSize(12);
this.pdf.setFont('helvetica', 'bold');
this.pdf.text(title, this.margin, this.position);
this.pdf.setLineWidth(0.5);
this.pdf.line(this.margin, this.position + 2, 210 - this.margin, this.position + 2);
this.yPos += 10;
this.position = this.yPos;
}
addAddress(clubName, addressLines) {
this.pdf.setFontSize(10);
this.pdf.setFont('helvetica', 'bold');
this.pdf.text(clubName, this.xPos, this.yPos);
this.yPos += 5;
this.pdf.setFont('helvetica', 'normal');
addressLines.forEach(line => {
this.pdf.text(line, this.xPos, this.yPos);
this.yPos += 5;
});
this.yPos += 10;
this.checkColumnOverflow();
}
checkColumnOverflow() {
if (this.isLeftColumn) {
if (this.yPos > this.pageHeight) {
this.xPos += this.columnWidth + this.columnGap;
this.yPos = this.position;
this.isLeftColumn = false;
}
} else {
if (this.yPos > this.pageHeight) {
this.pdf.addPage();
this.xPos = this.margin;
this.yPos = this.position;
this.isLeftColumn = true;
}
}
}
addTrainingPlan(clubName, trainingDate, trainingStart, trainingEnd, trainingPlan) {
const formattedDate = new Date(trainingDate).toLocaleDateString('de-DE');
const formattedStartTime = trainingStart.slice(0, 5);
const formattedEndTime = trainingEnd.slice(0, 5);
addHeader(clubName, formattedDate, formattedStartTime, formattedEndTime) {
this.pdf.setFontSize(14);
this.pdf.setFont('helvetica', 'bold');
this.pdf.text(`${clubName} - Trainingsplan`, this.margin, this.yPos);
@@ -94,42 +54,88 @@ class PDFGenerator {
this.yPos += 7;
this.pdf.text(`Uhrzeit: ${formattedStartTime} - ${formattedEndTime}`, this.margin, this.yPos);
this.yPos += 10;
}
addTableHeaders() {
this.pdf.setFont('helvetica', 'bold');
this.pdf.text('Uhrzeit', this.margin, this.yPos);
this.pdf.text('Aktivität', this.margin + 60, this.yPos);
this.pdf.text('Länge / Gesamtzeit (Min)', this.margin + 150, this.yPos);
this.yPos += 10;
this.pdf.text('Startzeit', this.COLUMN_START_TIME, this.yPos);
this.pdf.text('Aktivität / Zeitblock', this.COLUMN_ACTIVITY, this.yPos);
this.pdf.text('Gruppe', this.COLUMN_GROUP, this.yPos);
this.pdf.text('Dauer (Min)', this.COLUMN_DURATION, this.yPos);
this.yPos += this.LINE_HEIGHT;
this.pdf.setFont('helvetica', 'normal');
trainingPlan.forEach((item, index) => {
const time = this.calculatePlanItemTime(index, trainingStart, trainingPlan);
this.pdf.text(time.slice(0, 5), this.margin, this.yPos);
this.pdf.text(item.predefinedActivity.name, this.margin + 60, this.yPos);
this.pdf.text(item.duration.toString(), this.margin + 150, this.yPos);
this.yPos += 7;
}
if (this.yPos > this.pageHeight) {
this.addNewPage();
addTrainingPlan(clubName, trainingDate, trainingStart, trainingEnd, trainingPlan) {
const formattedDate = new Date(trainingDate).toLocaleDateString('de-DE');
const formattedStartTime = trainingStart ? trainingStart.slice(0, 5) : '';
const formattedEndTime = trainingEnd ? trainingEnd.slice(0, 5) : '';
this.addHeader(clubName, formattedDate, formattedStartTime, formattedEndTime);
this.addTableHeaders();
for (const item of trainingPlan) {
if (item.isTimeblock) {
this.addTimeBlock(item);
} else {
this.addActivity(item);
}
});
this.checkPageOverflow();
}
}
calculatePlanItemTime(index, startTime, trainingPlan) {
let time = startTime;
for (let i = 0; i < index; i++) {
time = this.addDurationToTime(time, trainingPlan[i].duration);
addTimeBlock(item) {
this.pdf.setFont('helvetica');
this.pdf.text(item.startTime, this.COLUMN_START_TIME, this.yPos);
this.pdf.text('Zeitblock', this.COLUMN_ACTIVITY, this.yPos);
this.yPos += this.LINE_HEIGHT;
this.pdf.setFont('helvetica', 'normal');
if (item.groupActivities && item.groupActivities.length > 0) {
this.addGroupActivities(item.groupActivities);
}
return time;
}
addDurationToTime(startTime, duration) {
let [hours, minutes] = startTime.split(':').map(Number);
minutes += Number(duration);
if (minutes >= 60) {
hours += Math.floor(minutes / 60);
minutes = minutes % 60;
addActivity(item) {
const startTime = item.startTime;
const activityName = item.predefinedActivity
? item.predefinedActivity.name
: item.activity;
const groupName = item.groupActivity ? item.groupActivity.name : '';
const duration = item.duration ? item.duration.toString() : '';
let text = '';
if (item.durationText) {
text = item.durationText + ' / ';
}
text += duration;
this.pdf.text(startTime, this.COLUMN_START_TIME, this.yPos);
this.pdf.text(activityName, this.COLUMN_ACTIVITY, this.yPos);
this.pdf.text(groupName, this.COLUMN_GROUP, this.yPos);
this.pdf.text(text, this.COLUMN_DURATION, this.yPos);
this.yPos += this.LINE_HEIGHT;
if (item.groupActivities && item.groupActivities.length > 0) {
this.addGroupActivities(item.groupActivities);
}
}
addGroupActivities(groupActivities) {
for (const groupItem of groupActivities) {
const activityName = groupItem.groupPredefinedActivity
? groupItem.groupPredefinedActivity.name
: '';
const groupName = groupItem.groupsGroupActivity
? groupItem.groupsGroupActivity.name
: '';
this.pdf.text('', this.COLUMN_START_TIME, this.yPos); // Leere Startzeit
this.pdf.text(' - ' + activityName, this.COLUMN_ACTIVITY + 5, this.yPos); // Einrückung
this.pdf.text(groupName, this.COLUMN_GROUP, this.yPos);
this.pdf.text('', this.COLUMN_DURATION, this.yPos); // Leere Dauer
this.yPos += this.LINE_HEIGHT;
this.checkPageOverflow();
}
}
checkPageOverflow() {
if (this.yPos > this.pageHeight) {
this.addNewPage();
}
hours = hours % 24;
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
}
save(filename) {

View File

@@ -5,7 +5,9 @@ import store from './store';
import '@/assets/css/main.scss';
import './assets/css/vue-multiselect.css';
createApp(App)
const app = createApp(App);
app.config.devtools = true;
app
.use(router)
.use(store)
.mount('#app');

View File

@@ -73,11 +73,6 @@ const store = createStore({
clubs: state => state.clubs,
currentClubName: state => {
const club = state.clubs.find(club => club.id === parseInt(state.currentClub));
if (club) {
console.log('Found Club:', club.name);
} else {
console.log('Club not found');
}
return club ? club.name : '';
}
},

View File

@@ -46,50 +46,105 @@
<div v-if="date !== 'new' && date !== null">
<div class="columns">
<div class="column">
<h3>Gruppenverwaltung</h3>
<div>
<h4>Vorhandene Gruppen</h4>
<ul>
<li v-for="group in groups" :key="group.id">
{{ group.name }} (Leiter: {{ group.lead }})
</li>
</ul>
</div>
<div>
<h4>Neue Gruppe erstellen</h4>
<div class="groups">
<div>
<label for="groupName">Gruppenname:</label>
<input type="text" v-model="newGroupName" required />
</div>
<div>
<label for="groupLead">Leiter:</label>
<input type="text" v-model="newGroupLead" required />
</div>
<div>
<label>&nbsp;</label>
<button type="submit" @click="addGroup">Gruppe hinzufügen</button>
</div>
</div>
</div>
<h3>Trainingsplan</h3>
<table>
<thead>
<tr>
<th></th>
<th>Uhrzeit</th>
<th>Aktivität</th>
<th>Länge / Gesamtzeit (Min)</th>
<th></th>
</tr>
</thead>
<tbody ref="sortableList">
<tr v-for="(planItem, index) in trainingPlan" :key="planItem.id">
<td class="drag-handle"></td>
<td>{{ calculatePlanItemTime(index) }}</td>
<td>{{ planItem.predefinedActivity.name }}</td>
<td>{{ planItem.durationText }} / {{ planItem.duration }}</td>
<td><span @click="removePlanItem(planItem.id)" class="add-plan-item">-</span></td>
</tr>
<tr>
<td></td>
<td>{{ calculateNextTime }}</td>
<td>
<input type="text" v-model="newPlanItem.activity" @input="handleActivityInput"
placeholder="Aktivität eingeben" />
<div v-if="showDropdown" class="dropdown">
<div v-for="activity in filteredPredefinedActivities" :key="activity.id"
@click="selectPredefinedActivity(activity)">
{{ activity.name }} ({{ activity.durationText || '' }} / {{
activity.duration }} Minuten)
</div>
</div>
</td>
<td>
<input type="text" v-model="newPlanItem.durationInput" @input="calculateDuration"
placeholder="z.B. 2x7 oder 3*5" style="width:10em" />
<input type="number" v-model="newPlanItem.duration" placeholder="Minuten" />
<span class="add-plan-item" @click="addPlanItem">+</span>
</td>
</tr>
</tbody>
</table>
<div>
<table>
<thead>
<tr>
<th>Startzeit</th>
<th>Aktivität / Zeitblock</th>
<th>Gruppe</th>
<th>Dauer (Min)</th>
<th></th>
</tr>
</thead>
<tbody ref="sortableList">
<template v-for="(item, index) in trainingPlan" :key="item.id">
<tr>
<td>{{ item.startTime }}</td>
<td>
<span v-if="item.isTimeblock"><i>Zeitblock</i></span>
<span v-else>{{ item.predefinedActivity ? item.predefinedActivity.name :
item.activity }}</span>
</td>
<td>{{ item.groupActivity ? item.groupActivity.name : '' }}</td>
<td><span v-if="item.durationText">{{ item.durationText }} / </span>{{ item.duration }}</td>
<td><button @click="removePlanItem(item.id)">Entfernen</button></td>
</tr>
<template v-for="groupItem in item.groupActivities">
<tr>
<td></td>
<td>{{ groupItem.groupPredefinedActivity.name }}</td>
<td>{{ groupItem.groupsGroupActivity.name }}</td>
<td></td>
<td></td>
</tr>
</template>
</template>
<tr>
<td>{{ calculateNextTime }}</td>
<td colspan="4" v-if="!addNewItem && !addNewTimeblock && !addNewGroupActivity">
<button @click="openNewPlanItem()">Gesamt-Aktivität</button>
<button @click="addTimeblock()">Zeitblock</button>
<button v-if="parentIsTimeblock()"
@click="addGroupActivity">Gruppen-Aktivität</button>
</td>
<td v-if="addNewItem || addNewGroupActivity">
<input v-if="addtype === 'activity'" type="text" v-model="newPlanItem.activity"
placeholder="Aktivität / Zeitblock" required />
</td>
<td v-else-if="addNewTimeblock">Zeitblock</td>
<td v-if="addNewGroupActivity" colspan="2">
<select v-model="newPlanItem.groupId">
<option v-for="group in groups" :key="group.id" :value="group.id">{{
group.name }}</option>
</select>
</td>
<td v-else-if="addNewItem || addNewTimeblock"></td>
<td v-if="(addNewItem || addNewTimeblock) && !addNewGroupActivity">
<input type="text" v-model="newPlanItem.durationInput"
@input="calculateDuration" placeholder="z.B. 2x7 oder 3*5"
style="width:10em" />
<input type="number" v-model="newPlanItem.duration" placeholder="Minuten" />
</td>
<td v-else-if="addNewGroupActivity"></td>
<td v-if="addNewItem || addNewTimeblock || addNewGroupActivity">
<span class="add-plan-item" @click="addPlanItem">+</span>
<span class="cancel" @click="cancelAddItem">X</span>
</td>
</tr>
</tbody>
</table>
<button v-if="trainingPlan && trainingPlan.length && trainingPlan.length > 0"
@click="generatePDF">Als PDF herunterladen</button>
</div>
</div>
<div class="column">
<h3>Teilnehmer</h3>
<ul>
@@ -116,39 +171,6 @@
</div>
</div>
</div>
<div v-if="showNotesModal" class="modal">
<div class="modal-content">
<span class="close" @click="closeNotesModal">&times;</span>
<h3>Notizen für {{ selectedMember.firstName }} {{ selectedMember.lastName }}</h3>
<div>Telefon-Nr.: {{ selectedMember.phone }}</div>
<div class="modal-body">
<div class="modal-left">
<img v-if="selectedMember.imageUrl" :src="selectedMember.imageUrl" alt="Mitgliedsbild"
style="width: 250px; height: 250px; object-fit: cover;" />
</div>
<div class="modal-right">
<multiselect v-model="selectedMemberTags" :options="availableTags" placeholder="Tags auswählen"
label="name" track-by="id" multiple :close-on-select="true" @tag="addNewTagForMember"
@remove="removeMemberTag" @input="updateMemberTags" :allow-empty="false"
@keydown.enter.prevent="addNewTagForMemberFromInput" />
<div>
<textarea v-model="newNoteContent" placeholder="Neue Notiz" rows="4" cols="30"></textarea>
<button @click="addMemberNote">Hinzufügen</button>
</div>
<ul>
<li v-for="note in notes" :key="note.id">
<button @click="deleteNote(note.id)" class="cancel-action">Löschen</button>
{{ note.content }}
</li>
</ul>
</div>
</div>
</div>
</div>
<div v-if="showImage" class="memberImage">
<img :src="imageUrl" @click="closeImage" />
</div>
</div>
</template>
@@ -188,11 +210,21 @@ export default {
activity: '',
duration: '',
durationText: '',
groupId: '',
isTimeBlock: false,
},
predefinedActivities: [],
showDropdown: false,
showImage: false,
imageUrl: '',
groups: [],
currentTimeBlockId: null,
newGroupName: '',
newGroupLead: '',
addtype: 'activity',
addNewItem: false,
addNewGroupActivity: false,
addNewTimeblock: false,
};
},
watch: {
@@ -206,11 +238,12 @@ export default {
computed: {
...mapGetters(['isAuthenticated', 'currentClub', 'currentClubName']),
calculateNextTime() {
let lastTime = this.trainingStart;
for (let item of this.trainingPlan) {
lastTime = this.addDurationToTime(lastTime, item.duration);
this.calculateAllItemTimes();
if (this.trainingPlan.length === 0) {
return this.trainingStart;
}
return lastTime;
const lastItem = this.trainingPlan[this.trainingPlan.length - 1];
return lastItem.endTime;
},
filteredPredefinedActivities() {
const input = this.newPlanItem.activity.toLowerCase();
@@ -224,8 +257,8 @@ export default {
if (this.isAuthenticated && this.currentClub) {
const response = await apiClient.get(`/diary/${this.currentClub}`);
this.dates = response.data.map(entry => ({ id: entry.id, date: entry.date }));
this.loadTags();
this.loadPredefinedActivities();
await this.loadTags();
await this.loadPredefinedActivities();
}
},
setCurrentDate() {
@@ -245,7 +278,6 @@ export default {
name: tag.name
}));
this.previousActivityTags = [...this.selectedActivityTags];
await this.loadMembers();
await this.loadParticipants(dateId);
await this.loadActivities(dateId);
@@ -254,6 +286,7 @@ export default {
.then(response => response.data);
this.initializeSortable();
await this.loadGroups();
} else {
this.newDate = '';
this.trainingStart = '';
@@ -275,7 +308,6 @@ export default {
trainingStart: this.trainingStart || null,
trainingEnd: this.trainingEnd || null,
});
console.log(response);
this.dates.push({ id: response.data.id, date: response.data.date });
this.date = { id: response.data.id, date: response.data.date };
this.showForm = false;
@@ -324,6 +356,14 @@ export default {
console.error('Fehler beim Laden der vordefinierten Aktivitäten:', error);
}
},
async loadGroups() {
try {
const response = await apiClient.get(`/group/${this.currentClub}/${this.date.id}`);
this.groups = response.data;
} catch (error) {
console.log(error);
}
},
isParticipant(memberId) {
return this.participants.includes(memberId);
},
@@ -359,7 +399,7 @@ export default {
},
async openNotesModal(member) {
this.selectedMember = member;
await this.loadMemberImage(member);
await this.loadMemberImage(member);
this.loadMemberNotesAndTags(this.date.id, member.id);
this.showNotesModal = true;
},
@@ -467,7 +507,6 @@ export default {
const selectedTags = this.selectedActivityTags;
if (!selectedTags || !Array.isArray(selectedTags)) {
console.log(typeof selectedTags, JSON.stringify(selectedTags));
throw new TypeError('Expected selectedTags to be an array');
}
@@ -549,36 +588,95 @@ export default {
},
async addPlanItem() {
try {
await apiClient.post(`/diary-date-activities/${this.currentClub}`, {
diaryDateId: this.date.id,
activity: this.newPlanItem.activity,
duration: this.newPlanItem.duration,
durationText: this.newPlanItem.durationText,
orderId: this.trainingPlan.length
});
this.newPlanItem = { activity: '', duration: '', durationText: '' };
if (this.addNewItem || this.addNewTimeblock) {
await apiClient.post(`/diary-date-activities/${this.currentClub}`, {
diaryDateId: this.date.id,
activity: this.addNewTimeblock ? '' : this.newPlanItem.activity,
isTimeblock: this.addNewTimeblock,
duration: this.newPlanItem.duration,
durationText: this.newPlanItem.durationText,
orderId: this.trainingPlan.length
});
} else if (this.addNewGroupActivity) {//clubId, diaryDateActivityId, groupId, activity
await apiClient.post(`/diary-date-activities/group`, {
clubId: this.currentClub,
diaryDateId: this.date.id,
activity: this.newPlanItem.activity,
groupId: this.newPlanItem.groupId,
});
}
this.addNewTimeblock = false;
this.addNewItem = false;
this.newPlanItem = { activity: '', duration: '', durationText: '', groupId: '' };
this.trainingPlan = await apiClient.get(`/diary-date-activities/${this.currentClub}/${this.date.id}`).then(response => response.data);
} catch (error) {
console.error('Fehler beim Hinzufügen des Planungsitems:', error);
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
}
},
async updatePlanItemGroup(planItemId, groupId) {
try {
await apiClient.put(`/diary-date-activities/${this.currentClub}/${planItemId}/group`, {
groupId: groupId
});
} catch (error) {
console.error('Fehler beim Aktualisieren der Planungs-Item-Gruppe:', error);
}
},
async removePlanItem(planItemId) {
try {
await apiClient.delete(`/diary-date-activities/${this.currentClub}`, {
params: { planItemId }
});
this.planItems = this.planItems.filter(item => item.id !== planItemId);
await apiClient.delete(`/diary-date-activities/${this.currentClub}/${planItemId}`);
this.trainingPlan = this.trainingPlan.filter(item => item.id !== planItemId);
} catch (error) {
console.error('Fehler beim Entfernen des Planungsitems:', error);
}
},
calculatePlanItemTime(index) {
let time = this.trainingStart;
for (let i = 0; i < index; i++) {
time = this.addDurationToTime(time, this.trainingPlan[i].duration);
isTimeGreater(time1, time2) {
const [hours1, minutes1] = time1.split(':').map(Number);
const [hours2, minutes2] = time2.split(':').map(Number);
if (hours1 > hours2) return true;
if (hours1 < hours2) return false;
return minutes1 > minutes2;
},
calculateAllItemTimes() {
let currentTime = this.trainingStart;
let index = 0;
const trainingPlanLength = this.trainingPlan.length;
while (index < trainingPlanLength) {
const currentItem = this.trainingPlan[index];
if (!currentItem.groupId) {
currentItem.startTime = currentTime;
currentItem.endTime = this.addDurationToTime(currentItem.startTime, currentItem.duration);
currentTime = currentItem.endTime;
index += 1;
} else {
const groupActivities = [];
while (index < trainingPlanLength && this.trainingPlan[index].groupId) {
groupActivities.push(this.trainingPlan[index]);
index += 1;
}
for (const item of groupActivities) {
item.startTime = currentTime;
item.endTime = this.addDurationToTime(item.startTime, item.duration);
}
let latestEndTime = currentTime;
for (const item of groupActivities) {
if (this.isTimeGreater(item.endTime, latestEndTime)) {
latestEndTime = item.endTime;
}
}
currentTime = latestEndTime;
}
}
return time;
},
calculatePlanItemTime(index) {
this.calculateAllItemTimes();
return this.trainingPlan[index].startTime;
},
addDurationToTime(startTime, duration) {
let [hours, minutes] = startTime.split(':').map(Number);
@@ -670,20 +768,57 @@ export default {
this.imageUrl = URL.createObjectURL(response.data);
} catch (error) {
console.error("Failed to load member image:", error);
this.imageUrl = null;
this.imageUrl = null;
}
},
recalculateTimes() {
let currentTime = this.trainingStart; // Die Startzeit des Trainings
let currentTime = this.trainingStart;
this.trainingPlan.forEach((item, index) => {
item.startTime = currentTime;
currentTime = this.addDurationToTime(currentTime, item.duration);
item.startTime = currentTime;
currentTime = this.addDurationToTime(currentTime, item.duration);
});
},
async addGroup() {
try {
const form = {
clubid: this.currentClub,
dateid: this.date.id,
name: this.newGroupName,
lead: this.newGroupLead,
}
await apiClient.post('/group', form);
await this.loadGroups();
} catch (error) {
}
},
parentIsTimeblock() {
return this.trainingPlan && this.trainingPlan.length > 0 ? (this.trainingPlan[this.trainingPlan.length - 1].isTimeblock) : false;
},
openNewPlanItem() {
this.addNewItem = true;
this.addNewGroupActivity = false;
this.addNewTimeblock = false;
},
cancelAddItem() {
this.addNewItem = false;
this.addNewGroupActivity = false;
this.addNewTimeblock = false;
},
addTimeblock() {
this.addNewTimeblock = true;
this.addNewGroupActivity = false;
this.addNewItem = false;
},
async addGroupActivity() {
this.addNewGroupActivity = true;
this.addNewItem = false;
this.addNewTimeblock = false;
},
},
async mounted() {
await this.init();
}
},
};
</script>
@@ -703,6 +838,7 @@ button[type="button"] {
h3 {
display: block;
}
.columns {
display: flex;
justify-content: space-between;
@@ -843,6 +979,22 @@ input[type="number"] {
line-height: 1.2em;
font-weight: bold;
margin-left: 5px;
border-radius: 2px;
}
.cancel {
border: 1px solid black;
cursor: pointer;
display: inline-block;
width: 1.2em;
height: 1.2em;
text-align: center;
line-height: 1.2em;
font-weight: bold;
margin-left: 5px;
color: #ff0000;
font-weight: bold;
border-radius: 2px;
}
.add-plan-item:hover {
@@ -871,8 +1023,8 @@ input[type="number"] {
flex: 1;
}
.img-icon {
cursor: pointer;
img {
max-width: 100%;
}
.memberImage {
@@ -886,8 +1038,14 @@ input[type="number"] {
overflow: hidden;
padding: 3px;
}
.memberImage > img {
.memberImage>img {
max-width: 100%;
max-height: 100%;
}
.groups {
display: flex;
flex-direction: row;
}
</style>

View File

@@ -142,7 +142,6 @@ export default {
},
getCurrentClubName() {
const club = this.clubs.find(club => club.id === this.currentClub);
console.log(club, this.currentClub);
return club ? club.name : '';
},
async generatePDF() {
@@ -164,7 +163,6 @@ export default {
},
getUniqueLocations() {
const uniqueLocations = new Map();
this.matches.forEach(match => {
const location = match.location;
const clubName = match.homeTeam.name;
@@ -173,9 +171,7 @@ export default {
location.address,
`${location.zip} ${location.city}`
];
const addressKey = addressLines.join('; '); // Unique key für die Map
const addressKey = addressLines.join('; ');
if (!uniqueLocations.has(addressKey)) {
uniqueLocations.set(clubName, addressLines);
}