payment-kit 1.13.161 → 1.13.162

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.13.161",
3
+ "version": "1.13.162",
4
4
  "scripts": {
5
5
  "dev": "cross-env COMPONENT_STORE_URL=https://test.store.blocklet.dev blocklet dev --open",
6
6
  "eject": "vite eject",
@@ -50,7 +50,7 @@
50
50
  "@arcblock/jwt": "^1.18.110",
51
51
  "@arcblock/ux": "^2.9.39",
52
52
  "@blocklet/logger": "1.16.23",
53
- "@blocklet/payment-react": "1.13.161",
53
+ "@blocklet/payment-react": "1.13.162",
54
54
  "@blocklet/sdk": "1.16.23",
55
55
  "@blocklet/ui-react": "^2.9.39",
56
56
  "@blocklet/uploader": "^0.0.74",
@@ -110,7 +110,7 @@
110
110
  "devDependencies": {
111
111
  "@abtnode/types": "1.16.23",
112
112
  "@arcblock/eslint-config-ts": "^0.2.4",
113
- "@blocklet/payment-types": "1.13.161",
113
+ "@blocklet/payment-types": "1.13.162",
114
114
  "@types/cookie-parser": "^1.4.6",
115
115
  "@types/cors": "^2.8.17",
116
116
  "@types/dotenv-flow": "^3.3.3",
@@ -149,5 +149,5 @@
149
149
  "parser": "typescript"
150
150
  }
151
151
  },
152
- "gitHead": "55cb16d9cd06b91b949a1a1c88b14670b0c1aca8"
152
+ "gitHead": "e11cae8972d35cde567d4784511aacd33a29c1bc"
153
153
  }
@@ -0,0 +1,375 @@
1
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
2
+ import { api, usePaymentContext } from '@blocklet/payment-react';
3
+ import type { TCustomer } from '@blocklet/payment-types';
4
+ import { Add, Close } from '@mui/icons-material';
5
+ import { Box, styled } from '@mui/system';
6
+ import { useEffect, useState } from 'react';
7
+
8
+ import { ProductsProvider } from '../contexts/products';
9
+ import InfoCard from './info-card';
10
+ import { FilterProducts } from './payment-link/product-select';
11
+
12
+ const fetchUserData = (params: Record<string, any> = {}): Promise<{ list: TCustomer[]; count: number }> => {
13
+ const search = new URLSearchParams();
14
+ Object.keys(params).forEach((key) => {
15
+ let v = params[key];
16
+ if (key === 'q') {
17
+ v = Object.entries(v)
18
+ .map((x) => x.join(':'))
19
+ .join(' ');
20
+ }
21
+ search.set(key, String(v));
22
+ });
23
+ return api.get(`api/customers?${search.toString()}`).then((res) => res.data);
24
+ };
25
+
26
+ const fetchSubscriptionItems = (params: Record<string, any> = {}): Promise<{ list: TCustomer[]; count: number }> => {
27
+ const search = new URLSearchParams();
28
+ Object.keys(params).forEach((key) => {
29
+ const v = params[key];
30
+ search.set(key, String(v));
31
+ });
32
+ return api.get(`api/subscription-items?${search.toString()}`).then((res) => res.data);
33
+ };
34
+
35
+ type Props = {
36
+ search?: Record<string, any>;
37
+ status?: string[];
38
+ currency?: boolean;
39
+ setSearch: (x: any) => void;
40
+ };
41
+
42
+ export default function FilterTooolbar(props: Props) {
43
+ const { setSearch, search, status, currency } = props;
44
+ const handleSearch = (obj: any) => {
45
+ setSearch({
46
+ ...search,
47
+ ...obj,
48
+ });
49
+ };
50
+
51
+ return (
52
+ <Root>
53
+ <div className="table-toolbar-left">
54
+ <SearchStatus setSearch={handleSearch} status={status} />
55
+ <SearchCustomers setSearch={handleSearch} />
56
+ {currency ? <SearchCurrency setSearch={handleSearch} /> : <SearchProducts setSearch={handleSearch} />}
57
+ </div>
58
+ </Root>
59
+ );
60
+ }
61
+
62
+ const defaultProps = {
63
+ search: {},
64
+ status: {},
65
+ currency: false,
66
+ };
67
+
68
+ FilterTooolbar.defaultProps = defaultProps;
69
+ SearchStatus.defaultProps = defaultProps;
70
+ SearchCurrency.defaultProps = defaultProps;
71
+ SearchProducts.defaultProps = defaultProps;
72
+ SearchCustomers.defaultProps = defaultProps;
73
+
74
+ function SearchStatus({ status = [], setSearch }: Pick<Props, 'status' | 'setSearch'>) {
75
+ const [show, setShow] = useState(false);
76
+ const [display, setDisplay] = useState('');
77
+ const { t } = useLocaleContext();
78
+ return (
79
+ <section
80
+ onClick={() => {
81
+ setShow(!show);
82
+ }}>
83
+ <div className="option-btn">
84
+ {display ? (
85
+ <Close
86
+ sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }}
87
+ onClick={(e) => {
88
+ e.stopPropagation();
89
+ setSearch({
90
+ status: '',
91
+ });
92
+ setDisplay('');
93
+ }}
94
+ />
95
+ ) : (
96
+ <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }} />
97
+ )}
98
+ {t('common.status')}
99
+ <span>{display}</span>
100
+ </div>
101
+ <ul className="status-options" style={{ display: show ? 'block' : 'none' }}>
102
+ {status.map((x: any) => (
103
+ <li
104
+ onClick={() => {
105
+ setSearch({
106
+ status: x,
107
+ });
108
+ setDisplay(x);
109
+ }}
110
+ key={x}>
111
+ {x}
112
+ </li>
113
+ ))}
114
+ </ul>
115
+ </section>
116
+ );
117
+ }
118
+
119
+ function filterCurrency(methods: any) {
120
+ const out: any = {};
121
+ methods.forEach((m: any) => {
122
+ const currencies = m.payment_currencies;
123
+ currencies.forEach((c: any) => {
124
+ out[c.symbol] = c.id;
125
+ });
126
+ });
127
+ return out;
128
+ }
129
+
130
+ function SearchCurrency({ setSearch }: Pick<Props, 'setSearch'>) {
131
+ const [show, setShow] = useState(false);
132
+ const [display, setDisplay] = useState('');
133
+ const { settings } = usePaymentContext();
134
+ const currencies = filterCurrency(settings.paymentMethods);
135
+ const { t } = useLocaleContext();
136
+
137
+ return (
138
+ <section
139
+ onClick={() => {
140
+ setShow(!show);
141
+ }}>
142
+ <div className="option-btn">
143
+ {display ? (
144
+ <Close
145
+ sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }}
146
+ onClick={(e) => {
147
+ e.stopPropagation();
148
+ setSearch({
149
+ currency_id: '',
150
+ });
151
+ setDisplay('');
152
+ }}
153
+ />
154
+ ) : (
155
+ <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }} />
156
+ )}
157
+ {t('common.currency')}
158
+ <span>{display}</span>
159
+ </div>
160
+ <ul className="status-options" style={{ display: show ? 'block' : 'none' }}>
161
+ {Object.keys(currencies).map((k: any) => (
162
+ <li
163
+ onClick={() => {
164
+ setSearch({
165
+ currency_id: currencies[k],
166
+ });
167
+ setDisplay(k);
168
+ }}
169
+ key={k}>
170
+ {k}
171
+ </li>
172
+ ))}
173
+ </ul>
174
+ </section>
175
+ );
176
+ }
177
+
178
+ function SearchCustomers({ setSearch }: Pick<Props, 'setSearch'>) {
179
+ const [customers, setCustomers] = useState([]);
180
+ const [show, setShow] = useState(false);
181
+ const [text, setText] = useState('');
182
+ const [display, setDisplay] = useState('');
183
+ const { t } = useLocaleContext();
184
+
185
+ useEffect(() => {
186
+ fetchUserData({
187
+ q: {
188
+ 'like-name': text,
189
+ 'like-email': text,
190
+ 'like-did': text,
191
+ 'like-metadata': text,
192
+ 'like-phone': text,
193
+ },
194
+ page: 1,
195
+ pageSize: 100,
196
+ }).then((data: any) => {
197
+ setCustomers(data.list);
198
+ });
199
+ }, [text]);
200
+
201
+ return (
202
+ <section onClick={() => setShow(!show)}>
203
+ <div className="option-btn">
204
+ {display ? (
205
+ <Close
206
+ sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }}
207
+ onClick={(e) => {
208
+ e.stopPropagation();
209
+ setSearch({
210
+ customer_id: '',
211
+ });
212
+ setDisplay('');
213
+ }}
214
+ />
215
+ ) : (
216
+ <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }} />
217
+ )}
218
+ {t('common.customer')}
219
+ <span>{display}</span>
220
+ </div>
221
+ <ul className="status-options" style={{ display: show ? 'block' : 'none' }} onClick={(e) => e.stopPropagation()}>
222
+ <input
223
+ type="text"
224
+ placeholder="search customers"
225
+ onChange={(e) => {
226
+ setText(e.target.value);
227
+ }}
228
+ />
229
+ {customers.map((x: any) => (
230
+ <li
231
+ key={x.id}
232
+ onClick={() => {
233
+ setSearch({
234
+ customer_id: x.id,
235
+ });
236
+ setDisplay(x.name);
237
+ }}>
238
+ <InfoCard
239
+ logo={`/.well-known/service/user/avatar/${x.did}?imageFilter=resize&w=48&h=48`}
240
+ name={x.email}
241
+ key={x.id}
242
+ description={`${x.did.slice(0, 6)}...${x.did.slice(-6)}`}
243
+ />
244
+ </li>
245
+ ))}
246
+ </ul>
247
+ </section>
248
+ );
249
+ }
250
+
251
+ function SearchProducts({ setSearch }: Pick<Props, 'setSearch'>) {
252
+ const [show, setShow] = useState(false);
253
+ const [price, setPrice] = useState({} as any);
254
+ const [display, setDisplay] = useState('');
255
+ const isSubscription = window.location.pathname.includes('subscriptions');
256
+ const { t } = useLocaleContext();
257
+
258
+ useEffect(() => {
259
+ if (!price.id) {
260
+ return;
261
+ }
262
+ fetchSubscriptionItems({
263
+ price_id: price.id,
264
+ }).then((data) => {
265
+ const str = data.list.map((x: any) => x.subscription_id).join(',');
266
+ const key = isSubscription ? 'id' : 'subscription_id';
267
+ setSearch({
268
+ q: {
269
+ [key]: str,
270
+ },
271
+ page: 1,
272
+ pageSize: 100,
273
+ });
274
+ });
275
+ }, [price]);
276
+
277
+ return (
278
+ <section onClick={() => setShow(!show)}>
279
+ <div className="option-btn">
280
+ {display ? (
281
+ <Close
282
+ sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }}
283
+ onClick={(e) => {
284
+ e.stopPropagation();
285
+ setSearch({
286
+ q: '',
287
+ });
288
+ setDisplay('');
289
+ }}
290
+ />
291
+ ) : (
292
+ <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.2rem' }} />
293
+ )}
294
+ {t('admin.subscription.product')}
295
+ <span>{display}</span>
296
+ </div>
297
+ <ul className="status-options" style={{ display: show ? 'block' : 'none' }} onClick={(e) => e.stopPropagation()}>
298
+ <ProductsProvider>
299
+ <FilterProducts
300
+ hasSelected={() => false}
301
+ onSelect={(p: any) => {
302
+ setPrice(p);
303
+ setDisplay(`${p.productName}(${p.displayPrice})`);
304
+ }}
305
+ />
306
+ </ProductsProvider>
307
+ </ul>
308
+ </section>
309
+ );
310
+ }
311
+
312
+ const Root = styled(Box)`
313
+ .table-toolbar-left {
314
+ display: flex;
315
+ align-items: cneter;
316
+ }
317
+
318
+ .table-toolbar-left section {
319
+ position: relative;
320
+ list-style: none;
321
+ font-size: 14px;
322
+ font-weight: normal;
323
+ padding: 0 5px;
324
+ cursor: pointer;
325
+ }
326
+
327
+ .option-btn {
328
+ display: flex;
329
+ align-items: center;
330
+ border-radius: 25px;
331
+ background: #f6f6f6;
332
+ padding: 0 10px;
333
+ }
334
+
335
+ .option-btn span {
336
+ color: #3773f2;
337
+ padding: 0 3px;
338
+ }
339
+
340
+ .custom-toobar-title-inner {
341
+ line-height: normal;
342
+ }
343
+
344
+ .status-options {
345
+ position: absolute;
346
+ padding: 10px;
347
+ background: #fff;
348
+ border: 1px solid #eee;
349
+ border-radius: 5px;
350
+ z-index: 999999;
351
+ top: 25px;
352
+ display: block;
353
+ max-height: 500px;
354
+ overflow-y: auto;
355
+ overflow-x: hidden;
356
+ }
357
+
358
+ .status-options input {
359
+ width: 100%;
360
+ border: 1px solid #eee;
361
+ padding: 5px 10px;
362
+ border-radius: 20px;
363
+ margin-bottom: 10px;
364
+ }
365
+
366
+ .status-options li {
367
+ list-style: none;
368
+ padding: 5px;
369
+ line-height: normal;
370
+ }
371
+
372
+ .custom-toobar-title-inner span {
373
+ overflow: auto;
374
+ }
375
+ `;
@@ -3,13 +3,13 @@ import { getDurableData } from '@arcblock/ux/lib/Datatable';
3
3
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
4
4
  import { Status, api, formatTime, getInvoiceStatusColor } from '@blocklet/payment-react';
5
5
  import type { TInvoiceExpanded } from '@blocklet/payment-types';
6
- import { CircularProgress, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material';
6
+ import { CircularProgress, Typography } from '@mui/material';
7
7
  import { fromUnitToToken } from '@ocap/util';
8
8
  import { useEffect, useState } from 'react';
9
9
  import { useNavigate } from 'react-router-dom';
10
10
 
11
- import { debounce } from '../../libs/util';
12
11
  import CustomerLink from '../customer/link';
12
+ import FilterTooolbar from '../filter-toolbar';
13
13
  import Table from '../table';
14
14
  import InvoiceActions from './action';
15
15
 
@@ -18,15 +18,13 @@ const fetchData = (params: Record<string, any> = {}): Promise<{ list: TInvoiceEx
18
18
  Object.keys(params).forEach((key) => {
19
19
  let v = params[key];
20
20
  if (key === 'q') {
21
- v = Object.entries(params[key])
21
+ v = Object.entries(v)
22
22
  .map((x) => x.join(':'))
23
23
  .join(' ');
24
24
  }
25
25
  search.set(key, String(v));
26
26
  });
27
- return params.q
28
- ? api.get(`api/invoices/search?${search.toString()}`).then((res) => res.data)
29
- : api.get(`/api/invoices?${search.toString()}`).then((res) => res.data);
27
+ return api.get(`/api/invoices?${search.toString()}`).then((res) => res.data);
30
28
  };
31
29
 
32
30
  type SearchProps = {
@@ -36,6 +34,7 @@ type SearchProps = {
36
34
  customer_id?: string;
37
35
  subscription_id?: string;
38
36
  q?: any;
37
+ o?: string;
39
38
  };
40
39
 
41
40
  type ListProps = {
@@ -69,7 +68,6 @@ const getListKey = (props: ListProps) => {
69
68
  InvoiceList.defaultProps = {
70
69
  features: {
71
70
  customer: true,
72
- filter: true,
73
71
  },
74
72
  customer_id: '',
75
73
  subscription_id: '',
@@ -102,7 +100,7 @@ export default function InvoiceList({ customer_id, subscription_id, features, st
102
100
  });
103
101
 
104
102
  useEffect(() => {
105
- debounce(refresh, 1000)();
103
+ refresh();
106
104
  }, [search]);
107
105
 
108
106
  if (!data.list) {
@@ -131,7 +129,6 @@ export default function InvoiceList({ customer_id, subscription_id, features, st
131
129
  name: 'status',
132
130
  width: 60,
133
131
  options: {
134
- filter: true,
135
132
  customBodyRenderLite: (_: string, index: number) => {
136
133
  const item = data.list[index] as TInvoiceExpanded;
137
134
  return <Status label={item?.status} color={getInvoiceStatusColor(item?.status)} />;
@@ -146,7 +143,6 @@ export default function InvoiceList({ customer_id, subscription_id, features, st
146
143
  label: t('common.description'),
147
144
  name: 'description',
148
145
  options: {
149
- filter: true,
150
146
  customBodyRenderLite: (_: string, index: number) => {
151
147
  const item = data.list[index];
152
148
  return item?.description || item?.id;
@@ -166,6 +162,8 @@ export default function InvoiceList({ customer_id, subscription_id, features, st
166
162
  label: t('common.createdAt'),
167
163
  name: 'created_at',
168
164
  options: {
165
+ sort: true,
166
+ responsive: 'vertical',
169
167
  customBodyRender: (e: string) => {
170
168
  return formatTime(e);
171
169
  },
@@ -193,7 +191,6 @@ export default function InvoiceList({ customer_id, subscription_id, features, st
193
191
  name: 'customer_id',
194
192
  width: 60,
195
193
  options: {
196
- filter: true,
197
194
  customBodyRenderLite: (_: string, index: number) => {
198
195
  const item = data.list[index] as TInvoiceExpanded;
199
196
  return <CustomerLink customer={item.customer} />;
@@ -231,34 +228,19 @@ export default function InvoiceList({ customer_id, subscription_id, features, st
231
228
  navigate(`/admin/billing/${item.id}`);
232
229
  }
233
230
  },
234
- onFilterChange: (key: any, filterList: any, type: any, index: number) => {
235
- if (type === 'reset') {
236
- setSearch({
237
- status: '',
238
- customer_id,
239
- subscription_id,
240
- pageSize: 100,
241
- page: 1,
242
- });
243
- } else if (filterList && filterList[index]) {
244
- // 这里暂时没有更好的取值方式
245
- const value = filterList[index][0];
246
- setSearch({
247
- q: {
248
- ...search.q,
249
- [key]: encodeURIComponent(value),
250
- },
251
- pageSize: 100,
252
- page: 1,
253
- });
254
- }
231
+ onColumnSortChange(_: any, order: any) {
232
+ setSearch({
233
+ ...search,
234
+ q: search.q || {},
235
+ o: order,
236
+ });
255
237
  },
256
238
  onSearchChange: (text: string) => {
257
239
  if (text) {
258
240
  setSearch({
259
241
  q: {
260
- 'like-did': text,
261
- 'like-name': text,
242
+ 'like-description': text,
243
+ 'like-metadata': text,
262
244
  'like-number': text,
263
245
  },
264
246
  pageSize: 100,
@@ -278,18 +260,7 @@ export default function InvoiceList({ customer_id, subscription_id, features, st
278
260
  toolbar={features?.toolbar}
279
261
  footer={features?.footer}
280
262
  title={
281
- <div className="table-toolbar-left">
282
- <ToggleButtonGroup
283
- value={search.status}
284
- onChange={(_, value) => setSearch((x) => ({ ...x, status: value }))}
285
- exclusive>
286
- <ToggleButton value="">All</ToggleButton>
287
- <ToggleButton value="draft">Draft</ToggleButton>
288
- <ToggleButton value="uncollectible">Outstanding</ToggleButton>
289
- <ToggleButton value="open">Past Due</ToggleButton>
290
- <ToggleButton value="paid">Paid</ToggleButton>
291
- </ToggleButtonGroup>
292
- </div>
263
+ <FilterTooolbar setSearch={setSearch} search={search} status={['paid', 'open', 'uncollectible']} currency />
293
264
  }
294
265
  />
295
266
  );
@@ -3,13 +3,14 @@ import { getDurableData } from '@arcblock/ux/lib/Datatable';
3
3
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
4
4
  import { Status, api, formatTime, getPaymentIntentStatusColor } from '@blocklet/payment-react';
5
5
  import type { TPaymentIntentExpanded } from '@blocklet/payment-types';
6
- import { CircularProgress, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material';
6
+ import { CircularProgress, Typography } from '@mui/material';
7
7
  import { fromUnitToToken } from '@ocap/util';
8
8
  import { useEffect, useState } from 'react';
9
9
  import { useNavigate } from 'react-router-dom';
10
10
 
11
11
  import { debounce } from '../../libs/util';
12
12
  import CustomerLink from '../customer/link';
13
+ import FilterTooolbar from '../filter-toolbar';
13
14
  import Table from '../table';
14
15
  import PaymentIntentActions from './actions';
15
16
 
@@ -18,15 +19,13 @@ const fetchData = (params: Record<string, any> = {}): Promise<{ list: TPaymentIn
18
19
  Object.keys(params).forEach((key) => {
19
20
  let v = params[key];
20
21
  if (key === 'q') {
21
- v = Object.entries(params[key])
22
+ v = Object.entries(v)
22
23
  .map((x) => x.join(':'))
23
24
  .join(' ');
24
25
  }
25
26
  search.set(key, String(v));
26
27
  });
27
- return params.q
28
- ? api.get(`api/payment-intents/search?${search.toString()}`).then((res) => res.data)
29
- : api.get(`/api/payment-intents?${search.toString()}`).then((res) => res.data);
28
+ return api.get(`/api/payment-intents?${search.toString()}`).then((res) => res.data);
30
29
  };
31
30
 
32
31
  type SearchProps = {
@@ -36,6 +35,7 @@ type SearchProps = {
36
35
  customer_id?: string;
37
36
  invoice_id?: string;
38
37
  q?: any;
38
+ o?: any;
39
39
  };
40
40
 
41
41
  type ListProps = {
@@ -142,6 +142,8 @@ export default function PaymentList({ customer_id, invoice_id, features }: ListP
142
142
  label: t('common.createdAt'),
143
143
  name: 'created_at',
144
144
  options: {
145
+ sort: true,
146
+ filterType: 'dropdown',
145
147
  customBodyRender: (e: string) => {
146
148
  return formatTime(e);
147
149
  },
@@ -193,34 +195,12 @@ export default function PaymentList({ customer_id, invoice_id, features }: ListP
193
195
  count: data.count,
194
196
  page: search.page - 1,
195
197
  rowsPerPage: search.pageSize,
196
- onFilterChange: (key: any, filterList: any, type: any, index: number) => {
197
- if (type === 'reset') {
198
- setSearch({
199
- status: '',
200
- customer_id,
201
- invoice_id,
202
- pageSize: 100,
203
- page: 1,
204
- });
205
- } else if (filterList && filterList[index]) {
206
- // 这里暂时没有更好的取值方式
207
- const value = filterList[index][0];
208
- setSearch({
209
- q: {
210
- ...search.q,
211
- [key]: encodeURIComponent(value),
212
- },
213
- pageSize: 100,
214
- page: 1,
215
- });
216
- }
217
- },
218
198
  onSearchChange: (text: string) => {
219
199
  if (text) {
220
200
  setSearch({
221
201
  q: {
222
- 'like-did': text,
223
- 'like-name': text,
202
+ 'like-description': text,
203
+ 'like-metadata': text,
224
204
  },
225
205
  pageSize: 100,
226
206
  page: 1,
@@ -235,6 +215,13 @@ export default function PaymentList({ customer_id, invoice_id, features }: ListP
235
215
  });
236
216
  }
237
217
  },
218
+ onColumnSortChange(_: any, order: any) {
219
+ setSearch({
220
+ ...search,
221
+ q: search.q || {},
222
+ o: order,
223
+ });
224
+ },
238
225
  onRowClick: (_: any, { dataIndex }: any) => {
239
226
  const item = data.list[dataIndex] as TPaymentIntentExpanded;
240
227
  navigate(`/admin/payments/${item.id}`);
@@ -243,18 +230,7 @@ export default function PaymentList({ customer_id, invoice_id, features }: ListP
243
230
  toolbar={features?.toolbar}
244
231
  footer={features?.footer}
245
232
  title={
246
- <div className="table-toolbar-left">
247
- <ToggleButtonGroup
248
- value={search.status}
249
- onChange={(_, value) => setSearch((x) => ({ ...x, status: value }))}
250
- exclusive>
251
- <ToggleButton value="">All</ToggleButton>
252
- <ToggleButton value="succeeded">Succeeded</ToggleButton>
253
- <ToggleButton value="canceled">Canceled</ToggleButton>
254
- <ToggleButton value="requires_capture">Uncaptured</ToggleButton>
255
- <ToggleButton value="requires_action,requires_confirmation,requires_payment_method">Failed</ToggleButton>
256
- </ToggleButtonGroup>
257
- </div>
233
+ <FilterTooolbar setSearch={setSearch} search={search} status={['succeeded', 'requires_action']} currency />
258
234
  }
259
235
  />
260
236
  );