payment-kit 1.18.6 → 1.18.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/api/src/libs/auth.ts +1 -1
  2. package/api/src/routes/connect/change-payment.ts +47 -22
  3. package/api/src/routes/connect/change-plan.ts +45 -20
  4. package/api/src/routes/connect/setup.ts +46 -21
  5. package/api/src/routes/connect/subscribe.ts +40 -21
  6. package/api/src/routes/payment-links.ts +1 -1
  7. package/blocklet.yml +1 -1
  8. package/package.json +19 -19
  9. package/src/components/filter-toolbar.tsx +10 -10
  10. package/src/components/layout/admin.tsx +1 -0
  11. package/src/components/payment-link/product-select.tsx +1 -1
  12. package/src/components/price/currency-select.tsx +3 -1
  13. package/src/components/price/form.tsx +1 -1
  14. package/src/components/section/header.tsx +1 -1
  15. package/src/components/subscription/list.tsx +1 -0
  16. package/src/components/uploader.tsx +1 -0
  17. package/src/global.css +4 -4
  18. package/src/libs/util.ts +13 -0
  19. package/src/pages/admin/developers/webhooks/detail.tsx +1 -1
  20. package/src/pages/admin/overview.tsx +3 -3
  21. package/src/pages/admin/payments/intents/detail.tsx +1 -1
  22. package/src/pages/admin/payments/payouts/detail.tsx +1 -1
  23. package/src/pages/admin/payments/refunds/detail.tsx +1 -1
  24. package/src/pages/admin/products/products/detail.tsx +1 -1
  25. package/src/pages/customer/payout/detail.tsx +1 -1
  26. package/src/pages/customer/recharge.tsx +35 -6
  27. package/src/pages/customer/subscription/change-payment.tsx +8 -2
  28. package/src/pages/customer/subscription/change-plan.tsx +1 -1
  29. package/src/pages/integrations/donations/index.tsx +1 -1
  30. package/src/pages/integrations/donations/preview.tsx +73 -52
  31. package/src/pages/integrations/overview.tsx +63 -40
@@ -126,7 +126,7 @@ function SearchStatus({
126
126
  <Button className="option-btn" variant="text">
127
127
  {search!.status ? (
128
128
  <Close
129
- sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }}
129
+ sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.05rem' }}
130
130
  onClick={(e) => {
131
131
  e.stopPropagation();
132
132
  setSearch({
@@ -136,7 +136,7 @@ function SearchStatus({
136
136
  }}
137
137
  />
138
138
  ) : (
139
- <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }} />
139
+ <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.05rem' }} />
140
140
  )}
141
141
  {t('common.status')}
142
142
  <span>{formatStatus ? formatStatus(search!.status) : search!.status}</span>
@@ -192,7 +192,7 @@ function SearchCurrency({ setSearch, search }: Pick<Props, 'setSearch' | 'search
192
192
  <Button className="option-btn" variant="text">
193
193
  {search!.currency_id ? (
194
194
  <Close
195
- sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }}
195
+ sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.05rem' }}
196
196
  onClick={(e) => {
197
197
  e.stopPropagation();
198
198
  setSearch({
@@ -202,7 +202,7 @@ function SearchCurrency({ setSearch, search }: Pick<Props, 'setSearch' | 'search
202
202
  }}
203
203
  />
204
204
  ) : (
205
- <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }} />
205
+ <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.05rem' }} />
206
206
  )}
207
207
  {t('common.currency')}
208
208
  <span>{Object.keys(currencies).find((x) => currencies[x] === search!.currency_id)}</span>
@@ -260,7 +260,7 @@ function SearchCustomers({ setSearch, search }: Pick<Props, 'setSearch' | 'searc
260
260
  <Button className="option-btn" variant="text">
261
261
  {search!.customer_id ? (
262
262
  <Close
263
- sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }}
263
+ sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.05rem' }}
264
264
  onClick={(e) => {
265
265
  e.stopPropagation();
266
266
  setSearch({
@@ -270,7 +270,7 @@ function SearchCustomers({ setSearch, search }: Pick<Props, 'setSearch' | 'searc
270
270
  }}
271
271
  />
272
272
  ) : (
273
- <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }} />
273
+ <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.05rem' }} />
274
274
  )}
275
275
  {t('common.customer')}
276
276
  <span>{customers.find((x) => x.id === search!.customer_id)?.name}</span>
@@ -373,7 +373,7 @@ function SearchProducts({ setSearch, search }: Pick<Props, 'setSearch' | 'search
373
373
  }}>
374
374
  {display ? (
375
375
  <Close
376
- sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }}
376
+ sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.05rem' }}
377
377
  onClick={(e) => {
378
378
  e.stopPropagation();
379
379
  setSearch({
@@ -385,7 +385,7 @@ function SearchProducts({ setSearch, search }: Pick<Props, 'setSearch' | 'search
385
385
  }}
386
386
  />
387
387
  ) : (
388
- <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }} />
388
+ <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.05rem' }} />
389
389
  )}
390
390
  {t('admin.subscription.product')}
391
391
  <span>{display}</span>
@@ -424,7 +424,7 @@ function SearchDonation({ donation = [], search, setSearch }: Pick<Props, 'donat
424
424
  <Button className="option-btn" variant="text">
425
425
  {search!.donation ? (
426
426
  <Close
427
- sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }}
427
+ sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.05rem' }}
428
428
  onClick={(e) => {
429
429
  e.stopPropagation();
430
430
  setSearch({
@@ -434,7 +434,7 @@ function SearchDonation({ donation = [], search, setSearch }: Pick<Props, 'donat
434
434
  }}
435
435
  />
436
436
  ) : (
437
- <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }} />
437
+ <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.05rem' }} />
438
438
  )}
439
439
  {t('common.donation')}
440
440
  <span>{search!.donation}</span>
@@ -20,6 +20,7 @@ const Root = styled(Dashboard)<{ padding: string }>`
20
20
  margin-right: 24px;
21
21
  min-height: 32px;
22
22
  min-width: auto;
23
+ font-size: 0.875rem;
23
24
  }
24
25
 
25
26
  .MuiTabs-root {
@@ -39,7 +39,7 @@ export default function ProductSelect({ mode: initialMode, hasSelected, onSelect
39
39
 
40
40
  const items = (callback?: any) =>
41
41
  filterProducts(products, hasSelected).map((product) => [
42
- <ListSubheader key={product.id} sx={{ fontSize: '1rem', color: 'text.secondary', lineHeight: '2.5rem' }}>
42
+ <ListSubheader key={product.id} sx={{ fontSize: '0.875rem', color: 'text.secondary', lineHeight: '2.1875rem' }}>
43
43
  <Stack direction="row" alignItems="center" spacing={0.5}>
44
44
  {product.images[0] ? (
45
45
  <Avatar src={product.images[0]} alt={product.name} variant="square" sx={size} />
@@ -92,7 +92,9 @@ export default function CurrencySelect({
92
92
  disabled={disabled}
93
93
  onClose={() => setMode(initialMode)}>
94
94
  {extraCurrencies.map((method) => [
95
- <ListSubheader key={method.id} sx={{ fontSize: '1rem', color: 'text.secondary', lineHeight: '2.5rem' }}>
95
+ <ListSubheader
96
+ key={method.id}
97
+ sx={{ fontSize: '0.875rem', color: 'text.secondary', lineHeight: '2.1875rem' }}>
96
98
  {method.name}
97
99
  </ListSubheader>,
98
100
  ...method.payment_currencies.map((currency) => (
@@ -425,7 +425,7 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
425
425
  <MenuItem value="month_2">{t('common.custom')}</MenuItem>
426
426
  </Select>
427
427
  {get(errors, getFieldName('recurring.interval_config'))?.message && (
428
- <Typography color="error" sx={{ fontSize: '0.75rem', mt: 0.5, ml: 1.75 }}>
428
+ <Typography color="error" sx={{ fontSize: '0.65625rem', mt: 0.5, ml: 1.75 }}>
429
429
  {/* @ts-ignore */}
430
430
  {get(errors, getFieldName('recurring.interval_config')).message}
431
431
  </Typography>
@@ -23,7 +23,7 @@ export default function SectionHeader(props: Props) {
23
23
  sx={{
24
24
  fontSize: {
25
25
  xs: '18px',
26
- md: '1.25rem',
26
+ md: '1.09375rem',
27
27
  },
28
28
  }}
29
29
  component="div">
@@ -219,6 +219,7 @@ export default function SubscriptionList({ customer_id, features, status }: List
219
219
  q: {
220
220
  'like-metadata': text,
221
221
  'like-description': text,
222
+ 'like-id': text,
222
223
  },
223
224
  pageSize: 100,
224
225
  page: 1,
@@ -62,6 +62,7 @@ export default function Uploader({
62
62
  }}
63
63
  coreProps={{
64
64
  restrictions: {
65
+ // @ts-ignore
65
66
  allowedFileExts,
66
67
  maxFileSize,
67
68
  maxNumberOfFiles,
package/src/global.css CHANGED
@@ -2,7 +2,6 @@ html,
2
2
  body {
3
3
  padding: 0;
4
4
  margin: 0;
5
- font-size: 14px;
6
5
  }
7
6
 
8
7
  a:has(> div) {
@@ -11,8 +10,8 @@ a:has(> div) {
11
10
 
12
11
  .MuiButton-sizeSmall {
13
12
  font-weight: 500;
14
- font-size: 1rem;
15
- line-height: 1.5;
13
+ font-size: 0.875rem;
14
+ line-height: 1.3125rem;
16
15
  border-color: #ccc;
17
16
  }
18
17
 
@@ -21,6 +20,7 @@ a:has(> div) {
21
20
  margin-right: 24px;
22
21
  min-height: 32px;
23
22
  min-width: auto;
23
+ font-size: 0.875rem;
24
24
  }
25
25
 
26
26
  .MuiTabs-root {
@@ -53,7 +53,7 @@ a:has(> div) {
53
53
  }
54
54
 
55
55
  .MuiTableCell-root {
56
- font-size: 1rem !important;
56
+ font-size: 0.875rem !important;
57
57
  padding-top: 8px;
58
58
  padding-bottom: 8px;
59
59
  padding-right: 24px;
package/src/libs/util.ts CHANGED
@@ -3,12 +3,14 @@
3
3
  /* eslint-disable @typescript-eslint/indent */
4
4
  import { formatCheckoutHeadlines, formatPrice, getPrefix, getPriceCurrencyOptions } from '@blocklet/payment-react';
5
5
  import type {
6
+ ChainType,
6
7
  LineItem,
7
8
  PriceRecurring,
8
9
  TInvoiceExpanded,
9
10
  TLineItemExpanded,
10
11
  TPaymentCurrency,
11
12
  TPaymentLinkExpanded,
13
+ TPaymentMethod,
12
14
  TPaymentMethodExpanded,
13
15
  TPrice,
14
16
  TProductExpanded,
@@ -364,3 +366,14 @@ export function getAppInfo(address: string): { name: string; avatar: string; typ
364
366
  }
365
367
  return null;
366
368
  }
369
+
370
+ export function getTokenBalanceLink(method: TPaymentMethod, address: string) {
371
+ const explorerHost = (method?.settings?.[method?.type as ChainType] as any)?.explorer_host || '';
372
+ if (method.type === 'arcblock' && address) {
373
+ return joinURL(explorerHost, 'accounts', address, 'tokens');
374
+ }
375
+ if (['ethereum', 'base'].includes(method.type) && address) {
376
+ return joinURL(explorerHost, 'address', address);
377
+ }
378
+ return '';
379
+ }
@@ -77,7 +77,7 @@ export default function WebhookDetail(props: { id: string }) {
77
77
  title={
78
78
  <ul style={{ padding: 0, margin: 0 }}>
79
79
  {data.enabled_events.map((x) => (
80
- <li key={x} style={{ fontSize: '0.9rem' }}>
80
+ <li key={x} style={{ fontSize: '0.7875rem' }}>
81
81
  {x}
82
82
  </li>
83
83
  ))}
@@ -298,7 +298,7 @@ export default function Overview() {
298
298
  sx={{ width: 36, height: 36 }}
299
299
  />
300
300
  <Box flex={1}>
301
- <Typography variant="h5" component="div" sx={{ fontSize: '2rem' }}>
301
+ <Typography variant="h5" component="div" sx={{ fontSize: '1.75rem' }}>
302
302
  {formatBNStr(
303
303
  summary.data?.balances?.[currencyId] as string,
304
304
  currencies[currencyId]?.decimal as number
@@ -338,7 +338,7 @@ export default function Overview() {
338
338
  variant="outlined"
339
339
  sx={{ padding: 1, width: 0.48 }}>
340
340
  <Box>
341
- <Typography component="div" sx={{ fontSize: '2rem' }}>
341
+ <Typography component="div" sx={{ fontSize: '1.75rem' }}>
342
342
  {metric.count}
343
343
  </Typography>
344
344
  <Typography sx={{ fontSize: 14 }} color="text.secondary">
@@ -366,7 +366,7 @@ export default function Overview() {
366
366
  variant="outlined"
367
367
  sx={{ padding: 1, width: 0.48 }}>
368
368
  <Box>
369
- <Typography component="div" sx={{ fontSize: '2rem' }}>
369
+ <Typography component="div" sx={{ fontSize: '1.75rem' }}>
370
370
  {metric.count}
371
371
  </Typography>
372
372
  <Typography sx={{ fontSize: 14 }} color="text.secondary">
@@ -139,7 +139,7 @@ export default function PaymentIntentDetail(props: { id: string }) {
139
139
  sx={{ width: '52px', height: '52px', borderRadius: 'var(--radius-s, 4px)' }}
140
140
  />
141
141
  <Stack direction="column" alignItems="flex-start" justifyContent="space-around">
142
- <Amount amount={received} sx={{ my: 0, fontSize: '2rem', lineHeight: '32px' }} />
142
+ <Amount amount={received} sx={{ my: 0, fontSize: '1.75rem', lineHeight: '32px' }} />
143
143
  <Copyable text={props.id} />
144
144
  </Stack>
145
145
  </Stack>
@@ -159,7 +159,7 @@ export default function PayoutDetail(props: { id: string }) {
159
159
  sx={{ width: '52px', height: '52px', borderRadius: 'var(--radius-s, 4px)' }}
160
160
  />
161
161
  <Stack direction="column" alignItems="flex-start" justifyContent="space-around">
162
- <Amount amount={total} sx={{ my: 0, fontSize: '2rem', lineHeight: '32px' }} />
162
+ <Amount amount={total} sx={{ my: 0, fontSize: '1.75rem', lineHeight: '32px' }} />
163
163
  <Copyable text={props.id} />
164
164
  </Stack>
165
165
  </Stack>
@@ -137,7 +137,7 @@ export default function RefundDetail(props: { id: string }) {
137
137
  sx={{ width: '52px', height: '52px', borderRadius: 'var(--radius-s, 4px)' }}
138
138
  />
139
139
  <Stack direction="column" alignItems="flex-start" justifyContent="space-around">
140
- <Amount amount={amount} sx={{ my: 0, fontSize: '2rem', lineHeight: '32px' }} />
140
+ <Amount amount={amount} sx={{ my: 0, fontSize: '1.75rem', lineHeight: '32px' }} />
141
141
  <Copyable text={props.id} />
142
142
  </Stack>
143
143
  </Stack>
@@ -389,7 +389,7 @@ export default function ProductDetail(props: { id: string }) {
389
389
  sx={{
390
390
  fontSize: {
391
391
  xs: '18px',
392
- md: '1.25rem',
392
+ md: '1.09375rem',
393
393
  },
394
394
  }}>
395
395
  {t('admin.product.cross_sell.title')}
@@ -113,7 +113,7 @@ export default function PayoutDetail() {
113
113
  sx={{ width: '52px', height: '52px', borderRadius: 'var(--radius-s, 4px)' }}
114
114
  />
115
115
  <Stack direction="column" alignItems="flex-start" justifyContent="space-around">
116
- <Amount amount={total} sx={{ my: 0, fontSize: '2rem', lineHeight: '32px' }} />
116
+ <Amount amount={total} sx={{ my: 0, fontSize: '1.75rem', lineHeight: '32px' }} />
117
117
  </Stack>
118
118
  </Stack>
119
119
  </Stack>
@@ -28,14 +28,14 @@ import {
28
28
  } from '@blocklet/payment-react';
29
29
  import { joinURL } from 'ufo';
30
30
  import type { TSubscriptionExpanded } from '@blocklet/payment-types';
31
- import { ArrowBackOutlined } from '@mui/icons-material';
31
+ import { ArrowBackOutlined, ArrowForwardOutlined } from '@mui/icons-material';
32
32
  import { BN, fromUnitToToken } from '@ocap/util';
33
33
  import RechargeList from '../../components/invoice/recharge';
34
34
  import SubscriptionDescription from '../../components/subscription/description';
35
35
  import InfoRow from '../../components/info-row';
36
36
  import Currency from '../../components/currency';
37
37
  import SubscriptionMetrics from '../../components/subscription/metrics';
38
- import { goBackOrFallback } from '../../libs/util';
38
+ import { getTokenBalanceLink, goBackOrFallback } from '../../libs/util';
39
39
  import CustomerLink from '../../components/customer/link';
40
40
  import { useSessionContext } from '../../contexts/session';
41
41
  import { formatSmartDuration, TimeUnit } from '../../libs/dayjs';
@@ -237,6 +237,8 @@ export default function RechargePage() {
237
237
  });
238
238
  };
239
239
 
240
+ const balanceLink = getTokenBalanceLink(paymentMethod!, payerValue?.paymentAddress || receiveAddress);
241
+
240
242
  return (
241
243
  <Root>
242
244
  <Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ position: 'relative' }}>
@@ -336,16 +338,43 @@ export default function RechargePage() {
336
338
  </BalanceCard>
337
339
 
338
340
  <BalanceCard
341
+ onClick={() => balanceLink && window.open(balanceLink, '_blank')}
339
342
  sx={{
340
343
  background: 'var(--tags-tag-orange-bg, #B7FEE3)',
341
344
  color: 'var(--tags-tag-orange-text, #007C52)',
342
345
  borderRadius: 'var(--radius-m, 8px)',
343
346
  border: 'none',
347
+
348
+ transition: 'all 0.2s ease-in-out',
349
+ position: 'relative',
350
+ cursor: balanceLink ? 'pointer' : 'default',
351
+ '&:hover': balanceLink
352
+ ? {
353
+ '& .MuiSvgIcon-root': {
354
+ opacity: 1,
355
+ transform: 'translateX(0)',
356
+ },
357
+ }
358
+ : undefined,
344
359
  }}>
345
- <Typography variant="subtitle1">{t('admin.customer.summary.balance')}</Typography>
346
- <Typography variant="h4">
347
- {currentBalance} {subscription.paymentCurrency.symbol}
348
- </Typography>
360
+ <Stack direction="row" alignItems="center" spacing={1}>
361
+ <Stack flex={1}>
362
+ <Typography variant="subtitle1">{t('admin.customer.summary.balance')}</Typography>
363
+ <Typography variant="h4">
364
+ {currentBalance} {subscription.paymentCurrency.symbol}
365
+ </Typography>
366
+ </Stack>
367
+ {balanceLink && (
368
+ <ArrowForwardOutlined
369
+ sx={{
370
+ opacity: 0,
371
+ transform: 'translateX(-10px)',
372
+ transition: 'all 0.2s ease-in-out',
373
+ color: 'inherit',
374
+ }}
375
+ />
376
+ )}
377
+ </Stack>
349
378
  </BalanceCard>
350
379
 
351
380
  <Paper elevation={0} sx={{ mb: 2, mt: 2, backgroundColor: 'background.default' }}>
@@ -6,6 +6,7 @@ import Toast from '@arcblock/ux/lib/Toast';
6
6
  import {
7
7
  AddressForm,
8
8
  CurrencySelector,
9
+ LoadingButton,
9
10
  PaymentSummary,
10
11
  StripeForm,
11
12
  api,
@@ -20,7 +21,6 @@ import {
20
21
  } from '@blocklet/payment-react';
21
22
  import type { TCustomer, TPaymentCurrency, TPaymentMethod, TSubscriptionExpanded } from '@blocklet/payment-types';
22
23
  import { ArrowBackOutlined } from '@mui/icons-material';
23
- import { LoadingButton } from '@mui/lab';
24
24
  import { Alert, CircularProgress, Stack, Typography } from '@mui/material';
25
25
  import { styled } from '@mui/system';
26
26
  import { useRequest, useSetState } from 'ahooks';
@@ -270,7 +270,13 @@ function CustomerSubscriptionChangePayment({ subscription, customer, onComplete
270
270
  {state.paying ? t('payment.checkout.processing') : t('payment.customer.changePayment.submit')}
271
271
  </LoadingButton>
272
272
  <Typography
273
- sx={{ mt: 1, color: 'text.secondary', fontSize: '0.9rem', lineHeight: '1.1rem', textAlign: 'center' }}>
273
+ sx={{
274
+ mt: 1,
275
+ color: 'text.secondary',
276
+ fontSize: '0.7875rem',
277
+ lineHeight: '0.9625rem',
278
+ textAlign: 'center',
279
+ }}>
274
280
  {t('payment.customer.changePayment.confirm', {
275
281
  payee,
276
282
  symbol: findCurrency(settings.paymentMethods, selectedCurrencyId)?.symbol,
@@ -2,6 +2,7 @@
2
2
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
3
3
  import Toast from '@arcblock/ux/lib/Toast';
4
4
  import {
5
+ LoadingButton,
5
6
  PricingTable,
6
7
  api,
7
8
  formatBNStr,
@@ -12,7 +13,6 @@ import {
12
13
  } from '@blocklet/payment-react';
13
14
  import type { TLineItemExpanded, TPricingTableExpanded, TSubscriptionExpanded } from '@blocklet/payment-types';
14
15
  import { ArrowBackOutlined } from '@mui/icons-material';
15
- import { LoadingButton } from '@mui/lab';
16
16
  import { Alert, CircularProgress, Divider, Stack, Typography } from '@mui/material';
17
17
  import { useRequest, useSetState } from 'ahooks';
18
18
  import { useRef } from 'react';
@@ -269,7 +269,7 @@ export default function DonationList() {
269
269
 
270
270
  return (
271
271
  <>
272
- <Stack direction="row" alignItems="center" gap={1} flexWrap="wrap" mb={-1}>
272
+ <Stack direction="row" alignItems="center" gap={1} flexWrap="wrap">
273
273
  <Typography variant="h6">{t('admin.donate.intro')}</Typography>
274
274
  <Button variant="text" size="small" onClick={() => setShowExample(true)} sx={{ color: 'text.link' }}>
275
275
  {t('admin.donate.usage.viewExample')}
@@ -3,6 +3,50 @@ import { Box, Typography, Button, TextField, Stack, Paper, Divider } from '@mui/
3
3
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
4
4
  import type { TSetting } from '@blocklet/payment-types';
5
5
 
6
+ function PreviewAvatars({ count }: { count: number }) {
7
+ return (
8
+ <Stack flexDirection="row" justifyContent="center" alignItems="center">
9
+ {/* Avatar Group */}
10
+ <Box sx={{ display: 'flex', position: 'relative' }}>
11
+ {Array(Math.min(count, 5))
12
+ .fill(0)
13
+ .map((_, i) => (
14
+ <Box
15
+ // eslint-disable-next-line react/no-array-index-key
16
+ key={i}
17
+ sx={{
18
+ width: '24px',
19
+ height: '24px',
20
+ borderRadius: '50%',
21
+ bgcolor: '#e0e0e0',
22
+ border: '2px solid #fff',
23
+ position: 'relative',
24
+ marginLeft: i === 0 ? 0 : '-8px',
25
+ zIndex: count - i,
26
+ }}
27
+ />
28
+ ))}
29
+ </Box>
30
+
31
+ {/* Counter Box */}
32
+ <Box
33
+ sx={{
34
+ fontSize: '14px',
35
+ color: 'text.secondary',
36
+ pl: 1.5,
37
+ pr: 1,
38
+ ml: -1,
39
+ borderRadius: '8px',
40
+ backgroundColor: '#f4f4f5',
41
+ height: '24px',
42
+ display: 'flex',
43
+ alignItems: 'center',
44
+ }}>
45
+ {`${count} supporter${count > 1 ? 's' : ''} (XX ABT)`}
46
+ </Box>
47
+ </Stack>
48
+ );
49
+ }
6
50
  export default function DonationPreview({ config }: { config: TSetting['settings'] }) {
7
51
  const { t } = useLocaleContext();
8
52
  const hasPresets = config.settings.amount.presets?.length > 0;
@@ -41,43 +85,12 @@ export default function DonationPreview({ config }: { config: TSetting['settings
41
85
  {t('admin.donate.btn.preview')}
42
86
  </Typography>
43
87
  <Stack spacing={2} alignItems="center">
44
- <Button variant="contained" color="primary">
88
+ <Button variant="outlined" color="primary">
45
89
  {config.settings.btnText}
46
90
  </Button>
47
-
91
+ <PreviewAvatars count={3} />
48
92
  <Box sx={{ width: '100%', maxWidth: 300 }}>
49
- <Typography variant="caption" display="block" gutterBottom color="text.secondary" mb={1} textAlign="center">
50
- total XX ABT
51
- </Typography>
52
- {config.settings.historyType === 'avatar' ? (
53
- <Box
54
- sx={{
55
- height: 40,
56
- position: 'relative',
57
- display: 'flex',
58
- alignItems: 'center',
59
- justifyContent: 'center',
60
- }}>
61
- {Array(5)
62
- .fill(0)
63
- .map((_, i) => (
64
- <Box
65
- // eslint-disable-next-line react/no-array-index-key
66
- key={i}
67
- sx={{
68
- width: 32,
69
- height: 32,
70
- borderRadius: '50%',
71
- bgcolor: '#e0e0e0',
72
- position: 'absolute',
73
- left: `calc(50% - 16px + ${i * 24}px - ${2 * 24}px)`,
74
- opacity: 1 - i * 0.1,
75
- border: '2px solid #fff',
76
- }}
77
- />
78
- ))}
79
- </Box>
80
- ) : (
93
+ {config.settings.historyType === 'table' && (
81
94
  <Box
82
95
  sx={{
83
96
  borderRadius: 1,
@@ -96,30 +109,38 @@ export default function DonationPreview({ config }: { config: TSetting['settings
96
109
  sx={{
97
110
  display: 'flex',
98
111
  justifyContent: 'center',
99
- gap: 2,
112
+ alignItems: 'center',
113
+ gap: 1,
100
114
  opacity: 1 - i * 0.2,
101
115
  width: '100%',
102
116
  maxWidth: 240,
103
117
  }}>
118
+ <Box display="flex" alignItems="center" gap={0.5} width="75%">
119
+ <Box
120
+ // eslint-disable-next-line react/no-array-index-key
121
+ key={i}
122
+ sx={{
123
+ width: '16px',
124
+ height: '16px',
125
+ borderRadius: '50%',
126
+ bgcolor: '#e0e0e0',
127
+ border: '2px solid #fff',
128
+ position: 'relative',
129
+ }}
130
+ />
131
+ <Box
132
+ sx={{
133
+ width: '100%',
134
+ height: 8,
135
+ borderRadius: 1,
136
+ bgcolor: '#e0e0e0',
137
+ }}
138
+ />
139
+ </Box>
140
+
104
141
  <Box
105
142
  sx={{
106
- width: '30%',
107
- height: 8,
108
- borderRadius: 1,
109
- bgcolor: '#e0e0e0',
110
- }}
111
- />
112
- <Box
113
- sx={{
114
- width: '20%',
115
- height: 8,
116
- borderRadius: 1,
117
- bgcolor: '#e0e0e0',
118
- }}
119
- />
120
- <Box
121
- sx={{
122
- width: '15%',
143
+ width: '25%',
123
144
  height: 8,
124
145
  borderRadius: 1,
125
146
  bgcolor: '#e0e0e0',