wiki_ghostguild/app/pages/index.vue

108 lines
3.4 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<h1 class="text-4xl font-bold text-gray-900 dark:text-white mb-4">
Ghost Guild Knowledge Commons
</h1>
<p class="text-xl text-gray-600 dark:text-gray-400 mb-8">
Collaborative knowledge base for the Baby Ghosts community
</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">📚 Browse Articles</h2>
<p class="text-gray-600 dark:text-gray-400 mb-4">
Explore our growing collection of guides and resources
</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">👥 Community</h2>
<p class="text-gray-600 dark:text-gray-400 mb-4">
Connect with other Baby Ghosts members
</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.slug"
class="bg-white dark:bg-gray-800 p-4 rounded-lg shadow"
>
<NuxtLink
:to="`/articles/${article.slug}`"
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>