import { saleorClient } from "./client"; import { GET_PRODUCTS, GET_PRODUCT_BY_SLUG } from "./queries/Products"; import type { Product, ProductList } from "@/types/saleor"; const CHANNEL = process.env.NEXT_PUBLIC_SALEOR_CHANNEL || "default-channel"; export async function getProducts( locale: string = "SR", first: number = 100 ): Promise { try { const { data } = await saleorClient.query({ query: GET_PRODUCTS, variables: { channel: CHANNEL, locale: locale.toUpperCase(), first, }, }); return data?.products?.edges.map((edge: { node: Product }) => edge.node) || []; } catch (error) { console.error("Error fetching products from Saleor:", error); return []; } } export async function getProductBySlug( slug: string, locale: string = "SR" ): Promise { try { const { data } = await saleorClient.query({ query: GET_PRODUCT_BY_SLUG, variables: { slug, channel: CHANNEL, locale: locale.toUpperCase(), }, }); return data?.product || null; } catch (error) { console.error(`Error fetching product ${slug} from Saleor:`, error); return null; } } export function getProductPrice(product: Product): string { const variant = product.variants?.[0]; if (!variant?.pricing?.price?.gross?.amount) { return ""; } return formatPrice( variant.pricing.price.gross.amount, variant.pricing.price.gross.currency ); } export function getProductImage(product: Product): string { if (product.media && product.media.length > 0) { return product.media[0].url; } if (product.variants?.[0]?.media && product.variants[0].media.length > 0) { return product.variants[0].media[0].url; } return "/placeholder-product.jpg"; } export function isProductAvailable(product: Product): boolean { const variant = product.variants?.[0]; if (!variant) return false; return (variant.quantityAvailable || 0) > 0; } export function formatPrice(amount: number, currency: string = "RSD"): string { return new Intl.NumberFormat("sr-RS", { style: "currency", currency: currency, minimumFractionDigits: 0, }).format(amount); } // Parse Saleor's JSON description format (EditorJS) to plain text/HTML export function parseDescription(description: string | null | undefined): string { if (!description) return ""; // If it's already plain text (not JSON), return as-is if (!description.startsWith("{")) { return description; } try { const parsed = JSON.parse(description); // Handle EditorJS format: { blocks: [{ data: { text: "..." } }] } if (parsed.blocks && Array.isArray(parsed.blocks)) { return parsed.blocks .map((block: any) => { if (block.data?.text) { return block.data.text; } return ""; }) .filter(Boolean) .join("\n\n"); } // Fallback: return stringified if unknown format return description; } catch (e) { // If JSON parse fails, return original return description; } } // Get localized product data export function getLocalizedProduct( product: Product, locale: string = "SR" ): { name: string; slug: string; description: string; seoTitle?: string; seoDescription?: string; } { const isEnglish = locale.toLowerCase() === "en"; const translation = isEnglish ? product.translation : null; const rawDescription = translation?.description || product.description; return { name: translation?.name || product.name, slug: translation?.slug || product.slug, description: parseDescription(rawDescription), seoTitle: translation?.seoTitle || product.seoTitle, seoDescription: translation?.seoDescription || product.seoDescription, }; }