@blocklet/payment-react 1.18.20 → 1.18.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,7 @@ type Props = {
17
17
  dialogProps?: DialogProps;
18
18
  detailLinkOptions?: DetailLinkOptions;
19
19
  successToast?: boolean;
20
+ alertMessage?: string;
20
21
  children?: (handlePay: (item: SummaryItem) => void, data: {
21
22
  subscription?: Subscription;
22
23
  summary: {
@@ -32,7 +33,7 @@ type SummaryItem = {
32
33
  currency: PaymentCurrency;
33
34
  method: PaymentMethod;
34
35
  };
35
- declare function OverdueInvoicePayment({ subscriptionId, customerId, mode, dialogProps, children, onPaid, detailLinkOptions, successToast, }: Props): import("react").JSX.Element | null;
36
+ declare function OverdueInvoicePayment({ subscriptionId, customerId, mode, dialogProps, children, onPaid, detailLinkOptions, successToast, alertMessage, }: Props): import("react").JSX.Element | null;
36
37
  declare namespace OverdueInvoicePayment {
37
38
  var defaultProps: {
38
39
  mode: string;
@@ -47,6 +48,7 @@ declare namespace OverdueInvoicePayment {
47
48
  subscriptionId: undefined;
48
49
  customerId: undefined;
49
50
  successToast: boolean;
51
+ alertMessage: string;
50
52
  };
51
53
  }
52
54
  export default OverdueInvoicePayment;
@@ -35,7 +35,8 @@ function OverdueInvoicePayment({
35
35
  onPaid = () => {
36
36
  },
37
37
  detailLinkOptions = { enabled: true },
38
- successToast = true
38
+ successToast = true,
39
+ alertMessage = ""
39
40
  }) {
40
41
  const { t } = useLocaleContext();
41
42
  const { connect } = usePaymentContext();
@@ -245,19 +246,25 @@ function OverdueInvoicePayment({
245
246
  });
246
247
  }
247
248
  if (customerId) {
249
+ let title = "";
248
250
  if (summaryList.length === 1) {
249
- return t("payment.customer.overdue.title", {
251
+ title = t("payment.customer.overdue.title", {
250
252
  subscriptionCount: data.subscriptionCount || 0,
251
253
  count: data.invoices?.length,
252
254
  total: formatAmount(summaryList[0]?.amount, summaryList[0]?.currency?.decimal),
253
255
  symbol: summaryList[0]?.currency?.symbol,
254
256
  method: getMethodText(summaryList[0]?.method)
255
257
  });
258
+ } else {
259
+ title = t("payment.customer.overdue.simpleTitle", {
260
+ subscriptionCount: data.subscriptionCount || 0,
261
+ count: data.invoices?.length
262
+ });
256
263
  }
257
- return t("payment.customer.overdue.simpleTitle", {
258
- subscriptionCount: data.subscriptionCount || 0,
259
- count: data.invoices?.length
260
- });
264
+ if (alertMessage) {
265
+ return `${title}${alertMessage}`;
266
+ }
267
+ return `${title}${t("payment.customer.overdue.defaultAlert")}`;
261
268
  }
262
269
  return "";
263
270
  };
@@ -388,6 +395,7 @@ OverdueInvoicePayment.defaultProps = {
388
395
  detailLinkOptions: { enabled: true },
389
396
  subscriptionId: void 0,
390
397
  customerId: void 0,
391
- successToast: true
398
+ successToast: true,
399
+ alertMessage: ""
392
400
  };
393
401
  export default OverdueInvoicePayment;
@@ -1,2 +1,9 @@
1
1
  export declare const getPhoneUtil: () => Promise<any>;
2
2
  export declare const validatePhoneNumber: (phoneNumber: string) => Promise<any>;
3
+ /**
4
+ * Format a phone number to international format
5
+ * @param phoneNumber The original phone number
6
+ * @param defaultCountry Default country code (ISO 3166-1 alpha-2)
7
+ * @returns Formatted phone number
8
+ */
9
+ export declare const formatPhone: (phoneNumber: string | undefined, defaultCountry?: string) => string;
@@ -1,17 +1,27 @@
1
1
  let phoneUtil = null;
2
2
  export const getPhoneUtil = async () => {
3
3
  if (!phoneUtil) {
4
- const { PhoneNumberUtil } = await import(
4
+ const result = await import(
5
5
  /* webpackChunkName: "phone-util" */
6
6
  "google-libphonenumber"
7
7
  );
8
+ const PhoneNumberUtil = (result.default || result)?.PhoneNumberUtil;
9
+ if (!PhoneNumberUtil) {
10
+ throw new Error("PhoneNumberUtil not found");
11
+ }
8
12
  phoneUtil = PhoneNumberUtil.getInstance();
9
13
  }
10
14
  return phoneUtil;
11
15
  };
12
16
  export const validatePhoneNumber = async (phoneNumber) => {
13
17
  try {
14
- const util = await getPhoneUtil();
18
+ let util = null;
19
+ try {
20
+ util = await getPhoneUtil();
21
+ } catch (err) {
22
+ const pattern = /^[+]?[(]?[0-9]{3}[)]?[-\s.]?[0-9]{3}[-\s.]?[0-9]{4,6}$/im;
23
+ return pattern.test(phoneNumber);
24
+ }
15
25
  const parsed = util.parseAndKeepRawInput(phoneNumber);
16
26
  return util.isValidNumber(parsed);
17
27
  } catch (err) {
@@ -19,3 +29,84 @@ export const validatePhoneNumber = async (phoneNumber) => {
19
29
  return false;
20
30
  }
21
31
  };
32
+ export const formatPhone = (phoneNumber, defaultCountry = "US") => {
33
+ if (!phoneNumber || phoneNumber.trim() === "") {
34
+ return "";
35
+ }
36
+ const cleanedNumber = phoneNumber.replace(/[^\d+]/g, "");
37
+ if (cleanedNumber.startsWith("+")) {
38
+ return cleanedNumber;
39
+ }
40
+ const COUNTRY_CODES = {
41
+ US: "1",
42
+ // United States
43
+ CA: "1",
44
+ // Canada
45
+ CN: "86",
46
+ // China
47
+ HK: "852",
48
+ // Hong Kong
49
+ IN: "91",
50
+ // India
51
+ UK: "44",
52
+ // United Kingdom
53
+ GB: "44",
54
+ // United Kingdom
55
+ JP: "81",
56
+ // Japan
57
+ KR: "82",
58
+ // South Korea
59
+ AU: "61",
60
+ // Australia
61
+ DE: "49",
62
+ // Germany
63
+ FR: "33",
64
+ // France
65
+ IT: "39",
66
+ // Italy
67
+ ES: "34",
68
+ // Spain
69
+ BR: "55",
70
+ // Brazil
71
+ RU: "7",
72
+ // Russia
73
+ MX: "52",
74
+ // Mexico
75
+ SG: "65",
76
+ // Singapore
77
+ AE: "971"
78
+ // UAE
79
+ };
80
+ const COUNTRY_PATTERNS = [
81
+ [/^1[3-9]\d{9}$/, "86"],
82
+ // China mobile: 11 digits, starts with 1
83
+ [/^\d{10}$/, "1"],
84
+ // US/Canada: 10 digits
85
+ [/^[6-9]\d{9}$/, "91"],
86
+ // India: 10 digits, starts with 6-9
87
+ [/^0[1-9]\d{8,9}$/, "81"],
88
+ // Japan: 10-11 digits, starts with 0
89
+ [/^07\d{9}$/, "44"],
90
+ // UK mobile: 11 digits, starts with 07
91
+ [/^04\d{8}$/, "61"],
92
+ // Australia mobile: 10 digits, starts with 04
93
+ [/^01[0-9]\d{7,8}$/, "82"],
94
+ // Korea mobile: 10-11 digits, starts with 01
95
+ [/^[0-9]\d{8}$/, "86"]
96
+ // China landline: 9 digits
97
+ ];
98
+ let numberToFormat = cleanedNumber;
99
+ if (numberToFormat.startsWith("0")) {
100
+ numberToFormat = numberToFormat.substring(1);
101
+ }
102
+ for (const [pattern, countryCode2] of COUNTRY_PATTERNS) {
103
+ if (pattern.test(cleanedNumber)) {
104
+ if (cleanedNumber.startsWith("0") && !["1", "86"].includes(countryCode2)) {
105
+ return `+${countryCode2}${cleanedNumber.substring(1)}`;
106
+ }
107
+ return `+${countryCode2}${cleanedNumber}`;
108
+ }
109
+ }
110
+ const countryCode = COUNTRY_CODES[defaultCountry.toUpperCase()] || defaultCountry;
111
+ return `+${countryCode}${numberToFormat}`;
112
+ };
package/es/locales/en.js CHANGED
@@ -242,7 +242,7 @@ export default flat({
242
242
  warning: "Past due invoices need to be paid immediately, otherwise you can not make new purchases anymore.",
243
243
  alert: {
244
244
  title: "You have unpaid invoices",
245
- description: "Seems you have unpaid invoices from previous subscriptions, new purchases are not allowed unless you have paid all past due invoices.",
245
+ customMessage: "Please pay immediately, otherwise new purchases or subscriptions will be prohibited.",
246
246
  confirm: "Pay Now"
247
247
  },
248
248
  view: "View Due Invoices"
@@ -318,9 +318,10 @@ export default flat({
318
318
  owner: "Subscription Owner"
319
319
  },
320
320
  overdue: {
321
- title: "You have {count} due invoices for {subscriptionCount} subscriptions, totaling {total} {symbol}{method}. Please pay immediately to avoid service disruption.",
322
- simpleTitle: "You have {count} due invoices. Please pay now to ensure uninterrupted service.",
323
- empty: "Great! You have no due invoices."
321
+ title: "You have {count} due invoices for {subscriptionCount} subscriptions, totaling {total} {symbol}{method}. ",
322
+ simpleTitle: "You have {count} due invoices. ",
323
+ empty: "Great! You have no due invoices.",
324
+ defaultAlert: "Please pay immediately to avoid service disruption."
324
325
  }
325
326
  },
326
327
  invoice: {
package/es/locales/zh.js CHANGED
@@ -243,6 +243,7 @@ export default flat({
243
243
  alert: {
244
244
  title: "\u4F60\u6709\u6B20\u8D39\u8D26\u5355",
245
245
  description: "\u770B\u8D77\u6765\u4F60\u6709\u6B20\u8D39\u7684\u8D26\u5355\uFF0C\u5728\u4F60\u652F\u4ED8\u6240\u6709\u6B20\u8D39\u8D26\u5355\u4E4B\u524D\uFF0C\u65B0\u7684\u8D2D\u4E70\u6216\u8005\u8BA2\u9605\u5C06\u88AB\u7981\u6B62\uFF0C\u8BF7\u4E0D\u8981\u8C03\u76AE\u3002",
246
+ customMessage: "\u8BF7\u7ACB\u5373\u652F\u4ED8\uFF0C\u5426\u5219\u65B0\u7684\u8D2D\u4E70\u6216\u8005\u8BA2\u9605\u5C06\u88AB\u7981\u6B62\u3002",
246
247
  confirm: "\u53BB\u652F\u4ED8"
247
248
  },
248
249
  view: "\u67E5\u770B\u6B20\u8D39\u660E\u7EC6"
@@ -318,9 +319,10 @@ export default flat({
318
319
  owner: "\u8BA2\u9605\u62E5\u6709\u8005"
319
320
  },
320
321
  overdue: {
321
- title: "\u60A8\u6709 {count} \u5F20\u6B20\u8D39\u8D26\u5355\uFF0C\u6D89\u53CA {subscriptionCount} \u4E2A\u8BA2\u9605\uFF0C\u603B\u91D1\u989D {total} {symbol}{method}\u3002\u8BF7\u7ACB\u5373\u652F\u4ED8\uFF0C\u4EE5\u514D\u5F71\u54CD\u60A8\u7684\u4F7F\u7528\u3002",
322
- simpleTitle: "\u60A8\u6709 {count} \u5F20\u6B20\u8D39\u8D26\u5355\uFF0C\u8BF7\u7ACB\u5373\u652F\u4ED8\uFF0C\u4EE5\u514D\u5F71\u54CD\u60A8\u7684\u4F7F\u7528\u3002",
323
- empty: "\u606D\u559C\uFF01\u60A8\u5F53\u524D\u6CA1\u6709\u6B20\u8D39\u8D26\u5355\u3002"
322
+ title: "\u60A8\u6709 {count} \u5F20\u6B20\u8D39\u8D26\u5355\uFF0C\u6D89\u53CA {subscriptionCount} \u4E2A\u8BA2\u9605\uFF0C\u603B\u91D1\u989D {total} {symbol}{method}\u3002",
323
+ simpleTitle: "\u60A8\u6709 {count} \u5F20\u6B20\u8D39\u8D26\u5355,",
324
+ empty: "\u606D\u559C\uFF01\u60A8\u5F53\u524D\u6CA1\u6709\u6B20\u8D39\u8D26\u5355\u3002",
325
+ defaultAlert: "\u8BF7\u7ACB\u5373\u652F\u4ED8\uFF0C\u4EE5\u514D\u5F71\u54CD\u60A8\u7684\u4F7F\u7528\u3002"
324
326
  }
325
327
  },
326
328
  invoice: {
@@ -29,6 +29,7 @@ import ProductDonation from "./product-donation.js";
29
29
  import ConfirmDialog from "../components/confirm.js";
30
30
  import PaymentBeneficiaries from "../components/payment-beneficiaries.js";
31
31
  import DonationSkeleton from "./skeleton/donation.js";
32
+ import { formatPhone } from "../libs/phone-validator.js";
32
33
  const getBenefits = async (id, url) => {
33
34
  const { data } = await api.get(`/api/payment-links/${id}/benefits?${url ? `url=${url}` : ""}`);
34
35
  return data;
@@ -80,20 +81,22 @@ function PaymentInner({
80
81
  defaultValues: {
81
82
  customer_name: customer?.name || session?.user?.fullName || "",
82
83
  customer_email: customer?.email || session?.user?.email || "",
83
- customer_phone: customer?.phone || session?.user?.phone || "",
84
+ customer_phone: formatPhone(customer?.phone || session?.user?.phone || ""),
84
85
  payment_method: defaultMethodId,
85
86
  payment_currency: defaultCurrencyId,
86
87
  billing_address: Object.assign(
87
88
  {
88
- country: "",
89
- state: "",
90
- city: "",
91
- line1: "",
92
- line2: "",
93
- postal_code: ""
89
+ country: session?.user?.address?.country || "",
90
+ state: session?.user?.address?.province || "",
91
+ city: session?.user?.address?.city || "",
92
+ line1: session?.user?.address?.line1 || "",
93
+ line2: session?.user?.address?.line2 || "",
94
+ postal_code: session?.user?.address?.postalCode || ""
94
95
  },
95
96
  customer?.address || {},
96
- { country: isValidCountry(customer?.address?.country || "") ? customer?.address?.country : "us" }
97
+ {
98
+ country: isValidCountry(customer?.address?.country || session?.user?.address?.country || "") ? customer?.address?.country : "us"
99
+ }
97
100
  )
98
101
  }
99
102
  });
@@ -11,7 +11,6 @@ import { joinURL } from "ufo";
11
11
  import { dispatch } from "use-bus";
12
12
  import isEmail from "validator/es/lib/isEmail";
13
13
  import isEmpty from "lodash/isEmpty";
14
- import ConfirmDialog from "../../components/confirm.js";
15
14
  import FormInput from "../../components/input.js";
16
15
  import { usePaymentContext } from "../../contexts/payment.js";
17
16
  import { useSubscription } from "../../hooks/subscription.js";
@@ -29,8 +28,9 @@ import CurrencySelector from "./currency.js";
29
28
  import PhoneInput from "./phone.js";
30
29
  import StripeCheckout from "./stripe/index.js";
31
30
  import { useMobile } from "../../hooks/mobile.js";
32
- import { validatePhoneNumber } from "../../libs/phone-validator.js";
31
+ import { formatPhone, validatePhoneNumber } from "../../libs/phone-validator.js";
33
32
  import LoadingButton from "../../components/loading-button.js";
33
+ import OverdueInvoicePayment from "../../components/over-due-invoice-payment.js";
34
34
  export const waitForCheckoutComplete = async (sessionId) => {
35
35
  let result;
36
36
  await pWaitFor(
@@ -53,6 +53,31 @@ export const hasDidWallet = (user) => {
53
53
  const connected = user?.connectedAccounts || user?.extraConfigs?.connectedAccounts || [];
54
54
  return connected.some((x) => x.provider === "wallet");
55
55
  };
56
+ const setUserFormValues = (userInfo, currentValues, setValue, options = {}) => {
57
+ const { preferExisting = true } = options;
58
+ const basicFields = {
59
+ customer_name: userInfo.name || userInfo.fullName,
60
+ customer_email: userInfo.email,
61
+ customer_phone: formatPhone(userInfo.phone)
62
+ };
63
+ const addressFields = {
64
+ "billing_address.state": userInfo.address?.state || userInfo.address?.province,
65
+ "billing_address.line1": userInfo.address?.line1,
66
+ "billing_address.line2": userInfo.address?.line2,
67
+ "billing_address.city": userInfo.address?.city,
68
+ "billing_address.postal_code": userInfo.address?.postal_code || userInfo.address?.postalCode,
69
+ "billing_address.country": userInfo.address?.country
70
+ };
71
+ if (options.showPhone) {
72
+ addressFields["billing_address.country"] = userInfo.metadata?.phone?.country || userInfo.address?.country;
73
+ }
74
+ const allFields = { ...addressFields, ...basicFields };
75
+ Object.entries(allFields).forEach(([field, value]) => {
76
+ if (!preferExisting || !currentValues[field.split(".")[0]]) {
77
+ setValue(field, value);
78
+ }
79
+ });
80
+ };
56
81
  PaymentForm.defaultProps = {
57
82
  onlyShowBtn: false,
58
83
  isDonation: false
@@ -129,22 +154,30 @@ export default function PaymentForm({
129
154
  useEffect(() => {
130
155
  if (session?.user) {
131
156
  const values = getValues();
132
- if (!values.customer_name) {
133
- setValue("customer_name", session.user.fullName);
134
- }
135
- if (!values.customer_email) {
136
- setValue("customer_email", session.user.email);
137
- }
138
- if (!values.customer_phone) {
139
- setValue("customer_phone", session.user.phone);
140
- }
141
- }
142
- if (!session?.user) {
143
- setValue("customer_name", "");
144
- setValue("customer_email", "");
145
- setValue("customer_phone", "");
157
+ setUserFormValues(session.user, values, setValue, {
158
+ preferExisting: false,
159
+ showPhone: checkoutSession.phone_number_collection?.enabled
160
+ });
161
+ } else {
162
+ setUserFormValues(
163
+ {
164
+ name: "",
165
+ email: "",
166
+ phone: "",
167
+ address: {
168
+ state: "",
169
+ line1: "",
170
+ line2: "",
171
+ city: "",
172
+ postal_code: ""
173
+ }
174
+ },
175
+ {},
176
+ setValue,
177
+ { preferExisting: false, showPhone: checkoutSession.phone_number_collection?.enabled }
178
+ );
146
179
  }
147
- }, [session?.user, getValues, setValue]);
180
+ }, [session?.user, getValues, setValue, checkoutSession.phone_number_collection?.enabled]);
148
181
  useEffect(() => {
149
182
  setValue("payment_method", currencies[paymentCurrencyIndex]?.method?.id);
150
183
  setValue("payment_currency", currencies[paymentCurrencyIndex]?.id);
@@ -175,7 +208,7 @@ export default function PaymentForm({
175
208
  buttonText = session?.user || isDonation ? buttonText : t("payment.checkout.connect", { action: buttonText });
176
209
  const method = paymentMethods.find((x) => x.id === paymentMethod);
177
210
  const isDonationMode = checkoutSession?.submit_type === "donate" && isDonation;
178
- const showForm = session?.user;
211
+ const showForm = !!session?.user;
179
212
  const skipBindWallet = method.type === "stripe";
180
213
  const handleConnected = async () => {
181
214
  try {
@@ -199,33 +232,9 @@ export default function PaymentForm({
199
232
  const { data: profile } = await api.get("/api/customers/me?fallback=1");
200
233
  if (profile) {
201
234
  const values = getValues();
202
- if (!values.customer_name) {
203
- setValue("customer_name", profile.name);
204
- }
205
- if (!values.customer_email) {
206
- setValue("customer_email", profile.email);
207
- }
208
- if (!values.customer_phone) {
209
- setValue("customer_phone", profile.phone);
210
- }
211
- if (profile.address?.country) {
212
- setValue("billing_address.country", profile.address.country);
213
- }
214
- if (profile.address?.state) {
215
- setValue("billing_address.state", profile.address.state);
216
- }
217
- if (profile.address?.line1) {
218
- setValue("billing_address.line1", profile.address.line1);
219
- }
220
- if (profile.address?.line2) {
221
- setValue("billing_address.line2", profile.address.line2);
222
- }
223
- if (profile.address?.city) {
224
- setValue("billing_address.city", profile.address.city);
225
- }
226
- if (profile.address?.postal_code) {
227
- setValue("billing_address.postal_code", profile.address.postal_code);
228
- }
235
+ setUserFormValues(profile, values, setValue, {
236
+ showPhone: checkoutSession.phone_number_collection?.enabled
237
+ });
229
238
  }
230
239
  };
231
240
  const onFormSubmit = async (data) => {
@@ -377,17 +386,32 @@ export default function PaymentForm({
377
386
  }
378
387
  ) }),
379
388
  state.customerLimited && /* @__PURE__ */ jsx(
380
- ConfirmDialog,
389
+ OverdueInvoicePayment,
381
390
  {
382
- onConfirm: () => window.open(
383
- joinURL(getPrefix(), `/customer/invoice/past-due?referer=${encodeURIComponent(window.location.href)}`),
384
- "_self"
385
- ),
386
- onCancel: () => setState({ customerLimited: false }),
387
- confirm: t("payment.customer.pastDue.alert.confirm"),
388
- title: t("payment.customer.pastDue.alert.title"),
389
- message: t("payment.customer.pastDue.alert.description"),
390
- color: "primary"
391
+ customerId: customer?.id || session?.user?.did,
392
+ onPaid: () => {
393
+ setState({ customerLimited: false });
394
+ onAction();
395
+ },
396
+ alertMessage: t("payment.customer.pastDue.alert.customMessage"),
397
+ detailLinkOptions: {
398
+ enabled: true,
399
+ onClick: () => {
400
+ setState({ customerLimited: false });
401
+ window.open(
402
+ joinURL(
403
+ getPrefix(),
404
+ `/customer/invoice/past-due?referer=${encodeURIComponent(window.location.href)}`
405
+ ),
406
+ "_self"
407
+ );
408
+ }
409
+ },
410
+ dialogProps: {
411
+ open: state.customerLimited,
412
+ onClose: () => setState({ customerLimited: false }),
413
+ title: t("payment.customer.pastDue.alert.title")
414
+ }
391
415
  }
392
416
  )
393
417
  ] });
@@ -528,17 +552,29 @@ export default function PaymentForm({
528
552
  ["subscription", "setup"].includes(checkoutSession.mode) && /* @__PURE__ */ jsx(Typography, { sx: { mt: 2.5, color: "text.lighter", fontSize: "0.7875rem", lineHeight: "0.9625rem" }, children: t("payment.checkout.confirm", { payee }) })
529
553
  ] }) }),
530
554
  state.customerLimited && /* @__PURE__ */ jsx(
531
- ConfirmDialog,
555
+ OverdueInvoicePayment,
532
556
  {
533
- onConfirm: () => window.open(
534
- joinURL(getPrefix(), `/customer/invoice/past-due?referer=${encodeURIComponent(window.location.href)}`),
535
- "_self"
536
- ),
537
- onCancel: () => setState({ customerLimited: false }),
538
- confirm: t("payment.customer.pastDue.alert.confirm"),
539
- title: t("payment.customer.pastDue.alert.title"),
540
- message: t("payment.customer.pastDue.alert.description"),
541
- color: "primary"
557
+ customerId: customer?.id || session?.user?.didssion?.user?.did,
558
+ onPaid: () => {
559
+ setState({ customerLimited: false });
560
+ onAction();
561
+ },
562
+ alertMessage: t("payment.customer.pastDue.alert.customMessage"),
563
+ detailLinkOptions: {
564
+ enabled: true,
565
+ onClick: () => {
566
+ setState({ customerLimited: false });
567
+ window.open(
568
+ joinURL(getPrefix(), `/customer/invoice/past-due?referer=${encodeURIComponent(window.location.href)}`),
569
+ "_self"
570
+ );
571
+ }
572
+ },
573
+ dialogProps: {
574
+ open: state.customerLimited,
575
+ onClose: () => setState({ customerLimited: false }),
576
+ title: t("payment.customer.pastDue.alert.title")
577
+ }
542
578
  }
543
579
  )
544
580
  ] });
@@ -1,7 +1,7 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { InputAdornment } from "@mui/material";
3
3
  import omit from "lodash/omit";
4
- import { useEffect } from "react";
4
+ import { useEffect, useRef, useCallback } from "react";
5
5
  import { useFormContext, useWatch } from "react-hook-form";
6
6
  import { defaultCountries, usePhoneInput } from "react-international-phone";
7
7
  import FormInput from "../../components/input.js";
@@ -11,25 +11,46 @@ export default function PhoneInput({ ...props }) {
11
11
  const countryFieldName = props.countryFieldName || "billing_address.country";
12
12
  const { control, getValues, setValue } = useFormContext();
13
13
  const values = getValues();
14
+ const isUpdatingRef = useRef(false);
15
+ const safeUpdate = useCallback((callback) => {
16
+ if (isUpdatingRef.current)
17
+ return;
18
+ try {
19
+ isUpdatingRef.current = true;
20
+ callback();
21
+ } finally {
22
+ requestAnimationFrame(() => {
23
+ isUpdatingRef.current = false;
24
+ });
25
+ }
26
+ }, []);
14
27
  const { phone, handlePhoneValueChange, inputRef, country, setCountry } = usePhoneInput({
15
28
  defaultCountry: isValidCountry(values[countryFieldName]) ? values[countryFieldName] : "us",
16
29
  value: values[props.name] || "",
17
30
  countries: defaultCountries,
18
31
  onChange: (data) => {
19
- setValue(props.name, data.phone);
20
- setValue(countryFieldName, data.country);
32
+ safeUpdate(() => {
33
+ setValue(props.name, data.phone);
34
+ setValue(countryFieldName, data.country);
35
+ });
21
36
  }
22
37
  });
23
38
  const userCountry = useWatch({ control, name: countryFieldName });
24
39
  useEffect(() => {
25
- if (userCountry !== country) {
40
+ if (!userCountry || userCountry === country)
41
+ return;
42
+ safeUpdate(() => {
26
43
  setCountry(userCountry);
27
- }
28
- }, [userCountry]);
29
- const onCountryChange = (v) => {
30
- setCountry(v);
31
- setValue(countryFieldName, v);
32
- };
44
+ });
45
+ }, [userCountry, country, setCountry, safeUpdate]);
46
+ const onCountryChange = useCallback(
47
+ (v) => {
48
+ safeUpdate(() => {
49
+ setCountry(v);
50
+ });
51
+ },
52
+ [setCountry, safeUpdate]
53
+ );
33
54
  return (
34
55
  // @ts-ignore
35
56
  /* @__PURE__ */ jsx(
@@ -28,6 +28,7 @@ import PaymentSkeleton from "./skeleton/payment.js";
28
28
  import PaymentSuccess from "./success.js";
29
29
  import PaymentSummary from "./summary.js";
30
30
  import { useMobile } from "../hooks/mobile.js";
31
+ import { formatPhone } from "../libs/phone-validator.js";
31
32
  PaymentInner.defaultProps = {
32
33
  completed: false,
33
34
  showCheckoutSummary: true
@@ -58,20 +59,22 @@ function PaymentInner({
58
59
  defaultValues: {
59
60
  customer_name: customer?.name || session?.user?.fullName || "",
60
61
  customer_email: customer?.email || session?.user?.email || "",
61
- customer_phone: customer?.phone || session?.user?.phone || "",
62
+ customer_phone: formatPhone(customer?.phone || session?.user?.phone || ""),
62
63
  payment_method: defaultMethodId,
63
64
  payment_currency: defaultCurrencyId,
64
65
  billing_address: Object.assign(
65
66
  {
66
- country: "",
67
- state: "",
68
- city: "",
69
- line1: "",
70
- line2: "",
71
- postal_code: ""
67
+ country: session?.user?.address?.country || "",
68
+ state: session?.user?.address?.province || "",
69
+ city: session?.user?.address?.city || "",
70
+ line1: session?.user?.address?.line1 || "",
71
+ line2: session?.user?.address?.line2 || "",
72
+ postal_code: session?.user?.address?.postalCode || ""
72
73
  },
73
74
  customer?.address || {},
74
- { country: isValidCountry(customer?.address?.country || "") ? customer?.address?.country : "us" }
75
+ {
76
+ country: isValidCountry(customer?.address?.country || session?.user?.address?.country || "") ? customer?.address?.country : "us"
77
+ }
75
78
  )
76
79
  }
77
80
  });
@@ -35,9 +35,6 @@ export default function ProductDonation({
35
35
  }
36
36
  };
37
37
  const getDefaultPreset = () => {
38
- if (settings?.amount?.preset) {
39
- return formatAmount(settings.amount.preset);
40
- }
41
38
  try {
42
39
  const savedPreset = localStorage.getItem(getUserStorageKey(DONATION_PRESET_KEY_BASE));
43
40
  if (savedPreset) {
@@ -53,7 +50,13 @@ export default function ProductDonation({
53
50
  }
54
51
  if (presets.length > 0) {
55
52
  const middleIndex = Math.floor(presets.length / 2);
56
- return presets[middleIndex] || presets[0];
53
+ return presets[middleIndex];
54
+ }
55
+ if (settings?.amount?.preset) {
56
+ return formatAmount(settings.amount.preset);
57
+ }
58
+ if (presets.length > 0) {
59
+ return presets[0];
57
60
  }
58
61
  return "0";
59
62
  };
@@ -17,6 +17,7 @@ type Props = {
17
17
  dialogProps?: DialogProps;
18
18
  detailLinkOptions?: DetailLinkOptions;
19
19
  successToast?: boolean;
20
+ alertMessage?: string;
20
21
  children?: (handlePay: (item: SummaryItem) => void, data: {
21
22
  subscription?: Subscription;
22
23
  summary: {
@@ -32,7 +33,7 @@ type SummaryItem = {
32
33
  currency: PaymentCurrency;
33
34
  method: PaymentMethod;
34
35
  };
35
- declare function OverdueInvoicePayment({ subscriptionId, customerId, mode, dialogProps, children, onPaid, detailLinkOptions, successToast, }: Props): import("react").JSX.Element | null;
36
+ declare function OverdueInvoicePayment({ subscriptionId, customerId, mode, dialogProps, children, onPaid, detailLinkOptions, successToast, alertMessage, }: Props): import("react").JSX.Element | null;
36
37
  declare namespace OverdueInvoicePayment {
37
38
  var defaultProps: {
38
39
  mode: string;
@@ -47,6 +48,7 @@ declare namespace OverdueInvoicePayment {
47
48
  subscriptionId: undefined;
48
49
  customerId: undefined;
49
50
  successToast: boolean;
51
+ alertMessage: string;
50
52
  };
51
53
  }
52
54
  export default OverdueInvoicePayment;