UNPKG

@blocklet/payment-react

Version:

Reusable react components for payment kit v2

391 lines (388 loc) 11.2 kB
"use strict"; 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; } } `;