canina/frontend/application/app/wiki/[slug]/page.tsx
parsa aghaei 70d58e7086
All checks were successful
Deploy Canina / deploy (push) Successful in 1m44s
feat(seo): unify dynamic SEO metadata and title formatting across backend, admin and application
2026-08-19 15:03:10 +03:30

88 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

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';
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'https://api.canina.ir';
async function getWikiTerm(key: string) {
try {
const res = await fetch(`${API_URL}/api/wiki/${encodeURIComponent(key)}`, { next: { revalidate: 60 } });
if (!res.ok) throw new Error('Failed to fetch wiki term');
return res.json();
} catch (error) {
console.error(error);
return null;
}
}
import { getSeoConfig, formatPageTitle } from "../../../lib/seo";
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
const { slug } = await params;
const term = await getWikiTerm(slug);
const config = await getSeoConfig();
if (!term) {
return {
title: formatPageTitle('ترکیب علمی یافت نشد', config.brandNameFa, config.titleSeparator, config.titlePosition),
};
}
const rawTitle = term.metaTitle || `ترکیب علمی ${term.term}`;
const title = formatPageTitle(rawTitle, config.brandNameFa, config.titleSeparator, config.titlePosition, false);
const description = term.metaDescription || term.definition?.replace(/<[^>]+>/g, '').substring(0, 155).trim() || config.defaultMetaDescription;
const canonicalUrl = `${config.canonicalBaseUrl.replace(/\/$/, '')}/wiki/${slug}`;
return {
title,
description,
alternates: {
canonical: canonicalUrl,
},
openGraph: {
title,
description,
url: canonicalUrl,
siteName: config.brandNameFa,
type: "article",
}
};
}
export default async function WikiTermPage({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const term = await getWikiTerm(slug);
if (!term) {
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>
<h1 className="text-4xl lg:text-5xl font-black text-medical-gray-900 mb-6 leading-tight">
{term.term}
</h1>
<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: term.definition }}
/>
</div>
</div>
);
}