diff --git a/backend/routes/nuscoreApiRoutes.js b/backend/routes/nuscoreApiRoutes.js index 82423377..af9ad438 100644 --- a/backend/routes/nuscoreApiRoutes.js +++ b/backend/routes/nuscoreApiRoutes.js @@ -188,6 +188,18 @@ router.put('/submit/:uuid', async (req, res) => { const { uuid } = req.params; const reportData = req.body; + console.log('[nuscore submit] request', { + uuid, + wo: reportData?.wo ?? null, + isCompleted: reportData?.isCompleted ?? null, + homePin: reportData?.homePin ?? null, + guestPin: reportData?.guestPin ?? null, + releaseSignatureHome: reportData?.signature?.releaseSignatureHome ?? null, + releaseSignatureGuest: reportData?.signature?.releaseSignatureGuest ?? null, + lineupSignatureHome: reportData?.signature?.lineupSignatureHome ?? null, + lineupSignatureGuest: reportData?.signature?.lineupSignatureGuest ?? null + }); + try { // Hole Cookies für diese UUID (falls vorhanden) // Versuche zuerst UUID, dann Code als Fallback @@ -229,12 +241,26 @@ router.put('/submit/:uuid', async (req, res) => { responseData = { message: responseText }; } - if (!response.ok) { + console.log('[nuscore submit] response', { + uuid, + httpStatus: response.status, + resultState: responseData?.resultState ?? null, + validationErrors: responseData?.validationErrors ?? [], + releaseSignatureHome: responseData?.object?.signature?.releaseSignatureHome ?? null, + releaseSignatureGuest: responseData?.object?.signature?.releaseSignatureGuest ?? null, + lineupSignatureHome: responseData?.object?.signature?.lineupSignatureHome ?? null, + lineupSignatureGuest: responseData?.object?.signature?.lineupSignatureGuest ?? null + }); + + const resultState = responseData?.resultState; + const validationErrors = Array.isArray(responseData?.validationErrors) ? responseData.validationErrors : []; + + if (!response.ok || resultState === 'VALIDATION_ERROR') { console.error(`❌ Submit fehlgeschlagen: HTTP ${response.status}`, responseData); - return res.status(response.status).json({ + return res.status(resultState === 'VALIDATION_ERROR' ? 422 : response.status).json({ error: 'Fehler beim Absenden des Spielberichts', details: responseData, - status: response.status, + status: resultState === 'VALIDATION_ERROR' ? 422 : response.status, statusText: response.statusText }); } @@ -294,6 +320,18 @@ router.put('/validate/:uuid', async (req, res) => { const { uuid } = req.params; const reportData = req.body; + console.log('[nuscore validate] request', { + uuid, + wo: reportData?.wo ?? null, + isCompleted: reportData?.isCompleted ?? null, + homePin: reportData?.homePin ?? null, + guestPin: reportData?.guestPin ?? null, + releaseSignatureHome: reportData?.signature?.releaseSignatureHome ?? null, + releaseSignatureGuest: reportData?.signature?.releaseSignatureGuest ?? null, + lineupSignatureHome: reportData?.signature?.lineupSignatureHome ?? null, + lineupSignatureGuest: reportData?.signature?.lineupSignatureGuest ?? null + }); + try { // Hole Cookies für diese UUID (falls vorhanden) // Versuche zuerst UUID, dann Code als Fallback @@ -335,6 +373,17 @@ router.put('/validate/:uuid', async (req, res) => { responseData = { message: responseText }; } + console.log('[nuscore validate] response', { + uuid, + httpStatus: response.status, + resultState: responseData?.resultState ?? null, + validationErrors: responseData?.validationErrors ?? [], + releaseSignatureHome: responseData?.object?.signature?.releaseSignatureHome ?? null, + releaseSignatureGuest: responseData?.object?.signature?.releaseSignatureGuest ?? null, + lineupSignatureHome: responseData?.object?.signature?.lineupSignatureHome ?? null, + lineupSignatureGuest: responseData?.object?.signature?.lineupSignatureGuest ?? null + }); + // Speichere neue Cookies falls vorhanden const newCookies = extractCookies(response.headers.raw()['set-cookie']); if (Object.keys(newCookies).length > 0) { diff --git a/docs/OPTIMIZATION_TODO.md b/docs/OPTIMIZATION_TODO.md index 9fe7b6db..48b8320f 100644 --- a/docs/OPTIMIZATION_TODO.md +++ b/docs/OPTIMIZATION_TODO.md @@ -102,7 +102,7 @@ Diese Liste beschreibt die naechsten sinnvollen Optimierungsschritte nach dem zu ## Prioritaet D -- [ ] Selten genutzte Spezialviews optisch komplett an das Theme angleichen. +- [x] Selten genutzte Spezialviews optisch komplett an das Theme angleichen. Wahrscheinliche Kandidaten: - `MatchReportDialog.vue` - `NuscoreAnalyzer.vue` @@ -110,25 +110,42 @@ Diese Liste beschreibt die naechsten sinnvollen Optimierungsschritte nach dem zu - `PermissionsView.vue` Ziel: - keine hart sichtbaren Bootstrap-/Altfarben in Randbereichen + Erledigt am 2026-03-17: + - `MatchReportDialog.vue`, `NuscoreAnalyzer.vue` und `PermissionsView.vue` auf Theme-Farben und ruhigere Statusflaechen umgestellt + - `TournamentResultsTab.vue` als verbleibender sichtbarer Tournament-Randbereich an die Badge-/Statuslogik des Themes angepasst -- [ ] Zeichnungs-/Court-Komponenten visuell und technisch aufraeumen. +- [x] Zeichnungs-/Court-Komponenten visuell und technisch aufraeumen. Kandidaten: - `CourtDrawingTool.vue` - `CourtDrawingRender.vue` Grund: - grosse Komponenten - funktionale Farbsemantik gemischt mit Alt-Styling + Erledigt am 2026-03-17: + - Court-Paletten zentralisiert + - Tool-/Render-Flaechen, Buttons und Grid-Zustaende ans Theme angepasst + - verbliebene harte Altfarben im sichtbaren UI deutlich reduziert ## Querliegende Verbesserungen -- [ ] Manuelle SQL-Migrationen kuenftig direkt mit jeder Schemaaenderung in `docs/manual_sql_migrations.md` mitpflegen. +- [x] Manuelle SQL-Migrationen kuenftig direkt mit jeder Schemaaenderung in `docs/manual_sql_migrations.md` mitpflegen. + Erledigt am 2026-03-18: + - Pflege-Regel direkt in `docs/manual_sql_migrations.md` dokumentiert + - SQL-Migrationsdoku damit nicht mehr nur Sammelablage, sondern verbindlicher Prozesspunkt -- [ ] Fuer grosse Frontend-Dateien eine grobe Zielgroesse einfuehren. +- [x] Fuer grosse Frontend-Dateien eine grobe Zielgroesse einfuehren. Vorschlag: - Warnbereich ab ~80 KB - struktureller Refactor ab ~120 KB + Erledigt am 2026-03-18: + - `docs/frontend_size_budget.md` angelegt + - Audit-Skript `npm run audit:frontend-size` ergaenzt -- [ ] Inline-TODOs/FIXMEs regelmaessig in Repo-Doku ueberfuehren und aus produktiven Hauptdateien entfernen. +- [x] Inline-TODOs/FIXMEs regelmaessig in Repo-Doku ueberfuehren und aus produktiven Hauptdateien entfernen. + Erledigt am 2026-03-18: + - `docs/inline_todo_registry.md` angelegt + - Audit-Skript `npm run audit:inline-todos` ergaenzt + - Produktivcode per Audit geprueft: keine offenen Marker in `frontend/src` und `backend` ## Aktuelle groesste Kandidaten nach Dateigroesse diff --git a/docs/frontend_size_budget.md b/docs/frontend_size_budget.md new file mode 100644 index 00000000..df33579d --- /dev/null +++ b/docs/frontend_size_budget.md @@ -0,0 +1,44 @@ +# Frontend Size Budget + +Stand: 2026-03-18 + +## Ziel + +Grosse Frontend-Dateien sollen frueh sichtbar werden, bevor einzelne Views oder Komponenten wieder schwer wartbar werden. + +## Regeln + +- `warn` ab grob `80 KB` +- `refactor` ab grob `120 KB` + +Diese Werte sind bewusst pragmatisch und gelten fuer: + +- `.vue` +- `.js` +- `.ts` +- `.scss` + +unter `frontend/src/`. + +## Verwendung + +Audit aus dem Repo-Root: + +```bash +npm run audit:frontend-size +``` + +Das Skript liefert eine sortierte Liste der groessten Frontend-Dateien und markiert sie als: + +- `ok` +- `warn` +- `refactor` + +## Aktueller Umgang + +- `warn` bedeutet: bei der naechsten groesseren Aenderung Struktur pruefen. +- `refactor` bedeutet: keine weitere groessere Fachlogik ohne vorherige oder parallele Extraktion in Subkomponenten/Services. + +## Aktuelle Kandidaten + +Die aktuelle Liste wird bewusst nicht statisch doppelt gepflegt. Stattdessen ist `npm run audit:frontend-size` die Referenz. diff --git a/docs/inline_todo_registry.md b/docs/inline_todo_registry.md new file mode 100644 index 00000000..a98f0dbb --- /dev/null +++ b/docs/inline_todo_registry.md @@ -0,0 +1,30 @@ +# Inline TODO Registry + +Stand: 2026-03-18 + +## Regel + +Produktiver Frontend-/Backend-Code soll keine offenen `TODO`, `FIXME` oder `XXX` Marker dauerhaft enthalten. + +Wenn waehrend der Entwicklung ein solcher Marker noetig ist: + +1. so kurz wie moeglich im Code belassen +2. in eine Doku-Datei oder Issue-Liste ueberfuehren +3. den Marker im Produktivcode wieder entfernen + +## Audit + +Aus dem Repo-Root: + +```bash +npm run audit:inline-todos +``` + +## Aktueller Stand + +Zum Stand `2026-03-18` gibt es keine offenen `TODO`-/`FIXME`-/`XXX`-Marker mehr in: + +- `frontend/src` +- `backend` + +Verbleibende TODO-Abschnitte liegen nur noch in Dokumentation, z.B. fuer Android-Portierung oder fachliche Backlog-Punkte. diff --git a/docs/manual_sql_migrations.md b/docs/manual_sql_migrations.md index 5ef0cb94..a9e729e6 100644 --- a/docs/manual_sql_migrations.md +++ b/docs/manual_sql_migrations.md @@ -2,6 +2,20 @@ Diese Datei sammelt SQL-Aenderungen, die auf Live/Test manuell eingespielt werden muessen, wenn das Produktions-Setup keine automatische Schema-Migration ausfuehrt. +## Pflege-Regel + +Ab jetzt gilt fuer jede Schemaaenderung: + +1. SQL fuer `test` und `live` direkt hier eintragen. +2. Datum, betroffene Tabelle/Felder und optionalen Backfill dokumentieren. +3. Erst danach den Frontend-/Backend-Teil als abgeschlossen markieren. + +Ergaenzend: + +- Die produktive Anwendung soll sich nicht auf `sync({ alter: true })` verlassen. +- Manuelle Migrationsschritte gehoeren in diese Datei, nicht nur in Chat-Verlaeufe oder Commit-Messages. +- Wenn eine Aenderung rueckwaertskompatibel ist, soll das hier explizit vermerkt werden. + ## 2026-03-17 ### `predefined_activities.exclude_from_stats` @@ -49,3 +63,7 @@ Optionaler Schutz gegen doppelte Teilnehmerzeilen pro Trainingstag: ALTER TABLE participants ADD UNIQUE KEY participants_diary_date_member_unique (diary_date_id, member_id); ``` + +Rueckwaertskompatibilitaet: + +- Bestehende Datensaetze bleiben durch den Default `present` gueltig. diff --git a/frontend/src/components/CourtDrawingRender.vue b/frontend/src/components/CourtDrawingRender.vue index 1b7bd101..25a1fc00 100644 --- a/frontend/src/components/CourtDrawingRender.vue +++ b/frontend/src/components/CourtDrawingRender.vue @@ -14,13 +14,33 @@ ref="canvas" :width="config.canvas.width" :height="config.canvas.height" - style="margin:0 auto;" + class="render-canvas" >