Füge myTischtennis-Verbindung hinzu: Ergänze Navigationslinks, verbessere Fehlerbehandlung und aktualisiere Import-Logik
All checks were successful
Code Analysis and Production Deploy / analyze (push) Successful in 4m36s
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Successful in 2m33s

This commit is contained in:
Torsten Schulz (local)
2026-09-04 14:24:11 +02:00
parent 497d804244
commit 63b5786e43
3 changed files with 22 additions and 3 deletions

View File

@@ -443,6 +443,13 @@
>
Einstellungen
</NuxtLink>
<NuxtLink
to="/cms/mytischtennis"
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
@click="showCmsDropdown = false"
>
myTischtennis
</NuxtLink>
<NuxtLink
to="/cms/benutzer"
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
@@ -860,6 +867,13 @@
>
Einstellungen
</NuxtLink>
<NuxtLink
to="/cms/mytischtennis"
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
@click="isMobileMenuOpen = false"
>
myTischtennis
</NuxtLink>
<NuxtLink
v-if="canManageUsers"
to="/cms/benutzer"

View File

@@ -20,6 +20,9 @@
<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">
Letzter Abruf fehlgeschlagen: {{ status.lastImportError }}
</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>
@@ -40,6 +43,6 @@ const busy = ref(false); const message = ref(''); const error = ref(false)
const formattedLastImport = computed(() => status.value.lastSuccessfulImportAt ? new Intl.DateTimeFormat('de-DE', { dateStyle: 'medium', timeStyle: 'short' }).format(new Date(status.value.lastSuccessfulImportAt)) : 'noch nie')
async function load() { status.value = await $fetch('/api/cms/mytischtennis') }
async function save() { busy.value = true; message.value = ''; error.value = false; try { status.value = await $fetch('/api/cms/mytischtennis', { method: 'PUT', body: form }); form.password = ''; message.value = 'Zugang verschlüsselt gespeichert.' } catch { error.value = true; message.value = 'Zugang konnte nicht gespeichert werden.' } finally { busy.value = false } }
async function runImport() { busy.value = true; message.value = ''; error.value = false; try { const result = await $fetch('/api/cms/mytischtennis/import', { method: 'POST' }); message.value = `${result.rowCount} Werte wurden aktualisiert.`; await load() } catch { error.value = true; message.value = 'Abruf fehlgeschlagen. Bitte Zugang und CAPTCHA-Status prüfen.' } finally { busy.value = false } }
async function runImport() { busy.value = true; message.value = ''; error.value = false; try { const result = await $fetch('/api/cms/mytischtennis/import', { method: 'POST' }); message.value = `${result.rowCount} Werte wurden aktualisiert.`; await load() } catch (caught) { error.value = true; message.value = caught?.data?.statusMessage || 'Abruf fehlgeschlagen.'; await load().catch(() => {}) } finally { busy.value = false } }
onMounted(load)
</script>

View File

@@ -13,7 +13,9 @@ export default defineEventHandler(async (event) => {
const result = await importQttrValues({ connection })
return { success: true, rowCount: result.rowCount, importedAt: result.importedAt }
} catch (error) {
await saveMyTischtennisConnection({ ...connection, lastImportError: String(error.message || error).slice(0, 500) })
throw createError({ statusCode: 502, statusMessage: 'TTR-Abruf bei myTischtennis fehlgeschlagen.' })
const detail = String(error.message || error).slice(0, 500)
console.error('[mytischtennis] TTR-Abruf fehlgeschlagen:', detail)
await saveMyTischtennisConnection({ ...connection, lastImportError: detail })
throw createError({ statusCode: 502, statusMessage: `TTR-Abruf fehlgeschlagen: ${detail}` })
}
})