feat(mannschaften): align public pages with season query logic
Some checks failed
Code Analysis and Production Deploy / deploy-production (push) Has been cancelled
Code Analysis and Production Deploy / deploy-test (push) Has been cancelled
Code Analysis and Production Deploy / analyze (push) Has been cancelled

This commit is contained in:
Torsten Schulz (local)
2026-05-20 18:01:07 +02:00
parent cfd9365d07
commit 11ff823fe2
4 changed files with 97 additions and 11 deletions

View File

@@ -52,7 +52,7 @@
<!-- Mannschaftsaufstellung --> <!-- Mannschaftsaufstellung -->
<div class="border-t border-gray-200 pt-6"> <div class="border-t border-gray-200 pt-6">
<h3 class="text-xl font-semibold text-gray-900 mb-4"> <h3 class="text-xl font-semibold text-gray-900 mb-4">
Mannschaftsaufstellung Saison 2025/26 Mannschaftsaufstellung Saison {{ selectedSeasonLabel }}
</h3> </h3>
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-4"> <div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-4">
<div <div
@@ -102,11 +102,36 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue' import { ref, onMounted, computed } from 'vue'
import { Users } from 'lucide-vue-next' import { Users } from 'lucide-vue-next'
const props = defineProps({
season: {
type: String,
default: ''
}
})
const mannschaften = ref([]) const mannschaften = ref([])
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(props.season || '').trim()
return /^\d{2}--\d{2}$/.test(value) ? value : getCurrentSeasonSlug()
})
const selectedSeasonLabel = computed(() => {
const match = String(selectedSeason.value || '').match(/^(\d{2})--(\d{2})$/)
return match ? `20${match[1]}/${match[2]}` : selectedSeason.value
})
async function fetchCsvText(url) { async function fetchCsvText(url) {
const attempt = async () => { const attempt = async () => {
const withBuster = `${url}${url.includes('?') ? '&' : '?'}_t=${Date.now()}` const withBuster = `${url}${url.includes('?') ? '&' : '?'}_t=${Date.now()}`
@@ -125,7 +150,9 @@ async function fetchCsvText(url) {
const loadMannschaften = async () => { const loadMannschaften = async () => {
try { 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()}` : ''}`)
// Vereinfachter CSV-Parser // Vereinfachter CSV-Parser
const lines = csv.split('\n').filter(line => line.trim() !== '') const lines = csv.split('\n').filter(line => line.trim() !== '')

View File

@@ -325,7 +325,7 @@
<!-- Zurück-Button --> <!-- Zurück-Button -->
<div class="text-center"> <div class="text-center">
<NuxtLink <NuxtLink
to="/mannschaften" :to="{ path: '/mannschaften', query: selectedSeason ? { season: selectedSeason } : {} }"
class="inline-flex items-center px-6 py-3 bg-primary-600 hover:bg-primary-700 text-white font-semibold rounded-lg transition-colors" 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 Zurück zur Übersicht
@@ -359,6 +359,19 @@ import { ref, computed, onMounted } from 'vue'
import { Users } from 'lucide-vue-next' import { Users } from 'lucide-vue-next'
const route = useRoute() 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 mannschaft = ref(null)
const mannschaftSpielplan = ref([]) const mannschaftSpielplan = ref([])
const spielplanSeason = ref('') const spielplanSeason = ref('')
@@ -413,7 +426,9 @@ async function fetchCsvText(url) {
const loadMannschaften = async () => { const loadMannschaften = async () => {
try { 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 if (!csv) return
const lines = csv.split('\n').filter(line => line.trim() !== '') const lines = csv.split('\n').filter(line => line.trim() !== '')
@@ -485,7 +500,9 @@ const loadTeamTable = async () => {
try { try {
const params = new URLSearchParams({ team: mannschaft.value.mannschaft }) const params = new URLSearchParams({ team: mannschaft.value.mannschaft })
if (spielplanSeason.value) { if (selectedSeason.value) {
params.set('season', selectedSeason.value)
} else if (spielplanSeason.value) {
params.set('season', spielplanSeason.value) params.set('season', spielplanSeason.value)
} }
@@ -594,7 +611,9 @@ const loadSpielplan = async () => {
spielplanError.value = '' spielplanError.value = ''
try { 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() const result = await response.json()
if (!result.success) { if (!result.success) {

View File

@@ -7,10 +7,10 @@
<div class="w-24 h-1 bg-primary-600 mb-8" /> <div class="w-24 h-1 bg-primary-600 mb-8" />
<p class="text-xl text-gray-600 mb-12"> <p class="text-xl text-gray-600 mb-12">
Unsere aktiven Mannschaften in der Saison 2025/26 Unsere aktiven Mannschaften in der Saison {{ selectedSeasonLabel }}
</p> </p>
<MannschaftenUebersicht /> <MannschaftenUebersicht :season="selectedSeason" />
<div class="mt-16"> <div class="mt-16">
<div class="bg-primary-50 p-8 rounded-xl border border-primary-100"> <div class="bg-primary-50 p-8 rounded-xl border border-primary-100">
@@ -21,7 +21,7 @@
Alle aktuellen Spielpläne und Ergebnisse unserer Mannschaften finden Sie hier. Alle aktuellen Spielpläne und Ergebnisse unserer Mannschaften finden Sie hier.
</p> </p>
<NuxtLink <NuxtLink
to="/mannschaften/spielplaene" :to="{ path: '/mannschaften/spielplaene', query: { season: selectedSeason } }"
class="inline-flex items-center px-6 py-3 bg-primary-600 hover:bg-primary-700 text-white font-semibold rounded-lg transition-colors" class="inline-flex items-center px-6 py-3 bg-primary-600 hover:bg-primary-700 text-white font-semibold rounded-lg transition-colors"
> >
Zu den Spielplänen Zu den Spielplänen
@@ -33,8 +33,29 @@
</template> </template>
<script setup> <script setup>
import { computed } from 'vue'
import MannschaftenUebersicht from '~/components/MannschaftenUebersicht.vue' import MannschaftenUebersicht from '~/components/MannschaftenUebersicht.vue'
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 selectedSeasonLabel = computed(() => {
const match = String(selectedSeason.value || '').match(/^(\d{2})--(\d{2})$/)
return match ? `20${match[1]}/${match[2]}` : selectedSeason.value
})
useHead({ useHead({
title: 'Mannschaften - Harheimer TC', title: 'Mannschaften - Harheimer TC',
}) })

View File

@@ -361,6 +361,9 @@
<script setup> <script setup>
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
const route = useRoute()
const router = useRouter()
useHead({ useHead({
title: 'Spielpläne - Mannschaften - Harheimer TC' title: 'Spielpläne - Mannschaften - Harheimer TC'
}) })
@@ -378,6 +381,19 @@ const seasons = ref([])
const selectedSeason = ref('') const selectedSeason = ref('')
const hasLoadedSpielplan = ref(false) const hasLoadedSpielplan = ref(false)
function 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)}`
}
function normalizeSeasonOrDefault(value) {
const season = String(value || '').trim()
return /^\d{2}--\d{2}$/.test(season) ? season : getCurrentSeasonSlug()
}
async function fetchCsvText(url) { async function fetchCsvText(url) {
const attempt = async () => { const attempt = async () => {
const withBuster = `${url}${url.includes('?') ? '&' : '?'}_t=${Date.now()}` const withBuster = `${url}${url.includes('?') ? '&' : '?'}_t=${Date.now()}`
@@ -405,7 +421,7 @@ const loadData = async () => {
const [spielplanResponse, mannschaftenResponse] = await Promise.all([ const [spielplanResponse, mannschaftenResponse] = await Promise.all([
fetch(`/api/spielplan${params.toString() ? `?${params.toString()}` : ''}`), fetch(`/api/spielplan${params.toString() ? `?${params.toString()}` : ''}`),
fetchCsvText('/api/mannschaften') fetchCsvText(`/api/mannschaften${params.toString() ? `?${params.toString()}` : ''}`)
]) ])
const spielplanResult = await spielplanResponse.json() const spielplanResult = await spielplanResponse.json()
@@ -494,11 +510,13 @@ const applyMannschaftenResponse = async (csvText) => {
} }
const onSeasonChange = () => { const onSeasonChange = () => {
router.replace({ query: { ...route.query, season: selectedSeason.value } })
spielplanData.value = [] spielplanData.value = []
filteredData.value = [] filteredData.value = []
headers.value = [] headers.value = []
lastUpdated.value = '' lastUpdated.value = ''
hasLoadedSpielplan.value = false hasLoadedSpielplan.value = false
loadData()
} }
const filterData = () => { const filterData = () => {
@@ -841,6 +859,7 @@ const getWettbewerbText = () => {
} }
onMounted(() => { onMounted(() => {
selectedSeason.value = normalizeSeasonOrDefault(route.query.season)
loadData() loadData()
}) })