@blocklet/payment-react
Version:
Reusable react components for payment kit v2
180 lines (179 loc) • 5.95 kB
JavaScript
import { jsx, jsxs } from "react/jsx-runtime";
import { useState } from "react";
import { Button, Typography, Stack, Alert } from "@mui/material";
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
import Toast from "@arcblock/ux/lib/Toast";
import { joinURL } from "ufo";
import { useRequest } from "ahooks";
import { Dialog } from "@arcblock/ux";
import { usePaymentContext } from "../contexts/payment.js";
import { formatError, formatToDate, getPrefix, isCrossOrigin } from "../libs/util.js";
import api from "../libs/api.js";
import LoadingButton from "./loading-button.js";
const fetchSubscriptionDetail = async (params) => {
const url = `/api/subscriptions/${params.subscriptionId}`;
const res = await api.get(params.authToken ? joinURL(url, `?authToken=${params.authToken}`) : url);
return res.data;
};
const fetchRecoverInfo = async (params) => {
const url = `/api/subscriptions/${params.subscriptionId}/recover-info`;
const res = await api.get(params.authToken ? joinURL(url, `?authToken=${params.authToken}`) : url);
return res.data;
};
const recoverSubscription = async (params) => {
const url = `/api/subscriptions/${params.subscriptionId}/recover`;
const res = await api.put(params.authToken ? joinURL(url, `?authToken=${params.authToken}`) : url);
return res.data;
};
function RecoverSubscription({
subscriptionId,
dialogProps = {
open: true
},
onResumed = () => {
},
successToast = true,
authToken = void 0
}) {
const { t, locale } = useLocaleContext();
const { connect } = usePaymentContext();
const [recoverLoading, setRecoverLoading] = useState(false);
const [dialogOpen, setDialogOpen] = useState(dialogProps.open || false);
const { data, error, loading } = useRequest(() => fetchRecoverInfo({ subscriptionId, authToken }), {
ready: !!subscriptionId
});
const isCrossOriginRequest = isCrossOrigin();
const needStake = data?.needStake ?? false;
const handleSuccess = async () => {
try {
const subscription = await fetchSubscriptionDetail({ subscriptionId, authToken });
if (successToast) {
Toast.success(t("payment.customer.recover.success"));
}
setDialogOpen(false);
onResumed(subscription);
setRecoverLoading(false);
} catch (err) {
console.error("Failed to fetch updated subscription:", err);
Toast.error(formatError(err));
setRecoverLoading(false);
}
};
const handleRecoverWithStake = () => {
setRecoverLoading(true);
try {
connect.open({
locale,
containerEl: void 0,
saveConnect: false,
action: "re-stake",
prefix: joinURL(getPrefix(), "/api/did"),
useSocket: !isCrossOriginRequest,
extraParams: { subscriptionId },
messages: {
scan: t("common.connect.defaultScan"),
title: t("payment.customer.recover.reStakeTitle"),
confirm: t("common.connect.confirm")
},
onSuccess: handleSuccess,
onClose: () => {
connect.close();
setRecoverLoading(false);
},
onError: (err) => {
Toast.error(formatError(err));
setRecoverLoading(false);
}
});
} catch (err) {
Toast.error(formatError(err));
setRecoverLoading(false);
}
};
const handleDirectRecover = async () => {
setRecoverLoading(true);
try {
const result = await recoverSubscription({ subscriptionId, authToken });
if (result.needStake) {
handleRecoverWithStake();
return;
}
const { subscription } = result;
if (successToast) {
Toast.success(t("payment.customer.recover.success"));
}
setDialogOpen(false);
onResumed(subscription);
setRecoverLoading(false);
} catch (err) {
Toast.error(formatError(err));
setRecoverLoading(false);
}
};
const handleRecover = () => {
if (needStake) {
handleRecoverWithStake();
} else {
handleDirectRecover();
}
};
const handleClose = () => {
setDialogOpen(false);
dialogProps.onClose?.();
};
if (loading) {
return null;
}
return /* @__PURE__ */ jsx(
Dialog,
{
PaperProps: {
style: { minHeight: "auto" }
},
...dialogProps || {},
open: dialogOpen,
title: dialogProps?.title || t("payment.customer.recover.title"),
sx: { "& .MuiDialogContent-root": { pt: 0 } },
onClose: handleClose,
children: error ? /* @__PURE__ */ jsx(Alert, { severity: "error", children: error.message }) : /* @__PURE__ */ jsxs(
Stack,
{
sx: {
gap: 2
},
children: [
/* @__PURE__ */ jsx(
Typography,
{
variant: "body2",
sx: {
color: "text.secondary"
},
children: t("payment.customer.recover.description", {
date: formatToDate(Number(data?.subscription?.current_period_end || "0") * 1e3)
})
}
),
needStake && /* @__PURE__ */ jsx(Alert, { severity: "warning", children: t("payment.customer.recover.stakeRequiredDescription") }),
/* @__PURE__ */ jsxs(
Stack,
{
direction: "row",
sx: {
justifyContent: "flex-end",
gap: 2,
mt: 2
},
children: [
/* @__PURE__ */ jsx(Button, { variant: "outlined", color: "primary", onClick: handleClose, children: t("common.cancel") }),
/* @__PURE__ */ jsx(LoadingButton, { variant: "contained", size: "small", loading: recoverLoading, onClick: handleRecover, children: t("common.confirm") })
]
}
)
]
}
)
}
);
}
export default RecoverSubscription;