seo check
This commit is contained in:
@@ -1,5 +1,18 @@
|
|||||||
import AboutUsPage from "@/components/aboutUs";
|
import AboutUsPage from "@/components/aboutUs";
|
||||||
import Layout from "@/components/layout/StLayout";
|
import Layout from "@/components/layout/StLayout";
|
||||||
|
import { getStateInfo } from "@/lib/getStateInfo";
|
||||||
|
|
||||||
|
export async function generateMetadata() {
|
||||||
|
const { matchedCity } = await getStateInfo();
|
||||||
|
const siteName = matchedCity?.site_name || "نوبت 724";
|
||||||
|
const title = `درباره ما | ${siteName}`;
|
||||||
|
const description = `آشنایی با ${siteName}، سیستم آنلاین نوبتدهی پزشکی. هدف ما ارائه خدمات سریع و کارآمد رزرو نوبت پزشکی برای همه مردم است.`;
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
openGraph: { title, description },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function AboutUs() {
|
function AboutUs() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
+68
-6
@@ -1,24 +1,86 @@
|
|||||||
import BlogPage from "@/components/blog";
|
import BlogPage from "@/components/blog";
|
||||||
import Layout from "@/components/layout/StLayout";
|
import Layout from "@/components/layout/StLayout";
|
||||||
import { fetchReq } from "@/lib/req";
|
import { fetchReq } from "@/lib/req";
|
||||||
|
import { getStateInfo } from "@/lib/getStateInfo";
|
||||||
|
|
||||||
async function Blog({ params: { slug } }) {
|
export async function generateMetadata({ params }) {
|
||||||
|
const { slug } = await params;
|
||||||
|
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||||
|
const { matchedCity } = await getStateInfo();
|
||||||
|
const siteName = matchedCity?.site_name || "نوبت 724";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const blog = await fetchReq(`${API_URL}/api/v1/blog/${slug}`);
|
||||||
|
if (!blog) return {};
|
||||||
|
|
||||||
|
const title = `${blog.title} | ${siteName}`;
|
||||||
|
const rawText = blog.body ? blog.body.replace(/<[^>]*>/g, "").trim() : "";
|
||||||
|
const description = rawText.slice(0, 160) || blog.title;
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
openGraph: {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
type: "article",
|
||||||
|
...(blog.created && { publishedTime: blog.created }),
|
||||||
|
images: blog.images?.[0]
|
||||||
|
? [blog.images[0]]
|
||||||
|
: ["https://www.nobat724.com/assets/images/logo.png"],
|
||||||
|
},
|
||||||
|
twitter: {
|
||||||
|
card: "summary_large_image",
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
images: blog.images?.[0]
|
||||||
|
? [blog.images[0]]
|
||||||
|
: ["https://www.nobat724.com/assets/images/logo.png"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function Blog({ params }) {
|
||||||
|
const { slug } = await params;
|
||||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||||
|
|
||||||
const blog = await fetchReq(`${API_URL}/api/v1/blog/${slug}`);
|
const blog = await fetchReq(`${API_URL}/api/v1/blog/${slug}`);
|
||||||
|
|
||||||
// Get related blogs based on first tag
|
|
||||||
let relatedBlogs = [];
|
let relatedBlogs = [];
|
||||||
if (blog?.tag?.[0]?.id) {
|
if (blog?.tag?.[0]?.id) {
|
||||||
const tagId = blog.tag[0].id;
|
const tagId = blog.tag[0].id;
|
||||||
const relatedResponse = await fetchReq(`${API_URL}/api/v1/blogs?page=1&limit=12&tag=${tagId}`);
|
const relatedResponse = await fetchReq(
|
||||||
|
`${API_URL}/api/v1/blogs?page=1&limit=12&tag=${tagId}`
|
||||||
|
);
|
||||||
relatedBlogs = relatedResponse?.blogs || [];
|
relatedBlogs = relatedResponse?.blogs || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const jsonLd = blog
|
||||||
|
? {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Article",
|
||||||
|
headline: blog.title,
|
||||||
|
...(blog.images?.[0] && { image: blog.images[0] }),
|
||||||
|
...(blog.created && { datePublished: blog.created }),
|
||||||
|
...(blog.author && { author: { "@type": "Person", name: blog.author } }),
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<>
|
||||||
<BlogPage blog={blog} blogs={relatedBlogs} />
|
{jsonLd && (
|
||||||
</Layout>
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Layout>
|
||||||
|
<BlogPage blog={blog} blogs={relatedBlogs} />
|
||||||
|
</Layout>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
import BlogsPage from "@/components/blogs";
|
import BlogsPage from "@/components/blogs";
|
||||||
import Layout from "@/components/layout/StLayout";
|
import Layout from "@/components/layout/StLayout";
|
||||||
|
import { getStateInfo } from "@/lib/getStateInfo";
|
||||||
|
|
||||||
|
export async function generateMetadata() {
|
||||||
|
const { matchedCity } = await getStateInfo();
|
||||||
|
const siteName = matchedCity?.site_name || "نوبت 724";
|
||||||
|
const title = `مقالات و اخبار پزشکی | ${siteName}`;
|
||||||
|
const description = `جدیدترین مقالات، اخبار و راهنماهای پزشکی. اطلاعات تخصصی در حوزه سلامت و پزشکی از متخصصان ${siteName}.`;
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
openGraph: { title, description },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default function Blogs() {
|
export default function Blogs() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
+55
-10
@@ -1,28 +1,73 @@
|
|||||||
import ClinicPage from "@/components/clinic";
|
import ClinicPage from "@/components/clinic";
|
||||||
import Layout from "@/components/layout/StLayout";
|
import Layout from "@/components/layout/StLayout";
|
||||||
import { fetchReq } from "@/lib/req";
|
import { fetchReq } from "@/lib/req";
|
||||||
|
import { getStateInfo } from "@/lib/getStateInfo";
|
||||||
|
|
||||||
async function Clinic({ params: { slug },searchParams }) {
|
export async function generateMetadata({ params }) {
|
||||||
|
const { slug } = await params;
|
||||||
|
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||||
|
const { matchedCity } = await getStateInfo();
|
||||||
|
const siteName = matchedCity?.site_name || "نوبت 724";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const clinic = await fetchReq(`${API_URL}/api/v1/clinic/${slug}`);
|
||||||
|
if (!clinic) return {};
|
||||||
|
|
||||||
|
const title = `${clinic.title} | ${siteName}`;
|
||||||
|
const description = `رزرو نوبت و اطلاعات ${clinic.title}. مشاهده لیست پزشکان و خدمات درمانی موجود.`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
openGraph: {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
images: clinic.images_clinic?.[0]
|
||||||
|
? [clinic.images_clinic[0]]
|
||||||
|
: ["https://www.nobat724.com/assets/images/logo.png"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function Clinic({ params, searchParams }) {
|
||||||
|
const { slug } = await params;
|
||||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||||
const page = Number(searchParams?.page) || 1;
|
const page = Number(searchParams?.page) || 1;
|
||||||
const reqClinics = await fetchReq(
|
const limit = 50;
|
||||||
`${API_URL}/api/v1/clinic/${slug}`
|
|
||||||
);
|
|
||||||
const limit=50
|
|
||||||
|
|
||||||
|
const reqClinics = await fetchReq(`${API_URL}/api/v1/clinic/${slug}`);
|
||||||
const reqDoctors = await fetchReq(
|
const reqDoctors = await fetchReq(
|
||||||
`${API_URL}/api/v1/clinic/doctor-list/${slug}?page=${page}&limit=${limit}`
|
`${API_URL}/api/v1/clinic/doctor-list/${slug}?page=${page}&limit=${limit}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
const clinic = reqClinics;
|
const clinic = reqClinics;
|
||||||
const doctors = reqDoctors?.data || [];
|
const doctors = reqDoctors?.data || [];
|
||||||
const pagedoctors=reqDoctors?.page
|
const pagedoctors = reqDoctors?.page;
|
||||||
|
|
||||||
|
const jsonLd = clinic
|
||||||
|
? {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "MedicalClinic",
|
||||||
|
name: clinic.title,
|
||||||
|
...(clinic.images_clinic?.[0] && { image: clinic.images_clinic[0] }),
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<>
|
||||||
<ClinicPage data={clinic} doctors={doctors} slug={slug} pages={pagedoctors} />
|
{jsonLd && (
|
||||||
</Layout>
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Layout>
|
||||||
|
<ClinicPage data={clinic} doctors={doctors} slug={slug} pages={pagedoctors} />
|
||||||
|
</Layout>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,23 @@ import Layout from "@/components/layout/StLayout";
|
|||||||
import { getStateInfo } from "@/lib/getStateInfo";
|
import { getStateInfo } from "@/lib/getStateInfo";
|
||||||
import { buildClinicParams } from "@/helper";
|
import { buildClinicParams } from "@/helper";
|
||||||
|
|
||||||
|
export async function generateMetadata() {
|
||||||
|
const { matchedCity, matchedState } = await getStateInfo();
|
||||||
|
const siteName = matchedCity?.site_name || "نوبت 724";
|
||||||
|
const cityName = matchedCity?.name || matchedState?.name || "";
|
||||||
|
const title = cityName
|
||||||
|
? `کلینیکهای ${cityName} | جستجو و رزرو نوبت | ${siteName}`
|
||||||
|
: `جستجوی کلینیک و مراکز درمانی | ${siteName}`;
|
||||||
|
const description = cityName
|
||||||
|
? `لیست کلینیکها و مراکز درمانی در ${cityName}. رزرو آنلاین نوبت از بهترین مراکز درمانی ${cityName}.`
|
||||||
|
: `جستجوی کلینیکها و مراکز درمانی در سراسر کشور. رزرو آنلاین نوبت سریع و آسان.`;
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
openGraph: { title, description },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default async function Clinics({ searchParams }) {
|
export default async function Clinics({ searchParams }) {
|
||||||
const awaitedSearchParams = await searchParams;
|
const awaitedSearchParams = await searchParams;
|
||||||
const { matchedCity, matchedState } = await getStateInfo();
|
const { matchedCity, matchedState } = await getStateInfo();
|
||||||
|
|||||||
@@ -1,15 +1,54 @@
|
|||||||
import DoctorPage from "@/components/doctor";
|
import DoctorPage from "@/components/doctor";
|
||||||
import Layout from "@/components/layout/StLayout";
|
import Layout from "@/components/layout/StLayout";
|
||||||
|
import { getStateInfo } from "@/lib/getStateInfo";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
async function Doctor({ params: { slug } }) {
|
export async function generateMetadata({ params }) {
|
||||||
|
const { slug } = await params;
|
||||||
|
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||||
|
const { matchedCity } = await getStateInfo();
|
||||||
|
const siteName = matchedCity?.site_name || "نوبت 724";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await axios.get(`${API_URL}/api/v1/doctor/${slug}`);
|
||||||
|
const doctor = res.data;
|
||||||
|
if (!doctor) return {};
|
||||||
|
|
||||||
|
const specialtyNames = doctor.specialties?.map((s) => s.name).join(" و ") || "";
|
||||||
|
const title = `دکتر ${doctor.name}${specialtyNames ? " | " + specialtyNames : ""} | ${siteName}`;
|
||||||
|
const description =
|
||||||
|
doctor.detail ||
|
||||||
|
`رزرو نوبت آنلاین دکتر ${doctor.name}${specialtyNames ? " متخصص " + specialtyNames : ""}${doctor.address ? " | " + doctor.address : ""}`.trim();
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
openGraph: {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
type: "profile",
|
||||||
|
images: doctor.img ? [doctor.img] : ["https://www.nobat724.com/assets/images/logo.png"],
|
||||||
|
},
|
||||||
|
twitter: {
|
||||||
|
card: "summary",
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
images: doctor.img ? [doctor.img] : ["https://www.nobat724.com/assets/images/logo.png"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function Doctor({ params }) {
|
||||||
|
const { slug } = await params;
|
||||||
let doctor = null;
|
let doctor = null;
|
||||||
let comments = null;
|
let comments = null;
|
||||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resDoctor = await axios.get(`${API_URL}/api/v1/doctor/${slug}`);
|
const resDoctor = await axios.get(`${API_URL}/api/v1/doctor/${slug}`);
|
||||||
|
|
||||||
doctor = resDoctor.data;
|
doctor = resDoctor.data;
|
||||||
if (doctor) {
|
if (doctor) {
|
||||||
const resComments = await axios.get(
|
const resComments = await axios.get(
|
||||||
@@ -17,15 +56,37 @@ async function Doctor({ params: { slug } }) {
|
|||||||
);
|
);
|
||||||
comments = resComments?.data?.data;
|
comments = resComments?.data?.data;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {}
|
||||||
// console.error("problem with req:", error.message);
|
|
||||||
// return redirect("/unauthorized");
|
const specialtyNames = doctor?.specialties?.map((s) => s.name).join(" و ") || "";
|
||||||
}
|
const jsonLd = doctor
|
||||||
|
? {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Physician",
|
||||||
|
name: `دکتر ${doctor.name}`,
|
||||||
|
...(specialtyNames && { medicalSpecialty: specialtyNames }),
|
||||||
|
...(doctor.img && { image: doctor.img }),
|
||||||
|
...(doctor.address && {
|
||||||
|
address: {
|
||||||
|
"@type": "PostalAddress",
|
||||||
|
streetAddress: doctor.address,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<>
|
||||||
<DoctorPage doctor={doctor} comments={comments} slug={slug} />
|
{jsonLd && (
|
||||||
</Layout>
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Layout>
|
||||||
|
<DoctorPage doctor={doctor} comments={comments} slug={slug} />
|
||||||
|
</Layout>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,23 @@ import { buildDoctorParams } from "@/helper";
|
|||||||
import { getStateInfo } from "@/lib/getStateInfo";
|
import { getStateInfo } from "@/lib/getStateInfo";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
|
export async function generateMetadata() {
|
||||||
|
const { matchedCity, matchedState } = await getStateInfo();
|
||||||
|
const siteName = matchedCity?.site_name || "نوبت 724";
|
||||||
|
const cityName = matchedCity?.name || matchedState?.name || "";
|
||||||
|
const title = cityName
|
||||||
|
? `پزشکان ${cityName} | جستجو و رزرو نوبت | ${siteName}`
|
||||||
|
: `جستجوی پزشک و رزرو نوبت آنلاین | ${siteName}`;
|
||||||
|
const description = cityName
|
||||||
|
? `لیست پزشکان متخصص در ${cityName}. جستجو بر اساس تخصص و منطقه. رزرو آنلاین نوبت پزشکی در ${cityName}.`
|
||||||
|
: `جستجوی پزشکان متخصص در سراسر کشور. رزرو آنلاین نوبت پزشکی سریع و آسان با نوبت 724.`;
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
openGraph: { title, description },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async function Doctors({ searchParams }) {
|
async function Doctors({ searchParams }) {
|
||||||
const awaitedSearchParams = await searchParams;
|
const awaitedSearchParams = await searchParams;
|
||||||
const { matchedCity, matchedState } = await getStateInfo();
|
const { matchedCity, matchedState } = await getStateInfo();
|
||||||
|
|||||||
+16
-2
@@ -14,13 +14,27 @@ export async function generateMetadata() {
|
|||||||
|
|
||||||
const canonicalUrl = await getCanonicalUrl();
|
const canonicalUrl = await getCanonicalUrl();
|
||||||
|
|
||||||
|
const title = matchedCity ? matchedCity.title : "نوبت724";
|
||||||
|
const description = matchedCity?.description || "نوبت 724 - سیستم آنلاین نوبتدهی برای پزشکان و کلینیکها. با استفاده از نوبت 724، به راحتی نوبت پزشکی خود را به صورت آنلاین رزرو کنید و از خدمات سریع و کارآمد ما بهرهمند شوید";
|
||||||
|
|
||||||
const baseMetadata = {
|
const baseMetadata = {
|
||||||
title: matchedCity ? matchedCity.title : "نوبت724",
|
title,
|
||||||
description: matchedCity?.description || "نوبت 724 - سیستم آنلاین نوبتدهی برای پزشکان و کلینیکها. با استفاده از نوبت 724، به راحتی نوبت پزشکی خود را به صورت آنلاین رزرو کنید و از خدمات سریع و کارآمد ما بهرهمند شوید",
|
description,
|
||||||
keywords: matchedCity
|
keywords: matchedCity
|
||||||
? matchedCity.keywords
|
? matchedCity.keywords
|
||||||
: "نوبت 724, نوبت دهی, رزرو نوبت, پزشک, پزشکی, کلینیک, بیمارستان, نوبت آنلاین, سیستم نوبت دهی, سیستم نوبت دهی آنلاین, سیستم نوبت دهی پزشکی, سیستم نوبت دهی کلینیک, سیستم نوبت دهی بیمارستان, سیستم نوبت دهی آنلاین پزشکی, سیستم نوبت دهی آنلاین کلینیک, سیستم نوبت دهی آنلاین بیمارستان",
|
: "نوبت 724, نوبت دهی, رزرو نوبت, پزشک, پزشکی, کلینیک, بیمارستان, نوبت آنلاین, سیستم نوبت دهی, سیستم نوبت دهی آنلاین, سیستم نوبت دهی پزشکی, سیستم نوبت دهی کلینیک, سیستم نوبت دهی بیمارستان, سیستم نوبت دهی آنلاین پزشکی, سیستم نوبت دهی آنلاین کلینیک, سیستم نوبت دهی آنلاین بیمارستان",
|
||||||
openGraph: {
|
openGraph: {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
type: "website",
|
||||||
|
locale: "fa_IR",
|
||||||
|
siteName: matchedCity?.site_name || "نوبت 724",
|
||||||
|
images: ["https://www.nobat724.com/assets/images/logo.png"],
|
||||||
|
},
|
||||||
|
twitter: {
|
||||||
|
card: "summary_large_image",
|
||||||
|
title,
|
||||||
|
description,
|
||||||
images: ["https://www.nobat724.com/assets/images/logo.png"],
|
images: ["https://www.nobat724.com/assets/images/logo.png"],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
+83
-88
@@ -1,7 +1,6 @@
|
|||||||
import { headers } from 'next/headers';
|
import { headers } from 'next/headers';
|
||||||
import cityData from '../data/city.json';
|
import cityData from '../data/city.json';
|
||||||
import specialtyData from '../data/specialties.json';
|
import specialtyData from '../data/specialties.json';
|
||||||
import stateData from '../data/state.json';
|
|
||||||
import {
|
import {
|
||||||
DOMAIN_CONFIG,
|
DOMAIN_CONFIG,
|
||||||
isMainDomain,
|
isMainDomain,
|
||||||
@@ -11,93 +10,103 @@ import {
|
|||||||
getBaseUrl
|
getBaseUrl
|
||||||
} from '../utils/sitemap';
|
} from '../utils/sitemap';
|
||||||
|
|
||||||
// Get current domain from headers
|
|
||||||
function getCurrentDomain() {
|
function getCurrentDomain() {
|
||||||
try {
|
try {
|
||||||
const headersList = headers();
|
const headersList = headers();
|
||||||
const host = headersList.get('host');
|
const host = headersList.get('host');
|
||||||
return host || DOMAIN_CONFIG.MAIN_DOMAIN;
|
return host || DOMAIN_CONFIG.MAIN_DOMAIN;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Fallback for static generation
|
|
||||||
console.warn('Headers not available during static generation, using main domain');
|
console.warn('Headers not available during static generation, using main domain');
|
||||||
return DOMAIN_CONFIG.MAIN_DOMAIN;
|
return DOMAIN_CONFIG.MAIN_DOMAIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get city data based on domain
|
|
||||||
function getCityByDomain(domain) {
|
function getCityByDomain(domain) {
|
||||||
return cityData.find(city => city.domain === domain);
|
return cityData.find(city => city.domain === domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get state name by province_id
|
|
||||||
function getStateById(provinceId) {
|
|
||||||
return stateData.find(state => state.id === provinceId)?.name || '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate static pages URLs
|
|
||||||
function getStaticPages(baseUrl) {
|
function getStaticPages(baseUrl) {
|
||||||
return [
|
return [
|
||||||
{
|
{ url: baseUrl, lastModified: new Date(), changeFrequency: 'daily', priority: 1 },
|
||||||
url: baseUrl,
|
{ url: `${baseUrl}/about-us`, lastModified: new Date(), changeFrequency: 'monthly', priority: 0.8 },
|
||||||
lastModified: new Date(),
|
{ url: `${baseUrl}/contact-us`, lastModified: new Date(), changeFrequency: 'monthly', priority: 0.8 },
|
||||||
changeFrequency: 'daily',
|
{ url: `${baseUrl}/blogs`, lastModified: new Date(), changeFrequency: 'weekly', priority: 0.9 },
|
||||||
priority: 1,
|
{ url: `${baseUrl}/doctors`, lastModified: new Date(), changeFrequency: 'daily', priority: 0.9 },
|
||||||
},
|
{ url: `${baseUrl}/clinics`, lastModified: new Date(), changeFrequency: 'daily', priority: 0.9 },
|
||||||
{
|
{ url: `${baseUrl}/specialties`, lastModified: new Date(), changeFrequency: 'weekly', priority: 0.9 },
|
||||||
url: `${baseUrl}/about-us`,
|
|
||||||
lastModified: new Date(),
|
|
||||||
changeFrequency: 'monthly',
|
|
||||||
priority: 0.8,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: `${baseUrl}/contact-us`,
|
|
||||||
lastModified: new Date(),
|
|
||||||
changeFrequency: 'monthly',
|
|
||||||
priority: 0.8,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: `${baseUrl}/blogs`,
|
|
||||||
lastModified: new Date(),
|
|
||||||
changeFrequency: 'weekly',
|
|
||||||
priority: 0.9,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: `${baseUrl}/doctors`,
|
|
||||||
lastModified: new Date(),
|
|
||||||
changeFrequency: 'daily',
|
|
||||||
priority: 0.9,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: `${baseUrl}/clinics`,
|
|
||||||
lastModified: new Date(),
|
|
||||||
changeFrequency: 'daily',
|
|
||||||
priority: 0.9,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: `${baseUrl}/specialties`,
|
|
||||||
lastModified: new Date(),
|
|
||||||
changeFrequency: 'weekly',
|
|
||||||
priority: 0.9,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate doctor search URLs based on domain
|
async function getDoctorUrls(baseUrl) {
|
||||||
function getDoctorSearchUrls(domain, baseUrl) {
|
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||||
// Return empty array - no URLs with search parameters
|
if (!API_URL) return [];
|
||||||
return [];
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${API_URL}/api/v1/doctors?page=1&limit=500`, {
|
||||||
|
next: { revalidate: 3600 },
|
||||||
|
});
|
||||||
|
if (!res.ok) return [];
|
||||||
|
const data = await res.json();
|
||||||
|
const doctors = data?.data || data?.doctors || data || [];
|
||||||
|
return doctors
|
||||||
|
.filter((d) => d?.uuid)
|
||||||
|
.map((d) => ({
|
||||||
|
url: `${baseUrl}/doctor/${d.uuid}`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'weekly',
|
||||||
|
priority: 0.8,
|
||||||
|
}));
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate clinic search URLs
|
async function getClinicUrls(baseUrl) {
|
||||||
function getClinicSearchUrls(domain, baseUrl) {
|
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||||
// Return empty array - no URLs with search parameters
|
if (!API_URL) return [];
|
||||||
return [];
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${API_URL}/api/v1/clinics?page=1&limit=500`, {
|
||||||
|
next: { revalidate: 3600 },
|
||||||
|
});
|
||||||
|
if (!res.ok) return [];
|
||||||
|
const data = await res.json();
|
||||||
|
const clinics = data?.data || data?.clinics || data || [];
|
||||||
|
return clinics
|
||||||
|
.filter((c) => c?.uuid)
|
||||||
|
.map((c) => ({
|
||||||
|
url: `${baseUrl}/clinic/${c.uuid}`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'weekly',
|
||||||
|
priority: 0.7,
|
||||||
|
}));
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate specialty pages URLs
|
async function getBlogUrls(baseUrl) {
|
||||||
function getSpecialtyUrls(domain, baseUrl) {
|
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||||
// Return empty array - no specialty URLs
|
if (!API_URL) return [];
|
||||||
return [];
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${API_URL}/api/v1/blogs?page=1&limit=200`, {
|
||||||
|
next: { revalidate: 3600 },
|
||||||
|
});
|
||||||
|
if (!res.ok) return [];
|
||||||
|
const data = await res.json();
|
||||||
|
const blogs = data?.blogs || data?.data || data || [];
|
||||||
|
return blogs
|
||||||
|
.filter((b) => b?.slug || b?.uuid)
|
||||||
|
.map((b) => ({
|
||||||
|
url: `${baseUrl}/blog/${b.slug || b.uuid}`,
|
||||||
|
lastModified: b.created ? new Date(b.created) : new Date(),
|
||||||
|
changeFrequency: 'monthly',
|
||||||
|
priority: 0.6,
|
||||||
|
}));
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function sitemap() {
|
export default async function sitemap() {
|
||||||
@@ -105,34 +114,20 @@ export default async function sitemap() {
|
|||||||
const domain = getCurrentDomain();
|
const domain = getCurrentDomain();
|
||||||
const baseUrl = getBaseUrl(domain);
|
const baseUrl = getBaseUrl(domain);
|
||||||
|
|
||||||
console.log(`Generating sitemap for domain: ${domain}, baseUrl: ${baseUrl}`);
|
const [staticPages, doctorUrls, clinicUrls, blogUrls] = await Promise.all([
|
||||||
console.log(`City data length: ${cityData.length}, Specialty data length: ${specialtyData.length}`);
|
Promise.resolve(getStaticPages(baseUrl)),
|
||||||
|
getDoctorUrls(baseUrl),
|
||||||
|
getClinicUrls(baseUrl),
|
||||||
|
getBlogUrls(baseUrl),
|
||||||
|
]);
|
||||||
|
|
||||||
// Get all URLs
|
const allUrls = [...staticPages, ...doctorUrls, ...clinicUrls, ...blogUrls];
|
||||||
const staticPages = getStaticPages(baseUrl);
|
|
||||||
const doctorSearchUrls = getDoctorSearchUrls(domain, baseUrl);
|
|
||||||
const clinicSearchUrls = getClinicSearchUrls(domain, baseUrl);
|
|
||||||
const specialtyUrls = getSpecialtyUrls(domain, baseUrl);
|
|
||||||
|
|
||||||
console.log(`Generated URLs - Static: ${staticPages.length}, Doctors: ${doctorSearchUrls.length}, Clinics: ${clinicSearchUrls.length}, Specialties: ${specialtyUrls.length}`);
|
return allUrls.filter(
|
||||||
|
(item, index, arr) => arr.findIndex((i) => i.url === item.url) === index
|
||||||
// Combine all URLs
|
|
||||||
const allUrls = [
|
|
||||||
...staticPages,
|
|
||||||
...doctorSearchUrls,
|
|
||||||
...clinicSearchUrls,
|
|
||||||
...specialtyUrls,
|
|
||||||
];
|
|
||||||
|
|
||||||
// Remove duplicates based on URL
|
|
||||||
const uniqueUrls = allUrls.filter((item, index, arr) =>
|
|
||||||
arr.findIndex(i => i.url === item.url) === index
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
return uniqueUrls;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error generating sitemap:', error);
|
console.error('Error generating sitemap:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
import Layout from "@/components/layout/StLayout";
|
import Layout from "@/components/layout/StLayout";
|
||||||
import SpecialtiesPage from "@/components/specialties";
|
import SpecialtiesPage from "@/components/specialties";
|
||||||
|
import { getStateInfo } from "@/lib/getStateInfo";
|
||||||
|
|
||||||
|
export async function generateMetadata() {
|
||||||
|
const { matchedCity } = await getStateInfo();
|
||||||
|
const siteName = matchedCity?.site_name || "نوبت 724";
|
||||||
|
const cityName = matchedCity?.name || "";
|
||||||
|
const title = cityName
|
||||||
|
? `تخصصهای پزشکی در ${cityName} | ${siteName}`
|
||||||
|
: `تخصصهای پزشکی | ${siteName}`;
|
||||||
|
const description = `لیست کامل تخصصهای پزشکی${cityName ? " در " + cityName : ""}. رزرو نوبت از متخصصین مختلف به صورت آنلاین.`;
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
openGraph: { title, description },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function Specialties() {
|
function Specialties() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user