@blocklet/payment-react 1.19.22 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.aigne/doc-smith/config.yaml +114 -0
- package/.aigne/doc-smith/output/structure-plan.json +361 -0
- package/.aigne/doc-smith/preferences.yml +55 -0
- package/.aigne/doc-smith/upload-cache.yaml +264 -0
- package/README.md +2 -3
- package/docs/_sidebar.md +33 -0
- package/docs/components-business-auto-topup.md +238 -0
- package/docs/components-business-overdue-invoice-payment.md +231 -0
- package/docs/components-business-resume-subscription.md +177 -0
- package/docs/components-business.md +45 -0
- package/docs/components-checkout-checkout-donate.md +199 -0
- package/docs/components-checkout-checkout-form.md +185 -0
- package/docs/components-checkout-checkout-table.md +228 -0
- package/docs/components-checkout.md +131 -0
- package/docs/components-history-credit-grants-list.md +98 -0
- package/docs/components-history-credit-transactions-list.md +116 -0
- package/docs/components-history-invoice-list.md +104 -0
- package/docs/components-history-payment-list.md +65 -0
- package/docs/components-history.md +92 -0
- package/docs/components-ui-form-elements-address-form.md +150 -0
- package/docs/components-ui-form-elements-country-select.md +105 -0
- package/docs/components-ui-form-elements-currency-selector.md +124 -0
- package/docs/components-ui-form-elements-phone-input.md +160 -0
- package/docs/components-ui-form-elements.md +125 -0
- package/docs/components-ui-payment-summary.md +157 -0
- package/docs/components-ui-pricing-table.md +227 -0
- package/docs/components-ui.md +44 -0
- package/docs/components.md +95 -0
- package/docs/getting-started.md +111 -0
- package/docs/guides-theming.md +175 -0
- package/docs/guides-utilities.md +235 -0
- package/docs/guides.md +95 -0
- package/docs/hooks-use-mobile.md +70 -0
- package/docs/hooks-use-subscription.md +129 -0
- package/docs/hooks.md +84 -0
- package/docs/overview.md +87 -0
- package/docs/providers-donate-provider.md +175 -0
- package/docs/providers-payment-provider.md +245 -0
- package/docs/providers.md +101 -0
- package/es/payment/form/index.js +15 -1
- package/lib/payment/form/index.js +14 -1
- package/package.json +5 -5
- package/src/payment/form/index.tsx +16 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# CreditTransactionsList
|
|
2
|
+
|
|
3
|
+
The `CreditTransactionsList` component renders a detailed and paginated table of credit transactions. It serves as a comprehensive log, allowing users to track how their credits have been utilized or adjusted over time. This component is essential for providing transparency in credit-based billing systems.
|
|
4
|
+
|
|
5
|
+
### Context Requirement
|
|
6
|
+
|
|
7
|
+
This component requires access to the session context to identify the current user. Therefore, it must be rendered within a `PaymentProvider`. For details on setting up the provider and a `useSessionContext` hook, please refer to the [PaymentProvider documentation](./providers-payment-provider.md).
|
|
8
|
+
|
|
9
|
+
### Properties
|
|
10
|
+
|
|
11
|
+
The `CreditTransactionsList` component accepts the following properties:
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Description | Default |
|
|
14
|
+
| --- | --- | --- | --- |
|
|
15
|
+
| `customer_id` | `string` | The ID of the customer whose transactions are to be displayed. If omitted, it defaults to the DID of the currently logged-in user from the session context. | `session.user.did` |
|
|
16
|
+
| `subscription_id` | `string` | Filters the transactions to show only those related to a specific subscription ID. | `''` |
|
|
17
|
+
| `credit_grant_id` | `string` | Filters the transactions to show only those related to a specific credit grant ID. | `''` |
|
|
18
|
+
| `pageSize` | `number` | The number of transactions to display per page. | `10` |
|
|
19
|
+
| `onTableDataChange` | `(data, prevData) => void` | A callback function that is triggered when the transaction data is fetched or updated. It receives the new data and the previous data as arguments. | `() => {}` |
|
|
20
|
+
| `showAdminColumns` | `boolean` | If `true`, additional columns relevant to administrators (such as 'Meter Event') are displayed. This only applies if the logged-in user has an 'owner' or 'admin' role. | `false` |
|
|
21
|
+
| `showTimeFilter` | `boolean` | If `true`, a date range picker is displayed above the table, allowing users to filter transactions by a specific time period. | `false` |
|
|
22
|
+
| `source` | `string` | An optional string to filter transactions by their source. | `''` |
|
|
23
|
+
| `mode` | `'dashboard' \| 'portal'` | Controls the navigation behavior of links within the table. Use `'dashboard'` for admin-facing views and `'portal'` for standard customer-facing portals. | `'portal'` |
|
|
24
|
+
|
|
25
|
+
### Usage Scenarios
|
|
26
|
+
|
|
27
|
+
All examples assume you have a `useSessionContext` hook configured as outlined in the `PaymentProvider` guide.
|
|
28
|
+
|
|
29
|
+
#### 1. Basic Customer View
|
|
30
|
+
|
|
31
|
+
To display the credit transaction history for the currently logged-in user, you can render the component without any specific IDs. It will automatically fetch the user's data from the session context.
|
|
32
|
+
|
|
33
|
+
```jsx
|
|
34
|
+
import React from 'react';
|
|
35
|
+
import { CreditTransactionsList } from '@blocklet/payment-react/components/history';
|
|
36
|
+
// Assuming useSessionContext is set up according to the PaymentProvider guide
|
|
37
|
+
import { useSessionContext } from '../../contexts/session';
|
|
38
|
+
|
|
39
|
+
export default function UserCreditHistoryPage() {
|
|
40
|
+
const { session } = useSessionContext();
|
|
41
|
+
|
|
42
|
+
// Render the component only when the session is active
|
|
43
|
+
if (!session.user) {
|
|
44
|
+
return <p>Please log in to see your credit history.</p>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<>
|
|
49
|
+
<h2>My Credit Transactions</h2>
|
|
50
|
+
<CreditTransactionsList pageSize={5} />
|
|
51
|
+
</>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
#### 2. Admin View with Filters
|
|
57
|
+
|
|
58
|
+
For an administrative dashboard, you can display transactions for a specific customer by providing their `customer_id`. You can also enable admin-specific columns and the date filter to provide more powerful data exploration tools.
|
|
59
|
+
|
|
60
|
+
```jsx
|
|
61
|
+
import React from 'react';
|
|
62
|
+
import { CreditTransactionsList } from '@blocklet/payment-react/components/history';
|
|
63
|
+
// Assuming useSessionContext is set up according to the PaymentProvider guide
|
|
64
|
+
import { useSessionContext } from '../../contexts/session';
|
|
65
|
+
|
|
66
|
+
export default function AdminCustomerCreditHistory({ customerId }) {
|
|
67
|
+
const { session } = useSessionContext();
|
|
68
|
+
const isAdmin = ['owner', 'admin'].includes(session?.user?.role || '');
|
|
69
|
+
|
|
70
|
+
if (!isAdmin) {
|
|
71
|
+
return <p>Access Denied.</p>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<>
|
|
76
|
+
<h2>Credit Transactions for Customer {customerId}</h2>
|
|
77
|
+
<CreditTransactionsList
|
|
78
|
+
customer_id={customerId}
|
|
79
|
+
showAdminColumns={true}
|
|
80
|
+
showTimeFilter={true}
|
|
81
|
+
mode="dashboard"
|
|
82
|
+
/>
|
|
83
|
+
</>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
#### 3. Transactions for a Specific Credit Grant
|
|
89
|
+
|
|
90
|
+
When you need to show a detailed usage report for a single credit grant, pass the `credit_grant_id`. This will filter the list to show only the transactions associated with that grant.
|
|
91
|
+
|
|
92
|
+
```jsx
|
|
93
|
+
import React from 'react';
|
|
94
|
+
import { CreditTransactionsList } from '@blocklet/payment-react/components/history';
|
|
95
|
+
|
|
96
|
+
export default function CreditGrantUsageDetails({ grantId }) {
|
|
97
|
+
return (
|
|
98
|
+
<>
|
|
99
|
+
<h3>Transaction History for this Grant</h3>
|
|
100
|
+
<CreditTransactionsList credit_grant_id={grantId} />
|
|
101
|
+
</>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Table Columns
|
|
107
|
+
|
|
108
|
+
The component renders a table with the following columns:
|
|
109
|
+
|
|
110
|
+
- **Amount**: The value of the credit transaction and its unit.
|
|
111
|
+
- **Credit Grant**: A link to the parent credit grant. This column is automatically hidden if the list is already filtered by a `credit_grant_id`.
|
|
112
|
+
- **Description**: Provides context for the transaction, such as the associated subscription or usage event.
|
|
113
|
+
- **Meter Event** (Admin Only): A link to the specific billing meter event that triggered the transaction. This is only visible when `showAdminColumns` is `true` and the user is an admin.
|
|
114
|
+
- **Date**: The timestamp indicating when the transaction was created.
|
|
115
|
+
|
|
116
|
+
After displaying credit usage, you might want to show an overview of all credit grants. To do this, you can use the [`CreditGrantsList`](./components-history-credit-grants-list.md) component.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# CustomerInvoiceList
|
|
2
|
+
|
|
3
|
+
The `CustomerInvoiceList` component renders a history of invoices for a specific customer or subscription. It supports two display formats: a compact list grouped by date (`list`) and a detailed, paginated table (`table`). The component can also display a 'Pay' button for open invoices, initiating the payment flow when clicked.
|
|
4
|
+
|
|
5
|
+
To function correctly, especially for payment actions and real-time updates, this component must be wrapped within a `PaymentProvider`. For details on setting up the provider and the `useSessionContext` hook, please refer to the [PaymentProvider documentation](./providers-payment-provider.md).
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
| Prop | Type | Description | Default |
|
|
10
|
+
| --- | --- | --- | --- |
|
|
11
|
+
| `customer_id` | `string` | The ID of the customer whose invoices are to be displayed. | `''` |
|
|
12
|
+
| `subscription_id` | `string` | The ID of the subscription for which to display invoices. | `''` |
|
|
13
|
+
| `currency_id` | `string` | Filters invoices by a specific currency ID. | `''` |
|
|
14
|
+
| `include_staking` | `boolean` | If `true`, includes staking-related invoices in the list. | `false` |
|
|
15
|
+
| `include_return_staking` | `boolean` | If `true`, includes invoices for returned stakes. | `false` |
|
|
16
|
+
| `include_recovered_from` | `boolean` | If `true`, includes invoices that were recovered from bad debt. | `false` |
|
|
17
|
+
| `status` | `string` | A comma-separated string of invoice statuses to display (e.g., 'open,paid,uncollectible,void'). | `'open,paid,uncollectible'` |
|
|
18
|
+
| `pageSize` | `number` | The number of invoices to display per page. | `10` |
|
|
19
|
+
| `target` | `string` | The target attribute for invoice links (e.g., `_self`, `_blank`). | `'_self'` |
|
|
20
|
+
| `action` | `string` | If set (e.g., to `'pay'`), a 'Pay' button is rendered for open or uncollectible invoices, triggering the payment flow on click. | `''` |
|
|
21
|
+
| `type` | `'list'` \| `'table'` | Determines the rendering mode. `'list'` groups invoices by date, while `'table'` shows a detailed data grid. | `'list'` |
|
|
22
|
+
| `onTableDataChange` | `(newData, oldData) => void` | A callback function that fires when the invoice data is loaded or refreshed. | `() => {}` |
|
|
23
|
+
| `relatedSubscription` | `boolean` | When `type` is `'table'`, setting this to `true` adds a column showing the subscription related to each invoice. | `false` |
|
|
24
|
+
|
|
25
|
+
## Usage Scenarios
|
|
26
|
+
|
|
27
|
+
### Basic Invoice History
|
|
28
|
+
|
|
29
|
+
To display a simple list of invoices for a particular subscription, set the `subscription_id` and use the default `type='list'`. This mode is ideal for a quick overview of past transactions.
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { PaymentProvider, CustomerInvoiceList } from '@blocklet/payment-react';
|
|
33
|
+
import { useSessionContext } from '../hooks/session'; // Your local session context hook
|
|
34
|
+
|
|
35
|
+
function InvoiceHistoryPage({ subscriptionId }) {
|
|
36
|
+
const { session, connectApi } = useSessionContext();
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<PaymentProvider session={session} connect={connectApi}>
|
|
40
|
+
<h2>Invoice History</h2>
|
|
41
|
+
<CustomerInvoiceList
|
|
42
|
+
subscription_id={subscriptionId}
|
|
43
|
+
status="paid,void"
|
|
44
|
+
/>
|
|
45
|
+
</PaymentProvider>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Detailed Invoice Table
|
|
51
|
+
|
|
52
|
+
For a more detailed view, use `type='table'`. This mode provides pagination and multiple columns of data, making it suitable for dashboards or customer management pages. You can also add the `relatedSubscription` column for customers with multiple subscriptions.
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import { PaymentProvider, CustomerInvoiceList } from '@blocklet/payment-react';
|
|
56
|
+
import { useSessionContext } from '../hooks/session'; // Your local session context hook
|
|
57
|
+
|
|
58
|
+
function CustomerDashboard({ customerId }) {
|
|
59
|
+
const { session, connectApi } = useSessionContext();
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<PaymentProvider session={session} connect={connectApi}>
|
|
63
|
+
<h3>All Invoices</h3>
|
|
64
|
+
<CustomerInvoiceList
|
|
65
|
+
customer_id={customerId}
|
|
66
|
+
type="table"
|
|
67
|
+
pageSize={20}
|
|
68
|
+
include_staking={true}
|
|
69
|
+
relatedSubscription={true}
|
|
70
|
+
status="open,paid,uncollectible,void"
|
|
71
|
+
/>
|
|
72
|
+
</PaymentProvider>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Invoices with Payment Action
|
|
78
|
+
|
|
79
|
+
By setting the `action` prop, you can enable a 'Pay' button for any invoices that are `open` or `uncollectible`. Clicking this button will open the payment modal provided by `PaymentProvider` to complete the transaction.
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import { PaymentProvider, CustomerInvoiceList } from '@blocklet/payment-react';
|
|
83
|
+
import { useSessionContext } from '../hooks/session'; // Your local session context hook
|
|
84
|
+
|
|
85
|
+
function PayInvoices({ customerId }) {
|
|
86
|
+
const { session, connectApi } = useSessionContext();
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<PaymentProvider session={session} connect={connectApi}>
|
|
90
|
+
<h3>Outstanding Invoices</h3>
|
|
91
|
+
<CustomerInvoiceList
|
|
92
|
+
customer_id={customerId}
|
|
93
|
+
status="open,uncollectible"
|
|
94
|
+
action="pay" // This enables the "Pay" button
|
|
95
|
+
type="table"
|
|
96
|
+
/>
|
|
97
|
+
</PaymentProvider>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Real-time Updates
|
|
103
|
+
|
|
104
|
+
The component automatically subscribes to the `invoice.paid` WebSocket event. When a customer successfully pays an invoice, the list will refresh in real-time to reflect the new `paid` status without requiring a page reload. This ensures that the invoice data is always up-to-date.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# CustomerPaymentList
|
|
2
|
+
|
|
3
|
+
The `CustomerPaymentList` component renders a detailed history of a customer's payments. It is designed for efficiency, featuring infinite scrolling to handle large numbers of transactions without compromising performance. Payments are automatically grouped by date for easy navigation and review.
|
|
4
|
+
|
|
5
|
+
## Props
|
|
6
|
+
|
|
7
|
+
| Prop | Type | Description | Required |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| `customer_id` | `string` | The ID of the customer whose payment history should be displayed. | Yes |
|
|
10
|
+
|
|
11
|
+
## Usage Example
|
|
12
|
+
|
|
13
|
+
To use the `CustomerPaymentList`, you must provide a `customer_id`. The component handles all the logic for fetching, paginating, and displaying the payment data. It must be wrapped within a `PaymentProvider` to function correctly.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { PaymentProvider, CustomerPaymentList } from '@blocklet/payment-react';
|
|
17
|
+
import { useSessionContext } from '../hooks/session'; // This is your app's custom session hook
|
|
18
|
+
import { Box, Typography } from '@mui/material';
|
|
19
|
+
|
|
20
|
+
function CustomerProfilePage() {
|
|
21
|
+
// Get session and connectApi from your application's session context.
|
|
22
|
+
const { session, connectApi } = useSessionContext();
|
|
23
|
+
|
|
24
|
+
// The customer ID would typically be the DID of the logged-in user.
|
|
25
|
+
const customerDid = session?.user?.did;
|
|
26
|
+
|
|
27
|
+
if (!session || !customerDid) {
|
|
28
|
+
return <Typography>Please log in to view payment history.</Typography>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<PaymentProvider session={session} connect={connectApi}>
|
|
33
|
+
<Box sx={{ p: 3 }}>
|
|
34
|
+
<Typography variant="h5" gutterBottom>
|
|
35
|
+
Payment History
|
|
36
|
+
</Typography>
|
|
37
|
+
<CustomerPaymentList customer_id={customerDid} />
|
|
38
|
+
</Box>
|
|
39
|
+
</PaymentProvider>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default CustomerProfilePage;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
In the example above, `useSessionContext` is a custom hook responsible for providing your application's session state. For detailed instructions on how to set up the `PaymentProvider` and create a session context, please refer to our guide on the [PaymentProvider](./providers-payment-provider.md).
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- **Automatic Pagination**: The component automatically fetches and renders payments in pages. A "Load More" button appears when more transactions are available, allowing users to load history on demand.
|
|
51
|
+
|
|
52
|
+
- **Date-Based Grouping**: To improve readability, all payments are grouped under the date they were created, making it easy to find transactions from a specific day.
|
|
53
|
+
|
|
54
|
+
- **Detailed Payment Information**: Each row in the list provides key details about the transaction:
|
|
55
|
+
- **Date & Time**: The exact creation time of the payment.
|
|
56
|
+
- **Amount**: The total amount received, formatted with the correct currency symbol.
|
|
57
|
+
- **Status**: The current status of the payment (e.g., `succeeded`, `processing`) shown with a colored indicator using the `Status` component.
|
|
58
|
+
- **Description**: The description associated with the payment intent.
|
|
59
|
+
- **Transaction Link**: A direct link to the relevant blockchain explorer for on-chain transactions, if applicable.
|
|
60
|
+
|
|
61
|
+
- **Loading and Empty States**: A loading indicator is displayed while the initial payment data is being fetched. If the customer has no payment history, a clear message is shown instead of an empty list.
|
|
62
|
+
|
|
63
|
+
## Related Components
|
|
64
|
+
|
|
65
|
+
For displaying a customer's invoice history, which is often related to their payment history, see the [`CustomerInvoiceList`](./components-history-invoice-list.md) component.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# History Components
|
|
2
|
+
|
|
3
|
+
The History Components are a suite of tools designed to give customers a clear and detailed view of their financial interactions. They are essential for building transparent and user-friendly account management sections, such as a customer portal or a billing history page. These components fetch and display data related to invoices, payments, and credit balances, providing a complete historical record.
|
|
4
|
+
|
|
5
|
+
```d2
|
|
6
|
+
direction: down
|
|
7
|
+
|
|
8
|
+
"Customer Portal" -> "Billing Section"
|
|
9
|
+
|
|
10
|
+
"Billing Section": {
|
|
11
|
+
"Invoices": "CustomerInvoiceList"
|
|
12
|
+
"Payments": "CustomerPaymentList"
|
|
13
|
+
"Credits": {
|
|
14
|
+
"Grants": "CreditGrantsList"
|
|
15
|
+
"Usage": "CreditTransactionsList"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
This section provides an overview of the components available for displaying historical data. Each component is designed to be easily integrated into your application to provide a specific piece of a customer's history.
|
|
21
|
+
|
|
22
|
+
<x-cards data-columns="2">
|
|
23
|
+
<x-card data-title="CustomerInvoiceList" data-icon="lucide:receipt" data-href="/components/history/invoice-list">
|
|
24
|
+
Renders a list of a customer's invoices, including key details like the amount, status, date, and a link to view the full invoice. It supports both a simple list view and a more detailed table view.
|
|
25
|
+
</x-card>
|
|
26
|
+
<x-card data-title="CustomerPaymentList" data-icon="lucide:credit-card" data-href="/components/history/payment-list">
|
|
27
|
+
Use this component to display a complete history of payments made by a customer. It lists each payment with its amount, status, date, and a link to the corresponding transaction on the blockchain, if applicable.
|
|
28
|
+
</x-card>
|
|
29
|
+
<x-card data-title="CreditGrantsList" data-icon="lucide:gift" data-href="/components/history/credit-grants-list">
|
|
30
|
+
The `CreditGrantsList` component shows all credit grants a customer has received. It details the status, remaining balance, and validity period of each grant, which is useful for managing promotional credits or prepaid balances.
|
|
31
|
+
</x-card>
|
|
32
|
+
<x-card data-title="CreditTransactionsList" data-icon="lucide:list-ordered" data-href="/components/history/credit-transactions-list">
|
|
33
|
+
To provide a granular view of how credits are used, the `CreditTransactionsList` component logs every transaction that affects a customer's credit balance. This includes credit deductions for service usage and any adjustments.
|
|
34
|
+
</x-card>
|
|
35
|
+
</x-cards>
|
|
36
|
+
|
|
37
|
+
### Example: Building a Billing Page
|
|
38
|
+
|
|
39
|
+
You can easily combine these components using a tabbed interface to create a complete billing history section for your users. Most history components rely on `PaymentProvider` to access the DID Connect instance for actions like paying an invoice.
|
|
40
|
+
|
|
41
|
+
The following example shows how to set up a complete billing page. It assumes you have a local `session.js` or `session.ts` file that exports `useSessionContext` for your DID Connect integration. For more details on setting up the provider, see the [PaymentProvider documentation](./providers-payment-provider.md).
|
|
42
|
+
|
|
43
|
+
```jsx
|
|
44
|
+
import React from 'react';
|
|
45
|
+
import { Tabs, Tab, Box, Typography } from '@mui/material';
|
|
46
|
+
import { PaymentProvider } from '@blocklet/payment-react/lib/contexts/payment';
|
|
47
|
+
import { useSessionContext } from '../contexts/session'; // Your local session context
|
|
48
|
+
|
|
49
|
+
import CustomerInvoiceList from '@blocklet/payment-react/lib/history/invoice/list';
|
|
50
|
+
import CustomerPaymentList from '@blocklet/payment-react/lib/history/payment/list';
|
|
51
|
+
import CreditGrantsList from '@blocklet/payment-react/lib/history/credit/grants-list';
|
|
52
|
+
import CreditTransactionsList from '@blocklet/payment-react/lib/history/credit/transactions-list';
|
|
53
|
+
|
|
54
|
+
function BillingHistoryPage() {
|
|
55
|
+
const { session, connect } = useSessionContext();
|
|
56
|
+
const [tab, setTab] = React.useState(0);
|
|
57
|
+
|
|
58
|
+
const handleChange = (event, newValue) => {
|
|
59
|
+
setTab(newValue);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// The customerId is the user's DID from the session.
|
|
63
|
+
const customerId = session.user?.did;
|
|
64
|
+
|
|
65
|
+
if (!session.ready || !customerId) {
|
|
66
|
+
return <Typography>Please log in to view your billing history.</Typography>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<PaymentProvider connect={connect}>
|
|
71
|
+
<Box sx={{ width: '100%' }}>
|
|
72
|
+
<Tabs value={tab} onChange={handleChange} aria-label="billing history tabs">
|
|
73
|
+
<Tab label="Invoices" />
|
|
74
|
+
<Tab label="Payments" />
|
|
75
|
+
<Tab label="Credit Grants" />
|
|
76
|
+
<Tab label="Credit Usage" />
|
|
77
|
+
</Tabs>
|
|
78
|
+
<Box sx={{ p: 3 }}>
|
|
79
|
+
{tab === 0 && <CustomerInvoiceList customer_id={customerId} type="table" />}
|
|
80
|
+
{tab === 1 && <CustomerPaymentList customer_id={customerId} />}
|
|
81
|
+
{tab === 2 && <CreditGrantsList customer_id={customerId} />}
|
|
82
|
+
{tab === 3 && <CreditTransactionsList customer_id={customerId} />}
|
|
83
|
+
</Box>
|
|
84
|
+
</Box>
|
|
85
|
+
</PaymentProvider>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
By using these components, you can build a comprehensive and professional billing history section. This not only improves user experience but also reduces support inquiries by providing customers with self-service access to their data.
|
|
91
|
+
|
|
92
|
+
After implementing history views, you may want to explore advanced topics like customization and theming. Continue to the next section to learn more in our [Guides](./guides.md).
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# AddressForm
|
|
2
|
+
|
|
3
|
+
The `AddressForm` component provides a pre-built UI for collecting billing address details. It includes fields for address line 1, city, state, postal code, and country, with built-in validation that adapts based on the selected country.
|
|
4
|
+
|
|
5
|
+
This component is designed to work seamlessly within the context of `react-hook-form`.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
| Prop | Type | Description | Required |
|
|
10
|
+
| --- | --- | --- | :---: |
|
|
11
|
+
| `mode` | `string` | Determines the form's behavior. Set to `'required'` to display the full address form. | Yes |
|
|
12
|
+
| `stripe` | `boolean` | If `true` and `mode` is not `'required'`, it displays a simplified form with only postal code and country. | Yes |
|
|
13
|
+
| `sx` | `SxProps` | Custom MUI styles to be applied to the root `Stack` component. | No |
|
|
14
|
+
| `fieldValidation` | `Record<string, any>` | An object for providing custom validation rules, such as regex patterns, for specific fields. | No |
|
|
15
|
+
| `errorPosition` | `'right'` \| `'bottom'` | Specifies the position of validation error messages relative to the input fields. Defaults to `'right'`. | No |
|
|
16
|
+
|
|
17
|
+
## Integration with React Hook Form
|
|
18
|
+
|
|
19
|
+
`AddressForm` uses `useFormContext` and therefore must be a descendant of a `FormProvider` component from `react-hook-form`. In a typical application, a higher-level component like `CheckoutForm` would wrap your feature and provide this context automatically.
|
|
20
|
+
|
|
21
|
+
Note: The following examples assume you have set up `PaymentProvider` and a local `useSessionContext` hook as described in the [PaymentProvider documentation](./providers-payment-provider.md).
|
|
22
|
+
|
|
23
|
+
## Usage Scenarios
|
|
24
|
+
|
|
25
|
+
### Complete Address Form
|
|
26
|
+
|
|
27
|
+
To collect a full billing address, set the `mode` prop to `'required'`. This will render all address fields as mandatory.
|
|
28
|
+
|
|
29
|
+
```jsx
|
|
30
|
+
import { FormProvider, useForm } from 'react-hook-form';
|
|
31
|
+
import { AddressForm } from '@blocklet/payment-react';
|
|
32
|
+
import { Button, Stack } from '@mui/material';
|
|
33
|
+
import { useSessionContext } from '../hooks/session'; // Adjust path to your session hook
|
|
34
|
+
|
|
35
|
+
export default function FullAddressFormExample() {
|
|
36
|
+
// Standard context setup. Not used in this specific form but required for consistency.
|
|
37
|
+
const { session, connectApi } = useSessionContext();
|
|
38
|
+
|
|
39
|
+
const methods = useForm({
|
|
40
|
+
mode: 'onTouched',
|
|
41
|
+
defaultValues: {
|
|
42
|
+
billing_address: {
|
|
43
|
+
line1: '',
|
|
44
|
+
city: '',
|
|
45
|
+
state: '',
|
|
46
|
+
postal_code: '',
|
|
47
|
+
country: 'US',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const onSubmit = (data) => {
|
|
53
|
+
alert('Form Submitted! Check console for data.');
|
|
54
|
+
console.log('Billing Address:', data.billing_address);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<FormProvider {...methods}>
|
|
59
|
+
<form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
60
|
+
<Stack spacing={2}>
|
|
61
|
+
<AddressForm mode="required" stripe={false} errorPosition="bottom" />
|
|
62
|
+
<Button type="submit" variant="contained">
|
|
63
|
+
Submit Address
|
|
64
|
+
</Button>
|
|
65
|
+
</Stack>
|
|
66
|
+
</form>
|
|
67
|
+
</FormProvider>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Simplified Stripe Form
|
|
73
|
+
|
|
74
|
+
In some payment flows, particularly with Stripe, only the postal code and country might be required for verification. To render this simplified version, ensure `mode` is not `'required'` and set the `stripe` prop to `true`.
|
|
75
|
+
|
|
76
|
+
```jsx
|
|
77
|
+
import { FormProvider, useForm } from 'react-hook-form';
|
|
78
|
+
import { AddressForm } from '@blocklet/payment-react';
|
|
79
|
+
import { Button, Stack } from '@mui/material';
|
|
80
|
+
import { useSessionContext } from '../hooks/session'; // Adjust path to your session hook
|
|
81
|
+
|
|
82
|
+
export default function StripeAddressFormExample() {
|
|
83
|
+
// Standard context setup. Not used in this specific form but required for consistency.
|
|
84
|
+
const { session, connectApi } = useSessionContext();
|
|
85
|
+
|
|
86
|
+
const methods = useForm({
|
|
87
|
+
mode: 'onTouched',
|
|
88
|
+
defaultValues: {
|
|
89
|
+
billing_address: {
|
|
90
|
+
postal_code: '',
|
|
91
|
+
country: 'US',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const onSubmit = (data) => {
|
|
97
|
+
alert('Form Submitted! Check console for data.');
|
|
98
|
+
console.log('Billing Info:', data.billing_address);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<FormProvider {...methods}>
|
|
103
|
+
<form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
104
|
+
<Stack spacing={2}>
|
|
105
|
+
<AddressForm mode="optional" stripe={true} errorPosition="bottom" />
|
|
106
|
+
<Button type="submit" variant="contained">
|
|
107
|
+
Submit
|
|
108
|
+
</Button>
|
|
109
|
+
</Stack>
|
|
110
|
+
</form>
|
|
111
|
+
</FormProvider>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Validation
|
|
117
|
+
|
|
118
|
+
`AddressForm` handles validation for required fields automatically. It also includes special validation logic for postal codes.
|
|
119
|
+
|
|
120
|
+
### Postal Code Validation
|
|
121
|
+
|
|
122
|
+
The postal code field is dynamically validated based on the selected country. The component uses the `validator.js` library to check if the postal code format is valid for a list of supported countries. For countries not on the supported list, a generic validation is applied.
|
|
123
|
+
|
|
124
|
+
### Custom Validation
|
|
125
|
+
|
|
126
|
+
You can extend the default validation by passing a `fieldValidation` object. This allows you to specify custom regex patterns and error messages for any address field.
|
|
127
|
+
|
|
128
|
+
For example, to add a pattern validation for the state field to accept only two-letter abbreviations:
|
|
129
|
+
|
|
130
|
+
```jsx
|
|
131
|
+
const customValidation = {
|
|
132
|
+
'billing_address.state': {
|
|
133
|
+
pattern: '^[A-Z]{2}$',
|
|
134
|
+
pattern_message: {
|
|
135
|
+
en: 'State must be a 2-letter abbreviation.',
|
|
136
|
+
// Add other locales as needed
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
<AddressForm
|
|
142
|
+
mode="required"
|
|
143
|
+
stripe={false}
|
|
144
|
+
fieldValidation={customValidation}
|
|
145
|
+
/>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Related Components
|
|
149
|
+
|
|
150
|
+
- **[CountrySelect](./components-ui-form-elements-country-select.md)**: The `AddressForm` uses this component internally to provide a searchable, user-friendly country dropdown with flags.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# CountrySelect
|
|
2
|
+
|
|
3
|
+
The `CountrySelect` component is a dropdown for selecting a country, featuring an integrated search filter, country flags, and a responsive design that adapts to desktop and mobile views. It is built to work seamlessly within forms managed by `react-hook-form` and must be wrapped in a `FormProvider` to function correctly.
|
|
4
|
+
|
|
5
|
+
## Props
|
|
6
|
+
|
|
7
|
+
The component accepts the following props:
|
|
8
|
+
|
|
9
|
+
| Prop | Type | Required | Default | Description |
|
|
10
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
11
|
+
| `value` | `CountryIso2` | Yes | | The ISO2 code of the currently selected country (e.g., 'us'). |
|
|
12
|
+
| `onChange` | `(value: CountryIso2) => void` | Yes | | Callback function invoked when a country is selected. |
|
|
13
|
+
| `name` | `string` | Yes | | The name of the input field, used for integration with `react-hook-form`. |
|
|
14
|
+
| `sx` | `SxProps` | No | `{}` | Custom styles applied to the root element using the MUI `sx` prop. |
|
|
15
|
+
| `showDialCode` | `boolean` | No | `false` | If `true`, the country's dial code is displayed next to its name in the list. |
|
|
16
|
+
|
|
17
|
+
## Basic Usage
|
|
18
|
+
|
|
19
|
+
Here is a basic example of how to use the `CountrySelect` component. It must be wrapped in a `FormProvider` from `react-hook-form` because it internally uses `useFormContext` to manage form state.
|
|
20
|
+
|
|
21
|
+
```jsx
|
|
22
|
+
import { useState } from 'react';
|
|
23
|
+
import { FormProvider, useForm } from 'react-hook-form';
|
|
24
|
+
import { CountrySelect } from '@blocklet/payment-react';
|
|
25
|
+
import { Box } from '@mui/material';
|
|
26
|
+
import type { CountryIso2 } from 'react-international-phone';
|
|
27
|
+
|
|
28
|
+
function BasicCountrySelect() {
|
|
29
|
+
const [selectedCountry, setSelectedCountry] = useState<CountryIso2>('us');
|
|
30
|
+
const methods = useForm({
|
|
31
|
+
defaultValues: {
|
|
32
|
+
country: 'us',
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const handleCountryChange = (country: CountryIso2) => {
|
|
37
|
+
setSelectedCountry(country);
|
|
38
|
+
console.log('Selected Country:', country);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<FormProvider {...methods}>
|
|
43
|
+
<Box sx={{ maxWidth: 300 }}>
|
|
44
|
+
<CountrySelect
|
|
45
|
+
name="country"
|
|
46
|
+
value={selectedCountry}
|
|
47
|
+
onChange={handleCountryChange}
|
|
48
|
+
/>
|
|
49
|
+
</Box>
|
|
50
|
+
</FormProvider>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default BasicCountrySelect;
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
### Search and Filtering
|
|
60
|
+
The dropdown includes a search field at the top of the list, allowing users to filter countries by name, two-letter ISO code, or dial code (e.g., `+1`). This makes it easy to find a specific country in the extensive list.
|
|
61
|
+
|
|
62
|
+
### Responsive Design
|
|
63
|
+
The component automatically adapts its UI based on the viewport. On desktop devices, it renders as a traditional dropdown menu. On mobile devices, it presents a full-width bottom-sheet dialog, providing a more native and touch-friendly user experience.
|
|
64
|
+
|
|
65
|
+
### Keyboard Accessibility
|
|
66
|
+
`CountrySelect` is fully navigable using the keyboard, enhancing accessibility:
|
|
67
|
+
- **ArrowDown / ArrowUp / Tab**: Navigate through the list of countries.
|
|
68
|
+
- **Enter**: Select the currently focused country and close the dropdown.
|
|
69
|
+
- **Escape**: Close the dropdown without making a selection.
|
|
70
|
+
|
|
71
|
+
## Customization
|
|
72
|
+
|
|
73
|
+
### Displaying the Dial Code
|
|
74
|
+
|
|
75
|
+
To display the phone dial code next to each country, set the `showDialCode` prop to `true`. This is particularly useful when pairing `CountrySelect` with the [`PhoneInput`](./components-ui-form-elements-phone-input.md) component to build a complete international phone number input.
|
|
76
|
+
|
|
77
|
+
```jsx
|
|
78
|
+
import { useState } from 'react';
|
|
79
|
+
import { FormProvider, useForm } from 'react-hook-form';
|
|
80
|
+
import { CountrySelect } from '@blocklet/payment-react';
|
|
81
|
+
import { Box } from '@mui/material';
|
|
82
|
+
import type { CountryIso2 } from 'react-international-phone';
|
|
83
|
+
|
|
84
|
+
function CountrySelectWithDialCode() {
|
|
85
|
+
const [country, setCountry] = useState<CountryIso2>('us');
|
|
86
|
+
const methods = useForm({ defaultValues: { country: 'us' } });
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<FormProvider {...methods}>
|
|
90
|
+
<Box sx={{ maxWidth: 300 }}>
|
|
91
|
+
<CountrySelect
|
|
92
|
+
name="country"
|
|
93
|
+
value={country}
|
|
94
|
+
onChange={setCountry}
|
|
95
|
+
showDialCode={true}
|
|
96
|
+
/>
|
|
97
|
+
</Box>
|
|
98
|
+
</FormProvider>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export default CountrySelectWithDialCode;
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
By combining these features, the `CountrySelect` component offers a robust and user-friendly solution for country input fields in any form.
|