Files
studio-hom/src/lib/static-images.ts
T

131 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<string, { images: StaticImage[]; aspectRatio: string | null }>;
/** `GET /tenants/{domain}/website/static-images?pageKey=…` grouped by slot key. */
export const getPageSlots = cache(async (pageKey: string): Promise<PageSlots> => {
const data = await meshkeeGet<StaticImagesResponse>(
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;
}