import { cache } from "react"; import { meshkeeGet, tenantPath } from "@/lib/meshkee"; export type StaticImage = { url?: string | null; titleFa?: string | null; titleEn?: string | null; subtext?: string | null; linkUrl?: string | null; }; export type StaticImageSlot = { key: string; label: string; kind: "single" | "list"; pageKey: string; aspectRatio: string; itemCount: number | null; recommendedWidth: number; }; /** * Catalog served at `GET /meshkee/static-image-slots`. * Keep `aspectRatio` / `recommendedWidth` in sync with the on-page frames — * if a frame’s size or ratio changes in development, update the matching entry here. */ export const STATIC_IMAGE_SLOTS: StaticImageSlot[] = [ { key: "slider", label: "اسلایدر تمام‌صفحه صفحه اول (قابل تکرار)", kind: "list", pageKey: "home", aspectRatio: "16:9", itemCount: null, recommendedWidth: 1920, }, { key: "four-category", label: "چهار خدمت / تخصص صفحه اول", kind: "list", pageKey: "home", aspectRatio: "3:4", itemCount: 4, recommendedWidth: 900, }, { key: "project-images", label: "پروژه‌های منتخب صفحه اول (میسونری — اندازه آزاد)", kind: "list", pageKey: "home", aspectRatio: "3:4", itemCount: null, recommendedWidth: 1200, }, { key: "sticky-frame-bg", label: "پس‌زمینه فریم استیکی OpeningFrame", kind: "single", pageKey: "home", aspectRatio: "16:9", itemCount: 1, recommendedWidth: 1920, }, { key: "instagram-row", label: "فریم صفحه اینستاگرام (اسکرین‌شات موبایل)", kind: "single", pageKey: "home", aspectRatio: "9:16", itemCount: 1, recommendedWidth: 720, }, { key: "brands", label: "لوگوی برندها / همکاران (قابل تکرار)", kind: "list", pageKey: "home", aspectRatio: "3:2", itemCount: null, recommendedWidth: 480, }, { key: "about-us-image", label: "تصاویر درباره ما (۲ تصویر)", kind: "list", pageKey: "about", aspectRatio: "16:9", itemCount: 2, recommendedWidth: 1600, }, ]; type StaticImagesResponse = { items?: { key: string; aspectRatio?: string | null; images?: (StaticImage & { sortOrder?: number })[]; }[]; }; export type PageSlots = Record; /** `GET /tenants/{domain}/website/static-images?pageKey=…` grouped by slot key. */ export const getPageSlots = cache(async (pageKey: string): Promise => { const data = await meshkeeGet( tenantPath(`/website/static-images?pageKey=${encodeURIComponent(pageKey)}`), {}, ); const grouped: PageSlots = {}; for (const slot of data.items ?? []) { const images = (slot.images ?? []) .filter((image) => image?.url) .sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0)); if (images.length) grouped[slot.key] = { images, aspectRatio: slot.aspectRatio ?? null }; } return grouped; }); /** CSS `aspect-ratio` for a slot: API value first, then the local catalog. */ export function slotRatio(key: string, slots?: PageSlots) { const fromApi = slots?.[key]?.aspectRatio; const fromCatalog = STATIC_IMAGE_SLOTS.find((entry) => entry.key === key)?.aspectRatio; return (fromApi || fromCatalog || "4:3").replace(":", " / "); } /** Images for a slot, or the local fallback list when CMS has none. */ export function slotImages(key: string, slots: PageSlots, fallback: StaticImage[]) { return slots[key]?.images?.length ? slots[key].images : fallback; }