payment-kit 1.17.2 → 1.17.4
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.
- package/api/src/integrations/arcblock/nft.ts +1 -1
- package/api/src/libs/env.ts +0 -2
- package/api/src/libs/middleware.ts +2 -2
- package/api/src/libs/overdraft-protection.ts +4 -1
- package/api/src/libs/security.ts +2 -2
- package/api/src/libs/subscription.ts +1 -1
- package/api/src/locales/en.ts +2 -2
- package/api/src/locales/zh.ts +2 -2
- package/api/src/queues/notification.ts +1 -1
- package/api/src/queues/subscription.ts +1 -1
- package/api/src/routes/connect/overdraft-protection.ts +4 -1
- package/api/src/routes/connect/shared.ts +12 -7
- package/api/src/routes/invoices.ts +21 -5
- package/api/src/routes/subscriptions.ts +1 -1
- package/blocklet.yml +1 -1
- package/package.json +23 -23
- package/src/components/customer/overdraft-protection.tsx +219 -74
- package/src/components/subscription/metrics.tsx +83 -7
- package/src/components/subscription/portal/actions.tsx +188 -153
- package/src/components/subscription/portal/list.tsx +1 -0
- package/src/libs/dayjs.ts +132 -0
- package/src/locales/en.tsx +18 -11
- package/src/locales/zh.tsx +17 -10
- package/src/pages/admin/billing/subscriptions/detail.tsx +1 -1
- package/src/pages/customer/recharge.tsx +63 -27
- package/src/pages/customer/subscription/detail.tsx +153 -10
- package/src/pages/customer/subscription/embed.tsx +1 -0
- /package/api/src/libs/notification/template/{subscription.overdraft-protection.exhausted.ts → subscription-overdraft-protection-exhausted.ts} +0 -0
package/src/locales/zh.tsx
CHANGED
|
@@ -24,6 +24,7 @@ export default flat({
|
|
|
24
24
|
rechargeTime: '充值时间',
|
|
25
25
|
submit: '提交',
|
|
26
26
|
custom: '自定义',
|
|
27
|
+
estimatedDuration: '预计可用 {duration}',
|
|
27
28
|
},
|
|
28
29
|
admin: {
|
|
29
30
|
balances: '余额',
|
|
@@ -445,6 +446,9 @@ export default flat({
|
|
|
445
446
|
update: '更新订阅',
|
|
446
447
|
resume: '恢复付款',
|
|
447
448
|
resumeTip: '您确定要继续收款吗?此订阅的未来账单将继续付款。',
|
|
449
|
+
paymentAddress: '扣费地址',
|
|
450
|
+
currentBalance: '扣款账户余额',
|
|
451
|
+
insufficientBalance: '余额不足,立即充值',
|
|
448
452
|
cancel: {
|
|
449
453
|
schedule: '计划取消',
|
|
450
454
|
title: '取消订阅',
|
|
@@ -634,34 +638,37 @@ export default flat({
|
|
|
634
638
|
error: '授权失败',
|
|
635
639
|
},
|
|
636
640
|
overdraftProtection: {
|
|
637
|
-
title: '
|
|
638
|
-
setting: '
|
|
639
|
-
tip: '
|
|
641
|
+
title: '订阅守护',
|
|
642
|
+
setting: '配置订阅守护',
|
|
643
|
+
tip: '为避免因扣费失败中断服务,您可以通过质押开启订阅守护。按时付款不会收取额外费用,请及时付清账单,若可用质押不足或者超期未付,我们将从质押中扣除并收取服务费',
|
|
640
644
|
enabled: '已启用',
|
|
641
645
|
disabled: '未启用',
|
|
642
646
|
returnRemaining: '退还剩余质押',
|
|
643
|
-
returnRemainingTip: '
|
|
647
|
+
returnRemainingTip: '退还剩余质押后,订阅守护服务将自动关闭,请确认操作。',
|
|
644
648
|
applyRemainingSuccess: '质押退还申请成功',
|
|
645
649
|
remaining: '您当前剩余可用质押:{amount} {symbol}, 每周期预计需质押:{estimateAmount} {symbol}。',
|
|
646
|
-
noRemaining: '
|
|
650
|
+
noRemaining: '当前无质押,为确保订阅守护服务的正常使用,请至少质押 {estimateAmount} {symbol}。',
|
|
647
651
|
remainingNotEnough:
|
|
648
652
|
'当前存在未支付的账单,总计 {due} {symbol},如果不支付,您当前剩余质押将无法覆盖下期账单,剩余可用质押:{unused} {symbol},请质押至少 {min} {symbol}。',
|
|
649
653
|
due: '请先支付欠款',
|
|
650
|
-
insufficient: '
|
|
651
|
-
insufficientTip: '
|
|
654
|
+
insufficient: '额度不足,下期账单将无法使用订阅守护服务, 请添加额度',
|
|
655
|
+
insufficientTip: '订阅守护服务额度不足,请尽快质押保证订阅守护服务的正常使用。',
|
|
652
656
|
intervals: '个周期',
|
|
653
657
|
estimatedDuration: '预计可用 {duration} {unit}',
|
|
654
658
|
rule: '规则:N * ( P + Fee )',
|
|
655
|
-
ruleTip: 'N 为周期数, P 为订阅账单费用, Fee
|
|
659
|
+
ruleTip: 'N 为周期数, P 为订阅账单费用, Fee 为订阅守护服务费用,单次费用为 {gas} {symbol}',
|
|
656
660
|
min: '质押金额不得小于 {min} {symbol}',
|
|
657
|
-
settingSuccess: '
|
|
658
|
-
settingError: '
|
|
661
|
+
settingSuccess: '订阅守护配置成功',
|
|
662
|
+
settingError: '订阅守护配置失败',
|
|
659
663
|
keepStake: '不退还质押',
|
|
660
664
|
returnStake: '退还剩余质押',
|
|
661
665
|
stake: '质押',
|
|
662
666
|
address: '质押账户',
|
|
663
667
|
total: '总质押:{total} {symbol},',
|
|
664
668
|
disableConfirm: '您当前有未支付的账单,请先付清账单。',
|
|
669
|
+
open: '开启订阅守护',
|
|
670
|
+
payerAddress: '付款账户',
|
|
671
|
+
stakingAddress: '质押地址',
|
|
665
672
|
},
|
|
666
673
|
unpaidInvoicesWarning: '您当前有未支付的账单,请先付清账单。',
|
|
667
674
|
unpaidInvoicesWarningTip: '您当前有未支付的账单,请及时付清。',
|
|
@@ -38,6 +38,7 @@ import SubscriptionMetrics from '../../components/subscription/metrics';
|
|
|
38
38
|
import { goBackOrFallback } from '../../libs/util';
|
|
39
39
|
import CustomerLink from '../../components/customer/link';
|
|
40
40
|
import { useSessionContext } from '../../contexts/session';
|
|
41
|
+
import { formatSmartDuration, TimeUnit } from '../../libs/dayjs';
|
|
41
42
|
|
|
42
43
|
const Root = styled(Stack)(({ theme }) => ({
|
|
43
44
|
marginBottom: theme.spacing(3),
|
|
@@ -73,6 +74,7 @@ export default function RechargePage() {
|
|
|
73
74
|
const [customAmount, setCustomAmount] = useState(false);
|
|
74
75
|
const [presetAmounts, setPresetAmounts] = useState<Array<{ amount: string; cycles: number }>>([]);
|
|
75
76
|
const { session } = useSessionContext();
|
|
77
|
+
const [cycleAmount, setCycleAmount] = useState('0');
|
|
76
78
|
|
|
77
79
|
const {
|
|
78
80
|
paymentCurrency,
|
|
@@ -116,6 +118,11 @@ export default function RechargePage() {
|
|
|
116
118
|
{ amount: getCycleAmount(5), cycles: 5 },
|
|
117
119
|
{ amount: getCycleAmount(10), cycles: 10 },
|
|
118
120
|
]);
|
|
121
|
+
|
|
122
|
+
setCycleAmount(fromUnitToToken(upcomingRes.data.amount || '0', upcomingRes.data?.currency?.decimal) || '0');
|
|
123
|
+
if (!amount && !customAmount) {
|
|
124
|
+
handleSelect(getCycleAmount(10));
|
|
125
|
+
}
|
|
119
126
|
} catch (err) {
|
|
120
127
|
setError(formatError(err) || t('common.fetchError'));
|
|
121
128
|
console.error(err);
|
|
@@ -124,19 +131,36 @@ export default function RechargePage() {
|
|
|
124
131
|
}
|
|
125
132
|
};
|
|
126
133
|
|
|
134
|
+
const rechargeRef = useRef<HTMLDivElement>(null);
|
|
135
|
+
|
|
127
136
|
useEffect(() => {
|
|
128
137
|
fetchData();
|
|
129
138
|
}, [subscriptionId]);
|
|
130
139
|
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
if (rechargeRef.current && subscription) {
|
|
142
|
+
setTimeout(() => {
|
|
143
|
+
// @ts-ignore
|
|
144
|
+
rechargeRef.current?.scrollIntoView({
|
|
145
|
+
behavior: 'smooth',
|
|
146
|
+
});
|
|
147
|
+
}, 200);
|
|
148
|
+
}
|
|
149
|
+
}, [subscription]);
|
|
150
|
+
|
|
131
151
|
const handleRecharge = () => {
|
|
132
152
|
if (!subscription) return;
|
|
133
153
|
|
|
154
|
+
if (Number.isNaN(Number(amount))) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
134
158
|
connect.open({
|
|
135
159
|
containerEl: undefined as unknown as Element,
|
|
136
160
|
saveConnect: false,
|
|
137
161
|
action: 'recharge',
|
|
138
162
|
prefix: joinURL(getPrefix(), '/api/did'),
|
|
139
|
-
extraParams: { subscriptionId, amount },
|
|
163
|
+
extraParams: { subscriptionId, amount: Number(amount) },
|
|
140
164
|
onSuccess: () => {
|
|
141
165
|
connect.close();
|
|
142
166
|
Toast.success(t('customer.recharge.success'));
|
|
@@ -154,7 +178,9 @@ export default function RechargePage() {
|
|
|
154
178
|
const handleAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
155
179
|
const { value } = e.target;
|
|
156
180
|
if (!subscription) return;
|
|
157
|
-
|
|
181
|
+
if (!/^\d*\.?\d*$/.test(value)) return;
|
|
182
|
+
// 不允许以小数点开头
|
|
183
|
+
if (value.startsWith('.')) return;
|
|
158
184
|
const precision = subscription.paymentCurrency.maximum_precision || 6;
|
|
159
185
|
const errorMessage = formatAmountPrecisionLimit(value, locale, precision);
|
|
160
186
|
setAmountError(errorMessage || '');
|
|
@@ -198,13 +224,16 @@ export default function RechargePage() {
|
|
|
198
224
|
const totalIntervals = cycles * intervalCount;
|
|
199
225
|
const availableUnitKeys = ['hour', 'day', 'week', 'month', 'year'];
|
|
200
226
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
227
|
+
if (!availableUnitKeys.includes(interval)) {
|
|
228
|
+
return t('customer.recharge.estimatedDuration', {
|
|
229
|
+
duration: totalIntervals,
|
|
230
|
+
unit: t('customer.recharge.intervals').toLowerCase(),
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
return t('common.estimatedDuration', {
|
|
234
|
+
duration: formatSmartDuration(totalIntervals, interval as TimeUnit, {
|
|
235
|
+
t,
|
|
236
|
+
}),
|
|
208
237
|
});
|
|
209
238
|
};
|
|
210
239
|
|
|
@@ -248,7 +277,7 @@ export default function RechargePage() {
|
|
|
248
277
|
alignItems: { xs: 'flex-start', sm: 'flex-start', md: 'center' },
|
|
249
278
|
gap: { xs: 1, sm: 1, md: 3 },
|
|
250
279
|
}}>
|
|
251
|
-
<SubscriptionMetrics subscription={subscription} />
|
|
280
|
+
<SubscriptionMetrics subscription={subscription} showBalance={false} />
|
|
252
281
|
</Stack>
|
|
253
282
|
</Box>
|
|
254
283
|
|
|
@@ -292,7 +321,7 @@ export default function RechargePage() {
|
|
|
292
321
|
</Box>
|
|
293
322
|
<Divider />
|
|
294
323
|
|
|
295
|
-
<Box sx={{ maxWidth: 600 }}>
|
|
324
|
+
<Box sx={{ maxWidth: 600 }} ref={rechargeRef}>
|
|
296
325
|
<Typography variant="h2" gutterBottom>
|
|
297
326
|
{t('customer.recharge.title')}
|
|
298
327
|
</Typography>
|
|
@@ -389,22 +418,29 @@ export default function RechargePage() {
|
|
|
389
418
|
</Paper>
|
|
390
419
|
|
|
391
420
|
{customAmount && (
|
|
392
|
-
<
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
421
|
+
<Box>
|
|
422
|
+
<TextField
|
|
423
|
+
fullWidth
|
|
424
|
+
label={t('customer.recharge.amount')}
|
|
425
|
+
variant="outlined"
|
|
426
|
+
type="text"
|
|
427
|
+
value={amount}
|
|
428
|
+
error={!!amountError}
|
|
429
|
+
helperText={amountError}
|
|
430
|
+
onChange={handleAmountChange}
|
|
431
|
+
InputProps={{
|
|
432
|
+
endAdornment: <Typography>{subscription.paymentCurrency.symbol}</Typography>,
|
|
433
|
+
autoComplete: 'off',
|
|
434
|
+
}}
|
|
435
|
+
sx={{ mt: 1 }}
|
|
436
|
+
inputRef={customInputRef}
|
|
437
|
+
/>
|
|
438
|
+
{amount && Number(amount) > 0 && Number(cycleAmount) > 0 && !amountError && (
|
|
439
|
+
<Typography variant="body2" sx={{ color: 'text.lighter', mt: '8px !important' }} fontSize={12}>
|
|
440
|
+
{formatEstimatedDuration(Math.floor(Number(amount) / Number(cycleAmount)))}
|
|
441
|
+
</Typography>
|
|
442
|
+
)}
|
|
443
|
+
</Box>
|
|
408
444
|
)}
|
|
409
445
|
|
|
410
446
|
<Button
|
|
@@ -1,24 +1,34 @@
|
|
|
1
1
|
/* eslint-disable react/no-unstable-nested-components */
|
|
2
2
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import {
|
|
4
|
+
CustomerInvoiceList,
|
|
5
|
+
TxLink,
|
|
6
|
+
api,
|
|
7
|
+
formatBNStr,
|
|
8
|
+
formatTime,
|
|
9
|
+
hasDelegateTxHash,
|
|
10
|
+
useMobile,
|
|
11
|
+
} from '@blocklet/payment-react';
|
|
12
|
+
import type { TPaymentCurrency, TSubscriptionExpanded } from '@blocklet/payment-types';
|
|
13
|
+
import { ArrowBackOutlined, CheckCircle } from '@mui/icons-material';
|
|
14
|
+
import { Alert, Avatar, Box, Button, CircularProgress, Divider, Stack, Typography } from '@mui/material';
|
|
7
15
|
import { useRequest } from 'ahooks';
|
|
8
16
|
import { Link, useNavigate, useParams } from 'react-router-dom';
|
|
9
17
|
import { styled } from '@mui/system';
|
|
10
|
-
import { BN } from '@ocap/util';
|
|
18
|
+
import { BN, fromUnitToToken } from '@ocap/util';
|
|
19
|
+
import { useCallback, useRef } from 'react';
|
|
11
20
|
import Currency from '../../../components/currency';
|
|
12
21
|
import CustomerLink from '../../../components/customer/link';
|
|
13
22
|
import InfoRow from '../../../components/info-row';
|
|
14
23
|
import SubscriptionDescription from '../../../components/subscription/description';
|
|
15
24
|
import SubscriptionItemList from '../../../components/subscription/items';
|
|
16
25
|
import SubscriptionMetrics from '../../../components/subscription/metrics';
|
|
17
|
-
import SubscriptionActions from '../../../components/subscription/portal/actions';
|
|
26
|
+
import SubscriptionActions, { ActionMethods } from '../../../components/subscription/portal/actions';
|
|
18
27
|
import { canChangePaymentMethod } from '../../../libs/util';
|
|
19
28
|
import { useSessionContext } from '../../../contexts/session';
|
|
20
29
|
import InfoMetric from '../../../components/info-metric';
|
|
21
30
|
import { useUnpaidInvoicesCheckForSubscription } from '../../../hooks/subscription';
|
|
31
|
+
import { formatSmartDuration, TimeUnit } from '../../../libs/dayjs';
|
|
22
32
|
|
|
23
33
|
const fetchData = (id: string | undefined): Promise<TSubscriptionExpanded> => {
|
|
24
34
|
return api.get(`/api/subscriptions/${id}`).then((res) => res.data);
|
|
@@ -29,6 +39,14 @@ const fetchOverdraftProtection = (
|
|
|
29
39
|
): Promise<{ enabled: boolean; remaining: string; unused: string; upcoming: { amount: string }; gas: string }> => {
|
|
30
40
|
return api.get(`/api/subscriptions/${id}/overdraft-protection`).then((res) => res.data);
|
|
31
41
|
};
|
|
42
|
+
|
|
43
|
+
const fetchCycleAmount = (
|
|
44
|
+
subscriptionId: string,
|
|
45
|
+
params: { overdraftProtection: boolean }
|
|
46
|
+
): Promise<{ amount: string; gas: string; currency: TPaymentCurrency }> => {
|
|
47
|
+
return api.get(`/api/subscriptions/${subscriptionId}/cycle-amount`, { params }).then((res) => res.data);
|
|
48
|
+
};
|
|
49
|
+
|
|
32
50
|
const InfoDirection = 'column';
|
|
33
51
|
const InfoAlignItems = 'flex-start';
|
|
34
52
|
|
|
@@ -48,8 +66,29 @@ export default function CustomerSubscriptionDetail() {
|
|
|
48
66
|
ready: ['active', 'trialing', 'past_due'].includes(data?.status || ''),
|
|
49
67
|
});
|
|
50
68
|
|
|
69
|
+
const {
|
|
70
|
+
data: cycleAmount = {
|
|
71
|
+
amount: '0',
|
|
72
|
+
gas: '0',
|
|
73
|
+
},
|
|
74
|
+
} = useRequest(
|
|
75
|
+
() =>
|
|
76
|
+
fetchCycleAmount(id, {
|
|
77
|
+
overdraftProtection: true,
|
|
78
|
+
}),
|
|
79
|
+
{
|
|
80
|
+
refreshDeps: [id],
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const actionRef = useRef<ActionMethods>();
|
|
85
|
+
|
|
51
86
|
const enableOverdraftProtection = !!overdraftProtection?.enabled;
|
|
52
87
|
|
|
88
|
+
const actionSetUp = useCallback((methods: ActionMethods) => {
|
|
89
|
+
actionRef.current = methods;
|
|
90
|
+
}, []);
|
|
91
|
+
|
|
53
92
|
if (data?.customer?.did && session?.user?.did && data.customer.did !== session.user.did) {
|
|
54
93
|
return <Alert severity="error">You do not have permission to access other customer data</Alert>;
|
|
55
94
|
}
|
|
@@ -75,13 +114,116 @@ export default function CustomerSubscriptionDetail() {
|
|
|
75
114
|
new BN(overdraftProtection.unused).lt(
|
|
76
115
|
new BN(overdraftProtection.upcoming?.amount).add(new BN(overdraftProtection.gas))
|
|
77
116
|
);
|
|
117
|
+
const estimateAmount = +fromUnitToToken(cycleAmount.amount, data.paymentCurrency?.decimal);
|
|
118
|
+
const remainingStake = +fromUnitToToken(overdraftProtection?.unused, data.paymentCurrency?.decimal);
|
|
119
|
+
const formatEstimatedDuration = (cycles: number) => {
|
|
120
|
+
if (!data?.pending_invoice_item_interval) return '';
|
|
121
|
+
const { interval, interval_count: intervalCount } = data.pending_invoice_item_interval;
|
|
122
|
+
const totalIntervals = cycles * intervalCount;
|
|
123
|
+
const availableUnitKeys = ['hour', 'day', 'week', 'month', 'year'];
|
|
124
|
+
|
|
125
|
+
if (!availableUnitKeys.includes(interval)) {
|
|
126
|
+
return t('customer.overdraftProtection.estimatedDuration', {
|
|
127
|
+
duration: totalIntervals,
|
|
128
|
+
unit: t('customer.overdraftProtection.intervals').toLowerCase(),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return t('common.estimatedDuration', {
|
|
132
|
+
duration: formatSmartDuration(totalIntervals, interval as TimeUnit, {
|
|
133
|
+
t,
|
|
134
|
+
}),
|
|
135
|
+
});
|
|
136
|
+
};
|
|
78
137
|
if (!enabled) {
|
|
79
|
-
return
|
|
138
|
+
return (
|
|
139
|
+
<Stack direction="row" spacing={1} alignItems="center">
|
|
140
|
+
<Typography sx={{ color: 'text.lighter' }}>{t('customer.overdraftProtection.disabled')}</Typography>
|
|
141
|
+
<Button
|
|
142
|
+
size="small"
|
|
143
|
+
sx={{
|
|
144
|
+
fontSize: '13px',
|
|
145
|
+
color: 'text.link',
|
|
146
|
+
'&:hover': { backgroundColor: 'primary.lighter' },
|
|
147
|
+
}}
|
|
148
|
+
onClick={() =>
|
|
149
|
+
actionRef.current?.openOverdraftProtection({
|
|
150
|
+
enabled: true,
|
|
151
|
+
})
|
|
152
|
+
}>
|
|
153
|
+
{t('customer.overdraftProtection.open')}
|
|
154
|
+
</Button>
|
|
155
|
+
</Stack>
|
|
156
|
+
);
|
|
80
157
|
}
|
|
158
|
+
|
|
81
159
|
if (enabled && insufficient) {
|
|
82
|
-
return
|
|
160
|
+
return (
|
|
161
|
+
<Button
|
|
162
|
+
size="small"
|
|
163
|
+
color="error"
|
|
164
|
+
sx={{
|
|
165
|
+
fontSize: '12px',
|
|
166
|
+
textAlign: 'left',
|
|
167
|
+
}}
|
|
168
|
+
onClick={() =>
|
|
169
|
+
actionRef.current?.openOverdraftProtection({
|
|
170
|
+
enabled: true,
|
|
171
|
+
})
|
|
172
|
+
}>
|
|
173
|
+
{t('customer.overdraftProtection.insufficient')}
|
|
174
|
+
</Button>
|
|
175
|
+
);
|
|
83
176
|
}
|
|
84
|
-
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<Stack direction="row" spacing={1} alignItems="center">
|
|
180
|
+
<Stack direction="row" spacing={0.5} alignItems="center">
|
|
181
|
+
<CheckCircle
|
|
182
|
+
sx={{
|
|
183
|
+
fontSize: '16px',
|
|
184
|
+
color: 'success.main',
|
|
185
|
+
verticalAlign: 'middle',
|
|
186
|
+
}}
|
|
187
|
+
/>
|
|
188
|
+
<Typography
|
|
189
|
+
sx={{
|
|
190
|
+
color: 'success.main',
|
|
191
|
+
fontWeight: 500,
|
|
192
|
+
}}>
|
|
193
|
+
{t('customer.overdraftProtection.enabled')}
|
|
194
|
+
</Typography>
|
|
195
|
+
</Stack>
|
|
196
|
+
<Divider
|
|
197
|
+
orientation="vertical"
|
|
198
|
+
flexItem
|
|
199
|
+
sx={{
|
|
200
|
+
mx: 1,
|
|
201
|
+
borderColor: 'divider',
|
|
202
|
+
}}
|
|
203
|
+
/>
|
|
204
|
+
<Typography
|
|
205
|
+
sx={{
|
|
206
|
+
color: 'text.primary',
|
|
207
|
+
display: 'flex',
|
|
208
|
+
alignItems: 'center',
|
|
209
|
+
gap: 0.5,
|
|
210
|
+
fontWeight: 500,
|
|
211
|
+
}}>
|
|
212
|
+
<Avatar src={data.paymentCurrency?.logo} sx={{ width: 16, height: 16 }} alt={data.paymentCurrency?.name} />
|
|
213
|
+
<Box display="flex" alignItems="baseline">
|
|
214
|
+
{formatBNStr(overdraftProtection?.unused, data.paymentCurrency.decimal)}
|
|
215
|
+
<Typography
|
|
216
|
+
sx={{
|
|
217
|
+
color: 'text.secondary',
|
|
218
|
+
fontSize: '14px',
|
|
219
|
+
ml: 0.5,
|
|
220
|
+
}}>
|
|
221
|
+
{data.paymentCurrency.symbol}({formatEstimatedDuration(Math.ceil(remainingStake / estimateAmount))})
|
|
222
|
+
</Typography>
|
|
223
|
+
</Box>
|
|
224
|
+
</Typography>
|
|
225
|
+
</Stack>
|
|
226
|
+
);
|
|
85
227
|
};
|
|
86
228
|
|
|
87
229
|
return (
|
|
@@ -119,7 +261,7 @@ export default function CustomerSubscriptionDetail() {
|
|
|
119
261
|
onChange: () => refreshOverdraftProtection(),
|
|
120
262
|
}}
|
|
121
263
|
showRecharge
|
|
122
|
-
mode={isMobile ? 'menu' : '
|
|
264
|
+
mode={isMobile ? 'menu-only' : 'primary-buttons'}
|
|
123
265
|
actionProps={{
|
|
124
266
|
cancel: {
|
|
125
267
|
variant: 'outlined',
|
|
@@ -134,6 +276,7 @@ export default function CustomerSubscriptionDetail() {
|
|
|
134
276
|
color: 'primary',
|
|
135
277
|
},
|
|
136
278
|
}}
|
|
279
|
+
setUp={actionSetUp}
|
|
137
280
|
/>
|
|
138
281
|
</Stack>
|
|
139
282
|
</Stack>
|