From 07370bfcef146d61df435383a28f5040caee3009 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Thu, 26 Feb 2026 16:18:55 +0100 Subject: [PATCH] feat(match-report): implement floating keyboard for set input in MatchReportApiDialog - Added a floating keyboard overlay for set input, allowing users to enter scores without using the system keyboard. - Updated input fields to be read-only and disabled system keyboard interactions, enhancing user experience. - Implemented methods to manage keyboard interactions, including key input, backspace, and confirmation actions. - Improved styling for the floating keyboard to ensure clarity and usability during score entry. --- .../src/components/MatchReportApiDialog.vue | 155 +++++++++++++++--- 1 file changed, 132 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/MatchReportApiDialog.vue b/frontend/src/components/MatchReportApiDialog.vue index e295213d..89a803ba 100644 --- a/frontend/src/components/MatchReportApiDialog.vue +++ b/frontend/src/components/MatchReportApiDialog.vue @@ -386,27 +386,13 @@
-
- - -
@@ -455,6 +441,23 @@ + + +
+
+
+ {{ editingSetValue || 'Satz z.B. 11:9' }} +
+
+ + + + + + +
+
+
@@ -713,6 +716,8 @@ export default { results: [], // Fehlermeldungen für Satzeingaben errors: [], + // Aktive Zelle der schwebenden Satz-Tastatur: { matchIndex, setIndex } oder null + editingSetCell: null, // Abschluss-Felder protestText: '', finalHomePin: '', @@ -788,6 +793,11 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr .trim(); return norm(this.meetingData.league) === norm(this.meetingData.group); }, + editingSetValue() { + if (!this.editingSetCell || !this.results[this.editingSetCell.matchIndex]) return ''; + const sets = this.results[this.editingSetCell.matchIndex].sets || []; + return sets[this.editingSetCell.setIndex] || ''; + }, canOpenNextStages() { // Wenn das Match bereits abgeschlossen ist, dürfen keine Änderungen mehr gemacht werden if (this.isMatchCompleted) { @@ -2144,6 +2154,38 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr } this.results[matchIndex].sets[setIndex] = current + char; }, + + isSetKeyboardOpen(matchIndex, setIndex) { + return this.editingSetCell && this.editingSetCell.matchIndex === matchIndex && this.editingSetCell.setIndex === setIndex; + }, + openSetKeyboard(matchIndex, setIndex) { + if (this.isSetInputDisabled(matchIndex, setIndex)) return; + this.editingSetCell = { matchIndex, setIndex }; + }, + closeSetKeyboard() { + this.editingSetCell = null; + }, + setKeyboardKey(char) { + if (!this.editingSetCell || !this.results[this.editingSetCell.matchIndex]) return; + const { matchIndex, setIndex } = this.editingSetCell; + const sets = this.results[matchIndex].sets || []; + const current = sets[setIndex] || ''; + if (current.length >= 6) return; + this.results[matchIndex].sets[setIndex] = current + char; + }, + setKeyboardBackspace() { + if (!this.editingSetCell || !this.results[this.editingSetCell.matchIndex]) return; + const { matchIndex, setIndex } = this.editingSetCell; + const sets = this.results[matchIndex].sets || []; + const current = sets[setIndex] || ''; + this.results[matchIndex].sets[setIndex] = current.slice(0, -1); + }, + setKeyboardOk() { + if (!this.editingSetCell) return; + const { matchIndex, setIndex } = this.editingSetCell; + this.processScoreInput(matchIndex, setIndex); + this.closeSetKeyboard(); + }, reopenMatch(idx) { const m = this.results[idx]; m.completed = false; @@ -3762,6 +3804,78 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr background-color: #f0f0f0; } +/* Schwebende Satz-Tastatur (ersetzt System-Tastatur) */ +.set-keyboard-overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.4); + display: flex; + align-items: flex-end; + justify-content: center; + z-index: 10000; + padding: 0; +} +.set-keyboard { + background: #f0f0f0; + border-radius: 12px 12px 0 0; + padding: 12px; + padding-bottom: max(12px, env(safe-area-inset-bottom)); + box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.2); + width: 100%; + max-width: 360px; +} +.set-keyboard-value { + text-align: center; + font-size: 1.25rem; + font-family: monospace; + padding: 10px 12px; + margin-bottom: 10px; + background: #fff; + border: 1px solid #ccc; + border-radius: 8px; + min-height: 44px; + line-height: 1.4; +} +.set-keyboard-value.placeholder { + color: #999; +} +.set-keyboard-keys { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 8px; +} +.set-key { + min-height: 48px; + font-size: 1.25rem; + border: 1px solid #bbb; + border-radius: 8px; + background: #fff; + cursor: pointer; + font-family: inherit; + -webkit-tap-highlight-color: transparent; + touch-action: manipulation; +} +.set-key:active { + background: #e0e0e0; +} +.set-key-backspace { + font-size: 1.1rem; +} +.set-key-ok { + grid-column: span 2; + background: var(--primary-color, #1976d2); + color: #fff; + border-color: var(--primary-hover, #1565c0); + font-weight: 600; +} +.set-key-ok:active { + opacity: 0.9; +} +.set-input.keyboard-open { + border-color: var(--primary-color); + box-shadow: 0 0 0 2px rgba(var(--primary-rgb, 25, 118, 210), 0.3); +} + /* Mobile-spezifische Optimierungen */ @media (max-width: 768px) { .set-input { @@ -3769,14 +3883,9 @@ Wir wünschen den Spielen einen schönen, spannenden und fairen Verlauf und begr padding: 8px; font-size: 16px; /* Verhindert Zoom auf iOS */ -webkit-appearance: none; + appearance: none; border-radius: 6px; } - - .set-extra-buttons { - display: flex; - flex-direction: column; - gap: 2px; - } } .state-cell { text-align: center; } .state-content { display: flex; flex-direction: row; align-items: center; gap: 8px; }