From e2956576216a426bc28b75e5dee2a0071ec46e9d Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Wed, 12 Nov 2025 16:13:04 +0100 Subject: [PATCH] Add validation endpoint for meeting reports and enhance frontend functionality This commit introduces a new API endpoint in the backend for validating meeting reports, allowing for improved error handling and cookie management. The frontend has been updated to include a validation function that checks the report data before submission, providing users with feedback on validation warnings and errors. These changes enhance the overall user experience by ensuring data integrity and improving interaction with the meeting report feature. --- backend/routes/nuscoreApiRoutes.js | 76 +++++++++++++++++++ .../src/components/MatchReportApiDialog.vue | 53 ++++++++++++- 2 files changed, 127 insertions(+), 2 deletions(-) diff --git a/backend/routes/nuscoreApiRoutes.js b/backend/routes/nuscoreApiRoutes.js index 064a1f2..b2ccaba 100644 --- a/backend/routes/nuscoreApiRoutes.js +++ b/backend/routes/nuscoreApiRoutes.js @@ -271,4 +271,80 @@ router.put('/submit/:uuid', async (req, res) => { } }); +// Validate Meeting Report API-Endpunkt (für Zwischenspeicherung) +router.put('/validate/:uuid', async (req, res) => { + const { uuid } = req.params; + const reportData = req.body; + + try { + // Hole Cookies für diese UUID (falls vorhanden) + // Versuche zuerst UUID, dann Code als Fallback + let cookies = cookieStore.get(uuid) || {}; + + // Falls keine Cookies für UUID vorhanden, versuche Code zu finden + if (Object.keys(cookies).length === 0 && reportData.gameCode) { + cookies = cookieStore.get(reportData.gameCode) || {}; + } + + const url = `https://ttde-apps.liga.nu/nuliga/rs/tt/2022/meetingentry/reports/${uuid}/validate`; + + const response = await fetch(url, { + method: 'PUT', + headers: { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0', + 'Accept': 'application/json, text/plain, */*', + 'Accept-Language': 'de,en-US;q=0.7,en;q=0.3', + 'Accept-Encoding': 'gzip, deflate, br, zstd', + 'Content-Type': 'application/json', + 'Referer': `https://ttde-apps.liga.nu/nuliga/nuscore-tt/meeting/${uuid}/report-clearance/review`, + 'Origin': 'https://ttde-apps.liga.nu', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'same-origin', + 'Connection': 'keep-alive', + ...(Object.keys(cookies).length > 0 && { 'Cookie': formatCookies(cookies) }) + }, + body: JSON.stringify(reportData) + }); + + const responseText = await response.text(); + let responseData; + + try { + responseData = JSON.parse(responseText); + } catch (e) { + // Falls keine JSON-Antwort, verwende Text + responseData = { message: responseText }; + } + + // Speichere neue Cookies falls vorhanden + const newCookies = extractCookies(response.headers.raw()['set-cookie']); + if (Object.keys(newCookies).length > 0) { + cookieStore.set(uuid, { ...cookies, ...newCookies }); + if (reportData.gameCode) { + cookieStore.set(reportData.gameCode, { ...cookies, ...newCookies }); + } + } + + // CORS-Header setzen + res.set({ + 'Content-Type': 'application/json; charset=utf-8', + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type', + 'Cache-Control': 'no-cache, no-store, must-revalidate' + }); + + // Validiere auch bei Fehlern (für Validierungsfehler) + res.status(response.status).json(responseData); + + } catch (error) { + console.error(`❌ Fehler beim Validieren des Spielberichts für UUID ${uuid}:`, error); + res.status(500).json({ + error: 'Fehler beim Validieren des Spielberichts', + details: error.message + }); + } +}); + export default router; diff --git a/frontend/src/components/MatchReportApiDialog.vue b/frontend/src/components/MatchReportApiDialog.vue index 2fda516..ac7f381 100644 --- a/frontend/src/components/MatchReportApiDialog.vue +++ b/frontend/src/components/MatchReportApiDialog.vue @@ -1467,6 +1467,55 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr } }, + async validateReport() { + try { + if (!this.meetingData || !this.meetingData.nuLigaMeetingUuid) { + console.warn('⚠️ Keine Meeting-UUID verfügbar für Validierung'); + return; + } + + // Erstelle eine Kopie des aktuellen Match-Objekts + const matchData = JSON.parse(JSON.stringify(this.match)); + + // Aktualisiere die Match-Daten mit unseren Eingaben + this.updateMatchData(matchData); + + const uuid = this.meetingData.nuLigaMeetingUuid; + + console.log('🔄 Validiere Spielbericht...'); + + const response = await fetch(`${backendBaseUrl}/api/nuscore/validate/${uuid}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(matchData) + }); + + const result = await response.json(); + + if (response.ok) { + console.log('✅ Validierung erfolgreich:', result); + + // Zeige Validierungswarnungen falls vorhanden + if (result.validationWarnings && result.validationWarnings.length > 0) { + console.warn('⚠️ Validierungswarnungen:', result.validationWarnings); + } + + // Zeige Validierungsfehler falls vorhanden + if (result.validationErrors && result.validationErrors.length > 0) { + console.error('❌ Validierungsfehler:', result.validationErrors); + } + } else { + console.warn('⚠️ Validierung mit Fehlern:', result); + } + + } catch (error) { + console.error('❌ Fehler beim Validieren:', error); + // Validierungsfehler sind nicht kritisch, daher kein Alert + } + }, + showMatchDataDialog(matchData) { // Erstelle einen neuen Dialog für die Datenanzeige const dialog = document.createElement('div'); @@ -2837,8 +2886,8 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr // Intelligente Navigation nach Zertifizierung this.navigateAfterCertification(); - // TODO: Hier würden wir die signierte Aufstellung an das Backend senden - // await this.submitSignedLineup(team); + // Validiere und speichere die Änderungen + await this.validateReport(); } else { this.showSigningError(team); }