- author pages resolve slug or login and canonicalise to the slug - tag pages, per-page SEO meta and canonicals that keep ?page=N - sitemap source pages the API and builds locs from journal.routes - /rss.xml proxies the API feed with x-forwarded-for - neutral README; version 0.1.0
44 lines
1.7 KiB
Vue
44 lines
1.7 KiB
Vue
<script setup lang="ts">
|
|
// journal-index: the post list, paginated with ?page=N. A non-numeric page
|
|
// or a page past the last one is a real 404.
|
|
import { pageOutOfRange, parsePageParam } from '../utils/pagination.ts'
|
|
import { listTitle } from '../utils/seo.ts'
|
|
import { toListPost } from '../utils/view.ts'
|
|
import type { JournalModuleOptions } from '../utils/types.ts'
|
|
|
|
// Re-run setup (and its 404 checks) on every query change.
|
|
definePageMeta({ key: (route) => route.fullPath })
|
|
|
|
const route = useRoute()
|
|
const api = useJournalApi()
|
|
const cfg = useRuntimeConfig().public.journal as JournalModuleOptions
|
|
const { t } = useI18n()
|
|
|
|
const page = parsePageParam(route.query.page)
|
|
if (page === null) throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
|
|
|
|
const { data, error } = await useAsyncData(
|
|
`journal-index-${page}`,
|
|
() => api.listPosts({ page, perPage: cfg.perPage.index, sort: cfg.sort }),
|
|
{ transform: (res) => ({ ...res, data: res.data.map(toListPost) }) },
|
|
)
|
|
if (error.value || !data.value) {
|
|
throw createError({ statusCode: (error.value as { statusCode?: number } | undefined)?.statusCode ?? 500, fatal: true })
|
|
}
|
|
if (pageOutOfRange(page, data.value.meta.last_page)) {
|
|
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
|
|
}
|
|
|
|
const title = listTitle(t('journal.index.title'), page, t('journal.pagination.pageTitle', { page }))
|
|
useSeoMeta({ title, ogTitle: title })
|
|
</script>
|
|
|
|
<template>
|
|
<section v-if="data" class="journal-index">
|
|
<JournalIndexHeader :page="page" />
|
|
<JournalPostList :posts="data.data" />
|
|
<JournalPagination :current="data.meta.current_page" :last="data.meta.last_page" />
|
|
<JournalRssLink />
|
|
</section>
|
|
</template>
|