- Fix seed-products.ts TS error (implicit any) and BOM handling - Re-run full seed to restore correct Persian encoding in DB - Fix productService query→search param mismatch - Fix IngredientWiki hardcoded port 4000→use settingsStore - Restore seed-products-data.json from git after accidental corruption
77 lines
2.8 KiB
TypeScript
77 lines
2.8 KiB
TypeScript
import Link from 'next/link';
|
||
import { ChevronRight } from 'lucide-react';
|
||
import type { Metadata } from 'next';
|
||
|
||
async function getBlog(slug: string) {
|
||
try {
|
||
const res = await fetch(`http://localhost:4000/api/blogs/${slug}`, { next: { revalidate: 60 } });
|
||
if (!res.ok) throw new Error('Failed to fetch blog');
|
||
return res.json();
|
||
} catch (error) {
|
||
console.error(error);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> {
|
||
const blog = await getBlog(params.slug);
|
||
if (!blog) return { title: 'مقاله یافت نشد' };
|
||
|
||
return {
|
||
title: blog.metaTitle || blog.title,
|
||
description: blog.metaDescription || blog.title,
|
||
};
|
||
}
|
||
|
||
export default async function BlogPage({ params }: { params: { slug: string } }) {
|
||
const blog = await getBlog(params.slug);
|
||
|
||
if (!blog) {
|
||
return (
|
||
<div className="min-h-[50vh] flex flex-col items-center justify-center font-vazir text-center" dir="rtl">
|
||
<h1 className="text-3xl font-black text-medical-gray-900 mb-4">مقالهای یافت نشد</h1>
|
||
<Link href="/wiki" className="text-canina-blue font-bold flex items-center gap-2">
|
||
<ChevronRight className="w-4 h-4" />
|
||
بازگشت به دانشنامه
|
||
</Link>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div className="bg-white py-20 px-4 font-vazir" dir="rtl">
|
||
<div className="max-w-4xl mx-auto">
|
||
<Link href="/wiki" className="inline-flex items-center gap-2 text-medical-gray-400 hover:text-canina-blue transition-colors font-bold mb-8">
|
||
<ChevronRight className="w-5 h-5" />
|
||
بازگشت به مقالات
|
||
</Link>
|
||
|
||
{blog.imageUrl && (
|
||
<div className="aspect-video rounded-[2rem] overflow-hidden mb-12 shadow-xl border border-medical-gray-100">
|
||
<img src={blog.imageUrl} alt={blog.title} className="w-full h-full object-cover" />
|
||
</div>
|
||
)}
|
||
|
||
<h1 className="text-4xl lg:text-5xl font-black text-medical-gray-900 mb-6 leading-tight">
|
||
{blog.title}
|
||
</h1>
|
||
|
||
<div className="flex items-center gap-4 text-sm font-bold text-medical-gray-400 mb-12 pb-8 border-b border-medical-gray-100">
|
||
<span>نوشته شده در {new Date(blog.createdAt).toLocaleDateString('fa-IR')}</span>
|
||
{blog.author && (
|
||
<>
|
||
<span className="w-1 h-1 rounded-full bg-medical-gray-300" />
|
||
<span>توسط {blog.author.firstName} {blog.author.lastName}</span>
|
||
</>
|
||
)}
|
||
</div>
|
||
|
||
<div
|
||
className="prose prose-lg prose-medical-gray max-w-none prose-headings:font-black prose-p:leading-relaxed prose-a:text-canina-blue"
|
||
dangerouslySetInnerHTML={{ __html: blog.content }}
|
||
/>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|