101 lines
3.1 KiB
Vue
101 lines
3.1 KiB
Vue
<template>
|
|
<div>
|
|
<p class="text-xl text-gray-600 dark:text-gray-400 mb-8">
|
|
A wiki for ghosts! 👻
|
|
</p>
|
|
|
|
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
<div class="bg-white dark:bg-gray-800 p-6 rounded-lg shadow">
|
|
<h2 class="text-xl font-semibold mb-2">View all articles</h2>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-4"></p>
|
|
<NuxtLink to="/articles" class="text-blue-600 hover:text-blue-800">
|
|
View All Articles →
|
|
</NuxtLink>
|
|
</div>
|
|
|
|
<!-- <div
|
|
v-if="isAuthenticated"
|
|
class="bg-white dark:bg-gray-800 p-6 rounded-lg shadow"
|
|
>
|
|
<h2 class="text-xl font-semibold mb-2">Contribute</h2>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-4">
|
|
Share your knowledge with the community
|
|
</p>
|
|
<NuxtLink to="/articles/new" class="text-blue-600 hover:text-blue-800">
|
|
Create Article →
|
|
</NuxtLink>
|
|
</div> -->
|
|
|
|
<div class="bg-white dark:bg-gray-800 p-6 rounded-lg shadow">
|
|
<h2 class="text-xl font-semibold mb-2">Ghost Guild</h2>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-4"></p>
|
|
<a
|
|
href="https://ghostguild.org"
|
|
class="text-blue-600 hover:text-blue-800"
|
|
>
|
|
Visit Ghost Guild →
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Recent Articles -->
|
|
<div class="mt-12">
|
|
<h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-6">
|
|
Recent Articles
|
|
</h2>
|
|
<div v-if="pending" class="text-gray-600 dark:text-gray-400">
|
|
Loading...
|
|
</div>
|
|
<div v-else-if="articles?.length" class="space-y-4">
|
|
<article
|
|
v-for="article in articles"
|
|
:key="article.stem"
|
|
class="bg-white dark:bg-gray-800 p-4 rounded-lg shadow"
|
|
>
|
|
<NuxtLink
|
|
:to="`/articles/${article.stem}`"
|
|
class="text-xl font-semibold text-blue-600 hover:text-blue-800"
|
|
>
|
|
{{ article.title }}
|
|
</NuxtLink>
|
|
<p class="text-gray-600 dark:text-gray-400 mt-2">
|
|
{{ article.description }}
|
|
</p>
|
|
<div class="mt-2 text-sm text-gray-500">
|
|
<span>{{ article.category }}</span> •
|
|
<span>{{
|
|
new Date(article.publishedAt).toLocaleDateString()
|
|
}}</span>
|
|
</div>
|
|
</article>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
const { isAuthenticated } = useAuth();
|
|
|
|
// Fetch recent articles from Nuxt Content to keep generate static-friendly
|
|
const { data: recentArticles, pending } = await useAsyncData(
|
|
"recent-articles",
|
|
async () => {
|
|
const entries = await queryCollection("articles").all();
|
|
|
|
const getTimestamp = (value) => {
|
|
if (!value) {
|
|
return 0;
|
|
}
|
|
const date = new Date(value);
|
|
return Number.isNaN(date.getTime()) ? 0 : date.getTime();
|
|
};
|
|
|
|
return entries
|
|
.filter((article) => article.published !== false)
|
|
.sort((a, b) => getTimestamp(b.publishedAt) - getTimestamp(a.publishedAt))
|
|
.slice(0, 5);
|
|
},
|
|
);
|
|
|
|
const articles = computed(() => recentArticles.value || []);
|
|
</script>
|