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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3.2",
2
+ "version": "1.3.3",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -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
- props.errors[
859
- `${element.name}-${index}`
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={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
- setFieldError(field.name, '')
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
- import _map from 'lodash/map'
3
+
4
+ import { AxiosError } from 'axios'
5
5
  import _get from 'lodash/get'
6
- import { IReferralPromotion } from '../../types'
6
+ import _map from 'lodash/map'
7
+ import React, { useEffect, useRef, useState } from 'react'
8
+
7
9
  import { getConfirmationData } from '../../api'
8
- import { AxiosError } from 'axios'
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">Your Tickets are Confirmed!</p>
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">Your tickets are available in My Tickets section</span>
126
+ <span className="main">{ confirmationMain }</span>
112
127
  )}
113
- <span className="helper">
114
- Please bring them with you to the event
115
- </span>
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
- isWindowDefined &&
360
- window.document.addEventListener('custom-logout', handleLogout)
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
- isWindowDefined &&
372
- window.document.removeEventListener('custom-login', handleExternalLogin)
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 = !event?.salesStarted && event?.salesStart
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
- {!wrappedActionsSectionComponent &&
489
- !eventSaleIsNotStarted &&
490
- isTicketOnSale &&
491
- !event?.salesEnded &&
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
- onClick={handleGetTicketClick}
502
- >
503
- {getTicketsLabel || 'GET TICKETS'}
504
- </Button>
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">