@blocklet/payment-react 1.20.20 → 1.20.22

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.
@@ -9,7 +9,16 @@ function EmptyStub() {
9
9
  return null;
10
10
  }
11
11
  const Table = React.memo(
12
- ({ options, columns, toolbar = true, footer = true, hasRowLink = false, emptyNodeText = "", ...rest }) => {
12
+ ({
13
+ options,
14
+ columns,
15
+ toolbar = true,
16
+ footer = true,
17
+ hasRowLink = false,
18
+ emptyNodeText = "",
19
+ bordered = true,
20
+ ...rest
21
+ }) => {
13
22
  const { locale, t } = useLocaleContext();
14
23
  const { isMobile } = useMobile();
15
24
  const defaultOptions = {
@@ -45,7 +54,8 @@ const Table = React.memo(
45
54
  ...rest,
46
55
  components,
47
56
  hasRowLink,
48
- isMobile
57
+ isMobile,
58
+ bordered
49
59
  }
50
60
  );
51
61
  }
@@ -55,19 +65,23 @@ const Wrapped = styled(Datatable)`
55
65
  font-size: 0.875rem !important;
56
66
  }` : ""}
57
67
  .MuiPaper-root {
58
- border-radius: 8px;
68
+ border-radius: ${(props) => props?.bordered ? "8px" : "0"};
59
69
  overflow: hidden;
60
70
  }
61
71
  table.MuiTable-root {
62
- outline: 1px solid;
63
- outline-color: ${({ theme }) => theme.palette.divider};
64
- border-radius: ${({ theme }) => `${2 * theme.shape.borderRadius}px`};
72
+ ${(props) => props?.bordered ? `
73
+ outline: 1px solid;
74
+ outline-color: ${props.theme.palette.divider};
75
+ border-radius: ${2 * props.theme.shape.borderRadius}px;
76
+ ` : ""}
65
77
  overflow: hidden;
66
78
  }
67
79
  [class*='MUIDataTable-responsiveBase'] {
68
- outline: 1px solid;
69
- outline-color: ${({ theme }) => theme.palette.divider};
70
- border-radius: ${({ theme }) => `${2 * theme.shape.borderRadius}px`};
80
+ ${(props) => props?.bordered ? `
81
+ outline: 1px solid;
82
+ outline-color: ${props.theme.palette.divider};
83
+ border-radius: ${2 * props.theme.shape.borderRadius}px;
84
+ ` : ""}
71
85
  }
72
86
 
73
87
  th.MuiTableCell-head {
@@ -76,11 +90,11 @@ const Wrapped = styled(Datatable)`
76
90
  background: ${({ theme }) => theme.palette.grey[50]};
77
91
  border-bottom: none;
78
92
  &:first-of-type {
79
- border-top-left-radius: 8px;
93
+ ${(props) => props?.bordered ? "border-top-left-radius: 8px;" : ""}
80
94
  padding-left: 20px;
81
95
  }
82
96
  &:last-of-type {
83
- border-top-right-radius: 8px;
97
+ ${(props) => props?.bordered ? "border-top-right-radius: 8px;" : ""}
84
98
  }
85
99
  }
86
100
 
@@ -88,11 +102,11 @@ const Wrapped = styled(Datatable)`
88
102
  background: ${({ theme }) => theme.palette.grey[100]};
89
103
  }
90
104
  tr.MuiTableRow-root:last-of-type td:first-of-type {
91
- border-bottom-left-radius: 8px;
105
+ ${(props) => props?.bordered ? "border-bottom-left-radius: 8px;" : ""}
92
106
  }
93
107
 
94
108
  tr.MuiTableRow-root:last-of-type td:last-of-type {
95
- border-bottom-right-radius: 8px;
109
+ ${(props) => props?.bordered ? "border-bottom-right-radius: 8px;" : ""}
96
110
  }
97
111
 
98
112
  tr.MuiTableRow-root:nth-of-type(even) {
@@ -191,6 +205,16 @@ const Wrapped = styled(Datatable)`
191
205
  [class*='MUIDataTable-responsiveBase'] tr:not([class*='responsiveSimple']) td.MuiTableCell-body > div {
192
206
  width: inherit;
193
207
  }
208
+ ${({ mobileTDFlexDirection }) => mobileTDFlexDirection === "row" ? `
209
+ .MuiTable-root > .MuiTableBody-root > .MuiTableRow-root > td.MuiTableCell-root {
210
+ align-items: center;
211
+ padding: 4px 0;
212
+ > div {
213
+ width: fit-content;
214
+ flex: inherit;
215
+ }
216
+ }
217
+ ` : ""}
194
218
  }
195
219
  `;
196
220
  export default Table;
package/es/locales/en.js CHANGED
@@ -185,7 +185,17 @@ export default flat({
185
185
  progress: "Progress {progress}%",
186
186
  delivered: "Installation completed",
187
187
  failed: "Processing failed",
188
- failedMsg: "An exception occurred during installation. We will automatically process a refund for you. We apologize for the inconvenience. Thank you for your understanding!"
188
+ failedMsg: "An exception occurred during installation. We will automatically process a refund for you. We apologize for the inconvenience. Thank you for your understanding!",
189
+ launcher: {
190
+ processing: "Installing {name}",
191
+ completed: "{name} installed successfully",
192
+ failed: "Failed to install {name}"
193
+ },
194
+ didnames: {
195
+ processing: "Domain ({domain}) registering",
196
+ completed: "Domain ({domain}) registered successfully",
197
+ failed: "Domain ({domain}) registered failed"
198
+ }
189
199
  },
190
200
  confirm: {
191
201
  withStake: "By confirming, you allow {payee} to charge your account for future payments and, if necessary, slash your stake. You can cancel your subscription or withdraw your stake at any time.",
package/es/locales/zh.js CHANGED
@@ -185,7 +185,17 @@ export default flat({
185
185
  progress: "\u8FDB\u5EA6 {progress}%",
186
186
  delivered: "\u5B89\u88C5\u6210\u529F",
187
187
  failed: "\u5B89\u88C5\u5931\u8D25",
188
- failedMsg: "\u5F88\u62B1\u6B49\uFF0C\u5B89\u88C5\u8FC7\u7A0B\u4E2D\u9047\u5230\u4E86\u4E00\u4E9B\u95EE\u9898\u3002\u6211\u4EEC\u6B63\u5728\u5904\u7406\u8FD9\u4E2A\u95EE\u9898\uFF0C\u7A0D\u540E\u4F1A\u81EA\u52A8\u4E3A\u60A8\u9000\u6B3E\u3002\u611F\u8C22\u60A8\u7684\u8010\u5FC3\u7B49\u5F85\uFF01"
188
+ failedMsg: "\u5F88\u62B1\u6B49\uFF0C\u5B89\u88C5\u8FC7\u7A0B\u4E2D\u9047\u5230\u4E86\u4E00\u4E9B\u95EE\u9898\u3002\u6211\u4EEC\u6B63\u5728\u5904\u7406\u8FD9\u4E2A\u95EE\u9898\uFF0C\u7A0D\u540E\u4F1A\u81EA\u52A8\u4E3A\u60A8\u9000\u6B3E\u3002\u611F\u8C22\u60A8\u7684\u8010\u5FC3\u7B49\u5F85\uFF01",
189
+ launcher: {
190
+ processing: "\u6B63\u5728\u5B89\u88C5 {name}",
191
+ completed: "\u5B89\u88C5 {name} \u6210\u529F",
192
+ failed: "\u5B89\u88C5 {name} \u5931\u8D25"
193
+ },
194
+ didnames: {
195
+ processing: "\u6B63\u5728\u6CE8\u518C {domain}",
196
+ completed: "\u6CE8\u518C {domain} \u6210\u529F",
197
+ failed: "\u6CE8\u518C {domain} \u5931\u8D25"
198
+ }
189
199
  },
190
200
  confirm: {
191
201
  withStake: "\u786E\u8BA4\u8BA2\u9605\uFF0C\u5373\u8868\u793A\u60A8\u6388\u6743 {payee} \u4ECE\u60A8\u7684\u8D26\u6237\u6263\u53D6\u672A\u6765\u6B3E\u9879\uFF0C\u5E76\u5728\u5FC5\u8981\u65F6\u7F5A\u6CA1\u8D28\u62BC\u3002\u60A8\u53EF\u968F\u65F6\u53D6\u6D88\u8BA2\u9605\u6216\u64A4\u9500\u8D28\u62BC\u3002",
@@ -495,8 +495,15 @@ export default function PaymentForm({
495
495
  setState({ stripePaying: false, paying: true });
496
496
  await handleConnected();
497
497
  };
498
- const onStripeCancel = () => {
499
- setState({ stripePaying: false });
498
+ const onStripeCancel = async () => {
499
+ try {
500
+ await api.post(`/api/checkout-sessions/${checkoutSession.id}/abort-stripe`);
501
+ } catch (err) {
502
+ console.error(err);
503
+ Toast.error(formatError(err));
504
+ } finally {
505
+ setState({ stripePaying: false });
506
+ }
500
507
  };
501
508
  useEffect(() => {
502
509
  const handleKeyDown = (e) => {
@@ -304,7 +304,9 @@ function PaymentInner({
304
304
  {
305
305
  mode,
306
306
  pageInfo: state.checkoutSession.metadata?.page_info,
307
- hasVendor: state.checkoutSession.metadata?.page_info?.hasVendor || state.checkoutSession.line_items.some((item) => item.price?.product?.vendor_config?.length > 0),
307
+ vendorCount: state.checkoutSession.line_items.reduce((total, item) => {
308
+ return total + (item.price?.product?.vendor_config?.length || 0);
309
+ }, 0),
308
310
  sessionId: state.checkoutSession.id,
309
311
  payee: getStatementDescriptor(state.checkoutSession.line_items),
310
312
  action: state.checkoutSession.mode,
@@ -1,3 +1,4 @@
1
+ export declare function VendorPlaceholder(): import("react").JSX.Element;
1
2
  interface VendorStatus {
2
3
  success: boolean;
3
4
  name?: string;
@@ -7,6 +8,7 @@ interface VendorStatus {
7
8
  message: string;
8
9
  appUrl?: string;
9
10
  title?: string;
11
+ vendorType: string;
10
12
  }
11
13
  export declare function VendorProgressItem({ vendor }: {
12
14
  vendor: VendorStatus;
@@ -1,7 +1,37 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
3
- import { Box, LinearProgress, Typography } from "@mui/material";
3
+ import { Box, LinearProgress, Skeleton, Typography } from "@mui/material";
4
4
  import { useCallback, useEffect, useRef, useState } from "react";
5
+ import { Check } from "@mui/icons-material";
6
+ export function VendorPlaceholder() {
7
+ return /* @__PURE__ */ jsxs(Box, { sx: { mb: 2 }, children: [
8
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 1 }, children: [
9
+ /* @__PURE__ */ jsx(Skeleton, { variant: "rounded", height: 16, width: 150 }),
10
+ /* @__PURE__ */ jsx(Skeleton, { variant: "rounded", height: 16, width: 50 })
11
+ ] }),
12
+ /* @__PURE__ */ jsx(Skeleton, { variant: "rounded", height: 8, width: "100%" })
13
+ ] });
14
+ }
15
+ const getVendorLabel = (vendor, isFailed, t) => {
16
+ const name = vendor.name || vendor.title;
17
+ const isCompleted = vendor.status === "delivered";
18
+ if (vendor.vendorType === "didnames") {
19
+ if (isFailed) {
20
+ return t("payment.checkout.vendor.didnames.failed", { name });
21
+ }
22
+ if (isCompleted) {
23
+ return t("payment.checkout.vendor.didnames.completed", { name });
24
+ }
25
+ return t("payment.checkout.vendor.didnames.processing", { name });
26
+ }
27
+ if (isFailed) {
28
+ return t("payment.checkout.vendor.launcher.failed", { name });
29
+ }
30
+ if (isCompleted) {
31
+ return t("payment.checkout.vendor.launcher.completed", { name });
32
+ }
33
+ return t("payment.checkout.vendor.launcher.processing", { name });
34
+ };
5
35
  export function VendorProgressItem({ vendor }) {
6
36
  const { t } = useLocaleContext();
7
37
  const [displayProgress, setDisplayProgress] = useState(0);
@@ -29,7 +59,7 @@ export function VendorProgressItem({ vendor }) {
29
59
  newProgress = Math.min(startProgress + elapsed / 1e3, 99);
30
60
  }
31
61
  newProgress = Math.round(newProgress);
32
- setDisplayProgress((pre) => pre > newProgress ? pre : newProgress);
62
+ setDisplayProgress((pre) => Math.min(pre > newProgress ? pre : newProgress, 100));
33
63
  if (realProgress === 100) {
34
64
  return;
35
65
  }
@@ -52,11 +82,11 @@ export function VendorProgressItem({ vendor }) {
52
82
  }, [startAnimation]);
53
83
  const isCompleted = displayProgress >= 100;
54
84
  const isFailed = vendor.status === "failed";
55
- const nameText = vendor.name || vendor.title;
85
+ const nameText = getVendorLabel(vendor, isFailed, t);
56
86
  if (isFailed) {
57
87
  return /* @__PURE__ */ jsxs(Box, { sx: { mb: 2 }, children: [
58
88
  /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 1 }, children: [
59
- /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { color: "text.secondary" }, children: nameText ? `${nameText} - ${t("payment.checkout.vendor.failed")}` : t("payment.checkout.vendor.failed") }),
89
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { color: "text.secondary" }, children: nameText }),
60
90
  /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { color: "error.main", fontWeight: 500 }, children: t("payment.checkout.vendor.progress", { progress: 0 }) })
61
91
  ] }),
62
92
  /* @__PURE__ */ jsx(
@@ -77,17 +107,23 @@ export function VendorProgressItem({ vendor }) {
77
107
  )
78
108
  ] });
79
109
  }
80
- const statusText = isCompleted ? t("payment.checkout.vendor.delivered") : t("payment.checkout.vendor.processing");
110
+ if (!vendor.name && !vendor.title) {
111
+ return /* @__PURE__ */ jsx(VendorPlaceholder, {});
112
+ }
81
113
  return /* @__PURE__ */ jsxs(Box, { sx: { mb: 2 }, children: [
82
114
  /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 1 }, children: [
83
- /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { color: "text.secondary" }, children: nameText ? `${nameText} - ${statusText}` : statusText }),
84
- /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { color: "text.secondary", fontWeight: 500 }, children: t("payment.checkout.vendor.progress", { progress: displayProgress }) })
115
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", sx: { color: "text.secondary", display: "flex", alignItems: "center" }, children: [
116
+ nameText,
117
+ " ",
118
+ isCompleted ? /* @__PURE__ */ jsx(Check, { sx: { color: "success.main", ml: 0.5 }, fontSize: "small" }) : null
119
+ ] }),
120
+ isCompleted ? null : /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { color: "text.secondary", fontWeight: 500 }, children: t("payment.checkout.vendor.progress", { progress: displayProgress }) })
85
121
  ] }),
86
122
  /* @__PURE__ */ jsx(
87
123
  LinearProgress,
88
124
  {
89
125
  variant: "determinate",
90
- value: Math.min(displayProgress, 100),
126
+ value: displayProgress || 0,
91
127
  sx: {
92
128
  height: 8,
93
129
  borderRadius: 4,
@@ -1,7 +1,7 @@
1
1
  type Props = {
2
2
  mode: string;
3
3
  pageInfo?: any;
4
- hasVendor?: boolean;
4
+ vendorCount?: number;
5
5
  sessionId?: string;
6
6
  message: string;
7
7
  action: string;
@@ -10,5 +10,5 @@ type Props = {
10
10
  subscriptionId?: string;
11
11
  subscriptions?: any[];
12
12
  };
13
- export default function PaymentSuccess({ mode, pageInfo, hasVendor, sessionId, message, action, payee, invoiceId, subscriptionId, subscriptions, }: Props): import("react").JSX.Element;
13
+ export default function PaymentSuccess({ mode, pageInfo, vendorCount, sessionId, message, action, payee, invoiceId, subscriptionId, subscriptions, }: Props): import("react").JSX.Element;
14
14
  export {};
@@ -5,11 +5,11 @@ import { useEffect, useRef, useState } from "react";
5
5
  import { joinURL } from "ufo";
6
6
  import { Button } from "@arcblock/ux";
7
7
  import { usePaymentContext } from "../contexts/payment.js";
8
- import { VendorProgressItem } from "./progress-item.js";
8
+ import { VendorPlaceholder, VendorProgressItem } from "./progress-item.js";
9
9
  export default function PaymentSuccess({
10
10
  mode,
11
11
  pageInfo = {},
12
- hasVendor = false,
12
+ vendorCount = 0,
13
13
  sessionId = "",
14
14
  message,
15
15
  action,
@@ -26,7 +26,7 @@ export default function PaymentSuccess({
26
26
  const timerRef = useRef(Date.now());
27
27
  let next = null;
28
28
  useEffect(() => {
29
- if (!hasVendor || !sessionId) return void 0;
29
+ if (vendorCount === 0 || !sessionId) return void 0;
30
30
  const fetchVendorStatus = async (interval2) => {
31
31
  try {
32
32
  const response = await api.get(joinURL(prefix, `/api/vendors/order/${sessionId}/status`), {});
@@ -50,9 +50,22 @@ export default function PaymentSuccess({
50
50
  fetchVendorStatus(interval);
51
51
  }, 5e3);
52
52
  return () => clearInterval(interval);
53
- }, [hasVendor, api, prefix, sessionId]);
53
+ }, [vendorCount, api, prefix, sessionId]);
54
+ const renderPlaceholders = () => {
55
+ const placeholders = [];
56
+ for (let i = 0; i < vendorCount; i++) {
57
+ placeholders.push(/* @__PURE__ */ jsx(VendorPlaceholder, {}, `placeholder-${i}`));
58
+ }
59
+ return placeholders;
60
+ };
61
+ const renderVendors = () => {
62
+ if (!vendorStatus) return renderPlaceholders();
63
+ return vendorStatus.vendors?.map((vendor, index) => {
64
+ return /* @__PURE__ */ jsx(VendorProgressItem, { vendor }, vendor.title || `vendor-${index}`);
65
+ });
66
+ };
54
67
  const renderVendorProgress = () => {
55
- if (!hasVendor || !vendorStatus) return null;
68
+ if (vendorCount === 0) return null;
56
69
  return /* @__PURE__ */ jsxs(
57
70
  Paper,
58
71
  {
@@ -68,7 +81,7 @@ export default function PaymentSuccess({
68
81
  gap: 2
69
82
  },
70
83
  children: [
71
- vendorStatus.vendors?.map((vendor, index) => /* @__PURE__ */ jsx(VendorProgressItem, { vendor }, vendor.title || `vendor-${index}`)),
84
+ renderVendors(),
72
85
  hasFailed ? /* @__PURE__ */ jsx(Typography, { variant: "h6", sx: { color: "warning.main", mb: 1 }, children: t("payment.checkout.vendor.failedMsg") }) : null,
73
86
  pageInfo?.success_message?.[locale] && isAllCompleted ? /* @__PURE__ */ jsx(Typography, { variant: "h6", sx: { color: "text.primary", mb: 1 }, children: pageInfo?.success_message?.[locale] }) : null
74
87
  ]
@@ -189,6 +189,7 @@ export default function PaymentSummary({
189
189
  setState({ loading: false });
190
190
  }
191
191
  };
192
+ const hasSubTotal = +staking > 0 || allowPromotionCodes;
192
193
  const ProductCardList = /* @__PURE__ */ jsxs(
193
194
  Stack,
194
195
  {
@@ -353,7 +354,7 @@ export default function PaymentSummary({
353
354
  /* @__PURE__ */ jsx(Collapse, { in: state.expanded || !isMobile, timeout: "auto", unmountOnExit: true, children: ProductCardList })
354
355
  ] }) : ProductCardList,
355
356
  /* @__PURE__ */ jsx(Divider, { sx: { mt: 2.5, mb: 2.5 } }),
356
- +staking > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
357
+ +staking > 0 && /* @__PURE__ */ jsxs(Stack, { spacing: 1, children: [
357
358
  /* @__PURE__ */ jsxs(
358
359
  Stack,
359
360
  {
@@ -450,103 +451,95 @@ export default function PaymentSummary({
450
451
  currencyId: currency.id
451
452
  }
452
453
  ) }),
453
- hasDiscounts && /* @__PURE__ */ jsx(
454
- Box,
455
- {
456
- sx: {
457
- py: 1.5
458
- },
459
- children: sessionDiscounts.map((discount) => {
460
- const promotionCodeInfo = discount.promotion_code_details;
461
- const couponInfo = discount.coupon_details;
462
- const discountDescription = couponInfo ? formatCouponTerms(couponInfo, discountCurrency, locale) : "";
463
- const notSupported = discountDescription === t("payment.checkout.coupon.noDiscount");
464
- return /* @__PURE__ */ jsxs(Stack, { children: [
465
- /* @__PURE__ */ jsxs(
466
- Stack,
467
- {
468
- direction: "row",
469
- spacing: 1,
470
- sx: {
471
- justifyContent: "space-between",
472
- alignItems: "center"
473
- },
474
- children: [
475
- /* @__PURE__ */ jsxs(
476
- Stack,
477
- {
478
- direction: "row",
479
- spacing: 1,
480
- sx: {
481
- alignItems: "center",
482
- backgroundColor: "grey.100",
483
- width: "fit-content",
484
- px: 1,
485
- py: 0.5,
486
- borderRadius: 1
487
- },
488
- children: [
489
- /* @__PURE__ */ jsxs(
490
- Typography,
491
- {
492
- sx: {
493
- fontWeight: "medium",
494
- fontSize: "small",
495
- display: "flex",
496
- alignItems: "center",
497
- gap: 0.5
498
- },
499
- children: [
500
- /* @__PURE__ */ jsx(LocalOffer, { sx: { color: "warning.main", fontSize: "small" } }),
501
- promotionCodeInfo?.code || discount.verification_data?.code || t("payment.checkout.discount")
502
- ]
503
- }
504
- ),
505
- !completed && /* @__PURE__ */ jsx(
506
- Button,
507
- {
508
- size: "small",
509
- disabled: paymentState.paying || paymentState.stripePaying,
510
- onClick: () => handleRemovePromotion(checkoutSessionId),
511
- sx: {
512
- minWidth: "auto",
513
- width: 16,
514
- height: 16,
515
- color: "text.secondary",
516
- "&.Mui-disabled": {
517
- color: "text.disabled"
518
- }
519
- },
520
- children: /* @__PURE__ */ jsx(Close, { sx: { fontSize: 14 } })
454
+ hasDiscounts && /* @__PURE__ */ jsx(Box, { children: sessionDiscounts.map((discount) => {
455
+ const promotionCodeInfo = discount.promotion_code_details;
456
+ const couponInfo = discount.coupon_details;
457
+ const discountDescription = couponInfo ? formatCouponTerms(couponInfo, discountCurrency, locale) : "";
458
+ const notSupported = discountDescription === t("payment.checkout.coupon.noDiscount");
459
+ return /* @__PURE__ */ jsxs(Stack, { children: [
460
+ /* @__PURE__ */ jsxs(
461
+ Stack,
462
+ {
463
+ direction: "row",
464
+ spacing: 1,
465
+ sx: {
466
+ justifyContent: "space-between",
467
+ alignItems: "center"
468
+ },
469
+ children: [
470
+ /* @__PURE__ */ jsxs(
471
+ Stack,
472
+ {
473
+ direction: "row",
474
+ spacing: 1,
475
+ sx: {
476
+ alignItems: "center",
477
+ backgroundColor: "grey.100",
478
+ width: "fit-content",
479
+ px: 1,
480
+ py: 1,
481
+ borderRadius: 1
482
+ },
483
+ children: [
484
+ /* @__PURE__ */ jsxs(
485
+ Typography,
486
+ {
487
+ sx: {
488
+ fontWeight: "medium",
489
+ display: "flex",
490
+ alignItems: "center",
491
+ gap: 0.5
492
+ },
493
+ children: [
494
+ /* @__PURE__ */ jsx(LocalOffer, { sx: { color: "warning.main", fontSize: "small" } }),
495
+ promotionCodeInfo?.code || discount.verification_data?.code || t("payment.checkout.discount")
496
+ ]
497
+ }
498
+ ),
499
+ !completed && /* @__PURE__ */ jsx(
500
+ Button,
501
+ {
502
+ size: "small",
503
+ disabled: paymentState.paying || paymentState.stripePaying,
504
+ onClick: () => handleRemovePromotion(checkoutSessionId),
505
+ sx: {
506
+ minWidth: "auto",
507
+ width: 16,
508
+ height: 16,
509
+ color: "text.secondary",
510
+ "&.Mui-disabled": {
511
+ color: "text.disabled"
521
512
  }
522
- )
523
- ]
524
- }
525
- ),
526
- /* @__PURE__ */ jsxs(Typography, { sx: { color: "text.secondary" }, children: [
527
- "-",
528
- formatAmount(discount.discount_amount || "0", discountCurrency.decimal),
529
- " ",
530
- discountCurrency.symbol
531
- ] })
532
- ]
533
- }
534
- ),
535
- discountDescription && /* @__PURE__ */ jsx(
536
- Typography,
537
- {
538
- sx: {
539
- fontSize: "small",
540
- color: notSupported ? "error.main" : "text.secondary",
541
- mt: 0.5
542
- },
543
- children: discountDescription
544
- }
545
- )
546
- ] }, discount.promotion_code || discount.coupon || `discount-${discount.discount_amount}`);
547
- })
548
- }
549
- ),
513
+ },
514
+ children: /* @__PURE__ */ jsx(Close, { sx: { fontSize: 14 } })
515
+ }
516
+ )
517
+ ]
518
+ }
519
+ ),
520
+ /* @__PURE__ */ jsxs(Typography, { sx: { color: "text.secondary" }, children: [
521
+ "-",
522
+ formatAmount(discount.discount_amount || "0", discountCurrency.decimal),
523
+ " ",
524
+ discountCurrency.symbol
525
+ ] })
526
+ ]
527
+ }
528
+ ),
529
+ discountDescription && /* @__PURE__ */ jsx(
530
+ Typography,
531
+ {
532
+ sx: {
533
+ fontSize: "small",
534
+ color: notSupported ? "error.main" : "text.secondary",
535
+ mt: 0.5
536
+ },
537
+ children: discountDescription
538
+ }
539
+ )
540
+ ] }, discount.promotion_code || discount.coupon || `discount-${discount.discount_amount}`);
541
+ }) }),
542
+ hasSubTotal && /* @__PURE__ */ jsx(Divider, { sx: { my: 1 } }),
550
543
  /* @__PURE__ */ jsxs(
551
544
  Stack,
552
545
  {