"Updated backend and frontend code: added console logs, modified DiaryMemberController, DiaryTagController, DiaryService, and DiaryView, and made changes to CSS and vite.config.js"

This commit is contained in:
Torsten Schulz
2024-11-06 16:16:25 +01:00
parent 46efa9a9a4
commit 1efa4e588f
9 changed files with 110 additions and 41 deletions

View File

@@ -63,4 +63,7 @@ button.cancel-action {
button.cancel-action:hover {
background-color: #f2f2f2;
color: #45a049;
}
.pointer {
cursor: pointer;
}

View File

@@ -158,17 +158,6 @@
</div>
</div>
<div class="column">
<h3>Teilnehmer</h3>
<ul>
<li v-for="member in sortedMembers()" :key="member.id">
<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>
<span @click="showPic(member)" class="img-icon" v-if="member.hasImage">&#x1F5BC;</span>
<span>&#x2139;</span>
</li>
</ul>
<h3>Aktivitäten</h3>
<textarea v-model="newActivity"></textarea>
<button @click="addActivity">Aktivität hinzufügen</button>
@@ -179,11 +168,36 @@
</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" />
@remove="removeActivityTag" :allow-empty="false" @keydown.enter.prevent="addNewTagFromInput" />
<h3>Teilnehmer</h3>
<ul>
<li v-for="member in sortedMembers()" :key="member.id">
<input type="checkbox" :value="member.id" @change="toggleParticipant(member.id)"
:checked="isParticipant(member.id)">
<span class="clickable" @click="selectMember(member)"
:class="{ highlighted: selectedMember && selectedMember.id === member.id }">{{
member.firstName
}} {{
member.lastName }}</span>
<span @click="openNotesModal(member)" class="clickable">📝</span>
<span @click="showPic(member)" class="img-icon" v-if="member.hasImage">&#x1F5BC;</span>
<span class="pointer" @click="openTagInfos(member)"></span>
</li>
</ul>
</div>
</div>
</div>
<div v-if="showTagHistoryModal" class="modal">
<div class="modal-content">
<span class="close" @click="closeTagHistoryModal">&times;</span>
<h3>Tag-Historie {{ tagHistoryMember.firstName }} {{ tagHistoryMember.lastName }}</h3>
Diese Funktion ist noch nicht implementiert
</div>
</div>
<div v-if="showImage" class="memberImage">
<img :src="imageUrl" @click="closeImage" />
</div>
</div>
<img v-if="showImage" class="img" :src="imageUrl" @click="closeImage()" />
</template>
@@ -212,6 +226,7 @@ export default {
activities: [],
notes: [],
newNoteContent: '',
noteMember: null,
selectedMember: null,
showNotesModal: false,
selectedActivityTags: [],
@@ -241,6 +256,9 @@ export default {
addNewTimeblock: false,
showGeneralData: false,
editingGroupId: null,
doMemberTagUpdates: true,
showTagHistoryModal: false,
tagHistoryMember: null,
};
},
watch: {
@@ -409,18 +427,25 @@ export default {
description: this.newActivity,
tags: this.selectedActivityTags.map(tag => tag.id)
});
this.activities.push(response.data);
this.activities.push(response.data[0]);
this.newActivity = '';
this.selectedActivityTags = [];
}
},
async openNotesModal(member) {
async selectMember(member) {
this.selectedMember = member;
await this.loadMemberImage(member);
},
async openNotesModal(member) {
this.noteMember = member;
try {
await this.loadMemberImage(member);
} catch (error) {
}
this.loadMemberNotesAndTags(this.date.id, member.id);
this.showNotesModal = true;
},
async loadMemberNotesAndTags(diaryDateId, memberId) {
this.doMemberTagUpdates = false;
try {
const notesResponse = await apiClient.get(`/diarymember/${this.currentClub}/note`, {
params: { diaryDateId, memberId }
@@ -431,15 +456,16 @@ export default {
});
this.selectedMemberTags = tagsResponse.data.map(tag => ({
id: tag.tag.id,
name: tag.tag.name
label: tag.tag.label
}));
} catch (error) {
console.error('Error loading member notes and tags:', error);
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
}
this.doMemberTagUpdates = true;
},
async addMemberNote() {
if (this.newNoteContent) {
if (this.newNoteContent && this.selectedMember) {
const response = await apiClient.post(`/diarymember/${this.currentClub}/note`, {
memberId: this.selectedMember.id,
diaryDateId: this.date.id,
@@ -448,6 +474,8 @@ export default {
this.notes = response.data;
this.newNoteContent = '';
this.selectedTagsNotes = [];
} else {
alert('Bitte wählen Sie einen Teilnehmer aus und geben Sie einen Notiztext ein.');
}
},
async deleteNote(noteId) {
@@ -468,7 +496,7 @@ export default {
async addNewTag(newTagName) {
try {
const response = await apiClient.post('/tags', { name: newTagName });
const newTag = response.data;
const newTag = response.data[0];
this.availableTags.push(newTag);
this.selectedActivityTags.push(newTag);
} catch (error) {
@@ -495,9 +523,13 @@ export default {
}
},
async linkTagToDiaryDate(tag) {
if (!tag || !tag.id) {
console.warn("Ungültiges Tag-Objekt:", tag);
return;
}
try {
const tagId = tag.id;
await apiClient.post(`/diary/tag/${this.currentClub}/add-tag`, {
const response = await apiClient.post(`/diary/tag/${this.currentClub}/add-tag`, {
diaryDateId: this.date.id,
tagId: tagId
});
@@ -522,17 +554,14 @@ export default {
async updateActivityTags() {
try {
const selectedTags = this.selectedActivityTags;
if (!selectedTags || !Array.isArray(selectedTags)) {
if (!Array.isArray(selectedTags)) {
throw new TypeError('Expected selectedTags to be an array');
}
for (let tag of selectedTags) {
if (!this.previousActivityTags.includes(tag)) {
if (tag && tag.id && !this.previousActivityTags.some(prevTag => prevTag.id === tag.id)) {
await this.linkTagToDiaryDate(tag);
}
}
this.previousActivityTags = [...selectedTags];
} catch (error) {
console.error('Fehler beim Verknüpfen der Tags mit dem Trainingstag:', error);
@@ -540,6 +569,9 @@ export default {
}
},
async updateMemberTags() {
if (!this.doMemberTagUpdates || !this.selectedMember) {
return;
}
try {
for (let tag of this.selectedMemberTags) {
if (!this.previousMemberTags.includes(tag)) {
@@ -590,12 +622,12 @@ export default {
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
}
},
handleActivityInput() {
if (this.newPlanItem.activity) {
this.showDropdown = true;
} else {
this.showDropdown = false;
async handleActivityTagInput(tags) {
const newTags = tags.filter(tag => !this.previousActivityTags.some(prevTag => prevTag.id === tag.id));
for (const tag of newTags) {
await this.linkTagToDiaryDate(tag);
}
this.previousActivityTags = [...tags];
},
selectPredefinedActivity(activity) {
this.newPlanItem.activity = activity.name;
@@ -744,7 +776,7 @@ export default {
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
}
},
async loadMemberImage(member) {
/* async loadMemberImage(member) {
try {
const response = await apiClient.get(`/clubmembers/image/${this.currentClub}/${member.id}`, {
responseType: 'blob',
@@ -752,10 +784,9 @@ export default {
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 pdf = new PDFGenerator();
pdf.addTrainingPlan(this.currentClubName, this.date.date, this.trainingStart, this.trainingEnd, this.trainingPlan);
@@ -786,7 +817,6 @@ export default {
this.imageUrl = URL.createObjectURL(response.data);
this.showImage = true;
} catch (error) {
console.error("Failed to load member image:", error);
this.imageUrl = null;
}
},
@@ -838,7 +868,6 @@ export default {
this.showGeneralData = !this.showGeneralData;
},
getFormattedDate(date) {
console.log(date, typeof date);
return (new Date(date)).toLocaleDateString('de-DE', { year: 'numeric', month: '2-digit', day: '2-digit'});
},
editGroup(groupId) {
@@ -861,6 +890,14 @@ export default {
cancelEditGroup() {
this.editingGroupId = null;
},
async openTagInfos(member) {
this.showTagHistoryModal = true;
this.tagHistoryMember = member;
},
closeTagHistoryModal() {
this.showTagHistoryModal = false;
this.tagHistoryMember = null;
},
},
async mounted() {
await this.init();
@@ -1025,6 +1062,13 @@ input[type="number"] {
color: #45a049;
}
.highlighted {
background-color: #45a049;
color: white;
padding: 0.2em;
border-radius: 4px;
}
.add-plan-item {
border: 1px solid black;
cursor: pointer;

View File

@@ -3,6 +3,7 @@ import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
mode: 'development',
resolve: {
alias: {
'@': '/src'