payment-kit 1.18.39 → 1.18.40
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/libs/subscription.ts +107 -97
- package/api/src/routes/checkout-sessions.ts +3 -1
- package/api/src/routes/subscriptions.ts +3 -1
- package/blocklet.yml +1 -1
- package/package.json +9 -9
- package/scripts/sdk.js +27 -1
- package/src/components/customer/link.tsx +6 -0
- package/src/components/info-card.tsx +2 -2
- package/src/components/info-metric.tsx +1 -1
- package/src/components/metadata/list.tsx +4 -2
- package/src/components/subscription/description.tsx +8 -6
- package/src/components/subscription/portal/actions.tsx +105 -36
- package/src/components/subscription/portal/list.tsx +152 -74
- package/src/components/subscription/status.tsx +17 -5
- package/src/locales/en.tsx +12 -7
- package/src/locales/zh.tsx +6 -2
- package/src/pages/admin/billing/invoices/detail.tsx +1 -5
- package/src/pages/admin/billing/subscriptions/detail.tsx +1 -5
- package/src/pages/admin/customers/customers/detail.tsx +1 -5
- package/src/pages/admin/developers/events/detail.tsx +1 -5
- package/src/pages/admin/developers/index.tsx +1 -1
- package/src/pages/admin/developers/webhooks/detail.tsx +1 -3
- package/src/pages/admin/overview.tsx +4 -4
- package/src/pages/admin/payments/intents/detail.tsx +1 -5
- package/src/pages/admin/payments/payouts/detail.tsx +1 -5
- package/src/pages/admin/payments/refunds/detail.tsx +1 -5
- package/src/pages/admin/products/links/detail.tsx +1 -5
- package/src/pages/admin/products/prices/detail.tsx +1 -5
- package/src/pages/admin/products/pricing-tables/detail.tsx +1 -5
- package/src/pages/admin/products/products/detail.tsx +1 -5
- package/src/pages/admin/settings/payment-methods/index.tsx +1 -1
- package/src/pages/customer/index.tsx +67 -138
- package/src/pages/customer/payout/detail.tsx +37 -49
- package/src/pages/customer/subscription/change-payment.tsx +2 -35
- package/src/pages/customer/subscription/detail.tsx +1 -5
- package/src/pages/integrations/donations/index.tsx +1 -1
- package/src/pages/integrations/overview.tsx +1 -1
|
@@ -22,6 +22,7 @@ import { useNavigate } from 'react-router-dom';
|
|
|
22
22
|
import { joinURL } from 'ufo';
|
|
23
23
|
import { BN } from '@ocap/util';
|
|
24
24
|
import DID from '@arcblock/ux/lib/DID';
|
|
25
|
+
import { AddOutlined } from '@mui/icons-material';
|
|
25
26
|
import CustomerCancelForm from './cancel';
|
|
26
27
|
import OverdraftProtectionDialog from '../../customer/overdraft-protection';
|
|
27
28
|
import Actions from '../../actions';
|
|
@@ -32,10 +33,11 @@ interface ActionConfig {
|
|
|
32
33
|
key: string;
|
|
33
34
|
show: boolean;
|
|
34
35
|
label: string | ReactNode | (() => ReactNode);
|
|
36
|
+
labelText?: string;
|
|
35
37
|
tooltip?: string;
|
|
36
38
|
onClick: (e?: React.MouseEvent) => void;
|
|
37
39
|
variant?: 'text' | 'outlined' | 'contained';
|
|
38
|
-
color?: 'inherit' | 'primary' | 'secondary' | 'error';
|
|
40
|
+
color?: 'inherit' | 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error';
|
|
39
41
|
sx?: any;
|
|
40
42
|
primary?: boolean;
|
|
41
43
|
component?: any;
|
|
@@ -46,8 +48,8 @@ interface ActionConfig {
|
|
|
46
48
|
|
|
47
49
|
type ActionProps = {
|
|
48
50
|
[key: string]: {
|
|
49
|
-
color?:
|
|
50
|
-
variant?:
|
|
51
|
+
color?: 'inherit' | 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error';
|
|
52
|
+
variant?: 'text' | 'outlined' | 'contained';
|
|
51
53
|
sx?: {
|
|
52
54
|
[key: string]: any;
|
|
53
55
|
};
|
|
@@ -81,6 +83,10 @@ type Props = {
|
|
|
81
83
|
actionProps?: ActionProps;
|
|
82
84
|
mode?: ActionDisplayMode;
|
|
83
85
|
setUp?: (methods: ActionMethods) => void;
|
|
86
|
+
includeActions?: string[] | null;
|
|
87
|
+
excludeActions?: string[] | null;
|
|
88
|
+
forceShowDetailAction?: boolean;
|
|
89
|
+
buttonSize?: 'small' | 'medium' | 'large';
|
|
84
90
|
};
|
|
85
91
|
|
|
86
92
|
SubscriptionActions.defaultProps = {
|
|
@@ -94,6 +100,10 @@ SubscriptionActions.defaultProps = {
|
|
|
94
100
|
mode: 'all-buttons',
|
|
95
101
|
setUp: null,
|
|
96
102
|
showUnsubscribe: true,
|
|
103
|
+
includeActions: null,
|
|
104
|
+
excludeActions: null,
|
|
105
|
+
forceShowDetailAction: false,
|
|
106
|
+
buttonSize: 'small',
|
|
97
107
|
};
|
|
98
108
|
const fetchExtraActions = async ({
|
|
99
109
|
id,
|
|
@@ -144,6 +154,10 @@ export function SubscriptionActionsInner({
|
|
|
144
154
|
mode,
|
|
145
155
|
setUp,
|
|
146
156
|
showBalanceInfo,
|
|
157
|
+
includeActions,
|
|
158
|
+
excludeActions,
|
|
159
|
+
forceShowDetailAction,
|
|
160
|
+
buttonSize,
|
|
147
161
|
}: Props) {
|
|
148
162
|
const { t, locale } = useLocaleContext();
|
|
149
163
|
const { reset, getValues } = useFormContext();
|
|
@@ -153,19 +167,29 @@ export function SubscriptionActionsInner({
|
|
|
153
167
|
const { checkUnpaidInvoices } = useUnpaidInvoicesCheckForSubscription(subscription.id, true);
|
|
154
168
|
const action = getSubscriptionAction(subs, actionProps ?? {});
|
|
155
169
|
|
|
170
|
+
const showAction = (actionName: string) => {
|
|
171
|
+
if (excludeActions && excludeActions.length > 0) {
|
|
172
|
+
return !excludeActions.includes(actionName);
|
|
173
|
+
}
|
|
174
|
+
if (includeActions && includeActions.length > 0) {
|
|
175
|
+
return includeActions.includes(actionName);
|
|
176
|
+
}
|
|
177
|
+
return true;
|
|
178
|
+
};
|
|
179
|
+
|
|
156
180
|
const { data: extraActions } = useRequest(() => fetchExtraActions({ id: subscription.id, showExtra: !!showExtra }));
|
|
157
181
|
|
|
158
182
|
const { data: upcoming = {} } = useRequest(
|
|
159
183
|
() => api.get(`/api/subscriptions/${subscription.id}/upcoming`).then((res) => res.data),
|
|
160
184
|
{
|
|
161
|
-
ready: !!(showRecharge && supportRecharge(subscription)) && showBalanceInfo,
|
|
185
|
+
ready: showAction('recharge') && !!(showRecharge && supportRecharge(subscription)) && showBalanceInfo,
|
|
162
186
|
}
|
|
163
187
|
);
|
|
164
188
|
|
|
165
189
|
const { data: payerValue = {} } = useRequest(
|
|
166
190
|
() => api.get(`/api/subscriptions/${subscription.id}/payer-token`).then((res) => res.data),
|
|
167
191
|
{
|
|
168
|
-
ready: !!(showRecharge && supportRecharge(subscription)) && showBalanceInfo,
|
|
192
|
+
ready: showAction('recharge') && !!(showRecharge && supportRecharge(subscription)) && showBalanceInfo,
|
|
169
193
|
}
|
|
170
194
|
);
|
|
171
195
|
|
|
@@ -187,12 +211,13 @@ export function SubscriptionActionsInner({
|
|
|
187
211
|
((typeof showOverdraftProtection === 'boolean' && showOverdraftProtection) ||
|
|
188
212
|
(typeof showOverdraftProtection === 'object' && showOverdraftProtection.show)) &&
|
|
189
213
|
subscription?.paymentMethod?.type === 'arcblock' &&
|
|
190
|
-
['active', 'trialing', 'past_due'].includes(subscription?.status)
|
|
214
|
+
['active', 'trialing', 'past_due'].includes(subscription?.status) &&
|
|
215
|
+
showAction('protection');
|
|
191
216
|
|
|
192
217
|
const { data: delegation = { sufficient: true }, refresh: refreshDelegation } = useRequest(
|
|
193
218
|
() => api.get(`/api/subscriptions/${subscription.id}/delegation`).then((res) => res.data),
|
|
194
219
|
{
|
|
195
|
-
ready: shouldFetchDelegation,
|
|
220
|
+
ready: showAction('delegation') && shouldFetchDelegation,
|
|
196
221
|
refreshDeps: [subscription.id, shouldFetchDelegation],
|
|
197
222
|
}
|
|
198
223
|
);
|
|
@@ -359,7 +384,17 @@ export function SubscriptionActionsInner({
|
|
|
359
384
|
const supportUnsubscribe = action?.action === 'cancel' && showUnsubscribe;
|
|
360
385
|
const supportAction = action && (action?.action !== 'cancel' || supportUnsubscribe);
|
|
361
386
|
const supportResume = isWillCanceled(subscription) && action?.action === 'recover';
|
|
362
|
-
const serviceActions = subscription.service_actions?.filter((x: any) => x?.type !== 'notification') || [
|
|
387
|
+
const serviceActions = subscription.service_actions?.filter((x: any) => x?.type !== 'notification') || [
|
|
388
|
+
{
|
|
389
|
+
name: 'notification',
|
|
390
|
+
text: {
|
|
391
|
+
en: 'Application Details',
|
|
392
|
+
zh: '应用详情',
|
|
393
|
+
},
|
|
394
|
+
link: '/customer/notification',
|
|
395
|
+
color: 'primary',
|
|
396
|
+
},
|
|
397
|
+
];
|
|
363
398
|
const actionConfigs: ActionConfig[] = [
|
|
364
399
|
{
|
|
365
400
|
key: 'delegation',
|
|
@@ -367,8 +402,8 @@ export function SubscriptionActionsInner({
|
|
|
367
402
|
label: t('customer.delegation.btn'),
|
|
368
403
|
tooltip: t('customer.delegation.title'),
|
|
369
404
|
onClick: handleDelegate,
|
|
370
|
-
variant: 'outlined',
|
|
371
|
-
color: 'primary',
|
|
405
|
+
variant: actionProps?.delegation?.variant || 'outlined',
|
|
406
|
+
color: actionProps?.delegation?.color || 'primary',
|
|
372
407
|
primary: true,
|
|
373
408
|
},
|
|
374
409
|
{
|
|
@@ -376,8 +411,8 @@ export function SubscriptionActionsInner({
|
|
|
376
411
|
show: shouldFetchOverdraftProtection,
|
|
377
412
|
label: t('customer.overdraftProtection.setting'),
|
|
378
413
|
onClick: () => setState({ openProtection: true, protectionInitValues: null }),
|
|
379
|
-
variant: 'outlined',
|
|
380
|
-
color: 'primary',
|
|
414
|
+
variant: actionProps?.protection?.variant || 'outlined',
|
|
415
|
+
color: actionProps?.protection?.color || 'primary',
|
|
381
416
|
},
|
|
382
417
|
{
|
|
383
418
|
key: 'recharge',
|
|
@@ -385,6 +420,7 @@ export function SubscriptionActionsInner({
|
|
|
385
420
|
label: () => {
|
|
386
421
|
const balanceDisplay = (
|
|
387
422
|
<Stack direction="row" spacing={0.5} alignItems="center">
|
|
423
|
+
<AddOutlined fontSize="small" />
|
|
388
424
|
{t('customer.recharge.title')}
|
|
389
425
|
</Stack>
|
|
390
426
|
);
|
|
@@ -417,23 +453,23 @@ export function SubscriptionActionsInner({
|
|
|
417
453
|
)}
|
|
418
454
|
<Stack spacing={0.5}>
|
|
419
455
|
<Box display="flex" justifyContent="space-between">
|
|
420
|
-
<Typography sx={{ color: 'text.secondary' }}>
|
|
456
|
+
<Typography sx={{ color: 'text.secondary' }} variant="body2">
|
|
421
457
|
{t('admin.subscription.currentBalance')}
|
|
422
458
|
</Typography>
|
|
423
|
-
<Typography>
|
|
459
|
+
<Typography variant="body2">
|
|
424
460
|
{formattedBalance} {subscription.paymentCurrency.symbol}
|
|
425
461
|
</Typography>
|
|
426
462
|
</Box>
|
|
427
463
|
<Box display="flex" justifyContent="space-between">
|
|
428
|
-
<Typography sx={{ color: 'text.secondary' }}>
|
|
464
|
+
<Typography sx={{ color: 'text.secondary' }} variant="body2">
|
|
429
465
|
{t('admin.subscription.nextInvoiceAmount')}
|
|
430
466
|
</Typography>
|
|
431
|
-
<Typography>
|
|
467
|
+
<Typography variant="body2">
|
|
432
468
|
{formattedUpcoming} {subscription.paymentCurrency.symbol}
|
|
433
469
|
</Typography>
|
|
434
470
|
</Box>
|
|
435
471
|
<Box display="flex" justifyContent="space-between">
|
|
436
|
-
<Typography sx={{ color: 'text.secondary' }}>
|
|
472
|
+
<Typography sx={{ color: 'text.secondary' }} variant="body2">
|
|
437
473
|
{t('admin.subscription.paymentAddress')}
|
|
438
474
|
</Typography>
|
|
439
475
|
<DID did={payerValue?.paymentAddress} responsive={false} compact showAvatar={false} />
|
|
@@ -449,12 +485,13 @@ export function SubscriptionActionsInner({
|
|
|
449
485
|
|
|
450
486
|
return balanceDisplay;
|
|
451
487
|
},
|
|
488
|
+
labelText: t('customer.recharge.title'),
|
|
452
489
|
onClick: (e) => {
|
|
453
490
|
e?.stopPropagation();
|
|
454
491
|
navigate(`/customer/subscription/${subscription.id}/recharge`);
|
|
455
492
|
},
|
|
456
|
-
variant: 'outlined',
|
|
457
|
-
color: 'primary',
|
|
493
|
+
variant: actionProps?.recharge?.variant || 'outlined',
|
|
494
|
+
color: actionProps?.recharge?.color || 'primary',
|
|
458
495
|
primary: !isWillCanceled(subscription),
|
|
459
496
|
sx:
|
|
460
497
|
isInsufficientBalance || payerValue.token === '0'
|
|
@@ -464,14 +501,15 @@ export function SubscriptionActionsInner({
|
|
|
464
501
|
backgroundColor: 'error.main',
|
|
465
502
|
borderRadius: '50%',
|
|
466
503
|
position: 'absolute',
|
|
467
|
-
top: '
|
|
468
|
-
right: '-
|
|
469
|
-
width: '
|
|
470
|
-
height: '
|
|
504
|
+
top: '3px',
|
|
505
|
+
right: '-3px',
|
|
506
|
+
width: '6px',
|
|
507
|
+
height: '6px',
|
|
471
508
|
zIndex: 1,
|
|
472
509
|
},
|
|
510
|
+
...(actionProps?.recharge?.sx || {}),
|
|
473
511
|
}
|
|
474
|
-
: {},
|
|
512
|
+
: actionProps?.recharge?.sx || {},
|
|
475
513
|
},
|
|
476
514
|
{
|
|
477
515
|
key: 'changePlan',
|
|
@@ -481,9 +519,9 @@ export function SubscriptionActionsInner({
|
|
|
481
519
|
e?.stopPropagation();
|
|
482
520
|
navigate(`/customer/subscription/${subscription.id}/change-plan`);
|
|
483
521
|
},
|
|
484
|
-
variant: 'contained',
|
|
485
|
-
color: 'primary',
|
|
486
|
-
sx:
|
|
522
|
+
variant: actionProps?.changePlan?.variant || 'contained',
|
|
523
|
+
color: actionProps?.changePlan?.color || 'primary',
|
|
524
|
+
sx: actionProps?.changePlan?.sx,
|
|
487
525
|
},
|
|
488
526
|
{
|
|
489
527
|
key: 'batchPay',
|
|
@@ -495,9 +533,9 @@ export function SubscriptionActionsInner({
|
|
|
495
533
|
batchPay: true,
|
|
496
534
|
});
|
|
497
535
|
},
|
|
498
|
-
variant: 'outlined',
|
|
499
|
-
color: 'error',
|
|
500
|
-
sx:
|
|
536
|
+
variant: actionProps?.batchPay?.variant || 'outlined',
|
|
537
|
+
color: actionProps?.batchPay?.color || 'error',
|
|
538
|
+
sx: actionProps?.batchPay?.sx,
|
|
501
539
|
primary: true,
|
|
502
540
|
},
|
|
503
541
|
{
|
|
@@ -537,15 +575,26 @@ export function SubscriptionActionsInner({
|
|
|
537
575
|
];
|
|
538
576
|
|
|
539
577
|
// 过滤出要显示的操作
|
|
540
|
-
const visibleActions = actionConfigs.filter((a) => a.show);
|
|
578
|
+
const visibleActions = actionConfigs.filter((a) => a.show && showAction(a.key));
|
|
541
579
|
|
|
542
580
|
// 转换为菜单项
|
|
543
581
|
const toMenuItem = (item: any) => ({
|
|
544
|
-
label: item.label,
|
|
582
|
+
label: item.labelText || (typeof item.label === 'function' ? item.label() : item.label),
|
|
545
583
|
handler: item.onClick,
|
|
546
584
|
color: item.color,
|
|
547
585
|
divider: item.divider,
|
|
548
586
|
});
|
|
587
|
+
const detailAction = forceShowDetailAction && (
|
|
588
|
+
<Button
|
|
589
|
+
className="action-button"
|
|
590
|
+
key="detail"
|
|
591
|
+
sx={actionProps?.detail?.sx || {}}
|
|
592
|
+
variant={actionProps?.detail?.variant || 'outlined'}
|
|
593
|
+
color={actionProps?.detail?.color || 'primary'}
|
|
594
|
+
onClick={() => navigate(`/customer/subscription/${subscription.id}`)}>
|
|
595
|
+
{t('customer.subscription.manage')}
|
|
596
|
+
</Button>
|
|
597
|
+
);
|
|
549
598
|
|
|
550
599
|
const toButton = (item: ActionConfig) => {
|
|
551
600
|
const labelContent = typeof item.label === 'function' ? item.label() : item.label;
|
|
@@ -560,7 +609,8 @@ export function SubscriptionActionsInner({
|
|
|
560
609
|
href={item.href}
|
|
561
610
|
target={item.target}
|
|
562
611
|
sx={item.sx}
|
|
563
|
-
|
|
612
|
+
className="action-button"
|
|
613
|
+
size={buttonSize}>
|
|
564
614
|
{item.tooltip ? (
|
|
565
615
|
<Tooltip title={item.tooltip}>
|
|
566
616
|
<span>{labelContent}</span>
|
|
@@ -572,7 +622,14 @@ export function SubscriptionActionsInner({
|
|
|
572
622
|
);
|
|
573
623
|
};
|
|
574
624
|
if (mode === 'menu-only') {
|
|
575
|
-
return
|
|
625
|
+
return (
|
|
626
|
+
<>
|
|
627
|
+
{detailAction}
|
|
628
|
+
{visibleActions.length > 0 && (
|
|
629
|
+
<Actions actions={visibleActions.map(toMenuItem)} variant="outlined" sx={actionProps?.menu?.sx || {}} />
|
|
630
|
+
)}
|
|
631
|
+
</>
|
|
632
|
+
);
|
|
576
633
|
}
|
|
577
634
|
|
|
578
635
|
if (mode === 'primary-buttons') {
|
|
@@ -580,13 +637,21 @@ export function SubscriptionActionsInner({
|
|
|
580
637
|
const menuItems = visibleActions.filter((a) => !a.primary);
|
|
581
638
|
return (
|
|
582
639
|
<>
|
|
640
|
+
{detailAction}
|
|
583
641
|
{primaryButtons.map(toButton)}
|
|
584
|
-
{menuItems.length > 0 &&
|
|
642
|
+
{menuItems.length > 0 && (
|
|
643
|
+
<Actions actions={menuItems.map(toMenuItem)} variant="outlined" sx={actionProps?.menu?.sx || {}} />
|
|
644
|
+
)}
|
|
585
645
|
</>
|
|
586
646
|
);
|
|
587
647
|
}
|
|
588
648
|
|
|
589
|
-
return
|
|
649
|
+
return (
|
|
650
|
+
<>
|
|
651
|
+
{detailAction}
|
|
652
|
+
{visibleActions.map(toButton)}
|
|
653
|
+
</>
|
|
654
|
+
);
|
|
590
655
|
};
|
|
591
656
|
|
|
592
657
|
return (
|
|
@@ -682,4 +747,8 @@ SubscriptionActionsInner.defaultProps = {
|
|
|
682
747
|
actionProps: {},
|
|
683
748
|
mode: 'all-buttons',
|
|
684
749
|
setUp: null,
|
|
750
|
+
includeActions: null,
|
|
751
|
+
excludeActions: null,
|
|
752
|
+
forceShowDetailAction: false,
|
|
753
|
+
buttonSize: 'small',
|
|
685
754
|
};
|
|
@@ -3,7 +3,17 @@ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
|
3
3
|
import Empty from '@arcblock/ux/lib/Empty';
|
|
4
4
|
import { api, formatPrice, getSubscriptionTimeSummary, useMobile } from '@blocklet/payment-react';
|
|
5
5
|
import type { TSubscriptionExpanded } from '@blocklet/payment-types';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
Avatar,
|
|
8
|
+
AvatarGroup,
|
|
9
|
+
Box,
|
|
10
|
+
Button,
|
|
11
|
+
CircularProgress,
|
|
12
|
+
Divider,
|
|
13
|
+
Stack,
|
|
14
|
+
StackProps,
|
|
15
|
+
Typography,
|
|
16
|
+
} from '@mui/material';
|
|
7
17
|
import { useInfiniteScroll } from 'ahooks';
|
|
8
18
|
|
|
9
19
|
import { useRef } from 'react';
|
|
@@ -39,8 +49,6 @@ type Props = {
|
|
|
39
49
|
setHasSubscriptions?: (state: boolean) => void;
|
|
40
50
|
} & Omit<StackProps, 'onChange'>;
|
|
41
51
|
|
|
42
|
-
const pageSize = 5;
|
|
43
|
-
|
|
44
52
|
export default function CurrentSubscriptions({
|
|
45
53
|
id,
|
|
46
54
|
status,
|
|
@@ -52,9 +60,10 @@ export default function CurrentSubscriptions({
|
|
|
52
60
|
setHasSubscriptions = () => {},
|
|
53
61
|
...rest
|
|
54
62
|
}: Props) {
|
|
55
|
-
const { t } = useLocaleContext();
|
|
63
|
+
const { t, locale } = useLocaleContext();
|
|
56
64
|
const { isMobile } = useMobile();
|
|
57
65
|
const listRef = useRef<HTMLDivElement | null>(null);
|
|
66
|
+
const pageSize = isMobile ? 5 : 10;
|
|
58
67
|
|
|
59
68
|
const { data, loadMore, loadingMore, loading, reload } = useInfiniteScroll<SubscriptionListResponse>(
|
|
60
69
|
(d) => {
|
|
@@ -91,54 +100,76 @@ export default function CurrentSubscriptions({
|
|
|
91
100
|
const hasAnySubscriptions = data.totalCount > 0;
|
|
92
101
|
|
|
93
102
|
const hasMore = data && data.list?.length < data.count;
|
|
94
|
-
const size = { width:
|
|
95
|
-
|
|
103
|
+
const size = isMobile ? { width: 42, height: 42 } : { width: 44, height: 44 };
|
|
96
104
|
return (
|
|
97
|
-
<Stack direction="column" spacing={2} sx={{ mt: 2 }}>
|
|
105
|
+
<Stack direction="column" spacing={2} sx={{ mt: 2, containerType: 'inline-size' }}>
|
|
98
106
|
{data.list?.length > 0 ? (
|
|
99
107
|
<>
|
|
100
108
|
<Stack
|
|
101
109
|
ref={listRef}
|
|
102
|
-
spacing={2}
|
|
103
110
|
sx={{
|
|
104
111
|
maxHeight: {
|
|
105
112
|
xs: '100%',
|
|
106
|
-
md: '
|
|
113
|
+
md: '700px',
|
|
107
114
|
},
|
|
108
115
|
overflowY: 'auto',
|
|
109
116
|
webkitOverflowScrolling: 'touch',
|
|
117
|
+
display: 'grid',
|
|
118
|
+
gridTemplateColumns: {
|
|
119
|
+
xs: 'repeat(1, 1fr)',
|
|
120
|
+
md: 'repeat(2, 1fr)',
|
|
121
|
+
},
|
|
122
|
+
'@container (max-width: 600px)': {
|
|
123
|
+
gridTemplateColumns: 'repeat(1, 1fr)',
|
|
124
|
+
},
|
|
125
|
+
gap: 2,
|
|
110
126
|
}}>
|
|
111
127
|
{data.list.map((subscription) => {
|
|
128
|
+
const summary = getSubscriptionTimeSummary(subscription, locale);
|
|
129
|
+
const subscriptionTime = summary
|
|
130
|
+
? t(`admin.subscription.${summary?.action}`, {
|
|
131
|
+
date: summary?.time,
|
|
132
|
+
prefix: summary?.isToday ? 'at' : 'on',
|
|
133
|
+
})
|
|
134
|
+
: '';
|
|
112
135
|
return (
|
|
113
136
|
<Stack
|
|
114
137
|
key={subscription.id}
|
|
115
|
-
direction="row"
|
|
116
|
-
justifyContent="space-between"
|
|
117
|
-
gap={{
|
|
118
|
-
xs: 1,
|
|
119
|
-
sm: 2,
|
|
120
|
-
}}
|
|
121
138
|
sx={{
|
|
122
|
-
padding:
|
|
123
|
-
|
|
139
|
+
padding: 2,
|
|
140
|
+
height: '100%',
|
|
141
|
+
borderRadius: 1,
|
|
142
|
+
border: '1px solid',
|
|
143
|
+
borderColor: 'divider',
|
|
144
|
+
boxShadow: 1,
|
|
145
|
+
display: 'flex',
|
|
146
|
+
flexDirection: 'column',
|
|
147
|
+
justifyContent: 'space-between',
|
|
148
|
+
gap: 2,
|
|
124
149
|
'&:hover': {
|
|
125
|
-
backgroundColor: 'grey.
|
|
150
|
+
backgroundColor: 'grey.50',
|
|
126
151
|
transition: 'background-color 200ms linear',
|
|
127
152
|
cursor: 'pointer',
|
|
128
153
|
},
|
|
129
154
|
}}
|
|
130
155
|
flexWrap="wrap">
|
|
131
|
-
<Stack direction="column" flex={1} spacing={
|
|
156
|
+
<Stack direction="column" flex={1} spacing={2} {...rest}>
|
|
132
157
|
<Stack
|
|
133
|
-
direction=
|
|
158
|
+
direction="row"
|
|
134
159
|
spacing={1}
|
|
135
|
-
alignItems=
|
|
136
|
-
flexWrap="wrap"
|
|
160
|
+
alignItems="flex-start"
|
|
137
161
|
justifyContent="space-between"
|
|
138
162
|
onClick={() => onClickSubscription(subscription)}>
|
|
139
|
-
<Stack direction="row" spacing={1.5}>
|
|
140
|
-
<AvatarGroup
|
|
141
|
-
{
|
|
163
|
+
<Stack direction="row" spacing={1.5} alignItems="center">
|
|
164
|
+
<AvatarGroup
|
|
165
|
+
max={2}
|
|
166
|
+
sx={{
|
|
167
|
+
'& .MuiAvatar-colorDefault': {
|
|
168
|
+
...size,
|
|
169
|
+
boxSizing: 'border-box',
|
|
170
|
+
},
|
|
171
|
+
}}>
|
|
172
|
+
{subscription.items.slice(0, 2).map((item) =>
|
|
142
173
|
item.price.product.images.length > 0 ? (
|
|
143
174
|
// @ts-ignore
|
|
144
175
|
<Avatar
|
|
@@ -155,15 +186,13 @@ export default function CurrentSubscriptions({
|
|
|
155
186
|
)
|
|
156
187
|
)}
|
|
157
188
|
</AvatarGroup>
|
|
158
|
-
<Stack
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}}>
|
|
166
|
-
<SubscriptionDescription subscription={subscription} hideSubscription variant="body1" />
|
|
189
|
+
<Stack direction="column" spacing={0.25}>
|
|
190
|
+
<SubscriptionDescription
|
|
191
|
+
subscription={subscription}
|
|
192
|
+
hideSubscription
|
|
193
|
+
maxLength={isMobile ? 30 : 40}
|
|
194
|
+
variant={isMobile ? 'subtitle2' : 'subtitle1'}
|
|
195
|
+
/>
|
|
167
196
|
<SubscriptionStatus
|
|
168
197
|
subscription={subscription}
|
|
169
198
|
sx={{ height: 18, width: 'fit-content' }}
|
|
@@ -171,40 +200,40 @@ export default function CurrentSubscriptions({
|
|
|
171
200
|
/>
|
|
172
201
|
</Stack>
|
|
173
202
|
</Stack>
|
|
174
|
-
<Stack>
|
|
175
|
-
<Typography variant="subtitle1" fontWeight={500} fontSize={16}>
|
|
176
|
-
{
|
|
177
|
-
// @ts-ignore
|
|
178
|
-
formatPrice(subscription.items[0].price, subscription.paymentCurrency)
|
|
179
|
-
}
|
|
180
|
-
</Typography>
|
|
181
|
-
</Stack>
|
|
182
203
|
</Stack>
|
|
204
|
+
|
|
205
|
+
<Divider />
|
|
183
206
|
<Stack
|
|
184
207
|
gap={1}
|
|
185
208
|
justifyContent="space-between"
|
|
186
|
-
flexWrap="
|
|
209
|
+
flexWrap="nowrap"
|
|
187
210
|
sx={{
|
|
188
|
-
flexDirection:
|
|
189
|
-
|
|
190
|
-
lg: 'row',
|
|
191
|
-
},
|
|
192
|
-
alignItems: {
|
|
193
|
-
xs: 'flex-start',
|
|
194
|
-
lg: 'center',
|
|
195
|
-
},
|
|
211
|
+
flexDirection: 'row',
|
|
212
|
+
alignItems: 'center',
|
|
196
213
|
}}>
|
|
197
214
|
<Box
|
|
198
215
|
component="div"
|
|
199
216
|
onClick={() => onClickSubscription(subscription)}
|
|
200
|
-
sx={{
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
217
|
+
sx={{
|
|
218
|
+
display: 'flex',
|
|
219
|
+
gap: {
|
|
220
|
+
xs: 0.5,
|
|
221
|
+
md: 1,
|
|
222
|
+
},
|
|
223
|
+
flexDirection: 'row',
|
|
224
|
+
flexWrap: 'wrap',
|
|
225
|
+
}}>
|
|
226
|
+
<Typography variant={isMobile ? 'subtitle2' : 'subtitle1'} sx={{ whiteSpace: 'nowrap' }}>
|
|
227
|
+
{
|
|
228
|
+
// @ts-ignore
|
|
229
|
+
formatPrice(subscription.items[0].price, subscription.paymentCurrency)
|
|
230
|
+
}
|
|
231
|
+
</Typography>
|
|
232
|
+
{subscriptionTime && (
|
|
233
|
+
<Typography variant="body2" color="text.secondary">
|
|
234
|
+
({subscriptionTime})
|
|
235
|
+
</Typography>
|
|
236
|
+
)}
|
|
208
237
|
</Box>
|
|
209
238
|
<SubscriptionActions
|
|
210
239
|
subscription={subscription}
|
|
@@ -217,32 +246,81 @@ export default function CurrentSubscriptions({
|
|
|
217
246
|
showUnsubscribe={false}
|
|
218
247
|
showRecharge={!isWillCanceled(subscription)}
|
|
219
248
|
showBalanceInfo
|
|
249
|
+
includeActions={['recharge']}
|
|
220
250
|
actionProps={{
|
|
221
|
-
|
|
222
|
-
variant: '
|
|
223
|
-
color: 'primary',
|
|
224
|
-
},
|
|
225
|
-
recover: {
|
|
226
|
-
variant: 'outlined',
|
|
227
|
-
color: 'info',
|
|
228
|
-
},
|
|
229
|
-
pastDue: {
|
|
230
|
-
variant: 'outlined',
|
|
251
|
+
recharge: {
|
|
252
|
+
variant: 'text',
|
|
231
253
|
color: 'primary',
|
|
254
|
+
sx: {
|
|
255
|
+
whiteSpace: 'nowrap',
|
|
256
|
+
},
|
|
232
257
|
},
|
|
233
258
|
}}
|
|
234
259
|
/>
|
|
235
260
|
</Stack>
|
|
236
261
|
</Stack>
|
|
262
|
+
<Stack
|
|
263
|
+
sx={{
|
|
264
|
+
display: 'flex',
|
|
265
|
+
justifyContent: 'flex-end',
|
|
266
|
+
'.action-button': {
|
|
267
|
+
flex: 1,
|
|
268
|
+
},
|
|
269
|
+
}}>
|
|
270
|
+
<SubscriptionActions
|
|
271
|
+
subscription={subscription}
|
|
272
|
+
onChange={(v) => {
|
|
273
|
+
reload();
|
|
274
|
+
if (onChange) {
|
|
275
|
+
onChange(v);
|
|
276
|
+
}
|
|
277
|
+
}}
|
|
278
|
+
forceShowDetailAction
|
|
279
|
+
showUnsubscribe={false}
|
|
280
|
+
excludeActions={['recharge']}
|
|
281
|
+
actionProps={{
|
|
282
|
+
cancel: {
|
|
283
|
+
variant: 'outlined',
|
|
284
|
+
color: 'primary',
|
|
285
|
+
},
|
|
286
|
+
recover: {
|
|
287
|
+
variant: 'outlined',
|
|
288
|
+
color: 'info',
|
|
289
|
+
},
|
|
290
|
+
pastDue: {
|
|
291
|
+
variant: 'outlined',
|
|
292
|
+
color: 'primary',
|
|
293
|
+
},
|
|
294
|
+
detail: {
|
|
295
|
+
variant: 'contained',
|
|
296
|
+
sx: {
|
|
297
|
+
color: 'text.primary',
|
|
298
|
+
|
|
299
|
+
backgroundColor: 'grey.100',
|
|
300
|
+
'&:hover': {
|
|
301
|
+
backgroundColor: 'grey.200',
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
menu: {
|
|
306
|
+
sx: {
|
|
307
|
+
color: 'text.primary',
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
}}
|
|
311
|
+
mode="menu-only"
|
|
312
|
+
buttonSize="medium"
|
|
313
|
+
/>
|
|
314
|
+
</Stack>
|
|
237
315
|
</Stack>
|
|
238
316
|
);
|
|
239
317
|
})}
|
|
240
|
-
{hasMore && !isMobile && showLoadingMore && (
|
|
241
|
-
<Box alignItems="center" gap={0.5} display="flex" mt={0.5}>
|
|
242
|
-
{t('common.loadingMore', { resource: t('admin.subscriptions') })}
|
|
243
|
-
</Box>
|
|
244
|
-
)}
|
|
245
318
|
</Stack>
|
|
319
|
+
{hasMore && !isMobile && showLoadingMore && (
|
|
320
|
+
<Box alignItems="center" gap={0.5} display="flex" mt={0.5}>
|
|
321
|
+
{t('common.loadingMore', { resource: t('admin.subscriptions') })}
|
|
322
|
+
</Box>
|
|
323
|
+
)}
|
|
246
324
|
{isMobile && (
|
|
247
325
|
<Box>
|
|
248
326
|
{hasMore && (
|