Files
ui/docs/app/pages/blog/[...slug].vue
HugoRCD 64d574ba6e up
2025-05-06 14:09:34 +02:00

99 lines
2.8 KiB
Vue

<script setup lang="ts">
import { kebabCase } from 'scule'
const route = useRoute()
const [{ data: page }, { data: surround }] = await Promise.all([
useAsyncData(kebabCase(route.path), () => queryCollection('blog').path(route.path).first()),
useAsyncData(`${kebabCase(route.path)}-surround`, () => {
return queryCollectionItemSurroundings('blog', route.path, {
fields: ['description']
}).order('date', 'DESC')
})
])
if (!page.value) {
throw createError({ statusCode: 404, statusMessage: 'Article not found', fatal: true })
}
const title = page.value.seo?.title || page.value.title
const description = page.value.seo?.description || page.value.description
useSeoMeta({
title,
description,
ogDescription: description,
ogTitle: title
})
if (page.value.image) {
defineOgImage({ url: page.value.image })
} else {
defineOgImageComponent('Docs', {
headline: 'Blog',
title,
description
})
}
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric'
})
}
</script>
<template>
<UMain class="mt-20 px-2">
<UContainer class="relative min-h-screen">
<UPage v-if="page">
<ULink
to="/blog"
class="text-sm flex items-center gap-1"
>
<UIcon name="lucide:chevron-left" />
Blog
</ULink>
<div class="flex flex-col gap-3 mt-8">
<div class="flex text-xs text-muted items-center justify-center gap-2">
<span v-if="page.date">
{{ formatDate(page.date) }}
</span>
<span v-if="page.date && page.minRead">
-
</span>
<span v-if="page.minRead">
{{ page.minRead }} MIN READ
</span>
</div>
<NuxtImg
:src="page.image"
:alt="page.title"
class="rounded-lg w-full h-[400px] object-cover object-center max-w-5xl mx-auto"
/>
<h1 class="text-4xl text-center font-medium max-w-3xl mx-auto mt-4">
{{ page.title }}
</h1>
<p class="text-muted text-center max-w-2xl mx-auto">
{{ page.description }}
</p>
<div class="mt-4 flex justify-center flex-wrap items-center gap-6">
<UUser v-for="(author, index) in page.authors" :key="index" v-bind="author" :description="author.to ? `@${author.to.split('/').pop()}` : undefined" />
</div>
</div>
<UPageBody class="max-w-3xl mx-auto">
<ContentRenderer
v-if="page.body"
:value="page"
/>
<USeparator v-if="surround?.length" />
<UContentSurround :surround="surround" />
</UPageBody>
</UPage>
</UContainer>
</UMain>
</template>