@sprintup-cms/sdk 1.8.14 → 1.8.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -485,18 +485,19 @@ function ProductListBlock({ block }) {
485
485
  title && /* @__PURE__ */ jsx("h2", { className: "text-2xl md:text-3xl font-semibold tracking-tight", children: title }),
486
486
  subtitle && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-2", children: subtitle })
487
487
  ] }),
488
- /* @__PURE__ */ jsx("div", { className: `grid gap-6 grid-cols-1 ${gridCols}`, children: products.map((product) => /* @__PURE__ */ jsxs("div", { className: "border rounded-lg overflow-hidden group hover:shadow-md transition-shadow", children: [
489
- /* @__PURE__ */ jsxs("div", { className: "aspect-square relative bg-muted overflow-hidden", children: [
490
- product.image ? /* @__PURE__ */ jsx("img", { src: product.image, alt: product.name, className: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" }) : /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-muted-foreground/30", children: /* @__PURE__ */ jsx("svg", { className: "w-12 h-12", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" }) }) }),
491
- product.badge && /* @__PURE__ */ jsx("span", { className: "absolute top-3 left-3 text-xs px-2 py-1 rounded bg-primary text-primary-foreground", children: product.badge })
492
- ] }),
488
+ /* @__PURE__ */ jsx("div", { className: `grid gap-6 grid-cols-1 ${gridCols}`, children: products.map((product) => /* @__PURE__ */ jsxs("div", { className: "border rounded-lg overflow-hidden group hover:shadow-md transition-shadow bg-card", children: [
489
+ product.image && /* @__PURE__ */ jsx("div", { className: "aspect-video relative bg-muted overflow-hidden", children: /* @__PURE__ */ jsx("img", { src: product.image, alt: product.name, className: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" }) }),
493
490
  /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-2", children: [
494
- product.category && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground uppercase tracking-wide", children: product.category }),
495
- /* @__PURE__ */ jsx("h3", { className: "font-medium text-sm line-clamp-2", children: product.name }),
491
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
492
+ product.category && /* @__PURE__ */ jsx("span", { className: "text-xs px-2 py-0.5 rounded-full bg-primary/10 text-primary font-medium", children: product.category }),
493
+ product.badge && /* @__PURE__ */ jsx("span", { className: "text-xs px-2 py-0.5 rounded-full bg-muted text-muted-foreground", children: product.badge })
494
+ ] }),
495
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold text-base line-clamp-2", children: product.name }),
496
496
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pt-1", children: [
497
- showPrice && /* @__PURE__ */ jsxs("span", { className: "font-semibold", children: [
498
- currency,
499
- typeof product.price === "number" ? product.price.toFixed(2) : product.price
497
+ showPrice && product.price > 0 && /* @__PURE__ */ jsxs("span", { className: "font-bold text-lg", children: [
498
+ typeof product.price === "number" ? product.price.toFixed(2) : product.price,
499
+ " ",
500
+ currency
500
501
  ] }),
501
502
  showRating && product.rating && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
502
503
  /* @__PURE__ */ jsx("svg", { className: "w-3.5 h-3.5 fill-yellow-400 text-yellow-400", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" }) }),
@@ -614,15 +615,13 @@ function CMSBlocks({ blocks, pageType, className = "", custom = {} }) {
614
615
  }) });
615
616
  }
616
617
  function normaliseProductServer(raw) {
617
- if (raw.id !== void 0 && raw.price !== void 0) return raw;
618
618
  const firstPlan = Array.isArray(raw.plans) && raw.plans.length > 0 ? raw.plans[0] : null;
619
619
  const courseCount = Array.isArray(raw.courses) ? raw.courses.length : void 0;
620
- const image = raw.image && !raw.image.startsWith("data:") ? raw.image : raw.thumbnail ?? void 0;
621
620
  return {
622
621
  id: raw._id ?? raw.id ?? String(Math.random()),
623
622
  name: raw.name ?? "Unnamed",
624
623
  price: firstPlan?.price ?? raw.price ?? 0,
625
- image,
624
+ color: raw.primaryColor ?? raw.color ?? void 0,
626
625
  rating: raw.rating ?? void 0,
627
626
  category: raw.type ? raw.type.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()) : void 0,
628
627
  badge: courseCount ? `${courseCount} course${courseCount !== 1 ? "s" : ""}` : raw.duration ? `${raw.duration} min` : void 0
@@ -633,7 +632,7 @@ function ServerProductListBlock({ block }) {
633
632
  const { title, subtitle, columns = 3, showPrice = true, showRating = true, limit = 6, currency = "$" } = cfg;
634
633
  const cols = parseInt(String(columns), 10);
635
634
  const gridCols = cols === 2 ? "sm:grid-cols-2" : cols === 4 ? "sm:grid-cols-2 lg:grid-cols-4" : "sm:grid-cols-2 lg:grid-cols-3";
636
- const rawProducts = Array.isArray(cfg.prefetchedProducts) ? cfg.prefetchedProducts : [];
635
+ const rawProducts = Array.isArray(block._resolvedProducts) ? block._resolvedProducts : Array.isArray(cfg.prefetchedProducts) ? cfg.prefetchedProducts : [];
637
636
  const products = rawProducts.map(normaliseProductServer).slice(0, Number(limit));
638
637
  if (products.length === 0) {
639
638
  return /* @__PURE__ */ jsx("section", { className: "py-12", children: /* @__PURE__ */ jsx("div", { className: "max-w-6xl mx-auto px-4", children: /* @__PURE__ */ jsx("div", { className: "text-center py-12 border border-dashed border-border rounded-lg bg-muted/10", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "No products available" }) }) }) });
@@ -643,18 +642,32 @@ function ServerProductListBlock({ block }) {
643
642
  title && /* @__PURE__ */ jsx("h2", { className: "text-2xl md:text-3xl font-semibold tracking-tight", children: title }),
644
643
  subtitle && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-2", children: subtitle })
645
644
  ] }),
646
- /* @__PURE__ */ jsx("div", { className: `grid gap-6 grid-cols-1 ${gridCols}`, children: products.map((product) => /* @__PURE__ */ jsxs("div", { className: "border rounded-lg overflow-hidden group hover:shadow-md transition-shadow", children: [
647
- /* @__PURE__ */ jsxs("div", { className: "aspect-square relative bg-muted overflow-hidden", children: [
648
- product.image ? /* @__PURE__ */ jsx("img", { src: product.image, alt: product.name, className: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" }) : /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-muted-foreground/30", children: /* @__PURE__ */ jsx("svg", { className: "w-12 h-12", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" }) }) }),
649
- product.badge && /* @__PURE__ */ jsx("span", { className: "absolute top-3 left-3 text-xs px-2 py-1 rounded bg-primary text-primary-foreground", children: product.badge })
650
- ] }),
651
- /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-2", children: [
652
- product.category && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground uppercase tracking-wide", children: product.category }),
653
- /* @__PURE__ */ jsx("h3", { className: "font-medium text-sm line-clamp-2", children: product.name }),
654
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pt-1", children: [
655
- showPrice && /* @__PURE__ */ jsxs("span", { className: "font-semibold", children: [
656
- currency,
657
- typeof product.price === "number" ? product.price.toFixed(2) : product.price
645
+ /* @__PURE__ */ jsx("div", { className: `grid gap-6 grid-cols-1 ${gridCols}`, children: products.map((product) => /* @__PURE__ */ jsxs("div", { className: "border rounded-xl overflow-hidden group hover:shadow-lg transition-shadow bg-card flex flex-col", children: [
646
+ /* @__PURE__ */ jsx(
647
+ "div",
648
+ {
649
+ className: "h-2 w-full",
650
+ style: { backgroundColor: product.color ?? "#6366f1" }
651
+ }
652
+ ),
653
+ /* @__PURE__ */ jsxs("div", { className: "p-5 flex flex-col gap-3 flex-1", children: [
654
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
655
+ product.category && /* @__PURE__ */ jsx(
656
+ "span",
657
+ {
658
+ className: "text-xs px-2 py-0.5 rounded-full font-medium text-white",
659
+ style: { backgroundColor: product.color ?? "#6366f1" },
660
+ children: product.category
661
+ }
662
+ ),
663
+ product.badge && /* @__PURE__ */ jsx("span", { className: "text-xs px-2 py-0.5 rounded-full bg-muted text-muted-foreground", children: product.badge })
664
+ ] }),
665
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold text-base line-clamp-2 flex-1", children: product.name }),
666
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mt-auto pt-2 border-t border-border", children: [
667
+ showPrice && product.price > 0 && /* @__PURE__ */ jsxs("span", { className: "font-bold text-lg", children: [
668
+ typeof product.price === "number" ? product.price.toFixed(2) : product.price,
669
+ " ",
670
+ currency
658
671
  ] }),
659
672
  showRating && product.rating && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
660
673
  /* @__PURE__ */ jsx("svg", { className: "w-3.5 h-3.5 fill-yellow-400 text-yellow-400", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" }) }),
@@ -682,6 +695,27 @@ async function generateMetadata({ params }) {
682
695
  }
683
696
  };
684
697
  }
698
+ async function resolveProductListBlocks(blocks) {
699
+ return Promise.all(blocks.map(async (block) => {
700
+ if (block.type !== "product-list") return block;
701
+ const cfg = block.content ?? block.data ?? {};
702
+ if (Array.isArray(cfg.prefetchedProducts) && cfg.prefetchedProducts.length > 0) return block;
703
+ const endpoint = cfg.endpoint;
704
+ if (!endpoint) return block;
705
+ try {
706
+ const headers = { "Accept": "application/json" };
707
+ const token = cfg.token ?? cfg.apiToken;
708
+ if (token) headers["Authorization"] = `Bearer ${token}`;
709
+ const res = await fetch(endpoint, { headers, next: { revalidate: cfg.refreshInterval || 300 } });
710
+ if (!res.ok) return block;
711
+ const json = await res.json();
712
+ const items = Array.isArray(json) ? json : json.products ?? json.data ?? json.items ?? json.result ?? [];
713
+ return { ...block, _resolvedProducts: items };
714
+ } catch {
715
+ return block;
716
+ }
717
+ }));
718
+ }
685
719
  async function CMSCatchAllPage({ params }) {
686
720
  const { slug } = await params;
687
721
  const slugStr = slug.join("/");
@@ -704,6 +738,7 @@ async function CMSCatchAllPage({ params }) {
704
738
  if (page.pageTypeId) {
705
739
  pageType = await client.getPageType(page.pageTypeId);
706
740
  }
741
+ const resolvedBlocks = await resolveProductListBlocks(page.blocks ?? []);
707
742
  return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-background", children: [
708
743
  isPreview && /* @__PURE__ */ jsxs("div", { className: "sticky top-0 z-50 flex items-center justify-between px-4 py-2.5 bg-amber-500 text-white text-sm font-medium shadow", children: [
709
744
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
@@ -725,11 +760,11 @@ async function CMSCatchAllPage({ params }) {
725
760
  }
726
761
  )
727
762
  ] }),
728
- /* @__PURE__ */ jsx("article", { className: "max-w-5xl mx-auto px-6 py-12", children: page.blocks?.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
729
- page.blocks.map(
763
+ /* @__PURE__ */ jsx("article", { className: "max-w-5xl mx-auto px-6 py-12", children: resolvedBlocks.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
764
+ resolvedBlocks.map(
730
765
  (block, idx) => block.type === "product-list" ? /* @__PURE__ */ jsx(ServerProductListBlock, { block }, block.id ?? idx) : null
731
766
  ),
732
- /* @__PURE__ */ jsx(CMSBlocks, { blocks: page.blocks.filter((b) => b.type !== "product-list"), pageType })
767
+ /* @__PURE__ */ jsx(CMSBlocks, { blocks: resolvedBlocks.filter((b) => b.type !== "product-list"), pageType })
733
768
  ] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-24 text-muted-foreground border-2 border-dashed border-border rounded-xl", children: [
734
769
  /* @__PURE__ */ jsx("p", { className: "text-sm", children: "No content added yet." }),
735
770
  isPreview && /* @__PURE__ */ jsx("p", { className: "text-xs mt-1 opacity-60", children: "Add blocks in the CMS editor to see them here." })