186 lines
4.8 KiB
Vue
Raw Permalink 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="knowledgeBox topSpace">
<section class="teaserBox">
<div class="container">
<h1>Digital Insights Magazin</h1>
<h2>Wissenswertes rund um moderne Weblösungen</h2>
<p>Hier finden Sie praxisnahe Beiträge zu Technik, Strategie und Gestaltung im Web. Wir bieten wertvolle Impulse und aktuelles Wissen,
damit Sie gut informiert sind und fundierte Entscheidungen für Ihre Webprojekte treffen können.
</p>
<div class="selectionZone">
<button
:class="{ active: isAllSelected }"
@click="selectAll"
>
Alle
</button>
<button
v-for="category in categories"
:key="category.id"
:class="{ active: selectedCategories.has(category.id) }"
@click="toggleCategory(category.id)"
>
{{ category.name }}
</button>
</div>
</div>
</section>
<section class="articleBox container">
<transition-group
name="article"
tag="div"
class="grid"
appear
>
<ArticleCard
v-for="article in filteredArticles"
:key="article.id"
:header="article.header"
:image="article.image"
:link="localePath({ name: 'article-link', params: { link: article.slug } })"
:readmore-text="$t('pages.magazin.readmore')"
/>
</transition-group>
</section>
</div>
</template>
<script setup lang="ts">
definePageMeta({
sitemap: {
lastmod: '2025-06-23', // ISO 8601 oder dynamisch generieren
changefreq: 'daily', // optional
priority: 1 // optional
}
})
import { useMainStore } from '@/stores/main'
import { storeToRefs } from 'pinia'
import { useLocalePath } from '#i18n'
const localePath = useLocalePath()
const mainStore = useMainStore()
const { articles, categories } = storeToRefs(mainStore)
const truncateText = (text: string, length = 200) =>
text?.length > length ? text.substring(0, length) + '…' : text
const currentDomain = typeof window !== 'undefined'
? window.location.origin
: 'https://www.digimedialoop.de'
const selectedCategories = ref<Set<number>>(new Set())
const isAllSelected = computed(() => selectedCategories.value.size === 0)
function toggleCategory(categoryId: number) {
if (selectedCategories.value.has(categoryId)) {
selectedCategories.value.delete(categoryId)
} else {
selectedCategories.value.add(categoryId)
}
}
function selectAll() {
selectedCategories.value.clear()
}
const filteredArticles = computed(() => {
if (isAllSelected.value) return articles.value
return articles.value.filter(article => {
if (!article.categories || article.categories.length === 0) return false
return article.categories.some(cat => selectedCategories.value.has(cat.id))
})
})
// SEO: JSON-LD für Artikelübersicht
watch(articles, (newVal) => {
if (newVal?.length) {
useHead({
script: [
{
type: 'application/ld+json',
children: JSON.stringify({
"@context": "https://schema.org",
"@type": "ItemList",
itemListElement: newVal.map((article, index) => ({
"@type": "ListItem",
position: index + 1,
url: `${currentDomain}/wissenswertes/artikel/${article.slug}`,
name: article.header,
}))
})
}
]
})
}
}, { immediate: true })
</script>
<style lang="sass">
.knowledgeBox
h1
margin: 2rem 0 0 0
h2
margin: 0 0 0 0
.selectionZone
border: 1px solid $lightgrey
border-radius: 1rem
padding: 1rem 1.5rem 0 1.5rem
background-color: lighten($beige, 5%)
margin: 0 0 4rem 0
button
all: unset
background-color: white
padding: .5rem 1.5rem
border-radius: .8rem
margin: 0 1rem 1rem 0
box-shadow: 1px 1px 1px 0 rgba(black, .3)
border: 1px solid darken($lightgrey, 8%)
transition: .5s
cursor: pointer
&:hover
transform: scale(1.05)
&.active
font-family: 'Mainfont-Bold'
box-shadow: 0 0 2px 0 rgba(black, .3)
background-color: darken($lightgrey, 10%)
border: 1px solid darken($lightgrey, 25%)
.articleBox
display: flex
justify-content: center
width: (9)0%
.grid
display: grid
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr))
gap: 2.5rem
justify-content: start
width: 100%
max-width: 100%
margin: 0 auto
transition: all 0.3s ease-in-out // weichere Umordnung der Items
.article-enter-from,
.article-leave-to
opacity: 0
transform: scale(0.85)
.article-enter-active,
.article-leave-active
transition: all 0.3s ease
</style>