tf-checkout-react 1.0.106 → 1.2.1

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 (77) hide show
  1. package/README.md +278 -1
  2. package/dist/api/index.d.ts +40 -28
  3. package/dist/components/account-settings/index.d.ts +3 -0
  4. package/dist/components/billing-info-container/index.d.ts +11 -8
  5. package/dist/components/common/PhoneNumberField.d.ts +9 -0
  6. package/dist/components/common/index.d.ts +1 -0
  7. package/dist/components/confirmationContainer/index.d.ts +2 -1
  8. package/dist/components/countdown/index.d.ts +2 -1
  9. package/dist/components/forgotPasswordModal/index.d.ts +11 -0
  10. package/dist/components/index.d.ts +1 -0
  11. package/dist/components/loginModal/index.d.ts +35 -2
  12. package/dist/components/myTicketsContainer/index.d.ts +2 -1
  13. package/dist/components/myTicketsContainer/tableConfig.d.ts +1 -1
  14. package/dist/components/orderDetailsContainer/index.d.ts +6 -1
  15. package/dist/components/orderDetailsContainer/ticketsTable.d.ts +2 -1
  16. package/dist/components/paymentContainer/index.d.ts +2 -1
  17. package/dist/components/resetPasswordContainer/index.d.ts +10 -0
  18. package/dist/components/signupModal/index.d.ts +14 -0
  19. package/dist/components/ticketsContainer/PromoCodeSection.d.ts +3 -2
  20. package/dist/components/ticketsContainer/TicketsSection.d.ts +1 -2
  21. package/dist/components/ticketsContainer/index.d.ts +7 -3
  22. package/dist/index.d.ts +2 -0
  23. package/dist/tf-checkout-react.cjs.development.js +2177 -1482
  24. package/dist/tf-checkout-react.cjs.development.js.map +1 -1
  25. package/dist/tf-checkout-react.cjs.production.min.js +1 -1
  26. package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
  27. package/dist/tf-checkout-react.esm.js +2166 -1473
  28. package/dist/tf-checkout-react.esm.js.map +1 -1
  29. package/dist/tf-checkout-styles.css +1 -1
  30. package/dist/utils/cookies.d.ts +3 -0
  31. package/dist/utils/createCheckoutDataBodyWithDefaultHolder.d.ts +6 -1
  32. package/dist/utils/downloadPDF.d.ts +1 -1
  33. package/dist/utils/getDomain.d.ts +1 -0
  34. package/dist/utils/index.d.ts +2 -0
  35. package/package.json +12 -1
  36. package/src/api/index.ts +100 -29
  37. package/src/components/account-settings/index.tsx +161 -0
  38. package/src/components/account-settings/style.css +200 -0
  39. package/src/components/billing-info-container/index.tsx +145 -99
  40. package/src/components/billing-info-container/style.css +1 -1
  41. package/src/components/billing-info-container/utils.ts +11 -3
  42. package/src/components/common/PhoneNumberField.tsx +68 -0
  43. package/src/components/common/SnackbarAlert.tsx +1 -1
  44. package/src/components/common/dist/PhoneNumberField.js +96 -0
  45. package/src/components/common/index.tsx +1 -0
  46. package/src/components/confirmationContainer/index.tsx +19 -9
  47. package/src/components/countdown/index.tsx +3 -1
  48. package/src/components/forgotPasswordModal/index.tsx +107 -0
  49. package/src/components/forgotPasswordModal/style.css +47 -0
  50. package/src/components/index.ts +1 -0
  51. package/src/components/loginModal/index.tsx +72 -71
  52. package/src/components/myTicketsContainer/index.tsx +99 -95
  53. package/src/components/myTicketsContainer/style.css +2 -2
  54. package/src/components/myTicketsContainer/tableConfig.tsx +3 -6
  55. package/src/components/orderDetailsContainer/index.tsx +80 -21
  56. package/src/components/orderDetailsContainer/style.css +7 -3
  57. package/src/components/orderDetailsContainer/ticketsTable.tsx +130 -83
  58. package/src/components/paymentContainer/index.tsx +114 -49
  59. package/src/components/registerModal/index.tsx +3 -10
  60. package/src/components/resetPasswordContainer/index.tsx +96 -0
  61. package/src/components/resetPasswordContainer/style.css +36 -0
  62. package/src/components/signupModal/index.tsx +195 -0
  63. package/src/components/signupModal/style.css +58 -0
  64. package/src/components/stripePayment/index.tsx +14 -12
  65. package/src/components/stripePayment/style.css +3 -3
  66. package/src/components/ticketResaleModal/index.tsx +12 -14
  67. package/src/components/ticketsContainer/PromoCodeSection.tsx +8 -7
  68. package/src/components/ticketsContainer/TicketRow.tsx +12 -6
  69. package/src/components/ticketsContainer/TicketsSection.tsx +0 -3
  70. package/src/components/ticketsContainer/index.tsx +155 -86
  71. package/src/env.ts +3 -3
  72. package/src/index.ts +3 -1
  73. package/src/utils/cookies.ts +42 -0
  74. package/src/utils/createCheckoutDataBodyWithDefaultHolder.ts +16 -4
  75. package/src/utils/downloadPDF.tsx +28 -6
  76. package/src/utils/getDomain.ts +15 -0
  77. package/src/utils/index.ts +2 -0
@@ -1,5 +1,11 @@
1
- import React, { FC, useEffect, useState, useRef } from 'react'
2
- import { AxiosError } from 'axios'
1
+ import './style.css'
2
+
3
+ import { CircularProgress, ThemeOptions } from '@mui/material'
4
+ import Backdrop from '@mui/material/Backdrop'
5
+ import Button from '@mui/material/Button'
6
+ import { createTheme,ThemeProvider } from '@mui/material/styles'
7
+ import { CSSProperties } from '@mui/styles'
8
+ import axios, { AxiosError } from 'axios'
3
9
  import {
4
10
  Field,
5
11
  Form,
@@ -8,29 +14,36 @@ import {
8
14
  FormikProps,
9
15
  FormikValues,
10
16
  } from 'formik'
11
- import Button from '@mui/material/Button'
12
- import _identity from 'lodash/identity'
13
- import _map from 'lodash/map'
14
17
  import _get from 'lodash/get'
18
+ import _identity from 'lodash/identity'
15
19
  import _includes from 'lodash/includes'
16
- import _isEqual from 'lodash/isEqual'
17
20
  import _isEmpty from 'lodash/isEmpty'
21
+ import _isEqual from 'lodash/isEqual'
22
+ import _map from 'lodash/map'
23
+ import { nanoid } from 'nanoid'
24
+ import React, { FC, useEffect, useRef,useState } from 'react'
18
25
 
19
- import './style.css'
20
- import { combineValidators, requiredValidator } from '../../validators'
21
- import { IBillingInfoData } from '../../types'
22
26
  import {
23
27
  getCart,
24
28
  getCountries,
25
29
  getProfileData,
26
- handleSetAccessToken,
30
+ getStates,
27
31
  postOnCheckout,
28
32
  register,
29
33
  setCustomHeader,
30
- getStates,
31
34
  } from '../../api'
35
+ import { IBillingInfoData } from '../../types'
36
+ import { createCheckoutDataBodyWithDefaultHolder, getCookieByName } from '../../utils'
37
+ import { ErrorFocus } from '../../utils/formikErrorFocus'
38
+ import { getQueryVariable } from '../../utils/getQueryVariable'
39
+ import { combineValidators, requiredValidator } from '../../validators'
40
+ import { DatePickerField } from '../common/DatePickerField'
41
+ import { CheckboxField, CustomField, PhoneNumberField,SelectField } from '../common/index'
42
+ import SnackbarAlert from '../common/SnackbarAlert'
43
+ import { ForgotPasswordModal } from '../forgotPasswordModal'
32
44
  import { LoginModal } from '../loginModal'
33
- import { RegisterModal } from '../registerModal'
45
+ import { SignupModal } from '../signupModal'
46
+ import TimerWidget from '../timerWidget'
34
47
  import {
35
48
  assingUniqueIds,
36
49
  createCheckoutDataBody,
@@ -39,19 +52,6 @@ import {
39
52
  getValidateFunctions,
40
53
  setLoggedUserData,
41
54
  } from './utils'
42
- import { createCheckoutDataBodyWithDefaultHolder } from '../../utils'
43
- import axios from 'axios'
44
- import { CustomField, CheckboxField, SelectField, FormikPhoneNumberField } from '../common/index'
45
- import { CircularProgress, ThemeOptions } from '@mui/material'
46
- import { nanoid } from 'nanoid'
47
- import { getQueryVariable } from '../../utils/getQueryVariable'
48
- import { ErrorFocus } from '../../utils/formikErrorFocus'
49
- import { ThemeProvider, createTheme } from '@mui/material/styles'
50
- import { CSSProperties } from '@mui/styles'
51
- import Backdrop from '@mui/material/Backdrop'
52
- import TimerWidget from '../timerWidget'
53
- import SnackbarAlert from '../common/SnackbarAlert'
54
- import { DatePickerField } from '../common/DatePickerField'
55
55
 
56
56
  export interface IBillingInfoPage {
57
57
  data?: IBillingInfoData[];
@@ -62,10 +62,7 @@ export interface IBillingInfoPage {
62
62
  eventId: any,
63
63
  res: any
64
64
  ) => void;
65
- onRegisterSuccess?: (value: {
66
- accessToken: string;
67
- refreshToken: string;
68
- }) => void;
65
+ onRegisterSuccess?: (value: any) => void;
69
66
  onRegisterError?: (e: AxiosError, email: string) => void;
70
67
  onSubmitError?: (e: AxiosError) => void;
71
68
  onGetCartSuccess?: (res: any) => void;
@@ -95,8 +92,14 @@ export interface IBillingInfoPage {
95
92
  onSkipBillingPage: (data: any) => void;
96
93
  skipPage?: boolean;
97
94
  canSkipHolderNames?: boolean;
95
+ shouldFetchCountries?: boolean;
96
+ onForgotPasswordSuccess?: (res: any) => void;
97
+ onForgotPasswordError?: (e: AxiosError) => void;
98
98
  onCountdownFinish?: () => void;
99
99
  enableTimer?: boolean;
100
+ logo?: string;
101
+ showForgotPasswordButton?: boolean;
102
+ showSignUpButton?: boolean;
100
103
  }
101
104
 
102
105
  const LogicRunner: FC<{
@@ -107,6 +110,7 @@ const LogicRunner: FC<{
107
110
  setUserValues: any;
108
111
  onGetStatesSuccess: any;
109
112
  onGetStatesError: any;
113
+ shouldFetchCountries: boolean;
110
114
  }> = ({
111
115
  values,
112
116
  setStates,
@@ -115,6 +119,7 @@ const LogicRunner: FC<{
115
119
  setUserValues,
116
120
  onGetStatesSuccess,
117
121
  onGetStatesError,
122
+ shouldFetchCountries,
118
123
  }) => {
119
124
  const prevCountry = useRef(values.country)
120
125
  useEffect(() => {
@@ -137,7 +142,7 @@ const LogicRunner: FC<{
137
142
  }
138
143
  }
139
144
  }
140
- fetchStates()
145
+ shouldFetchCountries && fetchStates()
141
146
  }, [values.country, setStates, setFieldValue])
142
147
  const userDataEncoded =
143
148
  typeof window !== 'undefined'
@@ -151,8 +156,8 @@ const LogicRunner: FC<{
151
156
  try {
152
157
  const parsedData = JSON.parse(userDataEncoded)
153
158
  const mappedValues = {
154
- firstName: parsedData?.first_name || '',
155
- lastName: parsedData?.last_name || '',
159
+ firstName: parsedData?.first_name || parsedData?.firstName || '',
160
+ lastName: parsedData?.last_name || parsedData?.lastName || '',
156
161
  email: parsedData?.email || '',
157
162
  phone: parsedData?.phone || '',
158
163
  confirmEmail: parsedData?.email || '',
@@ -160,15 +165,15 @@ const LogicRunner: FC<{
160
165
  street_address: parsedData?.street_address || '',
161
166
  country: parsedData?.country || '1',
162
167
  zip: parsedData?.zip || '',
163
- brand_opt_in: parsedData?.brand_opt_in || '',
168
+ brand_opt_in: parsedData?.brand_opt_in || false,
164
169
  city: parsedData?.city || '',
165
170
  confirmPassword: '',
166
171
  password: '',
167
- 'holderFirstName-0': parsedData?.first_name || '',
168
- 'holderLastName-0': parsedData?.last_name || '',
172
+ 'holderFirstName-0': parsedData?.first_name || parsedData?.firstName || '',
173
+ 'holderLastName-0': parsedData?.last_name || parsedData?.lastName || '',
169
174
  'holderEmail-0': parsedData?.email || '',
170
175
  }
171
- setValues(mappedValues)
176
+ setValues({ ...values, ...mappedValues })
172
177
  setUserValues(mappedValues)
173
178
  } catch (e) {}
174
179
  }
@@ -178,6 +183,7 @@ const LogicRunner: FC<{
178
183
  }, [userDataEncoded, setValues, setUserValues])
179
184
  return null
180
185
  }
186
+
181
187
  export const BillingInfoContainer = ({
182
188
  data = [],
183
189
  ticketHoldersFields = {
@@ -212,8 +218,14 @@ export const BillingInfoContainer = ({
212
218
  onSkipBillingPage = () => {},
213
219
  skipPage = false,
214
220
  canSkipHolderNames = false,
221
+ onForgotPasswordSuccess = () => {},
222
+ onForgotPasswordError = () => {},
223
+ shouldFetchCountries = true,
215
224
  onCountdownFinish = () => {},
216
- enableTimer = false
225
+ enableTimer = false,
226
+ logo,
227
+ showForgotPasswordButton = false,
228
+ showSignUpButton = false
217
229
  }: IBillingInfoPage) => {
218
230
  const themeMui = createTheme(themeOptions)
219
231
  const isWindowDefined = typeof window !== 'undefined'
@@ -226,16 +238,18 @@ export const BillingInfoContainer = ({
226
238
  ? window.localStorage.getItem('access_token') || ''
227
239
  : ''
228
240
  const [dataWithUniqueIds, setDataWithUniqueIds] = useState<
229
- IBillingInfoData[]
241
+ IBillingInfoData[]
230
242
  >(data)
231
- const [isLoggedIn, setIsLoggedIn] = useState(!!access_token)
243
+ const xtfCookie = getCookieByName('X-TF-ECOMMERCE')
244
+ const [isLoggedIn, setIsLoggedIn] = useState(!!(pIsLoggedIn || xtfCookie))
232
245
  const [cartInfoData, setCartInfo] = useState<any>({})
233
246
  const [countries, setCountries] = useState<any>([])
234
247
  const [states, setStates] = useState<any>([])
235
248
  const [showModalLogin, setShowModalLogin] = useState(false)
236
249
  const [alreadyHasUser, setAlreadyHasUser] = useState(false)
237
250
  const [userExpired, setUserExpired] = useState(false)
238
- const [showModalRegister, setShowModalRegister] = useState(false)
251
+ const [showModalSignup, setShowModalSignup] = useState(false)
252
+ const [showModalForgotPassword, setShowModalForgotPassword] = useState(false)
239
253
  const [ticketsQuantity, setTicketsQuantity] = useState<string[]>([])
240
254
  const [userValues, setUserValues] = useState<any>({
241
255
  firstName: '',
@@ -264,7 +278,7 @@ export const BillingInfoContainer = ({
264
278
  const showTicketHolders = getQueryVariable('names_required') === 'true'
265
279
  const eventId = getQueryVariable('event_id')
266
280
  const optedInFieldValue: boolean = _get(cartInfoData, 'optedIn', false)
267
- const ttfOptIn: boolean = Boolean(_get(cartInfoData, 'ttfOptIn', false))
281
+ const ttfOptIn = Boolean(_get(cartInfoData, 'ttfOptIn', false))
268
282
  const hideTtfOptIn: boolean = _get(cartInfoData, 'hide_ttf_opt_in', true)
269
283
  const expirationTime = _get(cartInfoData, 'expiresAt')
270
284
  const flagRequirePhone = getQueryVariable('phone_required') === 'true'
@@ -292,10 +306,10 @@ export const BillingInfoContainer = ({
292
306
  }
293
307
 
294
308
  useEffect(() => {
295
- if ((pIsLoggedIn || access_token) && !isLoggedIn) {
296
- setIsLoggedIn(true)
309
+ if ((pIsLoggedIn !== isLoggedIn) || xtfCookie) {
310
+ setIsLoggedIn(!!(pIsLoggedIn || xtfCookie))
297
311
  }
298
- }, [pIsLoggedIn, isLoggedIn, access_token])
312
+ }, [pIsLoggedIn, isLoggedIn, xtfCookie])
299
313
  //just once
300
314
  useEffect(() => {
301
315
  // fetch countries data
@@ -316,7 +330,7 @@ export const BillingInfoContainer = ({
316
330
  }
317
331
  }
318
332
  }
319
- fetchCountries()
333
+ shouldFetchCountries && fetchCountries()
320
334
  fetchCart()
321
335
  }, [])
322
336
  // fetch cart data
@@ -340,7 +354,7 @@ export const BillingInfoContainer = ({
340
354
  // fetch user data
341
355
  const fetchUserData = async (token: string) => {
342
356
  try {
343
- if (isWindowDefined && token) {
357
+ if ((isWindowDefined && token) || isLoggedIn) {
344
358
  const userDataResponse = await getProfileData(token)
345
359
  const profileSpecifiedData = _get(userDataResponse, 'data.data')
346
360
  const profileDataObj = setLoggedUserData(profileSpecifiedData)
@@ -363,7 +377,7 @@ export const BillingInfoContainer = ({
363
377
  }
364
378
  useEffect(() => {
365
379
  fetchUserData(access_token)
366
- }, [access_token])
380
+ }, [access_token, isLoggedIn])
367
381
 
368
382
  useEffect(() => {
369
383
  const collectPaymentData = async () => {
@@ -390,7 +404,7 @@ export const BillingInfoContainer = ({
390
404
  }, [skipPage, ticketsQuantity])
391
405
 
392
406
 
393
- const collectCheckoutBody = (values: object): object => {
407
+ const collectCheckoutBody = (values: Record<string, unknown>, profileData?: any): Record<string, unknown> => {
394
408
  let checkoutBody = {}
395
409
 
396
410
  // Auto collect ticket holders name when it was skipped optionally
@@ -398,13 +412,18 @@ export const BillingInfoContainer = ({
398
412
  checkoutBody = createCheckoutDataBodyWithDefaultHolder(
399
413
  ticketsQuantity.length,
400
414
  values,
401
- true
415
+ true,
416
+ { emailLogged, firstNameLogged, lastNameLogged },
402
417
  )
403
418
  } else {
404
419
  checkoutBody = createCheckoutDataBody(
405
420
  ticketsQuantity.length,
406
421
  values,
407
- { emailLogged, firstNameLogged, lastNameLogged },
422
+ {
423
+ emailLogged: emailLogged || profileData.email,
424
+ firstNameLogged: firstNameLogged || profileData.first_name || profileData.firstName,
425
+ lastNameLogged: lastNameLogged || profileData.last_name || profileData.lastName,
426
+ },
408
427
  showDOB
409
428
  )
410
429
  }
@@ -416,22 +435,23 @@ export const BillingInfoContainer = ({
416
435
  localStorage.removeItem('referral_key')
417
436
  }
418
437
 
419
- // Displaying loader
420
438
  if (loading || (enableTimer && !expirationTime && typeof window !== 'undefined')) {
421
439
  if (expirationTime === 0) {
422
440
  // Redirect to homepage (countdown finished and browser reloaded case)
423
- window.location.href='/'
441
+ window.location.href = '/'
424
442
  }
425
-
426
- return (
427
- <Backdrop sx={{ color: '#fff' }} open={true}>
428
- <CircularProgress color="inherit" />
429
- </Backdrop>
430
- )
431
443
  }
432
444
 
433
445
  return (
434
446
  <ThemeProvider theme={themeMui}>
447
+ {loading && (
448
+ <Backdrop
449
+ sx={{ color: '#fff', backgroundColor: '#000000bd', zIndex: 1205 }}
450
+ open={true}
451
+ >
452
+ <CircularProgress color="inherit" />
453
+ </Backdrop>
454
+ )}
435
455
  {!!expirationTime && enableTimer && (
436
456
  <TimerWidget
437
457
  expires_at={expirationTime}
@@ -450,7 +470,7 @@ export const BillingInfoContainer = ({
450
470
  },
451
471
  userValues
452
472
  )}
453
- enableReinitialize={true}
473
+ enableReinitialize={false}
454
474
  onSubmit={async (values, formikHelpers) => {
455
475
  try {
456
476
  if (isLoggedIn) {
@@ -466,7 +486,7 @@ export const BillingInfoContainer = ({
466
486
  }
467
487
  }
468
488
 
469
- const checkoutBody = collectCheckoutBody(values)
489
+ const checkoutBody = collectCheckoutBody(values, userData)
470
490
  const res = await postOnCheckout(checkoutBody, access_token)
471
491
  removeReferralKey()
472
492
  handleSubmit(
@@ -487,24 +507,22 @@ export const BillingInfoContainer = ({
487
507
  values,
488
508
  checkoutBodyForRegistration
489
509
  )
490
- let access_token_register = null
491
510
  try {
511
+ setLoading(true)
492
512
  const resRegister = await register(bodyFormData)
493
- access_token_register = _get(
494
- resRegister,
495
- 'data.data.attributes.access_token'
496
- )
497
- const refreshToken = _get(
498
- resRegister,
499
- 'data.data.attributes.refresh_token'
500
- )
501
- handleSetAccessToken(access_token_register)
502
- const tokens = {
503
- accessToken: access_token_register,
513
+ const xtfCookie = _get(resRegister, 'headers.x-tf-ecommerce')
514
+ const accessToken = _get(resRegister, 'data.data.attributes.access_token')
515
+ const refreshToken = _get(resRegister, 'data.data.attributes.refresh_token')
516
+ const userProfile = _get(resRegister, 'data.data.attributes.user_profile')
517
+
518
+ onRegisterSuccess({
519
+ xtfCookie,
520
+ accessToken,
504
521
  refreshToken,
505
- }
506
- onRegisterSuccess(tokens)
522
+ userProfile
523
+ })
507
524
  } catch (e) {
525
+ setLoading(false)
508
526
  if (axios.isAxiosError(e)) {
509
527
  const error = e?.response?.data?.message
510
528
  if (_includes(error, 'You must be aged')) {
@@ -531,7 +549,7 @@ export const BillingInfoContainer = ({
531
549
  }
532
550
  return
533
551
  }
534
- const profileData = await getProfileData(access_token_register)
552
+ const profileData = await getProfileData()
535
553
  const profileSpecifiedData = _get(profileData, 'data.data')
536
554
  const profileDataObj = setLoggedUserData(profileSpecifiedData)
537
555
  if (isWindowDefined) {
@@ -541,11 +559,8 @@ export const BillingInfoContainer = ({
541
559
  )
542
560
  }
543
561
 
544
- const checkoutBody = collectCheckoutBody(values)
545
- const res = await postOnCheckout(
546
- checkoutBody,
547
- access_token_register
548
- )
562
+ const checkoutBody = collectCheckoutBody(values, profileDataObj)
563
+ const res = await postOnCheckout(checkoutBody)
549
564
  removeReferralKey()
550
565
  handleSubmit(
551
566
  values,
@@ -554,6 +569,7 @@ export const BillingInfoContainer = ({
554
569
  res
555
570
  )
556
571
  } catch (e) {
572
+ setLoading(false)
557
573
  if (axios.isAxiosError(e)) {
558
574
  if (e.response?.data.error === 'invalid_token') {
559
575
  if (isWindowDefined) {
@@ -568,6 +584,8 @@ export const BillingInfoContainer = ({
568
584
  }
569
585
  onSubmitError(e)
570
586
  }
587
+ } finally {
588
+ setLoading(false)
571
589
  }
572
590
  }}
573
591
  >
@@ -582,6 +600,7 @@ export const BillingInfoContainer = ({
582
600
  setUserValues={setUserValues}
583
601
  onGetStatesSuccess={onGetStatesSuccess}
584
602
  onGetStatesError={onGetStatesError}
603
+ shouldFetchCountries={shouldFetchCountries}
585
604
  />
586
605
  <div className={`billing-info-container ${theme}`}>
587
606
  <SnackbarAlert
@@ -595,9 +614,11 @@ export const BillingInfoContainer = ({
595
614
  />
596
615
  {!isLoggedIn && (
597
616
  <div className="account-actions-block">
598
- <div>{accountInfoTitle}</div>
599
- <div>Login & skip ahead:</div>
600
- <div className="login-block">
617
+ <div className="action-item">
618
+ <div>{accountInfoTitle}</div>
619
+ <div>Login & skip ahead:</div>
620
+ </div>
621
+ <div className="action-item login-block">
601
622
  <button
602
623
  className="login-register-button"
603
624
  type="button"
@@ -636,6 +657,7 @@ export const BillingInfoContainer = ({
636
657
  const { groupClassname, groupItems } = group
637
658
  return (
638
659
  <React.Fragment key={group.uniqueId}>
660
+
639
661
  <div className={groupClassname}>
640
662
  {_map(
641
663
  groupItems.filter(el => {
@@ -656,7 +678,7 @@ export const BillingInfoContainer = ({
656
678
  'confirmPassword',
657
679
  'password-info',
658
680
  ].includes(element.name) &&
659
- isLoggedIn ? null : (
681
+ isLoggedIn ? null : (
660
682
  <React.Fragment key={element.uniqueId}>
661
683
  <div className={element.className}>
662
684
  {element.component ? (
@@ -664,8 +686,8 @@ export const BillingInfoContainer = ({
664
686
  ) : (
665
687
  <Field
666
688
  name={element.name}
667
- label={element.name === 'phone'
668
- ? `${element.label}${flagRequirePhone ? '' : ' (optional)'} `
689
+ label={element.name === 'phone'
690
+ ? `${element.label}${flagRequirePhone ? '' : ' (optional)'} `
669
691
  : element.label}
670
692
  type={element.type}
671
693
  validate={getValidateFunctions(
@@ -681,7 +703,7 @@ export const BillingInfoContainer = ({
681
703
  : element.type === 'select'
682
704
  ? SelectField
683
705
  : element.type === 'phone'
684
- ? FormikPhoneNumberField
706
+ ? PhoneNumberField
685
707
  : element.type === 'date'
686
708
  ? DatePickerField
687
709
  : CustomField
@@ -690,8 +712,8 @@ export const BillingInfoContainer = ({
690
712
  element.name === 'country'
691
713
  ? countries
692
714
  : element.name === 'state'
693
- ? states
694
- : []
715
+ ? states
716
+ : []
695
717
  }
696
718
  theme={theme}
697
719
  />
@@ -709,7 +731,7 @@ export const BillingInfoContainer = ({
709
731
  })}
710
732
  {!_isEmpty(ticketHoldersFields.fields) && (
711
733
  <div className="ticket-holders-fields">
712
- <p>{ticketHoldersFields.label}</p>
734
+ <h2>{ticketHoldersFields.label}</h2>
713
735
  {_map(ticketsQuantity, (_item, index) => (
714
736
  <div key={_item}>
715
737
  <h5>Ticket {index + 1}</h5>
@@ -731,6 +753,8 @@ export const BillingInfoContainer = ({
731
753
  component={
732
754
  element.type === 'checkbox'
733
755
  ? CheckboxField
756
+ : element.type === 'phone'
757
+ ? PhoneNumberField
734
758
  : CustomField
735
759
  }
736
760
  validate={combineValidators(
@@ -772,6 +796,7 @@ export const BillingInfoContainer = ({
772
796
  </Formik>
773
797
  {showModalLogin && (
774
798
  <LoginModal
799
+ logo={logo}
775
800
  onClose={() => {
776
801
  setShowModalLogin(false)
777
802
  }}
@@ -789,21 +814,42 @@ export const BillingInfoContainer = ({
789
814
  onGetProfileDataSuccess(data)
790
815
  }}
791
816
  onGetProfileDataError={onGetProfileDataError}
817
+ showSignUpButton={showSignUpButton}
818
+ showForgotPasswordButton={showForgotPasswordButton}
819
+ onForgotPassword={() => {
820
+ setShowModalLogin(false)
821
+ setShowModalForgotPassword(true)
822
+ }}
823
+ onSignup={() => {
824
+ setShowModalLogin(false)
825
+ setShowModalSignup(true)
826
+ }}
792
827
  />
793
828
  )}
794
- {showModalRegister && (
795
- <RegisterModal
829
+ {showModalSignup && (
830
+ <SignupModal
796
831
  onClose={() => {
797
- setShowModalRegister(false)
832
+ setShowModalSignup(false)
798
833
  }}
799
- onRegister={() => {
800
- setShowModalRegister(false)
834
+ onLogin={() => {
835
+ setShowModalSignup(false)
836
+ setShowModalLogin(true)
801
837
  }}
802
- onGetProfileDataSuccess={(data: any) => {
803
- fetchCart()
804
- onGetProfileDataSuccess(data)
838
+ onRegisterSuccess={onRegisterSuccess}
839
+ onRegisterError={onRegisterError}
840
+ />
841
+ )}
842
+ {showModalForgotPassword && (
843
+ <ForgotPasswordModal
844
+ onClose={() => {
845
+ setShowModalForgotPassword(false)
805
846
  }}
806
- onGetProfileDataError={onGetProfileDataError}
847
+ onLogin={() => {
848
+ setShowModalForgotPassword(false)
849
+ setShowModalLogin(true)
850
+ }}
851
+ onForgotPasswordSuccess={onForgotPasswordSuccess}
852
+ onForgotPasswordError={onForgotPasswordError}
807
853
  />
808
854
  )}
809
855
  </ThemeProvider>
@@ -103,4 +103,4 @@ button {
103
103
 
104
104
  .email-checking {
105
105
  margin-bottom: 15px;
106
- }
106
+ }
@@ -144,10 +144,10 @@ export const createCheckoutDataBody = (
144
144
  holder => Object.entries(holder).length > 0
145
145
  )
146
146
  ticket_holders = filteredHolders.map((item, index) => ({
147
- first_name: item[`holderFirstName-${index}`] || '',
148
- last_name: item[`holderLastName-${index}`] || '',
147
+ first_name: !index ? item[`holderFirstName-${index}`] || logedInValues.firstNameLogged || '' : item[`holderFirstName-${index}`] || '',
148
+ last_name: !index ? item[`holderLastName-${index}`] || logedInValues.lastNameLogged || '' : item[`holderLastName-${index}`] || '',
149
149
  phone: item[`holderPhone-${index}`] || '',
150
- email: item[`holderEmail-${index}`] || '',
150
+ email: !index ? item[`holderEmail-${index}`] || logedInValues.emailLogged || '' : item[`holderEmail-${index}`] || '',
151
151
  }))
152
152
 
153
153
  const filteredRestValue: { [key: string]: any } = {}
@@ -205,6 +205,14 @@ export const getValidateFunctions = (
205
205
  validationFunctions.push(isSameEmail)
206
206
  }
207
207
 
208
+ if (element.name === 'confirmPassword') {
209
+ const isSame = (confirmPassword?: string) =>
210
+ values.password !== confirmPassword
211
+ ? 'Password confirmation does not match'
212
+ : null
213
+ validationFunctions.push(isSame)
214
+ }
215
+
208
216
  return combineValidators(...validationFunctions)
209
217
  }
210
218
 
@@ -0,0 +1,68 @@
1
+ import TextField from '@mui/material/TextField'
2
+ import { FieldInputProps, FormikProps } from 'formik'
3
+ import _debounce from 'lodash/debounce'
4
+ import _get from 'lodash/get'
5
+ import React, { useCallback, useEffect } from 'react'
6
+
7
+ import { validatePhoneNumber } from '../../api'
8
+
9
+ export interface IPhoneNumberField {
10
+ label: string;
11
+ field: FieldInputProps<any>;
12
+ form: FormikProps<any>;
13
+
14
+ // optional
15
+ type: string;
16
+ }
17
+
18
+ export const PhoneNumberField = ({
19
+ label,
20
+ type = 'text',
21
+ field,
22
+ form: { errors, setFieldError, setStatus },
23
+ }: IPhoneNumberField) => {
24
+ const error = _get(errors, field.name)
25
+
26
+ // eslint-disable-next-line react-hooks/exhaustive-deps
27
+ const debounceCb = useCallback(
28
+ _debounce((cb: () => void) => void cb(), 1000),
29
+ []
30
+ )
31
+
32
+ useEffect(() => {
33
+ if (field.value) {
34
+ setStatus({ [field.name]: true })
35
+ }
36
+ debounceCb(async () => {
37
+ try {
38
+ if (field.value) {
39
+ await validatePhoneNumber(field.value)
40
+ }
41
+ setFieldError(field.name, '')
42
+ } catch (error) {
43
+ const message = _get(
44
+ error,
45
+ 'response.data.message',
46
+ 'Invalid phone number'
47
+ )
48
+ setFieldError(field.name, message)
49
+ } finally {
50
+ setStatus({ [field.name]: false })
51
+ }
52
+ })
53
+ // eslint-disable-next-line
54
+ }, [field.value])
55
+
56
+ return (
57
+ <TextField
58
+ {...field}
59
+ id={field.name}
60
+ label={label}
61
+ type={type}
62
+ fullWidth={true}
63
+ error={!!error}
64
+ helperText={error}
65
+ value={field.value || ''}
66
+ />
67
+ )
68
+ }
@@ -51,4 +51,4 @@ const SnackbarAlert = ({
51
51
  )
52
52
  }
53
53
 
54
- export default SnackbarAlert
54
+ export default SnackbarAlert