Add member change event handling for real-time updates

This commit introduces a new socket event for member changes, allowing real-time updates when members are created or updated. The backend now emits a 'member:changed' event upon successful member modifications, while the frontend listens for this event to refresh the member list in the DiaryView component. This enhances the interactivity and responsiveness of the application, ensuring users receive immediate feedback on member changes.
This commit is contained in:
Torsten Schulz (local)
2025-11-13 17:32:29 +01:00
parent e27a4d960d
commit 156f4d6921
4 changed files with 63 additions and 3 deletions

View File

@@ -1,5 +1,6 @@
import MemberService from "../services/memberService.js";
import MemberTransferService from "../services/memberTransferService.js";
import { emitMemberChanged } from '../services/socketService.js';
import { devLog } from '../utils/logger.js';
const getClubMembers = async(req, res) => {
@@ -32,6 +33,12 @@ const setClubMembers = async (req, res) => {
const { authcode: userToken } = req.headers;
const addResult = await MemberService.setClubMember(userToken, clubId, memberId, firstName, lastName, street, city, postalCode, birthdate,
phone, email, active, testMembership, picsInInternetAllowed, gender, ttr, qttr, memberFormHandedOver, contacts);
// Emit Socket-Event wenn Member erfolgreich erstellt/aktualisiert wurde
if (addResult.status === 200) {
emitMemberChanged(clubId);
}
res.status(addResult.status || 500).json(addResult.response);
} catch (error) {
console.error('[setClubMembers] - Error:', error);

View File

@@ -104,3 +104,8 @@ export const emitActivityChanged = (clubId, dateId) => {
emitToClub(clubId, 'activity:changed', { dateId });
};
// Event für Member-Änderungen (erstellen, aktualisieren)
export const emitMemberChanged = (clubId) => {
emitToClub(clubId, 'member:changed', { clubId });
};

View File

@@ -150,6 +150,17 @@ export const onActivityChanged = (callback) => {
}
};
export const onMemberChanged = (callback) => {
if (socket) {
socket.on('member:changed', (data) => {
console.log('📡 [Socket] member:changed empfangen:', data);
callback(data);
});
} else {
console.warn('⚠️ [Socket] onMemberChanged: Socket nicht verbunden');
}
};
// Event-Listener entfernen
export const offParticipantAdded = (callback) => {
if (socket) {
@@ -223,3 +234,9 @@ export const offActivityChanged = (callback) => {
}
};
export const offMemberChanged = (callback) => {
if (socket) {
socket.off('member:changed', callback);
}
};

View File

@@ -579,6 +579,7 @@ import {
onActivityMemberAdded,
onActivityMemberRemoved,
onActivityChanged,
onMemberChanged,
offParticipantAdded,
offParticipantRemoved,
offParticipantUpdated,
@@ -589,7 +590,8 @@ import {
offDiaryDateUpdated,
offActivityMemberAdded,
offActivityMemberRemoved,
offActivityChanged
offActivityChanged,
offMemberChanged
} from '../services/socketService.js';
export default {
@@ -1054,7 +1056,9 @@ export default {
async loadMembers() {
const response = await apiClient.get(`/clubmembers/get/${this.currentClub}/false`);
this.members = response.data;
// Erstelle ein neues Array, um Vue-Reaktivität sicherzustellen
this.members = Array.isArray(response.data) ? [...response.data] : [];
console.log('📡 [DiaryView] loadMembers: Mitglieder geladen, Anzahl:', this.members?.length || 0);
},
async loadParticipants(dateId) {
@@ -1615,7 +1619,8 @@ export default {
pdf.save('trainingsplan.pdf');
},
sortedMembers() {
return this.members.sort((a, b) => {
// Erstelle eine Kopie des Arrays, um Mutation zu vermeiden
return [...this.members].sort((a, b) => {
const firstNameComparison = a.firstName.localeCompare(b.firstName);
if (firstNameComparison === 0) {
return a.lastName.localeCompare(b.lastName);
@@ -2451,6 +2456,9 @@ export default {
onActivityMemberAdded(this.handleActivityMemberAdded);
onActivityMemberRemoved(this.handleActivityMemberRemoved);
onActivityChanged(this.handleActivityChanged);
// Event-Handler für Member-Änderungen
onMemberChanged(this.handleMemberChanged);
console.log('✅ [DiaryView] Alle Event-Handler registriert');
},
@@ -2466,6 +2474,7 @@ export default {
offActivityMemberAdded(this.handleActivityMemberAdded);
offActivityMemberRemoved(this.handleActivityMemberRemoved);
offActivityChanged(this.handleActivityChanged);
offMemberChanged(this.handleMemberChanged);
},
async handleParticipantAdded(data) {
@@ -2624,6 +2633,28 @@ export default {
console.log('⚠️ [DiaryView] Datum stimmt nicht überein oder kein Datum ausgewählt');
}
},
async handleMemberChanged(data) {
console.log('📡 [DiaryView] handleMemberChanged aufgerufen:', data);
console.log('📡 [DiaryView] Aktueller Club:', this.currentClub, 'Event Club:', data.clubId);
// Prüfe, ob der Club übereinstimmt
if (data.clubId && String(data.clubId) === String(this.currentClub)) {
console.log('✅ [DiaryView] Club stimmt überein, lade Mitgliederliste neu');
console.log('📡 [DiaryView] Aktuelle Mitgliederanzahl vor Reload:', this.members?.length || 0);
// Lade Mitgliederliste neu
try {
await this.loadMembers();
console.log('✅ [DiaryView] Mitgliederliste neu geladen, neue Anzahl:', this.members?.length || 0);
console.log('📡 [DiaryView] Mitgliederliste:', this.members);
// Force Vue update
this.$forceUpdate();
} catch (error) {
console.error('❌ [DiaryView] Fehler beim Neuladen der Mitgliederliste:', error);
}
} else {
console.log('⚠️ [DiaryView] Club stimmt nicht überein - Event Club:', data.clubId, 'Aktueller Club:', this.currentClub);
}
},
},
async mounted() {
await this.init();