payment-kit 1.18.38 → 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.
Files changed (41) hide show
  1. package/api/src/integrations/stripe/handlers/invoice.ts +22 -0
  2. package/api/src/integrations/stripe/handlers/payment-intent.ts +9 -1
  3. package/api/src/integrations/stripe/handlers/subscription.ts +137 -1
  4. package/api/src/libs/subscription.ts +107 -97
  5. package/api/src/queues/payment.ts +4 -0
  6. package/api/src/routes/checkout-sessions.ts +3 -1
  7. package/api/src/routes/subscriptions.ts +27 -18
  8. package/blocklet.yml +1 -1
  9. package/package.json +19 -19
  10. package/scripts/sdk.js +27 -1
  11. package/src/components/customer/link.tsx +6 -0
  12. package/src/components/info-card.tsx +2 -2
  13. package/src/components/info-metric.tsx +1 -1
  14. package/src/components/metadata/list.tsx +4 -2
  15. package/src/components/subscription/description.tsx +8 -6
  16. package/src/components/subscription/portal/actions.tsx +224 -45
  17. package/src/components/subscription/portal/list.tsx +153 -74
  18. package/src/components/subscription/status.tsx +17 -5
  19. package/src/locales/en.tsx +12 -7
  20. package/src/locales/zh.tsx +6 -2
  21. package/src/pages/admin/billing/invoices/detail.tsx +1 -5
  22. package/src/pages/admin/billing/subscriptions/detail.tsx +1 -5
  23. package/src/pages/admin/customers/customers/detail.tsx +1 -5
  24. package/src/pages/admin/developers/events/detail.tsx +1 -5
  25. package/src/pages/admin/developers/index.tsx +1 -1
  26. package/src/pages/admin/developers/webhooks/detail.tsx +1 -3
  27. package/src/pages/admin/overview.tsx +4 -4
  28. package/src/pages/admin/payments/intents/detail.tsx +5 -6
  29. package/src/pages/admin/payments/payouts/detail.tsx +1 -5
  30. package/src/pages/admin/payments/refunds/detail.tsx +1 -5
  31. package/src/pages/admin/products/links/detail.tsx +1 -5
  32. package/src/pages/admin/products/prices/detail.tsx +1 -5
  33. package/src/pages/admin/products/pricing-tables/detail.tsx +1 -5
  34. package/src/pages/admin/products/products/detail.tsx +1 -5
  35. package/src/pages/admin/settings/payment-methods/index.tsx +1 -1
  36. package/src/pages/customer/index.tsx +67 -138
  37. package/src/pages/customer/payout/detail.tsx +37 -49
  38. package/src/pages/customer/subscription/change-payment.tsx +2 -35
  39. package/src/pages/customer/subscription/detail.tsx +5 -6
  40. package/src/pages/integrations/donations/index.tsx +1 -1
  41. package/src/pages/integrations/overview.tsx +1 -1
@@ -161,11 +161,7 @@ export default function PriceDetail(props: { id: string }) {
161
161
  sm: 'column',
162
162
  md: 'row',
163
163
  },
164
- alignItems: {
165
- xs: 'flex-start',
166
- sm: 'flex-start',
167
- md: 'center',
168
- },
164
+ alignItems: 'flex-start',
169
165
  gap: {
170
166
  xs: 1,
171
167
  sm: 1,
@@ -157,11 +157,7 @@ export default function PricingTableDetail(props: { id: string }) {
157
157
  sm: 'column',
158
158
  md: 'row',
159
159
  },
160
- alignItems: {
161
- xs: 'flex-start',
162
- sm: 'flex-start',
163
- md: 'center',
164
- },
160
+ alignItems: 'flex-start',
165
161
  gap: {
166
162
  xs: 1,
167
163
  sm: 1,
@@ -197,11 +197,7 @@ export default function ProductDetail(props: { id: string }) {
197
197
  sm: 'column',
198
198
  md: 'row',
199
199
  },
200
- alignItems: {
201
- xs: 'flex-start',
202
- sm: 'flex-start',
203
- md: 'center',
204
- },
200
+ alignItems: 'flex-start',
205
201
  gap: {
206
202
  xs: 1,
207
203
  sm: 1,
@@ -421,7 +421,7 @@ export default function PaymentMethods() {
421
421
  {Object.keys(groups).map((x) => (
422
422
  <Box key={x} mt={3}>
423
423
  <Stack direction="row" alignItems="center" mb={1} flexWrap="wrap" gap={1}>
424
- <Typography variant="h6" sx={{ textTransform: 'uppercase' }}>
424
+ <Typography variant="subtitle2" sx={{ textTransform: 'uppercase' }}>
425
425
  {x}
426
426
  </Typography>
427
427
  </Stack>
@@ -29,6 +29,7 @@ import {
29
29
  Tooltip,
30
30
  Typography,
31
31
  Alert,
32
+ Divider,
32
33
  } from '@mui/material';
33
34
  import type { SelectChangeEvent } from '@mui/material/Select';
34
35
  import { styled } from '@mui/system';
@@ -58,7 +59,6 @@ const CurrencyCard = memo(
58
59
  label,
59
60
  data,
60
61
  currency,
61
- type,
62
62
  icon,
63
63
  }: {
64
64
  label: string;
@@ -72,21 +72,10 @@ const CurrencyCard = memo(
72
72
  payment_method_id: string;
73
73
  symbol: string;
74
74
  };
75
- type: 'balance' | 'spent' | 'stake' | 'refund' | 'due';
76
75
  }) => {
77
- const navigate = useNavigate();
78
- const { settings } = usePaymentContext();
79
- const method = settings?.paymentMethods?.find((m) => m.id === currency.payment_method_id);
80
- const { t } = useLocaleContext();
81
76
  const safeData = data || {};
82
77
  const value = formatBNStr(safeData[currency?.id], currency?.decimal, 6, true);
83
78
 
84
- const handleCardClick = () => {
85
- if (type === 'balance' && currency?.id) {
86
- navigate(`/customer/recharge/${currency.id}`);
87
- }
88
- };
89
-
90
79
  return (
91
80
  <Box
92
81
  sx={{
@@ -94,7 +83,7 @@ const CurrencyCard = memo(
94
83
  position: 'relative',
95
84
  height: '100%',
96
85
  display: 'flex',
97
- flexDirection: 'column',
86
+ flexDirection: 'row',
98
87
  justifyContent: 'space-between',
99
88
  containerType: 'inline-size',
100
89
  }}>
@@ -105,45 +94,9 @@ const CurrencyCard = memo(
105
94
  {icon}
106
95
  {label}
107
96
  </Typography>
108
- <Typography variant="h3" gutterBottom sx={{ color: 'text.primary', whiteSpace: 'nowrap' }}>
97
+ <Typography variant="body1" gutterBottom sx={{ color: 'text.primary', whiteSpace: 'nowrap' }}>
109
98
  {value} {currency.symbol}
110
99
  </Typography>
111
- {type === 'balance' && method?.type === 'arcblock' && (
112
- <Tooltip title={t('customer.recharge.rechargeTooltip')} arrow placement="top">
113
- <Box
114
- onClick={handleCardClick}
115
- sx={{
116
- position: 'absolute',
117
- top: 0,
118
- right: '12px',
119
- display: 'flex',
120
- alignItems: 'center',
121
- justifyContent: 'center',
122
- borderRadius: '50%',
123
- padding: '4px',
124
- zIndex: 1,
125
- cursor: 'pointer',
126
- color: 'text.secondary',
127
- '&:hover': {
128
- color: 'text.link',
129
- },
130
- '.recharge-title': {
131
- '@container (max-width: 230px)': {
132
- display: 'none',
133
- },
134
- '@container (min-width: 231px)': {
135
- display: 'inline-block',
136
- },
137
- },
138
- }}>
139
- <AddOutlined fontSize="small" />
140
-
141
- <Typography variant="body2" className="recharge-title">
142
- {t('customer.recharge.title')}
143
- </Typography>
144
- </Box>
145
- </Tooltip>
146
- )}
147
100
  </Box>
148
101
  );
149
102
  }
@@ -207,27 +160,6 @@ const isCardVisible = (type: string, config: any, data: any, currency: any, meth
207
160
  return config.alwaysShow || hasSummaryValue;
208
161
  };
209
162
 
210
- const getCardVisibility = (currency: any, data: any, method: any) => {
211
- return Object.entries(CARD_CONFIG).reduce(
212
- (acc, [type, config]) => {
213
- if (isCardVisible(type, config, data, currency, method)) {
214
- acc.visibleCards.push(type as CardType);
215
- }
216
- return acc;
217
- },
218
- { visibleCards: [] as CardType[] }
219
- );
220
- };
221
-
222
- // 计算最大卡片数量
223
- const calculateMaxCardCount = (currencies: any[], data: any, settings: any) => {
224
- return currencies.reduce((maxCount, currency) => {
225
- const method = settings?.paymentMethods?.find((m: any) => m.id === currency.payment_method_id);
226
- const { visibleCards } = getCardVisibility(currency, data, method);
227
- return Math.max(maxCount, visibleCards.length);
228
- }, 0);
229
- };
230
-
231
163
  const getCardIcon = (type: CardType) => {
232
164
  const iconMap = {
233
165
  balance: <AccountBalanceWalletOutlined color="success" fontSize="small" />,
@@ -327,6 +259,12 @@ export default function CustomerHome() {
327
259
  );
328
260
  }
329
261
 
262
+ const handleRecharge = (currency: any) => {
263
+ if (currency?.id) {
264
+ navigate(`/customer/recharge/${currency.id}`);
265
+ }
266
+ };
267
+
330
268
  const onToggleActive = (e: SelectChangeEvent) => {
331
269
  setSubscriptionLoading(true);
332
270
  setState({ onlyActive: e.target.value === 'active' });
@@ -339,7 +277,7 @@ export default function CustomerHome() {
339
277
  loadingCard || !hasSubscriptions ? null : (
340
278
  <Box className="base-card section section-subscription">
341
279
  <Box className="section-header">
342
- <Typography variant="h3">{t('admin.subscription.name')}</Typography>
280
+ <Typography variant="h3">{t('customer.subscription.title')}</Typography>
343
281
  <Stack direction="row" spacing={1} alignItems="center">
344
282
  <NotificationPreference />
345
283
  {subscriptionStatus && (
@@ -391,24 +329,28 @@ export default function CustomerHome() {
391
329
  </Box>
392
330
  );
393
331
 
394
- const maxCardCount = calculateMaxCardCount(currencies, data, settings);
395
-
396
- const responsiveColumns = {
397
- xs: Math.min(2, maxCardCount),
398
- sm: Math.min(3, maxCardCount),
399
- md: maxCardCount,
400
- };
401
-
402
332
  const SummaryCard = loadingCard ? (
403
333
  <SummaryCardSkeleton />
404
334
  ) : (
405
- <Box className="base-card section section-summary">
335
+ <Box className="base-card section section-summary" sx={{ containerType: 'inline-size' }}>
406
336
  {data?.summary && (
407
337
  <>
408
338
  <Box className="section-header">
409
339
  <Typography variant="h3">{t('admin.customer.summary.stats')}</Typography>
410
340
  </Box>
411
- <Stack gap={2} mt={2}>
341
+ <Stack
342
+ gap={2}
343
+ mt={2}
344
+ sx={{
345
+ display: 'grid',
346
+ gridTemplateColumns: {
347
+ xs: 'repeat(1, 1fr)',
348
+ md: 'repeat(2, 1fr)',
349
+ },
350
+ '@container (max-width: 600px)': {
351
+ gridTemplateColumns: 'repeat(1, 1fr)',
352
+ },
353
+ }}>
412
354
  {currencies.map((c) => {
413
355
  const method = settings?.paymentMethods?.find((m) => m.id === c.payment_method_id);
414
356
  if (method?.type !== 'arcblock') {
@@ -418,47 +360,45 @@ export default function CustomerHome() {
418
360
  <Stack
419
361
  key={c.id}
420
362
  sx={{
421
- pb: 2,
422
- borderBottom: '1px solid',
363
+ borderRadius: 1,
364
+ p: 2,
365
+ gap: 2,
366
+ border: '1px solid',
423
367
  borderColor: 'grey.100',
424
- '&:last-child': { borderBottom: 'none', pb: 0 },
368
+ boxShadow: 1,
425
369
  }}>
426
- <Box alignItems="center" display="flex" gap={1}>
427
- <Avatar src={c?.logo} alt={c?.symbol} sx={{ width: 18, height: 18 }} />
428
- <Typography
429
- variant="h5"
430
- component="div"
431
- sx={{ fontSize: '16px', color: 'text.primary', fontWeight: '500' }}>
432
- {c?.symbol}
433
- </Typography>
434
- <Typography sx={{ fontSize: 12 }} color="text.lighter">
435
- {c?.methodName}
436
- </Typography>
437
- </Box>
370
+ <Stack flexDirection="row" justifyContent="space-between">
371
+ <Box alignItems="center" display="flex" gap={1}>
372
+ <Avatar src={c?.logo} alt={c?.symbol} sx={{ width: 18, height: 18 }} />
373
+ <Typography
374
+ variant="h5"
375
+ component="div"
376
+ sx={{ fontSize: '16px', color: 'text.primary', fontWeight: '500' }}>
377
+ {c?.symbol}
378
+ </Typography>
379
+ <Typography sx={{ fontSize: 12 }} color="text.lighter">
380
+ {c?.methodName}
381
+ </Typography>
382
+ </Box>
383
+
384
+ {method?.type === 'arcblock' && (
385
+ <Tooltip title={t('customer.recharge.rechargeTooltip')} arrow placement="top">
386
+ <Button onClick={() => handleRecharge(c)} variant="text" color="primary" size="small">
387
+ <AddOutlined fontSize="small" />
388
+ <Typography variant="body2" className="recharge-title">
389
+ {t('customer.recharge.title')}
390
+ </Typography>
391
+ </Button>
392
+ </Tooltip>
393
+ )}
394
+ </Stack>
395
+ <Divider />
396
+
438
397
  <Stack
439
398
  className="section-body"
440
- flexDirection="row"
441
399
  sx={{
442
- gap: 3,
400
+ gap: 1,
443
401
  mt: 1.5,
444
- flexWrap: 'wrap',
445
- position: 'relative',
446
- display: 'grid',
447
- gridTemplateColumns: {
448
- xs: `repeat(${responsiveColumns.xs}, 1fr)`,
449
- sm: `repeat(${responsiveColumns.sm}, 1fr)`,
450
- md: `repeat(${responsiveColumns.md}, 1fr)`,
451
- },
452
- '&::after': {
453
- content: '""',
454
- position: 'absolute',
455
- right: 0,
456
- top: 0,
457
- bottom: 0,
458
- width: '1px',
459
- backgroundColor: 'background.paper',
460
- zIndex: 1,
461
- },
462
402
  }}>
463
403
  {/* 使用配置渲染卡片 */}
464
404
  {Object.entries(CARD_CONFIG).map(([type, config]) => {
@@ -472,28 +412,11 @@ export default function CustomerHome() {
472
412
  className="card-item"
473
413
  sx={{
474
414
  position: 'relative',
475
- '&::after': {
476
- content: '""',
477
- position: 'absolute',
478
- right: 0,
479
- top: 0,
480
- bottom: 0,
481
- width: '1px',
482
- backgroundColor: 'grey.100',
483
- zIndex: 1,
484
- },
485
- '&:has(+ .placeholder)::after': {
486
- display: 'none',
487
- },
488
- '&:last-child::after': {
489
- display: 'none',
490
- },
491
415
  }}>
492
416
  <CurrencyCard
493
417
  label={t(`admin.customer.summary.${type}`)}
494
418
  data={data?.summary?.[config.key] || emptyObject}
495
419
  currency={c}
496
- type={type as CardType}
497
420
  icon={getCardIcon(type as CardType)}
498
421
  />
499
422
  </Box>
@@ -601,8 +524,11 @@ export default function CustomerHome() {
601
524
  )}
602
525
  <Root>
603
526
  {SummaryCard}
527
+ <Divider />
604
528
  {SubscriptionCard}
529
+ <Divider />
605
530
  {InvoiceCard}
531
+ <Divider />
606
532
  {RevenueCard}
607
533
  {/* {DetailCard} */}
608
534
  </Root>
@@ -623,6 +549,11 @@ const Content = styled(Stack)`
623
549
  .section {
624
550
  height: fit-content;
625
551
  }
552
+ .base-card {
553
+ border: none;
554
+ padding: 0;
555
+ box-shadow: none;
556
+ }
626
557
  @media (max-width: ${({ theme }) => theme.breakpoints.values.md}px) {
627
558
  padding: 0px;
628
559
  .base-card {
@@ -634,18 +565,16 @@ const Content = styled(Stack)`
634
565
 
635
566
  const Root = styled(Stack)`
636
567
  gap: 24px;
568
+ display: flex;
569
+ flex-direction: column;
637
570
  @media (max-width: ${({ theme }) => theme.breakpoints.values.xl}px) {
638
571
  padding: 0px;
639
- gap: 0;
640
572
  .base-card {
641
573
  border: none;
642
574
  box-shadow: none;
643
575
  padding-left: 0;
644
576
  padding-right: 0;
645
577
  }
646
- .section-header h3 {
647
- font-size: 18px;
648
- }
649
578
  .section-summary {
650
579
  padding-top: 0;
651
580
  }
@@ -7,7 +7,6 @@ import {
7
7
  api,
8
8
  formatBNStr,
9
9
  formatTime,
10
- getCustomerAvatar,
11
10
  getPayoutStatusColor,
12
11
  getUserProfileLink,
13
12
  useMobile,
@@ -19,13 +18,11 @@ import { styled } from '@mui/system';
19
18
  import { useRequest } from 'ahooks';
20
19
 
21
20
  import { useParams } from 'react-router-dom';
22
- import DID from '@arcblock/ux/lib/DID';
23
21
  import InfoMetric from '../../../components/info-metric';
24
22
  import InfoRow from '../../../components/info-row';
25
23
  import SectionHeader from '../../../components/section/header';
26
24
  import { goBackOrFallback } from '../../../libs/util';
27
25
  import CustomerLink from '../../../components/customer/link';
28
- import InfoCard from '../../../components/info-card';
29
26
  import InfoRowGroup from '../../../components/info-row-group';
30
27
 
31
28
  const fetchData = (
@@ -134,11 +131,7 @@ export default function PayoutDetail() {
134
131
  sm: 'column',
135
132
  md: 'row',
136
133
  },
137
- alignItems: {
138
- xs: 'flex-start',
139
- sm: 'flex-start',
140
- md: 'center',
141
- },
134
+ alignItems: 'flex-start',
142
135
  gap: {
143
136
  xs: 1,
144
137
  sm: 1,
@@ -153,47 +146,42 @@ export default function PayoutDetail() {
153
146
  <InfoMetric
154
147
  label={t('customer.payout.payer')}
155
148
  value={
156
- <InfoCard
157
- logo={getCustomerAvatar(
158
- paymentIntent?.customer?.did,
159
- paymentIntent?.customer?.updated_at
160
- ? new Date(paymentIntent?.customer?.updated_at).toISOString()
161
- : '',
162
- 48
163
- )}
164
- logoName={paymentIntent?.customer?.metadata?.anonymous ? '' : paymentIntent?.customer?.name}
165
- name={
166
- <Typography
167
- variant="subtitle2"
168
- sx={{
169
- ...(isAnonymousPayer
170
- ? {}
171
- : {
172
- cursor: 'pointer',
173
- '&:hover': {
174
- color: 'text.link',
175
- },
176
- }),
177
- }}
178
- onClick={() => {
179
- if (isAnonymousPayer) {
180
- return;
181
- }
182
- const url = getUserProfileLink(paymentIntent?.customer?.did, locale);
183
- window.open(url, '_blank');
184
- }}>
185
- {paymentIntent?.customer?.name}
186
- {paymentIntent?.customer?.email ? ` (${paymentIntent?.customer?.email})` : ''}
187
- </Typography>
188
- }
189
- description={
190
- <DID
191
- did={paymentIntent?.customer?.did}
192
- {...(isMobile ? { responsive: false, compact: true } : {})}
193
- />
194
- }
195
- size={40}
196
- variant="rounded"
149
+ <CustomerLink
150
+ customer={paymentIntent.customer}
151
+ cardProps={{
152
+ onAvatarClick: () => {
153
+ if (isAnonymousPayer) {
154
+ return;
155
+ }
156
+ window.open(getUserProfileLink(paymentIntent?.customer?.did, locale), '_blank');
157
+ },
158
+ renderName: (user) => {
159
+ return (
160
+ <Typography
161
+ variant="subtitle1"
162
+ sx={{
163
+ ...(isAnonymousPayer
164
+ ? {}
165
+ : {
166
+ cursor: 'pointer',
167
+ '&:hover': {
168
+ color: 'text.link',
169
+ },
170
+ }),
171
+ }}
172
+ onClick={() => {
173
+ if (isAnonymousPayer) {
174
+ return;
175
+ }
176
+ const url = getUserProfileLink(user?.did, locale);
177
+ window.open(url, '_blank');
178
+ }}>
179
+ {user.fullName}
180
+ </Typography>
181
+ );
182
+ },
183
+ }}
184
+ linked={false}
197
185
  />
198
186
  }
199
187
  divider
@@ -22,7 +22,6 @@ import {
22
22
  import type { TCustomer, TPaymentCurrency, TPaymentMethod, TSubscriptionExpanded } from '@blocklet/payment-types';
23
23
  import { ArrowBackOutlined } from '@mui/icons-material';
24
24
  import { Alert, CircularProgress, Stack, Typography } from '@mui/material';
25
- import { styled } from '@mui/system';
26
25
  import { useRequest, useSetState } from 'ahooks';
27
26
  import pWaitFor from 'p-wait-for';
28
27
  import { useEffect, useState } from 'react';
@@ -221,7 +220,7 @@ function CustomerSubscriptionChangePayment({ subscription, customer, onComplete
221
220
  };
222
221
 
223
222
  return (
224
- <Root direction="column" spacing={4} sx={{ maxWidth: '540px' }}>
223
+ <Stack direction="column" spacing={4} sx={{ maxWidth: '540px' }}>
225
224
  <Stack className="page-header" direction="row" justifyContent="space-between" alignItems="center">
226
225
  <Stack
227
226
  direction="row"
@@ -307,7 +306,7 @@ function CustomerSubscriptionChangePayment({ subscription, customer, onComplete
307
306
  returnUrl={window.location.href.replace(/\/[^/]+$/, '')}
308
307
  />
309
308
  )}
310
- </Root>
309
+ </Stack>
311
310
  );
312
311
  }
313
312
 
@@ -363,35 +362,3 @@ export default function DataWrapper() {
363
362
 
364
363
  return <FormWrapper subscription={data.subscription} customer={data.customer} onComplete={runAsync} />;
365
364
  }
366
-
367
- const Root = styled(Stack)`
368
- .cko-payment-form {
369
- // .MuiInputBase-root {
370
- // border-radius: 0;
371
- // }
372
-
373
- // .MuiInputAdornment-positionStart {
374
- // width: 50px;
375
- // }
376
-
377
- // .MuiBox-root {
378
- // border: 1px solid #ccc;
379
- // margin: -1px 0 0 -1px;
380
- // }
381
-
382
- // .MuiFormHelperText-root {
383
- // margin-left: 14px;
384
- // }
385
-
386
- // .MuiOutlinedInput-notchedOutline {
387
- // border: none;
388
- // }
389
- }
390
-
391
- .cko-payment-submit {
392
- .MuiButtonBase-root {
393
- border-radius: 0;
394
- font-size: 1.3rem;
395
- }
396
- }
397
- `;
@@ -74,12 +74,14 @@ export default function CustomerSubscriptionDetail() {
74
74
  const { session } = useSessionContext();
75
75
  const { loading, error, data, refresh } = useRequest(() => fetchData(id));
76
76
  const { hasUnpaid, checkUnpaidInvoices } = useUnpaidInvoicesCheckForSubscription(id);
77
+ const overdraftProtectionReady =
78
+ ['active', 'trialing', 'past_due'].includes(data?.status || '') && data?.paymentMethod?.type === 'arcblock';
77
79
  const {
78
80
  data: overdraftProtection = null,
79
81
  loading: overdraftProtectionLoading,
80
82
  run: refreshOverdraftProtection,
81
83
  } = useRequest(() => fetchOverdraftProtection(id), {
82
- ready: ['active', 'trialing', 'past_due'].includes(data?.status || '') && data?.paymentMethod?.type === 'arcblock',
84
+ ready: overdraftProtectionReady,
83
85
  });
84
86
 
85
87
  const {
@@ -94,6 +96,7 @@ export default function CustomerSubscriptionDetail() {
94
96
  }),
95
97
  {
96
98
  refreshDeps: [id],
99
+ ready: overdraftProtectionReady,
97
100
  }
98
101
  );
99
102
 
@@ -367,11 +370,7 @@ export default function CustomerSubscriptionDetail() {
367
370
  sm: 'column',
368
371
  md: 'row',
369
372
  },
370
- alignItems: {
371
- xs: 'flex-start',
372
- sm: 'flex-start',
373
- md: 'center',
374
- },
373
+ alignItems: 'flex-start',
375
374
  gap: {
376
375
  xs: 1,
377
376
  sm: 1,
@@ -270,7 +270,7 @@ export default function DonationList() {
270
270
  return (
271
271
  <>
272
272
  <Stack direction="row" alignItems="center" gap={1} flexWrap="wrap">
273
- <Typography variant="h6">{t('admin.donate.intro')}</Typography>
273
+ <Typography variant="body2">{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')}
276
276
  </Button>
@@ -71,7 +71,7 @@ export default function Overview() {
71
71
  <Typography variant="h2" gutterBottom fontWeight="bold" mb={1}>
72
72
  {t('common.welcome')}
73
73
  </Typography>
74
- <Typography variant="body1" color="text.secondary" mb={2}>
74
+ <Typography variant="body2" color="text.secondary" mb={2}>
75
75
  {t('common.welcomeDesc')}
76
76
  </Typography>
77
77
  </Box>