import { cache } from 'react'; import type { Metadata } from 'next'; import { notFound } from 'next/navigation'; import { createCmsClient } from '@kit/cms'; import { withI18n } from '~/lib/i18n/with-i18n'; import { ChangelogDetail } from '../_components/changelog-detail'; interface ChangelogEntryPageProps { params: Promise<{ slug: string }>; } const getChangelogData = cache(changelogEntryLoader); async function changelogEntryLoader(slug: string) { const client = await createCmsClient(); const [entry, allEntries] = await Promise.all([ client.getContentItemBySlug({ slug, collection: 'changelog' }), client.getContentItems({ collection: 'changelog', sortBy: 'publishedAt', sortDirection: 'desc', content: false, }), ]); if (!entry) { return null; } // Find previous and next entries in the timeline const currentIndex = allEntries.items.findIndex((item) => item.slug === slug); const newerEntry = currentIndex > 0 ? allEntries.items[currentIndex - 1] : null; const olderEntry = currentIndex < allEntries.items.length - 1 ? allEntries.items[currentIndex + 1] : null; return { entry, previousEntry: olderEntry, nextEntry: newerEntry, }; } export async function generateMetadata({ params, }: ChangelogEntryPageProps): Promise { const slug = (await params).slug; const data = await getChangelogData(slug); if (!data) { notFound(); } const { title, publishedAt, description, image } = data.entry; return Promise.resolve({ title, description, openGraph: { title, description, type: 'article', publishedTime: publishedAt, url: data.entry.url, images: image ? [ { url: image, }, ] : [], }, twitter: { card: 'summary_large_image', title, description, images: image ? [image] : [], }, }); } async function ChangelogEntryPage({ params }: ChangelogEntryPageProps) { const slug = (await params).slug; const data = await getChangelogData(slug); if (!data) { notFound(); } return (
); } export default withI18n(ChangelogEntryPage);