Add first post for monday, add external posts from other authors, add components for internal and external links
93 lines
No EOL
3.4 KiB
Vue
93 lines
No EOL
3.4 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 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
|
|
}
|
|
})
|
|
return categories
|
|
})
|
|
|
|
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: 'asdf',
|
|
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 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> |