From 43f07da613ffaf37c709c7f600fd996c75ab7ca9 Mon Sep 17 00:00:00 2001 From: Vula Builder Date: Fri, 31 Jul 2026 18:44:27 +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..5755528 --- /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 VULA_CMS_URL = process.env.VULA_CMS_URL || 'https://ide.vulai.co.za' +const VULA_PROJECT_ID = process.env.VULA_CMS_PROJECT_ID || '' + +interface VulaProduct { + id: string; title: string; thumbnail: string | null + variants?: Array<{ prices?: Array<{ 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( + `${VULA_CMS_URL}/api/store/${VULA_PROJECT_ID}/products?${query}&limit=${ids.length}`, + { next: { revalidate: 300 } } + ) + if (!res.ok) return [] + const data = await res.json() as { products?: VulaProduct[] } + 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?.prices?.[0] + return ( + +
+ {product.thumbnail ? ( + {product.title} + ) : ( +
No image
+ )} +
+

{product.title}

+ {price?.amount && ( +

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

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