Replace the coming-soon page with products, mega menu, home slots, and catalog UI polish. Co-authored-by: Cursor <cursoragent@cursor.com>
61 lines
2.2 KiB
TypeScript
61 lines
2.2 KiB
TypeScript
import type { Metadata } from "next";
|
|
import Link from "next/link";
|
|
import { notFound } from "next/navigation";
|
|
|
|
import { JsonLd } from "@/components/CmsMeta";
|
|
import { asRichHtml, getBlogBySlug, safe } from "@/lib/catalog";
|
|
|
|
type PageProps = { params: Promise<{ slug: string }> };
|
|
|
|
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
|
|
const { slug } = await params;
|
|
const data = await safe(getBlogBySlug(slug), null);
|
|
if (!data) return { title: "نوشته پیدا نشد" };
|
|
const title = data.blog.seoMetaTitle || data.blog.title || data.blog.nameFa || slug;
|
|
const description = data.blog.seoMetaDescription || data.blog.summary || title;
|
|
const image = data.blog.thumbnailUrl || data.blog.image;
|
|
return {
|
|
title,
|
|
description,
|
|
openGraph: image ? { title, description, images: [{ url: image, alt: title }] } : { title, description },
|
|
};
|
|
}
|
|
|
|
export default async function BlogDetailPage({ params }: PageProps) {
|
|
const { slug } = await params;
|
|
const data = await safe(getBlogBySlug(slug), null);
|
|
if (!data) notFound();
|
|
|
|
const blog = data.blog;
|
|
const title = blog.title || blog.nameFa || slug;
|
|
const html = asRichHtml(blog.contentHtml || blog.descriptionHtml);
|
|
const image = blog.thumbnailUrl || blog.image;
|
|
|
|
return (
|
|
<main className="page">
|
|
<JsonLd data={blog.schema?.jsonLd ?? null} />
|
|
<article className="article wrap">
|
|
<header className="page-intro">
|
|
{blog.categoryNameFa ? <p className="kicker">{blog.categoryNameFa}</p> : null}
|
|
<h1>{title}</h1>
|
|
{blog.summary ? <p className="lead">{blog.summary}</p> : null}
|
|
</header>
|
|
{image ? (
|
|
<figure className="article__figure">
|
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
<img src={image} alt={title} />
|
|
</figure>
|
|
) : null}
|
|
{html ? (
|
|
<div className="rich-text" dangerouslySetInnerHTML={{ __html: html }} />
|
|
) : (
|
|
<p className="category-empty">متن این نوشته هنوز تکمیل نشده است.</p>
|
|
)}
|
|
<Link className="text-link" href="/blog">
|
|
بازگشت به مجله
|
|
</Link>
|
|
</article>
|
|
</main>
|
|
);
|
|
}
|