← Zurück zur Übersicht
@@ -237,17 +359,55 @@ import { ref, computed, onMounted } from 'vue'
import { Users } from 'lucide-vue-next'
const route = useRoute()
+
+const getCurrentSeasonSlug = () => {
+ const now = new Date()
+ const year = now.getFullYear()
+ const startYear = now.getMonth() >= 6 ? year : year - 1
+ const endYear = startYear + 1
+ return `${String(startYear).slice(-2)}--${String(endYear).slice(-2)}`
+}
+
+const selectedSeason = computed(() => {
+ const value = String(route.query.season || '').trim()
+ return /^\d{2}--\d{2}$/.test(value) ? value : getCurrentSeasonSlug()
+})
const mannschaft = ref(null)
const mannschaftSpielplan = ref([])
const spielplanSeason = ref('')
const isSpielplanLoading = ref(false)
const spielplanError = ref('')
+const activePanelTab = ref('matches')
+const isTableLoading = ref(false)
+const tableError = ref('')
+const teamTableRows = ref([])
+const spielplanDataUpdatedAt = ref('')
+const tableDataUpdatedAt = ref('')
+
+const hasTableLink = computed(() => {
+ const link = String(mannschaft.value?.weitere_informationen_link || '').trim()
+ return link.includes('/tabelle/')
+})
const spielplanSeasonLabel = computed(() => {
const match = String(spielplanSeason.value || '').match(/^(\d{2})--(\d{2})$/)
return match ? `20${match[1]}/${match[2]}` : ''
})
+const mannschaftSeasonLabel = computed(() => {
+ if (spielplanSeasonLabel.value) return spielplanSeasonLabel.value
+
+ const now = new Date()
+ const year = now.getFullYear()
+ const start = now.getMonth() >= 6 ? year : year - 1
+ return `${start}/${String(start + 1).slice(-2)}`
+})
+
+const dataUpdatedLabel = computed(() => {
+ const dateValue = tableDataUpdatedAt.value || spielplanDataUpdatedAt.value || mannschaft.value?.letzte_aktualisierung || ''
+ return formatDate(dateValue)
+})
+
async function fetchCsvText(url) {
const attempt = async () => {
const withBuster = `${url}${url.includes('?') ? '&' : '?'}_t=${Date.now()}`
@@ -266,7 +426,9 @@ async function fetchCsvText(url) {
const loadMannschaften = async () => {
try {
- const csv = await fetchCsvText('/api/mannschaften')
+ const params = new URLSearchParams()
+ if (selectedSeason.value) params.set('season', selectedSeason.value)
+ const csv = await fetchCsvText(`/api/mannschaften${params.toString() ? `?${params.toString()}` : ''}`)
if (!csv) return
const lines = csv.split('\n').filter(line => line.trim() !== '')
@@ -317,13 +479,55 @@ const loadMannschaften = async () => {
useHead({
title: `${mannschaft.value.mannschaft} - Harheimer TC`,
})
- await loadSpielplan()
+ await Promise.all([loadSpielplan(), loadTeamTable()])
}
} catch (error) {
console.error('Fehler beim Laden der Mannschaften:', error)
}
}
+const loadTeamTable = async () => {
+ if (!mannschaft.value) return
+
+ if (!hasTableLink.value) {
+ teamTableRows.value = []
+ tableError.value = ''
+ return
+ }
+
+ isTableLoading.value = true
+ tableError.value = ''
+
+ try {
+ const params = new URLSearchParams({ team: mannschaft.value.mannschaft })
+ if (selectedSeason.value) {
+ params.set('season', selectedSeason.value)
+ } else if (spielplanSeason.value) {
+ params.set('season', spielplanSeason.value)
+ }
+
+ const response = await fetch(`/api/spielplan/table?${params.toString()}`)
+ const result = await response.json()
+
+ if (!result.success) {
+ tableError.value = result.message || 'Tabelle konnte nicht geladen werden.'
+ teamTableRows.value = []
+ return
+ }
+
+ teamTableRows.value = Array.isArray(result?.table?.table?.leagueTable)
+ ? result.table.table.leagueTable
+ : []
+ tableDataUpdatedAt.value = result?.importedAt || ''
+ } catch (error) {
+ console.error('Fehler beim Laden der Tabelle:', error)
+ tableError.value = 'Tabelle konnte nicht geladen werden.'
+ teamTableRows.value = []
+ } finally {
+ isTableLoading.value = false
+ }
+}
+
const getTeamVariants = (cmsMannschaft) => {
const mannschaftMapping = {
'Erwachsene 1': ['harheimer tc'],
@@ -407,7 +611,9 @@ const loadSpielplan = async () => {
spielplanError.value = ''
try {
- const response = await fetch('/api/spielplan')
+ const params = new URLSearchParams()
+ if (selectedSeason.value) params.set('season', selectedSeason.value)
+ const response = await fetch(`/api/spielplan${params.toString() ? `?${params.toString()}` : ''}`)
const result = await response.json()
if (!result.success) {
@@ -417,6 +623,7 @@ const loadSpielplan = async () => {
}
spielplanSeason.value = result.season || ''
+ spielplanDataUpdatedAt.value = result?.source?.updatedAt || result?.source?.importedAt || ''
mannschaftSpielplan.value = result.data
.filter(row => isSpielForMannschaft(row, mannschaft.value.mannschaft))
.sort((a, b) => parseTerminTimestamp(a) - parseTerminTimestamp(b))
@@ -495,6 +702,33 @@ const getRowClass = (row) => {
return 'bg-white'
}
+const formatSaetze = (row) => {
+ const won = row?.sets_won
+ const lost = row?.sets_lost
+ if (won == null && lost == null) return row?.sets_relation || '-'
+ return `${won ?? 0}:${lost ?? 0}`
+}
+
+const formatBaelle = (row) => {
+ const won = row?.games_won
+ const lost = row?.games_lost
+ if (won == null && lost == null) return row?.games_relation || '-'
+ return `${won ?? 0}:${lost ?? 0}`
+}
+
+const formatPunkte = (row) => {
+ if (row?.points_won == null && row?.points_lost == null) return '-'
+ return `${row?.points_won ?? 0}:${row?.points_lost ?? 0}`
+}
+
+const isCurrentTeamRow = (row) => {
+ const teamName = String(row?.team_name || '').toLowerCase()
+ if (!teamName.includes('harheimer tc')) return false
+
+ const variants = getTeamVariants(mannschaft.value?.mannschaft || '')
+ return variants.some((variant) => isExactHarheimTeam(teamName, variant))
+}
+
onMounted(() => {
loadMannschaften()
})
diff --git a/pages/mannschaften/index.vue b/pages/mannschaften/index.vue
index bf20d6c..676323c 100644
--- a/pages/mannschaften/index.vue
+++ b/pages/mannschaften/index.vue
@@ -7,10 +7,10 @@
- Unsere aktiven Mannschaften in der Saison 2025/26
+ Unsere aktiven Mannschaften in der Saison {{ selectedSeasonLabel }}
-
+
@@ -21,7 +21,7 @@
Alle aktuellen Spielpläne und Ergebnisse unserer Mannschaften finden Sie hier.
Zu den Spielplänen
@@ -33,8 +33,29 @@