Refactor Spieler management UI in Mannschaften component for improved usability
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 44s

This commit updates the Spieler management interface by replacing the text input for moving players with a dropdown select, streamlining the process of transferring players between teams. It also adjusts the layout for better responsiveness and user experience, ensuring that player names are pre-selected based on their current team. These changes enhance the overall functionality and accessibility of the Mannschaften component.
This commit is contained in:
Torsten Schulz (local)
2026-01-18 23:15:37 +01:00
parent 7ada3b62c4
commit fa12bae426

View File

@@ -255,13 +255,13 @@
<div
v-for="(spieler, index) in formData.spielerListe"
:key="spieler.id"
class="p-3 border border-gray-200 rounded-lg bg-white"
class="px-3 py-2 border border-gray-200 rounded-lg bg-white"
>
<div class="flex flex-col sm:flex-row sm:items-center gap-2">
<div class="flex flex-col lg:flex-row lg:items-center gap-2">
<input
v-model="spieler.name"
type="text"
class="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500"
class="flex-1 min-w-[14rem] px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500"
placeholder="Spielername"
:disabled="isSaving"
>
@@ -296,42 +296,38 @@
<Trash2 :size="18" />
</button>
</div>
</div>
<!-- Verschieben -->
<div class="mt-2 flex flex-col sm:flex-row sm:items-center gap-2">
<input
v-model="moveTargetBySpielerId[spieler.id]"
list="mannschaften-targets"
type="text"
class="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500"
placeholder="In andere Mannschaft verschieben…"
:disabled="isSaving || !isEditing || otherMannschaften.length === 0"
>
<button
type="button"
class="inline-flex items-center justify-center px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
:disabled="isSaving || !isEditing || otherMannschaften.length === 0 || !canMoveSpieler(spieler.id)"
@click="moveSpielerToMannschaft(spieler.id)"
>
<ArrowRight
:size="18"
class="mr-2"
/>
Verschieben
</button>
<!-- Verschieben (kompakt in gleicher Zeile) -->
<div class="flex items-center gap-2">
<select
v-model="moveTargetBySpielerId[spieler.id]"
class="min-w-[14rem] px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 disabled:opacity-50 disabled:cursor-not-allowed"
:disabled="isSaving || !isEditing || mannschaftenSelectOptions.length <= 1"
title="Mannschaft auswählen"
>
<option
v-for="t in mannschaftenSelectOptions"
:key="t"
:value="t"
>
{{ t }}
</option>
</select>
<button
type="button"
class="inline-flex items-center justify-center px-3 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
:disabled="isSaving || !isEditing || mannschaftenSelectOptions.length <= 1 || !canMoveSpieler(spieler.id)"
@click="moveSpielerToMannschaft(spieler.id)"
title="In ausgewählte Mannschaft verschieben"
>
<ArrowRight :size="18" />
</button>
</div>
</div>
</div>
</div>
<datalist id="mannschaften-targets">
<option
v-for="t in otherMannschaften"
:key="t.idx"
:value="t.name"
/>
</datalist>
<div class="mt-3 flex items-center justify-between">
<button
type="button"
@@ -467,10 +463,12 @@ function serializeSpielerNames(spielerNames) {
.join('; ')
}
const otherMannschaften = computed(() => {
return mannschaften.value
.map((m, idx) => ({ idx, name: (m?.mannschaft || '').trim() }))
.filter(t => t.idx !== editingIndex.value && t.name)
const mannschaftenSelectOptions = computed(() => {
const current = (formData.value.mannschaft || '').trim()
const names = mannschaften.value
.map(m => (m?.mannschaft || '').trim())
.filter(Boolean)
return [...new Set([current, ...names])].filter(Boolean)
})
function resetSpielerDraftState() {
@@ -600,10 +598,17 @@ const openEditModal = (mannschaft, index) => {
showModal.value = true
errorMessage.value = ''
resetSpielerDraftState()
// Pro Spieler: aktuelle Mannschaft vorauswählen
const currentTeam = (formData.value.mannschaft || '').trim()
for (const s of formData.value.spielerListe) {
moveTargetBySpielerId.value[s.id] = currentTeam
}
}
const addSpieler = () => {
formData.value.spielerListe.push(newSpielerItem(''))
const item = newSpielerItem('')
formData.value.spielerListe.push(item)
moveTargetBySpielerId.value[item.id] = (formData.value.mannschaft || '').trim()
}
const removeSpieler = (spielerId) => {
@@ -633,7 +638,8 @@ const moveSpielerDown = (index) => {
const canMoveSpieler = (spielerId) => {
const targetName = (moveTargetBySpielerId.value[spielerId] || '').trim()
return Boolean(targetName)
const currentTeam = (formData.value.mannschaft || '').trim()
return Boolean(targetName) && Boolean(currentTeam) && targetName !== currentTeam
}
const moveSpielerToMannschaft = (spielerId) => {