feat: Revert homepage changes, fix Persian slug 404, and make various article and about us adjustments

- Removed the newly added city-focused section from the homepage.
- Fixed 404 error for Persian slugs in specialties and blog pages by implementing a decode helper.
- Removed the "مخصوص شهر" label from article headers.
- Linked article tags to their respective filter pages.
- Adjusted related content images to prevent distortion.
- Added a section in the "About Us" page for physician registration guidance.
- Updated the logo in the "About Us" header to the correct version.
- Added tests for the new functionality and ensured existing tests are updated accordingly.
This commit is contained in:
hamed
2026-08-08 21:06:48 +03:30
parent e8a073cae6
commit 9cfbd2e002
18 changed files with 704 additions and 145 deletions
+12 -6
View File
@@ -11,6 +11,7 @@ import {
findCityById,
} from "@/lib/domainHelpers";
import { safeJsonLd } from "@/lib/sanitize";
import { decodeRouteParam } from "@/lib/routeParams";
import { normalizeBlog, blogCover } from "@/helper";
const API_URL = process.env.NEXT_PUBLIC_API_URL;
@@ -39,7 +40,8 @@ async function getScopedBlog(slug) {
}
export async function generateMetadata({ params }) {
const { slug } = await params;
const { slug: rawSlug } = await params;
const slug = decodeRouteParam(rawSlug);
const { matchedCity } = await getStateInfo();
const siteName = matchedCity?.site_name || "نوبت 724";
@@ -82,7 +84,9 @@ export async function generateMetadata({ params }) {
// دامنه سرو می‌شد و هرکدام خودش را canonical اعلام می‌کرد.
// فیلد canonical_url اختصاصی (مثلاً نسخهٔ شهریِ پایپ‌لاین) مقدم است.
const origin = getBlogCanonicalOrigin(extractEntityCityId(blog));
const canonical = blog.canonical_url || `${origin}/blog/${slug}`;
// slug اینجا decode شده است؛ canonical باید شکل درصدی را بدهد وگرنه روی
// اسلاگ فارسی یک URL با کاراکتر غیر ASCII منتشر می‌شود.
const canonical = blog.canonical_url || `${origin}/blog/${encodeURIComponent(slug)}`;
return {
title,
@@ -115,7 +119,9 @@ export async function generateMetadata({ params }) {
}
async function Blog({ params }) {
const { slug } = await params;
const { slug: rawSlug } = await params;
const slug = decodeRouteParam(rawSlug);
const slugPath = encodeURIComponent(slug);
const blog = normalizeBlog(await getScopedBlog(slug));
if (!blog) notFound();
@@ -165,7 +171,7 @@ async function Blog({ params }) {
headline: blog.title,
...(articleDescription && { description: articleDescription }),
image: blogCover(blog),
mainEntityOfPage: { "@type": "WebPage", "@id": `${origin}/blog/${slug}` },
mainEntityOfPage: { "@type": "WebPage", "@id": `${origin}/blog/${slugPath}` },
...(blog.created && {
datePublished: new Date(blog.created * 1000).toISOString(),
}),
@@ -216,7 +222,7 @@ async function Blog({ params }) {
: []),
// آیتم آخر بدون `item` کل BreadcrumbList را نامعتبر می‌کند
{ "@type": "ListItem", position: categoryName ? 4 : 3, name: blog.title,
item: `${origin}/blog/${slug}` },
item: `${origin}/blog/${slugPath}` },
],
}
: null;
@@ -242,7 +248,7 @@ async function Blog({ params }) {
/>
)}
<Layout>
<BlogPage blog={blog} blogs={relatedBlogs} cityName={blogCity?.name} />
<BlogPage blog={blog} blogs={relatedBlogs} />
</Layout>
</>
);
+5 -2
View File
@@ -10,6 +10,7 @@ import { buildSpecialtyFaq, buildSpecialtyIntro } from "@/lib/specialtyContent";
import { isCategorySpecialty } from "@/lib/specialtyIndexing";
import { safeJsonLd } from "@/lib/sanitize";
import { fetchReq } from "@/lib/req";
import { decodeRouteParam } from "@/lib/routeParams";
import { isNextRedirectError } from "@/lib/maintenance";
const API_URL = process.env.NEXT_PUBLIC_API_URL;
@@ -42,7 +43,8 @@ const getDoctors = cache(async (specialtyId, cityId) => {
});
export async function generateMetadata({ params }) {
const { slug } = await params;
const { slug: rawSlug } = await params;
const slug = decodeRouteParam(rawSlug);
const specialty = findSpecialty(slug);
if (!specialty) notFound();
@@ -73,7 +75,8 @@ export async function generateMetadata({ params }) {
}
async function SpecialtyDetail({ params }) {
const { slug } = await params;
const { slug: rawSlug } = await params;
const slug = decodeRouteParam(rawSlug);
const specialty = findSpecialty(slug);
if (!specialty) notFound();