payment-kit 1.13.65 → 1.13.67
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/index.ts +4 -0
- package/api/src/integrations/blocklet/notification.ts +5 -3
- package/api/src/jobs/notification.ts +142 -0
- package/api/src/jobs/payment.ts +14 -0
- package/api/src/jobs/subscription.ts +2 -2
- package/api/src/libs/audit.ts +3 -1
- package/api/src/libs/env.ts +3 -0
- package/api/src/libs/event.ts +10 -1
- package/api/src/libs/invoice.ts +5 -0
- package/api/src/libs/notification/index.ts +23 -0
- package/api/src/libs/notification/template/base.ts +12 -0
- package/api/src/libs/notification/template/subscription-renew-failed.ts +286 -0
- package/api/src/libs/notification/template/subscription-renewed.ts +259 -0
- package/api/src/libs/notification/template/subscription-succeeded.ts +279 -0
- package/api/src/libs/notification/template/subscription-trial-start.ts +267 -0
- package/api/src/libs/notification/template/subscription-trial-will-end.ts +250 -0
- package/api/src/libs/notification/template/subscription-will-renew.ts +232 -0
- package/api/src/libs/payment.ts +100 -3
- package/api/src/libs/product.ts +19 -0
- package/api/src/libs/queue/index.ts +13 -0
- package/api/src/libs/subscription.ts +5 -0
- package/api/src/libs/time.ts +17 -0
- package/api/src/libs/util.ts +39 -0
- package/api/src/locales/en.ts +67 -0
- package/api/src/locales/zh.ts +64 -0
- package/api/src/routes/connect/collect.ts +6 -0
- package/api/src/schedule/index.ts +28 -0
- package/api/src/schedule/interface/diff.ts +9 -0
- package/api/src/schedule/subscription-trail-will-end.ts +197 -0
- package/api/src/schedule/subscription-will-renew.ts +195 -0
- package/api/src/store/models/subscription.ts +30 -12
- package/api/src/store/models/types.ts +13 -12
- package/api/third.d.ts +2 -0
- package/blocklet.yml +1 -1
- package/package.json +9 -7
- package/src/app.tsx +2 -0
- package/src/components/invoice/action.tsx +25 -7
- package/src/components/invoice/list.tsx +19 -4
- package/src/components/portal/invoice/list.tsx +1 -1
- package/src/components/portal/subscription/list.tsx +6 -5
- package/src/components/subscription/items/index.tsx +8 -4
- package/src/libs/util.ts +2 -2
- package/src/locales/en.tsx +5 -1
- package/src/locales/zh.tsx +5 -1
- package/src/pages/checkout/pricing-table.tsx +1 -1
- package/src/pages/customer/index.tsx +13 -2
- package/src/pages/customer/invoice.tsx +5 -4
- package/src/pages/customer/subscription/index.tsx +163 -0
- package/tsconfig.api.json +6 -1
|
@@ -39,6 +39,12 @@ type ListProps = {
|
|
|
39
39
|
customer_id?: string;
|
|
40
40
|
subscription_id?: string;
|
|
41
41
|
status?: string;
|
|
42
|
+
|
|
43
|
+
invoiceProps?: {
|
|
44
|
+
onClick?: (invoice: TInvoiceExpanded) => void | Promise<void>;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
mode?: 'admin' | 'customer';
|
|
42
48
|
};
|
|
43
49
|
|
|
44
50
|
const getListKey = (props: ListProps) => {
|
|
@@ -60,9 +66,13 @@ InvoiceList.defaultProps = {
|
|
|
60
66
|
customer_id: '',
|
|
61
67
|
subscription_id: '',
|
|
62
68
|
status: '',
|
|
69
|
+
|
|
70
|
+
invoiceProps: {},
|
|
71
|
+
|
|
72
|
+
mode: 'admin',
|
|
63
73
|
};
|
|
64
74
|
|
|
65
|
-
export default function InvoiceList({ customer_id, subscription_id, features, status }: ListProps) {
|
|
75
|
+
export default function InvoiceList({ customer_id, subscription_id, features, status, invoiceProps, mode }: ListProps) {
|
|
66
76
|
const listKey = getListKey({ customer_id, subscription_id });
|
|
67
77
|
const persisted = getDurableData(listKey);
|
|
68
78
|
|
|
@@ -159,7 +169,7 @@ export default function InvoiceList({ customer_id, subscription_id, features, st
|
|
|
159
169
|
sort: false,
|
|
160
170
|
customBodyRenderLite: (_: string, index: number) => {
|
|
161
171
|
const item = data.list[index] as TInvoiceExpanded;
|
|
162
|
-
return <InvoiceActions data={item} onChange={refresh} />;
|
|
172
|
+
return <InvoiceActions data={item} onChange={refresh} mode={mode} />;
|
|
163
173
|
},
|
|
164
174
|
},
|
|
165
175
|
},
|
|
@@ -200,9 +210,14 @@ export default function InvoiceList({ customer_id, subscription_id, features, st
|
|
|
200
210
|
count: data.count,
|
|
201
211
|
page: search.page - 1,
|
|
202
212
|
rowsPerPage: search.pageSize,
|
|
203
|
-
onRowClick: (_: any, { dataIndex }: any) => {
|
|
213
|
+
onRowClick: async (_: any, { dataIndex }: any) => {
|
|
204
214
|
const item = data.list[dataIndex] as TInvoiceExpanded;
|
|
205
|
-
|
|
215
|
+
|
|
216
|
+
if (invoiceProps?.onClick) {
|
|
217
|
+
await invoiceProps.onClick(item);
|
|
218
|
+
} else {
|
|
219
|
+
navigate(`/admin/billing/${item.id}`);
|
|
220
|
+
}
|
|
206
221
|
},
|
|
207
222
|
}}
|
|
208
223
|
toolbar={features?.toolbar}
|
|
@@ -85,7 +85,7 @@ export default function CustomerInvoiceList({ customer_id }: Props) {
|
|
|
85
85
|
<Typography component="span">{invoice.number}</Typography>
|
|
86
86
|
</Link>
|
|
87
87
|
</Box>
|
|
88
|
-
<Box flex={
|
|
88
|
+
<Box flex={2}>
|
|
89
89
|
<Typography>{formatToDate(invoice.created_at)}</Typography>
|
|
90
90
|
</Box>
|
|
91
91
|
<Box flex={1}>
|
|
@@ -3,7 +3,7 @@ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
|
3
3
|
import Toast from '@arcblock/ux/lib/Toast';
|
|
4
4
|
import type { Paginated, TSubscriptionExpanded } from '@did-pay/types';
|
|
5
5
|
import { ScheduleOutlined } from '@mui/icons-material';
|
|
6
|
-
import { Avatar, AvatarGroup, Box, Button, CircularProgress, Stack, Typography } from '@mui/material';
|
|
6
|
+
import { Avatar, AvatarGroup, Box, Button, CircularProgress, Stack, StackProps, Typography } from '@mui/material';
|
|
7
7
|
import { useInfiniteScroll, useSetState } from 'ahooks';
|
|
8
8
|
import { FormProvider, useForm, useFormContext } from 'react-hook-form';
|
|
9
9
|
|
|
@@ -29,12 +29,13 @@ const fetchData = (params: Record<string, any> = {}): Promise<Paginated<TSubscri
|
|
|
29
29
|
|
|
30
30
|
type Props = {
|
|
31
31
|
id: string;
|
|
32
|
-
onChange:
|
|
33
|
-
|
|
32
|
+
onChange: (action?: string) => any | Promise<any>;
|
|
33
|
+
onClickSubscription: (subscription: TSubscriptionExpanded) => void | Promise<void>;
|
|
34
|
+
} & Omit<StackProps, 'onChange'>;
|
|
34
35
|
|
|
35
36
|
const pageSize = 4;
|
|
36
37
|
|
|
37
|
-
export function CurrentSubscriptionsInner({ id, onChange }: Props) {
|
|
38
|
+
export function CurrentSubscriptionsInner({ id, onChange, onClickSubscription, ...rest }: Props) {
|
|
38
39
|
const { t } = useLocaleContext();
|
|
39
40
|
const { reset, getValues } = useFormContext();
|
|
40
41
|
|
|
@@ -108,7 +109,7 @@ export function CurrentSubscriptionsInner({ id, onChange }: Props) {
|
|
|
108
109
|
sm: 3,
|
|
109
110
|
}}
|
|
110
111
|
flexWrap="wrap">
|
|
111
|
-
<Stack direction="column" spacing={0.5}>
|
|
112
|
+
<Stack direction="column" spacing={0.5} onClick={() => onClickSubscription(subscription)} {...rest}>
|
|
112
113
|
<Stack direction="row" spacing={1} alignItems="center">
|
|
113
114
|
<AvatarGroup max={3}>
|
|
114
115
|
{subscription.items.map((item) =>
|
|
@@ -12,11 +12,14 @@ import UsageRecords from './usage-records';
|
|
|
12
12
|
type ListProps = {
|
|
13
13
|
data: TSubscriptionItemExpanded[];
|
|
14
14
|
currency: TPaymentCurrency;
|
|
15
|
+
mode?: 'admin' | 'customer';
|
|
15
16
|
};
|
|
16
17
|
|
|
17
|
-
SubscriptionItemList.defaultProps = {
|
|
18
|
+
SubscriptionItemList.defaultProps = {
|
|
19
|
+
mode: 'customer',
|
|
20
|
+
};
|
|
18
21
|
|
|
19
|
-
export default function SubscriptionItemList({ data, currency }: ListProps) {
|
|
22
|
+
export default function SubscriptionItemList({ data, currency, mode }: ListProps) {
|
|
20
23
|
const { t } = useLocaleContext();
|
|
21
24
|
|
|
22
25
|
const columns = [
|
|
@@ -73,7 +76,7 @@ export default function SubscriptionItemList({ data, currency }: ListProps) {
|
|
|
73
76
|
},
|
|
74
77
|
},
|
|
75
78
|
},
|
|
76
|
-
{
|
|
79
|
+
mode === 'admin' && {
|
|
77
80
|
label: '',
|
|
78
81
|
name: '',
|
|
79
82
|
align: 'center',
|
|
@@ -81,11 +84,12 @@ export default function SubscriptionItemList({ data, currency }: ListProps) {
|
|
|
81
84
|
sort: false,
|
|
82
85
|
customBodyRenderLite: (_: string, index: number) => {
|
|
83
86
|
const item = data[index] as TSubscriptionItemExpanded;
|
|
87
|
+
|
|
84
88
|
return <LineItemActions data={item as any} />;
|
|
85
89
|
},
|
|
86
90
|
},
|
|
87
91
|
},
|
|
88
|
-
];
|
|
92
|
+
].filter(Boolean);
|
|
89
93
|
|
|
90
94
|
return (
|
|
91
95
|
<Table
|
package/src/libs/util.ts
CHANGED
|
@@ -59,7 +59,7 @@ export function formatToDate(date: Date | string | number, locale = 'en') {
|
|
|
59
59
|
return '-';
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
return dayjs(date).locale(formatLocale(locale)).format('
|
|
62
|
+
return dayjs(date).locale(formatLocale(locale)).format('YYYY-MM-DD HH:mm:ss');
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
export function formatToDatetime(date: Date | string | number, locale = 'en') {
|
|
@@ -70,7 +70,7 @@ export function formatToDatetime(date: Date | string | number, locale = 'en') {
|
|
|
70
70
|
return dayjs(date).locale(formatLocale(locale)).format('lll');
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
export function formatTime(date: Date | string | number, format = '
|
|
73
|
+
export function formatTime(date: Date | string | number, format = 'YYYY-MM-DD HH:mm:ss', locale = 'en') {
|
|
74
74
|
if (!date) {
|
|
75
75
|
return '-';
|
|
76
76
|
}
|
package/src/locales/en.tsx
CHANGED
|
@@ -570,7 +570,6 @@ export default flat({
|
|
|
570
570
|
},
|
|
571
571
|
},
|
|
572
572
|
customer: {
|
|
573
|
-
subscriptions: 'Current Subscriptions',
|
|
574
573
|
invoices: 'Invoice History',
|
|
575
574
|
details: 'Billing Details',
|
|
576
575
|
update: 'Update Information',
|
|
@@ -603,5 +602,10 @@ export default flat({
|
|
|
603
602
|
download: 'Download PDF',
|
|
604
603
|
pay: 'Pay this invoice',
|
|
605
604
|
},
|
|
605
|
+
|
|
606
|
+
subscriptions: {
|
|
607
|
+
title: 'Manage subscriptions',
|
|
608
|
+
current: 'Current subscriptions',
|
|
609
|
+
},
|
|
606
610
|
},
|
|
607
611
|
});
|
package/src/locales/zh.tsx
CHANGED
|
@@ -557,7 +557,6 @@ export default flat({
|
|
|
557
557
|
},
|
|
558
558
|
},
|
|
559
559
|
customer: {
|
|
560
|
-
subscriptions: '当前订阅',
|
|
561
560
|
invoices: '发票历史',
|
|
562
561
|
details: '计费详情',
|
|
563
562
|
update: '更新客户信息',
|
|
@@ -589,5 +588,10 @@ export default flat({
|
|
|
589
588
|
download: '下载PDF',
|
|
590
589
|
pay: '支付此发票',
|
|
591
590
|
},
|
|
591
|
+
|
|
592
|
+
subscriptions: {
|
|
593
|
+
title: '订阅管理',
|
|
594
|
+
current: '当前订阅',
|
|
595
|
+
},
|
|
592
596
|
},
|
|
593
597
|
});
|
|
@@ -258,7 +258,7 @@ export default function PricingTable({ id }: Props) {
|
|
|
258
258
|
<Box>
|
|
259
259
|
<Typography>{t('checkout.include')}</Typography>
|
|
260
260
|
<List dense>
|
|
261
|
-
{x.product.features.map((f) => (
|
|
261
|
+
{x.product.features.map((f: any) => (
|
|
262
262
|
<ListItem key={f.name} disableGutters disablePadding>
|
|
263
263
|
<ListItemIcon sx={{ minWidth: 25 }}>
|
|
264
264
|
<CheckOutlined color="success" fontSize="small" />
|
|
@@ -6,6 +6,7 @@ import { Alert, Box, Button, CircularProgress, Grid, Stack } from '@mui/material
|
|
|
6
6
|
import { styled } from '@mui/system';
|
|
7
7
|
import { useRequest, useSetState } from 'ahooks';
|
|
8
8
|
import { FlagEmoji } from 'react-international-phone';
|
|
9
|
+
import { useNavigate } from 'react-router-dom';
|
|
9
10
|
|
|
10
11
|
import EditCustomer from '../../components/customer/edit';
|
|
11
12
|
import InfoRow from '../../components/info-row';
|
|
@@ -26,6 +27,7 @@ export default function CustomerHome() {
|
|
|
26
27
|
editing: false,
|
|
27
28
|
loading: false,
|
|
28
29
|
});
|
|
30
|
+
const navigate = useNavigate();
|
|
29
31
|
|
|
30
32
|
const { loading, error, data, runAsync } = useRequest(fetchData);
|
|
31
33
|
|
|
@@ -67,9 +69,18 @@ export default function CustomerHome() {
|
|
|
67
69
|
<Grid item xs={12} md={8}>
|
|
68
70
|
<Root direction="column" spacing={3} sx={{ my: 2 }}>
|
|
69
71
|
<Box className="section">
|
|
70
|
-
<SectionHeader title={t('customer.subscriptions')} mb={0} />
|
|
72
|
+
<SectionHeader title={t('customer.subscriptions.current')} mb={0} />
|
|
71
73
|
<Box className="section-body">
|
|
72
|
-
<CurrentSubscriptions
|
|
74
|
+
<CurrentSubscriptions
|
|
75
|
+
id={data.id}
|
|
76
|
+
onChange={runAsync}
|
|
77
|
+
style={{
|
|
78
|
+
cursor: 'pointer',
|
|
79
|
+
}}
|
|
80
|
+
onClickSubscription={(subscription) => {
|
|
81
|
+
navigate(`/customer/subscription/${subscription.id}`);
|
|
82
|
+
}}
|
|
83
|
+
/>
|
|
73
84
|
</Box>
|
|
74
85
|
</Box>
|
|
75
86
|
<Box className="section">
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
/* eslint-disable jsx-a11y/anchor-is-valid */
|
|
1
2
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
2
3
|
import Toast from '@arcblock/ux/lib/Toast';
|
|
3
4
|
import type { TInvoiceExpanded } from '@did-pay/types';
|
|
4
5
|
import { ArrowBackOutlined } from '@mui/icons-material';
|
|
5
|
-
import { Alert, Box, Button, CircularProgress, Grid, Stack, Typography } from '@mui/material';
|
|
6
|
+
import { Alert, Box, Button, CircularProgress, Grid, Link, Stack, Typography } from '@mui/material';
|
|
6
7
|
import { useRequest, useSetState } from 'ahooks';
|
|
7
|
-
import {
|
|
8
|
+
import { useParams } from 'react-router-dom';
|
|
8
9
|
|
|
9
10
|
import TxLink from '../../components/blockchain/tx';
|
|
10
11
|
import Currency from '../../components/currency';
|
|
@@ -72,11 +73,11 @@ export default function CustomerHome() {
|
|
|
72
73
|
<Layout>
|
|
73
74
|
<Grid container spacing={3} sx={{ mt: 1 }}>
|
|
74
75
|
<Grid item xs={12} md={12}>
|
|
75
|
-
<Link
|
|
76
|
+
<Link onClick={() => window.history.back()}>
|
|
76
77
|
<Stack direction="row" alignItems="center" sx={{ fontWeight: 'normal' }}>
|
|
77
78
|
<ArrowBackOutlined fontSize="small" sx={{ mr: 0.5, color: 'text.secondary' }} />
|
|
78
79
|
<Typography variant="h6" sx={{ color: 'text.secondary', fontWeight: 'normal' }}>
|
|
79
|
-
{t('
|
|
80
|
+
{t('common.previous')}
|
|
80
81
|
</Typography>
|
|
81
82
|
</Stack>
|
|
82
83
|
</Link>
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/* eslint-disable react/no-unstable-nested-components */
|
|
2
|
+
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
3
|
+
import type { TSubscriptionExpanded } from '@did-pay/types';
|
|
4
|
+
import { ArrowBackOutlined } from '@mui/icons-material';
|
|
5
|
+
import { Alert, Box, CircularProgress, Stack, Typography } from '@mui/material';
|
|
6
|
+
import { styled } from '@mui/system';
|
|
7
|
+
import { useRequest } from 'ahooks';
|
|
8
|
+
import { Link, useNavigate, useParams } from 'react-router-dom';
|
|
9
|
+
|
|
10
|
+
import TxLink from '../../../components/blockchain/tx';
|
|
11
|
+
import Currency from '../../../components/currency';
|
|
12
|
+
import InfoMetric from '../../../components/info-metric';
|
|
13
|
+
import InfoRow from '../../../components/info-row';
|
|
14
|
+
import InvoiceList from '../../../components/invoice/list';
|
|
15
|
+
import Layout from '../../../components/layout';
|
|
16
|
+
import SectionHeader from '../../../components/section/header';
|
|
17
|
+
import SubscriptionItemList from '../../../components/subscription/items';
|
|
18
|
+
import SubscriptionStatus from '../../../components/subscription/status';
|
|
19
|
+
import api from '../../../libs/api';
|
|
20
|
+
import { formatSubscriptionProduct, formatTime } from '../../../libs/util';
|
|
21
|
+
|
|
22
|
+
const fetchData = (id: string | undefined): Promise<TSubscriptionExpanded> => {
|
|
23
|
+
return api.get(`/api/subscriptions/${id}`).then((res) => res.data);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default function CustomerSubscription() {
|
|
27
|
+
const { id } = useParams() as { id: string };
|
|
28
|
+
const { t } = useLocaleContext();
|
|
29
|
+
const { loading, error, data } = useRequest(() => fetchData(id));
|
|
30
|
+
const navigate = useNavigate();
|
|
31
|
+
|
|
32
|
+
if (error) {
|
|
33
|
+
return <Alert severity="error">{error.message}</Alert>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (loading || !data) {
|
|
37
|
+
return <CircularProgress />;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Layout>
|
|
42
|
+
<Root direction="column" spacing={4} sx={{ mb: 4 }}>
|
|
43
|
+
<Box>
|
|
44
|
+
<Stack className="page-header" direction="row" justifyContent="space-between" alignItems="center">
|
|
45
|
+
<Link to="/customer">
|
|
46
|
+
<Stack direction="row" alignItems="center" sx={{ fontWeight: 'normal', mt: '16px' }}>
|
|
47
|
+
<ArrowBackOutlined fontSize="small" sx={{ mr: 0.5, color: 'text.secondary' }} />
|
|
48
|
+
<Typography variant="h6" sx={{ color: 'text.secondary', fontWeight: 'normal' }}>
|
|
49
|
+
{t('customer.subscriptions.title')}
|
|
50
|
+
</Typography>
|
|
51
|
+
</Stack>
|
|
52
|
+
</Link>
|
|
53
|
+
</Stack>
|
|
54
|
+
<Box mt={2}>
|
|
55
|
+
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
56
|
+
<Stack direction="row" alignItems="center">
|
|
57
|
+
<Typography variant="h5" sx={{ fontWeight: 600 }}>
|
|
58
|
+
{formatSubscriptionProduct(data.items)}
|
|
59
|
+
</Typography>
|
|
60
|
+
<SubscriptionStatus subscription={data} sx={{ ml: 1 }} />
|
|
61
|
+
</Stack>
|
|
62
|
+
</Stack>
|
|
63
|
+
<Stack
|
|
64
|
+
className="section-body"
|
|
65
|
+
direction="row"
|
|
66
|
+
spacing={3}
|
|
67
|
+
justifyContent="flex-start"
|
|
68
|
+
flexWrap="wrap"
|
|
69
|
+
sx={{ pt: 2, mt: 2, borderTop: '1px solid #eee' }}>
|
|
70
|
+
<InfoMetric
|
|
71
|
+
label={t('admin.subscription.startedAt')}
|
|
72
|
+
value={formatTime(data.start_date ? data.start_date * 1000 : data.created_at)}
|
|
73
|
+
divider
|
|
74
|
+
/>
|
|
75
|
+
{!data.cancel_at && (
|
|
76
|
+
<InfoMetric
|
|
77
|
+
label={t('admin.subscription.nextInvoice')}
|
|
78
|
+
value={formatTime(data.current_period_end * 1000)}
|
|
79
|
+
divider
|
|
80
|
+
/>
|
|
81
|
+
)}
|
|
82
|
+
{data.cancel_at && (
|
|
83
|
+
<InfoMetric
|
|
84
|
+
label={t('admin.subscription.cancel.schedule')}
|
|
85
|
+
value={formatTime(data.cancel_at * 1000)}
|
|
86
|
+
divider
|
|
87
|
+
/>
|
|
88
|
+
)}
|
|
89
|
+
</Stack>
|
|
90
|
+
</Box>
|
|
91
|
+
</Box>
|
|
92
|
+
|
|
93
|
+
<Box className="section">
|
|
94
|
+
<SectionHeader title={t('admin.details')} />
|
|
95
|
+
<Stack>
|
|
96
|
+
<InfoRow
|
|
97
|
+
label={t('common.customer')}
|
|
98
|
+
value={<Link to={`/admin/customers/${data.customer.id}`}>{data.customer.name}</Link>}
|
|
99
|
+
/>
|
|
100
|
+
<InfoRow label={t('common.createdAt')} value={formatTime(data.created_at)} />
|
|
101
|
+
{data.status === 'paused' && !!data.pause_collection?.resumes_at && (
|
|
102
|
+
<InfoRow label={t('common.resumesAt')} value={formatTime(data.pause_collection.resumes_at * 1000)} />
|
|
103
|
+
)}
|
|
104
|
+
<InfoRow
|
|
105
|
+
label={t('admin.subscription.currentPeriod')}
|
|
106
|
+
value={[formatTime(data.current_period_start * 1000), formatTime(data.current_period_end * 1000)].join(
|
|
107
|
+
' ~ '
|
|
108
|
+
)}
|
|
109
|
+
/>
|
|
110
|
+
<InfoRow
|
|
111
|
+
label={t('admin.subscription.trialingPeriod')}
|
|
112
|
+
value={
|
|
113
|
+
data.trail_end && data.trail_start
|
|
114
|
+
? [formatTime(data.trail_start * 1000), formatTime(data.trail_end * 1000)].join(' ~ ')
|
|
115
|
+
: ''
|
|
116
|
+
}
|
|
117
|
+
/>
|
|
118
|
+
<InfoRow label={t('admin.subscription.discount')} value={data.discount_id ? data.discount_id : ''} />
|
|
119
|
+
<InfoRow label={t('admin.subscription.collectionMethod')} value={data.collection_method} />
|
|
120
|
+
<InfoRow
|
|
121
|
+
label={t('admin.paymentMethod._name')}
|
|
122
|
+
value={<Currency logo={data.paymentMethod.logo} name={data.paymentMethod.name} />}
|
|
123
|
+
/>
|
|
124
|
+
<InfoRow
|
|
125
|
+
label={t('admin.paymentCurrency.name')}
|
|
126
|
+
value={<Currency logo={data.paymentCurrency.logo} name={data.paymentCurrency.symbol} />}
|
|
127
|
+
/>
|
|
128
|
+
{data.payment_details?.arcblock?.tx_hash && (
|
|
129
|
+
<InfoRow
|
|
130
|
+
label={t('common.txHash')}
|
|
131
|
+
value={<TxLink details={data.payment_details} method={data.paymentMethod} />}
|
|
132
|
+
/>
|
|
133
|
+
)}
|
|
134
|
+
</Stack>
|
|
135
|
+
</Box>
|
|
136
|
+
|
|
137
|
+
<Box className="section">
|
|
138
|
+
<SectionHeader title={t('admin.product.pricing')} mb={0} />
|
|
139
|
+
<Box className="section-body">
|
|
140
|
+
<SubscriptionItemList data={data.items} currency={data.paymentCurrency} mode="customer" />
|
|
141
|
+
</Box>
|
|
142
|
+
</Box>
|
|
143
|
+
<Box className="section">
|
|
144
|
+
<SectionHeader title={t('admin.invoices')} mb={0} />
|
|
145
|
+
<Box className="section-body">
|
|
146
|
+
<InvoiceList
|
|
147
|
+
features={{ customer: false, toolbar: false }}
|
|
148
|
+
subscription_id={data.id}
|
|
149
|
+
invoiceProps={{
|
|
150
|
+
onClick: (invoice) => {
|
|
151
|
+
navigate(`/customer/invoice/${invoice.id}`);
|
|
152
|
+
},
|
|
153
|
+
}}
|
|
154
|
+
mode="customer"
|
|
155
|
+
/>
|
|
156
|
+
</Box>
|
|
157
|
+
</Box>
|
|
158
|
+
</Root>
|
|
159
|
+
</Layout>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const Root = styled(Stack)``;
|
package/tsconfig.api.json
CHANGED