Files
sanihome/src/lib/meshkee.ts
T
Alireza HassaniandCursor 1c2d1eb31c Wire homepage images to Meshkee slots and publish the catalog.
The dashboard can refresh these keys from the live site.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 09:55:05 +03:30

105 lines
2.5 KiB
TypeScript

export type StaticImage = {
id: string;
url?: string | null;
title?: 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;
kind: "single" | "list";
label?: string;
aspectRatio?: string;
recommendedWidth?: number;
sortOrder?: number;
images?: StaticImage[];
};
export const STATIC_IMAGE_KEYS = {
slider: "slider",
bannerInSpecialSale: "banner-in-special-sale",
categories: "categories",
twoBannerRow: "two-banner-row",
} as const;
export const STATIC_IMAGE_SLOT_CATALOG = [
{
key: STATIC_IMAGE_KEYS.slider,
label: "Homepage slider",
kind: "list" as const,
pageKey: "home",
aspectRatio: "16:9",
itemCount: null,
recommendedWidth: 1440,
},
{
key: STATIC_IMAGE_KEYS.bannerInSpecialSale,
label: "Banner in special sale",
kind: "single" as const,
pageKey: "home",
aspectRatio: "12:19",
itemCount: 1,
recommendedWidth: 480,
},
{
key: STATIC_IMAGE_KEYS.categories,
label: "Featured category images",
kind: "list" as const,
pageKey: "home",
aspectRatio: "1:1",
itemCount: null,
recommendedWidth: 400,
},
{
key: STATIC_IMAGE_KEYS.twoBannerRow,
label: "Two banner row",
kind: "list" as const,
pageKey: "home",
aspectRatio: "16:5",
itemCount: 2,
recommendedWidth: 1440,
},
];
const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
const DOMAIN = process.env.NEXT_PUBLIC_DOMAIN ?? "";
export async function getStaticImageSlots(): Promise<StaticImageSlot[]> {
if (!API_BASE || !DOMAIN) return [];
try {
const res = await fetch(
`${API_BASE}/tenants/${DOMAIN}/website/static-images`,
{ cache: "no-store" },
);
if (!res.ok) return [];
const data: { items?: StaticImageSlot[] } = await res.json();
return data.items ?? [];
} catch {
return [];
}
}
export function imagesForSlot(
slots: StaticImageSlot[],
key: string,
): StaticImageWithUrl[] {
const images = slots.find((slot) => slot.key === key)?.images ?? [];
return [...images]
.filter((image): image is StaticImageWithUrl => Boolean(image.url))
.sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0));
}
export function firstImageForSlot(
slots: StaticImageSlot[],
key: string,
): StaticImageWithUrl | undefined {
return imagesForSlot(slots, key)[0];
}