Refactor group ID handling in DiaryView and related services for consistency

Updated the handling of group IDs in DiaryView.vue to ensure they are consistently treated as strings. Enhanced the DiaryDateActivityService to filter out duplicate group activities and ensure proper handling of group IDs during updates. This improves data integrity and consistency across the application.
This commit is contained in:
Torsten Schulz (local)
2025-11-08 22:31:38 +01:00
parent d79e71d6d7
commit eb37532de2
3 changed files with 38 additions and 30 deletions

View File

@@ -163,7 +163,7 @@ Club.hasMany(UserClub, { foreignKey: 'clubId' });
Group.belongsTo(DiaryDate, { foreignKey: 'diaryDateId', as: 'diaryDateGroup' });
DiaryDate.hasMany(Group, { foreignKey: 'diaryDateId', as: 'groupsDiaryDate' });
GroupActivity.belongsTo(DiaryDateActivity, { foreignKey: 'id', as: 'activityGroupActivity' });
GroupActivity.belongsTo(DiaryDateActivity, { foreignKey: 'diaryDateActivity', as: 'activityGroupActivity' });
DiaryDateActivity.hasMany(GroupActivity, { foreignKey: 'diaryDateActivity', as: 'groupActivities' });
Group.hasOne(GroupActivity, { foreignKey: 'groupId', as: 'groupGroupActivity' });

View File

@@ -208,6 +208,17 @@ class DiaryDateActivityService {
// Auch für GroupActivities
if (activityData.groupActivities && activityData.groupActivities.length > 0) {
const seenGroupActivityIds = new Set();
activityData.groupActivities = activityData.groupActivities.filter(groupActivity => {
if (!groupActivity || groupActivity.id === undefined || groupActivity.id === null) {
return false;
}
if (seenGroupActivityIds.has(groupActivity.id)) {
return false;
}
seenGroupActivityIds.add(groupActivity.id);
return true;
});
for (const groupActivity of activityData.groupActivities) {
if (groupActivity.groupPredefinedActivity) {
// Hole die erste verfügbare Image-ID direkt aus der Datenbank

View File

@@ -173,7 +173,7 @@
@change="assignGroupToActivity(item.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">
<option v-for="group in groups" :key="group.id" :value="String(group.id)">
{{ group.name }}
</option>
</select>
@@ -199,8 +199,8 @@
<div style="display: flex; gap: 0.5rem; align-items: center; padding: 0.5rem; background: #f0f0f0; border-radius: 4px;">
<select v-model="newPlanItem.groupId" style="flex: 1;">
<option value="">Gruppe auswählen...</option>
<option v-for="group in groups" :key="group.id" :value="group.id">{{
group.name }}</option>
<option v-for="group in groups" :key="group.id" :value="String(group.id)">
{{ group.name }}</option>
</select>
<input type="text" v-model="newPlanItem.activity" placeholder="Aktivität"
@input="onNewItemInputChange" style="flex: 1;" />
@@ -257,7 +257,7 @@
@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">
<option v-for="group in groups" :key="group.id" :value="String(group.id)">
{{ group.name }}
</option>
</select>
@@ -317,11 +317,9 @@
<div style="display: flex; gap: 0.5rem; align-items: center;">
<select v-model="newPlanItem.groupId" style="flex: 1;">
<option value="">Gruppe auswählen...</option>
<option v-for="group in groups" :key="group.id" :value="group.id">{{
group.name }}</option>
<option v-for="group in groups" :key="group.id" :value="String(group.id)">
{{ group.name }}</option>
</select>
<input type="text" v-model="newPlanItem.activity" placeholder="Aktivität"
@input="onNewItemInputChange" style="flex: 1;" />
<div v-if="newItemShowDropdown && newItemSearchResults.length"
class="dropdown" style="max-height: 9.5em;">
<div v-for="s in newItemSearchResults" :key="s.id"
@@ -396,7 +394,7 @@
@change="updateMemberGroup(member.id, $event.target.value)"
style="margin-left: 10px; font-size: 8px; width: 5em;">
<option value="">-</option>
<option v-for="group in groups" :key="group.id" :value="group.id">
<option v-for="group in groups" :key="group.id" :value="String(group.id)">
{{ group.name }}
</option>
</select>
@@ -985,16 +983,12 @@ export default {
// Map für memberId -> participantId speichern
this.participantMapByMemberId = response.data.reduce((map, p) => { map[p.memberId] = p.id; return map; }, {});
// Map für memberId -> groupId speichern und mit Reaktivität initialisieren
this.memberGroupsMap = {};
const newMemberGroups = {};
response.data.forEach(p => {
if (p.groupId) {
if (this.$set) {
this.$set(this.memberGroupsMap, p.memberId, p.groupId);
} else {
this.memberGroupsMap[p.memberId] = p.groupId;
}
}
const groupValue = (p.groupId !== null && p.groupId !== undefined) ? String(p.groupId) : '';
newMemberGroups[p.memberId] = groupValue;
});
this.memberGroupsMap = newMemberGroups;
},
async loadActivities(dateId) {
@@ -1327,7 +1321,7 @@ export default {
clubId: this.currentClub,
diaryDateId: this.date.id,
activity: this.newPlanItem.activity,
groupId: this.newPlanItem.groupId,
groupId: Number(this.newPlanItem.groupId),
timeblockId: this.selectedTimeblockId,
});
}
@@ -2117,9 +2111,10 @@ export default {
if (!groupId) return; // Leere Auswahl ignorieren
try {
const normalizedGroupId = String(groupId);
// Alle Mitglieder der gewählten Gruppe zur Aktivität hinzufügen
const groupMembers = this.presentMembers.filter(member =>
this.getMemberGroup(member.id) === groupId
this.getMemberGroup(member.id) === normalizedGroupId
);
for (const member of groupMembers) {
@@ -2214,9 +2209,10 @@ export default {
if (!groupId) return; // Leere Auswahl ignorieren
try {
const normalizedGroupId = String(groupId);
// Alle Mitglieder der gewählten Gruppe zur Gruppen-Aktivität hinzufügen
const groupMembers = this.presentMembers.filter(member =>
this.getMemberGroup(member.id) === groupId
this.getMemberGroup(member.id) === normalizedGroupId
);
for (const member of groupMembers) {
@@ -2232,28 +2228,29 @@ export default {
// Gruppenzuordnung für Teilnehmer
getMemberGroup(memberId) {
return this.memberGroupsMap[memberId] || '';
const value = this.memberGroupsMap ? this.memberGroupsMap[memberId] : undefined;
return value !== undefined && value !== null ? String(value) : '';
},
async updateMemberGroup(memberId, groupId) {
try {
const selectedGroupId = groupId || '';
// Verwende Vue.set für Reaktivität (Vue 2)
const selectedGroupId = groupId ? String(groupId) : '';
if (this.$set) {
this.$set(this.memberGroupsMap, memberId, selectedGroupId);
} else {
// Vue 3 oder Fallback
this.memberGroupsMap = {
...this.memberGroupsMap,
[memberId]: selectedGroupId
};
}
// API-Call zum Speichern der Teilnehmer-Gruppenzuordnung
await apiClient.put(`/participants/${this.date.id}/${memberId}/group`, {
groupId: selectedGroupId || null
await apiClient.put(`/participants/${this.date.id}/${memberId}/group`, {
groupId: selectedGroupId ? Number(selectedGroupId) : null
});
// Synchronisiere die Teilnehmerliste, damit Anzeige und Datenlage übereinstimmen
await this.loadParticipants(this.date.id);
} catch (error) {
console.error('Fehler beim Aktualisieren der Teilnehmer-Gruppenzuordnung:', error);
this.showInfo('Fehler', 'Fehler beim Aktualisieren der Teilnehmer-Gruppenzuordnung', '', 'error');