import { articles, products } from "./data.js"; export const MESHKEE_DOMAIN = "asphp.ir"; export const MESHKEE_API = "https://api.meshkee.com/api/v1"; export const CUSTOMER_URL = "https://customer.asphp.ir.com"; export const DEFAULT_FAVICON = "/assets/favicon.png"; async function fetchJson(path, options = {}) { const response = await fetch(`${MESHKEE_API}${path}`, { cache: "no-store", ...options, headers: { Accept: "application/json", ...(options.body ? { "Content-Type": "application/json" } : {}), ...(options.headers || {}) } }); if (!response.ok) { throw new Error(`Meshkee API ${response.status}: ${path}`); } return response.json(); } export async function getTenant() { try { return await fetchJson(`/tenants/${MESHKEE_DOMAIN}`); } catch { return { id: "33", domain: MESHKEE_DOMAIN, nameFa: "تجهیزات سرور پارس" }; } } export async function getBranding() { try { const branding = await fetchJson(`/tenants/${MESHKEE_DOMAIN}/website/favicon`); return { faviconUrl: branding?.faviconUrl || DEFAULT_FAVICON, logoUrl: branding?.logoUrl || "/assets/logo.png", logoDarkUrl: branding?.logoDarkUrl || branding?.logoUrl || "/assets/logo.png", hasDedicatedFavicon: Boolean(branding?.hasDedicatedFavicon) }; } catch { return { faviconUrl: DEFAULT_FAVICON, logoUrl: "/assets/logo.png", logoDarkUrl: "/assets/logo.png", hasDedicatedFavicon: false }; } } export async function getStoreItems({ page = 1, pageSize = 12, query = "" } = {}) { try { const search = new URLSearchParams({ page: String(page), pageSize: String(pageSize) }); if (query) search.set("name", query); const data = await fetchJson(`/tenants/${MESHKEE_DOMAIN}/store-items?${search}`); const items = (data.items || []).map(normalizeStoreItem); if (items.length) return { ...data, items }; } catch {} const items = fallbackStoreItems(); return { items, total: items.length, page, pageSize, fallback: true }; } export async function getStoreItem(id) { try { const data = await fetchJson(`/tenants/${MESHKEE_DOMAIN}/store-items/${encodeURIComponent(id)}`); if (data.variant) return normalizeStoreItem(data.variant); } catch {} return fallbackStoreItems().find((item) => item.id === id || item.slug === id) || fallbackStoreItems()[0]; } export async function getBlogs({ page = 1, pageSize = 12 } = {}) { try { const data = await fetchJson(`/tenants/${MESHKEE_DOMAIN}/blogs?page=${page}&pageSize=${pageSize}`); const items = (data.items || []).map(normalizeBlog); if (items.length) return { ...data, items }; } catch {} const items = articles.map((article, index) => ({ id: `local-blog-${index + 1}`, slug: `local-blog-${index + 1}`, title: article.title, date: article.date, image: article.image, abstract: article.abstract, html: `

${article.abstract}

` })); return { items, total: items.length, page, pageSize, fallback: true }; } export async function getStaticImageSlots({ pageKey = "home" } = {}) { const fetchSlots = async (filterPageKey) => { const search = filterPageKey ? `?pageKey=${encodeURIComponent(filterPageKey)}` : ""; const data = await fetchJson(`/tenants/${MESHKEE_DOMAIN}/website/static-images${search}`); return Array.isArray(data.items) ? data.items.map(normalizeStaticImageSlot) : []; }; try { const pageSlots = await fetchSlots(pageKey); if (pageSlots.length || !pageKey) return pageSlots; return await fetchSlots(""); } catch { return []; } } export async function getStaticImageSlotMap(pageKey = "home") { const slots = await getStaticImageSlots({ pageKey }); return Object.fromEntries(slots.map((slot) => [slot.key, slot])); } export function staticSlotImages(slotMap, key, fallbackImages = []) { const slot = slotMap?.[key]; const images = slot?.images?.length ? slot.images : fallbackImages; const pickedImages = slot?.kind === "single" ? images.slice(0, 1) : images; return pickedImages.map((image, index) => { const normalized = typeof image === "string" ? { url: image } : image; return { url: normalized.url || normalized.image || normalized.imageUrl || normalized.src, href: normalized.linkUrl || normalized.href || normalized.link, titleFa: normalized.titleFa || normalized.nameFa || normalized.title || normalized.alt, titleEn: normalized.titleEn || normalized.nameEn || "", subtext: normalized.subtext || normalized.description || "", alt: normalized.alt || normalized.titleFa || normalized.title || slot?.label || "", width: normalized.width, height: normalized.height, aspectRatio: cssAspectRatio(slot?.aspectRatio || normalized.aspectRatio), sortOrder: normalized.sortOrder ?? index }; }).filter((image) => image.url); } export async function getBlog(slug) { try { const data = await fetchJson(`/tenants/${MESHKEE_DOMAIN}/blogs/${encodeURIComponent(slug)}`); if (data.blog) return normalizeBlog(data.blog); } catch {} const blogs = await getBlogs(); return blogs.items.find((blog) => blog.slug === slug || blog.id === slug) || blogs.items[0]; } export async function submitContact(payload) { return fetchJson(`/tenants/${MESHKEE_DOMAIN}/contact-submissions`, { method: "POST", body: JSON.stringify(payload) }); } export async function getCurrentUser(token) { return fetchJson("/auth/me", { headers: { Authorization: `Bearer ${token}` } }); } export async function addCartItem({ businessId, token, storeItemVariantId, quantity }) { return fetchJson(`/businesses/${businessId}/cart/items`, { method: "POST", headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ storeItemVariantId, quantity }) }); } export function normalizeStoreItem(item) { const product = item.product || {}; const images = [ ...(Array.isArray(item.images) ? item.images : []), ...(Array.isArray(item.gallery) ? item.gallery : []) ] .map((image) => image.url || image.imageUrl || image) .filter(Boolean); const image = item.imageUrl || item.titleImageUrl || item.mainImageUrl || product.imageUrl || product.main_image || images[0] || "/assets/product-server-g9.jpg"; return { id: String(item.id || item.variantId || item.storeItemVariantId || item.slug || product.id), slug: String(item.slug || item.id || item.variantId || product.slug || product.id), productId: String(item.productId || product.id || ""), title: item.titleFa || item.nameFa || item.title || product.titleFa || product.nameFa || product.title || "محصول فروشگاه", category: item.categoryName || product.categoryName || "تجهیزات سرور", image, images: images.length ? images : [image], price: item.finalPrice || item.salePrice || item.price || item.amount || null, currency: item.currency || item.priceCurrency || "تومان", description: item.description || item.descriptionHtml || product.description || product.mainTextHtml || "", technicalValues: item.technicalValues || item.technicalData || [], quantity: item.quantity ?? item.stock ?? null, isFestival: Boolean(item.isFestival), raw: item }; } export function normalizeStaticImageSlot(slot) { return { key: slot.key, pageKey: slot.pageKey, kind: slot.kind || "single", label: slot.label || slot.name || slot.key, aspectRatio: cssAspectRatio(slot.aspectRatio), recommendedWidth: slot.recommendedWidth, itemCount: slot.itemCount, images: Array.isArray(slot.images) ? slot.images .map((image) => ({ id: image.id, url: image.url || image.image || image.imageUrl || image.src, titleFa: image.titleFa || image.nameFa || image.title, titleEn: image.titleEn || image.nameEn || "", subtext: image.subtext || image.description || "", linkUrl: image.linkUrl || image.href || image.link, width: image.width, height: image.height, aspectRatio: cssAspectRatio(image.aspectRatio), sortOrder: image.sortOrder })) .filter((image) => image.url) .sort((a, b) => Number(a.sortOrder || 0) - Number(b.sortOrder || 0)) : [] }; } export function cssAspectRatio(value) { if (!value) return undefined; const text = String(value).trim(); const comma = text.match(/^(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)$/); if (comma) return `${comma[1]} / ${comma[2]}`; const colon = text.match(/^(\d+(?:\.\d+)?)\s*:\s*(\d+(?:\.\d+)?)$/); if (colon) return `${colon[1]} / ${colon[2]}`; const slash = text.match(/^(\d+(?:\.\d+)?)\s*\/\s*(\d+(?:\.\d+)?)$/); if (slash) return `${slash[1]} / ${slash[2]}`; return undefined; } export function fallbackStoreItems() { return products.map((product, index) => ({ id: `local-${index + 1}`, slug: `local-${index + 1}`, productId: `local-product-${index + 1}`, title: product.title, category: product.category, image: product.image, images: [product.image, "/assets/banner-2.jpg", "/assets/banner-3.jpg"], price: null, currency: "تومان", description: "برای قیمت، موجودی و کانفیگ اختصاصی این محصول با کارشناسان فروش تماس بگیرید.", technicalValues: [ { label: "دسته بندی", value: product.category }, { label: "وضعیت قیمت", value: "تماس با فروشگاه" } ], quantity: null, isFestival: index === 0, raw: product })); } export function normalizeBlog(blog) { return { id: String(blog.id || blog.blogId || blog.slug), slug: String(blog.slug || blog.id || blog.blogId), title: blog.titleFa || blog.title || blog.nameFa || "مقاله", date: blog.publishedAt || blog.createdAt || "", image: blog.titleImageUrl || blog.imageUrl || blog.main_image || blog.thumbnail || "/assets/banner-1.jpg", abstract: blog.abstract || blog.summary || blog.description || "", html: blog.mainTextHtml || blog.bodyHtml || blog.text || blog.content || "", raw: blog }; }