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'">
|
<template v-if="currentSubmenu === 'intern'">
|
||||||
<div class="flex min-w-0 flex-1 items-center gap-1 overflow-x-auto whitespace-nowrap">
|
<div class="flex min-w-0 flex-1 items-center gap-1 overflow-x-auto whitespace-nowrap">
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
to="/mitgliederbereich"
|
to="/mitgliederbereich"
|
||||||
class="px-2.5 py-1 text-xs font-semibold text-white hover:bg-primary-700/50 rounded transition-all"
|
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"
|
active-class="bg-primary-600"
|
||||||
>
|
>
|
||||||
Übersicht
|
Übersicht
|
||||||
</NuxtLink>
|
</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">
|
|
||||||
<div class="h-3 w-px bg-primary-700" />
|
<div class="h-3 w-px bg-primary-700" />
|
||||||
<NuxtLink
|
<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"
|
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"
|
active-class="text-white bg-primary-600"
|
||||||
>
|
>
|
||||||
Newsletter
|
Mitgliederliste
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</template>
|
|
||||||
<template v-if="canAccessContactRequests">
|
|
||||||
<div class="h-3 w-px bg-primary-700" />
|
|
||||||
<NuxtLink
|
<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"
|
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"
|
active-class="text-white bg-primary-600"
|
||||||
>
|
>
|
||||||
Kontaktanfragen
|
TTR / QTTR
|
||||||
</NuxtLink>
|
</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>
|
</div>
|
||||||
<template v-if="isAdmin">
|
<template v-if="isAdmin">
|
||||||
<div class="h-3 w-px shrink-0 bg-primary-700" />
|
<div class="h-3 w-px shrink-0 bg-primary-700" />
|
||||||
|
|||||||
@@ -208,11 +208,18 @@
|
|||||||
>
|
>
|
||||||
<div class="flex items-center mb-4">
|
<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">
|
<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>
|
</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>
|
</div>
|
||||||
<p class="text-gray-600">Vereinszugang und TTR-Synchronisierung</p>
|
<p class="text-gray-600">
|
||||||
|
Vereinszugang und TTR-Synchronisierung
|
||||||
|
</p>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
<!-- Benutzerverwaltung (Admin ODER Vorstand) -->
|
<!-- Benutzerverwaltung (Admin ODER Vorstand) -->
|
||||||
|
|||||||
@@ -1,33 +1,94 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-gray-50 py-10">
|
<div class="min-h-screen bg-gray-50 py-10">
|
||||||
<div class="max-w-2xl mx-auto px-4">
|
<div class="max-w-2xl mx-auto px-4">
|
||||||
<h1 class="text-3xl font-display font-bold text-gray-900">myTischtennis-Verbindung</h1>
|
<h1 class="text-3xl font-display font-bold text-gray-900">
|
||||||
<p class="mt-2 text-gray-600">Vereinszugang für den geschützten Import aktueller TTR- und QTTR-Werte.</p>
|
myTischtennis-Verbindung
|
||||||
<form class="mt-8 bg-white rounded-xl shadow-lg p-6 space-y-5" @submit.prevent="save">
|
</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">
|
<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.
|
Das Passwort wird verschlüsselt auf dem Server gespeichert und nie wieder angezeigt. Zugriff haben ausschließlich Admin und Vorstand.
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-sm font-medium text-gray-700 mb-1">myTischtennis-E-Mail</label>
|
<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>
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-sm font-medium text-gray-700 mb-1">Passwort</label>
|
<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>
|
||||||
<div class="grid sm:grid-cols-2 gap-4">
|
<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">Verband<input
|
||||||
<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>
|
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>
|
</div>
|
||||||
<p v-if="status.configured" class="text-sm text-gray-600">Hinterlegt: {{ status.email }} · letzter erfolgreicher Abruf: {{ formattedLastImport }}</p>
|
<p
|
||||||
<p v-if="status.lastImportError" class="rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-800">
|
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 }}
|
Letzter Abruf fehlgeschlagen: {{ status.lastImportError }}
|
||||||
</p>
|
</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">
|
<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
|
||||||
<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>
|
:disabled="busy"
|
||||||
<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>
|
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>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -72,7 +72,7 @@
|
|||||||
<thead class="bg-gray-50">
|
<thead class="bg-gray-50">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500">
|
<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>
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500">
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500">
|
||||||
Spieler
|
Spieler
|
||||||
@@ -190,17 +190,11 @@ function isOwnRow(playerName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatClubRank(row) {
|
function formatClubRank(row) {
|
||||||
const activeRank = sortBy.value === 'qttr' ? row.clubQttrRank : row.clubTtrRank
|
return `${row.clubQttrRank ?? '–'} (${row.clubTtrRank ?? '–'})`
|
||||||
const otherRank = sortBy.value === 'qttr' ? row.clubTtrRank : row.clubQttrRank
|
|
||||||
return `${activeRank ?? '–'} (${otherRank ?? '–'})`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function clubRankTitle(row) {
|
function clubRankTitle(row) {
|
||||||
const activeLabel = sortBy.value === 'qttr' ? 'QTTR' : 'TTR'
|
return `QTTR-Platzierung im Verein: ${row.clubQttrRank ?? 'nicht verfügbar'}; TTR-Platzierung im Verein: ${row.clubTtrRank ?? 'nicht verfügbar'}`
|
||||||
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'}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPlayerNameClass(row) {
|
function getPlayerNameClass(row) {
|
||||||
|
|||||||
Reference in New Issue
Block a user