canina/frontend/application/app/wiki/[slug]/page.tsx
parsa aghaei 7615aa0e51 fix: resolve seed encoding, search param, and wiki data source issues
- 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
2026-07-11 15:40:49 +03:30

77 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
);
}