-
-
[{{ s.code
- }}] {{ s.name }}
+
+
+
+
+ [{{ s.code
+ }}] {{ s.name }}
+
@@ -295,7 +299,7 @@
@click="addGroupActivity">Gruppen-Aktivität
-
+
-
-
-
- [{{ s.code
- }}] {{ s.name }}
+
+
+
+
+ [{{ s.code
+ }}] {{ s.name }}
+
@@ -327,12 +333,16 @@
-
-
- [{{ s.code
- }}] {{ s.name }}
+
+
+
+
+ [{{ s.code
+ }}] {{ s.name }}
+
@@ -555,6 +565,32 @@ import MemberActivityStatsDialog from '../components/MemberActivityStatsDialog.v
import AccidentFormDialog from '../components/AccidentFormDialog.vue';
import QuickAddMemberDialog from '../components/QuickAddMemberDialog.vue';
import MemberGalleryDialog from '../components/MemberGalleryDialog.vue';
+import {
+ connectSocket,
+ disconnectSocket,
+ onParticipantAdded,
+ onParticipantRemoved,
+ onParticipantUpdated,
+ onDiaryNoteAdded,
+ onDiaryNoteDeleted,
+ onDiaryTagAdded,
+ onDiaryTagRemoved,
+ onDiaryDateUpdated,
+ onActivityMemberAdded,
+ onActivityMemberRemoved,
+ onActivityChanged,
+ offParticipantAdded,
+ offParticipantRemoved,
+ offParticipantUpdated,
+ offDiaryNoteAdded,
+ offDiaryNoteDeleted,
+ offDiaryTagAdded,
+ offDiaryTagRemoved,
+ offDiaryDateUpdated,
+ offActivityMemberAdded,
+ offActivityMemberRemoved,
+ offActivityChanged
+} from '../services/socketService.js';
export default {
name: 'DiaryView',
@@ -698,6 +734,14 @@ export default {
selectedActivityTags(newTags) {
this.updateActivityTags(newTags);
},
+ currentClub(newClubId, oldClubId) {
+ // Wenn Club wechselt, Socket neu verbinden
+ if (newClubId && newClubId !== oldClubId) {
+ this.removeSocketListeners();
+ connectSocket(newClubId);
+ this.setupSocketListeners();
+ }
+ }
},
computed: {
...mapGetters(['isAuthenticated', 'currentClub', 'currentClubName']),
@@ -1992,9 +2036,7 @@ export default {
// Suche nach existierender Aktivität mit diesem Code
const searchResults = await this.searchPredefinedActivities(code);
- const existing = searchResults.find(a =>
- a.code && a.code.trim().toLowerCase() === code.toLowerCase()
- );
+ const existing = searchResults.find(a => a.code && a.code.trim().toLowerCase() === code.toLowerCase());
let activityToUse;
@@ -2004,9 +2046,9 @@ export default {
} else {
// Erstelle neue PredefinedActivity
const newActivity = {
- name: result.name || result.fields?.name || '',
+ name: result.name || (result.fields && result.fields.name) || '',
code: code,
- description: result.description || result.fields?.description || '',
+ description: result.description || (result.fields && result.fields.description) || '',
drawingData: result.drawingData || null
};
@@ -2389,9 +2431,209 @@ export default {
this.showInfo('Fehler', 'Fehler beim Erstellen des Mitglieds', getSafeErrorMessage(error), 'error');
}
},
+
+ // Socket.IO Event-Handler
+ setupSocketListeners() {
+ // Event-Handler für Teilnehmer-Änderungen
+ onParticipantAdded(this.handleParticipantAdded);
+ onParticipantRemoved(this.handleParticipantRemoved);
+ onParticipantUpdated(this.handleParticipantUpdated);
+
+ // Event-Handler für Tagebuch-Änderungen
+ onDiaryNoteAdded(this.handleDiaryNoteAdded);
+ onDiaryNoteDeleted(this.handleDiaryNoteDeleted);
+ onDiaryTagAdded(this.handleDiaryTagAdded);
+ onDiaryTagRemoved(this.handleDiaryTagRemoved);
+ onDiaryDateUpdated(this.handleDiaryDateUpdated);
+
+ // Event-Handler für Aktivitäts-Änderungen
+ console.log('🔧 [DiaryView] Registriere Activity-Event-Handler');
+ onActivityMemberAdded(this.handleActivityMemberAdded);
+ onActivityMemberRemoved(this.handleActivityMemberRemoved);
+ onActivityChanged(this.handleActivityChanged);
+ console.log('✅ [DiaryView] Alle Event-Handler registriert');
+ },
+
+ removeSocketListeners() {
+ offParticipantAdded(this.handleParticipantAdded);
+ offParticipantRemoved(this.handleParticipantRemoved);
+ offParticipantUpdated(this.handleParticipantUpdated);
+ offDiaryNoteAdded(this.handleDiaryNoteAdded);
+ offDiaryNoteDeleted(this.handleDiaryNoteDeleted);
+ offDiaryTagAdded(this.handleDiaryTagAdded);
+ offDiaryTagRemoved(this.handleDiaryTagRemoved);
+ offDiaryDateUpdated(this.handleDiaryDateUpdated);
+ offActivityMemberAdded(this.handleActivityMemberAdded);
+ offActivityMemberRemoved(this.handleActivityMemberRemoved);
+ offActivityChanged(this.handleActivityChanged);
+ },
+
+ async handleParticipantAdded(data) {
+ // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
+ if (this.date && this.date !== 'new' && this.date.id === data.dateId) {
+ console.log('📡 Teilnehmer hinzugefügt (Socket):', data);
+ // Lade Teilnehmer neu
+ await this.loadParticipants(data.dateId);
+ }
+ },
+
+ async handleParticipantRemoved(data) {
+ // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
+ if (this.date && this.date !== 'new' && this.date.id === data.dateId) {
+ console.log('📡 Teilnehmer entfernt (Socket):', data);
+ // Entferne aus participants-Array
+ this.participants = this.participants.filter(memberId => memberId !== data.participantId);
+ // Entferne aus Maps
+ delete this.participantMapByMemberId[data.participantId];
+ delete this.memberGroupsMap[data.participantId];
+ }
+ },
+
+ async handleParticipantUpdated(data) {
+ // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
+ if (this.date && this.date !== 'new' && this.date.id === data.dateId) {
+ console.log('📡 Teilnehmer aktualisiert (Socket):', data);
+ // Aktualisiere groupId in memberGroupsMap
+ const groupValue = (data.participant.groupId !== null && data.participant.groupId !== undefined)
+ ? String(data.participant.groupId)
+ : '';
+ this.memberGroupsMap = {
+ ...this.memberGroupsMap,
+ [data.participant.memberId]: groupValue
+ };
+ }
+ },
+
+ async handleDiaryNoteAdded(data) {
+ // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
+ if (this.date && this.date !== 'new' && this.date.id === data.dateId) {
+ console.log('📡 Tagebuch-Notiz hinzugefügt (Socket):', data);
+ // Lade Notizen neu, falls das betroffene Mitglied ausgewählt ist
+ if (this.selectedMember && data.note.memberId === this.selectedMember.id) {
+ try {
+ const notesResponse = await apiClient.get(`/notes?diaryDateId=${this.date.id}&memberId=${this.selectedMember.id}`);
+ this.notes = notesResponse.data;
+ } catch (error) {
+ console.error('Fehler beim Laden der Notizen:', error);
+ }
+ }
+ }
+ },
+
+ async handleDiaryNoteDeleted(data) {
+ // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
+ if (this.date && this.date !== 'new' && this.date.id === data.dateId) {
+ console.log('📡 Tagebuch-Notiz gelöscht (Socket):', data);
+ // Entferne Notiz aus notes-Array
+ this.notes = this.notes.filter(note => note.id !== data.noteId);
+ }
+ },
+
+ async handleDiaryTagAdded(data) {
+ // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
+ if (this.date && this.date !== 'new' && this.date.id === data.dateId) {
+ console.log('📡 Tagebuch-Tag hinzugefügt (Socket):', data);
+ // Lade Tags neu
+ await this.loadTags();
+ // Aktualisiere selectedActivityTags
+ if (data.tag && !this.selectedActivityTags.find(t => t.id === data.tag.id)) {
+ this.selectedActivityTags.push({
+ id: data.tag.id,
+ name: data.tag.name
+ });
+ }
+ }
+ },
+
+ async handleDiaryTagRemoved(data) {
+ // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
+ if (this.date && this.date !== 'new' && this.date.id === data.dateId) {
+ console.log('📡 Tagebuch-Tag entfernt (Socket):', data);
+ // Entferne Tag aus selectedActivityTags
+ this.selectedActivityTags = this.selectedActivityTags.filter(t => t.id !== data.tagId);
+ }
+ },
+
+ async handleDiaryDateUpdated(data) {
+ // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
+ if (this.date && this.date !== 'new' && this.date.id === data.dateId) {
+ console.log('📡 Tagebuch-Datum aktualisiert (Socket):', data);
+ // Aktualisiere Trainingszeiten
+ if (data.updates.trainingStart !== undefined) {
+ this.trainingStart = data.updates.trainingStart;
+ }
+ if (data.updates.trainingEnd !== undefined) {
+ this.trainingEnd = data.updates.trainingEnd;
+ }
+ }
+ },
+
+ async handleActivityMemberAdded(data) {
+ console.log('📡 [DiaryView] handleActivityMemberAdded aufgerufen:', data);
+ console.log('📡 [DiaryView] Aktuelles Datum:', this.date?.id, 'Event dateId:', data.dateId);
+ // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
+ if (this.date && this.date !== 'new' && this.date.id === data.dateId) {
+ console.log('✅ [DiaryView] Datum stimmt überein, lade Training Plan neu');
+ // Lade Training Plan neu
+ try {
+ this.trainingPlan = await apiClient.get(`/diary-date-activities/${this.currentClub}/${this.date.id}`).then(response => response.data);
+ this.calculateIntermediateTimes();
+ console.log('✅ [DiaryView] Training Plan neu geladen');
+ } catch (error) {
+ console.error('❌ [DiaryView] Fehler beim Neuladen des Trainingsplans:', error);
+ }
+ } else {
+ console.log('⚠️ [DiaryView] Datum stimmt nicht überein oder kein Datum ausgewählt');
+ }
+ },
+
+ async handleActivityMemberRemoved(data) {
+ console.log('📡 [DiaryView] handleActivityMemberRemoved aufgerufen:', data);
+ console.log('📡 [DiaryView] Aktuelles Datum:', this.date?.id, 'Event dateId:', data.dateId);
+ // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
+ if (this.date && this.date !== 'new' && this.date.id === data.dateId) {
+ console.log('✅ [DiaryView] Datum stimmt überein, lade Training Plan neu');
+ // Lade Training Plan neu
+ try {
+ this.trainingPlan = await apiClient.get(`/diary-date-activities/${this.currentClub}/${this.date.id}`).then(response => response.data);
+ this.calculateIntermediateTimes();
+ console.log('✅ [DiaryView] Training Plan neu geladen');
+ } catch (error) {
+ console.error('❌ [DiaryView] Fehler beim Neuladen des Trainingsplans:', error);
+ }
+ } else {
+ console.log('⚠️ [DiaryView] Datum stimmt nicht überein oder kein Datum ausgewählt');
+ }
+ },
+
+ async handleActivityChanged(data) {
+ console.log('📡 [DiaryView] handleActivityChanged aufgerufen:', data);
+ console.log('📡 [DiaryView] Aktuelles Datum:', this.date?.id, 'Event dateId:', data.dateId);
+ // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
+ if (this.date && this.date !== 'new' && this.date.id === data.dateId) {
+ console.log('✅ [DiaryView] Datum stimmt überein, lade Training Plan neu');
+ // Lade Training Plan neu
+ try {
+ this.trainingPlan = await apiClient.get(`/diary-date-activities/${this.currentClub}/${this.date.id}`).then(response => response.data);
+ this.calculateIntermediateTimes();
+ console.log('✅ [DiaryView] Training Plan neu geladen');
+ } catch (error) {
+ console.error('❌ [DiaryView] Fehler beim Neuladen des Trainingsplans:', error);
+ }
+ } else {
+ console.log('⚠️ [DiaryView] Datum stimmt nicht überein oder kein Datum ausgewählt');
+ }
+ },
},
async mounted() {
await this.init();
+
+ // Socket.IO verbinden
+ if (this.currentClub) {
+ connectSocket(this.currentClub);
+ this.setupSocketListeners();
+ }
+
// Versuche, Audio erst bei Nutzerinteraktion zu initialisieren (Autoplay-Policy)
const tryInit = () => {
if (!this.bellSound) this.bellSound = new Audio('/sound/bell-123742.mp3');
@@ -2405,6 +2647,12 @@ export default {
if (this.timeChecker) {
clearInterval(this.timeChecker);
}
+
+ // Socket.IO Event-Listener entfernen
+ this.removeSocketListeners();
+
+ // Socket.IO trennen
+ disconnectSocket();
}
};
@@ -2670,9 +2918,12 @@ input[type="number"] {
max-height: 200px;
overflow-y: auto;
position: absolute;
+ top: 100%;
+ left: 0;
+ margin-top: 2px;
background-color: white;
z-index: 9999;
- width: calc(100% - 20px);
+ width: 100%;
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
max-width: 30em;
}
|