@akropolys/kiku 1.5.18 → 1.6.0

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.
package/dist/index.mjs CHANGED
@@ -71,7 +71,7 @@ function SearchBar({
71
71
  }
72
72
  ignoreNextQueryChange.current = true;
73
73
  setOpen(false);
74
- setQuery(r.product.name ?? "");
74
+ setQuery(r.entity.title ?? r.entity.name ?? "");
75
75
  onSelect?.(r);
76
76
  };
77
77
  const handleCommitSearch = () => {
@@ -151,8 +151,8 @@ function SearchBar({
151
151
  children: [
152
152
  /* @__PURE__ */ jsx("span", { className: "hsk-sb-row-icon", children: /* @__PURE__ */ jsx(SearchIcon, {}) }),
153
153
  /* @__PURE__ */ jsxs("div", { className: "hsk-sb-row-body", children: [
154
- /* @__PURE__ */ jsx("div", { className: "hsk-sb-row-title", children: r.product.name }),
155
- (r.product.category || r.product.brand) && /* @__PURE__ */ jsx("div", { className: "hsk-sb-row-sub", children: r.product.category ?? r.product.brand })
154
+ /* @__PURE__ */ jsx("div", { className: "hsk-sb-row-title", children: r.entity.title ?? r.entity.name }),
155
+ (r.entity.category || r.entity.brand) && /* @__PURE__ */ jsx("div", { className: "hsk-sb-row-sub", children: r.entity.category ?? r.entity.brand })
156
156
  ] })
157
157
  ]
158
158
  },
@@ -653,7 +653,7 @@ I couldn't find any matching products in the store.`;
653
653
  }) }) });
654
654
  }
655
655
  const featured = sources.filter((src) => src.id && referencedIds.includes(src.id));
656
- const general = featured.length > 0 ? [] : sources.filter((src) => !src.id || !referencedIds.includes(src.id));
656
+ const general = referencedIds.length > 0 ? [] : sources.filter((src) => !src.id || !referencedIds.includes(src.id));
657
657
  return /* @__PURE__ */ jsxs4("div", { className: "hsk-sources-container", children: [
658
658
  featured.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "hsk-sources-group", style: { marginBottom: "10px" }, children: [
659
659
  /* @__PURE__ */ jsx5("div", { className: "hsk-sources-group-title", children: "\u2B50 Featured in response" }),
@@ -764,7 +764,6 @@ I couldn't find any matching products in the store.`;
764
764
  import { useState as useState5, useEffect as useEffect3, useRef as useRef5, useCallback as useCallback2 } from "react";
765
765
  import { createPortal } from "react-dom";
766
766
  import { useKiku as useKiku2 } from "@akropolys/sdk";
767
- import { usePaymentPolling } from "@akropolys/sdk";
768
767
  import { useAkropolysContext as useAkropolysContext3 } from "@akropolys/sdk";
769
768
 
770
769
  // src/components/ComparisonMatrix.tsx
@@ -1325,7 +1324,7 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource, referencedI
1325
1324
  railRef.current?.scrollBy({ left: 170, behavior: "smooth" });
1326
1325
  };
1327
1326
  const referenced = sources.filter((s) => s.id && referencedIds.includes(s.id));
1328
- const display = referenced.length > 0 ? referenced : sources;
1327
+ const display = referencedIds.length > 0 ? referenced : sources;
1329
1328
  return /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-sources-wrap", children: [
1330
1329
  /* @__PURE__ */ jsx7("div", { className: "hsk-cb-sources", ref: railRef, children: display.map((src, si) => {
1331
1330
  const isReferenced = !!(src.id && referencedIds.includes(src.id));
@@ -1713,31 +1712,15 @@ function ChatModal({
1713
1712
  }
1714
1713
  return "";
1715
1714
  });
1716
- const [merchantRef, setMerchantRef] = useState5(null);
1717
1715
  const [paymentPhase, setPaymentPhase] = useState5("idle");
1718
1716
  const [memoryKey, setMemoryKey] = useState5(null);
1719
1717
  const [sessions, setSessions] = useState5(() => loadSessions());
1720
1718
  const [sidebarOpen, setSidebarOpen] = useState5(false);
1721
1719
  const [replayMessages, setReplayMessages] = useState5(null);
1722
- const { status: pollStatus } = usePaymentPolling({
1723
- client: client.api,
1724
- merchantReference: merchantRef,
1725
- onSuccess: () => {
1726
- setPaymentPhase("done");
1727
- setMerchantRef(null);
1728
- },
1729
- onFailure: () => {
1730
- setPaymentPhase("failed");
1731
- setMerchantRef(null);
1732
- }
1733
- });
1734
1720
  useEffect3(() => {
1735
1721
  if (!lastAction) return;
1736
1722
  if (lastAction.type === "request_phone") {
1737
1723
  setPaymentPhase("prompt_phone");
1738
- } else if (lastAction.type === "awaiting_payment") {
1739
- setMerchantRef(lastAction.merchantReference ?? null);
1740
- setPaymentPhase("awaiting");
1741
1724
  }
1742
1725
  }, [lastAction]);
1743
1726
  const isStringTheme = typeof theme === "string";
@@ -1794,7 +1777,6 @@ function ChatModal({
1794
1777
  reset();
1795
1778
  setReplayMessages(null);
1796
1779
  setPaymentPhase("idle");
1797
- setMerchantRef(null);
1798
1780
  }, [reset, saveCurrentSession]);
1799
1781
  const handleSourceClick = (src) => {
1800
1782
  setSelectedProduct(src);
@@ -2082,56 +2064,6 @@ function ChatModal({
2082
2064
  ] })
2083
2065
  ] }) }) })
2084
2066
  ] }),
2085
- !replayMessages && paymentPhase === "awaiting" && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-payment-prompt hsk-cb-payment-prompt--awaiting", children: [
2086
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-payment-pulse-ring" }),
2087
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-payment-icon-wrap", children: /* @__PURE__ */ jsx7("span", { style: { fontSize: "2rem" }, children: "\u{1F4F1}" }) }),
2088
- /* @__PURE__ */ jsx7("p", { className: "hsk-cb-payment-label", style: { fontWeight: 600 }, children: "Check your phone" }),
2089
- /* @__PURE__ */ jsxs6("p", { className: "hsk-cb-payment-sub", children: [
2090
- "An M-Pesa STK push has been sent.",
2091
- /* @__PURE__ */ jsx7("br", {}),
2092
- "Enter your PIN to complete payment."
2093
- ] }),
2094
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-payment-dots", children: [
2095
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-dot hsk-cb-dot--amber" }),
2096
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-dot hsk-cb-dot--amber" }),
2097
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-dot hsk-cb-dot--amber" })
2098
- ] })
2099
- ] }),
2100
- !replayMessages && paymentPhase === "done" && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-payment-prompt hsk-cb-payment-prompt--success", children: [
2101
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-payment-success-ring" }),
2102
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-payment-icon-wrap", children: /* @__PURE__ */ jsx7("span", { style: { fontSize: "2.5rem" }, children: "\u2705" }) }),
2103
- /* @__PURE__ */ jsx7("p", { className: "hsk-cb-payment-label", children: "Payment complete!" }),
2104
- /* @__PURE__ */ jsx7("p", { className: "hsk-cb-payment-sub", children: "Thank you for your order. A confirmation has been sent." })
2105
- ] }),
2106
- !replayMessages && paymentPhase === "failed" && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-payment-prompt hsk-cb-payment-prompt--failed", children: [
2107
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-payment-icon-wrap", children: /* @__PURE__ */ jsx7("span", { style: { fontSize: "2.5rem" }, children: "\u274C" }) }),
2108
- /* @__PURE__ */ jsx7("p", { className: "hsk-cb-payment-label", children: "Payment failed or timed out" }),
2109
- /* @__PURE__ */ jsx7("p", { className: "hsk-cb-payment-sub", children: "Please check your M-Pesa PIN and try again, or contact support." }),
2110
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-payment-actions", children: [
2111
- /* @__PURE__ */ jsx7(
2112
- "button",
2113
- {
2114
- className: "hsk-cb-pay-submit",
2115
- onClick: () => {
2116
- setPaymentPhase("prompt_phone");
2117
- setMerchantRef(null);
2118
- },
2119
- children: "Try again"
2120
- }
2121
- ),
2122
- /* @__PURE__ */ jsx7(
2123
- "button",
2124
- {
2125
- className: "hsk-cb-pay-secondary",
2126
- onClick: () => {
2127
- setPaymentPhase("idle");
2128
- setMerchantRef(null);
2129
- },
2130
- children: "Cancel"
2131
- }
2132
- )
2133
- ] })
2134
- ] }),
2135
2067
  /* @__PURE__ */ jsx7("div", { ref: bottomRef, style: { height: 1 } })
2136
2068
  ] }),
2137
2069
  !replayMessages && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-input-wrap", children: [
@@ -2440,7 +2372,7 @@ function SparkleModal({
2440
2372
  if (!initialProduct && !fetchedProduct) {
2441
2373
  client.api.searchVector(productName, 1).then((res) => {
2442
2374
  if (res.results && res.results.length > 0) {
2443
- setFetchedProduct(res.results[0].product);
2375
+ setFetchedProduct(res.results[0].entity);
2444
2376
  }
2445
2377
  }).catch((err) => console.error("[Akropolys] Failed to fetch product details", err));
2446
2378
  }
@@ -2473,7 +2405,7 @@ function SparkleModal({
2473
2405
  const prevent = onNavigate?.(r);
2474
2406
  if (prevent !== false) {
2475
2407
  onClose();
2476
- if (r.product.url) window.location.href = r.product.url;
2408
+ if (r.entity.url) window.location.href = r.entity.url;
2477
2409
  }
2478
2410
  };
2479
2411
  const handleSend = async (text) => {
@@ -2560,7 +2492,7 @@ Question: ${q}`;
2560
2492
  /* @__PURE__ */ jsx8("div", { className: "hsk-cb-ai-text", children: renderMarkdown(msg.content) }),
2561
2493
  idx === 0 && displayProduct && /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-mobile-attachment-deck", children: [
2562
2494
  /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-mobile-main-card", children: [
2563
- /* @__PURE__ */ jsx8("div", { className: "hsk-sp-mobile-main-card-img", children: displayProduct.images?.[0] ? /* @__PURE__ */ jsx8("img", { src: displayProduct.images[0], alt: displayProduct.name }) : /* @__PURE__ */ jsx8("span", { children: "\u{1F6CD}" }) }),
2495
+ /* @__PURE__ */ jsx8("div", { className: "hsk-sp-mobile-main-card-img", children: displayProduct.images?.[0] ? /* @__PURE__ */ jsx8("img", { src: displayProduct.images[0], alt: displayProduct.name }) : /* @__PURE__ */ jsx8("span", { children: "\xF0\u0178\u203A\x8D" }) }),
2564
2496
  /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-mobile-main-card-info", children: [
2565
2497
  /* @__PURE__ */ jsx8("div", { className: "hsk-sp-mobile-main-card-brand", children: displayProduct.brand || displayProduct.category || "Product" }),
2566
2498
  /* @__PURE__ */ jsx8("div", { className: "hsk-sp-mobile-main-card-name", children: displayProduct.name }),
@@ -2583,8 +2515,8 @@ Question: ${q}`;
2583
2515
  (() => {
2584
2516
  const similarProducts = results.filter(
2585
2517
  (r) => {
2586
- const isSameName = !!(r.product.name && displayProduct?.name && r.product.name.toLowerCase() === displayProduct.name.toLowerCase());
2587
- const isSameSlug = r.product.slug && displayProduct?.slug && r.product.slug.toLowerCase() === displayProduct.slug.toLowerCase();
2518
+ const isSameName = !!(r.entity.name && displayProduct?.name && r.entity.name.toLowerCase() === displayProduct.name.toLowerCase());
2519
+ const isSameSlug = r.entity.slug && displayProduct?.slug && r.entity.slug.toLowerCase() === displayProduct.slug.toLowerCase();
2588
2520
  return !isSameName && !isSameSlug;
2589
2521
  }
2590
2522
  );
@@ -2592,17 +2524,17 @@ Question: ${q}`;
2592
2524
  return /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-mobile-similar-carousel-inline", children: [
2593
2525
  /* @__PURE__ */ jsx8("div", { className: "hsk-sp-mobile-similar-carousel-title", children: "Similar Products" }),
2594
2526
  /* @__PURE__ */ jsx8("div", { className: "hsk-sp-mobile-similar-carousel-list", children: similarProducts.map((r) => {
2595
- const price = parseFloat(r.product.price?.replace(/[^0-9.]/g, "") || "0");
2596
- const currency = r.product.currency ?? "KES";
2527
+ const price = parseFloat(r.entity.price?.replace(/[^0-9.]/g, "") || "0");
2528
+ const currency = r.entity.currency ?? "KES";
2597
2529
  return /* @__PURE__ */ jsxs7(
2598
2530
  "div",
2599
2531
  {
2600
2532
  className: "hsk-sp-mobile-similar-carousel-item",
2601
2533
  onClick: () => handleNav(r),
2602
2534
  children: [
2603
- /* @__PURE__ */ jsx8("div", { className: "hsk-sp-mobile-similar-carousel-img", children: r.product.images?.[0] ? /* @__PURE__ */ jsx8("img", { src: r.product.images[0], alt: r.product.name }) : /* @__PURE__ */ jsx8("span", { children: "\u{1F6CD}" }) }),
2535
+ /* @__PURE__ */ jsx8("div", { className: "hsk-sp-mobile-similar-carousel-img", children: r.entity.images?.[0] ? /* @__PURE__ */ jsx8("img", { src: r.entity.images[0], alt: r.entity.name }) : /* @__PURE__ */ jsx8("span", { children: "\xF0\u0178\u203A\x8D" }) }),
2604
2536
  /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-mobile-similar-carousel-meta", children: [
2605
- /* @__PURE__ */ jsx8("div", { className: "hsk-sp-mobile-similar-carousel-name", title: r.product.name, children: r.product.name }),
2537
+ /* @__PURE__ */ jsx8("div", { className: "hsk-sp-mobile-similar-carousel-name", title: r.entity.name, children: r.entity.name }),
2606
2538
  /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-mobile-similar-carousel-price", children: [
2607
2539
  currency,
2608
2540
  " ",
@@ -2706,7 +2638,7 @@ Question: ${q}`;
2706
2638
  /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-details-pane", children: [
2707
2639
  displayProduct && /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-product-profile-container", children: [
2708
2640
  /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-product-profile", children: [
2709
- /* @__PURE__ */ jsx8("div", { className: "hsk-sp-details-imgwrap", children: displayProduct.images?.[0] ? /* @__PURE__ */ jsx8("img", { src: displayProduct.images[0], alt: displayProduct.name }) : /* @__PURE__ */ jsx8("span", { className: "hsk-sp-img-placeholder", children: "\u{1F6CD}" }) }),
2641
+ /* @__PURE__ */ jsx8("div", { className: "hsk-sp-details-imgwrap", children: displayProduct.images?.[0] ? /* @__PURE__ */ jsx8("img", { src: displayProduct.images[0], alt: displayProduct.name }) : /* @__PURE__ */ jsx8("span", { className: "hsk-sp-img-placeholder", children: "\xF0\u0178\u203A\x8D" }) }),
2710
2642
  /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-details-meta", children: [
2711
2643
  displayProduct.brand && /* @__PURE__ */ jsx8("span", { className: "hsk-sp-item-brand", children: displayProduct.brand }),
2712
2644
  displayProduct.category && /* @__PURE__ */ jsx8("span", { className: "hsk-sp-item-cat", children: displayProduct.category }),
@@ -2723,7 +2655,7 @@ Question: ${q}`;
2723
2655
  ] }),
2724
2656
  /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-item-meta-badges", children: [
2725
2657
  displayProduct.rating && /* @__PURE__ */ jsxs7("span", { className: "hsk-sp-meta-badge hsk-sp-meta-badge-rating", children: [
2726
- "\u2605 ",
2658
+ "\xE2\u02DC\u2026 ",
2727
2659
  parseFloat(displayProduct.rating.toString()).toFixed(1),
2728
2660
  " ",
2729
2661
  displayProduct.reviewCount ? `(${displayProduct.reviewCount})` : ""
@@ -2753,8 +2685,8 @@ Question: ${q}`;
2753
2685
  /* @__PURE__ */ jsx8("div", { className: "hsk-sp-results", children: (() => {
2754
2686
  const similarProducts = results.filter(
2755
2687
  (r) => {
2756
- const isSameName = !!(r.product.name && displayProduct?.name && r.product.name.toLowerCase() === displayProduct.name.toLowerCase());
2757
- const isSameSlug = r.product.slug && displayProduct?.slug && r.product.slug.toLowerCase() === displayProduct.slug.toLowerCase();
2688
+ const isSameName = !!(r.entity.name && displayProduct?.name && r.entity.name.toLowerCase() === displayProduct.name.toLowerCase());
2689
+ const isSameSlug = r.entity.slug && displayProduct?.slug && r.entity.slug.toLowerCase() === displayProduct.slug.toLowerCase();
2758
2690
  return !isSameName && !isSameSlug;
2759
2691
  }
2760
2692
  );
@@ -2762,8 +2694,8 @@ Question: ${q}`;
2762
2694
  return /* @__PURE__ */ jsx8("div", { className: "hsk-sp-empty", children: "No similar products found." });
2763
2695
  }
2764
2696
  return similarProducts.map((r, i) => {
2765
- const price = parseFloat(r.product.price?.replace(/[^0-9.]/g, "") || "0");
2766
- const currency = r.product.currency ?? "KES";
2697
+ const price = parseFloat(r.entity.price?.replace(/[^0-9.]/g, "") || "0");
2698
+ const currency = r.entity.currency ?? "KES";
2767
2699
  return /* @__PURE__ */ jsxs7(
2768
2700
  "div",
2769
2701
  {
@@ -2771,11 +2703,11 @@ Question: ${q}`;
2771
2703
  style: { animationDelay: `${i * 55}ms`, cursor: "pointer" },
2772
2704
  onClick: () => handleNav(r),
2773
2705
  children: [
2774
- /* @__PURE__ */ jsx8("div", { className: "hsk-sp-img-wrap", children: r.product.images?.[0] ? /* @__PURE__ */ jsx8("img", { src: r.product.images[0], alt: r.product.name }) : /* @__PURE__ */ jsx8("span", { className: "hsk-sp-img-placeholder", children: "\u{1F6CD}" }) }),
2706
+ /* @__PURE__ */ jsx8("div", { className: "hsk-sp-img-wrap", children: r.entity.images?.[0] ? /* @__PURE__ */ jsx8("img", { src: r.entity.images[0], alt: r.entity.name }) : /* @__PURE__ */ jsx8("span", { className: "hsk-sp-img-placeholder", children: "\xF0\u0178\u203A\x8D" }) }),
2775
2707
  /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-item-body", children: [
2776
2708
  /* @__PURE__ */ jsxs7("div", { children: [
2777
- r.product.category && /* @__PURE__ */ jsx8("div", { className: "hsk-sp-item-cat", children: r.product.category }),
2778
- /* @__PURE__ */ jsx8("div", { className: "hsk-sp-item-name", title: r.product.name, children: r.product.name })
2709
+ r.entity.category && /* @__PURE__ */ jsx8("div", { className: "hsk-sp-item-cat", children: r.entity.category }),
2710
+ /* @__PURE__ */ jsx8("div", { className: "hsk-sp-item-name", title: r.entity.name, children: r.entity.name })
2779
2711
  ] }),
2780
2712
  /* @__PURE__ */ jsxs7("div", { className: "hsk-sp-item-price-row", children: [
2781
2713
  /* @__PURE__ */ jsx8("span", { className: "hsk-sp-item-currency", children: currency }),
@@ -2913,465 +2845,8 @@ function Sparkle({
2913
2845
  )
2914
2846
  ] });
2915
2847
  }
2916
-
2917
- // src/components/CartBadge.tsx
2918
- import { useCart } from "@akropolys/sdk";
2919
- import { jsx as jsx9 } from "react/jsx-runtime";
2920
- function CartBadge({ className }) {
2921
- const { cart } = useCart();
2922
- if (!cart || cart.item_count === 0) return null;
2923
- return /* @__PURE__ */ jsx9("span", { className: cn("hsk-cart-badge", className), children: cart.item_count });
2924
- }
2925
-
2926
- // src/components/CartDrawer.tsx
2927
- import { useState as useState8, useEffect as useEffect6 } from "react";
2928
- import { createPortal as createPortal4 } from "react-dom";
2929
- import { useCart as useCart3, useAkropolysContext as useAkropolysContext6 } from "@akropolys/sdk";
2930
-
2931
- // src/components/CheckoutModal.tsx
2932
- import { useState as useState7, useEffect as useEffect5 } from "react";
2933
- import { createPortal as createPortal3 } from "react-dom";
2934
- import { useCart as useCart2, useAkropolysContext as useAkropolysContext5, usePaymentPolling as usePaymentPolling2 } from "@akropolys/sdk";
2935
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
2936
- function CheckoutModal({
2937
- onClose,
2938
- theme,
2939
- customStyles,
2940
- hskThemeAttr
2941
- }) {
2942
- const { cart, loading: cartLoading } = useCart2();
2943
- const client = useAkropolysContext5();
2944
- const [config, setConfig] = useState7(null);
2945
- const [loadingConfig, setLoadingConfig] = useState7(true);
2946
- const [phone, setPhone] = useState7(() => {
2947
- if (typeof window !== "undefined") {
2948
- return localStorage.getItem("akropolys_user_phone") || "";
2949
- }
2950
- return "";
2951
- });
2952
- const [email, setEmail] = useState7(() => {
2953
- if (typeof window !== "undefined") {
2954
- return localStorage.getItem("akropolys_user_email") || "";
2955
- }
2956
- return "";
2957
- });
2958
- const [firstName, setFirstName] = useState7(() => {
2959
- if (typeof window !== "undefined") {
2960
- return localStorage.getItem("akropolys_user_firstname") || "";
2961
- }
2962
- return "";
2963
- });
2964
- const [lastName, setLastName] = useState7(() => {
2965
- if (typeof window !== "undefined") {
2966
- return localStorage.getItem("akropolys_user_lastname") || "";
2967
- }
2968
- return "";
2969
- });
2970
- const [phase, setPhase] = useState7("idle");
2971
- const [merchantRef, setMerchantRef] = useState7(null);
2972
- const [payError, setPayError] = useState7(null);
2973
- const {} = usePaymentPolling2({
2974
- client: client.api,
2975
- merchantReference: merchantRef,
2976
- onSuccess: () => {
2977
- setPhase("done");
2978
- setMerchantRef(null);
2979
- },
2980
- onFailure: () => {
2981
- setPhase("failed");
2982
- setPayError("Payment failed or timed out. Please try again.");
2983
- setMerchantRef(null);
2984
- }
2985
- });
2986
- useEffect5(() => {
2987
- client.api.getCheckoutConfig().then((res) => setConfig(res.payment_methods)).catch(() => {
2988
- }).finally(() => setLoadingConfig(false));
2989
- }, [client]);
2990
- const hasPaymentMethods = config && Object.values(config).some((m) => m.enabled);
2991
- const handlePay = async (e) => {
2992
- e.preventDefault();
2993
- if (!phone.trim()) {
2994
- setPayError("Phone number is required.");
2995
- return;
2996
- }
2997
- setPayError(null);
2998
- setPhase("awaiting");
2999
- try {
3000
- if (typeof window !== "undefined") {
3001
- localStorage.setItem("akropolys_user_phone", phone.trim());
3002
- localStorage.setItem("akropolys_user_email", email.trim());
3003
- localStorage.setItem("akropolys_user_firstname", firstName.trim());
3004
- localStorage.setItem("akropolys_user_lastname", lastName.trim());
3005
- }
3006
- const res = await client.api.initiatePayment(phone.trim(), email, firstName, lastName);
3007
- if (res?.merchantReference) {
3008
- setMerchantRef(res.merchantReference);
3009
- } else {
3010
- throw new Error("No merchant reference returned.");
3011
- }
3012
- } catch (err) {
3013
- setPhase("failed");
3014
- setPayError(err.message || "Could not connect to payment processor.");
3015
- }
3016
- };
3017
- const currency = cart?.currency || "KES";
3018
- const total = cart?.total || 0;
3019
- const backdropStyle = { ...customStyles, fontSize: "15px", fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif', zIndex: 999999 };
3020
- return createPortal3(
3021
- /* @__PURE__ */ jsx10(
3022
- "div",
3023
- {
3024
- className: "hsk-checkout-backdrop-full",
3025
- style: backdropStyle,
3026
- "data-hsk-theme": hskThemeAttr,
3027
- children: /* @__PURE__ */ jsxs8(
3028
- "div",
3029
- {
3030
- className: "hsk-checkout-modal-full",
3031
- style: customStyles,
3032
- "data-hsk-theme": hskThemeAttr,
3033
- children: [
3034
- /* @__PURE__ */ jsx10(
3035
- "button",
3036
- {
3037
- onClick: (e) => {
3038
- e.preventDefault();
3039
- e.stopPropagation();
3040
- onClose();
3041
- },
3042
- className: "hsk-checkout-close-x",
3043
- "aria-label": "Close checkout",
3044
- children: /* @__PURE__ */ jsxs8("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3045
- /* @__PURE__ */ jsx10("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
3046
- /* @__PURE__ */ jsx10("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
3047
- ] })
3048
- }
3049
- ),
3050
- /* @__PURE__ */ jsx10("div", { className: "hsk-checkout-panel-left", children: /* @__PURE__ */ jsxs8("div", { className: "hsk-checkout-left-content", children: [
3051
- /* @__PURE__ */ jsxs8("button", { onClick: (e) => {
3052
- e.preventDefault();
3053
- e.stopPropagation();
3054
- onClose();
3055
- }, className: "hsk-checkout-back-btn", children: [
3056
- /* @__PURE__ */ jsxs8("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
3057
- /* @__PURE__ */ jsx10("line", { x1: "19", y1: "12", x2: "5", y2: "12" }),
3058
- /* @__PURE__ */ jsx10("polyline", { points: "12 19 5 12 12 5" })
3059
- ] }),
3060
- "Back to store"
3061
- ] }),
3062
- /* @__PURE__ */ jsx10("div", { className: "hsk-checkout-store-info", children: /* @__PURE__ */ jsx10("h2", { children: "Secure Checkout" }) }),
3063
- /* @__PURE__ */ jsxs8("div", { className: "hsk-checkout-amount-due", children: [
3064
- /* @__PURE__ */ jsx10("span", { className: "hsk-checkout-label-muted", children: "Pay total" }),
3065
- /* @__PURE__ */ jsxs8("div", { className: "hsk-checkout-grand-total", children: [
3066
- currency,
3067
- " ",
3068
- total.toLocaleString(void 0, { minimumFractionDigits: 2 })
3069
- ] })
3070
- ] }),
3071
- cartLoading || !cart ? /* @__PURE__ */ jsx10("p", { className: "hsk-cart-loading", children: "Loading order..." }) : /* @__PURE__ */ jsx10("div", { className: "hsk-checkout-items-list-wrap", children: /* @__PURE__ */ jsx10("ul", { className: "hsk-checkout-items-list", children: cart.items.map((item) => /* @__PURE__ */ jsxs8("li", { className: "hsk-checkout-item-row", children: [
3072
- /* @__PURE__ */ jsxs8("div", { className: "hsk-checkout-item-img-container", children: [
3073
- item.image ? /* @__PURE__ */ jsx10("img", { src: item.image, alt: item.name, className: "hsk-checkout-item-img" }) : /* @__PURE__ */ jsx10("div", { className: "hsk-checkout-item-img-placeholder", children: "\u{1F6D2}" }),
3074
- /* @__PURE__ */ jsx10("span", { className: "hsk-checkout-item-qty-badge", children: item.quantity })
3075
- ] }),
3076
- /* @__PURE__ */ jsx10("div", { className: "hsk-checkout-item-details", children: /* @__PURE__ */ jsx10("span", { className: "hsk-checkout-item-name", children: item.name }) }),
3077
- /* @__PURE__ */ jsxs8("span", { className: "hsk-checkout-item-price", children: [
3078
- item.currency,
3079
- " ",
3080
- (item.price_numeric * item.quantity).toLocaleString(void 0, { minimumFractionDigits: 2 })
3081
- ] })
3082
- ] }, item.id)) }) })
3083
- ] }) }),
3084
- /* @__PURE__ */ jsx10("div", { className: "hsk-checkout-panel-right", children: /* @__PURE__ */ jsx10("div", { className: "hsk-checkout-right-content", children: phase === "done" ? /* @__PURE__ */ jsxs8("div", { className: "hsk-checkout-status-card success", children: [
3085
- /* @__PURE__ */ jsx10("div", { className: "hsk-status-icon-wrap success", children: /* @__PURE__ */ jsxs8("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
3086
- /* @__PURE__ */ jsx10("path", { d: "M22 11.08V12a10 10 0 1 1-5.93-9.14" }),
3087
- /* @__PURE__ */ jsx10("polyline", { points: "22 4 12 14.01 9 11.01" })
3088
- ] }) }),
3089
- /* @__PURE__ */ jsx10("h3", { children: "Payment Successful!" }),
3090
- /* @__PURE__ */ jsx10("p", { children: "Your transaction has been confirmed. Thank you for your order!" }),
3091
- /* @__PURE__ */ jsx10("button", { onClick: onClose, className: "hsk-pay-btn hsk-btn-primary", style: { marginTop: "1.5rem" }, children: "Continue Shopping" })
3092
- ] }) : phase === "awaiting" ? /* @__PURE__ */ jsxs8("div", { className: "hsk-checkout-status-card awaiting", children: [
3093
- /* @__PURE__ */ jsx10("div", { className: "hsk-status-spinner-wrap", children: /* @__PURE__ */ jsx10("div", { className: "hsk-status-spinner" }) }),
3094
- /* @__PURE__ */ jsx10("h3", { children: "Confirm payment on your phone" }),
3095
- /* @__PURE__ */ jsxs8("p", { children: [
3096
- "We've sent an M-Pesa STK push prompt to ",
3097
- /* @__PURE__ */ jsxs8("strong", { children: [
3098
- "254",
3099
- phone
3100
- ] }),
3101
- "."
3102
- ] }),
3103
- /* @__PURE__ */ jsxs8("div", { className: "hsk-checkout-stk-instructions", children: [
3104
- /* @__PURE__ */ jsx10("p", { children: "1. Check your phone lockscreen for the M-Pesa prompt." }),
3105
- /* @__PURE__ */ jsx10("p", { children: "2. Enter your M-Pesa PIN and press OK." }),
3106
- /* @__PURE__ */ jsx10("p", { children: "3. Wait here \u2014 this page auto-updates once confirmed." })
3107
- ] }),
3108
- /* @__PURE__ */ jsx10(
3109
- "button",
3110
- {
3111
- onClick: () => {
3112
- setPhase("cancelled");
3113
- setMerchantRef(null);
3114
- },
3115
- className: "hsk-checkout-cancel-btn",
3116
- children: "Cancel payment"
3117
- }
3118
- )
3119
- ] }) : phase === "cancelled" ? /* @__PURE__ */ jsxs8("div", { className: "hsk-checkout-status-card cancelled", children: [
3120
- /* @__PURE__ */ jsx10("div", { className: "hsk-status-icon-wrap cancelled", children: /* @__PURE__ */ jsxs8("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
3121
- /* @__PURE__ */ jsx10("path", { d: "m15 9-6 6M9 9l6 6" }),
3122
- /* @__PURE__ */ jsx10("circle", { cx: "12", cy: "12", r: "10" })
3123
- ] }) }),
3124
- /* @__PURE__ */ jsx10("h3", { children: "Payment Cancelled" }),
3125
- /* @__PURE__ */ jsx10("p", { children: "No charge was made. You can update your phone number and try again whenever you're ready." }),
3126
- /* @__PURE__ */ jsxs8("div", { className: "hsk-checkout-status-actions", children: [
3127
- /* @__PURE__ */ jsx10("button", { onClick: () => {
3128
- setPhase("idle");
3129
- setPayError(null);
3130
- }, className: "hsk-pay-btn hsk-btn-primary", children: "Try again" }),
3131
- /* @__PURE__ */ jsx10("button", { onClick: onClose, className: "hsk-checkout-cancel-btn", children: "Back to cart" })
3132
- ] })
3133
- ] }) : phase === "failed" ? /* @__PURE__ */ jsxs8("div", { className: "hsk-checkout-status-card failed", children: [
3134
- /* @__PURE__ */ jsx10("div", { className: "hsk-status-icon-wrap failed", children: /* @__PURE__ */ jsxs8("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
3135
- /* @__PURE__ */ jsx10("circle", { cx: "12", cy: "12", r: "10" }),
3136
- /* @__PURE__ */ jsx10("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
3137
- /* @__PURE__ */ jsx10("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
3138
- ] }) }),
3139
- /* @__PURE__ */ jsx10("h3", { children: "Payment Failed" }),
3140
- /* @__PURE__ */ jsx10("p", { className: "hsk-checkout-error-text", children: payError || "Could not verify M-Pesa transaction. Please check your phone and try again." }),
3141
- /* @__PURE__ */ jsxs8("div", { className: "hsk-checkout-status-actions", children: [
3142
- /* @__PURE__ */ jsx10("button", { onClick: () => {
3143
- setPhase("idle");
3144
- setPayError(null);
3145
- }, className: "hsk-pay-btn hsk-btn-primary", children: "Try again" }),
3146
- /* @__PURE__ */ jsx10("button", { onClick: onClose, className: "hsk-checkout-cancel-btn", children: "Back to cart" })
3147
- ] })
3148
- ] }) : /* @__PURE__ */ jsxs8("div", { className: "hsk-checkout-payment-form-wrap", children: [
3149
- /* @__PURE__ */ jsx10("h3", { className: "hsk-checkout-section-title", children: "Payment details" }),
3150
- loadingConfig ? /* @__PURE__ */ jsx10("p", { className: "hsk-cart-loading", children: "Loading payment configuration..." }) : !hasPaymentMethods ? /* @__PURE__ */ jsx10("p", { className: "hsk-checkout-error", children: "No payment methods configured for this store." }) : /* @__PURE__ */ jsxs8("form", { onSubmit: handlePay, className: "hsk-stripe-checkout-form", children: [
3151
- /* @__PURE__ */ jsxs8("div", { className: "hsk-form-group", children: [
3152
- /* @__PURE__ */ jsx10("label", { className: "hsk-form-label", children: "M-Pesa Mobile Number" }),
3153
- /* @__PURE__ */ jsxs8("div", { className: "hsk-phone-input-container", children: [
3154
- /* @__PURE__ */ jsx10("span", { className: "hsk-phone-prefix", children: "254" }),
3155
- /* @__PURE__ */ jsx10(
3156
- "input",
3157
- {
3158
- type: "tel",
3159
- required: true,
3160
- placeholder: "712345678",
3161
- pattern: "[0-9]{9}",
3162
- maxLength: 9,
3163
- value: phone,
3164
- onChange: (e) => setPhone(e.target.value.replace(/\D/g, "")),
3165
- className: "hsk-phone-input-field"
3166
- }
3167
- )
3168
- ] }),
3169
- /* @__PURE__ */ jsx10("span", { className: "hsk-form-hint", children: "Enter your 9-digit number (e.g. 712345678)" })
3170
- ] }),
3171
- /* @__PURE__ */ jsxs8("div", { className: "hsk-form-group", children: [
3172
- /* @__PURE__ */ jsx10("label", { className: "hsk-form-label", children: "Email address" }),
3173
- /* @__PURE__ */ jsx10(
3174
- "input",
3175
- {
3176
- type: "email",
3177
- placeholder: "john.doe@example.com",
3178
- value: email,
3179
- onChange: (e) => setEmail(e.target.value),
3180
- className: "hsk-form-input"
3181
- }
3182
- )
3183
- ] }),
3184
- /* @__PURE__ */ jsxs8("div", { className: "hsk-form-row", children: [
3185
- /* @__PURE__ */ jsxs8("div", { className: "hsk-form-group", children: [
3186
- /* @__PURE__ */ jsx10("label", { className: "hsk-form-label", children: "First Name" }),
3187
- /* @__PURE__ */ jsx10(
3188
- "input",
3189
- {
3190
- type: "text",
3191
- placeholder: "John",
3192
- value: firstName,
3193
- onChange: (e) => setFirstName(e.target.value),
3194
- className: "hsk-form-input"
3195
- }
3196
- )
3197
- ] }),
3198
- /* @__PURE__ */ jsxs8("div", { className: "hsk-form-group", children: [
3199
- /* @__PURE__ */ jsx10("label", { className: "hsk-form-label", children: "Last Name" }),
3200
- /* @__PURE__ */ jsx10(
3201
- "input",
3202
- {
3203
- type: "text",
3204
- placeholder: "Doe",
3205
- value: lastName,
3206
- onChange: (e) => setLastName(e.target.value),
3207
- className: "hsk-form-input"
3208
- }
3209
- )
3210
- ] })
3211
- ] }),
3212
- payError && /* @__PURE__ */ jsx10("div", { className: "hsk-form-error-banner", children: payError }),
3213
- /* @__PURE__ */ jsxs8("button", { type: "submit", className: "hsk-checkout-submit-btn", children: [
3214
- "Pay ",
3215
- currency,
3216
- " ",
3217
- total.toLocaleString()
3218
- ] }),
3219
- /* @__PURE__ */ jsx10("div", { className: "hsk-checkout-footer-brand", children: /* @__PURE__ */ jsx10("span", { children: "Powered by Akropolys" }) })
3220
- ] })
3221
- ] }) }) })
3222
- ]
3223
- }
3224
- )
3225
- }
3226
- ),
3227
- document.body
3228
- );
3229
- }
3230
-
3231
- // src/components/CartDrawer.tsx
3232
- import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
3233
- function CartDrawer({
3234
- trigger,
3235
- className,
3236
- theme
3237
- }) {
3238
- const { cart, loading } = useCart3();
3239
- const [open, setOpen] = useState8(false);
3240
- const [showCheckout, setShowCheckout] = useState8(false);
3241
- const [mounted, setMounted] = useState8(false);
3242
- const client = useAkropolysContext6();
3243
- useEffect6(() => {
3244
- setMounted(true);
3245
- const handleTriggerCheckout = () => {
3246
- setShowCheckout(true);
3247
- setOpen(false);
3248
- };
3249
- window.addEventListener("akropolys:trigger_checkout", handleTriggerCheckout);
3250
- return () => {
3251
- window.removeEventListener("akropolys:trigger_checkout", handleTriggerCheckout);
3252
- };
3253
- }, []);
3254
- useEffect6(() => {
3255
- if (open) {
3256
- document.body.style.overflow = "hidden";
3257
- } else {
3258
- document.body.style.overflow = "";
3259
- }
3260
- return () => {
3261
- document.body.style.overflow = "";
3262
- };
3263
- }, [open]);
3264
- const handleCheckout = async () => {
3265
- if (!cart || cart.items.length === 0) return;
3266
- const event = new CustomEvent("akropolys:trigger_checkout", { cancelable: true });
3267
- window.dispatchEvent(event);
3268
- if (event.defaultPrevented) {
3269
- setOpen(false);
3270
- return;
3271
- }
3272
- setShowCheckout(true);
3273
- };
3274
- const isStringTheme = typeof theme === "string";
3275
- const hskThemeAttr = isStringTheme ? theme : void 0;
3276
- const customStyles = !isStringTheme && theme ? {
3277
- ...theme?.primaryColor && { "--hsk-primary": theme.primaryColor, "--hsk-primary-color": theme.primaryColor },
3278
- ...theme?.backgroundColor && { "--hsk-bg": theme.backgroundColor },
3279
- ...theme?.textColor && { "--hsk-text": theme.textColor },
3280
- ...theme?.fontFamily && { "--hsk-font": theme.fontFamily },
3281
- ...theme?.borderRadius && { "--hsk-border-radius": theme.borderRadius }
3282
- } : void 0;
3283
- return /* @__PURE__ */ jsxs9(Fragment5, { children: [
3284
- trigger ? /* @__PURE__ */ jsx11("div", { onClick: () => setOpen(true), style: { display: "inline-block" }, children: trigger }) : /* @__PURE__ */ jsxs9(
3285
- "button",
3286
- {
3287
- onClick: () => setOpen(true),
3288
- className: cn("hsk-cart-trigger", className),
3289
- style: customStyles,
3290
- "data-hsk-theme": hskThemeAttr,
3291
- "aria-label": "Open cart",
3292
- children: [
3293
- /* @__PURE__ */ jsxs9("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3294
- /* @__PURE__ */ jsx11("circle", { cx: "9", cy: "21", r: "1" }),
3295
- /* @__PURE__ */ jsx11("circle", { cx: "20", cy: "21", r: "1" }),
3296
- /* @__PURE__ */ jsx11("path", { d: "M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6" })
3297
- ] }),
3298
- cart && cart.item_count > 0 ? /* @__PURE__ */ jsx11("span", { className: "hsk-cart-trigger-badge", children: cart.item_count }) : null
3299
- ]
3300
- }
3301
- ),
3302
- open && mounted && createPortal4(
3303
- /* @__PURE__ */ jsx11(
3304
- "div",
3305
- {
3306
- className: "hsk-cart-backdrop",
3307
- style: customStyles,
3308
- "data-hsk-theme": hskThemeAttr,
3309
- onClick: () => setOpen(false),
3310
- children: /* @__PURE__ */ jsxs9(
3311
- "div",
3312
- {
3313
- className: "hsk-cart-bottom-sheet",
3314
- style: customStyles,
3315
- "data-hsk-theme": hskThemeAttr,
3316
- onClick: (e) => e.stopPropagation(),
3317
- children: [
3318
- /* @__PURE__ */ jsx11("div", { className: "hsk-cart-sheet-handle" }),
3319
- /* @__PURE__ */ jsxs9("div", { className: "hsk-cart-sheet-header", children: [
3320
- /* @__PURE__ */ jsx11("h2", { children: "Your Cart" }),
3321
- /* @__PURE__ */ jsx11("button", { onClick: () => setOpen(false), className: "hsk-close-btn", children: "\xD7" })
3322
- ] }),
3323
- /* @__PURE__ */ jsx11("div", { className: "hsk-cart-sheet-content", children: loading && !cart ? /* @__PURE__ */ jsx11("div", { className: "hsk-cart-loading", children: "Loading cart..." }) : !cart || cart.items.length === 0 ? /* @__PURE__ */ jsx11("div", { className: "hsk-cart-empty", children: "Your cart is empty." }) : /* @__PURE__ */ jsx11("ul", { className: "hsk-cart-items", children: cart.items.map((item) => /* @__PURE__ */ jsxs9("li", { className: "hsk-cart-item", children: [
3324
- item.image && /* @__PURE__ */ jsx11("img", { src: item.image, alt: item.name, className: "hsk-cart-item-img" }),
3325
- /* @__PURE__ */ jsxs9("div", { className: "hsk-cart-item-info", children: [
3326
- /* @__PURE__ */ jsx11("span", { className: "hsk-cart-item-name", children: item.name }),
3327
- /* @__PURE__ */ jsxs9("span", { className: "hsk-cart-item-price", children: [
3328
- item.currency,
3329
- " ",
3330
- item.price_numeric.toLocaleString(void 0, { minimumFractionDigits: 2 })
3331
- ] })
3332
- ] }),
3333
- /* @__PURE__ */ jsxs9("div", { className: "hsk-cart-item-qty", children: [
3334
- "x",
3335
- item.quantity
3336
- ] })
3337
- ] }, item.id)) }) }),
3338
- cart && cart.items.length > 0 && /* @__PURE__ */ jsxs9("div", { className: "hsk-cart-sheet-footer", children: [
3339
- /* @__PURE__ */ jsxs9("div", { className: "hsk-cart-total", children: [
3340
- /* @__PURE__ */ jsx11("span", { children: "Total" }),
3341
- /* @__PURE__ */ jsxs9("span", { children: [
3342
- cart.currency,
3343
- " ",
3344
- cart.total.toLocaleString(void 0, { minimumFractionDigits: 2 })
3345
- ] })
3346
- ] }),
3347
- /* @__PURE__ */ jsx11("button", { onClick: handleCheckout, className: "hsk-checkout-btn", children: "Checkout securely" })
3348
- ] })
3349
- ]
3350
- }
3351
- )
3352
- }
3353
- ),
3354
- document.body
3355
- ),
3356
- showCheckout && mounted && /* @__PURE__ */ jsx11(
3357
- CheckoutModal,
3358
- {
3359
- onClose: () => {
3360
- setShowCheckout(false);
3361
- setOpen(false);
3362
- },
3363
- theme: isStringTheme ? theme : void 0,
3364
- customStyles,
3365
- hskThemeAttr
3366
- }
3367
- )
3368
- ] });
3369
- }
3370
2848
  export {
3371
- CartBadge,
3372
- CartDrawer,
3373
2849
  ChatWidget,
3374
- CheckoutModal,
3375
2850
  ComparisonMatrix,
3376
2851
  KikuButton,
3377
2852
  ChatWidget as KikuChat,