Files
harheimertc/components/MannschaftenUebersicht.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

211 lines
6.4 KiB
Vue

<template>
<div>
<div
v-if="mannschaften.length > 0"
class="space-y-8"
>
<div
v-for="(mannschaft, index) in mannschaften"
:key="index"
class="bg-white rounded-xl shadow-lg border border-gray-100 overflow-hidden"
>
<!-- Header -->
<div class="bg-gradient-to-r from-primary-600 to-primary-700 p-6">
<h2 class="text-2xl font-display font-bold text-white mb-2">
{{ mannschaft.mannschaft }}
</h2>
<p class="text-primary-100 text-lg">
{{ mannschaft.liga }}
</p>
</div>
<!-- Content -->
<div class="p-6">
<!-- Liga-Info -->
<div class="grid md:grid-cols-2 gap-6 mb-6">
<div class="space-y-3">
<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-3">
<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>
<!-- Mannschaftsaufstellung -->
<div class="border-t border-gray-200 pt-6">
<h3 class="text-xl font-semibold text-gray-900 mb-4">
Mannschaftsaufstellung Saison 2025/26 (Hinrunde)
</h3>
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-4">
<div
v-for="(spieler, spielerIndex) in getSpielerListe(mannschaft)"
:key="spielerIndex"
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>
<!-- Letzte Aktualisierung -->
<div class="border-t border-gray-200 pt-4 mt-6">
<p class="text-sm text-gray-500 text-center">
Zuletzt aktualisiert am: {{ formatDate(mannschaft.letzte_aktualisierung) }}
</p>
</div>
</div>
</div>
</div>
<div
v-else
class="text-center py-12 bg-gray-50 rounded-xl"
>
<Users
:size="48"
class="text-gray-400 mx-auto mb-4"
/>
<p class="text-gray-600">
Keine Mannschaftsdaten geladen
</p>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { Users } from 'lucide-vue-next'
const mannschaften = ref([])
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) throw new Error(`HTTP error! status: ${res.status}`)
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')
// Vereinfachter CSV-Parser
const lines = csv.split('\n').filter(line => line.trim() !== '')
if (lines.length < 2) {
return
}
mannschaften.value = lines.slice(1).map((line, _index) => {
// 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
}
const mannschaft = {
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] ? values[9].trim() : ''
}
return mannschaft
}).filter(mannschaft => mannschaft !== null)
} 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>