tf-checkout-react 1.6.6-beta.3 → 1.6.6-beta.31

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 (110) hide show
  1. package/README.md +61 -40
  2. package/dist/adapters/customFields.d.ts +1 -0
  3. package/dist/api/checkout.d.ts +1 -0
  4. package/dist/api/common.d.ts +1 -0
  5. package/dist/api/index.d.ts +1 -0
  6. package/dist/api/preRegistrationComplete.d.ts +1 -1
  7. package/dist/components/addonsContainer/AddonComponent.d.ts +5 -1
  8. package/dist/components/addonsContainer/SimpleAddonsContainer.d.ts +17 -0
  9. package/dist/components/addonsContainer/index.d.ts +5 -1
  10. package/dist/components/billing-info-container/index.d.ts +8 -1
  11. package/dist/components/billing-info-container/utils.d.ts +25 -1
  12. package/dist/components/common/DatePickerField.d.ts +7 -1
  13. package/dist/components/countdown/index.d.ts +1 -1
  14. package/dist/components/forgotPasswordModal/index.d.ts +2 -1
  15. package/dist/components/myTicketsContainer/index.d.ts +3 -2
  16. package/dist/components/orderDetailsContainer/index.d.ts +7 -1
  17. package/dist/components/paymentContainer/OrderDetails.d.ts +8 -0
  18. package/dist/components/paymentContainer/handlePayment.d.ts +15 -0
  19. package/dist/components/paymentContainer/index.d.ts +10 -5
  20. package/dist/components/preRegistration/FieldsSection.d.ts +7 -1
  21. package/dist/components/preRegistration/PreRegistrationComplete.d.ts +6 -0
  22. package/dist/components/preRegistration/constants.d.ts +2 -2
  23. package/dist/components/preRegistration/index.d.ts +6 -0
  24. package/dist/components/resetPasswordContainer/index.d.ts +2 -2
  25. package/dist/components/stripePayment/index.d.ts +18 -3
  26. package/dist/components/ticketsContainer/InfoIcon.d.ts +5 -0
  27. package/dist/components/ticketsContainer/TicketsSection.d.ts +3 -2
  28. package/dist/components/ticketsContainer/TimeSlotsSection.d.ts +25 -0
  29. package/dist/components/ticketsContainer/index.d.ts +18 -5
  30. package/dist/components/timerWidget/index.d.ts +2 -1
  31. package/dist/constants/index.d.ts +5 -0
  32. package/dist/index.d.ts +4 -1
  33. package/dist/tf-checkout-react.cjs.development.js +5196 -3599
  34. package/dist/tf-checkout-react.cjs.development.js.map +1 -1
  35. package/dist/tf-checkout-react.cjs.production.min.js +1 -1
  36. package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
  37. package/dist/tf-checkout-react.esm.js +5199 -3605
  38. package/dist/tf-checkout-react.esm.js.map +1 -1
  39. package/dist/tf-checkout-styles.css +1 -1
  40. package/dist/types/add_on.d.ts +1 -0
  41. package/dist/types/checkoutPageConfigs.d.ts +1 -1
  42. package/dist/types/order-data.d.ts +2 -1
  43. package/dist/utils/auth.d.ts +8 -0
  44. package/dist/utils/customFields.d.ts +11 -0
  45. package/dist/utils/getDomain.d.ts +1 -1
  46. package/dist/utils/index.d.ts +1 -1
  47. package/dist/utils/setConfigs.d.ts +1 -0
  48. package/package.json +3 -2
  49. package/src/adapters/customFields.ts +7 -1
  50. package/src/api/auth.ts +2 -1
  51. package/src/api/checkout.ts +8 -4
  52. package/src/api/common.ts +49 -2
  53. package/src/api/interceptors.ts +7 -23
  54. package/src/api/preRegistrationComplete.ts +1 -1
  55. package/src/api/publicRequest.ts +10 -0
  56. package/src/components/addonsContainer/AddonComponent.tsx +71 -11
  57. package/src/components/addonsContainer/SimpleAddonsContainer.tsx +388 -0
  58. package/src/components/addonsContainer/index.tsx +189 -58
  59. package/src/components/billing-info-container/index.tsx +704 -390
  60. package/src/components/billing-info-container/{utils.ts → utils.tsx} +119 -0
  61. package/src/components/common/CheckboxField/index.tsx +1 -1
  62. package/src/components/common/DatePickerField.tsx +25 -10
  63. package/src/components/common/SnackbarAlert.tsx +32 -34
  64. package/src/components/confirmationContainer/index.tsx +1 -1
  65. package/src/components/countdown/index.tsx +22 -22
  66. package/src/components/delegationsContainer/IssueComponent.tsx +2 -1
  67. package/src/components/forgotPasswordModal/index.tsx +44 -13
  68. package/src/components/loginForm/index.tsx +1 -1
  69. package/src/components/loginModal/index.tsx +2 -2
  70. package/src/components/loginModal/style.css +3 -1
  71. package/src/components/myTicketsContainer/index.tsx +13 -9
  72. package/src/components/orderDetailsContainer/index.tsx +188 -173
  73. package/src/components/paymentContainer/OrderDetails.tsx +170 -0
  74. package/src/components/paymentContainer/handlePayment.ts +86 -0
  75. package/src/components/paymentContainer/index.tsx +253 -226
  76. package/src/components/paymentContainer/style.css +113 -0
  77. package/src/components/preRegistration/FieldsSection.tsx +8 -0
  78. package/src/components/preRegistration/PreRegistrationComplete.tsx +128 -118
  79. package/src/components/preRegistration/PreRegistrationInformations.tsx +21 -15
  80. package/src/components/preRegistration/constants.tsx +10 -4
  81. package/src/components/preRegistration/index.tsx +194 -174
  82. package/src/components/registerForm/constants.tsx +3 -1
  83. package/src/components/registerForm/index.tsx +3 -3
  84. package/src/components/resetPasswordContainer/index.tsx +12 -13
  85. package/src/components/seatMapContainer/TicketsSection.tsx +2 -2
  86. package/src/components/stripePayment/index.tsx +129 -24
  87. package/src/components/ticketsContainer/InfoIcon.tsx +35 -0
  88. package/src/components/ticketsContainer/PromoCodeSection.tsx +34 -28
  89. package/src/components/ticketsContainer/TicketRow.tsx +1 -1
  90. package/src/components/ticketsContainer/TicketsSection.tsx +178 -52
  91. package/src/components/ticketsContainer/TimeSlotsSection.tsx +120 -0
  92. package/src/components/ticketsContainer/index.tsx +209 -99
  93. package/src/components/timerWidget/index.tsx +15 -3
  94. package/src/constants/index.ts +2 -0
  95. package/src/hoc/CustomFields/index.tsx +9 -1
  96. package/src/index.ts +7 -2
  97. package/src/types/add_on.ts +1 -0
  98. package/src/types/api/common.d.ts +27 -0
  99. package/src/types/api/orders.d.ts +19 -3
  100. package/src/types/api/payment.d.ts +5 -2
  101. package/src/types/api/preRegistrationComplete.d.ts +2 -2
  102. package/src/types/checkoutPageConfigs.ts +1 -1
  103. package/src/types/order-data.ts +2 -1
  104. package/src/types/pre-registration-complete.d.ts +6 -1
  105. package/src/utils/auth.ts +32 -0
  106. package/src/utils/cookies.ts +42 -11
  107. package/src/utils/customFields.ts +22 -0
  108. package/src/utils/getDomain.ts +10 -4
  109. package/src/utils/index.ts +1 -1
  110. package/src/utils/setConfigs.ts +3 -1
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { FormikErrors, FormikValues } from 'formik'
2
3
  import _flatMapDeep from 'lodash/flatMapDeep'
3
4
  import _forEach from 'lodash/forEach'
@@ -288,3 +289,121 @@ export const getFieldComponent = (element: IGroupItem) => {
288
289
  const fieldComponent = _get(fieldComponentConfigs, type, CustomField)
289
290
  return fieldComponent
290
291
  }
292
+
293
+ /**
294
+ * Renders a React component with the provided props
295
+ * @param Component - The React component to render
296
+ * @param props - The props to apply to the component
297
+ * @returns JSX element with applied props
298
+ */
299
+ export const renderComponentWithProps = <T extends Record<string, any>>(
300
+ Component: React.ComponentType<T>,
301
+ props: T
302
+ ): React.ReactElement<T> => <Component {...props} />
303
+
304
+ export const filterBillingInfoFields = (
305
+ fields: IGroupItem[],
306
+ options: {
307
+ showDOB: boolean;
308
+ hideTtfOptIn: boolean;
309
+ hidePhoneField: boolean;
310
+ flagRequirePhone: boolean;
311
+ collectMandatoryWalletAddress: boolean;
312
+ collectMandatoryJobTitle: boolean;
313
+ collectMandatoryBusinessCategory: boolean;
314
+ collectMandatoryCompany: boolean;
315
+ collectMandatoryInstagram: boolean;
316
+ flagFreeTicket: boolean;
317
+ hideWalletAddressField: boolean;
318
+ hideJobTitleField: boolean;
319
+ hideBusinessCategoryField: boolean;
320
+ hideCompanyField: boolean;
321
+ hideInstagramField: boolean;
322
+ }
323
+ ) => {
324
+ const {
325
+ showDOB,
326
+ hideTtfOptIn,
327
+ hidePhoneField,
328
+ flagRequirePhone,
329
+ collectMandatoryWalletAddress,
330
+ collectMandatoryJobTitle,
331
+ collectMandatoryBusinessCategory,
332
+ collectMandatoryCompany,
333
+ collectMandatoryInstagram,
334
+ flagFreeTicket,
335
+ hideWalletAddressField,
336
+ hideJobTitleField,
337
+ hideBusinessCategoryField,
338
+ hideCompanyField,
339
+ hideInstagramField,
340
+ } = options
341
+ return fields.filter(el => {
342
+ if (el.name === 'holderAge' && !showDOB) {
343
+ return false
344
+ }
345
+ if (el.name === 'ttf_opt_in' && hideTtfOptIn) {
346
+ return false
347
+ }
348
+ if (el.name === 'phone') {
349
+ if (!hidePhoneField) {
350
+ el.required = flagRequirePhone
351
+ } else {
352
+ return false
353
+ }
354
+ }
355
+ if (el.name === 'data_capture[wallet_address]') {
356
+ if (collectMandatoryWalletAddress) {
357
+ el.required = true
358
+ }
359
+ }
360
+ if (el.name === 'data_capture[jobTitle]') {
361
+ if (collectMandatoryJobTitle) {
362
+ el.required = true
363
+ }
364
+ }
365
+ if (el.name === 'data_capture[businessCategory]') {
366
+ if (collectMandatoryBusinessCategory) {
367
+ el.required = true
368
+ }
369
+ }
370
+ if (el.name === 'data_capture[company]') {
371
+ if (collectMandatoryCompany) {
372
+ el.required = true
373
+ }
374
+ }
375
+ if (el.name === 'data_capture[instagram]') {
376
+ if (collectMandatoryInstagram) {
377
+ el.required = true
378
+ }
379
+ }
380
+ if (['street_address', 'country', 'state', 'city'].includes(el.name)) {
381
+ if (flagFreeTicket) {
382
+ el.required = false
383
+ return false
384
+ }
385
+ }
386
+ if (
387
+ hideWalletAddressField &&
388
+ (el.name === 'wallet-address-info' || el.name === 'data_capture[wallet_address]')
389
+ ) {
390
+ return false
391
+ }
392
+ if (hideJobTitleField && el.name === 'data_capture[jobTitle]') {
393
+ return false
394
+ }
395
+ if (hideBusinessCategoryField && el.name === 'data_capture[businessCategory]') {
396
+ return false
397
+ }
398
+ if (hideCompanyField && el.name === 'data_capture[company]') {
399
+ return false
400
+ }
401
+ if (
402
+ hideInstagramField &&
403
+ (el.name === 'data_capture[instagram]' || el.name === 'instagram-info')
404
+ ) {
405
+ return false
406
+ }
407
+ return true
408
+ })
409
+ }
@@ -30,7 +30,7 @@ export const CheckboxField = ({
30
30
  >
31
31
  <FormGroup>
32
32
  <FormControlLabel
33
- control={<Checkbox {...field} checked={field.value} />}
33
+ control={<Checkbox {...field} checked={Boolean(field.value)} />}
34
34
  label={label}
35
35
  componentsProps={{ typography: customTheme?.checkbox }}
36
36
  />
@@ -1,4 +1,6 @@
1
+ import { ThemeOptions } from '@mui/material'
1
2
  import { createTheme, ThemeProvider } from '@mui/material/styles'
3
+ import { CSSProperties } from '@mui/styles'
2
4
  import { DatePicker } from '@mui/x-date-pickers'
3
5
  import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment'
4
6
  import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'
@@ -40,15 +42,23 @@ const compactStyles = {
40
42
  },
41
43
  }
42
44
 
43
- const compactStyleTheme = createTheme({
44
- components: {
45
- MuiPaper: {
46
- defaultProps: {
47
- sx: compactStyles,
48
- },
49
- },
50
- },
51
- })
45
+ const getTheme = (isCompact: boolean, baseThemeOptions?: object | null) => {
46
+ if (isCompact) {
47
+ return createTheme(
48
+ Object.assign(baseThemeOptions ?? {}, {
49
+ components: {
50
+ MuiPaper: {
51
+ defaultProps: {
52
+ sx: compactStyles,
53
+ },
54
+ },
55
+ },
56
+ })
57
+ )
58
+ }
59
+
60
+ return createTheme(baseThemeOptions ?? {})
61
+ }
52
62
 
53
63
  export interface IDatePickerFieldProps {
54
64
  label: string;
@@ -56,6 +66,10 @@ export interface IDatePickerFieldProps {
56
66
  field: FieldInputProps<any>;
57
67
  form: FormikProps<any>;
58
68
  theme: 'dark' | 'light';
69
+ themeOptions?: ThemeOptions & {
70
+ input?: CSSProperties;
71
+ checkbox?: CSSProperties;
72
+ };
59
73
 
60
74
  useCompact?: boolean;
61
75
  }
@@ -70,10 +84,11 @@ export const DatePickerField = ({
70
84
  form,
71
85
  theme,
72
86
  useCompact = true,
87
+ themeOptions,
73
88
  dateFormat = 'DD/MM/YYYY',
74
89
  placeholder = 'dd/mm/yyyy',
75
90
  }: IDatePickerFieldProps & IOtherProps) => (
76
- <ThemeProvider theme={useCompact ? compactStyleTheme : {}}>
91
+ <ThemeProvider theme={getTheme(useCompact, themeOptions ?? null)}>
77
92
  <LocalizationProvider dateAdapter={AdapterMoment}>
78
93
  <DatePicker
79
94
  value={field.value || ''}
@@ -1,15 +1,15 @@
1
- import React from 'react'
2
1
  import { Alert, AlertColor, Snackbar, SnackbarOrigin } from '@mui/material'
2
+ import React from 'react'
3
3
 
4
4
  interface ISnackbarAlertProps {
5
- isOpen: boolean
6
- message: string
7
- type: AlertColor
8
- position?: SnackbarOrigin
9
- autoHideDuration?: number
10
- variant?: 'filled' | 'standard' | 'outlined'
5
+ isOpen: boolean;
6
+ message: string;
7
+ type: AlertColor;
8
+ position?: SnackbarOrigin;
9
+ autoHideDuration?: number;
10
+ variant?: 'filled' | 'standard' | 'outlined';
11
11
 
12
- onClose: () => void
12
+ onClose: () => void;
13
13
  }
14
14
 
15
15
  const SnackbarAlert = ({
@@ -20,35 +20,33 @@ const SnackbarAlert = ({
20
20
  autoHideDuration = 3000,
21
21
  variant,
22
22
  onClose,
23
- }: ISnackbarAlertProps) => {
24
- return (
25
- <div className="snackbar-alert-container">
26
- <Snackbar
27
- autoHideDuration={autoHideDuration}
28
- open={isOpen}
29
- anchorOrigin={position || { vertical: 'top', horizontal: 'center' }}
23
+ }: ISnackbarAlertProps) => (
24
+ <div className="snackbar-alert-container">
25
+ <Snackbar
26
+ autoHideDuration={autoHideDuration}
27
+ open={isOpen}
28
+ anchorOrigin={position || { vertical: 'top', horizontal: 'center' }}
29
+ onClose={onClose}
30
+ classes={{
31
+ root: 'snackbar-alert-snackbar-root',
32
+ }}
33
+ >
34
+ <Alert
35
+ severity={type}
30
36
  onClose={onClose}
37
+ variant={variant || 'filled'}
31
38
  classes={{
32
- root: 'snackbar-alert-snackbar-root',
39
+ icon: 'snackbar-alert-icon',
40
+ root: 'snackbar-alert-alert-root',
41
+ action: 'snackbar-alert-action',
42
+ message: 'snackbar-alert-message',
43
+ filled: 'snackbar-alert-filled',
33
44
  }}
34
45
  >
35
- <Alert
36
- severity={type}
37
- onClose={onClose}
38
- variant={variant || 'filled'}
39
- classes={{
40
- icon: 'snackbar-alert-icon',
41
- root: 'snackbar-alert-alert-root',
42
- action: 'snackbar-alert-action',
43
- message: 'snackbar-alert-message',
44
- filled: 'snackbar-alert-filled',
45
- }}
46
- >
47
- {message}
48
- </Alert>
49
- </Snackbar>
50
- </div>
51
- )
52
- }
46
+ {message}
47
+ </Alert>
48
+ </Snackbar>
49
+ </div>
50
+ )
53
51
 
54
52
  export default SnackbarAlert
@@ -239,7 +239,7 @@ export const ConfirmationContainer = ({
239
239
  className="share-by-link-copy-icon"
240
240
  onClick={() => {
241
241
  navigator.clipboard.writeText(
242
- _get(inputRef, 'current.value')
242
+ _get(inputRef, 'current.value') || ""
243
243
  )
244
244
  setShowCopyModal(true)
245
245
  onLinkCopied()
@@ -1,7 +1,8 @@
1
- import React, { useEffect, useState } from 'react'
2
- import moment from 'moment-timezone'
3
1
  import './style.css'
4
2
 
3
+ import moment from 'moment-timezone'
4
+ import React, { useEffect, useState } from 'react'
5
+
5
6
  interface CountdownTypes {
6
7
  startDate: string;
7
8
  timezone?: string;
@@ -13,9 +14,8 @@ interface CountdownTypes {
13
14
  isLoggedIn?: boolean;
14
15
  }
15
16
 
16
- const isTimeExpired = (startDate: string, timezone: string) => {
17
- return !moment(startDate).isAfter(moment.tz(moment(), timezone).format('YYYY-MM-DD HH:mm:ss'))
18
- }
17
+ const isTimeExpired = (startDate: string, timezone: string) =>
18
+ !moment(startDate).isAfter(moment.tz(moment(), timezone).format('YYYY-MM-DD HH:mm:ss'))
19
19
 
20
20
  function Countdown({
21
21
  startDate,
@@ -25,7 +25,7 @@ function Countdown({
25
25
  showMessage = false,
26
26
  disableLeadingZero = false,
27
27
  callback = () => {},
28
- isLoggedIn
28
+ isLoggedIn,
29
29
  }: CountdownTypes) {
30
30
  const [duration, setDuration] = useState('')
31
31
  const [timeExpired, setTimeExpired] = useState(false)
@@ -35,11 +35,11 @@ function Countdown({
35
35
  }, [])
36
36
 
37
37
  useEffect(() => {
38
- let timer: any;
38
+ let timer: any
39
39
 
40
- if(!timeExpired) {
40
+ if (!timeExpired) {
41
41
  timer = setInterval(() => {
42
- if(isTimeExpired(startDate, timezone)) {
42
+ if (isTimeExpired(startDate, timezone)) {
43
43
  clearInterval(timer)
44
44
  setTimeExpired(true)
45
45
  callback()
@@ -58,8 +58,8 @@ function Countdown({
58
58
  second: duration.seconds(),
59
59
  }
60
60
  let timeLeft = ''
61
-
62
- for(let date in dateArr) {
61
+
62
+ for (const date in dateArr) {
63
63
  const unit = dateArr[date] === 1 ? date : date + 's'
64
64
  let val = dateArr[date]
65
65
 
@@ -67,13 +67,13 @@ function Countdown({
67
67
  val = '0' + dateArr[date]
68
68
  }
69
69
 
70
- if(timeLeft) {
70
+ if (timeLeft) {
71
71
  timeLeft += `, ${val} ${unit}`
72
- } else if(dateArr[date]) {
72
+ } else if (dateArr[date]) {
73
73
  timeLeft += `${val} ${unit}`
74
74
  }
75
75
  }
76
-
76
+
77
77
  setDuration(timeLeft)
78
78
  }, 1000)
79
79
  }
@@ -84,15 +84,15 @@ function Countdown({
84
84
 
85
85
  return (
86
86
  <>
87
- {!timeExpired && duration && (
88
- <div className={`countdown ${!isLoggedIn ? 'countdown-on-bottom' : ''}`}>
89
- <div>
90
- <p className='title'>{title}</p>
91
- <p>{duration}</p>
87
+ {!timeExpired && duration && (
88
+ <div className={`countdown ${!isLoggedIn ? 'countdown-on-bottom' : ''}`}>
89
+ <div>
90
+ <p className="title">{title}</p>
91
+ <p>{duration}</p>
92
+ </div>
93
+ {showMessage && <p className="message">{message}</p>}
92
94
  </div>
93
- {showMessage && <p className='message'>{message}</p>}
94
- </div>
95
- )}
95
+ )}
96
96
  </>
97
97
  )
98
98
  }
@@ -1,4 +1,5 @@
1
1
  import axios, { AxiosError } from 'axios'
2
+ import _get from 'lodash/get'
2
3
  import _identity from 'lodash/identity'
3
4
  import _map from 'lodash/map'
4
5
  import React, { useEffect, useState } from 'react'
@@ -123,7 +124,7 @@ const IssueComponent = ({
123
124
  resetForm()
124
125
  } catch (e) {
125
126
  if (axios.isAxiosError(e)) {
126
- const error = e?.response?.data?.message || 'Error'
127
+ const error = _get(e, 'response.data.message') || 'Error'
127
128
  setError(error)
128
129
  } else if (e instanceof Error) {
129
130
  setError(e?.message || 'Error')
@@ -3,6 +3,7 @@ import './style.css'
3
3
  import { Box, CircularProgress, Modal } from '@mui/material'
4
4
  import axios, { AxiosError } from 'axios'
5
5
  import { Field, Form, Formik } from 'formik'
6
+ import _identity from 'lodash/identity'
6
7
  import React, { FC, useState } from 'react'
7
8
  import * as Yup from 'yup'
8
9
 
@@ -13,9 +14,10 @@ import { PoweredBy } from '../common/PoweredBy'
13
14
  export interface IForgotPasswordProps {
14
15
  onClose: () => void;
15
16
  onLoginButtonClick: () => void;
16
- onForgotPasswordSuccess: (res: any) => void;
17
+ onForgotPasswordSuccess: (res: IAxiosResponseData) => void;
17
18
  onForgotPasswordError: (e: AxiosError) => void;
18
19
  showPoweredByImage?: boolean;
20
+ displaySuccessMessage?: boolean;
19
21
  }
20
22
 
21
23
  interface ValuesTypes {
@@ -39,21 +41,37 @@ const Schema = Yup.object().shape({
39
41
  })
40
42
 
41
43
  export const ForgotPasswordModal: FC<IForgotPasswordProps> = ({
42
- onClose = () => {},
43
- onLoginButtonClick = () => {},
44
- onForgotPasswordSuccess = () => {},
45
- onForgotPasswordError = () => {},
44
+ onClose = _identity,
45
+ onLoginButtonClick = _identity,
46
+ onForgotPasswordSuccess = _identity,
47
+ onForgotPasswordError = _identity,
46
48
  showPoweredByImage = false,
49
+ displaySuccessMessage = false,
47
50
  }) => {
48
51
  const [loading, setLoading] = useState(false)
52
+ const [successMessage, setSuccessMessage] = useState<string | null>(null)
53
+ const showSuccess = displaySuccessMessage && successMessage
49
54
 
50
55
  const onForgotPassword = async ({ email }: ValuesTypes) => {
56
+ if (showSuccess) {
57
+ setSuccessMessage(null)
58
+ onClose()
59
+ return
60
+ }
61
+
51
62
  try {
52
63
  setLoading(true)
53
64
  const { data } = await forgotPassword(email)
54
65
 
55
66
  onForgotPasswordSuccess(data)
56
- onClose()
67
+
68
+ if (displaySuccessMessage && data?.success) {
69
+ setSuccessMessage(data?.message)
70
+ }
71
+
72
+ if (!displaySuccessMessage) {
73
+ onClose()
74
+ }
57
75
  } catch (e) {
58
76
  if (axios.isAxiosError(e)) {
59
77
  onForgotPasswordError(e)
@@ -63,12 +81,10 @@ export const ForgotPasswordModal: FC<IForgotPasswordProps> = ({
63
81
  }
64
82
  }
65
83
 
66
- const _onClose = loading ? () => {} : onClose
67
-
68
84
  return (
69
85
  <Modal
70
86
  open={true}
71
- onClose={_onClose}
87
+ onClose={loading ? _identity : onClose}
72
88
  aria-labelledby="modal-modal-title"
73
89
  aria-describedby="modal-modal-description"
74
90
  className="forgot-password-modal"
@@ -85,16 +101,31 @@ export const ForgotPasswordModal: FC<IForgotPasswordProps> = ({
85
101
  <div className="forgot-password-container">
86
102
  <div className="title">Password Reset</div>
87
103
  <div className="forgot-password-container__singleField">
88
- <Field name="email" label="Email" component={CustomField} />
104
+ {showSuccess ? (
105
+ <p id="forgot-password-success-message">{successMessage}</p>
106
+ ) : (
107
+ <Field name="email" label="Email" component={CustomField} />
108
+ )}
89
109
  </div>
90
110
  </div>
91
111
  <div className="forgot-password-action-button">
92
- <button type="submit" disabled={!(isValid && dirty)}>
93
- {loading ? <CircularProgress size="22px" /> : 'Submit'}
112
+ <button
113
+ type="submit"
114
+ disabled={showSuccess ? false : !(isValid && dirty)}
115
+ >
116
+ {loading ? (
117
+ <CircularProgress size="22px" />
118
+ ) : showSuccess ? (
119
+ 'Close'
120
+ ) : (
121
+ 'Submit'
122
+ )}
94
123
  </button>
95
124
  </div>
96
125
  <div className="login">
97
- <span onClick={onLoginButtonClick}>Back to Log In</span>
126
+ <span aria-hidden onClick={onLoginButtonClick}>
127
+ Back to Log In
128
+ </span>
98
129
  </div>
99
130
  {showPoweredByImage ? <PoweredBy /> : null}
100
131
  </Form>
@@ -106,7 +106,7 @@ export const LoginForm: FC<ILoginFormProps> = ({
106
106
  onLoginSuccess(_get(authRes, 'data'))
107
107
  } catch (e) {
108
108
  if (axios.isAxiosError(e)) {
109
- const error = e?.response?.data?.message || 'Error'
109
+ const error = _get(e, 'response.data.message') || 'Error'
110
110
  setError(error)
111
111
  onLoginError(e)
112
112
  } else if (e instanceof Error) {
@@ -93,10 +93,10 @@ export const LoginModal: FC<Props> = ({
93
93
  const event = new window.CustomEvent('tf-login')
94
94
  window.document.dispatchEvent(event)
95
95
  }
96
- onLogin(_get(authRes, 'data.data'))
96
+ onLogin(_get(authRes, 'data.data', {}) as IProfileData)
97
97
  } catch (e) {
98
98
  if (axios.isAxiosError(e)) {
99
- const error = e?.response?.data?.message || 'Error'
99
+ const error = _get(e, 'response.data.message', 'Error')
100
100
  setError(error)
101
101
  } else if (e instanceof Error) {
102
102
  setError(e?.message || 'Error')
@@ -46,7 +46,9 @@
46
46
  background-color: #505050;
47
47
  border-color: #505050;
48
48
  }
49
-
49
+ .login-logo-tff{
50
+ height: 60px;
51
+ }
50
52
  .server_auth__error {
51
53
  color: red;
52
54
  padding-left: 25px;
@@ -31,6 +31,7 @@ interface MyTicketsTypes {
31
31
  selectEventsLabel?: string;
32
32
  openLoginModal?: () => void;
33
33
  hideDetailsButton?: boolean;
34
+ customNoOrderContent?: React.ReactNode;
34
35
  columns?: IColumnData[];
35
36
  }
36
37
 
@@ -49,6 +50,7 @@ export const MyTicketsContainer = ({
49
50
  hideDetailsButton = false,
50
51
  columns = [],
51
52
  openLoginModal,
53
+ customNoOrderContent = null,
52
54
  }: MyTicketsTypes) => {
53
55
  const [data, setData] = useState<any>(null)
54
56
  const [loading, setLoading] = useState(true)
@@ -79,7 +81,7 @@ export const MyTicketsContainer = ({
79
81
  setData(data)
80
82
  } catch (error) {
81
83
  if (axios.isAxiosError(error)) {
82
- if (error.response?.data.error === 'invalid_token') {
84
+ if (_get(error, 'response.data.error') === 'invalid_token') {
83
85
  if (isWindowDefined) {
84
86
  window.localStorage.removeItem('user_data')
85
87
  setUserExpired(true)
@@ -110,6 +112,15 @@ export const MyTicketsContainer = ({
110
112
  setFilter(eventFilter?.url_name || '')
111
113
  }
112
114
 
115
+ const noOrderContent = customNoOrderContent || (<div className="no_orders_section">
116
+ <div className="nodata_title">
117
+ You have no current ticket orders on this account
118
+ </div>
119
+ <div className="nodata_subtitle">
120
+ Discover your next nite out <a href="/events">here</a>.
121
+ </div>
122
+ </div>)
123
+
113
124
  return (
114
125
  <div className={`my-ticket ${theme}`}>
115
126
  <>
@@ -191,14 +202,7 @@ export const MyTicketsContainer = ({
191
202
  !loading && (
192
203
  <>
193
204
  <h2>My Ticket Orders</h2>
194
- <div className="no_orders_section">
195
- <div className="nodata_title">
196
- You have no current ticket orders on this account
197
- </div>
198
- <div className="nodata_subtitle">
199
- Discover your next nite out <a href="/events">here</a>.
200
- </div>
201
- </div>
205
+ {noOrderContent}
202
206
  </>
203
207
  )
204
208
  )}