diff --git a/frontend/src/components/CourtDrawingRender.vue b/frontend/src/components/CourtDrawingRender.vue index 24225b2..c76425e 100644 --- a/frontend/src/components/CourtDrawingRender.vue +++ b/frontend/src/components/CourtDrawingRender.vue @@ -110,7 +110,6 @@ export default { this.config.canvas.width = this.width || 600; this.config.canvas.height = this.height || 400; this.$nextTick(() => { - console.log('CourtDrawingRender: mounted with drawingData =', this.drawingData); this.init(); this.redraw(); }); @@ -120,11 +119,9 @@ export default { this.canvas = this.$refs.canvas; if (this.canvas) { this.ctx = this.canvas.getContext('2d'); - console.log('CourtDrawingRender: canvas/context initialized'); } }, redraw() { - console.log('CourtDrawingRender: redraw called with data =', this.drawingData); if (!this.ctx) return; const { width, height } = this.config.canvas; // clear and background diff --git a/frontend/src/components/CourtDrawingTool.vue b/frontend/src/components/CourtDrawingTool.vue index 76cdafb..76273d4 100644 --- a/frontend/src/components/CourtDrawingTool.vue +++ b/frontend/src/components/CourtDrawingTool.vue @@ -344,7 +344,6 @@ export default { this.loadDrawingFromMetadata(); } else if (oldVal && !newVal) { // drawingData wurde auf null gesetzt - reset alle Werte und zeichne leeres Canvas - console.log('CourtDrawingTool: drawingData set to null, resetting all values'); this.resetAllValues(); this.clearCanvas(); this.drawCourt(true); // forceRedraw = true @@ -354,7 +353,6 @@ export default { } }, mounted() { - console.log('CourtDrawingTool: mounted'); this.$nextTick(() => { this.initCanvas(); this.drawCourt(); @@ -365,12 +363,9 @@ export default { }, methods: { initCanvas() { - console.log('CourtDrawingTool: initCanvas called'); this.canvas = this.$refs.drawingCanvas; - console.log('CourtDrawingTool: canvas =', this.canvas); if (this.canvas) { this.ctx = this.canvas.getContext('2d'); - console.log('CourtDrawingTool: ctx =', this.ctx); this.ctx.lineCap = this.config.pen.cap; this.ctx.lineJoin = this.config.pen.join; } else { @@ -379,7 +374,6 @@ export default { }, drawCourt(forceRedraw = false) { - console.log('CourtDrawingTool: drawCourt called, forceRedraw:', forceRedraw); const ctx = this.ctx; const canvas = this.canvas; const config = this.config; @@ -389,8 +383,6 @@ export default { return; } - console.log('CourtDrawingTool: Drawing court...'); - console.log('Canvas dimensions:', canvas.width, 'x', canvas.height); // Hintergrund immer zeichnen wenn forceRedraw=true, sonst nur wenn Canvas leer ist const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); @@ -400,9 +392,7 @@ export default { // Hintergrund ctx.fillStyle = '#f0f0f0'; ctx.fillRect(0, 0, canvas.width, canvas.height); - console.log('Background drawn'); } else { - console.log('Canvas not empty, skipping background'); } // Tischtennis-Tisch @@ -411,8 +401,6 @@ export default { const tableX = (canvas.width - tableWidth) / 2; const tableY = (canvas.height - tableHeight) / 2; - console.log('Table dimensions:', tableWidth, 'x', tableHeight); - console.log('Table position:', tableX, ',', tableY); // Tischtennis-Tisch Hintergrund ctx.fillStyle = config.table.color; @@ -1074,9 +1062,6 @@ export default { }, testDraw() { - console.log('CourtDrawingTool: testDraw called'); - console.log('Canvas:', this.canvas); - console.log('Context:', this.ctx); if (!this.canvas || !this.ctx) { console.error('Canvas or context not available, trying to reinitialize...'); @@ -1084,7 +1069,6 @@ export default { } if (this.canvas && this.ctx) { - console.log('Drawing simple test...'); // Einfacher Test: Roter Kreis this.ctx.fillStyle = 'red'; @@ -1092,18 +1076,15 @@ export default { this.ctx.arc(300, 200, 50, 0, 2 * Math.PI); this.ctx.fill(); - console.log('Red circle drawn'); } else { console.error('Still no canvas or context available'); } }, - async saveDrawing() { - console.log('CourtDrawingTool: saveDrawing called'); + async saveDrawing() { try { const dataURL = this.canvas.toDataURL('image/png'); - console.log('CourtDrawingTool: dataURL created, length:', dataURL.length); this.$emit('input', dataURL); @@ -1121,7 +1102,6 @@ export default { timestamp: new Date().toISOString() }; - console.log('CourtDrawingTool: drawingData created:', drawingData); // Immer Metadaten nach oben geben this.$emit('update-drawing-data', drawingData); @@ -1129,18 +1109,12 @@ export default { // Konvertiere DataURL zu Blob für Upload const response = await fetch(dataURL); const blob = await response.blob(); - console.log('CourtDrawingTool: blob created, size:', blob.size); // Erstelle File-Objekt const file = new File([blob], `exercise-${Date.now()}.png`, { type: 'image/png' }); - console.log('CourtDrawingTool: file created:', file); - console.log('CourtDrawingTool: file type:', file.type); - console.log('CourtDrawingTool: file size:', file.size); // Emittiere das File und die Zeichnungsdaten für Upload - console.log('CourtDrawingTool: emitting upload-image event'); this.$emit('upload-image', file, drawingData); - console.log('CourtDrawingTool: upload-image event emitted'); } else { // Kein Bild-Upload mehr: gebe lediglich die Zeichnungsdaten an den Parent weiter, // damit Felder (Kürzel/Name/Beschreibung) gefüllt werden können @@ -1173,7 +1147,6 @@ export default { }, resetAllValues() { - console.log('CourtDrawingTool: Resetting all values to initial state'); this.selectedStartPosition = null; this.selectedCirclePosition = null; this.strokeType = null; @@ -1189,7 +1162,6 @@ export default { loadDrawingFromMetadata() { if (this.drawingData) { - console.log('CourtDrawingTool: Loading drawing from metadata:', this.drawingData); // Lade alle Zeichnungsdaten this.selectedStartPosition = this.drawingData.selectedStartPosition || null; @@ -1213,7 +1185,7 @@ export default { this.selectedCirclePosition = 'bottom'; } - console.log('CourtDrawingTool: Loaded values:', { + this.$emit('drawing-data', { selectedStartPosition: this.selectedStartPosition, selectedCirclePosition: this.selectedCirclePosition, strokeType: this.strokeType, @@ -1229,7 +1201,6 @@ export default { this.drawCourt(); }); - console.log('CourtDrawingTool: Drawing loaded from metadata'); } }, diff --git a/frontend/src/components/SeasonSelector.vue b/frontend/src/components/SeasonSelector.vue index 43e800d..f806c61 100644 --- a/frontend/src/components/SeasonSelector.vue +++ b/frontend/src/components/SeasonSelector.vue @@ -83,9 +83,7 @@ export default { error.value = null; try { - console.log('SeasonSelector: Loading seasons'); const response = await apiClient.get('/seasons'); - console.log('SeasonSelector: Loaded seasons:', response.data); seasons.value = response.data; // Wenn showCurrentSeason true ist und keine Saison ausgewählt, wähle die aktuelle diff --git a/frontend/src/views/PredefinedActivities.vue b/frontend/src/views/PredefinedActivities.vue index 8b69b8d..7853804 100644 --- a/frontend/src/views/PredefinedActivities.vue +++ b/frontend/src/views/PredefinedActivities.vue @@ -179,7 +179,6 @@ export default { const r = await apiClient.get(`/predefined-activities/${this.editModel.id}`); const { images } = r.data; this.images = images || []; - console.log('Images reloaded:', this.images); } catch (error) { console.error('Error reloading images:', error); } @@ -218,7 +217,6 @@ export default { async save() { if (!this.editModel) return; - console.log('Save: selectedFile =', this.selectedFile); if (this.editModel.id) { const { id, ...payload } = this.editModel; @@ -234,10 +232,8 @@ export default { // Nach dem Speichern (sowohl CREATE als auch UPDATE): Bild hochladen falls vorhanden if (this.selectedFile) { - console.log('Uploading image after save...'); await this.uploadImage(); } else { - console.log('No selectedFile to upload'); } await this.reload(); @@ -250,16 +246,9 @@ export default { }, async uploadImage() { if (!this.editModel || !this.editModel.id || !this.selectedFile) { - console.log('Upload skipped: editModel=', this.editModel, 'selectedFile=', this.selectedFile); return; } - console.log('Starting image upload...'); - console.log('editModel:', this.editModel); - console.log('selectedActivity:', this.selectedActivity); - console.log('Activity ID (editModel.id):', this.editModel.id); - console.log('Activity ID (selectedActivity.id):', this.selectedActivity?.id); - console.log('File:', this.selectedFile); const fd = new FormData(); fd.append('image', this.selectedFile); @@ -267,20 +256,17 @@ export default { // Füge Zeichnungsdaten hinzu, falls vorhanden if (this.selectedDrawingData) { fd.append('drawingData', JSON.stringify(this.selectedDrawingData)); - console.log('Added drawingData to FormData:', this.selectedDrawingData); } // Verwende PUT für Updates, POST für neue Activities const isUpdate = this.selectedActivity && this.selectedActivity.id === this.editModel.id; const method = isUpdate ? 'put' : 'post'; - console.log('Using method:', method); try { const response = await apiClient[method](`/predefined-activities/${this.editModel.id}/image`, fd, { headers: { 'Content-Type': 'multipart/form-data' } }); - console.log('Upload successful:', response); // Nach Upload Details neu laden await this.select(this.editModel); @@ -334,24 +320,15 @@ export default { }, async onDrawingImageUpload(file, drawingData) { - console.log('onDrawingImageUpload called with file:', file); - console.log('onDrawingImageUpload called with drawingData:', drawingData); - console.log('File type:', file?.type); - console.log('File size:', file?.size); - console.log('File name:', file?.name); // Setze das File und die Zeichnungsdaten für den Upload this.selectedFile = file; this.selectedDrawingData = drawingData; - console.log('selectedFile set to:', this.selectedFile); - console.log('selectedDrawingData set to:', this.selectedDrawingData); // Upload wird erst beim Speichern durchgeführt - console.log('File and drawing data ready for upload when saving'); }, async onImageUploaded() { - console.log('Image uploaded successfully, refreshing image list...'); // Bildliste aktualisieren if (this.editModel && this.editModel.id) { await this.select(this.editModel); diff --git a/frontend/src/views/ScheduleView.vue b/frontend/src/views/ScheduleView.vue index 3cdb63f..41bf0ed 100644 --- a/frontend/src/views/ScheduleView.vue +++ b/frontend/src/views/ScheduleView.vue @@ -49,15 +49,15 @@ {{ match.leagueDetails?.name || 'N/A' }} - {{ match.code }} + {{ match.code }} - - {{ match.homePin }} + {{ match.homePin }} - - {{ match.guestPin }} + {{ match.guestPin }} - @@ -204,18 +204,14 @@ export default { try { const clubId = this.currentClub; const seasonParam = this.selectedSeasonId ? `?seasonid=${this.selectedSeasonId}` : ''; - console.log('ScheduleView: Loading leagues for club:', clubId, 'season:', this.selectedSeasonId); const response = await apiClient.get(`/matches/leagues/current/${clubId}${seasonParam}`); - console.log('ScheduleView: Loaded leagues:', response.data); this.leagues = this.sortLeagues(response.data); - console.log('ScheduleView: Sorted leagues:', this.leagues); } catch (error) { console.error('ScheduleView: Error loading leagues:', error); alert('Fehler beim Laden der Ligen'); } }, onSeasonChange(season) { - console.log('ScheduleView: Season changed to:', season); this.currentSeason = season; this.loadLeagues(); // Leere die aktuellen Matches, da sie für eine andere Saison sind @@ -345,6 +341,30 @@ export default { return ''; // Keine besondere Farbe }, + async copyToClipboard(text, type) { + try { + await navigator.clipboard.writeText(text); + // Zeige eine kurze Bestätigung + const originalText = event.target.textContent; + event.target.textContent = '✓'; + event.target.style.color = '#4CAF50'; + + setTimeout(() => { + event.target.textContent = originalText; + event.target.style.color = ''; + }, 1000); + + } catch (err) { + console.error('Fehler beim Kopieren:', err); + // Fallback für ältere Browser + const textArea = document.createElement('textarea'); + textArea.value = text; + document.body.appendChild(textArea); + textArea.select(); + document.execCommand('copy'); + document.body.removeChild(textArea); + } + }, }, async created() { // Ligen werden geladen, sobald eine Saison ausgewählt ist @@ -506,6 +526,17 @@ li { border: 1px solid #bbdefb; } +.code-value.clickable { + cursor: pointer; + transition: all 0.2s ease; +} + +.code-value.clickable:hover { + background: #bbdefb; + transform: scale(1.05); + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + .pin-value { background: #fff3e0; color: #f57c00; @@ -516,6 +547,17 @@ li { border: 1px solid #ffcc02; } +.pin-value.clickable { + cursor: pointer; + transition: all 0.2s ease; +} + +.pin-value.clickable:hover { + background: #ffcc02; + transform: scale(1.05); + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + .no-data { color: #999; font-style: italic; diff --git a/frontend/src/views/TeamManagementView.vue b/frontend/src/views/TeamManagementView.vue index f549941..c88f044 100644 --- a/frontend/src/views/TeamManagementView.vue +++ b/frontend/src/views/TeamManagementView.vue @@ -263,14 +263,11 @@ export default { const loadTeams = async () => { if (!selectedClub.value || !selectedSeasonId.value) { - console.log('TeamManagementView: Skipping loadTeams - club:', selectedClub.value, 'season:', selectedSeasonId.value); return; } try { - console.log('TeamManagementView: Loading club teams for club:', selectedClub.value, 'season:', selectedSeasonId.value); const response = await apiClient.get(`/club-teams/club/${selectedClub.value}?seasonid=${selectedSeasonId.value}`); - console.log('TeamManagementView: Loaded club teams:', response.data); teams.value = response.data; // Lade alle Team-Dokumente nach dem Laden der Teams @@ -284,10 +281,8 @@ export default { if (!selectedClub.value) return; try { - console.log('TeamManagementView: Loading leagues for club:', selectedClub.value, 'season:', selectedSeasonId.value); const seasonParam = selectedSeasonId.value ? `?seasonid=${selectedSeasonId.value}` : ''; const response = await apiClient.get(`/club-teams/leagues/${selectedClub.value}${seasonParam}`); - console.log('TeamManagementView: Loaded leagues:', response.data); leagues.value = response.data; } catch (error) { console.error('Fehler beim Laden der Spielklassen:', error); @@ -408,9 +403,7 @@ export default { if (!teamToEdit.value) return; try { - console.log('TeamManagementView: Loading documents for team:', teamToEdit.value.id); const response = await apiClient.get(`/team-documents/club-team/${teamToEdit.value.id}`); - console.log('TeamManagementView: Loaded documents:', response.data); teamDocuments.value = response.data; } catch (error) { console.error('Fehler beim Laden der Team-Dokumente:', error); @@ -421,7 +414,6 @@ export default { if (!selectedClub.value) return; try { - console.log('TeamManagementView: Loading all team documents for club:', selectedClub.value); // Lade alle Dokumente für alle Teams des Clubs const allDocuments = []; for (const team of teams.value) { @@ -433,7 +425,6 @@ export default { } } teamDocuments.value = allDocuments; - console.log('TeamManagementView: Loaded all team documents:', allDocuments.length); } catch (error) { console.error('Fehler beim Laden aller Team-Dokumente:', error); } @@ -448,7 +439,6 @@ export default { parsingInProgress.value = true; try { - console.log('Datei hochladen und parsen:', pendingUploadFile.value.name, 'Typ:', pendingUploadType.value, 'für Liga:', teamToEdit.value.leagueId); // Schritt 1: Datei als Team-Dokument hochladen const formData = new FormData(); @@ -461,14 +451,12 @@ export default { } }); - console.log('Datei hochgeladen:', uploadResponse.data); // Schritt 2: Datei parsen (nur für PDF/TXT-Dateien) const fileExtension = pendingUploadFile.value.name.toLowerCase().split('.').pop(); if (fileExtension === 'pdf' || fileExtension === 'txt') { const parseResponse = await apiClient.post(`/team-documents/${uploadResponse.data.id}/parse?leagueid=${teamToEdit.value.leagueId}`); - console.log('Datei erfolgreich geparst:', parseResponse.data); const { parseResult, saveResult } = parseResponse.data; @@ -543,11 +531,9 @@ export default { } try { - console.log('PDF parsen:', document.originalFileName, 'für Liga:', team.leagueId); const response = await apiClient.post(`/team-documents/${document.id}/parse?leagueid=${team.leagueId}`); - console.log('PDF erfolgreich geparst:', response.data); const { parseResult, saveResult } = response.data; @@ -579,11 +565,6 @@ export default { // Lifecycle onMounted(() => { - console.log('TeamManagementView: onMounted - Store state:', { - currentClub: store.state.currentClub, - token: store.state.token, - username: store.state.username - }); // Lade Ligen beim ersten Laden der Seite (ohne Saison-Filter) loadLeagues(); }); diff --git a/frontend/src/views/TournamentsView.vue b/frontend/src/views/TournamentsView.vue index 0e9f185..04e567d 100644 --- a/frontend/src/views/TournamentsView.vue +++ b/frontend/src/views/TournamentsView.vue @@ -586,7 +586,6 @@ export default { try { const d = await apiClient.get(`/tournament/${this.currentClub}`); this.dates = d.data; - console.log('Loaded tournaments:', this.dates); // Prüfe, ob es einen Trainingstag heute gibt await this.checkTrainingToday(); @@ -601,7 +600,6 @@ export default { const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD Format const response = await apiClient.get(`/diary/${this.currentClub}`); - console.log('Training check response:', response.data); // Die API gibt alle Trainingstage zurück, filtere nach heute const trainingData = response.data; @@ -610,7 +608,6 @@ export default { } else { this.hasTrainingToday = false; } - console.log('Training today:', this.hasTrainingToday); } catch (error) { console.error('Fehler beim Prüfen des Trainingstags:', error); this.hasTrainingToday = false; @@ -625,7 +622,6 @@ export default { date: this.newDate }); - console.log('Tournament created, response:', r.data); // Speichere die ID des neuen Turniers const newTournamentId = r.data.id; @@ -982,7 +978,6 @@ export default { }, highlightMatch(player1Id, player2Id, groupId) { - console.log('highlightMatch called:', { player1Id, player2Id, groupId }); // Finde das entsprechende Match (auch unbeendete) const match = this.matches.find(m => @@ -992,17 +987,14 @@ export default { (m.player1.id === player2Id && m.player2.id === player1Id)) ); - console.log('Found match:', match); if (!match) { - console.log('No match found'); return; } // Setze Highlight-Klasse this.$nextTick(() => { const matchElement = document.querySelector(`tr[data-match-id="${match.id}"]`); - console.log('Match element:', matchElement); if (matchElement) { // Entferne vorherige Highlights @@ -1019,7 +1011,6 @@ export default { block: 'center' }); } else { - console.log('Match element not found in DOM'); } }); }, @@ -1083,23 +1074,18 @@ export default { const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD Format const response = await apiClient.get(`/diary/${this.currentClub}`); - console.log('Training response:', response.data); - console.log('Looking for date:', today); // Die API gibt alle Trainingstage zurück, filtere nach heute const trainingData = response.data; if (Array.isArray(trainingData)) { - console.log('Available training dates:', trainingData.map(t => t.date)); // Finde den Trainingstag für heute const todayTraining = trainingData.find(training => training.date === today); - console.log('Today training found:', todayTraining); if (todayTraining) { // Lade die Teilnehmer für diesen Trainingstag über die Participant-API const participantsResponse = await apiClient.get(`/participants/${todayTraining.id}`); - console.log('Participants response:', participantsResponse.data); const participants = participantsResponse.data;