@blocklet/payment-react 1.21.13 → 1.21.14
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 +2 -2
- package/es/components/country-select.d.ts +6 -2
- package/es/components/country-select.js +170 -30
- package/es/components/source-data-viewer.js +25 -14
- package/es/history/credit/transactions-list.js +11 -1
- package/es/index.d.ts +1 -0
- package/es/libs/validator.d.ts +161 -0
- package/es/libs/validator.js +172 -61
- package/es/locales/en.js +1 -0
- package/es/locales/zh.js +1 -0
- package/es/payment/form/address.d.ts +1 -2
- package/es/payment/form/address.js +38 -41
- package/es/payment/form/index.js +130 -13
- package/lib/components/country-select.d.ts +6 -2
- package/lib/components/country-select.js +173 -40
- package/lib/components/source-data-viewer.js +5 -3
- package/lib/history/credit/transactions-list.js +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/libs/validator.d.ts +161 -0
- package/lib/libs/validator.js +173 -6
- package/lib/locales/en.js +1 -0
- package/lib/locales/zh.js +1 -0
- package/lib/payment/form/address.d.ts +1 -2
- package/lib/payment/form/address.js +51 -55
- package/lib/payment/form/index.js +168 -12
- package/package.json +3 -3
- package/src/components/country-select.tsx +176 -25
- package/src/components/source-data-viewer.tsx +9 -3
- package/src/history/credit/transactions-list.tsx +6 -1
- package/src/index.ts +2 -0
- package/src/libs/validator.ts +173 -61
- package/src/locales/en.tsx +1 -0
- package/src/locales/zh.tsx +1 -0
- package/src/payment/form/address.tsx +45 -50
- package/src/payment/form/index.tsx +157 -12
|
@@ -9,13 +9,12 @@ import { getFieldValidation, validatePostalCode } from '../../libs/validator';
|
|
|
9
9
|
|
|
10
10
|
type Props = {
|
|
11
11
|
mode: string;
|
|
12
|
-
stripe: boolean;
|
|
13
12
|
sx?: SxProps;
|
|
14
13
|
fieldValidation?: Record<string, any>;
|
|
15
14
|
errorPosition?: 'right' | 'bottom';
|
|
16
15
|
};
|
|
17
16
|
|
|
18
|
-
export default function AddressForm({ mode,
|
|
17
|
+
export default function AddressForm({ mode, sx = {}, fieldValidation = {}, errorPosition = 'right' }: Props) {
|
|
19
18
|
const { t, locale } = useLocaleContext();
|
|
20
19
|
const { control } = useFormContext();
|
|
21
20
|
const country = useWatch({ control, name: 'billing_address.country' });
|
|
@@ -99,54 +98,50 @@ export default function AddressForm({ mode, stripe, sx = {}, fieldValidation = {
|
|
|
99
98
|
);
|
|
100
99
|
}
|
|
101
100
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
<
|
|
105
|
-
<Stack className="cko-payment-
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
<
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
<
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
'
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
/>
|
|
144
|
-
</Stack>
|
|
101
|
+
return (
|
|
102
|
+
<Fade in>
|
|
103
|
+
<Stack className="cko-payment-address cko-payment-form" sx={sx}>
|
|
104
|
+
<Stack direction="column" className="cko-payment-form" spacing={0}>
|
|
105
|
+
<FormLabel className="base-label">{t('payment.checkout.billing.postal_code')}</FormLabel>
|
|
106
|
+
<Stack direction="row" spacing={0}>
|
|
107
|
+
<FormInput
|
|
108
|
+
name="billing_address.postal_code"
|
|
109
|
+
rules={{
|
|
110
|
+
required: t('payment.checkout.required'),
|
|
111
|
+
validate: (x: string) => {
|
|
112
|
+
const isValid = validatePostalCode(x, country);
|
|
113
|
+
return isValid ? true : t('payment.checkout.invalid');
|
|
114
|
+
},
|
|
115
|
+
...getFieldValidation('billing_address.postal_code', fieldValidation, locale),
|
|
116
|
+
}}
|
|
117
|
+
errorPosition={errorPosition}
|
|
118
|
+
variant="outlined"
|
|
119
|
+
placeholder={t('payment.checkout.billing.postal_code')}
|
|
120
|
+
InputProps={{
|
|
121
|
+
startAdornment: (
|
|
122
|
+
<InputAdornment position="start" style={{ marginRight: '2px', marginLeft: '-8px' }}>
|
|
123
|
+
<Controller
|
|
124
|
+
name="billing_address.country"
|
|
125
|
+
control={control}
|
|
126
|
+
render={({ field }) => (
|
|
127
|
+
<CountrySelect
|
|
128
|
+
{...field}
|
|
129
|
+
ref={field.ref as unknown as React.RefObject<HTMLDivElement | null>}
|
|
130
|
+
sx={{
|
|
131
|
+
'.MuiOutlinedInput-notchedOutline': {
|
|
132
|
+
borderColor: 'transparent !important',
|
|
133
|
+
},
|
|
134
|
+
}}
|
|
135
|
+
/>
|
|
136
|
+
)}
|
|
137
|
+
/>
|
|
138
|
+
</InputAdornment>
|
|
139
|
+
),
|
|
140
|
+
}}
|
|
141
|
+
/>
|
|
145
142
|
</Stack>
|
|
146
143
|
</Stack>
|
|
147
|
-
</
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return null;
|
|
144
|
+
</Stack>
|
|
145
|
+
</Fade>
|
|
146
|
+
);
|
|
152
147
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import 'react-international-phone/style.css';
|
|
3
3
|
|
|
4
4
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
5
|
+
import { FlagEmoji } from 'react-international-phone';
|
|
5
6
|
// import { useTheme } from '@arcblock/ux/lib/Theme';
|
|
6
7
|
import Toast from '@arcblock/ux/lib/Toast';
|
|
7
8
|
import type {
|
|
@@ -52,7 +53,7 @@ import LoadingButton from '../../components/loading-button';
|
|
|
52
53
|
import OverdueInvoicePayment from '../../components/over-due-invoice-payment';
|
|
53
54
|
import { saveCurrencyPreference } from '../../libs/currency';
|
|
54
55
|
import ConfirmDialog from '../../components/confirm';
|
|
55
|
-
import { getFieldValidation } from '../../libs/validator';
|
|
56
|
+
import { getFieldValidation, validatePostalCode } from '../../libs/validator';
|
|
56
57
|
|
|
57
58
|
export const waitForCheckoutComplete = async (sessionId: string) => {
|
|
58
59
|
let result: CheckoutContext;
|
|
@@ -222,6 +223,7 @@ export default function PaymentForm({
|
|
|
222
223
|
creditInsufficientInfo: {
|
|
223
224
|
open: boolean;
|
|
224
225
|
} | null;
|
|
226
|
+
showEditForm: boolean;
|
|
225
227
|
}>({
|
|
226
228
|
submitting: false,
|
|
227
229
|
paying: false,
|
|
@@ -233,6 +235,7 @@ export default function PaymentForm({
|
|
|
233
235
|
stripePaying: false,
|
|
234
236
|
fastCheckoutInfo: null,
|
|
235
237
|
creditInsufficientInfo: null,
|
|
238
|
+
showEditForm: false,
|
|
236
239
|
});
|
|
237
240
|
|
|
238
241
|
const currencies = flattenPaymentMethods(paymentMethods);
|
|
@@ -368,25 +371,110 @@ export default function PaymentForm({
|
|
|
368
371
|
const showStake = method.type === 'arcblock' && !checkoutSession.subscription_data?.no_stake;
|
|
369
372
|
|
|
370
373
|
const isDonationMode = checkoutSession?.submit_type === 'donate' && isDonation;
|
|
371
|
-
|
|
374
|
+
|
|
375
|
+
const validateUserInfo = () => {
|
|
372
376
|
if (!session?.user) {
|
|
373
377
|
return false;
|
|
374
378
|
}
|
|
375
|
-
|
|
376
|
-
|
|
379
|
+
|
|
380
|
+
const { fullName, name, email, phone, address } = session.user;
|
|
381
|
+
const fieldValidation = checkoutSession.metadata?.page_info?.field_validation;
|
|
382
|
+
|
|
383
|
+
const hasName = !!(fullName || name);
|
|
384
|
+
if (!hasName) {
|
|
385
|
+
return false;
|
|
377
386
|
}
|
|
378
|
-
|
|
379
|
-
|
|
387
|
+
|
|
388
|
+
const hasValidEmail = email && isEmail(email);
|
|
389
|
+
if (!hasValidEmail) {
|
|
390
|
+
return false;
|
|
380
391
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
392
|
+
|
|
393
|
+
const nameValidation = getFieldValidation('customer_name', fieldValidation, locale);
|
|
394
|
+
if (nameValidation.pattern && fullName) {
|
|
395
|
+
const pattern = nameValidation.pattern.value;
|
|
396
|
+
if (!pattern.test(fullName)) {
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
384
399
|
}
|
|
385
|
-
|
|
400
|
+
|
|
401
|
+
const emailValidation = getFieldValidation('customer_email', fieldValidation, locale);
|
|
402
|
+
if (emailValidation.pattern && email) {
|
|
403
|
+
const pattern = emailValidation.pattern.value;
|
|
404
|
+
if (!pattern.test(email)) {
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (!address || !address.postalCode || !validatePostalCode(address.postalCode, address.country)) {
|
|
386
410
|
return false;
|
|
387
411
|
}
|
|
412
|
+
|
|
413
|
+
const postalCodeValidation = getFieldValidation('billing_address.postal_code', fieldValidation, locale);
|
|
414
|
+
if (postalCodeValidation.pattern) {
|
|
415
|
+
const pattern = postalCodeValidation.pattern.value;
|
|
416
|
+
if (!pattern.test(address.postalCode)) {
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (checkoutSession.phone_number_collection?.enabled) {
|
|
422
|
+
if (!phone || phone.trim() === '') {
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
const phoneValidation = getFieldValidation('customer_phone', fieldValidation, locale);
|
|
426
|
+
if (phoneValidation.pattern) {
|
|
427
|
+
const pattern = phoneValidation.pattern.value;
|
|
428
|
+
if (!pattern.test(phone)) {
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const addressMode = checkoutSession.billing_address_collection;
|
|
435
|
+
if (addressMode === 'required') {
|
|
436
|
+
if (!address?.country || !address?.province || !address?.line1 || !address?.city || !address?.postalCode) {
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const line1Validation = getFieldValidation('billing_address.line1', fieldValidation, locale);
|
|
441
|
+
if (line1Validation.pattern) {
|
|
442
|
+
const pattern = line1Validation.pattern.value;
|
|
443
|
+
if (!pattern.test(address.line1)) {
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const cityValidation = getFieldValidation('billing_address.city', fieldValidation, locale);
|
|
449
|
+
if (cityValidation.pattern) {
|
|
450
|
+
const pattern = cityValidation.pattern.value;
|
|
451
|
+
if (!pattern.test(address.city)) {
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const stateValidation = getFieldValidation('billing_address.state', fieldValidation, locale);
|
|
457
|
+
if (stateValidation.pattern) {
|
|
458
|
+
const pattern = stateValidation.pattern.value;
|
|
459
|
+
if (!pattern.test(address.province)) {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
388
465
|
return true;
|
|
389
|
-
}
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
const showForm = useMemo(() => {
|
|
469
|
+
if (!session?.user) {
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
472
|
+
if (state.showEditForm) {
|
|
473
|
+
return true;
|
|
474
|
+
}
|
|
475
|
+
return !validateUserInfo();
|
|
476
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
477
|
+
}, [session?.user, method, state.showEditForm]);
|
|
390
478
|
|
|
391
479
|
const handleConnected = async () => {
|
|
392
480
|
if (processingRef.current) {
|
|
@@ -910,6 +998,64 @@ export default function PaymentForm({
|
|
|
910
998
|
)}
|
|
911
999
|
</Stack>
|
|
912
1000
|
</Fade>
|
|
1001
|
+
{!showForm && session?.user && (
|
|
1002
|
+
<Stack
|
|
1003
|
+
spacing={1.25}
|
|
1004
|
+
sx={{
|
|
1005
|
+
mt: 2,
|
|
1006
|
+
p: 2,
|
|
1007
|
+
pt: 1,
|
|
1008
|
+
backgroundColor: 'background.paper',
|
|
1009
|
+
borderRadius: 1,
|
|
1010
|
+
border: '1px solid',
|
|
1011
|
+
borderColor: 'divider',
|
|
1012
|
+
}}>
|
|
1013
|
+
<Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ mb: 0.25 }}>
|
|
1014
|
+
<Typography variant="subtitle2" sx={{ color: 'text.primary', fontSize: '0.875rem' }}>
|
|
1015
|
+
{t('payment.checkout.customerInfo')}
|
|
1016
|
+
</Typography>
|
|
1017
|
+
<Button
|
|
1018
|
+
size="small"
|
|
1019
|
+
variant="text"
|
|
1020
|
+
onClick={() => setState({ showEditForm: true })}
|
|
1021
|
+
sx={{ minWidth: 0 }}>
|
|
1022
|
+
{t('common.edit')}
|
|
1023
|
+
</Button>
|
|
1024
|
+
</Stack>
|
|
1025
|
+
<Stack spacing={0.5}>
|
|
1026
|
+
<Typography variant="body2" sx={{ color: 'text.primary', fontWeight: 600, fontSize: '0.9375rem' }}>
|
|
1027
|
+
{session.user.fullName || session.user.name}
|
|
1028
|
+
</Typography>
|
|
1029
|
+
<Typography variant="body2" sx={{ color: 'text.secondary', fontSize: '0.8125rem' }}>
|
|
1030
|
+
{session.user.email}
|
|
1031
|
+
</Typography>
|
|
1032
|
+
{checkoutSession.phone_number_collection?.enabled && session.user.phone && (
|
|
1033
|
+
<Typography variant="body2" sx={{ color: 'text.secondary', fontSize: '0.8125rem' }}>
|
|
1034
|
+
{session.user.phone}
|
|
1035
|
+
</Typography>
|
|
1036
|
+
)}
|
|
1037
|
+
{session.user.address && (
|
|
1038
|
+
<Stack direction="row" alignItems="center" spacing={0.75}>
|
|
1039
|
+
{session.user.address.country && (
|
|
1040
|
+
<FlagEmoji iso2={session.user.address.country.toLowerCase()} style={{ width: 18, height: 14 }} />
|
|
1041
|
+
)}
|
|
1042
|
+
<Typography variant="body2" sx={{ color: 'text.secondary', fontSize: '0.8125rem' }}>
|
|
1043
|
+
{[
|
|
1044
|
+
session.user.address.line1,
|
|
1045
|
+
session.user.address.city,
|
|
1046
|
+
session.user.address.province,
|
|
1047
|
+
session.user.address.country?.toUpperCase(),
|
|
1048
|
+
]
|
|
1049
|
+
.filter(Boolean)
|
|
1050
|
+
.join(', ')}
|
|
1051
|
+
{session.user.address.postalCode &&
|
|
1052
|
+
` [ ${t('payment.checkout.billing.postal_code')}: ${session.user.address.postalCode} ]`}
|
|
1053
|
+
</Typography>
|
|
1054
|
+
</Stack>
|
|
1055
|
+
)}
|
|
1056
|
+
</Stack>
|
|
1057
|
+
</Stack>
|
|
1058
|
+
)}
|
|
913
1059
|
{showForm && (
|
|
914
1060
|
<Stack
|
|
915
1061
|
direction="column"
|
|
@@ -968,7 +1114,6 @@ export default function PaymentForm({
|
|
|
968
1114
|
)}
|
|
969
1115
|
<AddressForm
|
|
970
1116
|
mode={checkoutSession.billing_address_collection as string}
|
|
971
|
-
stripe={method?.type === 'stripe'}
|
|
972
1117
|
sx={{ marginTop: '0 !important' }}
|
|
973
1118
|
fieldValidation={checkoutSession.metadata?.page_info?.field_validation}
|
|
974
1119
|
errorPosition={formErrorPosition}
|