Files
harheimertc/components/PublicNews.vue

143 lines
4.1 KiB
Vue

<template>
<section v-if="news.length > 0" class="py-16 sm:py-20 bg-white">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<h2 class="text-4xl sm:text-5xl font-display font-bold text-gray-900 mb-4">
Aktuelles
</h2>
<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">
Die neuesten Nachrichten aus unserem Verein
</p>
</div>
<div class="flex justify-center">
<div class="grid gap-8" :class="getGridClass()">
<article
v-for="item in news"
:key="item.id"
@click="openNewsModal(item)"
class="bg-gray-50 rounded-xl p-6 border border-gray-200 hover:shadow-lg transition-shadow w-full max-w-sm flex flex-col cursor-pointer"
>
<div class="flex items-center text-sm text-gray-500 mb-3">
<Calendar :size="16" class="mr-2" />
{{ formatDate(item.created) }}
</div>
<h3 class="text-xl font-display font-bold text-gray-900 mb-3">
{{ item.title }}
</h3>
<p class="text-gray-700 line-clamp-3 flex-grow">
{{ item.content }}
</p>
</article>
</div>
</div>
</div>
<!-- News Modal -->
<div
v-if="selectedNews"
class="fixed inset-0 z-50 bg-black bg-opacity-50 flex items-center justify-center p-4"
@click.self="closeNewsModal"
>
<div class="bg-white rounded-xl shadow-2xl max-w-4xl w-full max-h-[90vh] flex flex-col">
<!-- Modal Header -->
<div class="flex items-center justify-between p-6 border-b border-gray-200">
<div class="flex-1">
<div class="flex items-center text-sm text-gray-500 mb-2">
<Calendar :size="16" class="mr-2" />
{{ formatDate(selectedNews.created) }}
</div>
<h2 class="text-2xl font-display font-bold text-gray-900">
{{ selectedNews.title }}
</h2>
</div>
<button
@click="closeNewsModal"
class="ml-4 p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg transition-colors"
>
<X :size="24" />
</button>
</div>
<!-- Modal Content (scrollable) -->
<div class="p-6 overflow-y-auto flex-1">
<div class="prose max-w-none text-gray-700 whitespace-pre-wrap">
{{ selectedNews.content }}
</div>
</div>
</div>
</div>
</section>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { Calendar, X } from 'lucide-vue-next'
const news = ref([])
const selectedNews = ref(null)
const loadNews = async () => {
try {
const response = await $fetch('/api/news-public')
news.value = response.news
} catch (error) {
console.error('Fehler beim Laden der öffentlichen News:', error)
}
}
const formatDate = (dateString) => {
if (!dateString) return ''
const date = new Date(dateString)
return date.toLocaleDateString('de-DE', {
year: 'numeric',
month: 'long',
day: 'numeric'
})
}
const getGridClass = () => {
const count = news.value.length
if (count === 1) {
// Eine Kachel: Eine Spalte, zentriert
return 'grid-cols-1 place-items-center'
} else if (count === 2) {
// Zwei Kacheln: Zwei Spalten, zentriert, gleiche Höhe
return 'grid-cols-1 md:grid-cols-2 place-items-stretch'
} else {
// Drei oder mehr Kacheln: Normale Grid-Darstellung
return 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3'
}
}
const openNewsModal = (item) => {
selectedNews.value = item
// Verhindere Scrollen im Hintergrund
document.body.style.overflow = 'hidden'
}
const closeNewsModal = () => {
selectedNews.value = null
// Erlaube Scrollen wieder
document.body.style.overflow = ''
}
onMounted(() => {
loadNews()
})
</script>
<style scoped>
.line-clamp-3 {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
</style>