@blocklet/payment-react
Version:
Reusable react components for payment kit v2
391 lines (388 loc) • 11.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
module.exports = PaymentSuccess;
var _jsxRuntime = require("react/jsx-runtime");
var _bridge = _interopRequireDefault(require("@arcblock/bridge"));
var _useBrowser = _interopRequireDefault(require("@arcblock/react-hooks/lib/useBrowser"));
var _context = require("@arcblock/ux/lib/Locale/context");
var _material = require("@mui/material");
var _react = require("react");
var _ufo = require("ufo");
var _ux = require("@arcblock/ux");
var _payment = require("../contexts/payment");
var _progressItem = require("./progress-item");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function PaymentSuccess({
mode,
pageInfo = {},
vendorCount = 0,
sessionId = "",
message,
action,
payee,
invoiceId = "",
subscriptionId = "",
subscriptions = []
}) {
const {
t,
locale
} = (0, _context.useLocaleContext)();
const {
prefix,
api
} = (0, _payment.usePaymentContext)();
const [vendorStatus, setVendorStatus] = (0, _react.useState)(null);
const [isAllCompleted, setIsAllCompleted] = (0, _react.useState)(false);
const [hasFailed, setHasFailed] = (0, _react.useState)(false);
const timerRef = (0, _react.useRef)(Date.now());
const browser = (0, _useBrowser.default)();
const inArcsphere = browser?.arcSphere;
let next = null;
(0, _react.useEffect)(() => {
if (vendorCount === 0 || !sessionId) return void 0;
const fetchVendorStatus = async interval2 => {
try {
const response = await api.get((0, _ufo.joinURL)(prefix, `/api/vendors/order/${sessionId}/status`), {});
const needCheckError = Date.now() - timerRef.current > 6 * 1e3;
const allCompleted = response.data?.vendors?.every(vendor => vendor.progress >= 100);
const hasAnyFailed = response.data?.vendors?.some(vendor => vendor.status === "failed" || needCheckError && !!vendor.error && !!vendor.error_message);
if (hasAnyFailed || allCompleted) {
clearInterval(interval2);
}
setHasFailed(hasAnyFailed);
setIsAllCompleted(!hasAnyFailed && allCompleted);
setVendorStatus(response.data);
} catch (error) {
console.error("Failed to fetch vendor status:", error);
}
};
fetchVendorStatus();
const interval = setInterval(() => {
fetchVendorStatus(interval);
}, 5e3);
return () => clearInterval(interval);
}, [vendorCount, api, prefix, sessionId]);
(0, _react.useEffect)(() => {
if (inArcsphere && isAllCompleted) {
try {
_bridge.default?.call?.("arc__toast", {
text: t("payment.checkout.vendor.arcSphereToast")
});
const timer = setTimeout(() => {
_bridge.default?.call?.("arcClosePage");
}, 3e3);
return () => clearTimeout(timer);
} catch (error) {}
}
return void 0;
}, [isAllCompleted, t, locale, inArcsphere]);
const renderPlaceholders = () => {
const placeholders = [];
for (let i = 0; i < vendorCount; i++) {
placeholders.push(/* @__PURE__ */(0, _jsxRuntime.jsx)(_progressItem.VendorPlaceholder, {}, `placeholder-${i}`));
}
return placeholders;
};
const renderVendors = () => {
if (!vendorStatus) return renderPlaceholders();
return vendorStatus.vendors?.map((vendor, index) => {
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_progressItem.VendorProgressItem, {
vendor
}, vendor.title || `vendor-${index}`);
});
};
const renderVendorProgress = () => {
if (vendorCount === 0) return null;
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Paper, {
elevation: 0,
sx: {
p: 3,
backgroundColor: "grey.50",
borderRadius: 2,
width: "100%",
mt: 2,
display: "flex",
flexDirection: "column",
gap: 2
},
children: [renderVendors(), hasFailed ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
variant: "h6",
sx: {
color: "warning.main",
mb: 1
},
children: t("payment.checkout.vendor.failedMsg")
}) : null, pageInfo?.success_message?.[locale] && isAllCompleted ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
variant: "h6",
sx: {
color: "text.primary",
mb: 1
},
children: pageInfo?.success_message?.[locale]
}) : null]
});
};
if (["subscription", "setup"].includes(action)) {
if (subscriptions && subscriptions.length > 1) {
next = /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Paper, {
elevation: 0,
sx: {
p: 3,
backgroundColor: "grey.50",
borderRadius: 2,
width: "100%",
mt: 2,
display: "flex",
flexDirection: "column",
gap: 2
},
children: subscriptions.map(subscription => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
display: "flex",
alignItems: "center",
justifyContent: "space-between"
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
variant: "body2",
sx: {
color: "text.secondary",
fontWeight: 500
},
children: subscription.description
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
sx: {
flex: 1,
borderBottom: "1px dashed",
borderColor: "grey.300",
mx: 2
}
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_ux.Button, {
variant: "text",
color: "primary",
size: "small",
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Link, {
href: (0, _ufo.joinURL)(prefix, `/customer/subscription/${subscription.id}`),
sx: {
color: "text.secondary"
},
children: t("payment.checkout.next.view")
})
})]
}, subscription.id))
});
} else if (subscriptionId) {
next = /* @__PURE__ */(0, _jsxRuntime.jsx)(_ux.Button, {
variant: "outlined",
color: "primary",
sx: {
mt: 2
},
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Link, {
href: (0, _ufo.joinURL)(prefix, `/customer/subscription/${subscriptionId}`),
children: t("payment.checkout.next.subscription", {
payee
})
})
});
}
} else if (invoiceId) {
next = /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
sx: {
textAlign: "center",
mt: 2
},
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Link, {
href: (0, _ufo.joinURL)(prefix, `/customer/invoice/${invoiceId}`),
children: t("payment.checkout.next.invoice", {
payee
})
})
});
}
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Grow, {
in: true,
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "column",
sx: {
alignItems: "center",
justifyContent: mode === "standalone" ? "center" : "flex-start",
height: mode === "standalone" ? "fit-content" : 300
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(Div, {
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)("div", {
className: "check-icon",
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)("span", {
className: "icon-line line-tip"
}), /* @__PURE__ */(0, _jsxRuntime.jsx)("span", {
className: "icon-line line-long"
}), /* @__PURE__ */(0, _jsxRuntime.jsx)("div", {
className: "icon-circle"
}), /* @__PURE__ */(0, _jsxRuntime.jsx)("div", {
className: "icon-fix"
})]
})
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
variant: "h5",
sx: {
color: "text.primary",
mb: 3
},
children: message
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
variant: "body1",
sx: {
color: "text.secondary",
textAlign: "center",
fontSize: "14px"
},
children: t("payment.checkout.completed.tip", {
payee
})
}), renderVendorProgress(), next]
})
});
}
const Div = (0, _material.styled)("div")`
width: 80px;
height: 115px;
.check-icon {
width: 80px;
height: 80px;
position: relative;
border-radius: 50%;
box-sizing: content-box;
border: 4px solid ${props => props.theme.palette.success.main};
}
.check-icon::before {
top: 3px;
left: -2px;
width: 30px;
transform-origin: 100% 50%;
border-radius: 100px 0 0 100px;
}
.check-icon::after {
top: 0;
left: 30px;
width: 60px;
transform-origin: 0 50%;
border-radius: 0 100px 100px 0;
animation: rotate-circle 4.25s ease-in;
}
.check-icon::before,
.check-icon::after {
content: '';
height: 100px;
position: absolute;
background: ${props => props.theme.palette.background.default};
transform: rotate(-45deg);
}
.check-icon .icon-line {
height: 5px;
background-color: ${props => props.theme.palette.success.main};
display: block;
border-radius: 2px;
position: absolute;
z-index: 10;
}
.check-icon .icon-line.line-tip {
top: 46px;
left: 14px;
width: 25px;
transform: rotate(45deg);
animation: icon-line-tip 0.75s;
}
.check-icon .icon-line.line-long {
top: 38px;
right: 8px;
width: 47px;
transform: rotate(-45deg);
animation: icon-line-long 0.75s;
}
.check-icon .icon-circle {
top: -4px;
left: -4px;
z-index: 10;
width: 80px;
height: 80px;
border-radius: 50%;
position: absolute;
box-sizing: content-box;
border: 4px solid rgba(76, 175, 80, 0.5);
}
.check-icon .icon-fix {
top: 8px;
width: 5px;
left: 26px;
z-index: 1;
height: 85px;
position: absolute;
transform: rotate(-45deg);
background-color: ${props => props.theme.palette.background.default};
}
@keyframes rotate-circle {
0% {
transform: rotate(-45deg);
}
5% {
transform: rotate(-45deg);
}
12% {
transform: rotate(-405deg);
}
100% {
transform: rotate(-405deg);
}
}
@keyframes icon-line-tip {
0% {
width: 0;
left: 1px;
top: 19px;
}
54% {
width: 0;
left: 1px;
top: 19px;
}
70% {
width: 50px;
left: -8px;
top: 37px;
}
84% {
width: 17px;
left: 21px;
top: 48px;
}
100% {
width: 25px;
left: 14px;
top: 45px;
}
}
@keyframes icon-line-long {
0% {
width: 0;
right: 46px;
top: 54px;
}
65% {
width: 0;
right: 46px;
top: 54px;
}
84% {
width: 55px;
right: 0px;
top: 35px;
}
100% {
width: 47px;
right: 8px;
top: 38px;
}
}
`;