@blocklet/payment-react
Version:
Reusable react components for payment kit v2
957 lines (956 loc) • 35.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
module.exports = PaymentPanel;
var _jsxRuntime = require("react/jsx-runtime");
var _react = require("react");
var _ArrowForward = _interopRequireDefault(require("@mui/icons-material/ArrowForward"));
var _CreditCard = _interopRequireDefault(require("@mui/icons-material/CreditCard"));
var _CurrencyBitcoin = _interopRequireDefault(require("@mui/icons-material/CurrencyBitcoin"));
var _ExpandMore = _interopRequireDefault(require("@mui/icons-material/ExpandMore"));
var _HelpOutline = _interopRequireDefault(require("@mui/icons-material/HelpOutline"));
var _LocalOfferOutlined = _interopRequireDefault(require("@mui/icons-material/LocalOfferOutlined"));
var _Close = _interopRequireDefault(require("@mui/icons-material/Close"));
var _LockOutlined = _interopRequireDefault(require("@mui/icons-material/LockOutlined"));
var _material = require("@mui/material");
var _context = require("@arcblock/ux/lib/Locale/context");
var _paymentReactHeadless = require("@blocklet/payment-react-headless");
var _ufo = require("ufo");
var _payment = require("../../../contexts/payment");
var _mobile = require("../../../hooks/mobile");
var _util = require("../../../libs/util");
var _overDueInvoicePayment = _interopRequireDefault(require("../../../components/over-due-invoice-payment"));
var _format = require("../../utils/format");
var _customerInfoCard = _interopRequireDefault(require("../../components/right/customer-info-card"));
var _subscriptionDisclaimer = _interopRequireDefault(require("../../components/right/subscription-disclaimer"));
var _statusFeedback = _interopRequireDefault(require("../../components/right/status-feedback"));
var _promotionInput = _interopRequireDefault(require("../../components/left/promotion-input"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function PaymentPanel() {
const {
t,
locale
} = (0, _context.useLocaleContext)();
const {
session,
sessionData,
subscription,
refresh
} = (0, _paymentReactHeadless.useSessionContext)();
const {
isDonation
} = (0, _paymentReactHeadless.useCheckoutStatus)();
const paymentMethod = (0, _paymentReactHeadless.usePaymentMethodFeature)();
const form = (0, _paymentReactHeadless.useCustomerFormFeature)();
const submit = (0, _paymentReactHeadless.useSubmitFeature)();
const pricing = (0, _paymentReactHeadless.usePricingFeature)();
const {
session: didSession,
connect,
prefix: paymentKitPrefix
} = (0, _payment.usePaymentContext)();
const {
inventoryOk
} = (0, _paymentReactHeadless.useLineItems)();
const promotion = (0, _paymentReactHeadless.usePromotion)();
const rate = (0, _paymentReactHeadless.useExchangeRate)();
const {
isMobile
} = (0, _mobile.useMobile)();
const isAmountLoading = paymentMethod.switching || rate.hasDynamicPricing && rate.status === "loading";
const {
currency,
types,
isStripe,
isCrypto
} = paymentMethod;
const mode = session?.mode || "payment";
const discounts = session?.discounts || [];
const isLoggedIn = !!didSession?.user;
const actionLabel = isDonation ? t("payment.checkout.donate") : t(`payment.checkout.${mode}`);
const buttonLabel = isLoggedIn ? actionLabel : t("payment.checkout.connect", {
action: actionLabel
});
const [customerLimited, setCustomerLimited] = (0, _react.useState)(false);
const [mobileDetailsOpen, setMobileDetailsOpen] = (0, _react.useState)(false);
const [promoDrawerOpen, setPromoDrawerOpen] = (0, _react.useState)(false);
(0, _react.useEffect)(() => {
if (submit.status === "failed" && submit.context?.code === "CUSTOMER_LIMITED") {
setCustomerLimited(true);
}
}, [submit.status, submit.context]);
const canSubmit = submit.status === "idle" && session?.status === "open" && inventoryOk;
const isProcessing = ["submitting", "waiting_did"].includes(submit.status);
const handleAction = (0, _react.useCallback)(() => {
if (!canSubmit) return;
submit.lock();
if (isLoggedIn || isDonation) {
submit.execute();
return;
}
didSession?.login?.(() => {
Promise.all([refresh(true), form.refetchCustomer()]).then(() => submit.execute()).catch(err => {
console.error("Post-login refresh failed:", err);
});
});
}, [canSubmit, isLoggedIn, isDonation, didSession, refresh, form, submit]);
(0, _react.useEffect)(() => {
if (didSession?.user && !submit.status.startsWith("submitting")) {
form.refetchCustomer();
}
}, [didSession?.user]);
const cryptoType = types.find(tp => tp.type === "crypto");
const cryptoMethods = (0, _react.useMemo)(() => paymentMethod.available.filter(m => m.type !== "stripe"), [paymentMethod.available]);
const networks = (0, _react.useMemo)(() => {
if (!cryptoMethods.length) return [];
return cryptoMethods.map(m => ({
id: m.id,
name: m.name,
logo: m.logo || "",
currencies: m.payment_currencies || []
}));
}, [cryptoMethods]);
const currentMethodId = paymentMethod.current?.id || "";
(0, _react.useEffect)(() => {
const handleKeyDown = e => {
if (e.key === "Enter" && canSubmit && submit.status === "idle") {
const tag = e.target?.tagName?.toLowerCase();
if (tag === "textarea") return;
handleAction();
}
};
document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}, [canSubmit, submit.status, handleAction]);
const didConnectOpenedRef = (0, _react.useRef)(false);
const didConnectSucceededRef = (0, _react.useRef)(false);
const submitStatusRef = (0, _react.useRef)(submit.status);
(0, _react.useEffect)(() => {
submitStatusRef.current = submit.status;
}, [submit.status]);
(0, _react.useEffect)(() => {
if (submit.status !== "waiting_did") {
didConnectOpenedRef.current = false;
didConnectSucceededRef.current = false;
return;
}
const ctx = submit.context;
if (ctx?.type !== "did_connect" || !connect) return;
if (didConnectOpenedRef.current) return;
didConnectOpenedRef.current = true;
const didPrefix = `${paymentKitPrefix || window.location.origin}/api/did`.replace(/([^:])\/\//g, "$1/");
connect.open({
locale,
action: ctx.action,
prefix: didPrefix,
saveConnect: false,
extraParams: ctx.extraParams,
onSuccess: async () => {
didConnectSucceededRef.current = true;
connect.close();
await submit.didConnectComplete();
},
onClose: () => {
connect.close();
if (submitStatusRef.current !== "waiting_did") return;
if (!didConnectSucceededRef.current) {
submit.reset();
}
},
onError: err => {
console.error("DID Connect error:", err);
if (submitStatusRef.current !== "waiting_did") return;
submit.reset();
},
messages: {
title: t("payment.checkout.connectModal.title", {
action: buttonLabel
}),
scan: t("payment.checkout.connectModal.scan"),
confirm: t("payment.checkout.connectModal.confirm")
}
});
}, [submit.status, submit.context, connect, locale, t, buttonLabel]);
const activeType = types.find(tp => tp.active)?.type || "crypto";
const hasMultipleTypes = types.length > 1;
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
display: "flex",
flexDirection: "column",
flex: 1,
minHeight: 0
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
flex: 1,
display: "flex",
flexDirection: "column",
overflowY: "auto",
minHeight: 0,
"&::-webkit-scrollbar": {
display: "none"
},
scrollbarWidth: "none"
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 13,
fontWeight: 700,
letterSpacing: "0.02em",
color: "text.primary",
mb: 2.5
},
children: t("payment.checkout.paymentDetails")
}), hasMultipleTypes && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.ToggleButtonGroup, {
value: activeType,
exclusive: true,
onChange: (_, v) => v && paymentMethod.setType(v),
fullWidth: true,
size: "small",
sx: {
mb: 2.5,
bgcolor: theme => theme.palette.mode === "dark" ? "rgba(255,255,255,0.06)" : "grey.100",
borderRadius: "10px",
p: 0.5,
"& .MuiToggleButton-root": {
textTransform: "none",
borderRadius: "8px !important",
py: 0.75,
border: "none",
fontSize: 14,
fontWeight: 500,
gap: 0.75,
color: "text.secondary"
},
"& .Mui-selected": {
bgcolor: "background.paper !important",
color: "text.primary",
fontWeight: 600,
boxShadow: theme => theme.palette.mode === "dark" ? "0 1px 3px rgba(0,0,0,0.3)" : "0 1px 3px rgba(0,0,0,0.08)",
"&:hover": {
bgcolor: "background.paper !important"
}
}
},
children: types.map(tp => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.ToggleButton, {
value: tp.type,
children: [tp.type === "stripe" ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_CreditCard.default, {
sx: {
fontSize: 18
}
}) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_CurrencyBitcoin.default, {
sx: {
fontSize: 18
}
}), tp.label || (tp.type === "stripe" ? "Card" : "Crypto")]
}, tp.type))
}), isCrypto && networks.length > 0 && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
spacing: 1.5,
sx: {
mb: 2.5
},
children: [networks.length > 1 && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
flex: 1
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 12,
fontWeight: 600,
color: "text.secondary",
mb: 0.5,
letterSpacing: "0.02em"
},
children: t("common.network")
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Select, {
value: currentMethodId,
onChange: e => {
const network = networks.find(n => n.id === e.target.value);
if (network?.currencies?.[0]) {
paymentMethod.setCurrency(network.currencies[0].id);
}
},
fullWidth: true,
size: "small",
sx: {
borderRadius: "8px",
bgcolor: theme => theme.palette.mode === "dark" ? "rgba(255,255,255,0.06)" : "grey.50",
"& .MuiOutlinedInput-notchedOutline": {
borderColor: "transparent"
},
"&:hover .MuiOutlinedInput-notchedOutline": {
borderColor: "divider"
},
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
borderColor: "primary.main",
borderWidth: 1
},
"& .MuiSelect-select": {
display: "flex",
alignItems: "center",
gap: 1,
py: 1
}
},
children: networks.map(net => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.MenuItem, {
value: net.id,
sx: {
gap: 1
},
children: [net.logo && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Avatar, {
src: net.logo,
sx: {
width: 20,
height: 20
}
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 14
},
children: net.name
})]
}, net.id))
})]
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
flex: 1
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 12,
fontWeight: 600,
color: "text.secondary",
mb: 0.5,
letterSpacing: "0.02em"
},
children: t("common.currency")
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Select, {
value: currency?.id || "",
onChange: e => paymentMethod.setCurrency(e.target.value),
fullWidth: true,
size: "small",
sx: {
borderRadius: "8px",
bgcolor: theme => theme.palette.mode === "dark" ? "rgba(255,255,255,0.06)" : "grey.50",
"& .MuiOutlinedInput-notchedOutline": {
borderColor: "transparent"
},
"&:hover .MuiOutlinedInput-notchedOutline": {
borderColor: "divider"
},
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
borderColor: "primary.main",
borderWidth: 1
},
"& .MuiSelect-select": {
display: "flex",
alignItems: "center",
gap: 1,
py: 1
}
},
children: (isCrypto && networks.length > 1 ? networks.find(n => n.id === currentMethodId)?.currencies || [] : cryptoType?.currencies || []).map(cur => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.MenuItem, {
value: cur.id,
sx: {
gap: 1
},
children: [cur.logo && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Avatar, {
src: cur.logo,
sx: {
width: 20,
height: 20
}
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 14
},
children: cur.symbol
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 12,
color: "text.secondary",
ml: 0.5
},
children: cur.name
})]
}, cur.id))
})]
})]
}), isStripe && currency && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
mb: 2.5
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 12,
fontWeight: 600,
color: "text.secondary",
mb: 0.5,
letterSpacing: "0.02em"
},
children: t("common.currency")
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Select, {
value: currency.id || "usd",
readOnly: true,
fullWidth: true,
size: "small",
IconComponent: () => null,
sx: {
borderRadius: "8px",
bgcolor: theme => theme.palette.mode === "dark" ? "rgba(255,255,255,0.06)" : "grey.50",
"& .MuiOutlinedInput-notchedOutline": {
borderColor: "transparent !important"
},
"& .MuiSelect-select": {
display: "flex",
alignItems: "center",
gap: 1,
py: 1
}
},
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.MenuItem, {
value: currency.id || "usd",
sx: {
gap: 1
},
children: [currency.logo && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Avatar, {
src: currency.logo,
sx: {
width: 20,
height: 20
}
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 14,
fontWeight: 600
},
children: currency.symbol
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 12,
color: "text.secondary",
ml: 0.5
},
children: currency.name
})]
})
})]
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_customerInfoCard.default, {
form,
isLoggedIn
})]
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
className: "cko-v2-submit-btn",
sx: {
flexShrink: 0
},
children: [isMobile && pricing.staking && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
onClick: () => setMobileDetailsOpen(!mobileDetailsOpen),
sx: {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
cursor: "pointer",
mb: 1
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 13,
fontWeight: 600,
color: "text.secondary"
},
children: t("payment.checkout.orderSummary")
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_ExpandMore.default, {
sx: {
fontSize: 18,
color: "text.secondary",
transition: "0.2s",
transform: mobileDetailsOpen ? "rotate(180deg)" : "rotate(0deg)"
}
})]
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Collapse, {
in: mobileDetailsOpen,
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
justifyContent: "space-between",
alignItems: "center",
sx: {
mb: 1
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
spacing: 0.5,
alignItems: "center",
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 13,
color: "text.secondary"
},
children: t("payment.checkout.staking.title")
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_HelpOutline.default, {
sx: {
fontSize: 14,
color: "text.disabled"
}
})]
}), isAmountLoading ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
variant: "text",
width: 60,
height: 18
}) : /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
sx: {
fontSize: 13,
fontWeight: 600
},
children: ["+", pricing.staking]
})]
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Divider, {
sx: {
mb: 1
}
})]
})]
}), !isMobile && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Divider, {
sx: {
mb: 2
}
}), pricing.staking && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
justifyContent: "space-between",
alignItems: "center",
sx: {
mb: 1
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
spacing: 0.5,
alignItems: "center",
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 14,
color: "text.secondary"
},
children: t("payment.checkout.staking.title")
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Tooltip, {
title: t("payment.checkout.staking.tooltip"),
placement: "top",
arrow: true,
slotProps: {
popper: {
sx: _format.whiteTooltipSx
}
},
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_HelpOutline.default, {
sx: {
fontSize: 16,
color: "text.disabled"
}
})
})]
}), isAmountLoading ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
variant: "text",
width: 80,
height: 22
}) : /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
sx: {
fontSize: 14,
fontWeight: 600
},
children: ["+", pricing.staking]
})]
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_promotionInput.default, {
promotion: {
applied: promotion.applied,
code: promotion.code,
active: promotion.active,
inactiveReason: promotion.inactiveReason,
apply: promotion.apply,
remove: promotion.remove
},
discounts,
discountAmount: pricing.discount,
currency,
isAmountLoading
})]
}), (() => {
const totalStr = pricing.total || "0";
const parts = totalStr.split(/\s+/);
const num = parts[0] || "0";
const sym = parts.slice(1).join(" ") || currency?.symbol || "";
const dotIdx = num.indexOf(".");
const intPart = dotIdx >= 0 ? num.slice(0, dotIdx) : num;
const decPart = dotIdx >= 0 ? num.slice(dotIdx) : "";
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
mb: isMobile ? 1.5 : 2.5
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
justifyContent: "space-between",
alignItems: "flex-end",
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontWeight: 700,
fontSize: 14,
color: "text.secondary",
pb: 0.5
},
children: t("common.totalDue")
}), isAmountLoading ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
variant: "text",
width: 140,
height: 44
}) : /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
textAlign: "right"
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
component: "span",
sx: {
fontSize: {
xs: 28,
md: 36
},
fontWeight: 800,
color: "text.primary",
lineHeight: 1,
transition: "opacity 0.3s ease"
},
children: intPart
}), decPart && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
component: "span",
sx: {
fontSize: {
xs: 16,
md: 20
},
fontWeight: 700,
color: "text.secondary",
lineHeight: 1
},
children: decPart
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
component: "span",
sx: {
fontSize: {
xs: 14,
md: 16
},
fontWeight: 600,
color: "text.secondary",
ml: 0.75
},
children: sym
})]
})]
}), (pricing.usdEquivalent || isMobile && promotion.active) && !isAmountLoading && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
justifyContent: "space-between",
alignItems: "center",
sx: {
mt: 0.25
},
children: [(() => {
if (isMobile && !promotion.applied && promotion.active) {
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
onClick: () => setPromoDrawerOpen(true),
sx: {
display: "flex",
alignItems: "center",
gap: 0.5,
cursor: "pointer"
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_LocalOfferOutlined.default, {
sx: {
fontSize: 14,
color: "primary.main"
}
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 12,
fontWeight: 600,
color: "primary.main"
},
children: (0, _format.tSafe)(t, "payment.checkout.promotion.add", "Add promo code")
})]
});
}
if (isMobile && promotion.applied) {
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
alignItems: "center",
spacing: 0.5,
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_LocalOfferOutlined.default, {
sx: {
fontSize: 14,
color: "success.main"
}
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 12,
fontWeight: 600,
color: "success.main"
},
children: promotion.code
}), pricing.discount && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
sx: {
fontSize: 11,
color: "text.secondary"
},
children: ["(-", pricing.discount, ")"]
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_Close.default, {
onClick: promotion.remove,
sx: {
fontSize: 14,
color: "error.main",
cursor: "pointer",
ml: 0.25
}
})]
});
}
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {});
})(), pricing.usdEquivalent && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
sx: {
fontSize: 13,
color: "text.secondary"
},
children: ["\u2248 ", pricing.usdEquivalent]
})]
})]
});
})(), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Button, {
variant: "contained",
size: "large",
fullWidth: true,
disabled: !canSubmit || submit.status === "waiting_stripe",
onClick: handleAction,
startIcon: isProcessing ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.CircularProgress, {
size: 20,
color: "inherit"
}) : null,
sx: {
py: 1.5,
fontSize: "1.1rem",
fontWeight: 600,
textTransform: "none",
borderRadius: "12px",
color: theme => (0, _format.primaryContrastColor)(theme),
position: "relative",
overflow: "hidden",
"&:hover": {
bgcolor: "primary.main"
},
"&:hover .arrow-icon": {
transform: "translateX(4px)"
},
"&:hover .shine-layer": {
transform: "translateX(100%)"
}
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
component: "span",
sx: {
position: "relative",
zIndex: 1
},
children: isProcessing ? `${t("payment.checkout.processing")}...` : buttonLabel
}), !isProcessing && /* @__PURE__ */(0, _jsxRuntime.jsx)(_ArrowForward.default, {
className: "arrow-icon",
sx: {
ml: 1,
position: "relative",
zIndex: 1,
transition: "transform 0.2s ease"
}
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
className: "shine-layer",
sx: {
position: "absolute",
inset: 0,
background: "linear-gradient(90deg, transparent, rgba(255,255,255,0.12), transparent)",
transform: "translateX(-100%)",
transition: "transform 0.7s ease",
pointerEvents: "none"
}
})]
}), isMobile && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
alignItems: "center",
justifyContent: "center",
spacing: 0.75,
sx: {
mt: 1.5,
opacity: 0.55
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_LockOutlined.default, {
sx: {
fontSize: 13,
color: "text.secondary"
}
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 11,
color: "text.secondary"
},
children: (0, _format.tSafe)(t, "payment.checkout.ssl", "SSL Secure")
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 11,
color: "text.disabled"
},
children: "\xB7"
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 11,
color: "text.secondary"
},
children: (0, _format.tSafe)(t, "common.terms", "Terms")
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 11,
color: "text.disabled"
},
children: "|"
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 11,
color: "text.secondary"
},
children: (0, _format.tSafe)(t, "common.privacy", "Privacy")
})]
})]
}), isMobile && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Drawer, {
anchor: "bottom",
open: promoDrawerOpen,
onClose: () => setPromoDrawerOpen(false),
PaperProps: {
sx: {
borderRadius: "16px 16px 0 0",
p: 3,
pb: 4,
minHeight: "30vh"
}
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
sx: {
width: 40,
height: 4,
bgcolor: "divider",
borderRadius: 2,
mx: "auto",
mb: 3
}
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontWeight: 700,
fontSize: 16,
mb: 2
},
children: (0, _format.tSafe)(t, "payment.checkout.promotion.add", "Add promo code")
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_promotionInput.default, {
initialShowInput: true,
promotion: {
applied: promotion.applied,
code: promotion.code,
active: promotion.active,
inactiveReason: promotion.inactiveReason,
apply: async (...args) => {
const result = await promotion.apply(...args);
if (result.success) setPromoDrawerOpen(false);
return result;
},
remove: promotion.remove
},
discounts,
discountAmount: pricing.discount,
currency
})]
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
flexShrink: 0
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_subscriptionDisclaimer.default, {
mode,
subscription,
staking: pricing.staking,
appName: (0, _util.getStatementDescriptor)(session?.line_items || [])
}), !isMobile && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
alignItems: "center",
justifyContent: "center",
spacing: 0.75,
sx: {
mt: 2.5,
opacity: 0.55
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_LockOutlined.default, {
sx: {
fontSize: 13,
color: "text.secondary"
}
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 11,
color: "text.secondary"
},
children: (0, _format.tSafe)(t, "payment.checkout.ssl", "SSL Secure")
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 11,
color: "text.disabled"
},
children: "\xB7"
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 11,
color: "text.secondary"
},
children: (0, _format.tSafe)(t, "common.terms", "Terms")
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 11,
color: "text.disabled"
},
children: "|"
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
fontSize: 11,
color: "text.secondary"
},
children: (0, _format.tSafe)(t, "common.privacy", "Privacy")
})]
})]
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_statusFeedback.default, {
status: submit.status,
context: submit.context,
onReset: submit.reset
}), customerLimited && /* @__PURE__ */(0, _jsxRuntime.jsx)(_overDueInvoicePayment.default, {
customerId: sessionData?.customer?.id || session?.user?.did,
onPaid: () => {
setCustomerLimited(false);
submit.retry();
},
alertMessage: t("payment.customer.pastDue.alert.customMessage"),
detailLinkOptions: {
enabled: true,
onClick: () => {
setCustomerLimited(false);
window.open((0, _ufo.joinURL)((0, _util.getPrefix)(), `/customer/invoice/past-due?referer=${encodeURIComponent(window.location.href)}`), "_self");
}
},
dialogProps: {
open: customerLimited,
onClose: () => {
setCustomerLimited(false);
submit.reset();
},
title: t("payment.customer.pastDue.alert.title")
}
})]
});
}