basicstack.org/pages/infrastructure/[slug].vue

87 lines
1.9 KiB
Vue
Raw Normal View History

<template>
<div v-if="item" class="infra-detail">
<div class="page-header">
<div class="container">
<NuxtLink to="/infrastructure" class="breadcrumb"> Infrastructure</NuxtLink>
<span class="badge badge-primary">{{ categoryLabels[item.category] ?? item.category }}</span>
<h1>{{ item.title }}</h1>
<p v-if="item.summary" class="summary">{{ item.summary }}</p>
</div>
</div>
<div class="container page-body">
<div class="prose" v-html="item.content" />
</div>
</div>
<div v-else class="not-found container">
<h1>Not found</h1>
<NuxtLink to="/infrastructure" class="btn btn-primary">Back to Infrastructure</NuxtLink>
</div>
</template>
<script setup lang="ts">
const route = useRoute()
const { getInfrastructureItem } = useDirectus()
const { data: item } = await useAsyncData(`infra-${route.params.slug}`, () =>
getInfrastructureItem(route.params.slug as string)
)
const categoryLabels: Record<string, string> = {
hosting: 'Hosting',
security: 'Security',
monitoring: 'Monitoring',
backup: 'Backup',
disaster_recovery: 'Disaster Recovery',
}
if (item.value) {
useSeoMeta({
title: `${item.value.title} BasicStack`,
description: item.value.summary ?? undefined,
})
}
</script>
<style scoped>
.page-header {
background: var(--color-bg-secondary);
border-bottom: 1px solid var(--color-border);
padding: var(--space-2xl) 0;
}
.breadcrumb {
color: var(--color-text-muted);
font-size: 0.875rem;
display: block;
margin-bottom: var(--space-lg);
}
.page-header .badge {
display: inline-block;
margin-bottom: var(--space-md);
}
.page-header h1 {
margin-bottom: var(--space-sm);
}
.summary {
color: var(--color-text-muted);
font-size: 1.0625rem;
margin: 0;
max-width: 65ch;
}
.page-body {
padding: var(--space-2xl) var(--space-lg);
max-width: 768px;
}
.not-found {
padding: var(--space-3xl) var(--space-lg);
text-align: center;
}
</style>