payment-kit 1.13.111 → 1.13.113

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.
Files changed (126) hide show
  1. package/api/src/libs/notification/template/subscription-trial-will-end.ts +1 -1
  2. package/api/src/libs/notification/template/subscription-will-renew.ts +1 -1
  3. package/api/src/routes/products.ts +1 -0
  4. package/api/src/routes/subscriptions.ts +2 -0
  5. package/blocklet.yml +1 -1
  6. package/package.json +6 -6
  7. package/src/components/actions.tsx +1 -2
  8. package/src/components/blockchain/tx.tsx +1 -1
  9. package/src/components/click-boundary.tsx +1 -2
  10. package/src/components/customer/actions.tsx +2 -3
  11. package/src/components/customer/edit.tsx +3 -3
  12. package/src/components/customer/form.tsx +22 -24
  13. package/src/components/drawer-form.tsx +2 -4
  14. package/src/components/event/list.tsx +2 -3
  15. package/src/components/invoice/action.tsx +2 -3
  16. package/src/components/invoice/list.tsx +3 -4
  17. package/src/components/invoice/table.tsx +7 -7
  18. package/src/components/metadata/form.tsx +3 -4
  19. package/src/components/passport/actions.tsx +1 -2
  20. package/src/components/passport/assign.tsx +1 -1
  21. package/src/components/payment-intent/actions.tsx +2 -3
  22. package/src/components/payment-intent/list.tsx +3 -4
  23. package/src/components/payment-link/actions.tsx +2 -3
  24. package/src/components/payment-link/item.tsx +3 -5
  25. package/src/components/payment-link/product-select.tsx +3 -4
  26. package/src/components/payment-link/rename.tsx +3 -4
  27. package/src/components/payment-method/arcblock.tsx +1 -2
  28. package/src/components/payment-method/bitcoin.tsx +1 -2
  29. package/src/components/payment-method/ethereum.tsx +1 -2
  30. package/src/components/payment-method/stripe.tsx +1 -2
  31. package/src/components/portal/invoice/list.tsx +4 -5
  32. package/src/components/portal/subscription/actions.tsx +7 -8
  33. package/src/components/portal/subscription/cancel.tsx +13 -12
  34. package/src/components/portal/subscription/list.tsx +4 -10
  35. package/src/components/price/currency-select.tsx +2 -2
  36. package/src/components/price/form.tsx +3 -4
  37. package/src/components/price/upsell-select.tsx +2 -3
  38. package/src/components/price/upsell.tsx +3 -5
  39. package/src/components/pricing-table/actions.tsx +2 -3
  40. package/src/components/pricing-table/payment-settings.tsx +4 -4
  41. package/src/components/pricing-table/price-item.tsx +4 -7
  42. package/src/components/pricing-table/product-item.tsx +3 -3
  43. package/src/components/pricing-table/rename.tsx +3 -4
  44. package/src/components/product/actions.tsx +2 -3
  45. package/src/components/product/add-price.tsx +2 -2
  46. package/src/components/product/create.tsx +2 -4
  47. package/src/components/product/cross-sell-select.tsx +3 -3
  48. package/src/components/product/cross-sell.tsx +4 -5
  49. package/src/components/product/edit.tsx +1 -1
  50. package/src/components/product/form.tsx +6 -6
  51. package/src/components/relative-time.tsx +1 -2
  52. package/src/components/subscription/actions/cancel.tsx +2 -3
  53. package/src/components/subscription/actions/index.tsx +2 -3
  54. package/src/components/subscription/items/actions.tsx +1 -1
  55. package/src/components/subscription/items/index.tsx +2 -2
  56. package/src/components/subscription/items/usage-records.tsx +2 -3
  57. package/src/components/subscription/list.tsx +3 -4
  58. package/src/components/subscription/metrics.tsx +2 -2
  59. package/src/components/subscription/status.tsx +3 -3
  60. package/src/components/webhook/attempts.tsx +3 -3
  61. package/src/contexts/products.tsx +2 -3
  62. package/src/libs/api.ts +2 -19
  63. package/src/libs/dayjs.ts +1 -15
  64. package/src/libs/util.ts +24 -555
  65. package/src/locales/en.tsx +0 -139
  66. package/src/locales/index.tsx +5 -23
  67. package/src/locales/zh.tsx +0 -136
  68. package/src/pages/admin/billing/index.tsx +4 -2
  69. package/src/pages/admin/billing/invoices/detail.tsx +3 -4
  70. package/src/pages/admin/billing/subscriptions/detail.tsx +3 -3
  71. package/src/pages/admin/customers/customers/detail.tsx +3 -5
  72. package/src/pages/admin/customers/customers/index.tsx +2 -3
  73. package/src/pages/admin/customers/index.tsx +4 -2
  74. package/src/pages/admin/developers/events/detail.tsx +2 -3
  75. package/src/pages/admin/developers/index.tsx +4 -2
  76. package/src/pages/admin/developers/webhooks/detail.tsx +3 -4
  77. package/src/pages/admin/developers/webhooks/index.tsx +3 -4
  78. package/src/pages/admin/index.tsx +10 -7
  79. package/src/pages/admin/payments/index.tsx +4 -2
  80. package/src/pages/admin/payments/intents/detail.tsx +4 -6
  81. package/src/pages/admin/payments/links/create.tsx +3 -5
  82. package/src/pages/admin/payments/links/detail.tsx +4 -5
  83. package/src/pages/admin/payments/links/index.tsx +4 -6
  84. package/src/pages/admin/products/passports/index.tsx +1 -1
  85. package/src/pages/admin/products/prices/actions.tsx +2 -3
  86. package/src/pages/admin/products/prices/detail.tsx +2 -3
  87. package/src/pages/admin/products/prices/list.tsx +2 -4
  88. package/src/pages/admin/products/pricing-tables/create.tsx +2 -3
  89. package/src/pages/admin/products/pricing-tables/detail.tsx +4 -5
  90. package/src/pages/admin/products/pricing-tables/index.tsx +2 -4
  91. package/src/pages/admin/products/products/create.tsx +2 -4
  92. package/src/pages/admin/products/products/detail.tsx +4 -5
  93. package/src/pages/admin/products/products/index.tsx +4 -6
  94. package/src/pages/admin/settings/index.tsx +4 -2
  95. package/src/pages/admin/settings/payment-methods/create.tsx +3 -5
  96. package/src/pages/admin/settings/payment-methods/index.tsx +2 -3
  97. package/src/pages/checkout/index.tsx +6 -3
  98. package/src/pages/checkout/pay.tsx +5 -69
  99. package/src/pages/checkout/pricing-table.tsx +3 -7
  100. package/src/pages/customer/index.tsx +7 -7
  101. package/src/pages/customer/invoice.tsx +10 -11
  102. package/src/pages/customer/subscription/detail.tsx +4 -4
  103. package/src/pages/customer/subscription/update.tsx +19 -19
  104. package/src/components/checkout/amount.tsx +0 -24
  105. package/src/components/checkout/error.tsx +0 -30
  106. package/src/components/checkout/footer.tsx +0 -12
  107. package/src/components/checkout/form/address.tsx +0 -119
  108. package/src/components/checkout/form/index.tsx +0 -400
  109. package/src/components/checkout/form/phone.tsx +0 -103
  110. package/src/components/checkout/form/stripe.tsx +0 -195
  111. package/src/components/checkout/form/user-buttons.tsx +0 -24
  112. package/src/components/checkout/header.tsx +0 -40
  113. package/src/components/checkout/pay.tsx +0 -385
  114. package/src/components/checkout/pricing-table.tsx +0 -205
  115. package/src/components/checkout/product-card.tsx +0 -52
  116. package/src/components/checkout/product-item.tsx +0 -111
  117. package/src/components/checkout/skeleton/overview.tsx +0 -21
  118. package/src/components/checkout/skeleton/payment.tsx +0 -35
  119. package/src/components/checkout/success.tsx +0 -183
  120. package/src/components/checkout/summary.tsx +0 -198
  121. package/src/components/input.tsx +0 -58
  122. package/src/components/livemode.tsx +0 -23
  123. package/src/components/pricing-table/product-skeleton.tsx +0 -39
  124. package/src/components/status.tsx +0 -19
  125. package/src/components/switch.tsx +0 -48
  126. package/src/contexts/settings.tsx +0 -54
@@ -1,111 +0,0 @@
1
- import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
2
- import type { PriceRecurring, TCheckoutSessionExpanded, TLineItemExpanded, TPaymentCurrency } from '@did-pay/types';
3
- import { Stack, Typography } from '@mui/material';
4
-
5
- import { formatLineItemPricing, formatPrice, formatRecurring, formatUpsellSaving } from '../../libs/util';
6
- import Status from '../status';
7
- import Switch from '../switch';
8
- import ProductCard from './product-card';
9
-
10
- type Props = {
11
- item: TLineItemExpanded;
12
- session: TCheckoutSessionExpanded;
13
- currency: TPaymentCurrency;
14
- onUpsell: Function;
15
- onDownsell: Function;
16
- mode?: 'normal' | 'cross-sell';
17
- children?: React.ReactNode;
18
- };
19
-
20
- ProductItem.defaultProps = {
21
- mode: 'normal',
22
- children: null,
23
- };
24
-
25
- export default function ProductItem({ item, session, currency, mode, children, onUpsell, onDownsell }: Props) {
26
- const { t, locale } = useLocaleContext();
27
- const pricing = formatLineItemPricing(item, currency, session.subscription_data?.trial_period_days || 0, locale);
28
- const saving = formatUpsellSaving(session, currency);
29
- const metered = item.price?.recurring?.usage_type === 'metered' ? t('common.metered') : '';
30
- const canUpsell = mode === 'normal' && session.line_items.length === 1;
31
- return (
32
- <Stack direction="column" alignItems="flex-start" spacing={1} sx={{ width: '100%' }}>
33
- <Stack direction="column" alignItems="flex-end" sx={{ width: '100%' }}>
34
- <Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ width: '100%' }}>
35
- <ProductCard
36
- logo={item.price.product?.images[0]}
37
- name={item.price.product?.name}
38
- description={item.price.product?.description}
39
- extra={
40
- item.price.type === 'recurring' && item.price.recurring
41
- ? [pricing.quantity, t('common.billed', { rule: `${formatRecurring(item.upsell_price?.recurring || item.price.recurring, true, 'per', locale)} ${metered}` })].filter(Boolean).join(', ') // prettier-ignore
42
- : pricing.quantity
43
- }
44
- />
45
- <Stack direction="column" alignItems="flex-end" flex={1}>
46
- <Typography sx={{ color: 'text.primary', fontWeight: 500 }} gutterBottom>
47
- {pricing.primary}
48
- </Typography>
49
- {pricing.secondary && (
50
- <Typography sx={{ fontSize: '0.85rem', color: 'text.secondary' }}>{pricing.secondary}</Typography>
51
- )}
52
- </Stack>
53
- </Stack>
54
- {children}
55
- </Stack>
56
- {canUpsell && !item.upsell_price_id && item.price.upsell?.upsells_to && (
57
- <Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ width: '100%' }}>
58
- <Typography
59
- component="label"
60
- htmlFor="upsell-switch"
61
- sx={{
62
- fontSize: 12,
63
- cursor: 'pointer',
64
- color: 'text.primary',
65
- }}>
66
- <Switch
67
- id="upsell-switch"
68
- sx={{ mr: 1 }}
69
- variant="success"
70
- checked={false}
71
- onChange={() => onUpsell(item.price_id, item.price.upsell?.upsells_to_id)}
72
- />
73
- {t('checkout.upsell.save', {
74
- recurring: formatRecurring(item.price.upsell.upsells_to.recurring as PriceRecurring, true, 'per', locale),
75
- })}
76
- <Status label={t('checkout.upsell.off', { saving })} color="primary" variant="outlined" sx={{ ml: 1 }} />
77
- </Typography>
78
- <Typography component="span" sx={{ fontSize: 12 }}>
79
- {formatPrice(item.price.upsell.upsells_to, currency, item.price.product?.unit_label, 1, true, locale)}
80
- </Typography>
81
- </Stack>
82
- )}
83
- {canUpsell && item.upsell_price_id && (
84
- <Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ width: '100%' }}>
85
- <Typography
86
- component="label"
87
- htmlFor="upsell-switch"
88
- sx={{
89
- fontSize: 12,
90
- cursor: 'pointer',
91
- color: 'text.secondary',
92
- }}>
93
- <Switch
94
- id="upsell-switch"
95
- sx={{ mr: 1 }}
96
- variant="success"
97
- checked
98
- onChange={() => onDownsell(item.upsell_price_id)}
99
- />
100
- {t('checkout.upsell.revert', {
101
- recurring: t(`common.${formatRecurring(item.price.recurring as PriceRecurring)}`),
102
- })}
103
- </Typography>
104
- <Typography component="span" sx={{ fontSize: 12 }}>
105
- {formatPrice(item.price, currency, item.price.product?.unit_label, 1, true, locale)}
106
- </Typography>
107
- </Stack>
108
- )}
109
- </Stack>
110
- );
111
- }
@@ -1,21 +0,0 @@
1
- import { Fade, Skeleton, Stack, Typography } from '@mui/material';
2
-
3
- export default function OverviewSkeleton() {
4
- return (
5
- <Fade in>
6
- <Stack direction="column">
7
- <Stack direction="row" alignItems="center" spacing={2}>
8
- <Skeleton variant="circular" width={32} height={32} />
9
- <Skeleton variant="text" sx={{ fontSize: '2rem', width: '40%' }} />
10
- </Stack>
11
- <Typography mt={3} component="div" variant="h4">
12
- <Skeleton />
13
- </Typography>
14
- <Typography component="div" variant="h2">
15
- <Skeleton />
16
- </Typography>
17
- <Skeleton sx={{ mt: 3 }} variant="rounded" width={200} height={200} />
18
- </Stack>
19
- </Fade>
20
- );
21
- }
@@ -1,35 +0,0 @@
1
- import { Box, Fade, Skeleton, Stack, Typography } from '@mui/material';
2
-
3
- export default function PaymentSkeleton() {
4
- return (
5
- <Fade in>
6
- <Stack direction="column" spacing={3}>
7
- <Skeleton variant="text" sx={{ fontSize: '2rem', width: '40%' }} />
8
- <Box>
9
- <Typography component="div" variant="h4">
10
- <Skeleton />
11
- </Typography>
12
- <Typography component="div" variant="h1">
13
- <Skeleton />
14
- </Typography>
15
- </Box>
16
- <Box>
17
- <Typography component="div" variant="h4">
18
- <Skeleton />
19
- </Typography>
20
- <Typography component="div" variant="h1">
21
- <Skeleton />
22
- </Typography>
23
- </Box>
24
- <Box>
25
- <Typography component="div" variant="h4">
26
- <Skeleton />
27
- </Typography>
28
- <Typography component="div" variant="h1">
29
- <Skeleton />
30
- </Typography>
31
- </Box>
32
- </Stack>
33
- </Fade>
34
- );
35
- }
@@ -1,183 +0,0 @@
1
- import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
2
- import { Grow, Stack, Typography } from '@mui/material';
3
- import { styled } from '@mui/system';
4
- import { Link } from 'react-router-dom';
5
-
6
- type Props = {
7
- message: string;
8
- action: string;
9
- payee: string;
10
- };
11
-
12
- export default function PaymentSuccess({ message, action, payee }: Props) {
13
- const { t } = useLocaleContext();
14
- return (
15
- <Grow in>
16
- <Stack direction="column" alignItems="center" justifyContent="center" sx={{ height: 360 }}>
17
- <Div>
18
- <div className="check-icon">
19
- <span className="icon-line line-tip" />
20
- <span className="icon-line line-long" />
21
- <div className="icon-circle" />
22
- <div className="icon-fix" />
23
- </div>
24
- </Div>
25
- <Typography variant="h5" color="text.primary" mb={3}>
26
- {message}
27
- </Typography>
28
- <Typography variant="body1" color="text.secondary" textAlign="center">
29
- {t('checkout.completed.tip', { payee })}
30
- </Typography>
31
- {['subscription', 'setup'].includes(action) && (
32
- <Typography textAlign="center" sx={{ mt: 2 }}>
33
- <Link to="/customer">{t('checkout.portal', { payee })}</Link>
34
- </Typography>
35
- )}
36
- </Stack>
37
- </Grow>
38
- );
39
- }
40
-
41
- const Div = styled('div')`
42
- width: 80px;
43
- height: 115px;
44
-
45
- .check-icon {
46
- width: 80px;
47
- height: 80px;
48
- position: relative;
49
- border-radius: 50%;
50
- box-sizing: content-box;
51
- border: 4px solid ${(props) => props.theme.palette.success.main};
52
- }
53
- .check-icon::before {
54
- top: 3px;
55
- left: -2px;
56
- width: 30px;
57
- transform-origin: 100% 50%;
58
- border-radius: 100px 0 0 100px;
59
- }
60
- .check-icon::after {
61
- top: 0;
62
- left: 30px;
63
- width: 60px;
64
- transform-origin: 0 50%;
65
- border-radius: 0 100px 100px 0;
66
- animation: rotate-circle 4.25s ease-in;
67
- }
68
- .check-icon::before,
69
- .check-icon::after {
70
- content: '';
71
- height: 100px;
72
- position: absolute;
73
- background: #ffffff;
74
- transform: rotate(-45deg);
75
- }
76
- .check-icon .icon-line {
77
- height: 5px;
78
- background-color: ${(props) => props.theme.palette.success.main};
79
- display: block;
80
- border-radius: 2px;
81
- position: absolute;
82
- z-index: 10;
83
- }
84
- .check-icon .icon-line.line-tip {
85
- top: 46px;
86
- left: 14px;
87
- width: 25px;
88
- transform: rotate(45deg);
89
- animation: icon-line-tip 0.75s;
90
- }
91
- .check-icon .icon-line.line-long {
92
- top: 38px;
93
- right: 8px;
94
- width: 47px;
95
- transform: rotate(-45deg);
96
- animation: icon-line-long 0.75s;
97
- }
98
- .check-icon .icon-circle {
99
- top: -4px;
100
- left: -4px;
101
- z-index: 10;
102
- width: 80px;
103
- height: 80px;
104
- border-radius: 50%;
105
- position: absolute;
106
- box-sizing: content-box;
107
- border: 4px solid rgba(76, 175, 80, 0.5);
108
- }
109
- .check-icon .icon-fix {
110
- top: 8px;
111
- width: 5px;
112
- left: 26px;
113
- z-index: 1;
114
- height: 85px;
115
- position: absolute;
116
- transform: rotate(-45deg);
117
- background-color: #ffffff;
118
- }
119
-
120
- @keyframes rotate-circle {
121
- 0% {
122
- transform: rotate(-45deg);
123
- }
124
- 5% {
125
- transform: rotate(-45deg);
126
- }
127
- 12% {
128
- transform: rotate(-405deg);
129
- }
130
- 100% {
131
- transform: rotate(-405deg);
132
- }
133
- }
134
- @keyframes icon-line-tip {
135
- 0% {
136
- width: 0;
137
- left: 1px;
138
- top: 19px;
139
- }
140
- 54% {
141
- width: 0;
142
- left: 1px;
143
- top: 19px;
144
- }
145
- 70% {
146
- width: 50px;
147
- left: -8px;
148
- top: 37px;
149
- }
150
- 84% {
151
- width: 17px;
152
- left: 21px;
153
- top: 48px;
154
- }
155
- 100% {
156
- width: 25px;
157
- left: 14px;
158
- top: 45px;
159
- }
160
- }
161
- @keyframes icon-line-long {
162
- 0% {
163
- width: 0;
164
- right: 46px;
165
- top: 54px;
166
- }
167
- 65% {
168
- width: 0;
169
- right: 46px;
170
- top: 54px;
171
- }
172
- 84% {
173
- width: 55px;
174
- right: 0px;
175
- top: 35px;
176
- }
177
- 100% {
178
- width: 47px;
179
- right: 8px;
180
- top: 38px;
181
- }
182
- }
183
- `;
@@ -1,198 +0,0 @@
1
- import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
2
- import type { TCheckoutSessionExpanded, TLineItemExpanded, TPaymentCurrency } from '@did-pay/types';
3
- import { LoadingButton } from '@mui/lab';
4
- import { Fade, Grow, Stack, Typography, keyframes } from '@mui/material';
5
- import { useRequest, useSetState } from 'ahooks';
6
- import noop from 'lodash/noop';
7
- import useBus from 'use-bus';
8
-
9
- import api from '../../libs/api';
10
- import { formatCheckoutHeadlines } from '../../libs/util';
11
- import Status from '../status';
12
- import PaymentAmount from './amount';
13
- import ProductItem from './product-item';
14
-
15
- const shake = keyframes`
16
- 0% {
17
- transform: rotate(0deg);
18
- }
19
- 25% {
20
- transform: rotate(2deg);
21
- }
22
- 50% {
23
- transform: rotate(0eg);
24
- }
25
- 75% {
26
- transform: rotate(-2deg);
27
- }
28
- 100% {
29
- transform: rotate(0deg);
30
- }
31
- `;
32
-
33
- type Props = {
34
- checkoutSession: TCheckoutSessionExpanded;
35
- currency: TPaymentCurrency;
36
- onUpsell: Function;
37
- onDownsell: Function;
38
- onApplyCrossSell: Function;
39
- onCancelCrossSell: Function;
40
- };
41
-
42
- async function fetchCrossSell(id: string) {
43
- try {
44
- const { data } = await api.get(`/api/checkout-sessions/${id}/cross-sell`);
45
- if (!data.error) {
46
- return data;
47
- }
48
-
49
- return null;
50
- } catch (err) {
51
- return null;
52
- }
53
- }
54
-
55
- export default function PaymentSummary({
56
- checkoutSession,
57
- currency,
58
- onUpsell,
59
- onDownsell,
60
- onApplyCrossSell,
61
- onCancelCrossSell,
62
- }: Props) {
63
- const { t, locale } = useLocaleContext();
64
- const [state, setState] = useSetState({ loading: false, shake: false });
65
- const { data, runAsync } = useRequest(() => fetchCrossSell(checkoutSession.id));
66
- const headlines = formatCheckoutHeadlines(checkoutSession, currency, locale);
67
-
68
- useBus(
69
- 'error.REQUIRE_CROSS_SELL',
70
- () => {
71
- setState({ shake: true });
72
- setTimeout(() => {
73
- setState({ shake: false });
74
- }, 1000);
75
- },
76
- []
77
- );
78
-
79
- const handleUpsell = async (from: string, to: string) => {
80
- await onUpsell(from, to);
81
- runAsync();
82
- };
83
-
84
- const handleDownsell = async (from: string) => {
85
- await onDownsell(from);
86
- runAsync();
87
- };
88
-
89
- const handleApplyCrossSell = async () => {
90
- if (data) {
91
- try {
92
- setState({ loading: true });
93
- await onApplyCrossSell(data.id);
94
- } catch (err) {
95
- console.error(err);
96
- } finally {
97
- setState({ loading: false });
98
- }
99
- }
100
- };
101
-
102
- const handleCancelCrossSell = async () => {
103
- try {
104
- setState({ loading: true });
105
- await onCancelCrossSell();
106
- } catch (err) {
107
- console.error(err);
108
- } finally {
109
- setState({ loading: false });
110
- }
111
- };
112
-
113
- return (
114
- <Fade in>
115
- <Stack
116
- className="cko-product"
117
- direction="column"
118
- sx={{
119
- mt: 8,
120
- }}>
121
- <Stack className="cko-product-summary" sx={{ mb: 4 }}>
122
- <Typography sx={{ fontWeight: 500, fontSize: '1.15rem', color: 'text.secondary' }}>
123
- {headlines.action}
124
- </Typography>
125
- <PaymentAmount amount={headlines.amount} />
126
- {headlines.then && (
127
- <Typography sx={{ fontSize: '0.9rem', color: 'text.secondary' }}>{headlines.then}</Typography>
128
- )}
129
- </Stack>
130
- <Stack spacing={2}>
131
- {checkoutSession.line_items.map((x: TLineItemExpanded) => (
132
- <ProductItem
133
- key={x.price_id}
134
- item={x}
135
- session={checkoutSession}
136
- currency={currency}
137
- onUpsell={handleUpsell}
138
- onDownsell={handleDownsell}>
139
- {x.cross_sell && (
140
- <LoadingButton
141
- size="small"
142
- loadingPosition="end"
143
- color="error"
144
- variant="text"
145
- loading={state.loading}
146
- onClick={handleCancelCrossSell}>
147
- {t('checkout.cross_sell.remove')}
148
- </LoadingButton>
149
- )}
150
- </ProductItem>
151
- ))}
152
- </Stack>
153
- {data && checkoutSession.line_items.some((x) => x.price_id === data.id) === false && (
154
- <Grow in>
155
- <Stack
156
- direction="column"
157
- alignItems="flex-end"
158
- spacing={0.5}
159
- sx={{
160
- border: '1px solid #eee',
161
- borderRadius: 1,
162
- padding: 1,
163
- animation: state.shake ? `${shake} 0.2s 5 ease-in-out` : 'none',
164
- mt: {
165
- xs: 4,
166
- md: 8,
167
- },
168
- }}>
169
- <ProductItem
170
- item={{ quantity: 1, price: data, price_id: data.id, cross_sell: true } as TLineItemExpanded}
171
- session={checkoutSession}
172
- currency={currency}
173
- onUpsell={noop}
174
- onDownsell={noop}
175
- />
176
- <Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ width: 1 }}>
177
- <Typography>
178
- {checkoutSession.cross_sell_behavior === 'required' && (
179
- <Status label={t('checkout.required')} color="info" variant="outlined" sx={{ mr: 1 }} />
180
- )}
181
- </Typography>
182
- <LoadingButton
183
- size="small"
184
- loadingPosition="end"
185
- color={checkoutSession.cross_sell_behavior === 'required' ? 'info' : 'info'}
186
- variant={checkoutSession.cross_sell_behavior === 'required' ? 'text' : 'text'}
187
- loading={state.loading}
188
- onClick={handleApplyCrossSell}>
189
- {t('checkout.cross_sell.add')}
190
- </LoadingButton>
191
- </Stack>
192
- </Stack>
193
- </Grow>
194
- )}
195
- </Stack>
196
- </Fade>
197
- );
198
- }
@@ -1,58 +0,0 @@
1
- import { Box, FormLabel, InputAdornment, TextField, TextFieldProps, Typography } from '@mui/material';
2
- import get from 'lodash/get';
3
- import { Controller, RegisterOptions, useFormContext } from 'react-hook-form';
4
-
5
- type InputProps = TextFieldProps & {
6
- name: string;
7
- label?: string;
8
- placeholder?: string;
9
- errorPosition?: 'right' | 'bottom';
10
- rules?: RegisterOptions;
11
- };
12
-
13
- FormInput.defaultProps = {
14
- label: '',
15
- placeholder: '',
16
- errorPosition: 'bottom',
17
- rules: {},
18
- };
19
-
20
- export function FormInputError({ error }: { error: string }) {
21
- return (
22
- <InputAdornment position="end">
23
- <Typography component="span" color="error">
24
- {error}
25
- </Typography>
26
- </InputAdornment>
27
- );
28
- }
29
-
30
- export default function FormInput({ name, label, placeholder, rules, errorPosition, ...rest }: InputProps) {
31
- const { control, formState } = useFormContext();
32
- const error = get(formState.errors, name)?.message as string;
33
- return (
34
- <Controller
35
- name={name}
36
- control={control}
37
- rules={rules}
38
- render={({ field }) => (
39
- <Box sx={{ width: '100%' }}>
40
- {!!label && <FormLabel>{label}</FormLabel>}
41
- <TextField
42
- fullWidth
43
- error={!!get(formState.errors, name)}
44
- helperText={errorPosition === 'bottom' && error ? error : ''}
45
- placeholder={placeholder}
46
- size="small"
47
- {...field}
48
- {...rest}
49
- InputProps={Object.assign(
50
- rest.InputProps || {},
51
- errorPosition === 'right' && error ? { endAdornment: <FormInputError error={error} /> } : {}
52
- )}
53
- />
54
- </Box>
55
- )}
56
- />
57
- );
58
- }
@@ -1,23 +0,0 @@
1
- import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
2
- import { Chip } from '@mui/material';
3
-
4
- export default function Livemode() {
5
- const { t } = useLocaleContext();
6
- return (
7
- <Chip
8
- label={t('common.livemode')}
9
- size="small"
10
- sx={{
11
- ml: 2,
12
- height: 18,
13
- lineHeight: 1,
14
- textTransform: 'uppercase',
15
- fontSize: '0.8rem',
16
- fontWeight: 'bold',
17
- borderRadius: '4px',
18
- backgroundColor: '#ffde92',
19
- color: '#bb5504',
20
- }}
21
- />
22
- );
23
- }
@@ -1,39 +0,0 @@
1
- import { Fade, Skeleton, Stack, Typography } from '@mui/material';
2
-
3
- export default function ProductSkeleton({ count }: { count: number }) {
4
- return (
5
- <Fade in>
6
- <Stack
7
- direction="column"
8
- alignItems="center"
9
- padding={4}
10
- spacing={1}
11
- sx={{
12
- width: 320,
13
- border: '1px solid #eee',
14
- borderRadius: 1,
15
- transition: 'border-color 0.3s ease 0s, box-shadow 0.3s ease 0s',
16
- boxShadow: '0 4px 8px rgba(0, 0, 0, 20%)',
17
- '&:hover': {
18
- borderColor: '#ddd',
19
- boxShadow: '0 8px 16px rgba(0, 0, 0, 20%)',
20
- },
21
- }}>
22
- <Typography component="div" variant="h4" sx={{ width: '50%' }}>
23
- <Skeleton />
24
- </Typography>
25
- <Skeleton variant="text" sx={{ fontSize: '1rem', width: '60%' }} />
26
- <Typography component="div" variant="h3" sx={{ width: '60%' }}>
27
- <Skeleton />
28
- </Typography>
29
- <Typography component="div" variant="h3" sx={{ width: '100%' }}>
30
- <Skeleton />
31
- </Typography>
32
- {Array.from({ length: count }).map((_, i) => (
33
- // eslint-disable-next-line react/no-array-index-key
34
- <Skeleton key={i} variant="text" sx={{ fontSize: '1rem', width: '60%' }} />
35
- ))}
36
- </Stack>
37
- </Fade>
38
- );
39
- }
@@ -1,19 +0,0 @@
1
- import { Chip, ChipProps } from '@mui/material';
2
-
3
- export default function Status(props: ChipProps) {
4
- return (
5
- <Chip
6
- size="small"
7
- variant="outlined"
8
- {...props}
9
- sx={{
10
- ...(props.sx || {}),
11
- borderRadius: '4px',
12
- height: 20,
13
- lineHeight: 1,
14
- textTransform: 'capitalize',
15
- marginRight: '10px',
16
- }}
17
- />
18
- );
19
- }