@huskel/sdk 0.4.7 → 0.4.9
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.css +480 -0
- package/dist/index.css.map +1 -1
- package/dist/index.js +246 -72
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +249 -75
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -97,6 +97,12 @@ var HuskelAPI = class {
|
|
|
97
97
|
if (sessionId) {
|
|
98
98
|
headers["X-Huskel-Session-Id"] = sessionId;
|
|
99
99
|
}
|
|
100
|
+
if (typeof window !== "undefined") {
|
|
101
|
+
const phone = localStorage.getItem("huskel_user_phone");
|
|
102
|
+
if (phone) {
|
|
103
|
+
headers["X-Huskel-Shopper-Phone"] = phone;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
100
106
|
const res = await fetch(url, {
|
|
101
107
|
method: "POST",
|
|
102
108
|
headers,
|
|
@@ -175,6 +181,12 @@ var HuskelAPI = class {
|
|
|
175
181
|
if (shopperId) headers["X-Huskel-Shopper-Id"] = shopperId;
|
|
176
182
|
const sessionId = (_b = this.getSessionId) == null ? void 0 : _b.call(this);
|
|
177
183
|
if (sessionId) headers["X-Huskel-Session-Id"] = sessionId;
|
|
184
|
+
if (typeof window !== "undefined") {
|
|
185
|
+
const phone = localStorage.getItem("huskel_user_phone");
|
|
186
|
+
if (phone) {
|
|
187
|
+
headers["X-Huskel-Shopper-Phone"] = phone;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
178
190
|
return headers;
|
|
179
191
|
}
|
|
180
192
|
async getCart() {
|
|
@@ -1660,7 +1672,12 @@ function ChatModal({
|
|
|
1660
1672
|
const [selectedProduct, setSelectedProduct] = (0, import_react12.useState)(null);
|
|
1661
1673
|
const bottomRef = (0, import_react12.useRef)(null);
|
|
1662
1674
|
const textareaRef = (0, import_react12.useRef)(null);
|
|
1663
|
-
const [phoneInput, setPhoneInput] = (0, import_react12.useState)(
|
|
1675
|
+
const [phoneInput, setPhoneInput] = (0, import_react12.useState)(() => {
|
|
1676
|
+
if (typeof window !== "undefined") {
|
|
1677
|
+
return localStorage.getItem("huskel_user_phone") || "";
|
|
1678
|
+
}
|
|
1679
|
+
return "";
|
|
1680
|
+
});
|
|
1664
1681
|
const [merchantRef, setMerchantRef] = (0, import_react12.useState)(null);
|
|
1665
1682
|
const [paymentPhase, setPaymentPhase] = (0, import_react12.useState)("idle");
|
|
1666
1683
|
const { status: pollStatus } = usePaymentPolling({
|
|
@@ -1688,7 +1705,10 @@ function ChatModal({
|
|
|
1688
1705
|
const handlePhoneSubmit = async () => {
|
|
1689
1706
|
if (!phoneInput.trim()) return;
|
|
1690
1707
|
try {
|
|
1691
|
-
|
|
1708
|
+
if (typeof window !== "undefined") {
|
|
1709
|
+
localStorage.setItem("huskel_user_phone", phoneInput.trim());
|
|
1710
|
+
}
|
|
1711
|
+
const res = await client.api.initiatePayment(phoneInput.trim());
|
|
1692
1712
|
setMerchantRef(res.merchantReference);
|
|
1693
1713
|
setPaymentPhase("awaiting");
|
|
1694
1714
|
} catch (e) {
|
|
@@ -1778,7 +1798,7 @@ function ChatModal({
|
|
|
1778
1798
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SparkleIcon3, {}) }),
|
|
1779
1799
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-cb-ai-body", children: [
|
|
1780
1800
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-ai-text", children: renderMarkdown(msg.content) }),
|
|
1781
|
-
isLast && sources.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1801
|
+
isLast && sources.length > 0 && (lastAction == null ? void 0 : lastAction.type) !== "request_phone" && (lastAction == null ? void 0 : lastAction.type) !== "awaiting_payment" && (lastAction == null ? void 0 : lastAction.type) !== "checkout" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1782
1802
|
SourcesCarousel,
|
|
1783
1803
|
{
|
|
1784
1804
|
sources,
|
|
@@ -1960,98 +1980,246 @@ function CheckoutModal({
|
|
|
1960
1980
|
customStyles,
|
|
1961
1981
|
hskThemeAttr
|
|
1962
1982
|
}) {
|
|
1963
|
-
var _a, _b, _c, _d;
|
|
1964
1983
|
const { cart, loading: cartLoading } = useCart();
|
|
1965
1984
|
const client = useHuskelContext();
|
|
1966
1985
|
const [config, setConfig] = (0, import_react13.useState)(null);
|
|
1967
|
-
const [
|
|
1968
|
-
const [
|
|
1969
|
-
|
|
1986
|
+
const [loadingConfig, setLoadingConfig] = (0, import_react13.useState)(true);
|
|
1987
|
+
const [phone, setPhone] = (0, import_react13.useState)(() => {
|
|
1988
|
+
if (typeof window !== "undefined") {
|
|
1989
|
+
return localStorage.getItem("huskel_user_phone") || "";
|
|
1990
|
+
}
|
|
1991
|
+
return "";
|
|
1992
|
+
});
|
|
1993
|
+
const [email, setEmail] = (0, import_react13.useState)(() => {
|
|
1994
|
+
if (typeof window !== "undefined") {
|
|
1995
|
+
return localStorage.getItem("huskel_user_email") || "";
|
|
1996
|
+
}
|
|
1997
|
+
return "";
|
|
1998
|
+
});
|
|
1999
|
+
const [firstName, setFirstName] = (0, import_react13.useState)(() => {
|
|
2000
|
+
if (typeof window !== "undefined") {
|
|
2001
|
+
return localStorage.getItem("huskel_user_firstname") || "";
|
|
2002
|
+
}
|
|
2003
|
+
return "";
|
|
2004
|
+
});
|
|
2005
|
+
const [lastName, setLastName] = (0, import_react13.useState)(() => {
|
|
2006
|
+
if (typeof window !== "undefined") {
|
|
2007
|
+
return localStorage.getItem("huskel_user_lastname") || "";
|
|
2008
|
+
}
|
|
2009
|
+
return "";
|
|
2010
|
+
});
|
|
2011
|
+
const [phase, setPhase] = (0, import_react13.useState)("idle");
|
|
2012
|
+
const [merchantRef, setMerchantRef] = (0, import_react13.useState)(null);
|
|
2013
|
+
const [payError, setPayError] = (0, import_react13.useState)(null);
|
|
2014
|
+
const {} = usePaymentPolling({
|
|
2015
|
+
client: client.api,
|
|
2016
|
+
merchantReference: merchantRef,
|
|
2017
|
+
onSuccess: () => {
|
|
2018
|
+
setPhase("done");
|
|
2019
|
+
setMerchantRef(null);
|
|
2020
|
+
},
|
|
2021
|
+
onFailure: () => {
|
|
2022
|
+
setPhase("failed");
|
|
2023
|
+
setPayError("Payment failed or timed out. Please try again.");
|
|
2024
|
+
setMerchantRef(null);
|
|
2025
|
+
}
|
|
2026
|
+
});
|
|
1970
2027
|
(0, import_react13.useEffect)(() => {
|
|
1971
|
-
client.api.getCheckoutConfig().then((res) => setConfig(res.payment_methods)).catch((
|
|
2028
|
+
client.api.getCheckoutConfig().then((res) => setConfig(res.payment_methods)).catch(() => {
|
|
2029
|
+
}).finally(() => setLoadingConfig(false));
|
|
1972
2030
|
}, [client]);
|
|
1973
|
-
const
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
2031
|
+
const hasPaymentMethods = config && Object.values(config).some((m) => m.enabled);
|
|
2032
|
+
const handlePay = async (e) => {
|
|
2033
|
+
e.preventDefault();
|
|
2034
|
+
if (!phone.trim()) {
|
|
2035
|
+
setPayError("Phone number is required.");
|
|
2036
|
+
return;
|
|
2037
|
+
}
|
|
2038
|
+
setPayError(null);
|
|
2039
|
+
setPhase("awaiting");
|
|
2040
|
+
try {
|
|
2041
|
+
if (typeof window !== "undefined") {
|
|
2042
|
+
localStorage.setItem("huskel_user_phone", phone.trim());
|
|
2043
|
+
localStorage.setItem("huskel_user_email", email.trim());
|
|
2044
|
+
localStorage.setItem("huskel_user_firstname", firstName.trim());
|
|
2045
|
+
localStorage.setItem("huskel_user_lastname", lastName.trim());
|
|
2046
|
+
}
|
|
2047
|
+
const res = await client.api.initiatePayment(phone.trim(), email, firstName, lastName);
|
|
2048
|
+
if (res == null ? void 0 : res.merchantReference) {
|
|
2049
|
+
setMerchantRef(res.merchantReference);
|
|
2050
|
+
} else {
|
|
2051
|
+
throw new Error("No merchant reference returned.");
|
|
1988
2052
|
}
|
|
1989
|
-
}
|
|
2053
|
+
} catch (err) {
|
|
2054
|
+
setPhase("failed");
|
|
2055
|
+
setPayError(err.message || "Could not connect to payment processor.");
|
|
2056
|
+
}
|
|
1990
2057
|
};
|
|
1991
|
-
const
|
|
2058
|
+
const currency = (cart == null ? void 0 : cart.currency) || "KES";
|
|
2059
|
+
const total = (cart == null ? void 0 : cart.total) || 0;
|
|
2060
|
+
const backdropStyle = __spreadProps(__spreadValues({}, customStyles), { fontSize: "15px", fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif', zIndex: 999999 });
|
|
1992
2061
|
return (0, import_react_dom3.createPortal)(
|
|
1993
2062
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1994
2063
|
"div",
|
|
1995
2064
|
{
|
|
1996
|
-
className: "hsk-
|
|
1997
|
-
style:
|
|
2065
|
+
className: "hsk-checkout-backdrop-full",
|
|
2066
|
+
style: backdropStyle,
|
|
1998
2067
|
"data-hsk-theme": hskThemeAttr,
|
|
1999
|
-
onClick: onClose,
|
|
2000
2068
|
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2001
2069
|
"div",
|
|
2002
2070
|
{
|
|
2003
|
-
className: "hsk-checkout-modal",
|
|
2071
|
+
className: "hsk-checkout-modal-full",
|
|
2004
2072
|
style: customStyles,
|
|
2005
2073
|
"data-hsk-theme": hskThemeAttr,
|
|
2006
|
-
onClick: (e) => e.stopPropagation(),
|
|
2007
2074
|
children: [
|
|
2008
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-checkout-
|
|
2009
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.
|
|
2015
|
-
|
|
2075
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-checkout-panel-left", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-checkout-left-content", children: [
|
|
2076
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("button", { onClick: (e) => {
|
|
2077
|
+
e.preventDefault();
|
|
2078
|
+
e.stopPropagation();
|
|
2079
|
+
onClose();
|
|
2080
|
+
}, className: "hsk-checkout-back-btn", disabled: phase !== "idle", children: [
|
|
2081
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2082
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "19", y1: "12", x2: "5", y2: "12" }),
|
|
2083
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "12 19 5 12 12 5" })
|
|
2084
|
+
] }),
|
|
2085
|
+
"Back to store"
|
|
2016
2086
|
] }),
|
|
2017
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("
|
|
2018
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
|
|
2025
|
-
item.quantity,
|
|
2026
|
-
"x ",
|
|
2027
|
-
item.name
|
|
2028
|
-
] }),
|
|
2029
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
|
|
2030
|
-
item.currency,
|
|
2031
|
-
" ",
|
|
2032
|
-
(item.price_numeric * item.quantity).toLocaleString(void 0, { minimumFractionDigits: 2 })
|
|
2033
|
-
] })
|
|
2034
|
-
] }, item.id)) }),
|
|
2035
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-checkout-total", children: [
|
|
2036
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Total" }),
|
|
2037
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
|
|
2038
|
-
cart.currency,
|
|
2039
|
-
" ",
|
|
2040
|
-
cart.total.toLocaleString(void 0, { minimumFractionDigits: 2 })
|
|
2041
|
-
] })
|
|
2042
|
-
] })
|
|
2087
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-checkout-store-info", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h2", { children: "Secure Checkout" }) }),
|
|
2088
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-checkout-amount-due", children: [
|
|
2089
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-checkout-label-muted", children: "Pay total" }),
|
|
2090
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-checkout-grand-total", children: [
|
|
2091
|
+
currency,
|
|
2092
|
+
" ",
|
|
2093
|
+
total.toLocaleString(void 0, { minimumFractionDigits: 2 })
|
|
2043
2094
|
] })
|
|
2044
2095
|
] }),
|
|
2045
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.
|
|
2046
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2096
|
+
cartLoading || !cart ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "hsk-cart-loading", children: "Loading order..." }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-checkout-items-list-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { className: "hsk-checkout-items-list", children: cart.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("li", { className: "hsk-checkout-item-row", children: [
|
|
2097
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-checkout-item-img-container", children: [
|
|
2098
|
+
item.image ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: item.image, alt: item.name, className: "hsk-checkout-item-img" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-checkout-item-img-placeholder", children: "\u{1F6D2}" }),
|
|
2099
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-checkout-item-qty-badge", children: item.quantity })
|
|
2100
|
+
] }),
|
|
2101
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-checkout-item-details", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-checkout-item-name", children: item.name }) }),
|
|
2102
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "hsk-checkout-item-price", children: [
|
|
2103
|
+
item.currency,
|
|
2104
|
+
" ",
|
|
2105
|
+
(item.price_numeric * item.quantity).toLocaleString(void 0, { minimumFractionDigits: 2 })
|
|
2052
2106
|
] })
|
|
2107
|
+
] }, item.id)) }) })
|
|
2108
|
+
] }) }),
|
|
2109
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-checkout-panel-right", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-checkout-right-content", children: phase === "done" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-checkout-status-card success", children: [
|
|
2110
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-status-icon-wrap success", children: "\u2705" }),
|
|
2111
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { children: "Payment Successful!" }),
|
|
2112
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: "Your transaction has been confirmed successfully. Thank you for your order!" }),
|
|
2113
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { onClick: onClose, className: "hsk-pay-btn hsk-btn-primary", style: { marginTop: "1.5rem" }, children: "Continue Shopping" })
|
|
2114
|
+
] }) : phase === "awaiting" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-checkout-status-card awaiting", children: [
|
|
2115
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-status-spinner-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-status-spinner" }) }),
|
|
2116
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { children: "Confirm payment on your phone" }),
|
|
2117
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("p", { children: [
|
|
2118
|
+
"We've sent an M-Pesa STK push prompt to ",
|
|
2119
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("strong", { children: [
|
|
2120
|
+
"254",
|
|
2121
|
+
phone
|
|
2122
|
+
] }),
|
|
2123
|
+
"."
|
|
2124
|
+
] }),
|
|
2125
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-checkout-stk-instructions", children: [
|
|
2126
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: "1. Check your phone lockscreen for the M-Pesa prompt." }),
|
|
2127
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: "2. Enter your M-Pesa PIN and press OK." }),
|
|
2128
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: "3. Wait here; this page will automatically redirect once confirmed." })
|
|
2129
|
+
] }),
|
|
2130
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2131
|
+
"button",
|
|
2132
|
+
{
|
|
2133
|
+
onClick: () => {
|
|
2134
|
+
setPhase("idle");
|
|
2135
|
+
setMerchantRef(null);
|
|
2136
|
+
},
|
|
2137
|
+
className: "hsk-checkout-cancel-btn",
|
|
2138
|
+
children: "Cancel and change phone number"
|
|
2139
|
+
}
|
|
2140
|
+
)
|
|
2141
|
+
] }) : phase === "failed" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-checkout-status-card failed", children: [
|
|
2142
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-status-icon-wrap failed", children: "\u274C" }),
|
|
2143
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { children: "Payment failed or timed out" }),
|
|
2144
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "hsk-checkout-error-text", children: payError || "Could not verify M-Pesa transaction." }),
|
|
2145
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { onClick: () => {
|
|
2146
|
+
setPhase("idle");
|
|
2147
|
+
setPayError(null);
|
|
2148
|
+
}, className: "hsk-pay-btn hsk-btn-primary", style: { marginTop: "1.5rem" }, children: "Try Again" })
|
|
2149
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-checkout-payment-form-wrap", children: [
|
|
2150
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: "hsk-checkout-section-title", children: "Payment details" }),
|
|
2151
|
+
loadingConfig ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "hsk-cart-loading", children: "Loading payment configuration..." }) : !hasPaymentMethods ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "hsk-checkout-error", children: "No payment methods configured for this store." }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { onSubmit: handlePay, className: "hsk-stripe-checkout-form", children: [
|
|
2152
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-form-group", children: [
|
|
2153
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { className: "hsk-form-label", children: "M-Pesa Mobile Number" }),
|
|
2154
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-phone-input-container", children: [
|
|
2155
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-phone-prefix", children: "254" }),
|
|
2156
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2157
|
+
"input",
|
|
2158
|
+
{
|
|
2159
|
+
type: "tel",
|
|
2160
|
+
required: true,
|
|
2161
|
+
placeholder: "712345678",
|
|
2162
|
+
pattern: "[0-9]{9}",
|
|
2163
|
+
maxLength: 9,
|
|
2164
|
+
value: phone,
|
|
2165
|
+
onChange: (e) => setPhone(e.target.value.replace(/\D/g, "")),
|
|
2166
|
+
className: "hsk-phone-input-field"
|
|
2167
|
+
}
|
|
2168
|
+
)
|
|
2169
|
+
] }),
|
|
2170
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-form-hint", children: "Enter your 9-digit number (e.g. 712345678)" })
|
|
2171
|
+
] }),
|
|
2172
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-form-group", children: [
|
|
2173
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { className: "hsk-form-label", children: "Email address" }),
|
|
2174
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2175
|
+
"input",
|
|
2176
|
+
{
|
|
2177
|
+
type: "email",
|
|
2178
|
+
placeholder: "john.doe@example.com",
|
|
2179
|
+
value: email,
|
|
2180
|
+
onChange: (e) => setEmail(e.target.value),
|
|
2181
|
+
className: "hsk-form-input"
|
|
2182
|
+
}
|
|
2183
|
+
)
|
|
2184
|
+
] }),
|
|
2185
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-form-row", children: [
|
|
2186
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-form-group", children: [
|
|
2187
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { className: "hsk-form-label", children: "First Name" }),
|
|
2188
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2189
|
+
"input",
|
|
2190
|
+
{
|
|
2191
|
+
type: "text",
|
|
2192
|
+
placeholder: "John",
|
|
2193
|
+
value: firstName,
|
|
2194
|
+
onChange: (e) => setFirstName(e.target.value),
|
|
2195
|
+
className: "hsk-form-input"
|
|
2196
|
+
}
|
|
2197
|
+
)
|
|
2198
|
+
] }),
|
|
2199
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-form-group", children: [
|
|
2200
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { className: "hsk-form-label", children: "Last Name" }),
|
|
2201
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2202
|
+
"input",
|
|
2203
|
+
{
|
|
2204
|
+
type: "text",
|
|
2205
|
+
placeholder: "Doe",
|
|
2206
|
+
value: lastName,
|
|
2207
|
+
onChange: (e) => setLastName(e.target.value),
|
|
2208
|
+
className: "hsk-form-input"
|
|
2209
|
+
}
|
|
2210
|
+
)
|
|
2211
|
+
] })
|
|
2212
|
+
] }),
|
|
2213
|
+
payError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-form-error-banner", children: payError }),
|
|
2214
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("button", { type: "submit", className: "hsk-checkout-submit-btn", children: [
|
|
2215
|
+
"Pay ",
|
|
2216
|
+
currency,
|
|
2217
|
+
" ",
|
|
2218
|
+
total.toLocaleString()
|
|
2219
|
+
] }),
|
|
2220
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-checkout-footer-brand", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Powered by Huskel AI" }) })
|
|
2053
2221
|
] })
|
|
2054
|
-
] }) })
|
|
2222
|
+
] }) }) })
|
|
2055
2223
|
]
|
|
2056
2224
|
}
|
|
2057
2225
|
)
|
|
@@ -2096,6 +2264,12 @@ function CartDrawer({
|
|
|
2096
2264
|
}, [open]);
|
|
2097
2265
|
const handleCheckout = async () => {
|
|
2098
2266
|
if (!cart || cart.items.length === 0) return;
|
|
2267
|
+
const event = new CustomEvent("huskel:trigger_checkout", { cancelable: true });
|
|
2268
|
+
window.dispatchEvent(event);
|
|
2269
|
+
if (event.defaultPrevented) {
|
|
2270
|
+
setOpen(false);
|
|
2271
|
+
return;
|
|
2272
|
+
}
|
|
2099
2273
|
setShowCheckout(true);
|
|
2100
2274
|
};
|
|
2101
2275
|
const isStringTheme = typeof theme === "string";
|