diff --git a/components/MannschaftenUebersicht.vue b/components/MannschaftenUebersicht.vue index 45f3ea9..9b9f055 100644 --- a/components/MannschaftenUebersicht.vue +++ b/components/MannschaftenUebersicht.vue @@ -107,15 +107,25 @@ 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 response = await fetch('/data/mannschaften.csv') - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`) - } - - const csv = await response.text() + const csv = await fetchCsvText('/data/mannschaften.csv') // Vereinfachter CSV-Parser const lines = csv.split('\n').filter(line => line.trim() !== '') diff --git a/components/Navigation.vue b/components/Navigation.vue index 6f9d7c6..cbbf493 100644 --- a/components/Navigation.vue +++ b/components/Navigation.vue @@ -923,10 +923,22 @@ const toggleMobileSubmenu = (menu) => { const loadMannschaften = async () => { try { - const response = await fetch('/data/mannschaften.csv') - if (!response.ok) return + const attempt = async () => { + const url = `/data/mannschaften.csv?_t=${Date.now()}` + const response = await fetch(url, { cache: 'no-store' }) + if (!response.ok) return null + return await response.text() + } - const csv = await response.text() + let csv = null + try { + csv = await attempt() + } catch (_e) { + // 1 Retry: hilft bei kurzen Restarts/Proxy-Resets (Firefox: NS_ERROR_NET_PARTIAL_TRANSFER) + await new Promise(resolve => setTimeout(resolve, 150)) + csv = await attempt() + } + if (!csv) return const lines = csv.split('\n').filter(line => line.trim() !== '') if (lines.length < 2) return diff --git a/pages/mannschaften/[slug].vue b/pages/mannschaften/[slug].vue index eb5d6fe..7b2c113 100644 --- a/pages/mannschaften/[slug].vue +++ b/pages/mannschaften/[slug].vue @@ -140,12 +140,26 @@ 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 response = await fetch('/data/mannschaften.csv') - if (!response.ok) return - - const csv = await response.text() + const csv = await fetchCsvText('/data/mannschaften.csv') + if (!csv) return const lines = csv.split('\n').filter(line => line.trim() !== '') if (lines.length < 2) return diff --git a/pages/mannschaften/spielplaene.vue b/pages/mannschaften/spielplaene.vue index ef5d1e4..2a9c8b7 100644 --- a/pages/mannschaften/spielplaene.vue +++ b/pages/mannschaften/spielplaene.vue @@ -299,6 +299,23 @@ const selectedWettbewerb = ref('punktrunde') const filteredData = ref([]) 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) { + // 1 Retry: hilft bei kurzen Restarts/Proxy-Resets (Firefox: NS_ERROR_NET_PARTIAL_TRANSFER) + await new Promise(resolve => setTimeout(resolve, 150)) + return await attempt() + } +} + const loadData = async () => { isLoading.value = true error.value = null @@ -307,7 +324,7 @@ const loadData = async () => { // Lade Spielplandaten und Mannschaften parallel const [spielplanResponse, mannschaftenResponse] = await Promise.all([ fetch('/api/spielplan'), - fetch('/data/mannschaften.csv') + fetchCsvText('/data/mannschaften.csv') ]) // Spielplandaten verarbeiten @@ -352,8 +369,8 @@ const loadData = async () => { } // Mannschaften aus CMS laden (manuell eingegebene Mannschaften) - if (mannschaftenResponse.ok) { - const csvText = await mannschaftenResponse.text() + if (mannschaftenResponse) { + const csvText = mannschaftenResponse const lines = csvText.split('\n').filter(line => line.trim() !== '') if (lines.length > 1) {