Initial commit: Alma Beauti Next.js site.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user