- Updated `getStateInfo` to fetch site context for domains not in city.json, returning `repContext` with representative details. - Implemented caching for site context requests to optimize performance. - Modified doctor and clinic listing pages to pass the `domain` parameter when fetching data for global representatives. - Adjusted metadata generation in layout and pages to reflect representative branding based on `repContext`. - Added documentation for the new functionality in `.claude/prompt/global-rep-domain-site.md`.
69 lines
2.3 KiB
JavaScript
69 lines
2.3 KiB
JavaScript
import { headers } from "next/headers";
|
|
|
|
// Data
|
|
import citiesData from "@/data/city.json";
|
|
import statesData from "@/data/state.json";
|
|
import { fetchReq } from "@/lib/req";
|
|
|
|
import { ROOT_CITY_ID, isRootCity } from "@/lib/rootCity";
|
|
export { ROOT_CITY_ID, isRootCity };
|
|
|
|
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
|
|
|
// دامنههای خارج از city.json (دامنه اختصاصی نمایندگان سراسری) از backend پرسیده میشوند
|
|
// (GET /api/v1/site-context). cache ماژولسطح تا هر render یک درخواست نزند؛
|
|
// خطای شبکه هرگز صفحه را نمیشکند (null = مثل دامنه ناشناخته).
|
|
const SITE_CONTEXT_TTL_MS = 5 * 60 * 1000;
|
|
const siteContextCache = new Map();
|
|
|
|
async function fetchSiteContext(host) {
|
|
if (!host || host === "localhost" || host === "127.0.0.1" || !API_URL) return null;
|
|
|
|
const cached = siteContextCache.get(host);
|
|
if (cached && cached.expires > Date.now()) return cached.value;
|
|
|
|
let value = null;
|
|
try {
|
|
const json = await fetchReq(
|
|
`${API_URL}/api/v1/site-context?domain=${encodeURIComponent(host)}`
|
|
);
|
|
if (json?.data?.type === "representation") {
|
|
value = json.data.representation; // { uuid, full_name, is_global }
|
|
}
|
|
} catch {
|
|
value = null;
|
|
}
|
|
|
|
siteContextCache.set(host, { value, expires: Date.now() + SITE_CONTEXT_TTL_MS });
|
|
return value;
|
|
}
|
|
|
|
export async function getStateInfo() {
|
|
const headersList = await headers();
|
|
|
|
const rawHost = headersList.get("host") || "";
|
|
const host = rawHost.split(":")[0];
|
|
const subdomain = host.split(".")[0];
|
|
|
|
// Match city by domain (supports both full domain and subdomain)
|
|
const matchedCity = citiesData.find((city) => {
|
|
const cityDomain = city.domain.split(".")[0]; // Extract subdomain from domain (e.g., "yasuj-nobat" from "yasuj-nobat.ir")
|
|
return cityDomain === subdomain;
|
|
});
|
|
|
|
const matchedState =
|
|
matchedCity &&
|
|
statesData.find((state) => state.id === matchedCity.province_id);
|
|
|
|
// فقط وقتی هیچ شهری match نشد سراغ backend میرویم — رفتار دامنههای شهری دستنخورده میماند.
|
|
const repContext = matchedCity ? null : await fetchSiteContext(host);
|
|
|
|
return {
|
|
matchedCity,
|
|
matchedState,
|
|
isRoot: isRootCity(matchedCity),
|
|
repContext,
|
|
host,
|
|
};
|
|
}
|