Fixed Diary
This commit is contained in:
@@ -81,15 +81,18 @@ class PDFGenerator {
|
||||
}
|
||||
|
||||
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);
|
||||
this.pdf.setFontSize(14);
|
||||
this.pdf.setFont('helvetica', 'bold');
|
||||
this.pdf.text(`${clubName} - Trainingsplan`, this.margin, this.yPos);
|
||||
this.yPos += 10;
|
||||
this.pdf.setFontSize(12);
|
||||
this.pdf.setFont('helvetica', 'normal');
|
||||
this.pdf.text(`Datum: ${trainingDate}`, this.margin, this.yPos);
|
||||
this.pdf.text(`Datum: ${formattedDate}`, this.margin, this.yPos);
|
||||
this.yPos += 7;
|
||||
this.pdf.text(`Uhrzeit: ${trainingStart} - ${trainingEnd}`, this.margin, this.yPos);
|
||||
this.pdf.text(`Uhrzeit: ${formattedStartTime} - ${formattedEndTime}`, this.margin, this.yPos);
|
||||
this.yPos += 10;
|
||||
this.pdf.setFont('helvetica', 'bold');
|
||||
this.pdf.text('Uhrzeit', this.margin, this.yPos);
|
||||
@@ -99,8 +102,8 @@ class PDFGenerator {
|
||||
this.pdf.setFont('helvetica', 'normal');
|
||||
trainingPlan.forEach((item, index) => {
|
||||
const time = this.calculatePlanItemTime(index, trainingStart, trainingPlan);
|
||||
this.pdf.text(time, this.margin, this.yPos);
|
||||
this.pdf.text(item.activity, this.margin + 60, this.yPos);
|
||||
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;
|
||||
|
||||
|
||||
@@ -3,14 +3,13 @@
|
||||
<h2>Trainingstagebuch</h2>
|
||||
<div>
|
||||
<label>Datum:
|
||||
<select v-model="selectedDate" @change="handleDateChange">
|
||||
<select v-model="date" @change="handleDateChange">
|
||||
<option value="new">Neu anlegen</option>
|
||||
<option v-for="entry in dates" :key="entry.id" :value="entry">{{ entry.date }} </option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div v-if="showForm && selectedDate === 'new'">
|
||||
<div v-if="showForm && date === 'new'">
|
||||
<h3>Neues Datum anlegen</h3>
|
||||
<form @submit.prevent="createDate">
|
||||
<div>
|
||||
@@ -29,8 +28,7 @@
|
||||
<button type="submit">Datum anlegen</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div v-if="!showForm && selectedDate !== null && selectedDate !== 'new'">
|
||||
<div v-if="!showForm && date !== null && date !== 'new'">
|
||||
<h3>Trainingszeiten bearbeiten</h3>
|
||||
<form @submit.prevent="updateTrainingTimes">
|
||||
<div>
|
||||
@@ -45,7 +43,7 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div v-if="selectedDate !== 'new' && selectedDate !== null">
|
||||
<div v-if="date !== 'new' && date !== null">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<h3>Trainingsplan</h3>
|
||||
@@ -62,7 +60,7 @@
|
||||
<tr v-for="(planItem, index) in trainingPlan" :key="planItem.id">
|
||||
<td class="drag-handle">☰</td>
|
||||
<td>{{ calculatePlanItemTime(index) }}</td>
|
||||
<td>{{ planItem.activity }}</td>
|
||||
<td>{{ planItem.predefinedActivity.name }}</td>
|
||||
<td>
|
||||
<span @click="removePlanItem(planItem.id)" class="add-plan-item">-</span>
|
||||
{{ planItem.duration }}
|
||||
@@ -78,7 +76,7 @@
|
||||
<div v-for="activity in filteredPredefinedActivities" :key="activity.id"
|
||||
@click="selectPredefinedActivity(activity)">
|
||||
{{ activity.name }} ({{ activity.durationText || '' }} / {{
|
||||
activity.duration }} Minuten)
|
||||
activity.duration }} Minuten)
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -91,7 +89,62 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button @click="generatePDF">PDF speichern</button>
|
||||
<button v-if="trainingPlan && trainingPlan.length && trainingPlan.length > 0" @click="generatePDF">Als PDF herunterladen</button>
|
||||
</div>
|
||||
|
||||
<div class="column">
|
||||
<h3>Teilnehmer</h3>
|
||||
<ul>
|
||||
<li v-for="member in members" :key="member.id">
|
||||
<label>
|
||||
<input type="checkbox" :value="member.id" @change="toggleParticipant(member.id)"
|
||||
:checked="isParticipant(member.id)">
|
||||
<span @click="openNotesModal(member)" class="clickable">{{ member.firstName }} {{
|
||||
member.lastName }}</span>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Aktivitäten</h3>
|
||||
<textarea v-model="newActivity"></textarea>
|
||||
<button @click="addActivity">Aktivität hinzufügen</button>
|
||||
<ul>
|
||||
<li v-for="activity in activities" :key="activity.id">
|
||||
{{ activity.description }}
|
||||
</li>
|
||||
</ul>
|
||||
<multiselect v-model="selectedActivityTags" :options="availableTags" placeholder="Tags auswählen"
|
||||
label="name" track-by="id" multiple :close-on-select="true" @tag="addNewTag"
|
||||
@remove="removeActivityTag" @input="updateActivityTags" :allow-empty="false"
|
||||
@keydown.enter.prevent="addNewTagFromInput" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="showNotesModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<span class="close" @click="closeNotesModal">×</span>
|
||||
<h3>Notizen für {{ selectedMember.firstName }} {{ selectedMember.lastName }}</h3>
|
||||
<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>
|
||||
@@ -101,19 +154,34 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import apiClient from '../apiClient.js';
|
||||
import Multiselect from 'vue-multiselect';
|
||||
import Sortable from 'sortablejs';
|
||||
import PDFGenerator from '../components/PDFGenerator.js';
|
||||
import PDFGenerator from '../components/PDFGenerator.js';
|
||||
|
||||
export default {
|
||||
name: 'DiaryView',
|
||||
components: { Multiselect },
|
||||
data() {
|
||||
return {
|
||||
selectedDate: null,
|
||||
date: null,
|
||||
dates: [],
|
||||
showForm: false,
|
||||
newDate: '',
|
||||
trainingStart: '',
|
||||
trainingEnd: '',
|
||||
members: [],
|
||||
participants: [],
|
||||
newActivity: '',
|
||||
activities: [],
|
||||
notes: [],
|
||||
newNoteContent: '',
|
||||
selectedMember: null,
|
||||
showNotesModal: false,
|
||||
selectedActivityTags: [],
|
||||
selectedMemberTags: [],
|
||||
availableTags: [],
|
||||
previousActivityTags: [],
|
||||
previousMemberTags: [],
|
||||
trainingPlan: [],
|
||||
newPlanItem: {
|
||||
activity: '',
|
||||
@@ -124,8 +192,16 @@ export default {
|
||||
showDropdown: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
selectedMemberTags(newTags) {
|
||||
this.updateMemberTags(newTags);
|
||||
},
|
||||
selectedActivityTags(newTags) {
|
||||
this.updateActivityTags(newTags);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['isAuthenticated', 'currentClub']),
|
||||
...mapGetters(['isAuthenticated', 'currentClub', 'currentClubName']),
|
||||
calculateNextTime() {
|
||||
let lastTime = this.trainingStart;
|
||||
for (let item of this.trainingPlan) {
|
||||
@@ -145,6 +221,7 @@ 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();
|
||||
}
|
||||
},
|
||||
@@ -153,15 +230,24 @@ export default {
|
||||
this.newDate = today;
|
||||
},
|
||||
async handleDateChange() {
|
||||
this.showForm = this.selectedDate === 'new';
|
||||
if (this.selectedDate && this.selectedDate !== 'new') {
|
||||
const dateId = this.selectedDate.id;
|
||||
const response = await apiClient.get(`/diary/${this.currentClub}/${dateId}`);
|
||||
const dateData = response.data;
|
||||
this.showForm = this.date === 'new';
|
||||
if (this.date && this.date !== 'new') {
|
||||
const dateId = this.date.id;
|
||||
const response = await apiClient.get(`/diary/${this.currentClub}`);
|
||||
const dateData = response.data.find(entry => entry.id === dateId);
|
||||
this.trainingStart = dateData.trainingStart;
|
||||
this.trainingEnd = dateData.trainingEnd;
|
||||
this.selectedActivityTags = dateData.diaryTags.map(tag => ({
|
||||
id: tag.id,
|
||||
name: tag.name
|
||||
}));
|
||||
this.previousActivityTags = [...this.selectedActivityTags]; // Hier setzen
|
||||
|
||||
await this.loadMembers();
|
||||
await this.loadParticipants(dateId);
|
||||
await this.loadActivities(dateId);
|
||||
this.trainingPlan = await apiClient
|
||||
.get(`/diary-date-activities/${this.currentClub}/${dateId}`)
|
||||
.get(`/diary-date-activities/${this.currentClub}/${this.date.id}`)
|
||||
.then(response => response.data);
|
||||
|
||||
this.initializeSortable();
|
||||
@@ -169,6 +255,7 @@ export default {
|
||||
this.newDate = '';
|
||||
this.trainingStart = '';
|
||||
this.trainingEnd = '';
|
||||
this.participants = [];
|
||||
}
|
||||
},
|
||||
initializeSortable() {
|
||||
@@ -186,7 +273,7 @@ export default {
|
||||
trainingEnd: this.trainingEnd || null,
|
||||
});
|
||||
this.dates.push({ id: response.data.id, date: response.data.date });
|
||||
this.selectedDate = { id: response.data.id, date: response.data.date };
|
||||
this.date = { id: response.data.id, date: response.data.date };
|
||||
this.showForm = false;
|
||||
this.newDate = '';
|
||||
this.trainingStart = '';
|
||||
@@ -197,7 +284,7 @@ export default {
|
||||
},
|
||||
async updateTrainingTimes() {
|
||||
try {
|
||||
const dateId = this.selectedDate.id;
|
||||
const dateId = this.date.id;
|
||||
await apiClient.put(`/diary/${this.currentClub}`, {
|
||||
dateId,
|
||||
trainingStart: this.trainingStart || null,
|
||||
@@ -209,6 +296,22 @@ export default {
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
async loadMembers() {
|
||||
const response = await apiClient.get(`/clubmembers/${this.currentClub}`);
|
||||
this.members = response.data;
|
||||
},
|
||||
async loadParticipants(dateId) {
|
||||
const response = await apiClient.get(`/participants/${dateId}`);
|
||||
this.participants = response.data.map(participant => participant.memberId);
|
||||
},
|
||||
async loadActivities(dateId) {
|
||||
const response = await apiClient.get(`/activities/${dateId}`);
|
||||
this.activities = response.data;
|
||||
},
|
||||
async loadTags() {
|
||||
const response = await apiClient.get('/tags');
|
||||
this.availableTags = response.data;
|
||||
},
|
||||
async loadPredefinedActivities() {
|
||||
try {
|
||||
const response = await apiClient.get('/predefined-activities');
|
||||
@@ -217,6 +320,216 @@ export default {
|
||||
console.error('Fehler beim Laden der vordefinierten Aktivitäten:', error);
|
||||
}
|
||||
},
|
||||
isParticipant(memberId) {
|
||||
return this.participants.includes(memberId);
|
||||
},
|
||||
async toggleParticipant(memberId) {
|
||||
const isParticipant = this.isParticipant(memberId);
|
||||
const dateId = this.date.id;
|
||||
if (isParticipant) {
|
||||
await apiClient.post('/participants/remove', {
|
||||
diaryDateId: dateId,
|
||||
memberId
|
||||
});
|
||||
this.participants = this.participants.filter(id => id !== memberId);
|
||||
} else {
|
||||
await apiClient.post('/participants/add', {
|
||||
diaryDateId: dateId,
|
||||
memberId
|
||||
});
|
||||
this.participants.push(memberId);
|
||||
}
|
||||
},
|
||||
async addActivity() {
|
||||
const dateId = this.date.id;
|
||||
if (this.newActivity) {
|
||||
const response = await apiClient.post('/activities/add', {
|
||||
diaryDateId: dateId,
|
||||
description: this.newActivity,
|
||||
tags: this.selectedActivityTags.map(tag => tag.id)
|
||||
});
|
||||
this.activities.push(response.data);
|
||||
this.newActivity = '';
|
||||
this.selectedActivityTags = [];
|
||||
}
|
||||
},
|
||||
async openNotesModal(member) {
|
||||
this.selectedMember = member;
|
||||
await this.loadMemberImage(member);
|
||||
this.loadMemberNotesAndTags(this.date.id, member.id);
|
||||
this.showNotesModal = true;
|
||||
},
|
||||
async loadMemberNotesAndTags(diaryDateId, memberId) {
|
||||
try {
|
||||
const notesResponse = await apiClient.get(`/diarymember/${this.currentClub}/note`, {
|
||||
params: { diaryDateId, memberId }
|
||||
});
|
||||
this.notes = notesResponse.data;
|
||||
const tagsResponse = await apiClient.get(`/diarymember/${this.currentClub}/tag`, {
|
||||
params: { diaryDateId, memberId }
|
||||
});
|
||||
this.selectedMemberTags = tagsResponse.data.map(tag => ({
|
||||
id: tag.tag.id,
|
||||
name: tag.tag.name
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('Error loading member notes and tags:', error);
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
async addMemberNote() {
|
||||
if (this.newNoteContent) {
|
||||
const response = await apiClient.post(`/diarymember/${this.currentClub}/note`, {
|
||||
memberId: this.selectedMember.id,
|
||||
diaryDateId: this.date.id,
|
||||
content: this.newNoteContent
|
||||
});
|
||||
this.notes = response.data;
|
||||
this.newNoteContent = '';
|
||||
this.selectedTagsNotes = [];
|
||||
}
|
||||
},
|
||||
async deleteNote(noteId) {
|
||||
const response = await apiClient.delete(`/diarymember/${this.currentClub}/note/${noteId}`, {
|
||||
clubId: this.currentClub
|
||||
});
|
||||
this.notes = response.data;
|
||||
},
|
||||
closeNotesModal() {
|
||||
this.showNotesModal = false;
|
||||
},
|
||||
async addNewTagFromInput(event) {
|
||||
const inputValue = event.target.value.trim();
|
||||
if (inputValue) {
|
||||
await this.addNewTag(inputValue);
|
||||
}
|
||||
},
|
||||
async addNewTag(newTagName) {
|
||||
try {
|
||||
const response = await apiClient.post('/tags', { name: newTagName });
|
||||
const newTag = response.data;
|
||||
this.availableTags.push(newTag);
|
||||
this.selectedActivityTags.push(newTag);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Hinzufügen eines neuen Tags:', error);
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
async addNewTagForMemberFromInput(event) {
|
||||
const inputValue = event.target.value.trim();
|
||||
if (inputValue) {
|
||||
await this.addNewTagForMember(inputValue);
|
||||
}
|
||||
},
|
||||
async addNewTagForMember(newTagName) {
|
||||
try {
|
||||
const response = await apiClient.post('/tags', { name: newTagName });
|
||||
const newTag = response.data;
|
||||
this.availableTags.push(newTag);
|
||||
this.selectedMemberTags.push(newTag);
|
||||
await this.linkTagToMemberAndDate(newTag);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Hinzufügen eines neuen Tags für das Mitglied:', error);
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
async linkTagToDiaryDate(tag) {
|
||||
try {
|
||||
const tagId = tag.id;
|
||||
await apiClient.post(`/diary/tag/${this.currentClub}/add-tag`, {
|
||||
diaryDateId: this.date.id,
|
||||
tagId: tagId
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Verknüpfen des Tags mit dem Trainingstag:', error);
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
async linkTagToMemberAndDate(tag) {
|
||||
try {
|
||||
const tagId = tag.id;
|
||||
await apiClient.post(`/diarymember/${this.currentClub}/tag`, {
|
||||
diaryDateId: this.date.id,
|
||||
memberId: this.selectedMember.id,
|
||||
tagId: tagId
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Verknüpfen des Tags mit dem Mitglied und Datum:', error);
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
async updateActivityTags() {
|
||||
try {
|
||||
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');
|
||||
}
|
||||
|
||||
for (let tag of selectedTags) {
|
||||
if (!this.previousActivityTags.includes(tag)) {
|
||||
await this.linkTagToDiaryDate(tag);
|
||||
}
|
||||
}
|
||||
|
||||
this.previousActivityTags = [...selectedTags];
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Verknüpfen der Tags mit dem Trainingstag:', error);
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
async updateMemberTags() {
|
||||
try {
|
||||
for (let tag of this.selectedMemberTags) {
|
||||
if (!this.previousMemberTags.includes(tag)) {
|
||||
await this.linkTagToMemberAndDate(tag);
|
||||
}
|
||||
}
|
||||
this.previousMemberTags = [...this.selectedMemberTags];
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Verknüpfen der Tags mit dem Mitglied und Datum:', error);
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
async removeMemberTag(tagId) {
|
||||
try {
|
||||
await apiClient.post(`/diarymember/${this.currentClub}/tag/remove`, {
|
||||
diaryDateId: this.date.id,
|
||||
memberId: this.selectedMember.id,
|
||||
tagId: tagId
|
||||
});
|
||||
this.selectedMemberTags = this.selectedMemberTags.filter(tag => tag.id !== tagId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Entfernen des Tags:', error);
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
async removeMemberNote(noteContent) {
|
||||
try {
|
||||
await apiClient.post(`/diarymember/${this.currentClub}/note/remove`, {
|
||||
diaryDateId: this.date.id,
|
||||
memberId: this.selectedMember.id,
|
||||
content: noteContent
|
||||
});
|
||||
this.notes = this.notes.filter(note => note.content !== noteContent);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Entfernen der Notiz:', error);
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
async removeActivityTag(tag) {
|
||||
try {
|
||||
const tagId = tag.id;
|
||||
await apiClient.delete(`/diary/${this.currentClub}/tag`, {
|
||||
params: { tagId }
|
||||
});
|
||||
this.selectedActivityTags = this.selectedActivityTags.filter(t => t.id !== tagId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Entfernen des Tags:', error);
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
handleActivityInput() {
|
||||
if (this.newPlanItem.activity) {
|
||||
this.showDropdown = true;
|
||||
@@ -233,14 +546,14 @@ export default {
|
||||
async addPlanItem() {
|
||||
try {
|
||||
await apiClient.post(`/diary-date-activities/${this.currentClub}`, {
|
||||
diaryDateId: this.selectedDate.id,
|
||||
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: '' };
|
||||
this.trainingPlan = await apiClient.get(`/diary-date-activities/${this.currentClub}/${this.selectedDate.id}`).then(response => response.data);
|
||||
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.');
|
||||
@@ -248,8 +561,10 @@ export default {
|
||||
},
|
||||
async removePlanItem(planItemId) {
|
||||
try {
|
||||
await apiClient.delete(`/diary-date-activities/${this.currentClub}/${planItemId}`);
|
||||
this.trainingPlan = this.trainingPlan.filter(item => item.id !== planItemId);
|
||||
await apiClient.delete(`/diary-date-activities/${this.currentClub}`, {
|
||||
params: { planItemId }
|
||||
});
|
||||
this.planItems = this.planItems.filter(item => item.id !== planItemId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Entfernen des Planungsitems:', error);
|
||||
}
|
||||
@@ -262,18 +577,39 @@ export default {
|
||||
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;
|
||||
}
|
||||
hours = hours % 24;
|
||||
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
|
||||
},
|
||||
calculateDuration() {
|
||||
const input = this.newPlanItem.durationInput;
|
||||
let calculatedDuration = 0;
|
||||
const multiplyPattern = /(\d+)\s*[x*]\s*(\d+)/i;
|
||||
const match = input.match(multiplyPattern);
|
||||
if (match) {
|
||||
const [, num1, num2] = match;
|
||||
calculatedDuration = parseInt(num1) * parseInt(num2);
|
||||
} else if (!isNaN(input)) {
|
||||
calculatedDuration = parseInt(input);
|
||||
}
|
||||
calculatedDuration = Math.ceil(calculatedDuration / 5) * 5;
|
||||
if (!this.newPlanItem.durationText || this.newPlanItem.durationText === input) {
|
||||
this.newPlanItem.duration = calculatedDuration;
|
||||
this.newPlanItem = { ...this.newPlanItem, duration: calculatedDuration };
|
||||
}
|
||||
},
|
||||
async removePlanItem(planItemId) {
|
||||
try {
|
||||
let [hours, minutes] = startTime.split(':').map(Number);
|
||||
minutes += Number(duration);
|
||||
if (minutes >= 60) {
|
||||
hours += Math.floor(minutes / 60);
|
||||
minutes = minutes % 60;
|
||||
}
|
||||
hours = hours % 24;
|
||||
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
|
||||
} catch(error) {
|
||||
console.log(error);
|
||||
return '';
|
||||
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);
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
async onDragEnd(evt) {
|
||||
@@ -287,18 +623,26 @@ export default {
|
||||
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
},
|
||||
async loadMemberImage(member) {
|
||||
try {
|
||||
const response = await apiClient.get(`/clubmembers/${this.currentClub}/image/${member.id}`, {
|
||||
responseType: 'blob',
|
||||
});
|
||||
const imageUrl = URL.createObjectURL(response.data);
|
||||
member.imageUrl = imageUrl;
|
||||
} catch (error) {
|
||||
console.error("Failed to load member image:", error);
|
||||
member.imageUrl = null;
|
||||
}
|
||||
},
|
||||
async generatePDF() {
|
||||
const clubName = this.$store.getters.currentClubName;
|
||||
const trainingDate = this.selectedDate.date;
|
||||
const trainingStart = this.trainingStart;
|
||||
const trainingEnd = this.trainingEnd;
|
||||
|
||||
const pdfGenerator = new PDFGenerator();
|
||||
pdfGenerator.addTrainingPlan(clubName, trainingDate, trainingStart, trainingEnd, this.trainingPlan);
|
||||
pdfGenerator.save('Trainingsplan.pdf');
|
||||
}
|
||||
const pdf = new PDFGenerator();
|
||||
pdf.addTrainingPlan(this.currentClubName, this.date.date, this.trainingStart, this.trainingEnd, this.trainingPlan);
|
||||
pdf.save('trainingsplan.pdf');
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
|
||||
await this.init();
|
||||
}
|
||||
};
|
||||
@@ -337,6 +681,62 @@ ul {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
overflow: auto;
|
||||
background-color: rgba(200, 200, 200, 0.5);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #fefefe;
|
||||
padding: 20px;
|
||||
border: 1px solid #555;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
box-shadow: 4px 3px 2px #999;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 15px;
|
||||
color: #aaa;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.close:hover,
|
||||
.close:focus {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
padding: 0;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.multiselect {
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
@@ -386,6 +786,11 @@ input[type="number"] {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
color: #45a049;
|
||||
}
|
||||
|
||||
.add-plan-item {
|
||||
border: 1px solid black;
|
||||
cursor: pointer;
|
||||
@@ -406,4 +811,21 @@ input[type="number"] {
|
||||
.drag-handle {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.modal-left {
|
||||
flex: 0 0 250px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.modal-right {
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user