@blocklet/payment-react 1.14.20 → 1.14.22

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 (136) hide show
  1. package/es/checkout/donate.d.ts +2 -1
  2. package/es/checkout/donate.js +9 -10
  3. package/es/checkout/form.d.ts +1 -1
  4. package/es/checkout/form.js +23 -1
  5. package/es/checkout/table.d.ts +1 -1
  6. package/es/checkout/table.js +8 -1
  7. package/es/components/blockchain/tx.js +2 -1
  8. package/es/components/country-select.d.ts +16 -0
  9. package/es/components/country-select.js +82 -0
  10. package/es/components/input.d.ts +21 -21
  11. package/es/components/input.js +43 -42
  12. package/es/components/livemode.js +1 -0
  13. package/es/components/pricing-table.js +0 -2
  14. package/es/components/status.js +2 -3
  15. package/es/components/table.d.ts +2 -0
  16. package/es/components/table.js +186 -0
  17. package/es/contexts/payment.d.ts +2 -0
  18. package/es/contexts/payment.js +5 -2
  19. package/es/history/invoice/list.d.ts +5 -1
  20. package/es/history/invoice/list.js +218 -48
  21. package/es/hooks/mobile.d.ts +4 -0
  22. package/es/hooks/mobile.js +10 -0
  23. package/es/index.d.ts +5 -1
  24. package/es/index.js +7 -1
  25. package/es/libs/util.d.ts +15 -2
  26. package/es/libs/util.js +92 -28
  27. package/es/locales/en.js +23 -7
  28. package/es/locales/index.d.ts +0 -1
  29. package/es/locales/index.js +10 -1
  30. package/es/locales/zh.js +22 -6
  31. package/es/payment/error.js +2 -2
  32. package/es/payment/footer.js +1 -1
  33. package/es/payment/form/address.d.ts +9 -2
  34. package/es/payment/form/address.js +69 -69
  35. package/es/payment/form/currency.js +39 -25
  36. package/es/payment/form/index.d.ts +1 -1
  37. package/es/payment/form/index.js +83 -81
  38. package/es/payment/form/phone.js +15 -51
  39. package/es/payment/index.d.ts +1 -10
  40. package/es/payment/index.js +274 -219
  41. package/es/payment/product-card.js +4 -4
  42. package/es/payment/product-donation.js +7 -2
  43. package/es/payment/product-item.d.ts +2 -2
  44. package/es/payment/product-item.js +120 -81
  45. package/es/payment/summary.js +188 -118
  46. package/es/theme/index.css +240 -0
  47. package/es/theme/index.d.ts +9 -0
  48. package/es/theme/index.js +243 -0
  49. package/es/theme/typography.d.ts +2 -0
  50. package/es/theme/typography.js +53 -0
  51. package/es/types/index.d.ts +11 -0
  52. package/lib/checkout/donate.d.ts +2 -1
  53. package/lib/checkout/donate.js +14 -2
  54. package/lib/checkout/form.d.ts +1 -1
  55. package/lib/checkout/form.js +22 -1
  56. package/lib/checkout/table.d.ts +1 -1
  57. package/lib/checkout/table.js +14 -1
  58. package/lib/components/blockchain/tx.js +4 -1
  59. package/lib/components/country-select.d.ts +16 -0
  60. package/lib/components/country-select.js +115 -0
  61. package/lib/components/input.d.ts +21 -21
  62. package/lib/components/input.js +21 -12
  63. package/lib/components/livemode.js +1 -0
  64. package/lib/components/pricing-table.js +0 -2
  65. package/lib/components/status.js +2 -3
  66. package/lib/components/table.d.ts +2 -0
  67. package/lib/components/table.js +220 -0
  68. package/lib/contexts/payment.d.ts +2 -0
  69. package/lib/contexts/payment.js +4 -1
  70. package/lib/history/invoice/list.d.ts +5 -1
  71. package/lib/history/invoice/list.js +293 -62
  72. package/lib/hooks/mobile.d.ts +4 -0
  73. package/lib/hooks/mobile.js +17 -0
  74. package/lib/index.d.ts +5 -1
  75. package/lib/index.js +36 -0
  76. package/lib/libs/util.d.ts +15 -2
  77. package/lib/libs/util.js +115 -37
  78. package/lib/locales/en.js +23 -7
  79. package/lib/locales/index.d.ts +0 -1
  80. package/lib/locales/index.js +14 -3
  81. package/lib/locales/zh.js +22 -6
  82. package/lib/payment/error.js +5 -1
  83. package/lib/payment/footer.js +1 -1
  84. package/lib/payment/form/address.d.ts +9 -2
  85. package/lib/payment/form/address.js +67 -59
  86. package/lib/payment/form/currency.js +31 -24
  87. package/lib/payment/form/index.d.ts +1 -1
  88. package/lib/payment/form/index.js +92 -93
  89. package/lib/payment/form/phone.js +11 -59
  90. package/lib/payment/index.d.ts +1 -10
  91. package/lib/payment/index.js +291 -219
  92. package/lib/payment/product-card.js +5 -4
  93. package/lib/payment/product-donation.js +9 -2
  94. package/lib/payment/product-item.d.ts +2 -2
  95. package/lib/payment/product-item.js +38 -19
  96. package/lib/payment/summary.js +219 -127
  97. package/lib/theme/index.css +240 -0
  98. package/lib/theme/index.d.ts +9 -0
  99. package/lib/theme/index.js +259 -0
  100. package/lib/theme/typography.d.ts +2 -0
  101. package/lib/theme/typography.js +59 -0
  102. package/lib/types/index.d.ts +11 -0
  103. package/package.json +14 -11
  104. package/src/checkout/donate.tsx +16 -10
  105. package/src/checkout/form.tsx +23 -0
  106. package/src/checkout/table.tsx +13 -1
  107. package/src/components/blockchain/tx.tsx +2 -1
  108. package/src/components/country-select.tsx +93 -0
  109. package/src/components/input.tsx +49 -46
  110. package/src/components/livemode.tsx +1 -0
  111. package/src/components/pricing-table.tsx +0 -2
  112. package/src/components/status.tsx +1 -2
  113. package/src/components/table.tsx +200 -0
  114. package/src/contexts/payment.tsx +6 -1
  115. package/src/history/invoice/list.tsx +258 -49
  116. package/src/hooks/mobile.ts +13 -0
  117. package/src/index.ts +7 -0
  118. package/src/libs/util.ts +120 -31
  119. package/src/locales/en.tsx +19 -4
  120. package/src/locales/index.tsx +10 -3
  121. package/src/locales/zh.tsx +18 -3
  122. package/src/payment/error.tsx +2 -2
  123. package/src/payment/footer.tsx +1 -1
  124. package/src/payment/form/address.tsx +56 -47
  125. package/src/payment/form/currency.tsx +29 -23
  126. package/src/payment/form/index.tsx +89 -76
  127. package/src/payment/form/phone.tsx +14 -51
  128. package/src/payment/index.tsx +294 -242
  129. package/src/payment/product-card.tsx +4 -4
  130. package/src/payment/product-donation.tsx +7 -3
  131. package/src/payment/product-item.tsx +49 -20
  132. package/src/payment/summary.tsx +191 -108
  133. package/src/theme/index.css +240 -0
  134. package/src/theme/index.tsx +250 -0
  135. package/src/theme/typography.ts +56 -0
  136. package/src/types/index.ts +12 -0
package/src/libs/util.ts CHANGED
@@ -24,7 +24,7 @@ import { joinURL } from 'ufo';
24
24
 
25
25
  import { t } from '../locales';
26
26
  import dayjs from './dayjs';
27
- import { PricingRenderProps } from '../types';
27
+ import { ActionProps, PricingRenderProps } from '../types';
28
28
 
29
29
  export const PAYMENT_KIT_DID = 'z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk';
30
30
 
@@ -533,6 +533,32 @@ export function formatUpsellSaving(items: TLineItemExpanded[], currency: TPaymen
533
533
  return Number(before.sub(after).mul(new BN(100)).div(before).toString()).toFixed(0);
534
534
  }
535
535
 
536
+ export function formatMeteredThen(
537
+ subscription: string,
538
+ recurring: string,
539
+ hasMetered: boolean,
540
+ locale: string = 'en'
541
+ ): string {
542
+ if (hasMetered) {
543
+ return t('payment.checkout.meteredThen', locale, { subscription, recurring });
544
+ }
545
+ return t('payment.checkout.then', locale, { subscription, recurring });
546
+ }
547
+
548
+ export function formatPriceDisplay(
549
+ { amount, then, actualAmount, showThen }: { amount: string; then?: string; actualAmount: string; showThen?: boolean },
550
+ recurring: string,
551
+ hasMetered: boolean,
552
+ locale: string = 'en'
553
+ ) {
554
+ if (Number(actualAmount) === 0 && hasMetered) {
555
+ return t('payment.checkout.metered', locale, { recurring });
556
+ }
557
+ if (showThen) {
558
+ return [amount, then].filter(Boolean).join(', ');
559
+ }
560
+ return [amount, then].filter(Boolean).join(' ');
561
+ }
536
562
  export function formatCheckoutHeadlines(
537
563
  items: TLineItemExpanded[],
538
564
  currency: TPaymentCurrency,
@@ -543,9 +569,13 @@ export function formatCheckoutHeadlines(
543
569
  amount: string;
544
570
  then?: string;
545
571
  secondary?: string;
572
+ showThen?: boolean;
573
+ actualAmount: string;
574
+ priceDisplay: string;
546
575
  } {
547
576
  const brand = getStatementDescriptor(items);
548
577
  const { total } = getCheckoutAmount(items, currency, trialInDays > 0);
578
+ const actualAmount = fromUnitToToken(total, currency.decimal);
549
579
  const amount = `${fromUnitToToken(total, currency.decimal)} ${currency.symbol}`;
550
580
 
551
581
  // empty
@@ -554,6 +584,8 @@ export function formatCheckoutHeadlines(
554
584
  action: t('payment.checkout.empty', locale),
555
585
  amount: '0',
556
586
  then: '',
587
+ actualAmount: '0',
588
+ priceDisplay: '0',
557
589
  };
558
590
  }
559
591
 
@@ -563,10 +595,10 @@ export function formatCheckoutHeadlines(
563
595
  if (items.every((x) => x.price.type === 'one_time')) {
564
596
  const action = t('payment.checkout.pay', locale, { payee: brand });
565
597
  if (items.length > 1) {
566
- return { action, amount };
598
+ return { action, amount, actualAmount, priceDisplay: amount };
567
599
  }
568
600
 
569
- return { action, amount, then: '' };
601
+ return { action, amount, then: '', actualAmount, priceDisplay: amount };
570
602
  }
571
603
 
572
604
  const item = items.find((x) => x.price.type === 'recurring');
@@ -576,10 +608,9 @@ export function formatCheckoutHeadlines(
576
608
  'per',
577
609
  locale
578
610
  );
579
-
611
+ const hasMetered = items.some((x) => x.price.type === 'recurring' && x.price.recurring?.usage_type === 'metered');
580
612
  // all recurring
581
613
  if (items.every((x) => x.price.type === 'recurring')) {
582
- const hasMetered = items.some((x) => x.price.type === 'recurring' && x.price.recurring?.usage_type === 'metered');
583
614
  const subscription = [
584
615
  hasMetered ? t('payment.checkout.least', locale) : '',
585
616
  fromUnitToToken(
@@ -597,32 +628,54 @@ export function formatCheckoutHeadlines(
597
628
  .join(' ');
598
629
  if (items.length > 1) {
599
630
  if (trialInDays > 0) {
600
- return {
631
+ const result = {
601
632
  action: t('payment.checkout.try2', locale, { name, count: items.length - 1 }),
602
633
  amount: t('payment.checkout.free', locale, { count: trialInDays }),
603
- then: t('payment.checkout.then', locale, { subscription, recurring }),
634
+ then: formatMeteredThen(subscription, recurring, hasMetered && Number(subscription) === 0, locale),
635
+ showThen: true,
636
+ actualAmount: '0',
637
+ };
638
+ return {
639
+ ...result,
640
+ priceDisplay: formatPriceDisplay(result, recurring, hasMetered, locale),
604
641
  };
605
642
  }
606
-
607
- return {
643
+ const result = {
608
644
  action: t('payment.checkout.sub2', locale, { name, count: items.length - 1 }),
609
645
  amount,
610
- then: recurring,
646
+ then: hasMetered ? t('payment.checkout.meteredThen', locale, { recurring }) : recurring,
647
+ showThen: hasMetered,
648
+ actualAmount,
649
+ };
650
+ return {
651
+ ...result,
652
+ priceDisplay: formatPriceDisplay(result, recurring, hasMetered, locale),
611
653
  };
612
654
  }
613
655
 
614
656
  if (trialInDays > 0) {
615
- return {
657
+ const result = {
616
658
  action: t('payment.checkout.try1', locale, { name }),
617
659
  amount: t('payment.checkout.free', locale, { count: trialInDays }),
618
- then: t('payment.checkout.then', locale, { subscription, recurring }),
660
+ then: formatMeteredThen(subscription, recurring, hasMetered && Number(subscription) === 0, locale),
661
+ showThen: true,
662
+ actualAmount: '0',
663
+ };
664
+ return {
665
+ ...result,
666
+ priceDisplay: formatPriceDisplay(result, recurring, hasMetered, locale),
619
667
  };
620
668
  }
621
-
622
- return {
669
+ const result = {
623
670
  action: t('payment.checkout.sub1', locale, { name }),
624
671
  amount,
625
- then: recurring,
672
+ then: hasMetered ? t('payment.checkout.meteredThen', locale, { recurring }) : recurring,
673
+ showThen: hasMetered,
674
+ actualAmount,
675
+ };
676
+ return {
677
+ ...result,
678
+ priceDisplay: formatPriceDisplay(result, recurring, hasMetered, locale),
626
679
  };
627
680
  }
628
681
 
@@ -639,10 +692,22 @@ export function formatCheckoutHeadlines(
639
692
  currency.decimal
640
693
  );
641
694
 
642
- return {
695
+ const result = {
643
696
  action: t('payment.checkout.pay', locale, { payee: brand }),
644
697
  amount,
645
- then: t('payment.checkout.then', locale, { subscription: `${subscription} ${currency.symbol}`, recurring }),
698
+ then: formatMeteredThen(
699
+ `${subscription} ${currency.symbol}`,
700
+ recurring,
701
+ hasMetered && Number(subscription) === 0,
702
+ locale
703
+ ),
704
+ showThen: true,
705
+ actualAmount,
706
+ };
707
+
708
+ return {
709
+ ...result,
710
+ priceDisplay: formatPriceDisplay(result, recurring, hasMetered, locale),
646
711
  };
647
712
  }
648
713
 
@@ -690,48 +755,65 @@ export function formatSubscriptionProduct(items: TSubscriptionItemExpanded[], ma
690
755
  }
691
756
 
692
757
  export const getSubscriptionTimeSummary = (subscription: TSubscriptionExpanded) => {
693
- const lines = [`Started on ${formatToDate(subscription.start_date * 1000)}`];
758
+ const lines = [`Start on ${formatToDate(subscription.start_date * 1000, 'en', 'YYYY-MM-DD')}`];
759
+
760
+ const getLineTimeMessage = (time: number) => {
761
+ const curDay = dayjs().isSame(dayjs(time), 'day');
762
+ const timeFormat = curDay ? 'HH:mm:ss' : 'YYYY-MM-DD';
763
+ return `${curDay ? 'in' : 'on'} ${formatToDate(time, 'en', timeFormat)}`;
764
+ };
765
+
694
766
  if (subscription.status === 'active' || subscription.status === 'trialing') {
695
767
  if (subscription.cancel_at) {
696
- lines.push(`will cancel on ${formatToDate(subscription.cancel_at * 1000)}`);
768
+ lines.push(`Ended ${getLineTimeMessage(subscription.cancel_at * 1000)}`);
697
769
  } else if (subscription.cancel_at_period_end) {
698
- lines.push(`will cancel on ${formatToDate(subscription.current_period_end * 1000)}`);
770
+ lines.push(`Ended ${getLineTimeMessage(subscription.current_period_end * 1000)}`);
699
771
  } else {
700
- lines.push(`will renew on ${formatToDate(subscription.current_period_end * 1000)}`);
772
+ lines.push(`Renew ${getLineTimeMessage(subscription.current_period_end * 1000)}`);
701
773
  }
702
774
  } else if (subscription.status === 'past_due') {
703
- lines.push(`will cancel on ${formatToDate((subscription.cancel_at || subscription.current_period_end) * 1000)}`);
775
+ lines.push(`Ended ${getLineTimeMessage((subscription.cancel_at || subscription.current_period_end) * 1000)}`);
704
776
  } else if (subscription.status === 'canceled') {
705
- lines.push(`canceled on ${formatToDate(subscription.canceled_at * 1000)}`);
777
+ lines.push(`Ended ${getLineTimeMessage(subscription.canceled_at * 1000)}`);
706
778
  }
707
779
 
708
- return lines.join(', ');
780
+ return lines.join(',');
709
781
  };
710
782
 
711
- export const getSubscriptionAction = (subscription: TSubscriptionExpanded) => {
783
+ export const getSubscriptionAction = (
784
+ subscription: TSubscriptionExpanded,
785
+ actionProps: ActionProps
786
+ ): {
787
+ action: string;
788
+ variant: string;
789
+ color: string;
790
+ canRenew: boolean;
791
+ text?: string;
792
+ sx?: any;
793
+ } | null => {
712
794
  if (subscription.status === 'active' || subscription.status === 'trialing') {
713
795
  if (subscription.cancel_at_period_end) {
714
796
  if (subscription.cancelation_details?.reason === 'payment_failed') {
715
797
  return null;
716
798
  }
717
799
 
718
- return { action: 'recover', variant: 'contained', color: 'primary', canRenew: false };
800
+ return { action: 'recover', variant: 'contained', color: 'primary', canRenew: false, ...actionProps?.recover };
719
801
  }
720
802
 
721
803
  if (subscription.cancel_at && subscription.cancel_at !== subscription.current_period_end) {
722
804
  return null;
723
805
  }
724
806
 
725
- return { action: 'cancel', variant: 'outlined', color: 'inherit', canRenew: false };
807
+ return { action: 'cancel', variant: 'outlined', color: 'inherit', canRenew: false, ...actionProps?.cancel };
726
808
  }
727
809
 
728
810
  if (subscription.status === 'past_due') {
729
811
  const canRenew = subscription.cancel_at && subscription.cancel_at !== subscription.current_period_end;
730
- return { action: 'pastDue', variant: 'contained', color: 'primary', canRenew };
812
+ return { action: 'pastDue', variant: 'contained', color: 'primary', canRenew, ...actionProps?.pastDue };
731
813
  }
732
814
 
733
815
  if (subscription.status !== 'canceled' && subscription.cancel_at_period_end) {
734
- return { action: 'recover', variant: 'contained', color: 'primary', canRenew: false };
816
+ return { action: 'recover', variant: 'contained', color: 'primary', canRenew: false, ...actionProps?.recover };
735
817
  }
736
818
 
737
819
  return null;
@@ -855,9 +937,9 @@ export function formatTotalPrice({
855
937
  const unitValue = new BN(price.custom_unit_amount || price.unit_amount);
856
938
  const currency: TPaymentCurrency = price?.currency ?? {};
857
939
 
858
- const total = `${fromUnitToToken(unitValue.mul(new BN(quantity)), currency.decimal)} ${currency.symbol}`;
940
+ const total = `${fromUnitToToken(unitValue.mul(new BN(quantity)), currency.decimal)} ${currency.symbol} `;
859
941
 
860
- const unit = `${fromUnitToToken(unitValue, currency.decimal)} ${currency.symbol}`;
942
+ const unit = `${fromUnitToToken(unitValue, currency.decimal)} ${currency.symbol} `;
861
943
 
862
944
  const appendUnit = (v: string, alt: string) => {
863
945
  if (product.unit_label) {
@@ -893,6 +975,13 @@ export function formatQuantityInventory(price: TPrice, quantity: string | number
893
975
  return '';
894
976
  }
895
977
 
978
+ export function formatSubscriptionStatus(status: string) {
979
+ if (status === 'canceled') {
980
+ return 'Ended';
981
+ }
982
+ return status;
983
+ }
984
+
896
985
  export function formatAmountPrecisionLimit(amount: string, locale = 'en', precision: number = 6) {
897
986
  if (!amount) {
898
987
  return '';
@@ -62,7 +62,7 @@ export default flat({
62
62
  continue: 'Continue',
63
63
  qty: 'Qty {count}',
64
64
  each: '{unit} each',
65
- trial: 'Free for {count} days',
65
+ trial: "Free for {count} day{count > 1 ? 's' : ''}",
66
66
  billed: 'billed {rule}',
67
67
  metered: 'based on usage',
68
68
  hour: 'hour',
@@ -85,6 +85,7 @@ export default flat({
85
85
  years: 'years',
86
86
  type: 'type',
87
87
  donation: 'Donation',
88
+ recoverFrom: 'Recovered From',
88
89
  quantityLimitPerCheckout: 'Exceed purchase limit',
89
90
  quantityNotEnough: 'Exceed inventory',
90
91
  amountPrecisionLimit: 'Amount decimal places must be less than or equal to {precision}',
@@ -110,11 +111,13 @@ export default flat({
110
111
  subscription: 'View subscription',
111
112
  invoice: 'View invoice',
112
113
  },
114
+ paymentRequired: 'Payment Required',
113
115
  staking: {
114
116
  title: 'Staking Required',
115
117
  tooltip:
116
118
  'Staking is used to ensure that future invoices can be paid normally. Revoking the staking from DID Wallet means canceling the subscription.',
117
119
  },
120
+ stakingConfirm: 'In this payment, the staked amount is separate from the product cost.',
118
121
  donation: {
119
122
  between: 'Please enter an amount between {min} and {max}.',
120
123
  custom: 'Custom Amount',
@@ -131,7 +134,9 @@ export default flat({
131
134
  sub1: 'Subscribe to {name}',
132
135
  sub2: 'Subscribe to {name} and {count} more',
133
136
  then: 'Then {subscription} {recurring}',
134
- free: '{count} days free',
137
+ meteredThen: 'Then {recurring} based on usage',
138
+ metered: '{recurring} based on usage',
139
+ free: "{count} day{count > 1 ? 's' : ''} free",
135
140
  least: 'continue with at least',
136
141
  completed: {
137
142
  payment: 'Thanks for your purchase',
@@ -140,8 +145,7 @@ export default flat({
140
145
  donate: 'Thanks for your support',
141
146
  tip: 'A payment to {payee} has been completed. You can view the details of this payment in your account.',
142
147
  },
143
- confirm:
144
- 'By confirming your subscription, you allow {payee} to charge your account or slashing your staking for this and future payments in accordance with their terms. You can always cancel your subscription, or revoking your staking from DID Wallet.',
148
+ confirm: 'Confirming allows {payee} to charge or reduce your staking. You can cancel or revoke staking anytime.',
145
149
  required: 'Required',
146
150
  invalid: 'Invalid',
147
151
  billing: {
@@ -184,12 +188,16 @@ export default flat({
184
188
  title: 'Nothing to show here',
185
189
  description: 'Seems this checkoutSession is not configured properly',
186
190
  },
191
+ orderSummary: 'Order Summary',
192
+ paymentDetails: 'Payment Details',
193
+ productListTotal: 'Includes {total} items',
187
194
  },
188
195
  customer: {
189
196
  payments: 'Payment History',
190
197
  invoices: 'Invoice History',
191
198
  details: 'Details',
192
199
  summary: 'Summary',
200
+ specifics: 'Specifics',
193
201
  update: 'Update Information',
194
202
  empty: 'Seems you do not have any subscriptions or payments here',
195
203
  cancel: {
@@ -271,12 +279,16 @@ export default flat({
271
279
  renewError: 'Failed to renew the subscription',
272
280
  empty: 'There are no invoices',
273
281
  next: 'No invoices yet, next invoice will be generated on {date}',
282
+ invoiceNumber: 'Invoice Number',
283
+ emptyList: 'No Invoice',
274
284
  },
275
285
  payment: {
276
286
  empty: 'There are no payments',
287
+ emptyList: 'No Payment',
277
288
  },
278
289
  refund: {
279
290
  empty: 'There are no refunds',
291
+ emptyList: 'No Refund',
280
292
  },
281
293
  subscriptions: {
282
294
  plan: 'Plan',
@@ -310,4 +322,7 @@ export default flat({
310
322
  [RefundType.stakeReturn]: 'Stake Return',
311
323
  },
312
324
  },
325
+ empty: {
326
+ records: 'No matching records found',
327
+ },
313
328
  });
@@ -1,4 +1,5 @@
1
1
  /* eslint-disable no-prototype-builtins */
2
+ import { template } from 'lodash';
2
3
  import en from './en';
3
4
  import zh from './zh';
4
5
 
@@ -8,9 +9,15 @@ export const translations = {
8
9
  en,
9
10
  };
10
11
 
11
- export const replace = (template: string, data: Record<string, any> = {}) =>
12
- template.replace(/{(\w*)}/g, (_, key) => (data.hasOwnProperty(key) ? data[key] : ''));
13
-
12
+ const replace = (t: string, data: Record<string, any> = {}): string => {
13
+ try {
14
+ const compiled = template(t, { interpolate: /{([\s\S]+?)}/g, escape: /{([\s\S]+?)}/g });
15
+ return compiled(data);
16
+ } catch (e) {
17
+ console.error(`Error evaluating template: ${t}`, e);
18
+ return '';
19
+ }
20
+ };
14
21
  export const createTranslator = ({ fallbackLocale = 'en' }: { fallbackLocale?: string }, langs: any = translations) => {
15
22
  return (key: string, locale = fallbackLocale, data: Record<string, any> = {}) => {
16
23
  if (!langs[locale] || !langs[locale][key]) {
@@ -85,6 +85,7 @@ export default flat({
85
85
  years: '年',
86
86
  type: '类型',
87
87
  donation: '打赏',
88
+ recoverFrom: '恢复自',
88
89
  quantityLimitPerCheckout: '超出购买限制',
89
90
  quantityNotEnough: '库存不足',
90
91
  amountPrecisionLimit: '金额小数位数必须在 {precision} 位以内',
@@ -110,10 +111,12 @@ export default flat({
110
111
  subscription: '查看订阅',
111
112
  invoice: '查看账单',
112
113
  },
114
+ paymentRequired: '支付数量',
113
115
  staking: {
114
116
  title: '质押数量',
115
117
  tooltip: '质押相当于保证金,用于确保未来的账单能够正常扣款,如果你从 DID Wallet 撤销质押,订阅也会被取消。',
116
118
  },
119
+ stakingConfirm: '在此支付中,质押金额与产品费用分开',
117
120
  donation: {
118
121
  between: '金额必须大于 {min} 且小于 {max}',
119
122
  custom: '输入金额',
@@ -130,7 +133,9 @@ export default flat({
130
133
  sub1: '订阅 {name}',
131
134
  sub2: '订阅 {name} 等{count}个产品',
132
135
  then: '然后 {subscription} {recurring}',
133
- free: '{count}',
136
+ meteredThen: '然后{recurring}按用量计费',
137
+ metered: '{recurring}按用量计费',
138
+ free: '免费试用 {count} 天',
134
139
  least: '至少',
135
140
  completed: {
136
141
  payment: '感谢您的购买',
@@ -139,8 +144,7 @@ export default flat({
139
144
  donate: '感谢您的支持',
140
145
  tip: '向{payee}的付款已完成。您可以在您的账户中查看此付款的详细信息。',
141
146
  },
142
- confirm:
143
- '通过确认您的订阅,您允许{payee}按照其条款对您的账户进行付款或者罚没您的质押。您随时可以取消您的订阅,或者撤销质押。',
147
+ confirm: '确认允许{payee}对您的账户进行付款或者罚没您的质押。您随时可以取消您的订阅,或者撤销质押。',
144
148
  required: '必填项',
145
149
  invalid: '无效',
146
150
  billing: {
@@ -181,12 +185,16 @@ export default flat({
181
185
  title: '没有任何购买项目',
182
186
  description: '可能这个付款链接没有正确配置',
183
187
  },
188
+ orderSummary: '订单概览',
189
+ paymentDetails: '支付信息',
190
+ productListTotal: '包括 {total} 项',
184
191
  },
185
192
  customer: {
186
193
  payments: '支付历史',
187
194
  invoices: '账单历史',
188
195
  details: '账户详情',
189
196
  summary: '计费摘要',
197
+ specifics: '具体信息',
190
198
  update: '更新客户信息',
191
199
  empty: '看起来您在这里没有任何订阅或支付',
192
200
  cancel: {
@@ -263,12 +271,16 @@ export default flat({
263
271
  renewError: '订阅恢复失败',
264
272
  empty: '没有任何账单',
265
273
  next: '还没有账单,下次账单将在 {date} 生成',
274
+ invoiceNumber: '账单编号',
275
+ emptyList: '没有账单',
266
276
  },
267
277
  payment: {
268
278
  empty: '没有支付记录',
279
+ emptyList: '没有支付记录',
269
280
  },
270
281
  refund: {
271
282
  empty: '没有退款记录',
283
+ emptyList: '没有退款记录',
272
284
  },
273
285
  subscriptions: {
274
286
  plan: '订阅',
@@ -302,4 +314,7 @@ export default flat({
302
314
  [RefundType.stakeReturn]: '退押金',
303
315
  },
304
316
  },
317
+ empty: {
318
+ records: '没有找到匹配的记录',
319
+ },
305
320
  });
@@ -13,7 +13,7 @@ type Props = {
13
13
  function getHeightStyle(mode: ModeType | undefined): any {
14
14
  switch (mode) {
15
15
  case 'standalone':
16
- return { height: '100vh' }; // 独立模式下,高度为100vh
16
+ return { height: '100vh', maxHeight: '100%' }; // 独立模式下,高度为100vh
17
17
  default:
18
18
  return { height: 'auto', minHeight: 200 }; // 默认情况下,高度根据内容自动调整
19
19
  }
@@ -29,7 +29,7 @@ export default function PaymentError({ title, description, button, mode }: Props
29
29
  <Typography variant="body1" sx={{ mb: 2, textAlign: 'center' }}>
30
30
  {description}
31
31
  </Typography>
32
- <Button variant="text" size="small" component={Link} href={window.blocklet?.appUrl}>
32
+ <Button variant="text" size="small" sx={{ color: 'text.link' }} component={Link} href={window.blocklet?.appUrl}>
33
33
  {button}
34
34
  </Button>
35
35
  </Stack>
@@ -2,7 +2,7 @@ import { Typography } from '@mui/material';
2
2
 
3
3
  export default function CheckoutFooter({ ...props }) {
4
4
  return (
5
- <Typography color="text.secondary" fontSize={12} {...props}>
5
+ <Typography color="text.lighter" fontSize={12} {...props}>
6
6
  Powered by{' '}
7
7
  <Typography component="span" sx={{ fontWeight: 'bold', fontSize: 12 }}>
8
8
  ArcBlock
@@ -1,53 +1,59 @@
1
1
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
2
- import { Fade, Stack, Typography } from '@mui/material';
2
+ import { Fade, FormLabel, InputAdornment, Stack, SxProps } from '@mui/material';
3
3
  import { Controller, useFormContext } from 'react-hook-form';
4
- import { CountrySelector } from 'react-international-phone';
5
-
6
4
  import FormInput from '../../components/input';
5
+ import CountrySelect from '../../components/country-select';
7
6
 
8
7
  type Props = {
9
8
  mode: string;
10
9
  stripe: boolean;
10
+ sx?: SxProps;
11
+ };
12
+
13
+ AddressForm.defaultProps = {
14
+ sx: {},
11
15
  };
12
16
 
13
- export default function AddressForm({ mode, stripe }: Props) {
17
+ export default function AddressForm({ mode, stripe, sx = {} }: Props) {
14
18
  const { t } = useLocaleContext();
15
- const { control, setValue } = useFormContext();
19
+ const { control } = useFormContext();
16
20
 
17
21
  if (mode === 'required') {
18
22
  return (
19
23
  <Fade in>
20
- <Stack className="cko-payment-address cko-payment-form">
21
- <Typography sx={{ mb: 1, color: 'text.primary', fontWeight: 600 }}>
22
- {t(`payment.checkout.billing.${mode}`)}
23
- </Typography>
24
+ <Stack className="cko-payment-address cko-payment-form" sx={sx}>
25
+ <FormLabel className="base-label">{t(`payment.checkout.billing.${mode}`)}</FormLabel>
24
26
  <Stack direction="column" className="cko-payment-form" spacing={0}>
25
27
  <Stack direction="row" spacing={0}>
26
- <Controller
27
- name="billing_address.country"
28
- control={control}
29
- render={({ field }) => (
30
- <CountrySelector
31
- selectedCountry={field.value}
32
- onSelect={({ iso2 }) => setValue(field.name, iso2)}
33
- buttonStyle={{
34
- width: '64px',
35
- height: '40px',
36
- border: '1px solid #ccc',
37
- marginLeft: -1,
38
- marginTop: -1,
39
- }}
40
- />
41
- )}
42
- />
43
28
  <FormInput
44
29
  name="billing_address.postal_code"
45
30
  rules={{ required: t('payment.checkout.required') }}
46
31
  errorPosition="right"
47
32
  variant="outlined"
48
33
  placeholder={t('payment.checkout.billing.postal_code')}
34
+ InputProps={{
35
+ startAdornment: (
36
+ <InputAdornment position="start">
37
+ <Controller
38
+ name="billing_address.country"
39
+ control={control}
40
+ render={({ field }) => (
41
+ <CountrySelect
42
+ {...field}
43
+ sx={{
44
+ '&.Mui-focused .MuiOutlinedInput-notchedOutline': {
45
+ borderColor: 'transparent',
46
+ },
47
+ }}
48
+ />
49
+ )}
50
+ />
51
+ </InputAdornment>
52
+ ),
53
+ }}
49
54
  />
50
55
  </Stack>
56
+ <FormLabel className="base-label">{t('payment.checkout.billing.state')}</FormLabel>
51
57
  <FormInput
52
58
  name="billing_address.state"
53
59
  rules={{ required: t('payment.checkout.required') }}
@@ -55,6 +61,7 @@ export default function AddressForm({ mode, stripe }: Props) {
55
61
  variant="outlined"
56
62
  placeholder={t('payment.checkout.billing.state')}
57
63
  />
64
+ <FormLabel className="base-label">{t('payment.checkout.billing.line1')}</FormLabel>
58
65
  <FormInput
59
66
  name="billing_address.line1"
60
67
  rules={{ required: t('payment.checkout.required') }}
@@ -62,6 +69,7 @@ export default function AddressForm({ mode, stripe }: Props) {
62
69
  variant="outlined"
63
70
  placeholder={t('payment.checkout.billing.line1')}
64
71
  />
72
+ <FormLabel className="base-label">{t('payment.checkout.billing.city')}</FormLabel>
65
73
  <FormInput
66
74
  name="billing_address.city"
67
75
  rules={{ required: t('payment.checkout.required') }}
@@ -78,29 +86,10 @@ export default function AddressForm({ mode, stripe }: Props) {
78
86
  if (stripe) {
79
87
  return (
80
88
  <Fade in>
81
- <Stack className="cko-payment-address cko-payment-form">
82
- <Typography sx={{ mb: 1, color: 'text.primary', fontWeight: 600 }}>
83
- {t(`payment.checkout.billing.${mode}`)}
84
- </Typography>
89
+ <Stack className="cko-payment-address cko-payment-form" sx={sx}>
90
+ <FormLabel className="base-label">{t(`payment.checkout.billing.${mode}`)}</FormLabel>
85
91
  <Stack direction="column" className="cko-payment-form" spacing={0}>
86
92
  <Stack direction="row" spacing={0}>
87
- <Controller
88
- name="billing_address.country"
89
- control={control}
90
- render={({ field }) => (
91
- <CountrySelector
92
- selectedCountry={field.value}
93
- onSelect={({ iso2 }) => setValue(field.name, iso2)}
94
- buttonStyle={{
95
- width: '64px',
96
- height: '40px',
97
- border: '1px solid #ccc',
98
- marginLeft: -1,
99
- marginTop: -1,
100
- }}
101
- />
102
- )}
103
- />
104
93
  <FormInput
105
94
  name="billing_address.postal_code"
106
95
  rules={{ required: t('payment.checkout.required') }}
@@ -108,6 +97,26 @@ export default function AddressForm({ mode, stripe }: Props) {
108
97
  variant="outlined"
109
98
  placeholder={t('payment.checkout.billing.postal_code')}
110
99
  wrapperStyle={{ height: '40px' }}
100
+ InputProps={{
101
+ startAdornment: (
102
+ <InputAdornment position="start">
103
+ <Controller
104
+ name="billing_address.country"
105
+ control={control}
106
+ render={({ field }) => (
107
+ <CountrySelect
108
+ {...field}
109
+ sx={{
110
+ '&.Mui-focused .MuiOutlinedInput-notchedOutline': {
111
+ borderColor: 'transparent',
112
+ },
113
+ }}
114
+ />
115
+ )}
116
+ />
117
+ </InputAdornment>
118
+ ),
119
+ }}
111
120
  />
112
121
  </Stack>
113
122
  </Stack>