Verbessere die Benutzeroberfläche der CMS-Seiten durch Anpassungen an der Navigation und dem myTischtennis-Formular. Optimiere die Anzeige der Vereinsränge in der QTTR-Tabelle.
This commit is contained in:
@@ -292,69 +292,69 @@
|
||||
<template v-if="currentSubmenu === 'intern'">
|
||||
<div class="flex min-w-0 flex-1 items-center gap-1 overflow-x-auto whitespace-nowrap">
|
||||
<NuxtLink
|
||||
to="/mitgliederbereich"
|
||||
class="px-2.5 py-1 text-xs font-semibold text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="bg-primary-600"
|
||||
>
|
||||
Übersicht
|
||||
</NuxtLink>
|
||||
<div class="h-3 w-px bg-primary-700" />
|
||||
<NuxtLink
|
||||
to="/mitgliederbereich/mitglieder"
|
||||
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="text-white bg-primary-600"
|
||||
>
|
||||
Mitgliederliste
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
to="/mitgliederbereich/qttr"
|
||||
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="text-white bg-primary-600"
|
||||
>
|
||||
TTR / QTTR
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
to="/mitgliederbereich/news"
|
||||
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="text-white bg-primary-600"
|
||||
>
|
||||
News
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
to="/mitgliederbereich/profil"
|
||||
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="text-white bg-primary-600"
|
||||
>
|
||||
Mein Profil
|
||||
</NuxtLink>
|
||||
<div class="h-3 w-px bg-primary-700" />
|
||||
<NuxtLink
|
||||
to="/mitgliederbereich/api"
|
||||
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="text-white bg-primary-600"
|
||||
>
|
||||
API-Dokumentation
|
||||
</NuxtLink>
|
||||
<template v-if="canAccessNewsletter">
|
||||
to="/mitgliederbereich"
|
||||
class="px-2.5 py-1 text-xs font-semibold text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="bg-primary-600"
|
||||
>
|
||||
Übersicht
|
||||
</NuxtLink>
|
||||
<div class="h-3 w-px bg-primary-700" />
|
||||
<NuxtLink
|
||||
to="/cms/newsletter"
|
||||
to="/mitgliederbereich/mitglieder"
|
||||
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="text-white bg-primary-600"
|
||||
>
|
||||
Newsletter
|
||||
Mitgliederliste
|
||||
</NuxtLink>
|
||||
</template>
|
||||
<template v-if="canAccessContactRequests">
|
||||
<div class="h-3 w-px bg-primary-700" />
|
||||
<NuxtLink
|
||||
to="/cms/kontaktanfragen"
|
||||
to="/mitgliederbereich/qttr"
|
||||
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="text-white bg-primary-600"
|
||||
>
|
||||
Kontaktanfragen
|
||||
TTR / QTTR
|
||||
</NuxtLink>
|
||||
</template>
|
||||
<NuxtLink
|
||||
to="/mitgliederbereich/news"
|
||||
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="text-white bg-primary-600"
|
||||
>
|
||||
News
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
to="/mitgliederbereich/profil"
|
||||
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="text-white bg-primary-600"
|
||||
>
|
||||
Mein Profil
|
||||
</NuxtLink>
|
||||
<div class="h-3 w-px bg-primary-700" />
|
||||
<NuxtLink
|
||||
to="/mitgliederbereich/api"
|
||||
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="text-white bg-primary-600"
|
||||
>
|
||||
API-Dokumentation
|
||||
</NuxtLink>
|
||||
<template v-if="canAccessNewsletter">
|
||||
<div class="h-3 w-px bg-primary-700" />
|
||||
<NuxtLink
|
||||
to="/cms/newsletter"
|
||||
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="text-white bg-primary-600"
|
||||
>
|
||||
Newsletter
|
||||
</NuxtLink>
|
||||
</template>
|
||||
<template v-if="canAccessContactRequests">
|
||||
<div class="h-3 w-px bg-primary-700" />
|
||||
<NuxtLink
|
||||
to="/cms/kontaktanfragen"
|
||||
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
||||
active-class="text-white bg-primary-600"
|
||||
>
|
||||
Kontaktanfragen
|
||||
</NuxtLink>
|
||||
</template>
|
||||
</div>
|
||||
<template v-if="isAdmin">
|
||||
<div class="h-3 w-px shrink-0 bg-primary-700" />
|
||||
|
||||
@@ -208,11 +208,18 @@
|
||||
>
|
||||
<div class="flex items-center mb-4">
|
||||
<div class="w-12 h-12 bg-teal-100 rounded-lg flex items-center justify-center group-hover:bg-teal-600 transition-colors">
|
||||
<RefreshCw :size="24" class="text-teal-600 group-hover:text-white" />
|
||||
<RefreshCw
|
||||
:size="24"
|
||||
class="text-teal-600 group-hover:text-white"
|
||||
/>
|
||||
</div>
|
||||
<h2 class="ml-4 text-xl font-semibold text-gray-900">myTischtennis</h2>
|
||||
<h2 class="ml-4 text-xl font-semibold text-gray-900">
|
||||
myTischtennis
|
||||
</h2>
|
||||
</div>
|
||||
<p class="text-gray-600">Vereinszugang und TTR-Synchronisierung</p>
|
||||
<p class="text-gray-600">
|
||||
Vereinszugang und TTR-Synchronisierung
|
||||
</p>
|
||||
</NuxtLink>
|
||||
|
||||
<!-- Benutzerverwaltung (Admin ODER Vorstand) -->
|
||||
|
||||
@@ -1,33 +1,94 @@
|
||||
<template>
|
||||
<div class="min-h-screen bg-gray-50 py-10">
|
||||
<div class="max-w-2xl mx-auto px-4">
|
||||
<h1 class="text-3xl font-display font-bold text-gray-900">myTischtennis-Verbindung</h1>
|
||||
<p class="mt-2 text-gray-600">Vereinszugang für den geschützten Import aktueller TTR- und QTTR-Werte.</p>
|
||||
<form class="mt-8 bg-white rounded-xl shadow-lg p-6 space-y-5" @submit.prevent="save">
|
||||
<h1 class="text-3xl font-display font-bold text-gray-900">
|
||||
myTischtennis-Verbindung
|
||||
</h1>
|
||||
<p class="mt-2 text-gray-600">
|
||||
Vereinszugang für den geschützten Import aktueller TTR- und QTTR-Werte.
|
||||
</p>
|
||||
<form
|
||||
class="mt-8 bg-white rounded-xl shadow-lg p-6 space-y-5"
|
||||
@submit.prevent="save"
|
||||
>
|
||||
<div class="rounded-lg bg-amber-50 border border-amber-200 p-4 text-sm text-amber-900">
|
||||
Das Passwort wird verschlüsselt auf dem Server gespeichert und nie wieder angezeigt. Zugriff haben ausschließlich Admin und Vorstand.
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">myTischtennis-E-Mail</label>
|
||||
<input v-model.trim="form.email" type="email" required autocomplete="username" class="w-full rounded-lg border border-gray-300 px-3 py-2">
|
||||
<input
|
||||
v-model.trim="form.email"
|
||||
type="email"
|
||||
required
|
||||
autocomplete="username"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2"
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Passwort</label>
|
||||
<input v-model="form.password" type="password" required autocomplete="current-password" class="w-full rounded-lg border border-gray-300 px-3 py-2">
|
||||
<input
|
||||
v-model="form.password"
|
||||
type="password"
|
||||
required
|
||||
autocomplete="current-password"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2"
|
||||
>
|
||||
</div>
|
||||
<div class="grid sm:grid-cols-2 gap-4">
|
||||
<label class="block text-sm font-medium text-gray-700">Verband<input v-model.trim="form.association" required class="mt-1 w-full rounded-lg border border-gray-300 px-3 py-2"></label>
|
||||
<label class="block text-sm font-medium text-gray-700">Vereinsnummer<input v-model.trim="form.clubId" required class="mt-1 w-full rounded-lg border border-gray-300 px-3 py-2"></label>
|
||||
<label class="block text-sm font-medium text-gray-700">Verband<input
|
||||
v-model.trim="form.association"
|
||||
required
|
||||
class="mt-1 w-full rounded-lg border border-gray-300 px-3 py-2"
|
||||
></label>
|
||||
<label class="block text-sm font-medium text-gray-700">Vereinsnummer<input
|
||||
v-model.trim="form.clubId"
|
||||
required
|
||||
class="mt-1 w-full rounded-lg border border-gray-300 px-3 py-2"
|
||||
></label>
|
||||
</div>
|
||||
<p v-if="status.configured" class="text-sm text-gray-600">Hinterlegt: {{ status.email }} · letzter erfolgreicher Abruf: {{ formattedLastImport }}</p>
|
||||
<p v-if="status.lastImportError" class="rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-800">
|
||||
<p
|
||||
v-if="status.configured"
|
||||
class="text-sm text-gray-600"
|
||||
>
|
||||
Hinterlegt: {{ status.email }} · letzter erfolgreicher Abruf: {{ formattedLastImport }}
|
||||
</p>
|
||||
<p
|
||||
v-if="status.lastImportError"
|
||||
class="rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-800"
|
||||
>
|
||||
Letzter Abruf fehlgeschlagen: {{ status.lastImportError }}
|
||||
</p>
|
||||
<p v-if="message" class="text-sm" :class="error ? 'text-red-700' : 'text-green-700'">{{ message }}</p>
|
||||
<p
|
||||
v-if="message"
|
||||
class="text-sm"
|
||||
:class="error ? 'text-red-700' : 'text-green-700'"
|
||||
>
|
||||
{{ message }}
|
||||
</p>
|
||||
<div class="flex gap-3 flex-wrap">
|
||||
<button :disabled="busy" class="rounded-lg bg-primary-600 px-4 py-2 font-semibold text-white disabled:opacity-60">Zugang speichern</button>
|
||||
<button type="button" :disabled="busy || !status.configured" class="rounded-lg border border-primary-600 px-4 py-2 font-semibold text-primary-700 disabled:opacity-60" @click="runImport">Jetzt abrufen</button>
|
||||
<button v-if="authStore.hasRole('admin')" type="button" :disabled="busy" class="rounded-lg border border-teal-600 px-4 py-2 font-semibold text-teal-700 disabled:opacity-60" @click="sendTestPush">Push-Test an mich senden</button>
|
||||
<button
|
||||
:disabled="busy"
|
||||
class="rounded-lg bg-primary-600 px-4 py-2 font-semibold text-white disabled:opacity-60"
|
||||
>
|
||||
Zugang speichern
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
:disabled="busy || !status.configured"
|
||||
class="rounded-lg border border-primary-600 px-4 py-2 font-semibold text-primary-700 disabled:opacity-60"
|
||||
@click="runImport"
|
||||
>
|
||||
Jetzt abrufen
|
||||
</button>
|
||||
<button
|
||||
v-if="authStore.hasRole('admin')"
|
||||
type="button"
|
||||
:disabled="busy"
|
||||
class="rounded-lg border border-teal-600 px-4 py-2 font-semibold text-teal-700 disabled:opacity-60"
|
||||
@click="sendTestPush"
|
||||
>
|
||||
Push-Test an mich senden
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500">
|
||||
Vereinsrang<br>{{ sortBy === 'qttr' ? '(QTTR / TTR)' : '(TTR / QTTR)' }}
|
||||
Vereinsrang<br>(QTTR / TTR)
|
||||
</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500">
|
||||
Spieler
|
||||
@@ -190,17 +190,11 @@ function isOwnRow(playerName) {
|
||||
}
|
||||
|
||||
function formatClubRank(row) {
|
||||
const activeRank = sortBy.value === 'qttr' ? row.clubQttrRank : row.clubTtrRank
|
||||
const otherRank = sortBy.value === 'qttr' ? row.clubTtrRank : row.clubQttrRank
|
||||
return `${activeRank ?? '–'} (${otherRank ?? '–'})`
|
||||
return `${row.clubQttrRank ?? '–'} (${row.clubTtrRank ?? '–'})`
|
||||
}
|
||||
|
||||
function clubRankTitle(row) {
|
||||
const activeLabel = sortBy.value === 'qttr' ? 'QTTR' : 'TTR'
|
||||
const otherLabel = sortBy.value === 'qttr' ? 'TTR' : 'QTTR'
|
||||
const activeRank = sortBy.value === 'qttr' ? row.clubQttrRank : row.clubTtrRank
|
||||
const otherRank = sortBy.value === 'qttr' ? row.clubTtrRank : row.clubQttrRank
|
||||
return `${activeLabel}-Platzierung im Verein: ${activeRank ?? 'nicht verfügbar'}; ${otherLabel}-Platzierung im Verein: ${otherRank ?? 'nicht verfügbar'}`
|
||||
return `QTTR-Platzierung im Verein: ${row.clubQttrRank ?? 'nicht verfügbar'}; TTR-Platzierung im Verein: ${row.clubTtrRank ?? 'nicht verfügbar'}`
|
||||
}
|
||||
|
||||
function getPlayerNameClass(row) {
|
||||
|
||||
Reference in New Issue
Block a user