import { API } from "./site"; export type StaticImage = { id: string; url?: string | null; titleFa?: string | null; titleEn?: string | null; subtext?: string | null; linkUrl?: string | null; width?: number | null; height?: number | null; sortOrder?: number; }; export type StaticImageWithUrl = StaticImage & { url: string }; export type StaticImageSlot = { id: string; key: string; pageKey?: string; kind: "single" | "list"; label?: string; aspectRatio?: string; recommendedWidth?: number; itemCount?: number | null; sortOrder?: number; images?: StaticImage[]; }; export type StaticImageCatalogSlot = { key: string; label: string; kind: "single" | "list"; pageKey: string; aspectRatio: string; itemCount: number | null; recommendedWidth: number; }; /** * Slot keys the dashboard Refresh button imports from * GET /meshkee/static-image-slots. Keep aspectRatio + recommendedWidth in * sync with the live CSS when a slot's size changes. */ export const STATIC_IMAGE_KEYS = { slider: "slider", bannersBelowSlider: "banners-below-slider", categories: "categories", fourBannerSection: "four-banner-section", threeBannerRow: "three-banner-row", aboutUsImage: "about-us-image", } as const; export const STATIC_IMAGE_SLOT_CATALOG: StaticImageCatalogSlot[] = [ { key: STATIC_IMAGE_KEYS.slider, label: "Homepage slider", kind: "list", pageKey: "home", aspectRatio: "21:8", itemCount: null, recommendedWidth: 1200, }, { key: STATIC_IMAGE_KEYS.bannersBelowSlider, label: "Banners below slider", kind: "list", pageKey: "home", aspectRatio: "13:5", itemCount: 2, recommendedWidth: 600, }, { key: STATIC_IMAGE_KEYS.categories, label: "Homepage categories", kind: "list", pageKey: "home", aspectRatio: "1:1", itemCount: null, recommendedWidth: 160, }, { key: STATIC_IMAGE_KEYS.fourBannerSection, label: "Four banner section", kind: "list", pageKey: "home", aspectRatio: "21:9", itemCount: 4, recommendedWidth: 600, }, { key: STATIC_IMAGE_KEYS.threeBannerRow, label: "Three banner row", kind: "list", pageKey: "home", aspectRatio: "12:5", itemCount: 3, recommendedWidth: 480, }, { key: STATIC_IMAGE_KEYS.aboutUsImage, label: "About us image", kind: "single", pageKey: "home", aspectRatio: "8:5", itemCount: 1, recommendedWidth: 720, }, ]; export function slotAspectStyle( ratio?: string | null, fallback?: string, ): { aspectRatio: string } | undefined { const value = ratio?.trim() || fallback; if (!value) return undefined; return { aspectRatio: value.replace(":", " / ") }; } export function slotAlt(image: StaticImage, fallback = ""): string { return image.titleFa?.trim() || image.titleEn?.trim() || fallback; } export function imagesForSlot(slots: StaticImageSlot[], key: string): StaticImageWithUrl[] { const slot = slots.find((item) => item.key === key); const raw = slot?.images ?? []; const sorted = [...raw].sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0)); const result: StaticImageWithUrl[] = []; for (const image of sorted) { const url = typeof image.url === "string" ? image.url.trim() : ""; if (!url) continue; result.push({ ...image, url }); } if (slot?.kind === "single") return result.slice(0, 1); return result; } export function firstImageForSlot( slots: StaticImageSlot[], key: string, ): StaticImageWithUrl | undefined { return imagesForSlot(slots, key)[0]; } export function slotByKey(slots: StaticImageSlot[], key: string): StaticImageSlot | undefined { return slots.find((slot) => slot.key === key); } export async function getStaticImageSlots(pageKey?: string): Promise { try { const url = new URL(`${API.base}/tenants/${API.domain}/website/static-images`); if (pageKey) url.searchParams.set("pageKey", pageKey); const response = await fetch(url, { next: { revalidate: 120 } }); if (!response.ok) return []; const data = (await response.json()) as { items?: StaticImageSlot[] }; return data.items ?? []; } catch { return []; } } export async function getStaticImageSlot(key: string): Promise { try { const url = new URL(`${API.base}/tenants/${API.domain}/website/static-images/${key}`); const response = await fetch(url, { next: { revalidate: 120 } }); if (!response.ok) return null; return (await response.json()) as StaticImageSlot; } catch { return null; } }