Files
harheimertc/pages/termine.vue
2025-12-20 10:17:16 +01:00

154 lines
4.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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 class="text-center mb-12">
<h1 class="text-4xl sm:text-5xl font-display font-bold text-gray-900 mb-4">
Termine & Events
</h1>
<div class="w-24 h-1 bg-primary-600 mx-auto mb-6" />
<p class="text-xl text-gray-600 max-w-3xl mx-auto">
Alle kommenden Termine und Veranstaltungen des Harheimer TC
</p>
</div>
<div
v-if="naechsteTermine.length > 0"
class="space-y-4"
>
<div
v-for="(termin, index) in naechsteTermine"
:key="index"
class="bg-white rounded-xl shadow-lg p-6 hover:shadow-xl transition-shadow"
>
<div class="flex items-start space-x-4">
<div class="flex-shrink-0 w-16 h-16 bg-primary-600 rounded-xl flex flex-col items-center justify-center text-white">
<span class="text-2xl font-bold">{{ formatDay(termin.datum) }}</span>
<span class="text-xs">{{ formatMonth(termin.datum) }}</span>
</div>
<div class="flex-1">
<div class="flex items-start justify-between">
<div>
<h3 class="text-xl font-semibold text-gray-900 mb-1">
{{ termin.titel }}
</h3>
<p class="text-gray-600 mb-2">
{{ termin.beschreibung }}
</p>
<p class="text-sm text-gray-500">
{{ formatFullDateTime(termin.datum, termin.uhrzeit) }}
</p>
</div>
<span
:class="[
'px-3 py-1 text-sm font-medium rounded-full',
termin.kategorie === 'Turnier' ? 'bg-yellow-100 text-yellow-800' : 'bg-blue-100 text-blue-800'
]"
>
{{ termin.kategorie }}
</span>
</div>
</div>
</div>
</div>
</div>
<div
v-else
class="text-center py-16 bg-white rounded-xl shadow-lg"
>
<Calendar
:size="64"
class="text-gray-400 mx-auto mb-4"
/>
<h3 class="text-2xl font-semibold text-gray-900 mb-2">
Keine kommenden Termine
</h3>
<p class="text-gray-600">
Aktuell sind keine Termine geplant. Schauen Sie bald wieder vorbei!
</p>
</div>
<div class="mt-12 bg-primary-50 border border-primary-100 rounded-xl p-6">
<h3 class="text-lg font-semibold text-primary-900 mb-2">
Hinweis
</h3>
<p class="text-primary-800">
Alle Termine sind vorbehaltlich kurzfristiger Änderungen.
Bei Fragen zu einzelnen Veranstaltungen kontaktieren Sie uns gerne.
</p>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { Calendar } from 'lucide-vue-next'
const termine = ref([])
const naechsteTermine = computed(() => {
const heute = new Date()
heute.setHours(0, 0, 0, 0)
return termine.value
.filter(t => {
// Datum + optionale Uhrzeit berücksichtigen
let terminDatum
if (t.uhrzeit && /^\d{2}:\d{2}$/.test(t.uhrzeit)) {
terminDatum = new Date(`${t.datum}T${t.uhrzeit}:00`)
} else {
terminDatum = new Date(t.datum)
}
return terminDatum >= heute
})
.sort((a, b) => {
const da = new Date(`${a.datum}${a.uhrzeit ? 'T' + a.uhrzeit + ':00' : ''}`)
const db = new Date(`${b.datum}${b.uhrzeit ? 'T' + b.uhrzeit + ':00' : ''}`)
return da - db
})
})
const formatDay = (dateString) => {
const date = new Date(dateString)
return date.getDate()
}
const formatMonth = (dateString) => {
const date = new Date(dateString)
const monate = ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez']
return monate[date.getMonth()]
}
const formatFullDate = (dateString) => {
const date = new Date(dateString)
const wochentage = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag']
const monate = ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember']
return `${wochentage[date.getDay()]}, ${date.getDate()}. ${monate[date.getMonth()]} ${date.getFullYear()}`
}
const formatFullDateTime = (datum, uhrzeit) => {
const base = formatFullDate(datum)
const time = uhrzeit && /^\d{2}:\d{2}$/.test(uhrzeit) ? `${uhrzeit} Uhr` : ''
return time ? `${base} ${time}` : base
}
const loadTermine = async () => {
try {
const response = await $fetch('/api/termine')
termine.value = response.termine || []
} catch (error) {
console.error('Fehler beim Laden der Termine:', error)
termine.value = []
}
}
onMounted(() => {
loadTermine()
})
useHead({
title: 'Termine & Events - Harheimer TC',
})
</script>