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.
- package/dist/api/index.d.ts +1 -0
- package/dist/api/preRegistrationComplete.d.ts +3 -0
- package/dist/components/billing-info-container/index.d.ts +1 -3
- package/dist/components/common/CopyField.d.ts +12 -0
- package/dist/components/common/CopyMessageModal.d.ts +7 -0
- package/dist/components/common/index.d.ts +1 -0
- package/dist/components/common/socials.d.ts +10 -0
- package/dist/components/confirmationContainer/index.d.ts +7 -7
- package/dist/components/confirmationContainer/social-buttons.d.ts +5 -2
- package/dist/components/forgotPasswordModal/index.d.ts +2 -3
- package/dist/components/loginForm/index.d.ts +1 -0
- package/dist/components/loginModal/index.d.ts +2 -3
- package/dist/components/preRegistration/FieldsSection.d.ts +13 -0
- package/dist/components/preRegistration/Influancers.d.ts +2 -0
- package/dist/components/preRegistration/PreRegistrationComplete.d.ts +5 -0
- package/dist/components/preRegistration/PreRegistrationInformations.d.ts +2 -0
- package/dist/components/preRegistration/Prewards.d.ts +2 -0
- package/dist/components/preRegistration/ShareOptions.d.ts +2 -0
- package/dist/components/preRegistration/constants.d.ts +2 -0
- package/dist/components/preRegistration/index.d.ts +17 -0
- package/dist/components/preRegistration/utils.d.ts +12 -0
- package/dist/components/ticketsContainer/TicketRow.d.ts +3 -2
- package/dist/components/ticketsContainer/utils.d.ts +9 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/useEventListener.d.ts +1 -0
- package/dist/hooks/useLocalStorageListener.d.ts +1 -0
- package/dist/images/instagram.svg +5 -0
- package/dist/images/spotify.svg +6 -0
- package/dist/index.d.ts +4 -1
- package/dist/tf-checkout-react.cjs.development.js +1508 -157
- package/dist/tf-checkout-react.cjs.development.js.map +1 -1
- package/dist/tf-checkout-react.cjs.production.min.js +1 -1
- package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
- package/dist/tf-checkout-react.esm.js +1509 -157
- package/dist/tf-checkout-react.esm.js.map +1 -1
- package/dist/utils/isValidNumber.d.ts +1 -0
- package/package.json +1 -1
- package/src/api/index.ts +28 -0
- package/src/api/preRegistrationComplete.ts +37 -0
- package/src/assets/images/instagram.svg +5 -0
- package/src/assets/images/spotify.svg +6 -0
- package/src/components/billing-info-container/index.tsx +1 -7
- package/src/components/common/CopyField.tsx +53 -0
- package/src/components/common/CopyMessageModal.tsx +34 -0
- package/src/components/common/NativeSelectFeild/index.tsx +1 -1
- package/src/components/common/index.tsx +1 -0
- package/src/components/common/socials.tsx +33 -0
- package/src/components/confirmationContainer/config.ts +62 -55
- package/src/components/confirmationContainer/index.tsx +11 -31
- package/src/components/confirmationContainer/social-buttons.tsx +43 -20
- package/src/components/forgotPasswordModal/index.tsx +4 -4
- package/src/components/loginForm/index.tsx +4 -0
- package/src/components/loginModal/index.tsx +5 -4
- package/src/components/preRegistration/FieldsSection.tsx +142 -0
- package/src/components/preRegistration/Influancers.tsx +34 -0
- package/src/components/preRegistration/PreRegistrationComplete.tsx +164 -0
- package/src/components/preRegistration/PreRegistrationInformations.tsx +54 -0
- package/src/components/preRegistration/Prewards.tsx +41 -0
- package/src/components/preRegistration/ShareOptions.tsx +77 -0
- package/src/components/preRegistration/constants.tsx +161 -0
- package/src/components/preRegistration/index.tsx +274 -0
- package/src/components/preRegistration/utils.ts +155 -0
- package/src/components/ticketsContainer/ReferralLogic.tsx +1 -1
- package/src/components/ticketsContainer/TicketRow.tsx +17 -14
- package/src/components/ticketsContainer/TicketsSection.tsx +2 -0
- package/src/components/ticketsContainer/index.tsx +77 -8
- package/src/components/ticketsContainer/utils.ts +30 -6
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useEventListener.ts +32 -0
- package/src/hooks/useLocalStorageListener.ts +27 -0
- package/src/index.ts +6 -2
- package/src/types/api/preRegistration.d.ts +11 -0
- package/src/types/api/preRegistrationComplete.d.ts +95 -0
- package/src/types/pre-registration-complete.d.ts +42 -0
- package/src/utils/cookies.ts +7 -7
- 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
|
-
|
|
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 =
|
|
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 (
|
|
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>
|