82 lines
1.7 KiB
Vue
82 lines
1.7 KiB
Vue
|
<template>
|
||
|
<div class="blog-archives" v-for="entry in yearGroup">
|
||
|
<div class="blog-archives__year">
|
||
|
<NuxtLink :to="'/blog/archive/' + entry.year">{{ entry.year }}</NuxtLink>
|
||
|
</div>
|
||
|
<div class="blog-archives__posts">
|
||
|
<article class="blog-archives__post" v-for="post in entry.posts">
|
||
|
<header>
|
||
|
<NuxtLink
|
||
|
:to="'/blog/' + post.fullSlug"
|
||
|
class="blog-archives__time"
|
||
|
>{{ getStamp(post) }}</NuxtLink
|
||
|
>
|
||
|
<h1>
|
||
|
<NuxtLink :to="'/blog/' + post.fullSlug">{{ post.title }}</NuxtLink>
|
||
|
</h1>
|
||
|
</header>
|
||
|
</article>
|
||
|
</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script setup lang="ts">
|
||
|
import { BlogPost } from '~~/lib/types/post';
|
||
|
|
||
|
interface Archive {
|
||
|
year: number;
|
||
|
posts: BlogPost[];
|
||
|
}
|
||
|
|
||
|
const props = defineProps<{ posts: BlogPost[] }>();
|
||
|
|
||
|
const monthNames = [
|
||
|
'Jan',
|
||
|
'Feb',
|
||
|
'Mar',
|
||
|
'Apr',
|
||
|
'May',
|
||
|
'Jun',
|
||
|
'Jul',
|
||
|
'Aug',
|
||
|
'Sep',
|
||
|
'Oct',
|
||
|
'Nov',
|
||
|
'Dec',
|
||
|
];
|
||
|
|
||
|
const yearGroup = computed<Archive[]>(() => {
|
||
|
const groups: Archive[] = [];
|
||
|
|
||
|
props.posts
|
||
|
.sort((a, b) =>
|
||
|
new Date(b.date)
|
||
|
.toISOString()
|
||
|
.localeCompare(new Date(a.date).toISOString(), 'en', { numeric: true })
|
||
|
)
|
||
|
.forEach((post) => {
|
||
|
const date = new Date(post.date);
|
||
|
const year = date.getFullYear();
|
||
|
|
||
|
const contains = groups.find((item) => item.year === year);
|
||
|
|
||
|
if (contains) {
|
||
|
contains.posts.push(post);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
groups.push({
|
||
|
year,
|
||
|
posts: [post],
|
||
|
});
|
||
|
});
|
||
|
|
||
|
return groups;
|
||
|
});
|
||
|
|
||
|
const getStamp = (post: BlogPost) => {
|
||
|
const date = new Date(post.date);
|
||
|
return `${monthNames[date.getMonth()]} ${date.getDate()}`;
|
||
|
};
|
||
|
</script>
|