import { fetchReq } from "@/lib/req"; import { isNextRedirectError } from "@/lib/maintenance"; import ClinicsPage from "@/components/clinics"; import Layout from "@/components/layout/StLayout"; import { getStateInfo } from "@/lib/getStateInfo"; import { buildClinicParams } from "@/helper"; import { listingRobots } from "@/lib/listingRobots"; import { getRequestOrigin } from "@/lib/getCanonicalUrl"; import { buildClinicsIntro } from "@/lib/listingIntro"; import { resolveCityDisplayName } from "@/lib/domainHelpers"; export async function generateMetadata({ searchParams }) { const awaitedParams = await searchParams; const { matchedCity, matchedState, isRoot, repContext } = await getStateInfo(); const siteName = matchedCity?.site_name || repContext?.full_name || "نوبت 724"; // روی دامنهٔ ریشه نام رکورد («نوبت 724») برند است نه شهر — نباید در Title بنشیند. const cityName = isRoot ? "" : matchedCity?.name || matchedState?.name || ""; const title = cityName ? `کلینیک‌های ${cityName} | جستجو و رزرو نوبت | ${siteName}` : `جستجوی کلینیک و مراکز درمانی | ${siteName}`; const description = cityName ? `لیست کلینیک‌ها و مراکز درمانی در ${cityName}. رزرو آنلاین نوبت از بهترین مراکز درمانی ${cityName}.` : `جستجوی کلینیک‌ها و مراکز درمانی در سراسر کشور. رزرو آنلاین نوبت سریع و آسان.`; const image = "/assets/images/og-image.png"; return { title, description, ...listingRobots(awaitedParams), openGraph: { title, description, images: [image] }, twitter: { card: "summary_large_image", title, description, images: [image] }, }; } export default async function Clinics({ searchParams }) { const awaitedSearchParams = await searchParams; const { matchedCity, matchedState, isRoot, repContext, host } = await getStateInfo(); const API_URL = process.env.NEXT_PUBLIC_API_URL; const stateParams = awaitedSearchParams.state; const cityParams = awaitedSearchParams.city; let clinics; try { // Params // کپی — awaitedSearchParams همان شیئی است که generateMetadata هم می‌خواند؛ // تزریق city/state روی خودش، سیاست robots را به noindex می‌برد. const newSearchParams = { ...awaitedSearchParams }; // Conditional State — روی دامنهٔ ریشه (nobat724) فیلتر اعمال نمی‌شود. if (stateParams) newSearchParams.state = stateParams; else if (matchedState && !isRoot) newSearchParams.state = matchedState.name; // Conditional City if (cityParams) newSearchParams.city = cityParams; else if (matchedCity && !isRoot) newSearchParams.city = matchedCity.name; const params = buildClinicParams(newSearchParams); // دامنه‌ی نماینده سراسری: backend فقط کلینیک‌های همان نماینده را برمی‌گرداند؛ فیلتر شهر بی‌معنی است. if (repContext?.is_global) { delete params.city; delete params.state; params.domain = host; } // Req clinics = await fetchReq(`${API_URL}/api/v1/clinics`, { params, }); } catch (err) { // ریدایرکت نکست با throw کار می‌کند؛ بدون این rethrow، ریدایرکت حالت تعمیرات بلعیده می‌شود. if (isNextRedirectError(err)) throw err; } // origin برای BreadcrumbList لازم است: گوگل در itemListElement آدرس مطلق می‌خواهد. const origin = await getRequestOrigin(); return ( ); }