tf-checkout-react 1.3.2 → 1.3.3
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/dist/components/billing-info-container/utils.d.ts +2 -2
- package/dist/components/common/PhoneNumberField.d.ts +1 -1
- package/dist/components/confirmationContainer/index.d.ts +7 -1
- package/dist/tf-checkout-react.cjs.development.js +89 -34
- package/dist/tf-checkout-react.cjs.development.js.map +1 -1
- package/dist/tf-checkout-react.cjs.production.min.js +1 -1
- package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
- package/dist/tf-checkout-react.esm.js +89 -34
- package/dist/tf-checkout-react.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/billing-info-container/index.tsx +13 -7
- package/src/components/billing-info-container/utils.ts +11 -2
- package/src/components/common/DatePickerField.tsx +7 -1
- package/src/components/common/PhoneNumberField.tsx +14 -2
- package/src/components/confirmationContainer/index.tsx +27 -11
- package/src/components/ticketsContainer/index.tsx +36 -27
package/package.json
CHANGED
|
@@ -779,7 +779,8 @@ export const BillingInfoContainer = React.memo(
|
|
|
779
779
|
validate={getValidateFunctions(
|
|
780
780
|
element,
|
|
781
781
|
states,
|
|
782
|
-
props.values
|
|
782
|
+
props.values,
|
|
783
|
+
props.errors,
|
|
783
784
|
)}
|
|
784
785
|
setFieldValue={props.setFieldValue}
|
|
785
786
|
onBlur={props.handleBlur}
|
|
@@ -829,14 +830,18 @@ export const BillingInfoContainer = React.memo(
|
|
|
829
830
|
return (
|
|
830
831
|
<div key={group.id}>
|
|
831
832
|
<div className={groupClassname}>
|
|
832
|
-
{_map(groupItems, element =>
|
|
833
|
+
{_map(groupItems, element => {
|
|
834
|
+
if (_includes(['holderFirstName', 'holderLastName'], element.name)) {
|
|
835
|
+
element.required = showTicketHolders
|
|
836
|
+
}
|
|
837
|
+
return (
|
|
833
838
|
<div
|
|
834
839
|
className={element.className}
|
|
835
840
|
key={element.name}
|
|
836
841
|
>
|
|
837
842
|
<Field
|
|
838
843
|
name={`${element.name}-${index}`}
|
|
839
|
-
label={element.label}
|
|
844
|
+
label={`${element.label}${element.required ? '' : ' (optional)'}`}
|
|
840
845
|
type={element.type}
|
|
841
846
|
component={
|
|
842
847
|
element.type === 'checkbox'
|
|
@@ -855,9 +860,9 @@ export const BillingInfoContainer = React.memo(
|
|
|
855
860
|
element.onValidate
|
|
856
861
|
? element.onValidate
|
|
857
862
|
: () =>
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
863
|
+
props.errors[
|
|
864
|
+
`${element.name}-${index}`
|
|
865
|
+
]
|
|
861
866
|
)}
|
|
862
867
|
disableDropdown={element.disableDropdown}
|
|
863
868
|
setPhoneValidationIsLoading={
|
|
@@ -865,7 +870,8 @@ export const BillingInfoContainer = React.memo(
|
|
|
865
870
|
}
|
|
866
871
|
/>
|
|
867
872
|
</div>
|
|
868
|
-
|
|
873
|
+
)
|
|
874
|
+
})}
|
|
869
875
|
</div>
|
|
870
876
|
</div>
|
|
871
877
|
)
|
|
@@ -8,7 +8,7 @@ import { CONFIGS } from '../../utils'
|
|
|
8
8
|
import { IGroupItem } from '../../types'
|
|
9
9
|
import { combineValidators, requiredValidator } from '../../validators'
|
|
10
10
|
import { nanoid } from 'nanoid'
|
|
11
|
-
import { FormikValues } from 'formik'
|
|
11
|
+
import { FormikErrors, FormikValues } from 'formik'
|
|
12
12
|
|
|
13
13
|
export interface ILoggedInValues {
|
|
14
14
|
emailLogged?: string;
|
|
@@ -180,7 +180,8 @@ export const createCheckoutDataBody = (
|
|
|
180
180
|
export const getValidateFunctions = (
|
|
181
181
|
element: IGroupItem,
|
|
182
182
|
states: Array<{ [key: string]: any }>,
|
|
183
|
-
values: FormikValues
|
|
183
|
+
values: FormikValues,
|
|
184
|
+
errors: FormikErrors<any>,
|
|
184
185
|
) => {
|
|
185
186
|
const validationFunctions: any[] = []
|
|
186
187
|
|
|
@@ -197,6 +198,14 @@ export const getValidateFunctions = (
|
|
|
197
198
|
validationFunctions.push(element.onValidate)
|
|
198
199
|
}
|
|
199
200
|
|
|
201
|
+
if (element.name === 'phone') {
|
|
202
|
+
const invalidPhone = () =>
|
|
203
|
+
errors.phone === 'Invalid phone number'
|
|
204
|
+
? 'Invalid phone number'
|
|
205
|
+
: null
|
|
206
|
+
validationFunctions.push(invalidPhone)
|
|
207
|
+
}
|
|
208
|
+
|
|
200
209
|
if (element.name === 'confirmEmail') {
|
|
201
210
|
const isSameEmail = (confirmEmail?: string) =>
|
|
202
211
|
values.email !== confirmEmail
|
|
@@ -90,7 +90,13 @@ export const DatePickerField = ({
|
|
|
90
90
|
{...params}
|
|
91
91
|
inputProps={{ ...params.inputProps, placeholder: 'dd/mm/yyyy' }}
|
|
92
92
|
theme={theme}
|
|
93
|
-
field={
|
|
93
|
+
field={{
|
|
94
|
+
...field, onChange: (evt: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
|
95
|
+
if (params.inputProps && params.inputProps.onChange) {
|
|
96
|
+
params.inputProps.onChange(evt);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}}
|
|
94
100
|
form={form}
|
|
95
101
|
label={label}
|
|
96
102
|
type="tel"
|
|
@@ -29,6 +29,7 @@ export const PhoneNumberField = ({
|
|
|
29
29
|
initialValues,
|
|
30
30
|
setFieldValue,
|
|
31
31
|
setFieldTouched,
|
|
32
|
+
setErrors,
|
|
32
33
|
},
|
|
33
34
|
disableDropdown = true,
|
|
34
35
|
fill = false,
|
|
@@ -50,17 +51,27 @@ export const PhoneNumberField = ({
|
|
|
50
51
|
|
|
51
52
|
debounceCb(async () => {
|
|
52
53
|
try {
|
|
54
|
+
if (!values[field.name]) {
|
|
55
|
+
const newErrors = { ...errors }
|
|
56
|
+
delete newErrors[field.name]
|
|
57
|
+
setErrors(newErrors)
|
|
58
|
+
return
|
|
59
|
+
}
|
|
53
60
|
if (values[field.name]) {
|
|
54
61
|
await validatePhoneNumber(values[field.name])
|
|
55
62
|
}
|
|
56
|
-
|
|
63
|
+
if (errors[field.name]) {
|
|
64
|
+
const newErrors = { ...errors }
|
|
65
|
+
delete newErrors[field.name]
|
|
66
|
+
setErrors(newErrors)
|
|
67
|
+
}
|
|
57
68
|
} catch (error) {
|
|
58
69
|
const message = _get(
|
|
59
70
|
error,
|
|
60
71
|
'response.data.message',
|
|
61
72
|
'Invalid phone number'
|
|
62
73
|
)
|
|
63
|
-
if (values[field.name]) {
|
|
74
|
+
if (values[field.name] && errors[field.name] !== message) {
|
|
64
75
|
setFieldError(field.name, message)
|
|
65
76
|
}
|
|
66
77
|
} finally {
|
|
@@ -93,6 +104,7 @@ export const PhoneNumberField = ({
|
|
|
93
104
|
fullWidth
|
|
94
105
|
autoFormat={false}
|
|
95
106
|
disableAreaCodes={true}
|
|
107
|
+
countryCodeEditable={false}
|
|
96
108
|
/>
|
|
97
109
|
</>
|
|
98
110
|
)
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/* eslint-disable react/no-unescaped-entities */
|
|
2
|
-
import React, { useEffect, useRef, useState } from 'react'
|
|
3
2
|
import './style.css'
|
|
4
|
-
|
|
3
|
+
|
|
4
|
+
import { AxiosError } from 'axios'
|
|
5
5
|
import _get from 'lodash/get'
|
|
6
|
-
import
|
|
6
|
+
import _map from 'lodash/map'
|
|
7
|
+
import React, { useEffect, useRef, useState } from 'react'
|
|
8
|
+
|
|
7
9
|
import { getConfirmationData } from '../../api'
|
|
8
|
-
import {
|
|
10
|
+
import { IReferralPromotion } from '../../types'
|
|
9
11
|
import SocialButtons from './social-buttons'
|
|
10
12
|
|
|
11
13
|
export interface IShareButton {
|
|
@@ -15,6 +17,13 @@ export interface IShareButton {
|
|
|
15
17
|
shareData: any;
|
|
16
18
|
}
|
|
17
19
|
|
|
20
|
+
|
|
21
|
+
export interface IConfirmationLabels {
|
|
22
|
+
confirmationTitle?: string;
|
|
23
|
+
confirmationMain?: string;
|
|
24
|
+
confirmationHelper?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
18
27
|
export interface IConfirmationPage {
|
|
19
28
|
hasCopyIcon?: boolean;
|
|
20
29
|
isReferralEnabled: boolean;
|
|
@@ -25,9 +34,11 @@ export interface IConfirmationPage {
|
|
|
25
34
|
onGetConfirmationDataError: (e: AxiosError) => void;
|
|
26
35
|
onLinkCopied: () => void;
|
|
27
36
|
orderHash?: string;
|
|
37
|
+
confirmationLabels: IConfirmationLabels;
|
|
28
38
|
}
|
|
29
39
|
|
|
30
40
|
export const ConfirmationContainer = ({
|
|
41
|
+
confirmationLabels,
|
|
31
42
|
hasCopyIcon = true,
|
|
32
43
|
isReferralEnabled,
|
|
33
44
|
showDefaultShareButtons,
|
|
@@ -93,7 +104,11 @@ export const ConfirmationContainer = ({
|
|
|
93
104
|
const newData = { ...data, personal_share_link: e.target.value }
|
|
94
105
|
setData(newData)
|
|
95
106
|
}
|
|
96
|
-
|
|
107
|
+
const {
|
|
108
|
+
confirmationTitle = 'Your Tickets are Confirmed!',
|
|
109
|
+
confirmationMain = 'Your tickets are available in My Tickets section',
|
|
110
|
+
confirmationHelper = 'Please bring them with you to the event',
|
|
111
|
+
} = confirmationLabels
|
|
97
112
|
return (
|
|
98
113
|
<div className="confirmation-page">
|
|
99
114
|
{data && (
|
|
@@ -103,16 +118,17 @@ export const ConfirmationContainer = ({
|
|
|
103
118
|
<img className='product-image' src={data.product_image}/>
|
|
104
119
|
</div>
|
|
105
120
|
<div className="header-product-text">
|
|
106
|
-
<p className="title">
|
|
121
|
+
<p className="title">{ confirmationTitle }</p>
|
|
107
122
|
<div className="share-message-section">
|
|
108
123
|
{data.attach_tickets ? (
|
|
109
124
|
<span className="main">Your tickets have been emailed to you</span>
|
|
110
125
|
) : (
|
|
111
|
-
<span className="main">
|
|
126
|
+
<span className="main">{ confirmationMain }</span>
|
|
112
127
|
)}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
128
|
+
{
|
|
129
|
+
<span className="helper">
|
|
130
|
+
{data.attach_tickets ? 'Please bring them with you to the event' : confirmationHelper }
|
|
131
|
+
</span>}
|
|
116
132
|
</div>
|
|
117
133
|
</div>
|
|
118
134
|
</div>
|
|
@@ -166,7 +182,7 @@ export const ConfirmationContainer = ({
|
|
|
166
182
|
src="https://img.icons8.com/office/50/000000/copy.png"
|
|
167
183
|
alt="copy"
|
|
168
184
|
/>: <span className='copy-icon'>Copy</span>}
|
|
169
|
-
|
|
185
|
+
|
|
170
186
|
</div>
|
|
171
187
|
</div>
|
|
172
188
|
</div>
|
|
@@ -356,20 +356,12 @@ export const TicketsContainer = ({
|
|
|
356
356
|
const themeMui = createTheme(themeOptions)
|
|
357
357
|
|
|
358
358
|
useEffect(() => {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
return () => {
|
|
362
|
-
isWindowDefined &&
|
|
363
|
-
window.document.removeEventListener('custom-logout', handleLogout)
|
|
364
|
-
}
|
|
365
|
-
}, [])
|
|
359
|
+
window.document.addEventListener('custom-login', handleExternalLogin)
|
|
360
|
+
window.document.addEventListener('custom-logout', handleLogout)
|
|
366
361
|
|
|
367
|
-
useEffect(() => {
|
|
368
|
-
isWindowDefined &&
|
|
369
|
-
window.document.addEventListener('custom-login', handleExternalLogin)
|
|
370
362
|
return () => {
|
|
371
|
-
|
|
372
|
-
|
|
363
|
+
window.document.removeEventListener('custom-login', handleExternalLogin)
|
|
364
|
+
window.document.removeEventListener('custom-logout', handleLogout)
|
|
373
365
|
}
|
|
374
366
|
}, [])
|
|
375
367
|
|
|
@@ -400,20 +392,42 @@ export const TicketsContainer = ({
|
|
|
400
392
|
_isEmpty(selectedTickets) ||
|
|
401
393
|
Object.values(selectedTickets)[0] === 0
|
|
402
394
|
|
|
395
|
+
const isTicketAvailable = _some(
|
|
396
|
+
tickets,
|
|
397
|
+
ticket => ticket.displayTicket && !ticket.soldOut && ticket.salesStarted
|
|
398
|
+
)
|
|
399
|
+
|
|
403
400
|
const wrappedActionsSectionComponent = React.isValidElement(
|
|
404
401
|
ActionsSectionComponent
|
|
405
402
|
)
|
|
406
403
|
? React.cloneElement(ActionsSectionComponent as React.ReactElement<any>, {
|
|
407
404
|
handleGetTicketClick,
|
|
408
405
|
isTicketOnSale,
|
|
406
|
+
isTicketAvailable,
|
|
409
407
|
})
|
|
410
408
|
: null
|
|
411
409
|
|
|
412
410
|
const externalUrl = event?.redirectUrl
|
|
413
|
-
const eventSaleIsNotStarted =
|
|
411
|
+
const eventSaleIsNotStarted =
|
|
412
|
+
!event?.salesStarted && event?.salesStart && !isTicketAvailable
|
|
414
413
|
const influencers = event?.referralsEnabled ? event?.referrals : []
|
|
415
414
|
const previewKey = getQueryVariable('pk') || undefined
|
|
416
415
|
|
|
416
|
+
const canShowGetTicketBtn = () => {
|
|
417
|
+
if (
|
|
418
|
+
!wrappedActionsSectionComponent &&
|
|
419
|
+
!eventSaleIsNotStarted &&
|
|
420
|
+
isTicketOnSale &&
|
|
421
|
+
!event?.salesEnded &&
|
|
422
|
+
!externalUrl &&
|
|
423
|
+
!previewKey
|
|
424
|
+
) {
|
|
425
|
+
return true
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return false
|
|
429
|
+
}
|
|
430
|
+
|
|
417
431
|
return (
|
|
418
432
|
<ThemeProvider theme={themeMui}>
|
|
419
433
|
{!isLoading && <ReferralLogic eventId={eventId} />}
|
|
@@ -485,24 +499,19 @@ export const TicketsContainer = ({
|
|
|
485
499
|
/>
|
|
486
500
|
) : null}
|
|
487
501
|
{wrappedActionsSectionComponent}
|
|
488
|
-
{
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
!externalUrl &&
|
|
493
|
-
!previewKey && (
|
|
494
|
-
<Button
|
|
495
|
-
aria-hidden={true}
|
|
496
|
-
className={`book-button
|
|
502
|
+
{canShowGetTicketBtn() && (
|
|
503
|
+
<Button
|
|
504
|
+
aria-hidden={true}
|
|
505
|
+
className={`book-button
|
|
497
506
|
${bookButtonIsDisabled ? 'disabled' : ''}
|
|
498
507
|
${isButtonScrollable ? 'is-scrollable' : ''}
|
|
499
508
|
${!isLoggedIn ? 'on-bottom' : ''}
|
|
500
509
|
`}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
510
|
+
onClick={handleGetTicketClick}
|
|
511
|
+
>
|
|
512
|
+
{getTicketsLabel || 'GET TICKETS'}
|
|
513
|
+
</Button>
|
|
514
|
+
)}
|
|
506
515
|
{isLogged && !hideSessionButtons ? (
|
|
507
516
|
<div className="session-wrapper">
|
|
508
517
|
<span className="session-container">
|