From 3f52fdbd70c030570e59cbb15b591cf776f61cff Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Wed, 28 Oct 2026 11:14:08 +0100 Subject: [PATCH] Send club context and surface TTR preview HTTP errors --- .../src/components/MatchReportApiDialog.vue | 22 ++++++++++++---- frontend/tests/ttrPreview.test.mjs | 25 ++++++++++++++++++- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/MatchReportApiDialog.vue b/frontend/src/components/MatchReportApiDialog.vue index c1713c5d..811b4c38 100755 --- a/frontend/src/components/MatchReportApiDialog.vue +++ b/frontend/src/components/MatchReportApiDialog.vue @@ -3369,6 +3369,15 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr this.activeSection = 'ttr'; await this.loadTtrPreview(); }, + readTtrPreviewResponse(response) { + if ((response.status != null && (response.status < 200 || response.status >= 300)) || response.data?.error) { + throw new Error(response.data?.error || response.data?.message || `TTR-Abruf fehlgeschlagen (HTTP ${response.status}).`); + } + if (!Array.isArray(response.data?.players)) { + throw new Error('Der Server hat keine gültigen TTR-Spielerdaten zurückgegeben.'); + } + return response.data; + }, async loadTtrPreview() { if (!this.canOpenTtrPreview || !this.meetingDetails) return; this.ttrLoading = true; @@ -3385,8 +3394,9 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr homeClubName: this.meetingData?.homeClub, guestClubName: this.meetingData?.guestClub, }); - this.ttrDiagnostics = response.data?.diagnostics || []; - this.applyTtrPreviewPlayers(Array.isArray(response.data?.players) ? response.data.players : []); + const payload = this.readTtrPreviewResponse(response); + this.ttrDiagnostics = payload.diagnostics || []; + this.applyTtrPreviewPlayers(payload.players); return; } if (!this.match?.id) { @@ -3394,6 +3404,7 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr return; } const response = await apiClient.post(`/matches/${this.match.id}/ttr-preview`, { + clubId: this.match.clubId ?? this.$store?.getters?.currentClub, homePlayers: this.ttrLineupPlayers('home'), guestPlayers: this.ttrLineupPlayers('guest'), homeTeamName: this.meetingData?.homeTeamname, @@ -3401,10 +3412,11 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr homeClubName: this.meetingData?.homeClub, guestClubName: this.meetingData?.guestClub, }); - this.ttrDiagnostics = response.data?.diagnostics || []; - this.applyTtrPreviewPlayers(Array.isArray(response.data?.players) ? response.data.players : []); + const payload = this.readTtrPreviewResponse(response); + this.ttrDiagnostics = payload.diagnostics || []; + this.applyTtrPreviewPlayers(payload.players); } catch (error) { - this.ttrError = error.response?.data?.error || 'TTR-Werte konnten nicht geladen werden.'; + this.ttrError = error.response?.data?.error || error.message || 'TTR-Werte konnten nicht geladen werden.'; } finally { this.ttrLoading = false; } diff --git a/frontend/tests/ttrPreview.test.mjs b/frontend/tests/ttrPreview.test.mjs index 77991e2c..0136fe03 100644 --- a/frontend/tests/ttrPreview.test.mjs +++ b/frontend/tests/ttrPreview.test.mjs @@ -102,13 +102,14 @@ test('test mode on a saved report calls the real endpoint and exposes lookup dia standaloneTest: false, isTestMode: true, canOpenTtrPreview: true, - match: { id: 42 }, + match: { id: 42, clubId: 7 }, meetingDetails: {}, meetingData: { homeClub: 'TSV 1875 Bonames', guestClub: 'Eintracht Frankfurt' }, }); const originalPost = context.apiClient.post; context.apiClient.post = async (url, body) => { assert.equal(url, '/matches/42/ttr-preview'); + assert.equal(body.clubId, 7); assert.equal(body.homeClubName, 'TSV 1875 Bonames'); assert.equal(body.homePlayers[0].name, 'Anton Schottdorf'); return { data: { players: [], diagnostics: [{ side: 'home', message: 'Session abgelaufen' }] } }; @@ -121,3 +122,25 @@ test('test mode on a saved report calls the real endpoint and exposes lookup dia context.apiClient.post = originalPost; } }); + +test('HTTP errors accepted by the shared API client are shown instead of becoming empty results', async () => { + const report = dialog(); + Object.assign(report, { + standaloneTest: false, canOpenTtrPreview: true, + match: { id: 42, clubId: 7 }, meetingDetails: {}, meetingData: {}, + }); + const originalPost = context.apiClient.post; + try { + for (const status of [400, 401, 403, 404, 500]) { + context.apiClient.post = async () => ({ status, data: { error: `Fehler ${status}` } }); + await report.loadTtrPreview(); + assert.equal(report.ttrError, `Fehler ${status}`); + assert.equal(report.ttrLoading, false); + } + context.apiClient.post = async () => ({ status: 200, data: 'Keine API-Antwort' }); + await report.loadTtrPreview(); + assert.match(report.ttrError, /keine gültigen TTR-Spielerdaten/); + } finally { + context.apiClient.post = originalPost; + } +});