feat: add new content pages

This commit is contained in:
beilunyang
2026-01-18 14:33:11 +08:00
committed by ty
parent cef0ee0f0c
commit 07ad672e7d
54 changed files with 2314 additions and 57 deletions
+68
View File
@@ -0,0 +1,68 @@
import { Header } from "@/components/layout/header"
import { getBlogPost, blogPosts } from "@/lib/blog-data"
import { notFound } from "next/navigation"
import { ArrowLeft } from "lucide-react"
import Link from "next/link"
import { getTranslations } from "next-intl/server"
export function generateStaticParams() {
return blogPosts.map((post) => ({
slug: post.slug,
}))
}
export async function generateMetadata({
params
}: {
params: Promise<{ locale: string; slug: string }>
}) {
const { locale, slug } = await params
const post = getBlogPost(slug, locale)
if (!post) return {}
return {
title: `${post.title} - MoeMail`
}
}
export default async function BlogPostPage({
params,
}: {
params: Promise<{ locale: string; slug: string }>
}) {
const { locale, slug } = await params
const post = getBlogPost(slug, locale)
const t = await getTranslations({ locale, namespace: "blog" })
if (!post) {
notFound()
}
return (
<div className="min-h-screen bg-background flex flex-col">
<Header />
<main className="container mx-auto px-4 py-24 flex-1">
<article className="max-w-3xl mx-auto space-y-8">
<Link
href={`/${locale}/blog`}
className="inline-flex items-center text-sm text-muted-foreground hover:text-foreground transition-colors"
>
<ArrowLeft className="mr-2 h-4 w-4" />
{t("backToBlog")}
</Link>
<header className="space-y-4">
<h1 className="text-4xl font-bold">{post.title}</h1>
<time className="text-muted-foreground block" dateTime={post.date}>
{post.date}
</time>
</header>
<div
className="prose dark:prose-invert max-w-none"
dangerouslySetInnerHTML={{ __html: post.content }}
/>
</article>
</main>
</div>
)
}
+62
View File
@@ -0,0 +1,62 @@
import { Header } from "@/components/layout/header"
import { getTranslations } from "next-intl/server"
import Link from "next/link"
import { getBlogPosts } from "@/lib/blog-data"
import { ArrowRight } from "lucide-react"
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params
const t = await getTranslations({ locale, namespace: "common" })
return {
title: `${t("nav.blog")} - ${t("app.name")}`
}
}
export default async function BlogIndexPage({
params,
}: {
params: Promise<{ locale: string }>
}) {
const { locale } = await params
const t = await getTranslations({ locale, namespace: "blog" })
const posts = getBlogPosts(locale)
return (
<div className="min-h-screen bg-background flex flex-col">
<Header />
<main className="container mx-auto px-4 py-24 flex-1">
<div className="max-w-4xl mx-auto space-y-12">
<div className="text-center space-y-4">
<h1 className="text-4xl font-bold">{t("title")}</h1>
<p className="text-muted-foreground text-lg">
{t("subtitle")}
</p>
</div>
<div className="grid gap-8 md:grid-cols-2">
{posts.map((post) => (
<article key={post.slug} className="group relative flex flex-col space-y-4 rounded-lg border p-6 hover:bg-accent/50 transition-colors">
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<time dateTime={post.date}>{post.date}</time>
</div>
<h2 className="text-2xl font-bold group-hover:text-primary transition-colors">
{post.title}
</h2>
<p className="text-muted-foreground flex-1">
{post.excerpt}
</p>
<Link
href={`/${locale}/blog/${post.slug}`}
className="inline-flex items-center font-medium text-primary hover:underline"
>
{t("readMore")} <ArrowRight className="ml-1 h-4 w-4" />
<span className="absolute inset-0" />
</Link>
</article>
))}
</div>
</div>
</main>
</div>
)
}