diff --git a/app/blog/sitemap.js b/app/blog/sitemap.js deleted file mode 100644 index 41c30f3..0000000 --- a/app/blog/sitemap.js +++ /dev/null @@ -1,49 +0,0 @@ -const API_URL = process.env.NEXT_PUBLIC_API_URL; -const MAIN_DOMAIN = 'https://nobat724.com'; -const PER_SITEMAP = 1000; - -function toSafeDate(value) { - if (!value) return new Date(); - const d = new Date(value); - return isNaN(d.getTime()) ? new Date() : d; -} - -export async function generateSitemaps() { - if (!API_URL) return [{ id: 0 }]; - - try { - const res = await fetch(`${API_URL}/api/v1/blogs?page=1&limit=1`, { - next: { revalidate: 86400 }, - }); - if (!res.ok) return [{ id: 0 }]; - const json = await res.json(); - const total = json?.meta?.totalRecords || 0; - const pageCount = Math.max(1, Math.ceil(total / PER_SITEMAP)); - return Array.from({ length: pageCount }, (_, id) => ({ id })); - } catch { - return [{ id: 0 }]; - } -} - -export default async function sitemap({ id }) { - if (!API_URL) return []; - - try { - const res = await fetch(`${API_URL}/api/v1/blogs?page=${id + 1}&limit=${PER_SITEMAP}`, { - next: { revalidate: 3600 }, - }); - if (!res.ok) return []; - const json = await res.json(); - const blogs = json?.data || []; - return blogs - .filter((b) => b?.slug || b?.uuid) - .map((b) => ({ - url: `${MAIN_DOMAIN}/blog/${b.slug || b.uuid}`, - lastModified: toSafeDate(b.created), - changeFrequency: 'monthly', - priority: 0.6, - })); - } catch { - return []; - } -} diff --git a/app/clinic/sitemap.js b/app/clinic/sitemap.js deleted file mode 100644 index 3855b58..0000000 --- a/app/clinic/sitemap.js +++ /dev/null @@ -1,43 +0,0 @@ -const API_URL = process.env.NEXT_PUBLIC_API_URL; -const MAIN_DOMAIN = 'https://nobat724.com'; -const PER_SITEMAP = 1000; - -export async function generateSitemaps() { - if (!API_URL) return [{ id: 0 }]; - - try { - const res = await fetch(`${API_URL}/api/v1/clinics?page=1&limit=1`, { - next: { revalidate: 86400 }, - }); - if (!res.ok) return [{ id: 0 }]; - const json = await res.json(); - const total = json?.meta?.totalRecords || 0; - const pageCount = Math.max(1, Math.ceil(total / PER_SITEMAP)); - return Array.from({ length: pageCount }, (_, id) => ({ id })); - } catch { - return [{ id: 0 }]; - } -} - -export default async function sitemap({ id }) { - if (!API_URL) return []; - - try { - const res = await fetch(`${API_URL}/api/v1/clinics?page=${id + 1}&limit=${PER_SITEMAP}`, { - next: { revalidate: 3600 }, - }); - if (!res.ok) return []; - const json = await res.json(); - const clinics = json?.data || []; - return clinics - .filter((c) => c?.uuid) - .map((c) => ({ - url: `${MAIN_DOMAIN}/clinic/${c.uuid}`, - lastModified: new Date(), - changeFrequency: 'weekly', - priority: 0.7, - })); - } catch { - return []; - } -} diff --git a/app/doctor/[slug]/page.js b/app/doctor/[slug]/page.js index b082f44..07d06e5 100644 --- a/app/doctor/[slug]/page.js +++ b/app/doctor/[slug]/page.js @@ -47,7 +47,7 @@ export async function generateMetadata({ params }) { const description = doctor.detail || `رزرو نوبت آنلاین دکتر ${doctor.name}${specialtyNames ? " متخصص " + specialtyNames : ""}${doctor.address ? " | " + doctor.address : ""}`.trim(); - const image = imageUrl(doctor.img) || FALLBACK_IMG; + const image = imageUrl(doctor.img?.[0]?.url) || FALLBACK_IMG; return { title, @@ -103,10 +103,10 @@ async function Doctor({ params }) { name: `دکتر ${doctor.name}`, url: `https://www.nobat724.com/doctor/${doctor.uuid}`, ...(specialtyNames && { medicalSpecialty: specialtyNames }), - ...(doctor.img && { + ...(doctor.img?.[0]?.url && { image: { "@type": "ImageObject", - url: imageUrl(doctor.img), + url: imageUrl(doctor.img[0].url), }, }), ...(Number(doctor.point) > 0 && { diff --git a/app/doctor/sitemap.js b/app/doctor/sitemap.js deleted file mode 100644 index 3edabf7..0000000 --- a/app/doctor/sitemap.js +++ /dev/null @@ -1,43 +0,0 @@ -const API_URL = process.env.NEXT_PUBLIC_API_URL; -const MAIN_DOMAIN = 'https://nobat724.com'; -const PER_SITEMAP = 1000; - -export async function generateSitemaps() { - if (!API_URL) return [{ id: 0 }]; - - try { - const res = await fetch(`${API_URL}/api/v1/doctors?page=1&limit=1`, { - next: { revalidate: 86400 }, - }); - if (!res.ok) return [{ id: 0 }]; - const json = await res.json(); - const total = json?.meta?.totalRecords || 0; - const pageCount = Math.max(1, Math.ceil(total / PER_SITEMAP)); - return Array.from({ length: pageCount }, (_, id) => ({ id })); - } catch { - return [{ id: 0 }]; - } -} - -export default async function sitemap({ id }) { - if (!API_URL) return []; - - try { - const res = await fetch(`${API_URL}/api/v1/doctors?page=${id + 1}&limit=${PER_SITEMAP}`, { - next: { revalidate: 3600 }, - }); - if (!res.ok) return []; - const json = await res.json(); - const doctors = json?.data || []; - return doctors - .filter((d) => d?.uuid) - .map((d) => ({ - url: `${MAIN_DOMAIN}/doctor/${d.uuid}`, - lastModified: new Date(), - changeFrequency: 'weekly', - priority: 0.8, - })); - } catch { - return []; - } -} diff --git a/app/sitemap.js b/app/sitemap.js index 658e5e4..8249457 100644 --- a/app/sitemap.js +++ b/app/sitemap.js @@ -1,6 +1,12 @@ import { headers } from 'next/headers'; import { getBaseUrl } from '../utils/sitemap'; +function toSafeDate(value) { + if (!value) return new Date(); + const d = new Date(value); + return isNaN(d.getTime()) ? new Date() : d; +} + const MAIN_DOMAIN = 'nobat724.com'; function getCurrentDomain() { @@ -27,11 +33,95 @@ function getStaticPages(baseUrl) { ]; } +async function getDoctorUrls(baseUrl) { + const API_URL = process.env.NEXT_PUBLIC_API_URL; + if (!API_URL) return []; + + try { + const res = await fetch(`${API_URL}/api/v1/doctors?page=1&limit=2000`, { + 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: NOW, + changeFrequency: 'weekly', + priority: 0.8, + })); + } catch { + return []; + } +} + +async function getClinicUrls(baseUrl) { + const API_URL = process.env.NEXT_PUBLIC_API_URL; + if (!API_URL) return []; + + try { + const res = await fetch(`${API_URL}/api/v1/clinics?page=1&limit=2000`, { + 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: NOW, + changeFrequency: 'weekly', + priority: 0.7, + })); + } catch { + return []; + } +} + +async function getBlogUrls(baseUrl) { + const API_URL = process.env.NEXT_PUBLIC_API_URL; + if (!API_URL) return []; + + try { + const res = await fetch(`${API_URL}/api/v1/blogs?page=1&limit=2000`, { + 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: toSafeDate(b.created), + changeFrequency: 'monthly', + priority: 0.6, + })); + } catch { + return []; + } +} + export default async function sitemap() { try { const domain = getCurrentDomain(); const baseUrl = getBaseUrl(domain); - return getStaticPages(baseUrl); + + const [staticPages, doctorUrls, clinicUrls, blogUrls] = await Promise.all([ + Promise.resolve(getStaticPages(baseUrl)), + getDoctorUrls(baseUrl), + getClinicUrls(baseUrl), + getBlogUrls(baseUrl), + ]); + + const allUrls = [...staticPages, ...doctorUrls, ...clinicUrls, ...blogUrls]; + + return allUrls.filter( + (item, index, arr) => arr.findIndex((i) => i.url === item.url) === index + ); } catch (error) { console.error('Error generating sitemap:', error); return []; diff --git a/lib/refreshCookie.js b/lib/refreshCookie.js index 12d888e..f345cc7 100644 --- a/lib/refreshCookie.js +++ b/lib/refreshCookie.js @@ -9,10 +9,12 @@ function cookieDomain(host) { return "." + hostname.split(".").slice(-2).join("."); } +const isSecure = process.env.NODE_ENV === "production"; + export function setRefreshCookie(response, refreshToken, host, maxAge = 60 * 60 * 24 * 30) { response.cookies.set(COOKIE_NAME, refreshToken, { httpOnly: true, - secure: true, + secure: isSecure, sameSite: "lax", path: "/", maxAge, @@ -23,7 +25,7 @@ export function setRefreshCookie(response, refreshToken, host, maxAge = 60 * 60 export function clearRefreshCookie(response, host) { response.cookies.set(COOKIE_NAME, "", { httpOnly: true, - secure: true, + secure: isSecure, sameSite: "lax", path: "/", maxAge: 0,