Files
harheimertc/pages/mannschaften/[slug].vue
Torsten Schulz (local) c39e5de29f
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 5s
Update CSV data fetching to use API endpoint in Mannschaften components
This commit modifies the loadMannschaften function across multiple components to fetch CSV data from the new API endpoint '/api/mannschaften' instead of the previous static file path '/data/mannschaften.csv'. This change enhances data retrieval consistency and aligns with the updated data management strategy in the application.
2026-01-19 08:28:43 +01:00

248 lines
8.0 KiB
Vue

<template>
<div class="min-h-full py-16 bg-gray-50">
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<div
v-if="mannschaft"
class="space-y-8"
>
<!-- Header -->
<div class="bg-gradient-to-r from-primary-600 to-primary-700 rounded-xl p-8 text-white">
<h1 class="text-4xl font-display font-bold mb-2">
{{ mannschaft.mannschaft }}
</h1>
<p class="text-primary-100 text-xl">
{{ mannschaft.liga }}
</p>
</div>
<!-- Liga-Info -->
<div class="bg-white rounded-xl shadow-lg p-6">
<h2 class="text-2xl font-semibold text-gray-900 mb-6">
Liga-Informationen
</h2>
<div class="grid md:grid-cols-2 gap-6">
<div class="space-y-4">
<div class="flex items-center space-x-3">
<div class="w-2 h-2 bg-primary-600 rounded-full" />
<span class="text-gray-600">Staffelleiter:</span>
<span class="font-semibold text-gray-900">{{ mannschaft.staffelleiter }}</span>
</div>
<div class="flex items-center space-x-3">
<div class="w-2 h-2 bg-primary-600 rounded-full" />
<span class="text-gray-600">Telefon:</span>
<span class="font-semibold text-gray-900">{{ mannschaft.telefon }}</span>
</div>
</div>
<div class="space-y-4">
<div class="flex items-center space-x-3">
<div class="w-2 h-2 bg-primary-600 rounded-full" />
<span class="text-gray-600">Heimspieltag:</span>
<span class="font-semibold text-gray-900">{{ mannschaft.heimspieltag }}</span>
</div>
<div class="flex items-center space-x-3">
<div class="w-2 h-2 bg-primary-600 rounded-full" />
<span class="text-gray-600">Spielsystem:</span>
<span class="font-semibold text-gray-900">{{ mannschaft.spielsystem }}</span>
</div>
</div>
</div>
</div>
<!-- Mannschaftsaufstellung -->
<div class="bg-white rounded-xl shadow-lg p-6">
<h2 class="text-2xl font-semibold text-gray-900 mb-6">
Mannschaftsaufstellung Saison 2025/26 (Hinrunde)
</h2>
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-4">
<div
v-for="(spieler, index) in getSpielerListe(mannschaft)"
:key="index"
class="bg-gray-50 rounded-lg p-4 text-center"
:class="spieler === mannschaft.mannschaftsfuehrer ? 'ring-2 ring-primary-500 bg-primary-50' : ''"
>
<div class="font-semibold text-gray-900">
{{ spieler }}
</div>
<div
v-if="spieler === mannschaft.mannschaftsfuehrer"
class="text-xs text-primary-600 font-medium mt-1"
>
Mannschaftsführer
</div>
</div>
</div>
</div>
<!-- Links -->
<div class="bg-white rounded-xl shadow-lg p-6">
<h2 class="text-2xl font-semibold text-gray-900 mb-6">
Weitere Informationen
</h2>
<div class="text-center">
<a
v-if="mannschaft.weitere_informationen_link && mannschaft.weitere_informationen_link !== ''"
:href="mannschaft.weitere_informationen_link"
target="_blank"
class="inline-flex items-center px-8 py-4 bg-primary-600 hover:bg-primary-700 text-white font-semibold rounded-lg transition-colors"
>
<BarChart
:size="24"
class="mr-3"
/>
Weitere Informationen
</a>
</div>
</div>
<!-- Letzte Aktualisierung -->
<div class="bg-white rounded-xl shadow-lg p-6">
<p class="text-sm text-gray-500 text-center">
Zuletzt aktualisiert am: {{ formatDate(mannschaft.letzte_aktualisierung) }}
</p>
</div>
<!-- Zurück-Button -->
<div class="text-center">
<NuxtLink
to="/mannschaften"
class="inline-flex items-center px-6 py-3 bg-primary-600 hover:bg-primary-700 text-white font-semibold rounded-lg transition-colors"
>
Zurück zur Übersicht
</NuxtLink>
</div>
</div>
<div
v-else
class="text-center py-16"
>
<h1 class="text-4xl font-display font-bold text-gray-900 mb-4">
Mannschaft nicht gefunden
</h1>
<p class="text-gray-600 mb-8">
Die angeforderte Mannschaft konnte nicht gefunden werden.
</p>
<NuxtLink
to="/mannschaften"
class="inline-flex items-center px-6 py-3 bg-primary-600 hover:bg-primary-700 text-white font-semibold rounded-lg transition-colors"
>
Zur Mannschaftsübersicht
</NuxtLink>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { Users } from 'lucide-vue-next'
const route = useRoute()
const mannschaft = ref(null)
async function fetchCsvText(url) {
const attempt = async () => {
const withBuster = `${url}${url.includes('?') ? '&' : '?'}_t=${Date.now()}`
const res = await fetch(withBuster, { cache: 'no-store' })
if (!res.ok) return null
return await res.text()
}
try {
return await attempt()
} catch (_e) {
await new Promise(resolve => setTimeout(resolve, 150))
return await attempt()
}
}
const loadMannschaften = async () => {
try {
const csv = await fetchCsvText('/api/mannschaften')
if (!csv) return
const lines = csv.split('\n').filter(line => line.trim() !== '')
if (lines.length < 2) return
const mannschaften = lines.slice(1).map(line => {
// Besserer CSV-Parser: Respektiert Anführungszeichen
const values = []
let current = ''
let inQuotes = false
for (let i = 0; i < line.length; i++) {
const char = line[i]
if (char === '"') {
inQuotes = !inQuotes
} else if (char === ',' && !inQuotes) {
values.push(current.trim())
current = ''
} else {
current += char
}
}
values.push(current.trim())
if (values.length < 10) return null
return {
mannschaft: values[0].trim(),
liga: values[1].trim(),
staffelleiter: values[2].trim(),
telefon: values[3].trim(),
heimspieltag: values[4].trim(),
spielsystem: values[5].trim(),
mannschaftsfuehrer: values[6].trim(),
spieler: values[7].trim(),
weitere_informationen_link: values[8].trim(),
letzte_aktualisierung: values[9].trim(),
slug: values[0].trim().toLowerCase().replace(/\s+/g, '-')
}
}).filter(mannschaft => mannschaft !== null)
// Finde die Mannschaft basierend auf dem Slug
const currentSlug = route.params.slug
mannschaft.value = mannschaften.find(m => m.slug === currentSlug) || null
if (mannschaft.value) {
useHead({
title: `${mannschaft.value.mannschaft} - Harheimer TC`,
})
}
} catch (error) {
console.error('Fehler beim Laden der Mannschaften:', error)
}
}
const getSpielerListe = (mannschaft) => {
if (!mannschaft.spieler) return []
return mannschaft.spieler.split(';').map(s => s.trim()).filter(s => s !== '')
}
const formatDate = (dateString) => {
if (!dateString) return ''
// Wenn bereits im Format DD.MM.YYYY, direkt zurückgeben
if (/^\d{2}\.\d{2}\.\d{4}$/.test(dateString)) {
return dateString
}
// Versuche, das Datum zu parsen
const date = new Date(dateString)
if (isNaN(date.getTime())) {
return dateString // Falls ungültig, Original zurückgeben
}
return date.toLocaleDateString('de-DE', {
day: '2-digit',
month: '2-digit',
year: 'numeric'
})
}
onMounted(() => {
loadMannschaften()
})
</script>