@blocklet/payment-react 1.24.2 → 1.24.4

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.
@@ -83,6 +83,9 @@ const InvoiceTable = _react.default.memo(props => {
83
83
  locale
84
84
  } = (0, _context.useLocaleContext)();
85
85
  const navigate = (0, _reactRouterDom.useNavigate)();
86
+ const {
87
+ getCurrency
88
+ } = (0, _payment.usePaymentContext)();
86
89
  const [search, setSearch] = (0, _react.useState)({
87
90
  pageSize: pageSize || 10,
88
91
  page: 1
@@ -222,52 +225,134 @@ const InvoiceTable = _react.default.memo(props => {
222
225
  }
223
226
  }
224
227
  }, ...(relatedSubscription ? [{
225
- label: t("common.relatedSubscription"),
226
- name: "subscription",
228
+ label: t("common.purchaseItems"),
229
+ name: "purchase_items",
227
230
  options: {
228
231
  customBodyRenderLite: (_, index) => {
229
232
  const invoice = data?.list[index];
230
- return invoice.subscription_id ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
231
- onClick: e => handleRelatedSubscriptionClick(e, invoice),
232
- sx: {
233
- color: "text.link",
233
+ const lines = invoice.lines || [];
234
+ const items = lines.map(line => {
235
+ const name = line.price?.product?.name || line.description;
236
+ if (!name) {
237
+ return null;
238
+ }
239
+ const quantity = Number(line.quantity || 0);
240
+ const label = Number.isFinite(quantity) && quantity > 1 ? `${name} x${quantity}` : name;
241
+ const lineKey = line.id || line.price?.id || line.price?.product?.id || line.description || name;
242
+ return {
243
+ key: String(lineKey),
244
+ label
245
+ };
246
+ }).filter(Boolean);
247
+ if (items.length === 0 && invoice.subscription?.description) {
248
+ items.push({
249
+ key: `subscription-${invoice.subscription_id || invoice.id}`,
250
+ label: invoice.subscription.description
251
+ });
252
+ }
253
+ const isSubscription = Boolean(invoice.subscription_id);
254
+ const clickableProps = isSubscription ? {
255
+ onClick: e => handleRelatedSubscriptionClick(e, invoice)
256
+ } : {};
257
+ if (items.length === 0) {
258
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
259
+ sx: {
260
+ color: "text.lighter"
261
+ },
262
+ children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
263
+ sx: {
264
+ fontSize: 14
265
+ },
266
+ children: t("common.none")
267
+ })
268
+ });
269
+ }
270
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
271
+ ...clickableProps,
272
+ sx: isSubscription ? {
234
273
  cursor: "pointer"
235
- },
236
- children: invoice.subscription?.description
237
- }) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
238
- onClick: e => handleLinkClick(e, invoice),
239
- sx: {
240
- ...linkStyle,
241
- color: "text.lighter"
242
- },
243
- children: t("common.none")
274
+ } : void 0,
275
+ children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, {
276
+ spacing: 0.5,
277
+ children: items.map(item => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
278
+ sx: {
279
+ fontSize: 14,
280
+ color: isSubscription ? "text.link" : "text.primary"
281
+ },
282
+ noWrap: true,
283
+ children: item.label
284
+ }, `${invoice.id}-item-${item.key}`))
285
+ })
244
286
  });
245
287
  }
246
288
  }
247
- }] : []), {
248
- label: t("common.updatedAt"),
249
- name: "name",
289
+ }, {
290
+ label: t("common.credits"),
291
+ name: "credits",
250
292
  options: {
251
- customBodyRenderLite: (val, index) => {
293
+ customBodyRenderLite: (_, index) => {
252
294
  const invoice = data?.list[index];
253
- return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
254
- onClick: e => handleLinkClick(e, invoice),
255
- sx: linkStyle,
256
- children: (0, _util.formatToDate)(invoice.created_at, locale, relatedSubscription ? "YYYY-MM-DD HH:mm" : "YYYY-MM-DD HH:mm:ss")
295
+ const lines = invoice.lines || [];
296
+ const creditItems = [];
297
+ lines.forEach(line => {
298
+ const lineKey = String(line.id || line.price?.id || line.price?.product?.id || line.description || invoice.id);
299
+ const pushCreditItem = (suffix, label) => {
300
+ creditItems.push({
301
+ key: `${lineKey}-${suffix}`,
302
+ label
303
+ });
304
+ };
305
+ const creditConfig = line.price?.metadata?.credit_config;
306
+ const creditAmount = Number(creditConfig?.credit_amount || 0);
307
+ if (creditAmount > 0) {
308
+ const quantity = Number(line.quantity || 0);
309
+ const totalAmount = creditAmount * (Number.isFinite(quantity) && quantity > 0 ? quantity : 1);
310
+ const currencySymbol = getCurrency(creditConfig?.currency_id)?.symbol || creditConfig?.currency_id || "Credits";
311
+ pushCreditItem("amount", `+${(0, _util.formatCreditAmount)(String(totalAmount), currencySymbol)}`);
312
+ return;
313
+ }
314
+ const scheduleConfig = creditConfig?.schedule;
315
+ const scheduledAmount = Number(scheduleConfig?.amount_per_grant || 0);
316
+ if (scheduleConfig?.enabled && scheduleConfig?.delivery_mode === "schedule" && scheduledAmount > 0) {
317
+ const quantity = Number(line.quantity || 0);
318
+ const totalAmount = scheduledAmount * (Number.isFinite(quantity) && quantity > 0 ? quantity : 1);
319
+ const currencySymbol = getCurrency(creditConfig?.currency_id)?.symbol || creditConfig?.currency_id || "Credits";
320
+ pushCreditItem("schedule", `+${(0, _util.formatCreditAmount)(String(totalAmount), currencySymbol)}`);
321
+ return;
322
+ }
323
+ const creditInfo = line.price?.credit;
324
+ const creditInfoAmount = Number(creditInfo?.amount || 0);
325
+ if (creditInfoAmount > 0) {
326
+ const currencySymbol = creditInfo.currency?.symbol || "Credits";
327
+ pushCreditItem("credit", `+${(0, _util.formatCreditAmount)(String(creditInfoAmount), currencySymbol)}`);
328
+ }
329
+ });
330
+ if (creditItems.length === 0) {
331
+ return "-";
332
+ }
333
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, {
334
+ spacing: 0.5,
335
+ children: creditItems.map(creditItem => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
336
+ sx: {
337
+ fontSize: 14,
338
+ color: "success.main"
339
+ },
340
+ noWrap: true,
341
+ children: creditItem.label
342
+ }, `${invoice.id}-credit-${creditItem.key}`))
257
343
  });
258
344
  }
259
345
  }
260
- }, {
261
- label: t("common.description"),
262
- name: "",
346
+ }] : []), {
347
+ label: t("common.updatedAt"),
348
+ name: "name",
263
349
  options: {
264
- sort: false,
265
350
  customBodyRenderLite: (val, index) => {
266
351
  const invoice = data?.list[index];
267
352
  return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
268
353
  onClick: e => handleLinkClick(e, invoice),
269
354
  sx: linkStyle,
270
- children: (0, _util.getInvoiceDescriptionAndReason)(invoice, locale)?.description || invoice.id
355
+ children: (0, _util.formatToDate)(invoice.created_at, locale, relatedSubscription ? "YYYY-MM-DD HH:mm" : "YYYY-MM-DD HH:mm:ss")
271
356
  });
272
357
  }
273
358
  }
package/lib/locales/en.js CHANGED
@@ -72,14 +72,24 @@ module.exports = (0, _flat.default)({
72
72
  remainingBalance: "Remaining Balance",
73
73
  credits: "credits",
74
74
  ofCredits: "of credits",
75
+ creditActivity: {
76
+ consumption: "Credit Consumed",
77
+ paidGrant: "Credit Top-up",
78
+ paidAmount: "Paid {amount}",
79
+ promotionalGrant: "Bonus",
80
+ resetGrant: "Credit Reset",
81
+ repayment: "Repayment"
82
+ },
75
83
  transferStatus: "Transaction Status",
76
84
  sourceData: "Source Data",
77
85
  viewGrant: "View Grant",
78
- viewSubscription: "View Subscription",
86
+ viewSubscription: "Subscription Detail",
79
87
  view: "View",
80
88
  meterEvent: "Meter Event",
81
89
  source: "Source",
82
90
  viewDetail: "View Detail",
91
+ viewTransactionDetail: "Transaction Detail",
92
+ viewConsumptionDetail: "Consumption Detail",
83
93
  customer: "Customer",
84
94
  currency: "Currency",
85
95
  custom: "Custom",
@@ -126,6 +136,8 @@ module.exports = (0, _flat.default)({
126
136
  slashStakeAmount: "Slash Stake Amount",
127
137
  know: "I know",
128
138
  relatedSubscription: "Subscription",
139
+ subscriptionOrCredit: "Subscription / Credit",
140
+ purchaseItems: "Purchase Items",
129
141
  connect: {
130
142
  defaultScan: "Use the following methods to complete this action",
131
143
  scan: "Use the following methods to complete this {action}",
@@ -133,8 +145,10 @@ module.exports = (0, _flat.default)({
133
145
  cancel: "Cancel"
134
146
  },
135
147
  paymentMethod: "Payment Method",
136
- viewInvoice: "View Invoice",
137
- submit: "Submit"
148
+ viewInvoice: "Invoice Detail",
149
+ submit: "Submit",
150
+ expired: "Expired",
151
+ consumed: "Consumed"
138
152
  },
139
153
  payment: {
140
154
  checkout: {
@@ -495,7 +509,9 @@ module.exports = (0, _flat.default)({
495
509
  amount: "Amount",
496
510
  paymentConfirmTitle: "Payment Confirmation",
497
511
  paymentConfirmDescription: "After completing this payment, the payment method you use will be automatically set as the default for this subscription. Additionally, we will retry payment for any other unpaid invoices associated with this subscription.",
498
- continue: "Continue"
512
+ continue: "Continue",
513
+ credit: "Credit",
514
+ creditRefresh: "Refresh every {interval} {unit}"
499
515
  },
500
516
  overduePayment: {
501
517
  setupPaymentDescription: "Use your saved card or add a new one to complete payment via Stripe.",
package/lib/locales/zh.js CHANGED
@@ -72,14 +72,24 @@ module.exports = (0, _flat.default)({
72
72
  remainingBalance: "\u5269\u4F59\u4F59\u989D",
73
73
  credits: "\u989D\u5EA6",
74
74
  ofCredits: "\u989D\u5EA6",
75
+ creditActivity: {
76
+ consumption: "\u989D\u5EA6\u6D88\u8017",
77
+ paidGrant: "\u989D\u5EA6\u5145\u503C",
78
+ paidAmount: "\u652F\u4ED8 {amount}",
79
+ promotionalGrant: "\u8D60\u9001",
80
+ resetGrant: "\u989D\u5EA6\u91CD\u7F6E",
81
+ repayment: "\u652F\u4ED8\u6B20\u8D39"
82
+ },
75
83
  transferStatus: "\u4EA4\u6613\u72B6\u6001",
76
84
  sourceData: "\u6E90\u6570\u636E",
77
85
  viewGrant: "\u67E5\u770B\u989D\u5EA6",
78
- viewSubscription: "\u67E5\u770B\u8BA2\u9605",
86
+ viewSubscription: "\u8BA2\u9605\u8BE6\u60C5",
79
87
  view: "\u67E5\u770B",
80
88
  meterEvent: "\u8BA1\u91CF\u4E8B\u4EF6",
81
89
  source: "\u6765\u6E90",
82
90
  viewDetail: "\u67E5\u770B\u8BE6\u60C5",
91
+ viewTransactionDetail: "\u4EA4\u6613\u8BE6\u60C5",
92
+ viewConsumptionDetail: "\u6D88\u8D39\u8BE6\u60C5",
83
93
  customer: "\u5BA2\u6237",
84
94
  currency: "\u5E01\u79CD",
85
95
  custom: "\u81EA\u5B9A\u4E49",
@@ -126,6 +136,8 @@ module.exports = (0, _flat.default)({
126
136
  slashStakeAmount: "\u7F5A\u6CA1\u91D1\u989D",
127
137
  know: "\u6211\u77E5\u9053\u4E86",
128
138
  relatedSubscription: "\u8BA2\u9605",
139
+ subscriptionOrCredit: "\u8BA2\u9605 / \u989D\u5EA6",
140
+ purchaseItems: "\u8D2D\u4E70\u9879",
129
141
  connect: {
130
142
  defaultScan: "\u4F7F\u7528\u4EE5\u4E0B\u65B9\u5F0F\u5B8C\u6210\u672C\u6B21\u64CD\u4F5C",
131
143
  scan: "\u4F7F\u7528\u4EE5\u4E0B\u65B9\u5F0F\u5B8C\u6210\u672C\u6B21{action}",
@@ -133,8 +145,10 @@ module.exports = (0, _flat.default)({
133
145
  cancel: "\u53D6\u6D88"
134
146
  },
135
147
  paymentMethod: "\u652F\u4ED8\u65B9\u5F0F",
136
- viewInvoice: "\u67E5\u770B\u8D26\u5355",
137
- submit: "\u63D0\u4EA4"
148
+ viewInvoice: "\u8D26\u5355\u8BE6\u60C5",
149
+ submit: "\u63D0\u4EA4",
150
+ expired: "\u5DF2\u8FC7\u671F",
151
+ consumed: "\u5DF2\u6D88\u8D39"
138
152
  },
139
153
  payment: {
140
154
  checkout: {
@@ -497,7 +511,9 @@ module.exports = (0, _flat.default)({
497
511
  payBatch: "\u652F\u4ED8\u6B20\u6B3E",
498
512
  paymentConfirmTitle: "\u652F\u4ED8\u786E\u8BA4",
499
513
  paymentConfirmDescription: "\u5B8C\u6210\u672C\u6B21\u652F\u4ED8\u540E\uFF0C\u60A8\u4F7F\u7528\u7684\u652F\u4ED8\u65B9\u5F0F\u5C06\u81EA\u52A8\u8BBE\u7F6E\u4E3A\u8BE5\u8BA2\u9605\u7684\u9ED8\u8BA4\u652F\u4ED8\u65B9\u5F0F\u3002\u6B64\u5916\uFF0C\u6211\u4EEC\u8FD8\u5C06\u5BF9\u8BE5\u8BA2\u9605\u7684\u5176\u4ED6\u6B20\u8D39\u8D26\u5355\u8FDB\u884C\u91CD\u8BD5\u6536\u8D39\u3002",
500
- continue: "\u7EE7\u7EED"
514
+ continue: "\u7EE7\u7EED",
515
+ credit: "\u989D\u5EA6",
516
+ creditRefresh: "\u6BCF{interval}{unit}\u5237\u65B0"
501
517
  },
502
518
  payment: {
503
519
  empty: "\u6CA1\u6709\u652F\u4ED8\u8BB0\u5F55",
@@ -113,7 +113,9 @@ function ProductItem({
113
113
  if (!isCreditProduct || !pendingAmount) return null;
114
114
  const pendingAmountBN = new _util.BN(pendingAmount || "0");
115
115
  if (!pendingAmountBN.gt(new _util.BN(0))) return null;
116
+ if (!creditAmount || creditAmount <= 0) return null;
116
117
  const creditAmountBN = (0, _util.fromTokenToUnit)(creditAmount, creditCurrency?.decimal || 2);
118
+ if (!creditAmountBN || creditAmountBN.isZero()) return null;
117
119
  return Math.ceil(pendingAmountBN.mul(new _util.BN(100)).div(creditAmountBN).toNumber() / 100);
118
120
  }, [isCreditProduct, pendingAmount, creditAmount, creditCurrency?.decimal]);
119
121
  const initialQuantity = (0, _react.useMemo)(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/payment-react",
3
- "version": "1.24.2",
3
+ "version": "1.24.4",
4
4
  "description": "Reusable react components for payment kit v2",
5
5
  "keywords": [
6
6
  "react",
@@ -96,7 +96,7 @@
96
96
  "@babel/core": "^7.27.4",
97
97
  "@babel/preset-env": "^7.27.2",
98
98
  "@babel/preset-react": "^7.27.1",
99
- "@blocklet/payment-types": "1.24.2",
99
+ "@blocklet/payment-types": "1.24.4",
100
100
  "@storybook/addon-essentials": "^7.6.20",
101
101
  "@storybook/addon-interactions": "^7.6.20",
102
102
  "@storybook/addon-links": "^7.6.20",
@@ -127,5 +127,5 @@
127
127
  "vite-plugin-babel": "^1.3.1",
128
128
  "vite-plugin-node-polyfills": "^0.23.0"
129
129
  },
130
- "gitHead": "8cefbfb9066513c7fb33beb2185ea4e58968aad7"
130
+ "gitHead": "d4a5f67e657cafa8862912bb8de38a3d56a7919d"
131
131
  }
@@ -7,6 +7,7 @@ import { createContext, useContext, useEffect, useState } from 'react';
7
7
 
8
8
  import axios from 'axios';
9
9
  import { joinURL } from 'ufo';
10
+ import useBus from 'use-bus';
10
11
  import api from '../libs/api';
11
12
  import { getPrefix, PAYMENT_KIT_DID } from '../libs/util';
12
13
  import { CachedRequest } from '../libs/cached-request';
@@ -178,6 +179,14 @@ function PaymentProvider({
178
179
  refreshDeps: [livemode],
179
180
  });
180
181
 
182
+ // Listen for settings changes and force refresh
183
+ useBus(
184
+ // @ts-ignore
185
+ ['paymentMethod.created', 'paymentMethod.updated', 'paymentCurrency.added', 'paymentCurrency.updated'],
186
+ () => run(true),
187
+ [run]
188
+ );
189
+
181
190
  useEffect(() => {
182
191
  const didSpace = session?.user?.didSpace as
183
192
  | {