tf-checkout-react 1.4.26 → 1.5.0

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 (76) hide show
  1. package/dist/api/index.d.ts +1 -0
  2. package/dist/api/preRegistrationComplete.d.ts +3 -0
  3. package/dist/components/billing-info-container/index.d.ts +1 -3
  4. package/dist/components/common/CopyField.d.ts +12 -0
  5. package/dist/components/common/CopyMessageModal.d.ts +7 -0
  6. package/dist/components/common/index.d.ts +1 -0
  7. package/dist/components/common/socials.d.ts +10 -0
  8. package/dist/components/confirmationContainer/index.d.ts +7 -7
  9. package/dist/components/confirmationContainer/social-buttons.d.ts +5 -2
  10. package/dist/components/forgotPasswordModal/index.d.ts +2 -3
  11. package/dist/components/loginForm/index.d.ts +1 -0
  12. package/dist/components/loginModal/index.d.ts +2 -3
  13. package/dist/components/preRegistration/FieldsSection.d.ts +13 -0
  14. package/dist/components/preRegistration/Influancers.d.ts +2 -0
  15. package/dist/components/preRegistration/PreRegistrationComplete.d.ts +5 -0
  16. package/dist/components/preRegistration/PreRegistrationInformations.d.ts +2 -0
  17. package/dist/components/preRegistration/Prewards.d.ts +2 -0
  18. package/dist/components/preRegistration/ShareOptions.d.ts +2 -0
  19. package/dist/components/preRegistration/constants.d.ts +2 -0
  20. package/dist/components/preRegistration/index.d.ts +17 -0
  21. package/dist/components/preRegistration/utils.d.ts +12 -0
  22. package/dist/components/ticketsContainer/TicketRow.d.ts +3 -2
  23. package/dist/components/ticketsContainer/utils.d.ts +9 -0
  24. package/dist/hooks/index.d.ts +1 -0
  25. package/dist/hooks/useEventListener.d.ts +1 -0
  26. package/dist/hooks/useLocalStorageListener.d.ts +1 -0
  27. package/dist/images/instagram.svg +5 -0
  28. package/dist/images/spotify.svg +6 -0
  29. package/dist/index.d.ts +4 -1
  30. package/dist/tf-checkout-react.cjs.development.js +1508 -157
  31. package/dist/tf-checkout-react.cjs.development.js.map +1 -1
  32. package/dist/tf-checkout-react.cjs.production.min.js +1 -1
  33. package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
  34. package/dist/tf-checkout-react.esm.js +1509 -157
  35. package/dist/tf-checkout-react.esm.js.map +1 -1
  36. package/dist/utils/isValidNumber.d.ts +1 -0
  37. package/package.json +1 -1
  38. package/src/api/index.ts +28 -0
  39. package/src/api/preRegistrationComplete.ts +37 -0
  40. package/src/assets/images/instagram.svg +5 -0
  41. package/src/assets/images/spotify.svg +6 -0
  42. package/src/components/billing-info-container/index.tsx +1 -7
  43. package/src/components/common/CopyField.tsx +53 -0
  44. package/src/components/common/CopyMessageModal.tsx +34 -0
  45. package/src/components/common/NativeSelectFeild/index.tsx +1 -1
  46. package/src/components/common/index.tsx +1 -0
  47. package/src/components/common/socials.tsx +33 -0
  48. package/src/components/confirmationContainer/config.ts +62 -55
  49. package/src/components/confirmationContainer/index.tsx +11 -31
  50. package/src/components/confirmationContainer/social-buttons.tsx +43 -20
  51. package/src/components/forgotPasswordModal/index.tsx +4 -4
  52. package/src/components/loginForm/index.tsx +4 -0
  53. package/src/components/loginModal/index.tsx +5 -4
  54. package/src/components/preRegistration/FieldsSection.tsx +142 -0
  55. package/src/components/preRegistration/Influancers.tsx +34 -0
  56. package/src/components/preRegistration/PreRegistrationComplete.tsx +164 -0
  57. package/src/components/preRegistration/PreRegistrationInformations.tsx +54 -0
  58. package/src/components/preRegistration/Prewards.tsx +41 -0
  59. package/src/components/preRegistration/ShareOptions.tsx +77 -0
  60. package/src/components/preRegistration/constants.tsx +161 -0
  61. package/src/components/preRegistration/index.tsx +274 -0
  62. package/src/components/preRegistration/utils.ts +155 -0
  63. package/src/components/ticketsContainer/ReferralLogic.tsx +1 -1
  64. package/src/components/ticketsContainer/TicketRow.tsx +17 -14
  65. package/src/components/ticketsContainer/TicketsSection.tsx +2 -0
  66. package/src/components/ticketsContainer/index.tsx +77 -8
  67. package/src/components/ticketsContainer/utils.ts +30 -6
  68. package/src/hooks/index.ts +1 -0
  69. package/src/hooks/useEventListener.ts +32 -0
  70. package/src/hooks/useLocalStorageListener.ts +27 -0
  71. package/src/index.ts +6 -2
  72. package/src/types/api/preRegistration.d.ts +11 -0
  73. package/src/types/api/preRegistrationComplete.d.ts +95 -0
  74. package/src/types/pre-registration-complete.d.ts +42 -0
  75. package/src/utils/cookies.ts +7 -7
  76. package/src/utils/isValidNumber.ts +8 -0
@@ -0,0 +1,161 @@
1
+ import React from 'react'
2
+
3
+ export const formFieldsNotLoggedIn: IFormFieldsSection[] = [
4
+ {
5
+ name: 'basic-info',
6
+ groupLabel: (
7
+ <>
8
+ <span>
9
+ If you want to enter your details manually, please type them below to create an
10
+ account, then click on
11
+ </span>
12
+ <b> Confirm Registration:</b>
13
+ </>
14
+ ),
15
+ groupLabelClassName: '',
16
+ groupClassName: '',
17
+ fields: [
18
+ {
19
+ className: 'half-width',
20
+ name: 'firstName',
21
+ label: 'First Name',
22
+ type: 'text',
23
+ required: true,
24
+ onValidate: null,
25
+ },
26
+ {
27
+ className: 'half-width',
28
+ name: 'lastName',
29
+ label: 'Last Name',
30
+ type: 'text',
31
+ required: true,
32
+ onValidate: null,
33
+ },
34
+ {
35
+ name: 'email',
36
+ label: 'Email',
37
+ type: 'email',
38
+ required: true,
39
+ onValidate: null,
40
+ },
41
+ {
42
+ name: 'confirmEmail',
43
+ label: 'Confirm Email',
44
+ type: 'email',
45
+ required: true,
46
+ onValidate: null,
47
+ },
48
+ ],
49
+ },
50
+ {
51
+ name: 'billing-info',
52
+ groupLabel: '',
53
+ groupLabelClassName: '',
54
+ groupClassName: '',
55
+ fields: [
56
+ {
57
+ className: 'half-width',
58
+ name: 'zip',
59
+ label: 'Post Code/Zip',
60
+ type: 'text',
61
+ required: true,
62
+ onValidate: null,
63
+ },
64
+ {
65
+ className: 'half-width',
66
+ name: 'country',
67
+ label: 'Country',
68
+ type: 'select',
69
+ required: true,
70
+ onValidate: null,
71
+ },
72
+ ],
73
+ },
74
+ {
75
+ name: 'password-info',
76
+ groupLabel: (
77
+ <div className="email-info-block">
78
+ <span>Choose a password for your new</span>
79
+ <b> Mana Common </b>
80
+ <span>account</span>
81
+ </div>
82
+ ),
83
+ groupLabelClassName: '',
84
+ groupClassName: '',
85
+ fields: [
86
+ {
87
+ className: 'half-width',
88
+ name: 'password',
89
+ label: 'Password',
90
+ type: 'password',
91
+ required: true,
92
+ onValidate: null,
93
+ },
94
+ {
95
+ className: 'half-width',
96
+ name: 'confirmPassword',
97
+ label: 'Confirm Password',
98
+ type: 'password',
99
+ required: true,
100
+ onValidate: null,
101
+ },
102
+ ],
103
+ },
104
+ ]
105
+
106
+ export const formFieldsLoggedIn: IFormFieldsSection[] = [
107
+ {
108
+ name: 'basic-info-logged-in',
109
+ groupLabel:
110
+ 'To confirm your pre-registration for {event_name} simply click on the confirmation button below.',
111
+ groupLabelClassName: '',
112
+ groupClassName: '',
113
+ fields: [
114
+ {
115
+ name: 'email',
116
+ label: 'Email',
117
+ type: 'email',
118
+ required: true,
119
+ onValidate: null,
120
+ },
121
+ {
122
+ name: 'confirmEmail',
123
+ label: 'Confirm Email',
124
+ type: 'email',
125
+ required: true,
126
+ onValidate: null,
127
+ },
128
+ ],
129
+ },
130
+ {
131
+ name: 'billing-info-logged-in',
132
+ groupLabel: '',
133
+ groupLabelClassName: '',
134
+ groupClassName: '',
135
+ fields: [
136
+ {
137
+ name: 'numTickets',
138
+ label: 'How many tickets do you want to buy?',
139
+ type: 'select',
140
+ required: true,
141
+ options: new Array(10).fill(null).map((_, index) => ({
142
+ label: index + 1,
143
+ value: index + 1,
144
+ })),
145
+ onValidate: null,
146
+ },
147
+ {
148
+ name: 'holderAge',
149
+ label: 'Ticket Holder Age',
150
+ type: 'date',
151
+ required: true,
152
+ onValidate: null,
153
+ },
154
+ {
155
+ name: 'brandOptIn',
156
+ label: 'I would like to be updated on Mana Common news, events and offers.',
157
+ type: 'checkbox',
158
+ },
159
+ ],
160
+ },
161
+ ]
@@ -0,0 +1,274 @@
1
+ import { Button, CircularProgress } from '@mui/material'
2
+ import axios, { AxiosError } from 'axios'
3
+ import { Form, Formik, FormikValues } from 'formik'
4
+ import _get from 'lodash/get'
5
+ import _identity from 'lodash/identity'
6
+ import _map from 'lodash/map'
7
+ import React, { FC, useEffect, useState } from 'react'
8
+
9
+ import { confirmPreRegistration, getCountries, getProfileData, register } from '../../api'
10
+ import { useCookieListener } from '../../hooks/useCookieListener'
11
+ import { CONFIGS, getCookieByName, getQueryVariable } from '../../utils'
12
+ import SnackbarAlert from '../common/SnackbarAlert'
13
+ import ConfirmModal from '../confirmModal'
14
+ import { ForgotPasswordModal, IForgotPasswordProps } from '../forgotPasswordModal'
15
+ import { LoginModal, Props } from '../loginModal'
16
+ import { formFieldsLoggedIn, formFieldsNotLoggedIn } from './constants'
17
+ import { FieldsSection } from './FieldsSection'
18
+ import { getFormInitialValues, updateFormFieldsAttributes } from './utils'
19
+
20
+ const X_TF_ECOMMERCE = 'X-TF-ECOMMERCE'
21
+ const isWindowDefined = typeof window !== 'undefined'
22
+
23
+ interface IPreRegistrationProps extends Props, IForgotPasswordProps {
24
+ eventId: string | number;
25
+ formFields?: IFormFieldsSection[];
26
+ additionalFieldAttribute?: IFieldAttribute;
27
+ isPreregistrationStarted: boolean;
28
+ onGetCountriesSuccess?: (res: any) => void;
29
+ onGetCountriesError?: (e: AxiosError) => void;
30
+ onConfirmationSuccess?: (res: any) => void;
31
+ onConfirmationError?: (e: AxiosError) => void;
32
+ onLoginSuccess?: (res: any) => void;
33
+ }
34
+
35
+ export const PreRegistration: FC<IPreRegistrationProps> = ({
36
+ eventId,
37
+ formFields: pFormFields,
38
+ additionalFieldAttribute,
39
+ isPreregistrationStarted,
40
+ logo,
41
+ showForgotPasswordButton,
42
+ onLoginSuccess = _identity,
43
+ onForgotPasswordSuccess = _identity,
44
+ onForgotPasswordError = _identity,
45
+ onGetCountriesSuccess = _identity,
46
+ onGetCountriesError = _identity,
47
+ onConfirmationSuccess = _identity,
48
+ onConfirmationError = _identity,
49
+ }) => {
50
+ const [error, setError] = useState('')
51
+ const [showModalLogin, setShowModalLogin] = useState(false)
52
+ const [alreadyHasUser, setAlreadyHasUser] = useState(false)
53
+ const [showModalForgotPassword, setShowModalForgotPassword] = useState(false)
54
+ const [countries, setCountries] = useState<{ [key: string]: string | number }[]>([])
55
+ const [isLoggedIn, setIsLoggedIn] = useState(Boolean(getCookieByName(X_TF_ECOMMERCE)))
56
+ const [confirmModalState, setConfirmModalState] = useState({ show: false, message: '' })
57
+ useCookieListener(X_TF_ECOMMERCE, value => setIsLoggedIn(Boolean(value)))
58
+
59
+ const formFields = updateFormFieldsAttributes(
60
+ pFormFields || isLoggedIn ? formFieldsLoggedIn : formFieldsNotLoggedIn,
61
+ additionalFieldAttribute
62
+ )
63
+
64
+ useEffect(() => {
65
+ // fetch countries data
66
+ const fetchCountries = async () => {
67
+ try {
68
+ const res = await getCountries()
69
+ setCountries(
70
+ _map(_get(res, 'data'), item => ({
71
+ label: item.name,
72
+ value: Number(item.id),
73
+ }))
74
+ )
75
+ onGetCountriesSuccess(res.data)
76
+ } catch (e) {
77
+ if (axios.isAxiosError(e)) {
78
+ const error = e?.response?.data?.message || 'Error'
79
+ setError(error)
80
+ onGetCountriesError(e)
81
+ }
82
+ }
83
+ }
84
+ fetchCountries()
85
+ }, [])
86
+
87
+ const hash = getQueryVariable('hash') || ''
88
+ const referrerId = getQueryVariable('referrer_id') || ''
89
+ return (
90
+ <div className="pre-registration-container">
91
+ <SnackbarAlert
92
+ type="error"
93
+ isOpen={!!error}
94
+ message={error || ''}
95
+ onClose={() => {
96
+ setError('')
97
+ }}
98
+ />
99
+ {confirmModalState.show && (
100
+ <ConfirmModal
101
+ hideCancelBtn
102
+ onConfirm={() => setConfirmModalState({ show: false, message: '' })}
103
+ message={confirmModalState.message}
104
+ />
105
+ )}
106
+ {!isLoggedIn && (
107
+ <div className="account-actions-block">
108
+ <div className="action-item">
109
+ <div>
110
+ <span>
111
+ Create (or log in to) your account, then click on Confirm Registration.
112
+ </span>
113
+ <span> If you have a</span>
114
+ <b> Mana Common </b>
115
+ <span>account and password already</span>
116
+ </div>
117
+ </div>
118
+ <div className="action-item login-block">
119
+ <button
120
+ className="login-register-button"
121
+ type="button"
122
+ onClick={() => {
123
+ setShowModalLogin(true)
124
+ }}
125
+ >
126
+ Login
127
+ </button>
128
+ </div>
129
+ </div>
130
+ )}
131
+ {showModalLogin && (
132
+ <LoginModal
133
+ logo={logo}
134
+ onClose={() => {
135
+ setShowModalLogin(false)
136
+ }}
137
+ onLogin={res => {
138
+ setShowModalLogin(false)
139
+ onLoginSuccess(res)
140
+ }}
141
+ showForgotPasswordButton={showForgotPasswordButton}
142
+ onForgotPassword={() => {
143
+ setShowModalLogin(false)
144
+ setShowModalForgotPassword(true)
145
+ }}
146
+ alreadyHasUser={alreadyHasUser}
147
+ />
148
+ )}
149
+ {showModalForgotPassword && (
150
+ <ForgotPasswordModal
151
+ onClose={() => {
152
+ setShowModalForgotPassword(false)
153
+ }}
154
+ onLoginButtonClick={() => {
155
+ setShowModalForgotPassword(false)
156
+ setShowModalLogin(true)
157
+ }}
158
+ onForgotPasswordSuccess={onForgotPasswordSuccess}
159
+ onForgotPasswordError={onForgotPasswordError}
160
+ />
161
+ )}
162
+ <h2>Pre-Registration</h2>
163
+ <Formik
164
+ initialValues={getFormInitialValues(formFields)}
165
+ enableReinitialize={true}
166
+ onSubmit={async (values: FormikValues) => {
167
+ try {
168
+ if (isLoggedIn) {
169
+ if (isPreregistrationStarted) {
170
+ const updatedValues = { ...values }
171
+ const holderAgeDate = new Date(values.holderAge)
172
+ updatedValues.dobDay = holderAgeDate.getDate()
173
+ updatedValues.dobMonth = holderAgeDate.getMonth() + 1
174
+ updatedValues.dobYear = holderAgeDate.getFullYear()
175
+ updatedValues.referrerId = referrerId
176
+ updatedValues.shareHash = hash
177
+ // remove date picker string value
178
+ delete updatedValues.holderAge
179
+
180
+ const confirmationData = await confirmPreRegistration(
181
+ eventId,
182
+ updatedValues as IConfirmPreRegistrationRequestData
183
+ )
184
+ if (isWindowDefined) {
185
+ window.localStorage.setItem(
186
+ 'pre-registration-hash',
187
+ _get(confirmationData, 'attributes.hash')
188
+ )
189
+ }
190
+
191
+ onConfirmationSuccess(confirmationData)
192
+ } else {
193
+ setConfirmModalState({
194
+ show: true,
195
+ message: 'The preregistration has not started',
196
+ })
197
+ }
198
+ } else {
199
+ const bodyFormData = new FormData()
200
+ bodyFormData.append('first_name', values.firstName)
201
+ bodyFormData.append('last_name', values.lastName)
202
+ bodyFormData.append('email', values.email)
203
+ bodyFormData.append('confirm_email', values.confirmEmail)
204
+ bodyFormData.append('zip', values.zip)
205
+ bodyFormData.append('country', values.country)
206
+ bodyFormData.append('password', values.password)
207
+ bodyFormData.append('password_confirmation', values.confirmPassword)
208
+ bodyFormData.append('client_id', CONFIGS.CLIENT_ID)
209
+ bodyFormData.append('client_secret', CONFIGS.CLIENT_SECRET)
210
+ bodyFormData.append('register_for', 'prereg')
211
+
212
+ const res = await register(bodyFormData)
213
+ const profileRes = await getProfileData()
214
+ onLoginSuccess(res.data)
215
+ if (isWindowDefined) {
216
+ window.localStorage.setItem(
217
+ 'user_data',
218
+ JSON.stringify(_get(profileRes, 'data'))
219
+ )
220
+ }
221
+ }
222
+ } catch (e) {
223
+ let errorMessage = e?.message || 'Error'
224
+ const emailErrors = e?.response?.data?.message?.email
225
+
226
+ if (typeof e?.response?.data?.message === 'string') {
227
+ errorMessage = e?.response?.data?.message
228
+ }
229
+ if (emailErrors?.length > 0) {
230
+ if (emailErrors[0] === 'The email is already used') {
231
+ setShowModalLogin(true)
232
+ setAlreadyHasUser(true)
233
+ }
234
+ } else {
235
+ setError(errorMessage)
236
+ }
237
+
238
+ onConfirmationError(e)
239
+ }
240
+ }}
241
+ >
242
+ {props => (
243
+ <Form>
244
+ <div className="login-modal-body">
245
+ <FieldsSection
246
+ formFields={formFields}
247
+ values={props.values}
248
+ setFieldValue={props.setFieldValue}
249
+ containerClass="pre-registration"
250
+ countries={countries}
251
+ />
252
+ </div>
253
+ <div className="button-container">
254
+ <Button
255
+ type="submit"
256
+ variant="contained"
257
+ className="login-register-button"
258
+ disabled={props.isSubmitting}
259
+ >
260
+ {props.isSubmitting ? (
261
+ <CircularProgress size={26} />
262
+ ) : isLoggedIn ? (
263
+ 'Confirm Pre-Registration'
264
+ ) : (
265
+ 'Create Account'
266
+ )}
267
+ </Button>
268
+ </div>
269
+ </Form>
270
+ )}
271
+ </Formik>
272
+ </div>
273
+ )
274
+ }
@@ -0,0 +1,155 @@
1
+ import { FormikValues } from 'formik'
2
+ import _forEach from 'lodash/forEach'
3
+ import _get from 'lodash/get'
4
+ import _identity from 'lodash/identity'
5
+ import _isEmpty from 'lodash/isEmpty'
6
+ import _map from 'lodash/map'
7
+ import _split from 'lodash/split'
8
+
9
+ import { combineValidators, requiredValidator } from '../../validators'
10
+ import { IShareButton } from '../confirmationContainer'
11
+
12
+ export const getValidateFunctions = ({
13
+ element,
14
+ values,
15
+ }: {
16
+ element: IFormField;
17
+ values: FormikValues;
18
+ }) => {
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ const validationFunctions: any[] = []
21
+ if (element.required) {
22
+ validationFunctions.push(requiredValidator)
23
+ }
24
+
25
+ if (element.onValidate) {
26
+ validationFunctions.push(element.onValidate)
27
+ }
28
+
29
+ if (element.name === 'confirmEmail') {
30
+ const isSameEmail = (confirmEmail?: string) =>
31
+ values.email !== confirmEmail ? 'Please confirm your email address correctly' : null
32
+ validationFunctions.push(isSameEmail)
33
+ }
34
+
35
+ if (element.name === 'confirmPassword') {
36
+ const isSame = (confirmPassword?: string) =>
37
+ values.password !== confirmPassword ? 'Password confirmation does not match' : null
38
+ validationFunctions.push(isSame)
39
+ }
40
+
41
+ return combineValidators(...validationFunctions)
42
+ }
43
+
44
+ export const getFormInitialValues = (fieldsSections: IFormFieldsSection[]) => {
45
+ const initialValues: { [key: string]: string | number | boolean } = {}
46
+ const isWindowDefined = typeof window !== 'undefined'
47
+ const userData = JSON.parse(
48
+ isWindowDefined ? window.localStorage.getItem('user_data') || '{}' : '{}'
49
+ ) as IProfileData
50
+
51
+ _forEach(fieldsSections, item => {
52
+ _forEach(item.fields, fieldItem => {
53
+ switch (fieldItem.name) {
54
+ case 'country':
55
+ case 'numTickets':
56
+ initialValues[fieldItem.name] = 1
57
+ break
58
+ case 'brandOptIn':
59
+ initialValues[fieldItem.name] = true
60
+ break
61
+ case 'confirmEmail':
62
+ initialValues[fieldItem.name] =
63
+ _get(userData, fieldItem.name) || _get(userData, 'email') || ''
64
+ break
65
+ default:
66
+ initialValues[fieldItem.name] = _get(userData, fieldItem.name) || ''
67
+ break
68
+ }
69
+ })
70
+ })
71
+
72
+ return initialValues
73
+ }
74
+
75
+ export const updateFormFieldsAttributes = (
76
+ formFields: IFormFieldsSection[],
77
+ attributes?: IFieldAttribute
78
+ ) => {
79
+ if (attributes && !_isEmpty(attributes)) {
80
+ const updatedFormFields = _map(formFields, fieldSection => {
81
+ const fieldSectionAttributes = attributes[fieldSection.name] || {}
82
+
83
+ const updatedFields = _map(fieldSection.fields, fieldItem => {
84
+ const fieldItemAttributes = attributes[fieldItem.name] || {}
85
+ return { ...fieldItem, ...fieldItemAttributes }
86
+ })
87
+
88
+ return {
89
+ ...fieldSection,
90
+ ...fieldSectionAttributes,
91
+ fields: updatedFields,
92
+ }
93
+ })
94
+
95
+ return updatedFormFields
96
+ }
97
+ return formFields
98
+ }
99
+
100
+ export const shareOptionsAdapter = (
101
+ data: Array<IShareOptionsActionData>,
102
+ shareUrl: string
103
+ ) => {
104
+ const adaptedData: Array<IShareButton> = []
105
+ _forEach(data, option => {
106
+ if (option.action !== 'shared_url') {
107
+ const [platform, method] = _split(option.action, '_')
108
+ const mainLabel = method ? method[0].toUpperCase() + method.substring(1) : 'Share'
109
+ adaptedData.push({
110
+ mainLabel: option.action === 'twitter' ? 'Tweet' : mainLabel + ' on',
111
+ subLabel:
112
+ option.action === 'twitter'
113
+ ? ' to your followers'
114
+ : platform[0].toUpperCase() + platform.substring(1),
115
+ platform,
116
+ shareData: {
117
+ quote: 'as',
118
+ url: option.socialUrl || shareUrl,
119
+ },
120
+ points: option.point,
121
+ eventActionId: option.id,
122
+ oneTimeAction: option.oneTimeAction,
123
+ alreadyApplied: option.alreadyApplied,
124
+ })
125
+ }
126
+ })
127
+ return adaptedData
128
+ }
129
+
130
+ export const getShuffleMethodByName = (
131
+ tokenShuffleMethod: string
132
+ ): ((value: string) => string) => {
133
+ const reverseString = (value: string) => value.split('').reverse().join('')
134
+ const symmetricShuffleString = (value: string) => {
135
+ const lengthOfStr = value.length
136
+ const part1 = value.substring(0, lengthOfStr / 2)
137
+ return value.substring(lengthOfStr / 2) + part1
138
+ }
139
+ const shuffleEveryTwoSymbolsInString = (value: string): string => {
140
+ const words = value.split('')
141
+ let shuffledStr = ''
142
+ for (let i = 0; i < words.length; i += 2) {
143
+ shuffledStr = shuffledStr.concat(words[i + 1], words[i])
144
+ }
145
+ return shuffledStr
146
+ }
147
+
148
+ if (tokenShuffleMethod === 'reverse_string') {
149
+ return reverseString
150
+ } else if (tokenShuffleMethod === 'symmetric_shuffle_string') {
151
+ return symmetricShuffleString
152
+ } else if (tokenShuffleMethod === 'shuffle_every_two_symbols_in_string')
153
+ return shuffleEveryTwoSymbolsInString
154
+ return _identity
155
+ }
@@ -14,7 +14,7 @@ export const ReferralLogic = (props: IReferralLogicProps) => {
14
14
 
15
15
  if (isWindowDefined) {
16
16
  const params: URLSearchParams = new URL(`${window.location}`).searchParams
17
- const referralId = params.get('ttf_r') || ''
17
+ const referralId = params.get('ttf_r') || params.get('referrer_id') || ''
18
18
  const referralValue = [eventId, '.', referralId].join('')
19
19
  const isAlreadyCounted = localStorage.getItem('referral_key') === referralValue
20
20
 
@@ -7,14 +7,15 @@ import Select from '@mui/material/Select'
7
7
  import _get from 'lodash/get'
8
8
  import React from 'react'
9
9
 
10
- import { getTicketSelectOptions } from './utils'
10
+ import { defineIsSalesClosed, getTicketSelectOptions } from './utils'
11
11
 
12
12
  interface ITicketRowProps {
13
13
  ticketTier: any;
14
14
  prevTicketTier: any;
15
15
  selectedTickets: any;
16
16
  handleTicketSelect: any;
17
- isSeatMapAllowed?: any;
17
+ event: any;
18
+ isSeatMapAllowed?: boolean;
18
19
  tableType?: boolean;
19
20
  }
20
21
 
@@ -23,13 +24,20 @@ export const TicketRow = ({
23
24
  prevTicketTier,
24
25
  selectedTickets,
25
26
  handleTicketSelect,
27
+ event,
26
28
  isSeatMapAllowed,
27
29
  tableType,
28
30
  }: ITicketRowProps) => {
29
31
  const soldOutMessage = ticketTier.soldOutMessage
30
32
  ? `${ticketTier.soldOutMessage}`.toUpperCase()
31
33
  : 'SOLD OUT'
32
- const isSalesClosed = !ticketTier.salesStarted || ticketTier.salesEnded
34
+ const isSalesClosed = defineIsSalesClosed({
35
+ salesStarted: ticketTier.salesStarted,
36
+ salesEnded: ticketTier.salesEnded,
37
+ presalesStarted: event?.presalesStarted,
38
+ presalesEnded: event?.presalesEnded,
39
+ presalesEnabled: event?.presales_enabled,
40
+ })
33
41
  const maxCount = tableType ? ticketTier.maxGuests : ticketTier.maxQuantity
34
42
  const minCount = tableType ? ticketTier.minGuests : ticketTier.minQuantity
35
43
  const { multiplier } = ticketTier
@@ -48,11 +56,7 @@ export const TicketRow = ({
48
56
  <FormControl fullWidth>
49
57
  <Select
50
58
  sx={{ borderRadius: 0 }}
51
- value={
52
- selectedTickets[ticketTier.id]
53
- ? selectedTickets[ticketTier.id]
54
- : 0
55
- }
59
+ value={selectedTickets[ticketTier.id] ? selectedTickets[ticketTier.id] : 0}
56
60
  onChange={handleTicketSelect}
57
61
  displayEmpty
58
62
  inputProps={{ 'aria-label': 'Without label' }}
@@ -87,14 +91,13 @@ export const TicketRow = ({
87
91
  returnValue = soldOutMessage
88
92
  } else if (isSalesClosed) {
89
93
  returnValue = ticketsClosedMessage
90
- } else if (
91
- canPurchaseTicket &&
92
- isSeatMapAllowed &&
93
- !isDirectPurchaseAllowed
94
- ) {
94
+ } else if (canPurchaseTicket && isSeatMapAllowed && !isDirectPurchaseAllowed) {
95
95
  // Seat Map Tickets renderer logic
96
96
  returnValue = null
97
- } else if (canPurchaseTicket) {
97
+ } else if (
98
+ canPurchaseTicket ||
99
+ (canPurchaseTicket && event?.presalesStarted && !event?.presalesEnded)
100
+ ) {
98
101
  returnValue = onSaleContent
99
102
  } else if (_get(prevTicketTier, 'in_stock')) {
100
103
  returnValue = 'SOON'
@@ -97,6 +97,7 @@ export const TicketsSection = ({
97
97
  prevTicketTier={arr[i - 1]}
98
98
  selectedTickets={selectedTickets}
99
99
  handleTicketSelect={ticketSelect}
100
+ event={event}
100
101
  />
101
102
  </div>
102
103
  </div>
@@ -161,6 +162,7 @@ export const TicketsSection = ({
161
162
  selectedTickets={selectedTickets}
162
163
  handleTicketSelect={ticketSelect}
163
164
  isSeatMapAllowed={isSeatMapAllowed}
165
+ event={event}
164
166
  />
165
167
  </div>
166
168
  </div>