payment-kit 1.18.56 → 1.19.1
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/.eslintrc.js +6 -0
- package/api/src/crons/index.ts +8 -0
- package/api/src/index.ts +4 -0
- package/api/src/libs/credit-grant.ts +146 -0
- package/api/src/libs/env.ts +1 -0
- package/api/src/libs/invoice.ts +4 -3
- package/api/src/libs/notification/template/base.ts +388 -2
- package/api/src/libs/notification/template/customer-credit-grant-granted.ts +149 -0
- package/api/src/libs/notification/template/customer-credit-grant-low-balance.ts +151 -0
- package/api/src/libs/notification/template/customer-credit-insufficient.ts +254 -0
- package/api/src/libs/notification/template/subscription-canceled.ts +193 -202
- package/api/src/libs/notification/template/subscription-refund-succeeded.ts +215 -237
- package/api/src/libs/notification/template/subscription-renewed.ts +130 -200
- package/api/src/libs/notification/template/subscription-succeeded.ts +100 -202
- package/api/src/libs/notification/template/subscription-trial-start.ts +142 -188
- package/api/src/libs/notification/template/subscription-trial-will-end.ts +146 -174
- package/api/src/libs/notification/template/subscription-upgraded.ts +96 -192
- package/api/src/libs/notification/template/subscription-will-canceled.ts +94 -135
- package/api/src/libs/notification/template/subscription-will-renew.ts +220 -245
- package/api/src/libs/payment.ts +69 -0
- package/api/src/libs/queue/index.ts +3 -2
- package/api/src/libs/session.ts +8 -0
- package/api/src/libs/subscription.ts +74 -3
- package/api/src/libs/ws.ts +23 -1
- package/api/src/locales/en.ts +33 -0
- package/api/src/locales/zh.ts +31 -0
- package/api/src/queues/credit-consume.ts +715 -0
- package/api/src/queues/credit-grant.ts +572 -0
- package/api/src/queues/notification.ts +173 -128
- package/api/src/queues/payment.ts +210 -122
- package/api/src/queues/subscription.ts +179 -0
- package/api/src/routes/checkout-sessions.ts +157 -9
- package/api/src/routes/connect/shared.ts +3 -2
- package/api/src/routes/credit-grants.ts +241 -0
- package/api/src/routes/credit-transactions.ts +208 -0
- package/api/src/routes/index.ts +8 -0
- package/api/src/routes/meter-events.ts +347 -0
- package/api/src/routes/meters.ts +219 -0
- package/api/src/routes/payment-currencies.ts +14 -2
- package/api/src/routes/payment-links.ts +1 -1
- package/api/src/routes/payment-methods.ts +14 -2
- package/api/src/routes/prices.ts +43 -0
- package/api/src/routes/pricing-table.ts +13 -7
- package/api/src/routes/products.ts +63 -4
- package/api/src/routes/settings.ts +1 -1
- package/api/src/routes/subscriptions.ts +4 -0
- package/api/src/store/migrations/20250610-billing-credit.ts +43 -0
- package/api/src/store/models/credit-grant.ts +486 -0
- package/api/src/store/models/credit-transaction.ts +268 -0
- package/api/src/store/models/customer.ts +8 -0
- package/api/src/store/models/index.ts +52 -1
- package/api/src/store/models/meter-event.ts +423 -0
- package/api/src/store/models/meter.ts +176 -0
- package/api/src/store/models/payment-currency.ts +66 -14
- package/api/src/store/models/price.ts +6 -0
- package/api/src/store/models/product.ts +2 -2
- package/api/src/store/models/subscription.ts +24 -0
- package/api/src/store/models/types.ts +28 -2
- package/api/tests/libs/subscription.spec.ts +53 -0
- package/blocklet.yml +9 -1
- package/package.json +57 -58
- package/scripts/sdk.js +233 -1
- package/src/app.tsx +10 -0
- package/src/components/actions.tsx +22 -9
- package/src/components/balance-list.tsx +40 -12
- package/src/components/collapse.tsx +33 -15
- package/src/components/copyable.tsx +8 -7
- package/src/components/currency.tsx +15 -7
- package/src/components/customer/actions.tsx +1 -5
- package/src/components/customer/credit-grant-item-list.tsx +99 -0
- package/src/components/customer/credit-overview.tsx +233 -0
- package/src/components/customer/form.tsx +7 -2
- package/src/components/customer/link.tsx +4 -12
- package/src/components/customer/notification-preference.tsx +18 -9
- package/src/components/customer/overdraft-protection.tsx +112 -41
- package/src/components/drawer-form.tsx +42 -18
- package/src/components/error.tsx +1 -5
- package/src/components/event/list.tsx +9 -10
- package/src/components/filter-toolbar.tsx +20 -19
- package/src/components/info-card.tsx +32 -18
- package/src/components/info-metric.tsx +16 -6
- package/src/components/info-row-group.tsx +1 -7
- package/src/components/info-row.tsx +30 -24
- package/src/components/invoice/action.tsx +1 -7
- package/src/components/invoice/list.tsx +34 -26
- package/src/components/invoice/recharge.tsx +5 -7
- package/src/components/invoice/table.tsx +17 -12
- package/src/components/layout/user.tsx +1 -1
- package/src/components/metadata/form.tsx +290 -94
- package/src/components/metadata/list.tsx +11 -3
- package/src/components/meter/actions.tsx +101 -0
- package/src/components/meter/add-usage-dialog.tsx +239 -0
- package/src/components/meter/events-list.tsx +657 -0
- package/src/components/meter/form.tsx +245 -0
- package/src/components/meter/products.tsx +264 -0
- package/src/components/meter/usage-guide.tsx +174 -0
- package/src/components/passport/actions.tsx +9 -4
- package/src/components/payment-currency/add.tsx +16 -3
- package/src/components/payment-currency/form.tsx +14 -6
- package/src/components/payment-intent/actions.tsx +24 -16
- package/src/components/payment-intent/list.tsx +30 -9
- package/src/components/payment-link/actions.tsx +1 -5
- package/src/components/payment-link/after-pay.tsx +4 -2
- package/src/components/payment-link/before-pay.tsx +14 -4
- package/src/components/payment-link/item.tsx +27 -6
- package/src/components/payment-link/preview.tsx +9 -9
- package/src/components/payment-link/product-select.tsx +69 -15
- package/src/components/payment-method/arcblock.tsx +8 -1
- package/src/components/payment-method/base.tsx +8 -1
- package/src/components/payment-method/bitcoin.tsx +8 -1
- package/src/components/payment-method/ethereum.tsx +8 -1
- package/src/components/payment-method/evm-rpc-input.tsx +11 -7
- package/src/components/payment-method/form.tsx +2 -7
- package/src/components/payment-method/stripe.tsx +2 -0
- package/src/components/payouts/actions.tsx +1 -5
- package/src/components/payouts/list.tsx +30 -10
- package/src/components/payouts/portal/list.tsx +11 -9
- package/src/components/price/currency-select.tsx +63 -32
- package/src/components/price/form.tsx +895 -370
- package/src/components/price/upsell-select.tsx +10 -2
- package/src/components/price/upsell.tsx +7 -2
- package/src/components/pricing-table/actions.tsx +1 -5
- package/src/components/pricing-table/customer-settings.tsx +5 -1
- package/src/components/pricing-table/payment-settings.tsx +14 -4
- package/src/components/pricing-table/preview.tsx +9 -9
- package/src/components/pricing-table/price-item.tsx +6 -1
- package/src/components/pricing-table/product-item.tsx +6 -1
- package/src/components/pricing-table/product-settings.tsx +17 -4
- package/src/components/product/actions.tsx +1 -5
- package/src/components/product/add-price.tsx +9 -7
- package/src/components/product/create.tsx +8 -9
- package/src/components/product/cross-sell-select.tsx +5 -1
- package/src/components/product/cross-sell.tsx +7 -2
- package/src/components/product/edit-price.tsx +21 -12
- package/src/components/product/features.tsx +26 -6
- package/src/components/product/form.tsx +115 -72
- package/src/components/progress-bar.tsx +1 -1
- package/src/components/refund/actions.tsx +1 -7
- package/src/components/refund/list.tsx +31 -18
- package/src/components/section/header.tsx +12 -14
- package/src/components/subscription/actions/cancel.tsx +22 -5
- package/src/components/subscription/actions/index.tsx +9 -10
- package/src/components/subscription/actions/pause.tsx +32 -6
- package/src/components/subscription/actions/slash-stake.tsx +5 -3
- package/src/components/subscription/description.tsx +12 -8
- package/src/components/subscription/items/index.tsx +31 -16
- package/src/components/subscription/items/usage-records.tsx +19 -5
- package/src/components/subscription/list.tsx +5 -7
- package/src/components/subscription/metrics.tsx +62 -15
- package/src/components/subscription/portal/actions.tsx +78 -71
- package/src/components/subscription/portal/cancel.tsx +10 -3
- package/src/components/subscription/portal/list.tsx +48 -26
- package/src/components/uploader.tsx +5 -13
- package/src/components/webhook/attempts.tsx +51 -16
- package/src/components/webhook/request-info.tsx +8 -6
- package/src/contexts/products.tsx +27 -10
- package/src/hooks/subscription.ts +34 -0
- package/src/libs/meter-utils.ts +196 -0
- package/src/libs/util.ts +4 -0
- package/src/locales/en.tsx +385 -4
- package/src/locales/zh.tsx +364 -0
- package/src/pages/admin/billing/index.tsx +61 -33
- package/src/pages/admin/billing/invoices/detail.tsx +49 -13
- package/src/pages/admin/billing/meters/create.tsx +60 -0
- package/src/pages/admin/billing/meters/detail.tsx +435 -0
- package/src/pages/admin/billing/meters/index.tsx +210 -0
- package/src/pages/admin/billing/meters/meter-event.tsx +346 -0
- package/src/pages/admin/billing/subscriptions/detail.tsx +90 -25
- package/src/pages/admin/customers/customers/credit-grant/detail.tsx +391 -0
- package/src/pages/admin/customers/customers/detail.tsx +67 -14
- package/src/pages/admin/customers/customers/index.tsx +6 -1
- package/src/pages/admin/customers/index.tsx +5 -0
- package/src/pages/admin/developers/events/detail.tsx +37 -11
- package/src/pages/admin/developers/index.tsx +1 -1
- package/src/pages/admin/developers/webhooks/detail.tsx +41 -11
- package/src/pages/admin/index.tsx +15 -2
- package/src/pages/admin/overview.tsx +107 -19
- package/src/pages/admin/payments/intents/detail.tsx +58 -14
- package/src/pages/admin/payments/payouts/detail.tsx +63 -15
- package/src/pages/admin/payments/refunds/detail.tsx +58 -14
- package/src/pages/admin/products/index.tsx +11 -4
- package/src/pages/admin/products/links/create.tsx +22 -4
- package/src/pages/admin/products/links/detail.tsx +43 -14
- package/src/pages/admin/products/passports/index.tsx +23 -4
- package/src/pages/admin/products/prices/actions.tsx +16 -9
- package/src/pages/admin/products/prices/detail.tsx +73 -14
- package/src/pages/admin/products/prices/list.tsx +15 -3
- package/src/pages/admin/products/pricing-tables/create.tsx +45 -12
- package/src/pages/admin/products/pricing-tables/detail.tsx +45 -14
- package/src/pages/admin/products/products/create.tsx +233 -54
- package/src/pages/admin/products/products/detail.tsx +74 -18
- package/src/pages/admin/settings/index.tsx +8 -1
- package/src/pages/admin/settings/payment-methods/index.tsx +87 -19
- package/src/pages/admin/settings/vault-config/edit-form.tsx +42 -28
- package/src/pages/admin/settings/vault-config/index.tsx +57 -10
- package/src/pages/customer/credit-grant/detail.tsx +308 -0
- package/src/pages/customer/index.tsx +76 -17
- package/src/pages/customer/invoice/detail.tsx +63 -14
- package/src/pages/customer/invoice/past-due.tsx +11 -3
- package/src/pages/customer/payout/detail.tsx +56 -13
- package/src/pages/customer/recharge/account.tsx +78 -18
- package/src/pages/customer/recharge/subscription.tsx +86 -25
- package/src/pages/customer/refund/list.tsx +60 -24
- package/src/pages/customer/subscription/change-payment.tsx +17 -6
- package/src/pages/customer/subscription/change-plan.tsx +34 -7
- package/src/pages/customer/subscription/detail.tsx +134 -34
- package/src/pages/customer/subscription/embed.tsx +25 -5
- package/src/pages/home.tsx +26 -4
- package/src/pages/integrations/donations/edit-form.tsx +25 -9
- package/src/pages/integrations/donations/index.tsx +26 -9
- package/src/pages/integrations/donations/preview.tsx +59 -15
- package/src/pages/integrations/index.tsx +10 -1
- package/src/pages/integrations/overview.tsx +78 -17
- package/vite.config.ts +60 -30
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
getPriceCurrencyOptions,
|
|
18
18
|
getStatementDescriptor,
|
|
19
19
|
isValidCountry,
|
|
20
|
+
showStaking,
|
|
20
21
|
usePaymentContext,
|
|
21
22
|
} from '@blocklet/payment-react';
|
|
22
23
|
import type { TCustomer, TPaymentCurrency, TPaymentMethod, TSubscriptionExpanded } from '@blocklet/payment-types';
|
|
@@ -222,14 +223,24 @@ function CustomerSubscriptionChangePayment({ subscription, customer, onComplete
|
|
|
222
223
|
setState({ stripePaying: false });
|
|
223
224
|
};
|
|
224
225
|
|
|
226
|
+
const currency = findCurrency(settings.paymentMethods, selectedCurrencyId) as TPaymentCurrency;
|
|
225
227
|
return (
|
|
226
228
|
<Stack direction="column" spacing={4} sx={{ maxWidth: '540px' }}>
|
|
227
|
-
<Stack
|
|
229
|
+
<Stack
|
|
230
|
+
className="page-header"
|
|
231
|
+
direction="row"
|
|
232
|
+
sx={{
|
|
233
|
+
justifyContent: 'space-between',
|
|
234
|
+
alignItems: 'center',
|
|
235
|
+
}}>
|
|
228
236
|
<Stack
|
|
229
237
|
direction="row"
|
|
230
|
-
|
|
231
|
-
sx={{
|
|
232
|
-
|
|
238
|
+
onClick={() => goBackOrFallback(`/customer/subscription/${subscription.id}`)}
|
|
239
|
+
sx={{
|
|
240
|
+
alignItems: 'center',
|
|
241
|
+
fontWeight: 'normal',
|
|
242
|
+
cursor: 'pointer',
|
|
243
|
+
}}>
|
|
233
244
|
<ArrowBackOutlined fontSize="small" sx={{ mr: 0.5, color: 'text.secondary' }} />
|
|
234
245
|
<SubscriptionDescription subscription={subscription} variant="h5" />
|
|
235
246
|
</Stack>
|
|
@@ -239,10 +250,10 @@ function CustomerSubscriptionChangePayment({ subscription, customer, onComplete
|
|
|
239
250
|
<SectionHeader title={t('payment.customer.changePayment.review')} />
|
|
240
251
|
<PaymentSummary
|
|
241
252
|
items={subscription.items as any[]}
|
|
242
|
-
currency={
|
|
253
|
+
currency={currency}
|
|
243
254
|
trialInDays={0}
|
|
244
255
|
billingThreshold={0}
|
|
245
|
-
showStaking={method
|
|
256
|
+
showStaking={showStaking(method, currency, !!subscription.billing_thresholds?.no_stake)}
|
|
246
257
|
/>
|
|
247
258
|
</Stack>
|
|
248
259
|
<Stack direction="column" spacing={2}>
|
|
@@ -219,7 +219,12 @@ export default function CustomerSubscriptionChangePlan() {
|
|
|
219
219
|
|
|
220
220
|
const getInfoRow = (label: string, value: string, prefix?: string) => {
|
|
221
221
|
return (
|
|
222
|
-
<Stack
|
|
222
|
+
<Stack
|
|
223
|
+
direction="row"
|
|
224
|
+
key={value}
|
|
225
|
+
sx={{
|
|
226
|
+
justifyContent: 'space-between',
|
|
227
|
+
}}>
|
|
223
228
|
<Typography variant="h6" sx={{ fontWeight: 'normal' }}>
|
|
224
229
|
{label}
|
|
225
230
|
</Typography>
|
|
@@ -233,12 +238,21 @@ export default function CustomerSubscriptionChangePlan() {
|
|
|
233
238
|
|
|
234
239
|
return (
|
|
235
240
|
<Stack direction="column" spacing={4} sx={{ mb: 4 }}>
|
|
236
|
-
<Stack
|
|
241
|
+
<Stack
|
|
242
|
+
className="page-header"
|
|
243
|
+
direction="row"
|
|
244
|
+
sx={{
|
|
245
|
+
justifyContent: 'space-between',
|
|
246
|
+
alignItems: 'center',
|
|
247
|
+
}}>
|
|
237
248
|
<Stack
|
|
238
249
|
direction="row"
|
|
239
|
-
|
|
240
|
-
sx={{
|
|
241
|
-
|
|
250
|
+
onClick={() => goBackOrFallback(`/customer/subscription/${data.subscription.id}`)}
|
|
251
|
+
sx={{
|
|
252
|
+
alignItems: 'center',
|
|
253
|
+
fontWeight: 'normal',
|
|
254
|
+
cursor: 'pointer',
|
|
255
|
+
}}>
|
|
242
256
|
<ArrowBackOutlined fontSize="small" sx={{ mr: 0.5, color: 'text.secondary' }} />
|
|
243
257
|
<SubscriptionDescription subscription={data.subscription} variant="h5" />
|
|
244
258
|
</Stack>
|
|
@@ -268,7 +282,13 @@ export default function CustomerSubscriptionChangePlan() {
|
|
|
268
282
|
{state.items.map((x: TLineItemExpanded) => {
|
|
269
283
|
const { product } = x.price;
|
|
270
284
|
return (
|
|
271
|
-
<Stack
|
|
285
|
+
<Stack
|
|
286
|
+
key={x.price_id}
|
|
287
|
+
direction="row"
|
|
288
|
+
sx={{
|
|
289
|
+
alignItems: 'center',
|
|
290
|
+
justifyContent: 'space-between',
|
|
291
|
+
}}>
|
|
272
292
|
<InfoCard logo={product.images[0]} name={product.name} description={product.description} />
|
|
273
293
|
<Typography component="p" style={{ fontWeight: 'bold' }}>
|
|
274
294
|
{formatPrice(
|
|
@@ -294,7 +314,14 @@ export default function CustomerSubscriptionChangePlan() {
|
|
|
294
314
|
<Divider />
|
|
295
315
|
{getInfoRow(t('payment.customer.changePlan.remaining'), state.due)}
|
|
296
316
|
<Divider />
|
|
297
|
-
<Stack
|
|
317
|
+
<Stack
|
|
318
|
+
direction="row"
|
|
319
|
+
spacing={2}
|
|
320
|
+
sx={{
|
|
321
|
+
alignItems: 'center',
|
|
322
|
+
justifyContent: 'flex-end',
|
|
323
|
+
pt: 2,
|
|
324
|
+
}}>
|
|
298
325
|
<LoadingButton
|
|
299
326
|
disabled={state.loading || state.paying}
|
|
300
327
|
onClick={() => setState({ priceId: '' })}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable react/no-unstable-nested-components */
|
|
2
2
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
3
3
|
import {
|
|
4
|
+
CreditTransactionsList,
|
|
4
5
|
CustomerInvoiceList,
|
|
5
6
|
TxLink,
|
|
6
7
|
api,
|
|
@@ -45,7 +46,7 @@ import SubscriptionActions, { ActionMethods } from '../../../components/subscrip
|
|
|
45
46
|
import { canChangePaymentMethod } from '../../../libs/util';
|
|
46
47
|
import { useSessionContext } from '../../../contexts/session';
|
|
47
48
|
import InfoMetric from '../../../components/info-metric';
|
|
48
|
-
import { useUnpaidInvoicesCheckForSubscription } from '../../../hooks/subscription';
|
|
49
|
+
import { useUnpaidInvoicesCheckForSubscription, usePendingAmountForSubscription } from '../../../hooks/subscription';
|
|
49
50
|
import { formatSmartDuration, TimeUnit } from '../../../libs/dayjs';
|
|
50
51
|
import InfoRowGroup from '../../../components/info-row-group';
|
|
51
52
|
|
|
@@ -74,6 +75,7 @@ export default function CustomerSubscriptionDetail() {
|
|
|
74
75
|
const { session } = useSessionContext();
|
|
75
76
|
const { loading, error, data, refresh } = useRequest(() => fetchData(id));
|
|
76
77
|
const { hasUnpaid, checkUnpaidInvoices } = useUnpaidInvoicesCheckForSubscription(id);
|
|
78
|
+
const { hasPendingAmount, pendingAmount } = usePendingAmountForSubscription(id, data?.paymentCurrency);
|
|
77
79
|
const overdraftProtectionReady =
|
|
78
80
|
['active', 'trialing', 'past_due'].includes(data?.status || '') && data?.paymentMethod?.type === 'arcblock';
|
|
79
81
|
const {
|
|
@@ -100,7 +102,7 @@ export default function CustomerSubscriptionDetail() {
|
|
|
100
102
|
}
|
|
101
103
|
);
|
|
102
104
|
|
|
103
|
-
const actionRef = useRef<ActionMethods>();
|
|
105
|
+
const actionRef = useRef<ActionMethods | undefined>(undefined);
|
|
104
106
|
|
|
105
107
|
const enableOverdraftProtection = !!overdraftProtection?.enabled;
|
|
106
108
|
|
|
@@ -119,11 +121,13 @@ export default function CustomerSubscriptionDetail() {
|
|
|
119
121
|
return <CircularProgress />;
|
|
120
122
|
}
|
|
121
123
|
|
|
124
|
+
const isCredit = data?.paymentCurrency?.type === 'credit';
|
|
122
125
|
const showOverdraftProtection =
|
|
123
126
|
data?.paymentMethod?.type === 'arcblock' &&
|
|
124
127
|
!overdraftProtectionLoading &&
|
|
125
128
|
!!overdraftProtection &&
|
|
126
|
-
['active', 'trialing', 'past_due'].includes(data.status)
|
|
129
|
+
['active', 'trialing', 'past_due'].includes(data.status) &&
|
|
130
|
+
!isCredit;
|
|
127
131
|
|
|
128
132
|
const renderOverdraftProtectionLabel = () => {
|
|
129
133
|
const enabled = data?.overdraft_protection?.enabled;
|
|
@@ -155,7 +159,12 @@ export default function CustomerSubscriptionDetail() {
|
|
|
155
159
|
};
|
|
156
160
|
if (!enabled) {
|
|
157
161
|
return (
|
|
158
|
-
<Stack
|
|
162
|
+
<Stack
|
|
163
|
+
direction="row"
|
|
164
|
+
spacing={1}
|
|
165
|
+
sx={{
|
|
166
|
+
alignItems: 'center',
|
|
167
|
+
}}>
|
|
159
168
|
<Typography sx={{ color: 'text.lighter' }}>{t('customer.overdraftProtection.disabled')}</Typography>
|
|
160
169
|
<Button
|
|
161
170
|
size="small"
|
|
@@ -195,9 +204,23 @@ export default function CustomerSubscriptionDetail() {
|
|
|
195
204
|
}
|
|
196
205
|
|
|
197
206
|
return (
|
|
198
|
-
<Stack
|
|
199
|
-
|
|
200
|
-
|
|
207
|
+
<Stack
|
|
208
|
+
direction="row"
|
|
209
|
+
sx={{
|
|
210
|
+
alignItems: 'center',
|
|
211
|
+
}}>
|
|
212
|
+
<Stack
|
|
213
|
+
direction="row"
|
|
214
|
+
spacing={1}
|
|
215
|
+
sx={{
|
|
216
|
+
alignItems: 'center',
|
|
217
|
+
}}>
|
|
218
|
+
<Stack
|
|
219
|
+
direction="row"
|
|
220
|
+
spacing={0.5}
|
|
221
|
+
sx={{
|
|
222
|
+
alignItems: 'center',
|
|
223
|
+
}}>
|
|
201
224
|
<CheckCircle
|
|
202
225
|
sx={{
|
|
203
226
|
fontSize: '16px',
|
|
@@ -234,7 +257,11 @@ export default function CustomerSubscriptionDetail() {
|
|
|
234
257
|
sx={{ width: 16, height: 16 }}
|
|
235
258
|
alt={data.paymentCurrency?.symbol}
|
|
236
259
|
/>
|
|
237
|
-
<Box
|
|
260
|
+
<Box
|
|
261
|
+
sx={{
|
|
262
|
+
display: 'flex',
|
|
263
|
+
alignItems: 'baseline',
|
|
264
|
+
}}>
|
|
238
265
|
{formatBNStr(overdraftProtection?.unused, data.paymentCurrency.decimal)}
|
|
239
266
|
<Typography
|
|
240
267
|
sx={{
|
|
@@ -280,23 +307,40 @@ export default function CustomerSubscriptionDetail() {
|
|
|
280
307
|
{t('customer.unpaidInvoicesWarningTip')}
|
|
281
308
|
</Alert>
|
|
282
309
|
)}
|
|
310
|
+
{hasPendingAmount && pendingAmount && (
|
|
311
|
+
<Alert severity="error" sx={{ mb: 2 }}>
|
|
312
|
+
{t('customer.pendingAmountWarningTip', {
|
|
313
|
+
amount: formatBNStr(pendingAmount, data?.paymentCurrency?.decimal),
|
|
314
|
+
symbol: data?.paymentCurrency?.symbol,
|
|
315
|
+
})}
|
|
316
|
+
</Alert>
|
|
317
|
+
)}
|
|
283
318
|
<Stack
|
|
284
319
|
className="page-header"
|
|
285
320
|
direction="row"
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
321
|
+
sx={{
|
|
322
|
+
justifyContent: 'space-between',
|
|
323
|
+
alignItems: 'center',
|
|
324
|
+
position: 'relative',
|
|
325
|
+
}}>
|
|
289
326
|
<Stack
|
|
290
327
|
direction="row"
|
|
291
328
|
onClick={() => navigate('/customer', { replace: true })}
|
|
292
|
-
|
|
293
|
-
|
|
329
|
+
sx={{
|
|
330
|
+
alignItems: 'center',
|
|
331
|
+
fontWeight: 'normal',
|
|
332
|
+
cursor: 'pointer',
|
|
333
|
+
}}>
|
|
294
334
|
<ArrowBackOutlined fontSize="small" sx={{ mr: 0.5, color: 'text.secondary' }} />
|
|
295
335
|
<Typography variant="h6" sx={{ color: 'text.secondary', fontWeight: 'normal' }}>
|
|
296
336
|
{t('payment.customer.subscriptions.title')}
|
|
297
337
|
</Typography>
|
|
298
338
|
</Stack>
|
|
299
|
-
<Stack
|
|
339
|
+
<Stack
|
|
340
|
+
direction="row"
|
|
341
|
+
sx={{
|
|
342
|
+
gap: 1,
|
|
343
|
+
}}>
|
|
300
344
|
<SubscriptionActions
|
|
301
345
|
subscription={data}
|
|
302
346
|
onChange={(action) => {
|
|
@@ -332,45 +376,64 @@ export default function CustomerSubscriptionDetail() {
|
|
|
332
376
|
</Stack>
|
|
333
377
|
</Stack>
|
|
334
378
|
<Box
|
|
335
|
-
mt={4}
|
|
336
379
|
sx={{
|
|
380
|
+
mt: 4,
|
|
337
381
|
display: 'flex',
|
|
382
|
+
|
|
338
383
|
gap: {
|
|
339
384
|
xs: 2,
|
|
340
385
|
sm: 2,
|
|
341
386
|
md: 5,
|
|
342
387
|
},
|
|
388
|
+
|
|
343
389
|
flexWrap: 'wrap',
|
|
390
|
+
|
|
344
391
|
flexDirection: {
|
|
345
392
|
xs: 'column',
|
|
346
393
|
sm: 'column',
|
|
347
394
|
md: 'row',
|
|
348
395
|
},
|
|
396
|
+
|
|
349
397
|
alignItems: {
|
|
350
398
|
xs: 'flex-start',
|
|
351
399
|
sm: 'flex-start',
|
|
352
400
|
md: 'center',
|
|
353
401
|
},
|
|
354
402
|
}}>
|
|
355
|
-
<Stack
|
|
356
|
-
|
|
403
|
+
<Stack
|
|
404
|
+
direction="row"
|
|
405
|
+
sx={{
|
|
406
|
+
justifyContent: 'space-between',
|
|
407
|
+
alignItems: 'center',
|
|
408
|
+
}}>
|
|
409
|
+
<Stack
|
|
410
|
+
direction="row"
|
|
411
|
+
sx={{
|
|
412
|
+
alignItems: 'center',
|
|
413
|
+
flexWrap: 'wrap',
|
|
414
|
+
gap: 1,
|
|
415
|
+
}}>
|
|
357
416
|
<SubscriptionDescription subscription={data} variant="h1" />
|
|
358
417
|
</Stack>
|
|
359
418
|
</Stack>
|
|
360
419
|
<Stack
|
|
361
420
|
className="section-body"
|
|
362
|
-
justifyContent="flex-start"
|
|
363
|
-
flexWrap="wrap"
|
|
364
421
|
sx={{
|
|
422
|
+
justifyContent: 'flex-start',
|
|
423
|
+
flexWrap: 'wrap',
|
|
424
|
+
|
|
365
425
|
'hr.MuiDivider-root:last-child': {
|
|
366
426
|
display: 'none',
|
|
367
427
|
},
|
|
428
|
+
|
|
368
429
|
flexDirection: {
|
|
369
430
|
xs: 'column',
|
|
370
431
|
sm: 'column',
|
|
371
432
|
md: 'row',
|
|
372
433
|
},
|
|
434
|
+
|
|
373
435
|
alignItems: 'flex-start',
|
|
436
|
+
|
|
374
437
|
gap: {
|
|
375
438
|
xs: 1,
|
|
376
439
|
sm: 1,
|
|
@@ -381,7 +444,12 @@ export default function CustomerSubscriptionDetail() {
|
|
|
381
444
|
{showOverdraftProtection && (
|
|
382
445
|
<InfoMetric
|
|
383
446
|
label={
|
|
384
|
-
<Stack
|
|
447
|
+
<Stack
|
|
448
|
+
direction="row"
|
|
449
|
+
spacing={0.5}
|
|
450
|
+
sx={{
|
|
451
|
+
alignItems: 'center',
|
|
452
|
+
}}>
|
|
385
453
|
<Typography component="span">{t('customer.overdraftProtection.title')}</Typography>
|
|
386
454
|
<MuiLink
|
|
387
455
|
href="https://www.arcblock.io/content/blog/en/payment-kit-v117-sub-guard#listen-to-the-audio-overview"
|
|
@@ -435,12 +503,28 @@ export default function CustomerSubscriptionDetail() {
|
|
|
435
503
|
value={renderOverdraftProtectionLabel()}
|
|
436
504
|
/>
|
|
437
505
|
)}
|
|
506
|
+
{isCredit && hasPendingAmount && (
|
|
507
|
+
<InfoMetric
|
|
508
|
+
label={t('admin.customer.creditGrants.pendingAmount')}
|
|
509
|
+
value={
|
|
510
|
+
<Typography
|
|
511
|
+
sx={{
|
|
512
|
+
color: 'error.main',
|
|
513
|
+
}}>{`${formatBNStr(pendingAmount, data?.paymentCurrency?.decimal)} ${data?.paymentCurrency?.symbol}`}</Typography>
|
|
514
|
+
}
|
|
515
|
+
/>
|
|
516
|
+
)}
|
|
438
517
|
</Stack>
|
|
439
518
|
</Box>
|
|
440
519
|
</Box>
|
|
441
520
|
<Divider />
|
|
442
521
|
<Box className="section" sx={{ containerType: 'inline-size' }}>
|
|
443
|
-
<Typography
|
|
522
|
+
<Typography
|
|
523
|
+
variant="h3"
|
|
524
|
+
className="section-header"
|
|
525
|
+
sx={{
|
|
526
|
+
mb: 3,
|
|
527
|
+
}}>
|
|
444
528
|
{t('admin.details')}
|
|
445
529
|
</Typography>
|
|
446
530
|
<InfoRowGroup
|
|
@@ -568,7 +652,12 @@ export default function CustomerSubscriptionDetail() {
|
|
|
568
652
|
</Box>
|
|
569
653
|
<Divider />
|
|
570
654
|
<Box className="section">
|
|
571
|
-
<Typography
|
|
655
|
+
<Typography
|
|
656
|
+
variant="h3"
|
|
657
|
+
className="section-header"
|
|
658
|
+
sx={{
|
|
659
|
+
mb: 1.5,
|
|
660
|
+
}}>
|
|
572
661
|
{t('admin.products')}
|
|
573
662
|
</Typography>
|
|
574
663
|
<Box className="section-body">
|
|
@@ -576,19 +665,30 @@ export default function CustomerSubscriptionDetail() {
|
|
|
576
665
|
</Box>
|
|
577
666
|
</Box>
|
|
578
667
|
<Divider />
|
|
579
|
-
|
|
580
|
-
<
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
<
|
|
585
|
-
subscription_id={data.id}
|
|
586
|
-
|
|
587
|
-
include_staking
|
|
588
|
-
status="open,paid,uncollectible,void"
|
|
589
|
-
/>
|
|
668
|
+
{isCredit ? (
|
|
669
|
+
<Box className="section">
|
|
670
|
+
<Typography variant="h3" className="section-header">
|
|
671
|
+
{t('admin.creditTransactions.title')}
|
|
672
|
+
</Typography>
|
|
673
|
+
<Box className="section-body">
|
|
674
|
+
<CreditTransactionsList customer_id={data.customer_id} subscription_id={data.id} showAdminColumns={false} />
|
|
675
|
+
</Box>
|
|
590
676
|
</Box>
|
|
591
|
-
|
|
677
|
+
) : (
|
|
678
|
+
<Box className="section">
|
|
679
|
+
<Typography variant="h3" className="section-header">
|
|
680
|
+
{t('customer.invoiceHistory')}
|
|
681
|
+
</Typography>
|
|
682
|
+
<Box className="section-body">
|
|
683
|
+
<CustomerInvoiceList
|
|
684
|
+
subscription_id={data.id}
|
|
685
|
+
type="table"
|
|
686
|
+
include_staking
|
|
687
|
+
status="open,paid,uncollectible,void"
|
|
688
|
+
/>
|
|
689
|
+
</Box>
|
|
690
|
+
</Box>
|
|
691
|
+
)}
|
|
592
692
|
</Root>
|
|
593
693
|
);
|
|
594
694
|
}
|
|
@@ -60,7 +60,7 @@ const fetchSubscriptionData = (id: string, authToken: string): Promise<TSubscrip
|
|
|
60
60
|
throw new Error('Subscription ID is missing');
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
return api.get(`/api/subscriptions/${id}?authToken=${authToken}`).then((res) => res.data);
|
|
63
|
+
return api.get(`/api/subscriptions/${id}?authToken=${authToken}`).then((res: any) => res.data);
|
|
64
64
|
};
|
|
65
65
|
|
|
66
66
|
const checkHasPastDue = async (subscriptionId: string, authToken: string): Promise<boolean> => {
|
|
@@ -153,7 +153,11 @@ export default function SubscriptionEmbed() {
|
|
|
153
153
|
{
|
|
154
154
|
name: t('payment.customer.subscriptions.plan'),
|
|
155
155
|
value: (
|
|
156
|
-
<Typography
|
|
156
|
+
<Typography
|
|
157
|
+
sx={{
|
|
158
|
+
fontWeight: 600,
|
|
159
|
+
marginRight: '10px',
|
|
160
|
+
}}>
|
|
157
161
|
{formatSubscriptionProduct(subscription.items)}
|
|
158
162
|
</Typography>
|
|
159
163
|
),
|
|
@@ -278,12 +282,22 @@ export default function SubscriptionEmbed() {
|
|
|
278
282
|
<Box sx={{ flex: 1, overflow: 'hidden' }}>
|
|
279
283
|
<List sx={{ height: '100%', display: 'flex', flexDirection: 'column' }} className="mini-invoice-list">
|
|
280
284
|
<ListSubheader disableGutters sx={{ padding: 0 }}>
|
|
281
|
-
<Typography
|
|
285
|
+
<Typography
|
|
286
|
+
component="h2"
|
|
287
|
+
variant="h6"
|
|
288
|
+
sx={{
|
|
289
|
+
fontSize: '16px',
|
|
290
|
+
}}>
|
|
282
291
|
{t('payment.customer.invoices')}
|
|
283
292
|
</Typography>
|
|
284
293
|
</ListSubheader>
|
|
285
294
|
{(invoices as any).length === 0 ? (
|
|
286
|
-
<Typography
|
|
295
|
+
<Typography
|
|
296
|
+
sx={{
|
|
297
|
+
color: 'text.lighter',
|
|
298
|
+
}}>
|
|
299
|
+
{t('payment.customer.invoice.empty')}
|
|
300
|
+
</Typography>
|
|
287
301
|
) : (
|
|
288
302
|
<Box sx={{ flex: 1, overflow: 'auto' }}>
|
|
289
303
|
{(invoices as any).map((item: any) => {
|
|
@@ -309,7 +323,13 @@ export default function SubscriptionEmbed() {
|
|
|
309
323
|
)}
|
|
310
324
|
</List>
|
|
311
325
|
</Box>
|
|
312
|
-
<Stack
|
|
326
|
+
<Stack
|
|
327
|
+
direction="row"
|
|
328
|
+
spacing={2}
|
|
329
|
+
sx={{
|
|
330
|
+
justifyContent: 'center',
|
|
331
|
+
mt: 2,
|
|
332
|
+
}}>
|
|
313
333
|
{subscription.service_actions
|
|
314
334
|
?.filter((x: any) => x?.type !== 'notification')
|
|
315
335
|
?.map((x) => (
|
package/src/pages/home.tsx
CHANGED
|
@@ -15,17 +15,39 @@ function Home() {
|
|
|
15
15
|
hideNavMenu={undefined}
|
|
16
16
|
maxWidth={false}
|
|
17
17
|
/>
|
|
18
|
-
<Stack
|
|
19
|
-
|
|
18
|
+
<Stack
|
|
19
|
+
sx={{
|
|
20
|
+
alignItems: 'center',
|
|
21
|
+
justifyContent: 'center',
|
|
22
|
+
height: '60vh',
|
|
23
|
+
width: '100vw',
|
|
24
|
+
}}>
|
|
25
|
+
<Stack
|
|
26
|
+
direction="column"
|
|
27
|
+
spacing={3}
|
|
28
|
+
sx={{
|
|
29
|
+
maxWidth: 'sm',
|
|
30
|
+
alignItems: 'center',
|
|
31
|
+
}}>
|
|
20
32
|
<Avatar
|
|
21
33
|
src={window.blocklet.appLogo}
|
|
22
34
|
sx={{ width: 80, height: 80 }}
|
|
23
35
|
variant="square"
|
|
24
36
|
alt={window.blocklet.appName || 'Payment Kit'}
|
|
25
37
|
/>
|
|
26
|
-
<Stack
|
|
38
|
+
<Stack
|
|
39
|
+
direction="column"
|
|
40
|
+
spacing={1}
|
|
41
|
+
sx={{
|
|
42
|
+
alignItems: 'center',
|
|
43
|
+
}}>
|
|
27
44
|
<Typography variant="h4">Payment Kit</Typography>
|
|
28
|
-
<Typography
|
|
45
|
+
<Typography
|
|
46
|
+
variant="h5"
|
|
47
|
+
sx={{
|
|
48
|
+
color: 'text.secondary',
|
|
49
|
+
fontWeight: 'normal',
|
|
50
|
+
}}>
|
|
29
51
|
<Typewriter
|
|
30
52
|
options={{
|
|
31
53
|
strings: ['The decentralized stripe alike payment solution for blocklets'],
|
|
@@ -157,11 +157,12 @@ export default function EditDonationForm({
|
|
|
157
157
|
minHeight: 0,
|
|
158
158
|
}}>
|
|
159
159
|
<Grid
|
|
160
|
-
item
|
|
161
|
-
xs={12}
|
|
162
|
-
md={6}
|
|
163
160
|
sx={{
|
|
164
161
|
height: '100%',
|
|
162
|
+
}}
|
|
163
|
+
size={{
|
|
164
|
+
xs: 12,
|
|
165
|
+
md: 6,
|
|
165
166
|
}}>
|
|
166
167
|
<Paper
|
|
167
168
|
elevation={0}
|
|
@@ -173,7 +174,13 @@ export default function EditDonationForm({
|
|
|
173
174
|
}}>
|
|
174
175
|
<Stack spacing={4}>
|
|
175
176
|
<Box>
|
|
176
|
-
<Typography
|
|
177
|
+
<Typography
|
|
178
|
+
variant="h6"
|
|
179
|
+
gutterBottom
|
|
180
|
+
sx={{
|
|
181
|
+
color: 'text.primary',
|
|
182
|
+
mb: 3,
|
|
183
|
+
}}>
|
|
177
184
|
{t('admin.donate.buttonSettings')}
|
|
178
185
|
</Typography>
|
|
179
186
|
<Stack spacing={3}>
|
|
@@ -190,7 +197,10 @@ export default function EditDonationForm({
|
|
|
190
197
|
)}
|
|
191
198
|
/>
|
|
192
199
|
|
|
193
|
-
<Stack
|
|
200
|
+
<Stack
|
|
201
|
+
sx={{
|
|
202
|
+
gap: 1,
|
|
203
|
+
}}>
|
|
194
204
|
<Typography variant="subtitle2" gutterBottom>
|
|
195
205
|
{t('admin.donate.historyType.title')}
|
|
196
206
|
</Typography>
|
|
@@ -219,7 +229,13 @@ export default function EditDonationForm({
|
|
|
219
229
|
<Divider />
|
|
220
230
|
|
|
221
231
|
<Box>
|
|
222
|
-
<Typography
|
|
232
|
+
<Typography
|
|
233
|
+
variant="h6"
|
|
234
|
+
gutterBottom
|
|
235
|
+
sx={{
|
|
236
|
+
color: 'text.primary',
|
|
237
|
+
mb: 3,
|
|
238
|
+
}}>
|
|
223
239
|
{t('admin.donate.amountSettings')}
|
|
224
240
|
</Typography>
|
|
225
241
|
<Stack spacing={3}>
|
|
@@ -297,11 +313,12 @@ export default function EditDonationForm({
|
|
|
297
313
|
</Grid>
|
|
298
314
|
|
|
299
315
|
<Grid
|
|
300
|
-
item
|
|
301
|
-
md={6}
|
|
302
316
|
sx={{
|
|
303
317
|
display: { xs: 'none', md: 'block' },
|
|
304
318
|
height: '100%',
|
|
319
|
+
}}
|
|
320
|
+
size={{
|
|
321
|
+
md: 6,
|
|
305
322
|
}}>
|
|
306
323
|
<Paper
|
|
307
324
|
elevation={0}
|
|
@@ -317,7 +334,6 @@ export default function EditDonationForm({
|
|
|
317
334
|
</Grid>
|
|
318
335
|
</FormProvider>
|
|
319
336
|
</Box>
|
|
320
|
-
|
|
321
337
|
<Box
|
|
322
338
|
sx={{
|
|
323
339
|
mt: 2,
|