100 lines
3.0 KiB
TypeScript
100 lines
3.0 KiB
TypeScript
import type { Metadata } from "next";
|
|
import Link from "next/link";
|
|
import { notFound, redirect } from "next/navigation";
|
|
|
|
import EntityTabs from "@/components/EntityTabs";
|
|
import PageHero from "@/components/PageHero";
|
|
import { blogHref, blogImage, blogTitleSlug, fetchBlogById, getLocalBlogPost } from "@/lib/blog";
|
|
import { fetchComments } from "@/lib/comments";
|
|
import { formatFaDateLong } from "@/lib/format";
|
|
import { pageMetadata } from "@/lib/seo";
|
|
|
|
export const revalidate = 60;
|
|
|
|
export async function generateMetadata({
|
|
params,
|
|
}: {
|
|
params: Promise<{ id: string; slug: string }>;
|
|
}): Promise<Metadata> {
|
|
const { id } = await params;
|
|
const apiPost = await fetchBlogById(id);
|
|
if (apiPost) {
|
|
return pageMetadata({
|
|
title: apiPost.title,
|
|
description: apiPost.abstract ?? apiPost.title,
|
|
path: blogHref(apiPost),
|
|
image: blogImage(apiPost),
|
|
});
|
|
}
|
|
const local = getLocalBlogPost(id);
|
|
if (!local) return { title: "مقاله" };
|
|
return pageMetadata({
|
|
title: local.title,
|
|
description: local.abstract ?? local.title,
|
|
path: blogHref(local),
|
|
image: blogImage(local),
|
|
});
|
|
}
|
|
|
|
export default async function BlogPostPage({
|
|
params,
|
|
}: {
|
|
params: Promise<{ id: string; slug: string }>;
|
|
}) {
|
|
const { id, slug } = await params;
|
|
const apiPost = await fetchBlogById(id);
|
|
|
|
if (apiPost) {
|
|
const canonical = blogTitleSlug(apiPost.title);
|
|
if (decodeURIComponent(slug) !== canonical) {
|
|
redirect(blogHref(apiPost));
|
|
}
|
|
|
|
const comments = await fetchComments("blog", apiPost.id);
|
|
const dateLabel = formatFaDateLong(apiPost.publishedAt || apiPost.createdAt);
|
|
return (
|
|
<>
|
|
<PageHero title={apiPost.title} english="BLOG" />
|
|
<section className="section">
|
|
<div className="container detail-page">
|
|
{dateLabel ? <p className="detail-date">{dateLabel}</p> : null}
|
|
{apiPost.abstract ? <p className="detail-lead">{apiPost.abstract}</p> : null}
|
|
{apiPost.mainTextHtml ? (
|
|
<div className="rich-text" dangerouslySetInnerHTML={{ __html: apiPost.mainTextHtml }} />
|
|
) : null}
|
|
<EntityTabs showDescription={false} comments={comments} />
|
|
<Link href="/blog" className="back-link">
|
|
بازگشت به مقالات
|
|
</Link>
|
|
</div>
|
|
</section>
|
|
</>
|
|
);
|
|
}
|
|
|
|
const local = getLocalBlogPost(id);
|
|
if (!local) notFound();
|
|
|
|
const canonical = blogTitleSlug(local.title);
|
|
if (decodeURIComponent(slug) !== canonical) {
|
|
redirect(blogHref(local));
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<PageHero title={local.title} english="BLOG" />
|
|
<section className="section">
|
|
<div className="container detail-page">
|
|
{local.dateLabel ? <p className="detail-date">{local.dateLabel}</p> : null}
|
|
<div className="detail-image">
|
|
<img src={blogImage(local)} alt={local.title} />
|
|
</div>
|
|
<Link href="/blog" className="back-link">
|
|
بازگشت به مقالات
|
|
</Link>
|
|
</div>
|
|
</section>
|
|
</>
|
|
);
|
|
}
|