From d15f0ddaa2f73678863907744114e5d50b7a323a Mon Sep 17 00:00:00 2001 From: Vula Builder Date: Mon, 27 Jul 2026 18:34:55 +0000 Subject: [PATCH] Deploy --- .../sections/ProductCarouselSection.tsx | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/components/sections/ProductCarouselSection.tsx diff --git a/src/components/sections/ProductCarouselSection.tsx b/src/components/sections/ProductCarouselSection.tsx new file mode 100644 index 0000000..9594fa6 --- /dev/null +++ b/src/components/sections/ProductCarouselSection.tsx @@ -0,0 +1,79 @@ +import Image from 'next/image' +import Link from 'next/link' +import { getProductCarousels } from '@/lib/cms' + +const BACKEND_URL = process.env.VULA_ECOMMERCE_BACKEND_URL || 'http://vula-ecommerce:9000' +const PUB_KEY = process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || '' + +interface MedusaProduct { + id: string; title: string; thumbnail: string | null + variants?: Array<{ calculated_price?: { calculated_amount?: number; currency_code?: string } }> +} + +const CURRENCY_SYMBOLS: Record = { zar: 'R', usd: '$', eur: '€', gbp: '£', kes: 'KSh', ngn: '₦', ghs: '₵' } +const fmt = (amount: number, code?: string) => + `${CURRENCY_SYMBOLS[(code ?? '').toLowerCase()] ?? (code?.toUpperCase() ?? '')}${(amount / 100).toFixed(2)}` + +async function fetchProductsByIds(ids: string[]): Promise { + if (!ids.length) return [] + try { + const query = ids.map(id => `id[]=${id}`).join('&') + const res = await fetch( + `${BACKEND_URL}/store/products?${query}&fields=id,title,thumbnail,variants.calculated_price&limit=${ids.length}`, + { headers: { 'x-publishable-api-key': PUB_KEY }, next: { revalidate: 300 } } + ) + if (!res.ok) return [] + const data = await res.json() as { products?: MedusaProduct[] } + return data.products ?? [] + } catch { return [] } +} + +export default async function ProductCarouselSection() { + const carousels = await getProductCarousels() + if (!carousels.length) return null + + const sections = await Promise.all( + carousels.map(async c => { + const ids = Array.isArray(c.data.product_ids) ? (c.data.product_ids as string[]) : [] + const prods = await fetchProductsByIds(ids) + return { title: c.data.title as string, products: prods } + }) + ) + + return ( + <> + {sections.filter(s => s.products.length > 0).map(section => ( +
+
+

{section.title}

+
+ {section.products.map(product => { + const variant = product.variants?.[0] + const price = variant?.calculated_price + return ( + +
+ {product.thumbnail ? ( + {product.title} + ) : ( +
No image
+ )} +
+

{product.title}

+ {price?.calculated_amount && ( +

{fmt(price.calculated_amount, price.currency_code)}

+ )} + + ) + })} +
+
+
+ ))} + + ) +}