wf4/app/pages/blog/index.vue
webfussel 7038e47c75 fix: filter
filter also reacting to external posts
2025-07-17 13:48:11 +02:00

94 lines
No EOL
3.5 KiB
Vue

<template>
<section id="blog" class="BlogOverview content">
<h1>Blogfussel - für mehr Fussel im Blog</h1>
<p>Hey! Hier sammel ich alles, was mir so durch den Kopf geht - von handfesten Tutorials und Code-Snippets über Freelancing-Stories
bis hin zu News meiner Apps und random Gedanken. Manchmal ausführlich, manchmal nur kurz angerissen.</p>
<main class="margin-top">
<ul class="category-list">
<li>
<NuxtLink class="inline-flex-row gap-sm side" to="/blog">
<span class="chip"
:class="{ 'dark' : route.query.category && Object.keys(allCategoriesAndCount).includes(route.query.category as string)}">Alle {{
articles?.length
}}</span>
</NuxtLink>
</li>
<li v-for="(count, category) in allCategoriesAndCount">
<NuxtLink class="inline-flex-row gap-sm side" :to="`?category=${category}`">
<span class="chip" :class="{ 'dark' : category !== route.query.category}"><BlogCategory :name="category"/> {{ count }}</span>
</NuxtLink>
</li>
</ul>
<div class="grid margin-top-middle article-overview">
<BlogCard v-for="article in allPosts" v-bind="article"/>
<div v-if="allPosts.length < 2"/>
<div v-if="allPosts.length < 3"/>
</div>
</main>
</section>
</template>
<script setup lang="ts">
import type { BlogCollectionItem } from '@nuxt/content'
import type { BlogCard, Category } from '../../components/Blog/types'
const route = useRoute()
const { data: articles } = await useAsyncData('articles', () => queryCollection('blog')
.where('date', '<', tomorrow(new Date()))
.order('date', 'DESC')
.all(),
)
const firstTen = computed<BlogCard[]>(() => {
if (route.query.category && Object.keys(allCategoriesAndCount.value).includes(route.query.category as Category)) {
return (articles.value?.filter(article => article.category === route.query.category).slice(0, 10) ?? []).map(makeBlogCard)
}
return (articles.value?.slice(0, 10) ?? []).map(makeBlogCard)
})
const { data: externalPostsRaw } = useFetch('/api/external-posts', { method: 'POST' })
const externalPosts = computed<BlogCard[]>(() => externalPostsRaw.value?.flatMap(externalBlog => {
return externalBlog.posts.map(post => ({
title: post.title,
description: post.excerpt,
image: post.thumbnail,
date: post.date,
link: post.url,
category: 'extern',
author: externalBlog.author,
}))
}) ?? [])
const allPosts = computed<BlogCard[]>(() => [...(firstTen.value ?? []), ...(externalPosts.value ?? [])].sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()))
const allCategoriesAndCount = computed<Record<Category, number>>(() => {
const categories = {} as Record<Category, number>
articles.value?.forEach(article => {
const category = article.category as Category
if (category) {
categories[category] = (categories[category] ?? 0) + 1
}
})
categories['extern'] = externalPosts.value?.length ?? 0
return categories
})
const makeBlogCard = (article: BlogCollectionItem): BlogCard => ({
title: article.title,
description: article.description,
image: article.thumbnail as string,
date: article.date as string,
link: article.path,
category: article.category as Category,
author: article.author as { name: string, image: string },
})
useHead({
link: [
{ rel: 'alternate', type: 'application/rss+xml', href: '/blog/rss.xml', title: 'blogfussel' },
],
})
</script>