@blocklet/payment-react 1.19.18 → 1.19.19

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 (55) hide show
  1. package/README.md +313 -0
  2. package/es/checkout/form.js +2 -2
  3. package/es/components/auto-topup/index.d.ts +14 -0
  4. package/es/components/auto-topup/index.js +417 -0
  5. package/es/components/auto-topup/modal.d.ts +35 -0
  6. package/es/components/auto-topup/modal.js +734 -0
  7. package/es/components/auto-topup/product-card.d.ts +13 -0
  8. package/es/components/auto-topup/product-card.js +173 -0
  9. package/es/components/collapse.d.ts +13 -0
  10. package/es/components/collapse.js +76 -0
  11. package/es/components/input.d.ts +2 -1
  12. package/es/components/input.js +64 -13
  13. package/es/components/label.d.ts +2 -1
  14. package/es/components/label.js +2 -1
  15. package/es/index.d.ts +4 -1
  16. package/es/index.js +7 -1
  17. package/es/libs/util.js +2 -1
  18. package/es/locales/en.js +56 -0
  19. package/es/locales/zh.js +56 -0
  20. package/es/payment/form/index.js +6 -0
  21. package/es/payment/product-item.js +17 -10
  22. package/lib/checkout/form.js +2 -2
  23. package/lib/components/auto-topup/index.d.ts +14 -0
  24. package/lib/components/auto-topup/index.js +451 -0
  25. package/lib/components/auto-topup/modal.d.ts +35 -0
  26. package/lib/components/auto-topup/modal.js +803 -0
  27. package/lib/components/auto-topup/product-card.d.ts +13 -0
  28. package/lib/components/auto-topup/product-card.js +149 -0
  29. package/lib/components/collapse.d.ts +13 -0
  30. package/lib/components/collapse.js +74 -0
  31. package/lib/components/input.d.ts +2 -1
  32. package/lib/components/input.js +66 -24
  33. package/lib/components/label.d.ts +2 -1
  34. package/lib/components/label.js +3 -1
  35. package/lib/index.d.ts +4 -1
  36. package/lib/index.js +24 -0
  37. package/lib/libs/util.js +2 -1
  38. package/lib/locales/en.js +56 -0
  39. package/lib/locales/zh.js +56 -0
  40. package/lib/payment/form/index.js +6 -0
  41. package/lib/payment/product-item.js +18 -10
  42. package/package.json +9 -9
  43. package/src/checkout/form.tsx +2 -2
  44. package/src/components/auto-topup/index.tsx +449 -0
  45. package/src/components/auto-topup/modal.tsx +773 -0
  46. package/src/components/auto-topup/product-card.tsx +156 -0
  47. package/src/components/collapse.tsx +82 -0
  48. package/src/components/input.tsx +71 -22
  49. package/src/components/label.tsx +8 -2
  50. package/src/index.ts +7 -0
  51. package/src/libs/util.ts +1 -0
  52. package/src/locales/en.tsx +59 -0
  53. package/src/locales/zh.tsx +57 -0
  54. package/src/payment/form/index.tsx +6 -0
  55. package/src/payment/product-item.tsx +18 -11
@@ -0,0 +1,734 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useState } from "react";
3
+ import {
4
+ Box,
5
+ Typography,
6
+ Stack,
7
+ Button,
8
+ FormControlLabel,
9
+ Alert,
10
+ CircularProgress,
11
+ InputAdornment,
12
+ MenuItem,
13
+ Avatar,
14
+ Select,
15
+ TextField
16
+ } from "@mui/material";
17
+ import { AccountBalanceWalletOutlined, AddOutlined, CreditCard, SwapHoriz } from "@mui/icons-material";
18
+ import { useForm, FormProvider, Controller } from "react-hook-form";
19
+ import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
20
+ import Toast from "@arcblock/ux/lib/Toast";
21
+ import Dialog from "@arcblock/ux/lib/Dialog";
22
+ import { useRequest, useSetState } from "ahooks";
23
+ import { useNavigate } from "react-router-dom";
24
+ import { joinURL } from "ufo";
25
+ import pWaitFor from "p-wait-for";
26
+ import DidAddress from "@arcblock/ux/lib/DID";
27
+ import Switch from "../switch-button.js";
28
+ import api from "../../libs/api.js";
29
+ import { formatError, flattenPaymentMethods, getPrefix, formatBNStr } from "../../libs/util.js";
30
+ import { usePaymentContext } from "../../contexts/payment.js";
31
+ import { createLink, handleNavigation } from "../../libs/navigation.js";
32
+ import Collapse from "../collapse.js";
33
+ import FormInput from "../input.js";
34
+ import StripeCheckout from "../../payment/form/stripe/index.js";
35
+ import AutoTopupProductCard from "./product-card.js";
36
+ import FormLabel from "../label.js";
37
+ const fetchConfig = async (customerId, currencyId) => {
38
+ const { data } = await api.get(`/api/auto-recharge-configs/customer/${customerId}`, {
39
+ params: { currency_id: currencyId }
40
+ });
41
+ return data;
42
+ };
43
+ const fetchCurrencyBalance = async (currencyId, payerAddress) => {
44
+ const { data } = await api.get("/api/customers/payer-token", {
45
+ params: { currencyId, payerAddress }
46
+ });
47
+ return data;
48
+ };
49
+ const DEFAULT_VALUES = {
50
+ enabled: false,
51
+ threshold: "100",
52
+ quantity: 1,
53
+ payment_method_id: "",
54
+ recharge_currency_id: "",
55
+ price_id: "",
56
+ daily_max_amount: 0,
57
+ daily_max_attempts: 0
58
+ };
59
+ export const waitForAutoRechargeComplete = async (configId) => {
60
+ let result;
61
+ await pWaitFor(
62
+ async () => {
63
+ const { data } = await api.get(`/api/auto-recharge-configs/retrieve/${configId}`);
64
+ result = data;
65
+ return !!result.payment_settings?.payment_method_options?.[result.paymentMethod.type]?.payer;
66
+ },
67
+ { interval: 2e3, timeout: 3 * 60 * 1e3 }
68
+ );
69
+ return result;
70
+ };
71
+ function PaymentMethodDisplay({
72
+ config,
73
+ onChangePaymentMethod,
74
+ paymentMethod,
75
+ currency
76
+ }) {
77
+ const { t } = useLocaleContext();
78
+ const [changePaymentMethod, setChangePaymentMethod] = useState(false);
79
+ const navigate = useNavigate();
80
+ const paymentInfo = config?.payment_settings?.payment_method_options?.[paymentMethod.type || ""];
81
+ const { data: balanceInfo, loading: balanceLoading } = useRequest(
82
+ async () => {
83
+ if (paymentMethod.type === "stripe") {
84
+ return null;
85
+ }
86
+ const result = await fetchCurrencyBalance(currency.id, paymentInfo?.payer);
87
+ return result;
88
+ },
89
+ {
90
+ refreshDeps: [currency.id, paymentInfo?.payer],
91
+ ready: !!currency.id && !!paymentInfo?.payer
92
+ }
93
+ );
94
+ const handleChangeToggle = () => {
95
+ const newChange = !changePaymentMethod;
96
+ setChangePaymentMethod(newChange);
97
+ onChangePaymentMethod(newChange);
98
+ };
99
+ if (!paymentInfo) {
100
+ return null;
101
+ }
102
+ const handleRecharge = (e) => {
103
+ const url = joinURL(getPrefix(), `/customer/recharge/${currency.id}?rechargeAddress=${paymentInfo?.payer}`);
104
+ const link = createLink(url, true);
105
+ handleNavigation(e, link, navigate);
106
+ };
107
+ const renderPaymentMethodInfo = () => {
108
+ if (paymentMethod.type === "stripe") {
109
+ return /* @__PURE__ */ jsxs(
110
+ Stack,
111
+ {
112
+ direction: "row",
113
+ spacing: 1,
114
+ sx: {
115
+ alignItems: "center"
116
+ },
117
+ children: [
118
+ /* @__PURE__ */ jsx(CreditCard, { fontSize: "small", color: "primary" }),
119
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", children: [
120
+ "**** **** **** ",
121
+ paymentInfo?.card_last4 || "****"
122
+ ] }),
123
+ /* @__PURE__ */ jsx(
124
+ Typography,
125
+ {
126
+ variant: "body2",
127
+ sx: {
128
+ color: "text.secondary",
129
+ textTransform: "uppercase"
130
+ },
131
+ children: paymentInfo?.card_brand || "CARD"
132
+ }
133
+ ),
134
+ paymentInfo?.exp_time && /* @__PURE__ */ jsx(
135
+ Typography,
136
+ {
137
+ variant: "body2",
138
+ sx: {
139
+ color: "text.secondary",
140
+ borderLeft: "1px solid",
141
+ borderColor: "divider",
142
+ pl: 1
143
+ },
144
+ children: paymentInfo?.exp_time
145
+ }
146
+ )
147
+ ]
148
+ }
149
+ );
150
+ }
151
+ return /* @__PURE__ */ jsxs(
152
+ Stack,
153
+ {
154
+ spacing: 1,
155
+ sx: {
156
+ borderRadius: 1,
157
+ backgroundColor: (theme) => theme.palette.mode === "dark" ? "grey.100" : "grey.50",
158
+ p: 2
159
+ },
160
+ children: [
161
+ /* @__PURE__ */ jsx(DidAddress, { did: paymentInfo?.payer, responsive: false, compact: true, copyable: false }),
162
+ (balanceInfo || balanceLoading) && /* @__PURE__ */ jsxs(
163
+ Stack,
164
+ {
165
+ direction: "row",
166
+ spacing: 1,
167
+ sx: {
168
+ alignItems: "center"
169
+ },
170
+ children: [
171
+ balanceLoading ? /* @__PURE__ */ jsx(CircularProgress, { size: 14, sx: { mr: 0.5 } }) : /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
172
+ /* @__PURE__ */ jsx(AccountBalanceWalletOutlined, { fontSize: "small", sx: { color: "text.lighter" } }),
173
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", sx: { color: "text.primary" }, children: [
174
+ /* @__PURE__ */ jsxs("strong", { children: [
175
+ formatBNStr(balanceInfo?.token || "0", currency?.decimal),
176
+ " "
177
+ ] }),
178
+ currency?.symbol || ""
179
+ ] })
180
+ ] }),
181
+ /* @__PURE__ */ jsxs(
182
+ Button,
183
+ {
184
+ size: "small",
185
+ variant: "text",
186
+ onClick: handleRecharge,
187
+ sx: { fontSize: "smaller", color: "primary.main" },
188
+ children: [
189
+ /* @__PURE__ */ jsx(AddOutlined, { fontSize: "small" }),
190
+ t("payment.autoTopup.addFunds")
191
+ ]
192
+ }
193
+ )
194
+ ]
195
+ }
196
+ )
197
+ ]
198
+ }
199
+ );
200
+ };
201
+ return /* @__PURE__ */ jsx(
202
+ Box,
203
+ {
204
+ sx: {
205
+ p: 2,
206
+ border: "1px solid",
207
+ borderColor: changePaymentMethod ? "primary.main" : "divider",
208
+ borderRadius: 1,
209
+ bgcolor: changePaymentMethod ? "primary.50" : "background.paper"
210
+ },
211
+ children: /* @__PURE__ */ jsxs(Stack, { spacing: 2, children: [
212
+ /* @__PURE__ */ jsxs(
213
+ Stack,
214
+ {
215
+ sx: {
216
+ flexDirection: { xs: "column", sm: "row" },
217
+ alignItems: { xs: "flex-start", sm: "center" },
218
+ justifyContent: { xs: "flex-start", sm: "space-between" }
219
+ },
220
+ children: [
221
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", sx: { display: "flex", alignItems: "center", gap: 1, whiteSpace: "nowrap" }, children: t("payment.autoTopup.currentPaymentMethod") }),
222
+ /* @__PURE__ */ jsx(
223
+ Button,
224
+ {
225
+ size: "small",
226
+ startIcon: /* @__PURE__ */ jsx(SwapHoriz, {}),
227
+ onClick: handleChangeToggle,
228
+ variant: "text",
229
+ sx: {
230
+ color: "primary.main",
231
+ whiteSpace: "nowrap",
232
+ alignSelf: { xs: "flex-end", sm: "center" }
233
+ },
234
+ children: changePaymentMethod ? t("payment.autoTopup.keepCurrent") : t("payment.autoTopup.changePaymentMethod")
235
+ }
236
+ )
237
+ ]
238
+ }
239
+ ),
240
+ changePaymentMethod ? /* @__PURE__ */ jsx(
241
+ Typography,
242
+ {
243
+ variant: "body2",
244
+ sx: {
245
+ color: "text.secondary"
246
+ },
247
+ children: t("payment.autoTopup.changePaymentMethodTip")
248
+ }
249
+ ) : renderPaymentMethodInfo()
250
+ ] })
251
+ }
252
+ );
253
+ }
254
+ export default function AutoTopup({
255
+ open,
256
+ onClose,
257
+ currencyId,
258
+ onSuccess = () => {
259
+ },
260
+ onError = () => {
261
+ },
262
+ defaultEnabled = void 0
263
+ }) {
264
+ const { t, locale } = useLocaleContext();
265
+ const { session, connect, settings } = usePaymentContext();
266
+ const [changePaymentMethod, setChangePaymentMethod] = useState(false);
267
+ const [state, setState] = useSetState({
268
+ loading: false,
269
+ submitting: false,
270
+ authorizationRequired: false,
271
+ stripeContext: {
272
+ client_secret: "",
273
+ intent_type: "",
274
+ status: "",
275
+ public_key: "",
276
+ customer: {}
277
+ }
278
+ });
279
+ const currencies = flattenPaymentMethods(settings.paymentMethods);
280
+ const methods = useForm({
281
+ defaultValues: {
282
+ enabled: defaultEnabled || DEFAULT_VALUES.enabled,
283
+ threshold: DEFAULT_VALUES.threshold,
284
+ quantity: DEFAULT_VALUES.quantity,
285
+ payment_method_id: DEFAULT_VALUES.payment_method_id,
286
+ recharge_currency_id: DEFAULT_VALUES.recharge_currency_id,
287
+ price_id: DEFAULT_VALUES.price_id,
288
+ daily_limits: {
289
+ max_attempts: DEFAULT_VALUES.daily_max_attempts,
290
+ max_amount: DEFAULT_VALUES.daily_max_amount
291
+ }
292
+ }
293
+ });
294
+ const { handleSubmit, setValue, watch } = methods;
295
+ const enabled = watch("enabled");
296
+ const quantity = watch("quantity");
297
+ const rechargeCurrencyId = watch("recharge_currency_id");
298
+ const handleClose = () => {
299
+ setState({
300
+ loading: false,
301
+ submitting: false,
302
+ authorizationRequired: false
303
+ });
304
+ onClose();
305
+ };
306
+ const { data: config } = useRequest(() => fetchConfig(session?.user?.did, currencyId), {
307
+ refreshDeps: [session?.user?.did, currencyId],
308
+ ready: !!session?.user?.did && !!currencyId,
309
+ onError: (error) => {
310
+ Toast.error(formatError(error));
311
+ },
312
+ onSuccess: (data) => {
313
+ setValue("enabled", defaultEnabled || data.enabled);
314
+ setValue("threshold", data.threshold);
315
+ setValue("quantity", data.quantity);
316
+ setValue("payment_method_id", data.payment_method_id);
317
+ setValue("recharge_currency_id", data.recharge_currency_id || data.price?.currency_id);
318
+ setValue("price_id", data.price_id);
319
+ setValue("daily_limits", {
320
+ max_amount: data.daily_limits?.max_amount || 0,
321
+ max_attempts: data.daily_limits?.max_attempts || 0
322
+ });
323
+ }
324
+ });
325
+ const filterCurrencies = useMemo(() => {
326
+ return currencies.filter((c) => config?.price?.currency_options?.find((o) => o.currency_id === c.id));
327
+ }, [currencies, config]);
328
+ const handleConnected = async () => {
329
+ try {
330
+ const result = await waitForAutoRechargeComplete(config?.id);
331
+ if (result) {
332
+ setState({ submitting: false, authorizationRequired: false });
333
+ onSuccess?.(config);
334
+ handleClose();
335
+ Toast.success(t("payment.autoTopup.saveSuccess"));
336
+ }
337
+ } catch (err) {
338
+ Toast.error(formatError(err));
339
+ } finally {
340
+ setState({ submitting: false, authorizationRequired: false });
341
+ }
342
+ };
343
+ const handleDisable = async () => {
344
+ try {
345
+ const submitData = {
346
+ ...config,
347
+ enabled: false
348
+ };
349
+ if (!config?.enabled) {
350
+ return;
351
+ }
352
+ const { data } = await api.post("/api/auto-recharge-configs/submit", submitData);
353
+ onSuccess?.(data);
354
+ Toast.success(t("payment.autoTopup.disableSuccess"));
355
+ } catch (error) {
356
+ Toast.error(formatError(error));
357
+ onError?.(error);
358
+ }
359
+ };
360
+ const handleEnableChange = async (checked) => {
361
+ setValue("enabled", checked);
362
+ if (!checked) {
363
+ await handleDisable();
364
+ }
365
+ };
366
+ const handleAuthorizationRequired = (authData) => {
367
+ setState({ authorizationRequired: true });
368
+ if (authData.stripeContext) {
369
+ setState({
370
+ stripeContext: {
371
+ client_secret: authData.stripeContext.client_secret,
372
+ intent_type: authData.stripeContext.intent_type,
373
+ status: authData.stripeContext.status,
374
+ public_key: authData.paymentMethod.settings.stripe.publishable_key,
375
+ customer: authData.customer
376
+ }
377
+ });
378
+ } else if (authData.delegation) {
379
+ handleDidConnect();
380
+ }
381
+ };
382
+ const handleDidConnect = () => {
383
+ try {
384
+ setState({ submitting: true });
385
+ connect.open({
386
+ containerEl: void 0,
387
+ saveConnect: false,
388
+ locale,
389
+ action: "auto-recharge-auth",
390
+ prefix: joinURL(getPrefix(), "/api/did"),
391
+ extraParams: {
392
+ autoRechargeConfigId: config?.id
393
+ },
394
+ messages: {
395
+ scan: t("payment.autoTopup.authTip"),
396
+ title: t("payment.autoTopup.authTitle"),
397
+ confirm: t("common.connect.confirm")
398
+ },
399
+ onSuccess: async () => {
400
+ connect.close();
401
+ await handleConnected();
402
+ },
403
+ onClose: () => {
404
+ connect.close();
405
+ setState({ submitting: false, authorizationRequired: false });
406
+ },
407
+ onError: (err) => {
408
+ setState({ submitting: false, authorizationRequired: false });
409
+ Toast.error(formatError(err));
410
+ }
411
+ });
412
+ } catch (error) {
413
+ setState({ submitting: false, authorizationRequired: false });
414
+ Toast.error(formatError(error));
415
+ }
416
+ };
417
+ const handleFormSubmit = async (formData) => {
418
+ setState({ submitting: true });
419
+ try {
420
+ const submitData = {
421
+ customer_id: session?.user?.did,
422
+ enabled: formData.enabled,
423
+ threshold: formData.threshold,
424
+ currency_id: currencyId,
425
+ recharge_currency_id: formData.recharge_currency_id,
426
+ price_id: formData.price_id,
427
+ quantity: formData.quantity,
428
+ daily_limits: {
429
+ max_attempts: formData.daily_limits.max_attempts || 0,
430
+ max_amount: formData.daily_limits.max_amount || "0"
431
+ },
432
+ change_payment_method: changePaymentMethod
433
+ };
434
+ const { data } = await api.post("/api/auto-recharge-configs/submit", submitData);
435
+ if (data.balanceResult && !data.balanceResult.sufficient) {
436
+ await handleAuthorizationRequired({
437
+ ...data.balanceResult,
438
+ paymentMethod: data.paymentMethod,
439
+ customer: data.customer
440
+ });
441
+ return;
442
+ }
443
+ setState({
444
+ submitting: false,
445
+ authorizationRequired: false
446
+ });
447
+ onSuccess?.(data);
448
+ handleClose();
449
+ Toast.success(t("payment.autoTopup.saveSuccess"));
450
+ } catch (error) {
451
+ setState({ submitting: false, authorizationRequired: false });
452
+ Toast.error(formatError(error));
453
+ onError?.(error);
454
+ }
455
+ };
456
+ const onSubmit = (formData) => {
457
+ handleFormSubmit(formData);
458
+ };
459
+ const rechargeCurrency = filterCurrencies.find((c) => c.id === rechargeCurrencyId);
460
+ const selectedMethod = settings.paymentMethods.find((method) => {
461
+ return method.payment_currencies.find((c) => c.id === rechargeCurrencyId);
462
+ });
463
+ const showStripeForm = state.authorizationRequired && selectedMethod?.type === "stripe";
464
+ const onStripeConfirm = async () => {
465
+ await handleConnected();
466
+ };
467
+ const onStripeCancel = () => {
468
+ setState({ submitting: false, authorizationRequired: false });
469
+ };
470
+ return /* @__PURE__ */ jsx(
471
+ Dialog,
472
+ {
473
+ open,
474
+ onClose: handleClose,
475
+ maxWidth: "sm",
476
+ fullWidth: true,
477
+ className: "base-dialog",
478
+ title: t("payment.autoTopup.title"),
479
+ actions: enabled ? /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 2, children: [
480
+ /* @__PURE__ */ jsx(Button, { variant: "outlined", onClick: handleClose, disabled: state.submitting, children: t("common.cancel") }),
481
+ /* @__PURE__ */ jsxs(
482
+ Button,
483
+ {
484
+ variant: "contained",
485
+ onClick: () => handleSubmit(onSubmit)(),
486
+ disabled: state.loading || state.authorizationRequired || state.submitting,
487
+ children: [
488
+ state.submitting && /* @__PURE__ */ jsx(CircularProgress, { size: 20, sx: { mr: 1 } }),
489
+ t("payment.autoTopup.saveConfiguration")
490
+ ]
491
+ }
492
+ )
493
+ ] }) : null,
494
+ children: /* @__PURE__ */ jsx(FormProvider, { ...methods, children: /* @__PURE__ */ jsx(Box, { component: "form", onSubmit: handleSubmit(onSubmit), children: /* @__PURE__ */ jsxs(
495
+ Stack,
496
+ {
497
+ sx: {
498
+ gap: 2
499
+ },
500
+ children: [
501
+ /* @__PURE__ */ jsx(Alert, { severity: "info", children: t("payment.autoTopup.tip") }),
502
+ /* @__PURE__ */ jsxs(
503
+ Stack,
504
+ {
505
+ spacing: 2,
506
+ direction: "row",
507
+ sx: {
508
+ alignItems: "center"
509
+ },
510
+ children: [
511
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle1", children: t("payment.autoTopup.enableLabel") }),
512
+ /* @__PURE__ */ jsx(
513
+ FormControlLabel,
514
+ {
515
+ control: /* @__PURE__ */ jsx(Switch, { checked: enabled, onChange: (e) => handleEnableChange(e.target.checked) }),
516
+ label: ""
517
+ }
518
+ )
519
+ ]
520
+ }
521
+ ),
522
+ enabled && /* @__PURE__ */ jsxs(Fragment, { children: [
523
+ /* @__PURE__ */ jsx(Box, { sx: { pt: 1 }, children: /* @__PURE__ */ jsxs(Stack, { spacing: 2.5, children: [
524
+ /* @__PURE__ */ jsxs(
525
+ Stack,
526
+ {
527
+ sx: {
528
+ gap: 2,
529
+ flexDirection: { xs: "column", sm: "row" },
530
+ alignItems: { xs: "flex-start", sm: "center" },
531
+ justifyContent: { xs: "flex-start", sm: "space-between" },
532
+ ".MuiTextField-root": {
533
+ width: {
534
+ xs: "100%",
535
+ sm: "auto"
536
+ }
537
+ }
538
+ },
539
+ children: [
540
+ /* @__PURE__ */ jsx(FormLabel, { boxSx: { width: "fit-content", whiteSpace: "nowrap", marginBottom: 0 }, children: t("payment.autoTopup.triggerThreshold") }),
541
+ /* @__PURE__ */ jsx(
542
+ Controller,
543
+ {
544
+ name: "threshold",
545
+ control: methods.control,
546
+ rules: {
547
+ required: t("payment.checkout.required"),
548
+ min: { value: 0, message: t("payment.autoTopup.thresholdMinError") }
549
+ },
550
+ render: ({ field }) => /* @__PURE__ */ jsx(
551
+ TextField,
552
+ {
553
+ ...field,
554
+ type: "number",
555
+ placeholder: t("payment.autoTopup.thresholdPlaceholder"),
556
+ sx: {
557
+ input: {
558
+ minWidth: 80
559
+ }
560
+ },
561
+ slotProps: {
562
+ input: {
563
+ endAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "end", children: config?.currency?.name })
564
+ },
565
+ htmlInput: {
566
+ min: 0,
567
+ step: 0.01
568
+ }
569
+ }
570
+ }
571
+ )
572
+ }
573
+ )
574
+ ]
575
+ }
576
+ ),
577
+ /* @__PURE__ */ jsxs(
578
+ Stack,
579
+ {
580
+ sx: {
581
+ gap: 2,
582
+ flexDirection: { xs: "column", sm: "row" },
583
+ alignItems: { xs: "flex-start", sm: "center" },
584
+ justifyContent: { xs: "flex-start", sm: "space-between" }
585
+ },
586
+ children: [
587
+ /* @__PURE__ */ jsx(FormLabel, { boxSx: { width: "fit-content", whiteSpace: "nowrap", marginBottom: 0 }, children: t("payment.autoTopup.purchaseBelow") }),
588
+ /* @__PURE__ */ jsx(
589
+ Controller,
590
+ {
591
+ name: "recharge_currency_id",
592
+ control: methods.control,
593
+ render: ({ field }) => /* @__PURE__ */ jsx(
594
+ Select,
595
+ {
596
+ ...field,
597
+ value: field.value,
598
+ onChange: (e) => field.onChange(e.target.value),
599
+ size: "small",
600
+ children: filterCurrencies.map((x) => /* @__PURE__ */ jsx(MenuItem, { value: x?.id, children: /* @__PURE__ */ jsxs(
601
+ Stack,
602
+ {
603
+ direction: "row",
604
+ sx: {
605
+ alignItems: "center",
606
+ gap: 1
607
+ },
608
+ children: [
609
+ /* @__PURE__ */ jsx(Avatar, { src: x?.logo, sx: { width: 20, height: 20 }, alt: x?.symbol }),
610
+ /* @__PURE__ */ jsxs(
611
+ Typography,
612
+ {
613
+ sx: {
614
+ color: "text.secondary"
615
+ },
616
+ children: [
617
+ x?.symbol,
618
+ " (",
619
+ x?.method?.name,
620
+ ")"
621
+ ]
622
+ }
623
+ )
624
+ ]
625
+ }
626
+ ) }, x?.id))
627
+ }
628
+ )
629
+ }
630
+ )
631
+ ]
632
+ }
633
+ ),
634
+ config?.price?.product && /* @__PURE__ */ jsx(
635
+ AutoTopupProductCard,
636
+ {
637
+ product: config.price.product,
638
+ price: config.price,
639
+ creditCurrency: config.currency,
640
+ currency: filterCurrencies.find((c) => c.id === rechargeCurrencyId) || filterCurrencies[0],
641
+ quantity,
642
+ onQuantityChange: (newQuantity) => setValue("quantity", newQuantity),
643
+ maxQuantity: 9999,
644
+ minQuantity: 1
645
+ }
646
+ ),
647
+ config && rechargeCurrency && /* @__PURE__ */ jsx(
648
+ PaymentMethodDisplay,
649
+ {
650
+ config,
651
+ onChangePaymentMethod: setChangePaymentMethod,
652
+ currency: rechargeCurrency,
653
+ paymentMethod: selectedMethod
654
+ }
655
+ ),
656
+ /* @__PURE__ */ jsx(Collapse, { trigger: t("payment.autoTopup.advanced"), children: /* @__PURE__ */ jsxs(
657
+ Stack,
658
+ {
659
+ sx: {
660
+ gap: 2,
661
+ pl: 2,
662
+ pr: 1
663
+ },
664
+ children: [
665
+ /* @__PURE__ */ jsx(
666
+ FormInput,
667
+ {
668
+ name: "daily_limits.max_amount",
669
+ label: t("payment.autoTopup.dailyLimits.maxAmount"),
670
+ type: "number",
671
+ placeholder: t("payment.autoTopup.dailyLimits.maxAmountPlaceholder"),
672
+ tooltip: t("payment.autoTopup.dailyLimits.maxAmountDescription"),
673
+ inputProps: {
674
+ min: 0,
675
+ step: 0.01
676
+ },
677
+ slotProps: {
678
+ input: {
679
+ endAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "end", children: filterCurrencies.find((c) => c.id === rechargeCurrencyId)?.symbol || "" })
680
+ }
681
+ },
682
+ sx: {
683
+ maxWidth: {
684
+ xs: "100%",
685
+ sm: "220px"
686
+ }
687
+ },
688
+ layout: "horizontal"
689
+ }
690
+ ),
691
+ /* @__PURE__ */ jsx(
692
+ FormInput,
693
+ {
694
+ name: "daily_limits.max_attempts",
695
+ label: t("payment.autoTopup.dailyLimits.maxAttempts"),
696
+ type: "number",
697
+ placeholder: t("payment.autoTopup.dailyLimits.maxAttemptsPlaceholder"),
698
+ tooltip: t("payment.autoTopup.dailyLimits.maxAttemptsDescription"),
699
+ inputProps: {
700
+ min: 0,
701
+ step: 1
702
+ },
703
+ sx: {
704
+ maxWidth: {
705
+ xs: "100%",
706
+ sm: "220px"
707
+ }
708
+ },
709
+ layout: "horizontal"
710
+ }
711
+ )
712
+ ]
713
+ }
714
+ ) })
715
+ ] }) }),
716
+ /* @__PURE__ */ jsx(Stack, { spacing: 2, children: showStripeForm && /* @__PURE__ */ jsx(Box, { sx: { mt: 2 }, children: state.stripeContext && /* @__PURE__ */ jsx(Box, { sx: { mt: 2 }, children: /* @__PURE__ */ jsx(
717
+ StripeCheckout,
718
+ {
719
+ clientSecret: state.stripeContext.client_secret,
720
+ intentType: state.stripeContext.intent_type,
721
+ publicKey: state.stripeContext.public_key,
722
+ customer: state.stripeContext.customer,
723
+ mode: "setup",
724
+ onConfirm: onStripeConfirm,
725
+ onCancel: onStripeCancel
726
+ }
727
+ ) }) }) })
728
+ ] })
729
+ ]
730
+ }
731
+ ) }) })
732
+ }
733
+ );
734
+ }