Enhance diary member activity management by adding validation and logging in addMembersToActivity function. Implement checks for participantIds to ensure they are an array, and log relevant information for better debugging. Update DiaryDateActivityService to improve error handling and logging for group activity associations. Modify frontend DiaryView to support group activity member assignment, including new methods for toggling and assigning members to group activities, enhancing user experience and functionality.

This commit is contained in:
Torsten Schulz (local)
2025-10-16 22:20:51 +02:00
parent 24aaa9c150
commit 01bbb85485
5 changed files with 190 additions and 6 deletions

View File

@@ -1 +1,19 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
{
"name": "Trainingstagebuch",
"short_name": "TT-Tagebuch",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#2c3e50",
"background_color": "#ffffff",
"display": "standalone"
}

View File

@@ -144,7 +144,7 @@
item.durationText }})</span>
</td>
<td>
<button @click="toggleActivityMembers(item)" title="Teilnehmer zuordnen"
<button v-if="!item.isTimeblock" @click="toggleActivityMembers(item)" title="Teilnehmer zuordnen"
class="person-btn">👤</button>
<button @click="removePlanItem(item.id)" class="trash-btn">🗑</button>
<div v-if="activityMembersOpenId === item.id" class="dropdown"
@@ -198,7 +198,38 @@
</td>
<td>{{ groupItem.groupsGroupActivity.name }}</td>
<td></td>
<td></td>
<td>
<button @click="toggleGroupActivityMembers(groupItem)" title="Teilnehmer zuordnen"
class="person-btn">👤</button>
<div v-if="groupActivityMembersOpenId === groupItem.id" class="dropdown"
style="max-height: 12em; padding: 0.25rem;">
<div style="margin-bottom: 0.25rem; font-weight: 600; display: flex; align-items: center; gap: 0.5rem;">
<span>Teilnehmer zuordnen</span>
<button @click="assignAllMembersToGroupActivity(groupItem.id)"
style="font-size: 10px; padding: 1px 4px; background: #28a745; color: white; border: none; border-radius: 2px;">
Alle
</button>
<select v-if="groups.length > 0"
@change="assignGroupToGroupActivity(groupItem.id, $event.target.value)"
style="font-size: 10px; width: 80px;">
<option value="">Gruppe...</option>
<option v-for="group in groups" :key="group.id" :value="group.id">
{{ group.name }}
</option>
</select>
</div>
<div style="max-height: 9.5em; overflow-y: auto;">
<label v-for="m in presentMembers" :key="m.id"
style="display:flex; align-items:center; gap:0.5rem;">
<input type="checkbox"
:checked="isAssignedToGroupActivity(groupItem.id, m.id)"
@change="toggleMemberForGroupActivity(groupItem.id, m.id, $event.target.checked)">
<span>{{ m.firstName }} {{ m.lastName }}</span>
</label>
</div>
</div>
</td>
</tr>
</template>
</template>
@@ -518,6 +549,8 @@ export default {
activityMembersMap: {}, // key: activityId, value: Set(participantIds)
activityGroupsMap: {}, // key: activityId, value: groupId
memberGroupsMap: {}, // key: memberId, value: groupId
groupActivityMembersOpenId: null,
groupActivityMembersMap: {}, // key: groupActivityId, value: Set(participantIds)
// Schnell hinzufügen Dialog
showQuickAddDialog: false,
newMember: {
@@ -1796,6 +1829,103 @@ export default {
}
},
// Group Activity Members Methods
async toggleGroupActivityMembers(groupItem) {
if (this.groupActivityMembersOpenId === groupItem.id) {
this.groupActivityMembersOpenId = null;
return;
}
this.groupActivityMembersOpenId = groupItem.id;
await this.ensureGroupActivityMembersLoaded(groupItem.id);
},
async ensureGroupActivityMembersLoaded(groupActivityId) {
if (this.groupActivityMembersMap[groupActivityId]) return;
try {
const r = await apiClient.get(`/diary-member-activities/${this.currentClub}/${groupActivityId}`);
const setIds = new Set(r.data.map(x => x.participantId));
this.$set ? this.$set(this.groupActivityMembersMap, groupActivityId, setIds) : (this.groupActivityMembersMap[groupActivityId] = setIds);
} catch (e) {
this.groupActivityMembersMap[groupActivityId] = new Set();
}
},
isAssignedToGroupActivity(groupActivityId, memberId) {
const participantId = this.participantIdForMember(memberId);
const setIds = this.groupActivityMembersMap[groupActivityId];
return setIds ? setIds.has(participantId) : false;
},
async toggleMemberForGroupActivity(groupActivityId, memberId, checked) {
let participantId = this.participantIdForMember(memberId);
try {
if (checked) {
// Falls Mitglied noch kein Participant ist: zuerst hinzufügen
if (!participantId) {
const created = await apiClient.post('/participants/add', {
diaryDateId: this.date.id,
memberId: memberId,
});
participantId = created.data.id;
if (!this.participantMapByMemberId) this.participantMapByMemberId = {};
this.participantMapByMemberId[memberId] = participantId;
if (!this.participants.includes(memberId)) this.participants.push(memberId);
}
// Zuordnung erstellen
await apiClient.post(`/diary-member-activities/${this.currentClub}/${groupActivityId}`, {
participantIds: [participantId],
});
const setIds = this.groupActivityMembersMap[groupActivityId] || new Set();
setIds.add(participantId);
this.$set ? this.$set(this.groupActivityMembersMap, groupActivityId, setIds) : (this.groupActivityMembersMap[groupActivityId] = setIds);
} else {
// Zuordnung entfernen
await apiClient.delete(`/diary-member-activities/${this.currentClub}/${groupActivityId}/${participantId}`);
const setIds = this.groupActivityMembersMap[groupActivityId];
if (setIds) {
setIds.delete(participantId);
}
}
} catch (error) {
console.error('Fehler beim Zuordnen des Teilnehmers zu Gruppen-Aktivität:', error);
this.showInfo('Fehler', 'Teilnehmer konnte nicht zugeordnet werden.', '', 'error');
}
},
async assignAllMembersToGroupActivity(groupActivityId) {
try {
// Alle anwesenden Mitglieder zur Gruppen-Aktivität hinzufügen
for (const member of this.presentMembers) {
if (!this.isAssignedToGroupActivity(groupActivityId, member.id)) {
await this.toggleMemberForGroupActivity(groupActivityId, member.id, true);
}
}
} catch (error) {
console.error('Fehler beim Zuordnen aller Teilnehmer:', error);
this.showInfo('Fehler', 'Fehler beim Zuordnen aller Teilnehmer', '', 'error');
}
},
async assignGroupToGroupActivity(groupActivityId, groupId) {
if (!groupId) return; // Leere Auswahl ignorieren
try {
// Alle Mitglieder der gewählten Gruppe zur Gruppen-Aktivität hinzufügen
const groupMembers = this.presentMembers.filter(member =>
this.getMemberGroup(member.id) === groupId
);
for (const member of groupMembers) {
if (!this.isAssignedToGroupActivity(groupActivityId, member.id)) {
await this.toggleMemberForGroupActivity(groupActivityId, member.id, true);
}
}
} catch (error) {
console.error('Fehler beim Zuordnen der Gruppe:', error);
this.showInfo('Fehler', 'Fehler beim Zuordnen der Gruppe', '', 'error');
}
},
// Gruppenzuordnung für Teilnehmer
getMemberGroup(memberId) {
return this.memberGroupsMap[memberId] || '';