tf-checkout-react 1.3.11 → 1.3.12-beta.2

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 (43) hide show
  1. package/dist/api/index.d.ts +1 -0
  2. package/dist/components/billing-info-container/index.d.ts +1 -3
  3. package/dist/components/forgotPasswordModal/index.d.ts +4 -5
  4. package/dist/components/loginForm/index.d.ts +45 -0
  5. package/dist/components/loginModal/index.d.ts +5 -43
  6. package/dist/components/preRegistration/FieldsSection.d.ts +13 -0
  7. package/dist/components/preRegistration/constants.d.ts +2 -0
  8. package/dist/components/preRegistration/index.d.ts +10 -0
  9. package/dist/components/preRegistration/utils.d.ts +9 -0
  10. package/dist/hooks/useCookieListener.d.ts +1 -0
  11. package/dist/hooks/useEventListener.d.ts +1 -0
  12. package/dist/index.d.ts +1 -0
  13. package/dist/tf-checkout-react.cjs.development.js +706 -90
  14. package/dist/tf-checkout-react.cjs.development.js.map +1 -1
  15. package/dist/tf-checkout-react.cjs.production.min.js +1 -1
  16. package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
  17. package/dist/tf-checkout-react.esm.js +707 -92
  18. package/dist/tf-checkout-react.esm.js.map +1 -1
  19. package/dist/utils/index.d.ts +1 -0
  20. package/dist/utils/replaceVarInString.d.ts +1 -0
  21. package/package.json +1 -1
  22. package/src/.DS_Store +0 -0
  23. package/src/api/index.ts +15 -0
  24. package/src/components/.DS_Store +0 -0
  25. package/src/components/billing-info-container/index.tsx +9 -8
  26. package/src/components/common/SelectField.tsx +1 -1
  27. package/src/components/common/dist/PhoneNumberField.js +96 -0
  28. package/src/components/forgotPasswordModal/index.tsx +12 -14
  29. package/src/components/loginForm/index.tsx +195 -0
  30. package/src/components/loginModal/index.tsx +39 -184
  31. package/src/components/preRegistration/FieldsSection.tsx +136 -0
  32. package/src/components/preRegistration/constants.tsx +155 -0
  33. package/src/components/preRegistration/index.tsx +219 -0
  34. package/src/components/preRegistration/utils.ts +95 -0
  35. package/src/hooks/useCookieListener.ts +32 -0
  36. package/src/hooks/useEventListener.ts +32 -0
  37. package/src/index.ts +2 -1
  38. package/src/types/api/auth.d.ts +55 -0
  39. package/src/types/api/preRegistration.d.ts +11 -0
  40. package/src/types/formFields.d.ts +30 -0
  41. package/src/utils/cookies.ts +7 -7
  42. package/src/utils/index.ts +1 -0
  43. package/src/utils/replaceVarInString.ts +9 -0
@@ -6,3 +6,4 @@ export { createCheckoutDataBodyWithDefaultHolder } from './createCheckoutDataBod
6
6
  export { setCustomCookie, getCookieByName, deleteCookieByName } from './cookies';
7
7
  export { getDomain } from './getDomain';
8
8
  export { createMarkup } from './createMarkup';
9
+ export { replaceVarInString } from './replaceVarInString';
@@ -0,0 +1 @@
1
+ export declare const replaceVarInString: (message: string | undefined, varArray: Array<string>) => string;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3.11",
2
+ "version": "1.3.12-beta.2",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
package/src/.DS_Store ADDED
Binary file
package/src/api/index.ts CHANGED
@@ -382,3 +382,18 @@ export const getCheckoutPageConfigs = async () => {
382
382
  const response = await publicRequest.get(`v1/checkout-configs`)
383
383
  return response.data
384
384
  }
385
+
386
+ export const confirmPreRegistration = async (
387
+ eventId: string | number,
388
+ data: IConfirmPreRegistrationRequestData
389
+ ) => {
390
+ const response = await publicRequest.post(
391
+ `v1/event/${eventId}/pre-registration/confirm`,
392
+ {
393
+ data: {
394
+ attributes: data,
395
+ },
396
+ }
397
+ )
398
+ return response.data
399
+ }
Binary file
@@ -35,6 +35,7 @@ import {
35
35
  import { IBillingInfoData } from '../../types'
36
36
  import {
37
37
  createCheckoutDataBodyWithDefaultHolder,
38
+ deleteCookieByName,
38
39
  getCookieByName,
39
40
  } from '../../utils'
40
41
  import { ErrorFocus } from '../../utils/formikErrorFocus'
@@ -81,8 +82,6 @@ export interface IBillingInfoPage {
81
82
  onGetStatesError?: (e: AxiosError) => void;
82
83
  onGetProfileDataSuccess?: (res: any) => void;
83
84
  onGetProfileDataError?: (e: AxiosError) => void;
84
- onAuthorizeSuccess?: () => void;
85
- onAuthorizeError?: (e: AxiosError) => void;
86
85
  onLogin?: () => void;
87
86
  onLoginSuccess?: () => void;
88
87
  onErrorClose?: () => void;
@@ -222,8 +221,6 @@ export const BillingInfoContainer = React.memo(
222
221
  onGetStatesError = _identity,
223
222
  onGetProfileDataSuccess = _identity,
224
223
  onGetProfileDataError = _identity,
225
- onAuthorizeSuccess = _identity,
226
- onAuthorizeError = _identity,
227
224
  onLogin,
228
225
  onLoginSuccess = _identity,
229
226
  isLoggedIn: pIsLoggedIn = false,
@@ -640,12 +637,18 @@ export const BillingInfoContainer = React.memo(
640
637
  } catch (e) {
641
638
  setLoading(false)
642
639
  if (axios.isAxiosError(e)) {
643
- if (e.response?.data.error === 'invalid_token') {
640
+ if (e.response?.status === 401 || e.response?.data?.error === 'invalid_token') {
644
641
  if (isWindowDefined) {
645
642
  window.localStorage.removeItem('user_data')
646
643
  window.localStorage.removeItem('access_token')
647
644
  setUserExpired(true)
648
645
  setShowModalLogin(true)
646
+ setIsLoggedIn(false)
647
+ setShowModalSignup(false)
648
+ setShowModalForgotPassword(false)
649
+ const event = new window.CustomEvent('tf-logout')
650
+ deleteCookieByName('X-TF-ECOMMERCE')
651
+ window.document.dispatchEvent(event)
649
652
  }
650
653
  }
651
654
  if (e.response?.data.message && !hideErrorsAlertSection) {
@@ -917,8 +920,6 @@ export const BillingInfoContainer = React.memo(
917
920
  }}
918
921
  alreadyHasUser={alreadyHasUser}
919
922
  userExpired={userExpired}
920
- onAuthorizeSuccess={onAuthorizeSuccess}
921
- onAuthorizeError={onAuthorizeError}
922
923
  onGetProfileDataSuccess={(data: any) => {
923
924
  fetchCart()
924
925
  onGetProfileDataSuccess(data)
@@ -954,7 +955,7 @@ export const BillingInfoContainer = React.memo(
954
955
  onClose={() => {
955
956
  setShowModalForgotPassword(false)
956
957
  }}
957
- onLogin={() => {
958
+ onLoginButtonClick={() => {
958
959
  setShowModalForgotPassword(false)
959
960
  setShowModalLogin(true)
960
961
  }}
@@ -63,7 +63,7 @@ export const SelectField = ({
63
63
  id: field.name,
64
64
  }}
65
65
  native={true}
66
- className={theme}
66
+ className={`Mui-Select ${theme}`}
67
67
  MenuProps={{ className: theme }}
68
68
  {...field}
69
69
  style={customTheme?.input}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (_) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ exports.__esModule = true;
50
+ exports.PhoneNumberField = void 0;
51
+ var TextField_1 = require("@mui/material/TextField");
52
+ var debounce_1 = require("lodash/debounce");
53
+ var get_1 = require("lodash/get");
54
+ var react_1 = require("react");
55
+ var api_1 = require("../../api");
56
+ exports.PhoneNumberField = function (_a) {
57
+ var label = _a.label, _b = _a.type, type = _b === void 0 ? 'text' : _b, field = _a.field, _c = _a.form, errors = _c.errors, setFieldError = _c.setFieldError, setStatus = _c.setStatus;
58
+ var error = get_1["default"](errors, field.name);
59
+ // eslint-disable-next-line react-hooks/exhaustive-deps
60
+ var debounceCb = react_1.useCallback(debounce_1["default"](function (cb) { return void cb(); }, 1000), []);
61
+ react_1.useEffect(function () {
62
+ var _a;
63
+ if (field.value) {
64
+ setStatus((_a = {}, _a[field.name] = true, _a));
65
+ }
66
+ debounceCb(function () { return __awaiter(void 0, void 0, void 0, function () {
67
+ var error_1, message;
68
+ var _a;
69
+ return __generator(this, function (_b) {
70
+ switch (_b.label) {
71
+ case 0:
72
+ _b.trys.push([0, 3, 4, 5]);
73
+ if (!field.value) return [3 /*break*/, 2];
74
+ return [4 /*yield*/, api_1.validatePhoneNumber(field.value)];
75
+ case 1:
76
+ _b.sent();
77
+ _b.label = 2;
78
+ case 2:
79
+ setFieldError(field.name, '');
80
+ return [3 /*break*/, 5];
81
+ case 3:
82
+ error_1 = _b.sent();
83
+ message = get_1["default"](error_1, 'response.data.message', 'Invalid phone number');
84
+ setFieldError(field.name, message);
85
+ return [3 /*break*/, 5];
86
+ case 4:
87
+ setStatus((_a = {}, _a[field.name] = false, _a));
88
+ return [7 /*endfinally*/];
89
+ case 5: return [2 /*return*/];
90
+ }
91
+ });
92
+ }); });
93
+ // eslint-disable-next-line
94
+ }, [field.value]);
95
+ return (react_1["default"].createElement(TextField_1["default"], __assign({}, field, { id: field.name, label: label, type: type, fullWidth: true, error: !!error, helperText: error, value: field.value || '', inputProps: { pattern: '[+0-9]/d+' } })));
96
+ };
@@ -1,15 +1,17 @@
1
- import React, { FC, useState } from 'react'
2
- import { Field, Form, Formik } from 'formik'
1
+ import './style.css'
2
+
3
+ import { Box, CircularProgress, Modal } from '@mui/material'
3
4
  import axios, { AxiosError } from 'axios'
4
- import { Modal, Box, CircularProgress } from '@mui/material'
5
- import { CustomField } from '../common/CustomField'
5
+ import { Field, Form, Formik } from 'formik'
6
+ import React, { FC, useState } from 'react'
6
7
  import * as Yup from 'yup'
8
+
7
9
  import { forgotPassword } from '../../api'
8
- import './style.css'
10
+ import { CustomField } from '../common/CustomField'
9
11
 
10
- interface IForgotPasswordProps {
12
+ export interface IForgotPasswordProps {
11
13
  onClose: () => void;
12
- onLogin: () => void;
14
+ onLoginButtonClick: () => void;
13
15
  onForgotPasswordSuccess: (res: any) => void;
14
16
  onForgotPasswordError: (e: AxiosError) => void;
15
17
  }
@@ -38,7 +40,7 @@ const Schema = Yup.object().shape({
38
40
 
39
41
  export const ForgotPasswordModal: FC<IForgotPasswordProps> = ({
40
42
  onClose = () => {},
41
- onLogin = () => {},
43
+ onLoginButtonClick = () => {},
42
44
  onForgotPasswordSuccess = () => {},
43
45
  onForgotPasswordError = () => {},
44
46
  }) => {
@@ -82,11 +84,7 @@ export const ForgotPasswordModal: FC<IForgotPasswordProps> = ({
82
84
  <div className="forgot-password-container">
83
85
  <div className="title">Password Reset</div>
84
86
  <div className="forgot-password-container__singleField">
85
- <Field
86
- name="email"
87
- label="Email"
88
- component={CustomField}
89
- />
87
+ <Field name="email" label="Email" component={CustomField} />
90
88
  </div>
91
89
  </div>
92
90
  <div className="forgot-password-action-button">
@@ -95,7 +93,7 @@ export const ForgotPasswordModal: FC<IForgotPasswordProps> = ({
95
93
  </button>
96
94
  </div>
97
95
  <div className="login">
98
- <span onClick={onLogin}>Back to Log In</span>
96
+ <span onClick={onLoginButtonClick}>Back to Log In</span>
99
97
  </div>
100
98
  </Form>
101
99
  )}
@@ -0,0 +1,195 @@
1
+ import axios, { AxiosError } from 'axios'
2
+ import { Field, Form, Formik } from 'formik'
3
+ import _get from 'lodash/get'
4
+ import _identity from 'lodash/identity'
5
+ import React, { FC, useState } from 'react'
6
+
7
+ import { authorize, getProfileData } from '../../api'
8
+ import {
9
+ combineValidators,
10
+ emailValidator,
11
+ requiredValidator,
12
+ } from '../../validators'
13
+ import { CustomField } from '../common'
14
+
15
+ export interface ILoginFormProps {
16
+ alreadyHasUser?: boolean;
17
+ userExpired?: boolean;
18
+
19
+ onLoginSuccess?: (res: IProfileData) => void;
20
+ onLoginError?: (e: AxiosError) => void;
21
+
22
+ onGetProfileDataSuccess?: (res: IProfileData) => void;
23
+ onGetProfileDataError?: (e: AxiosError) => void;
24
+
25
+ onForgotPasswordButtonClick?: () => void;
26
+ onSignupButtonClick?: () => void;
27
+
28
+ logo?: string;
29
+ showForgotPasswordButton?: boolean;
30
+ showSignUpButton?: boolean;
31
+ }
32
+
33
+ interface IUserData {
34
+ id: string;
35
+ firstName: string;
36
+ lastName: string;
37
+ email: string;
38
+ city?: string;
39
+ country?: string;
40
+ countryId?: string;
41
+ phone?: string;
42
+ streetAddress?: string;
43
+ state?: string;
44
+ zip?: string;
45
+ zipCode?: string;
46
+ stateId?: string;
47
+ }
48
+
49
+ export const setLoggedUserData = (data: IUserData) => ({
50
+ id: data.id,
51
+ first_name: data.firstName,
52
+ last_name: data.lastName,
53
+ email: data.email,
54
+ confirmEmail: data.email,
55
+ city: data?.city || '',
56
+ country: data?.countryId || data?.country || '',
57
+ phone: data?.phone || '',
58
+ street_address: data?.streetAddress || '',
59
+ state: data?.stateId || '',
60
+ zip: data?.zip || data?.zipCode || '',
61
+ })
62
+
63
+ export const LoginForm: FC<ILoginFormProps> = ({
64
+ alreadyHasUser = false,
65
+ userExpired = false,
66
+
67
+ onLoginSuccess = _identity,
68
+ onLoginError = _identity,
69
+
70
+ onGetProfileDataSuccess = _identity,
71
+ onGetProfileDataError = _identity,
72
+
73
+ onForgotPasswordButtonClick = _identity,
74
+ onSignupButtonClick = _identity,
75
+
76
+ logo,
77
+ showForgotPasswordButton = false,
78
+ showSignUpButton = false,
79
+ }) => {
80
+ const [error, setError] = useState('')
81
+ return (
82
+ <div>
83
+ <Formik
84
+ initialValues={{ email: '', password: '' }}
85
+ onSubmit={async ({ email, password }) => {
86
+ try {
87
+ const body = { email, password }
88
+ const authRes = await authorize(body)
89
+ let profileResponse = null
90
+ try {
91
+ profileResponse = await getProfileData()
92
+ onGetProfileDataSuccess(_get(profileResponse, 'data.data'))
93
+ } catch (e) {
94
+ if (axios.isAxiosError(e)) {
95
+ onGetProfileDataError(e)
96
+ }
97
+ return
98
+ }
99
+
100
+ const profileSpecifiedData = _get(profileResponse, 'data.data')
101
+ const profileDataObj = setLoggedUserData(profileSpecifiedData)
102
+ if (typeof window !== 'undefined') {
103
+ window.localStorage.setItem(
104
+ 'user_data',
105
+ JSON.stringify(profileDataObj)
106
+ )
107
+ const event = new window.CustomEvent('tf-login')
108
+ window.document.dispatchEvent(event)
109
+ }
110
+ onLoginSuccess(_get(authRes, 'data.data'))
111
+ } catch (e) {
112
+ if (axios.isAxiosError(e)) {
113
+ const error = e?.response?.data?.message || 'Error'
114
+ setError(error)
115
+ onLoginError(e)
116
+ } else if (e instanceof Error) {
117
+ setError(e?.message || 'Error')
118
+ }
119
+ }
120
+ }}
121
+ >
122
+ {props => (
123
+ <Form onSubmit={props.handleSubmit}>
124
+ <div className="modal-title">Login</div>
125
+ <div className="login-logo-container">
126
+ <img
127
+ className="login-logo-tff"
128
+ src={
129
+ logo ||
130
+ 'https://www.ticketfairy.com/resources/images/logo-ttf-black.svg'
131
+ }
132
+ alt="logo"
133
+ />
134
+ </div>
135
+ <div className="server_auth__error">{error}</div>
136
+ {alreadyHasUser && (
137
+ <p className="info-text-for-login">
138
+ It appears this email is already attached to an account. Please
139
+ log in here to complete your registration.
140
+ </p>
141
+ )}
142
+ {userExpired && (
143
+ <p className="info-text-for-login">
144
+ Your session has expired, please log in again.
145
+ </p>
146
+ )}
147
+ <div className="login-modal-body">
148
+ <div className="login-modal-body__email">
149
+ <Field
150
+ name="email"
151
+ label="Email"
152
+ type="email"
153
+ component={CustomField}
154
+ validate={combineValidators(
155
+ requiredValidator,
156
+ emailValidator
157
+ )}
158
+ />
159
+ </div>
160
+ <div className="login-modal-body__password">
161
+ <Field
162
+ name="password"
163
+ label="Password"
164
+ type="password"
165
+ component={CustomField}
166
+ validate={requiredValidator}
167
+ />
168
+ </div>
169
+ <div className="login-action-button">
170
+ <button type="submit">Login</button>
171
+ </div>
172
+ {showForgotPasswordButton && (
173
+ <div className="forgot-password">
174
+ <span
175
+ aria-hidden="true"
176
+ onClick={onForgotPasswordButtonClick}
177
+ >
178
+ Forgot password?
179
+ </span>
180
+ </div>
181
+ )}
182
+ {showSignUpButton && (
183
+ <div className="forgot-password">
184
+ <span aria-hidden="true" onClick={onSignupButtonClick}>
185
+ Sign up
186
+ </span>
187
+ </div>
188
+ )}
189
+ </div>
190
+ </Form>
191
+ )}
192
+ </Formik>
193
+ </div>
194
+ )
195
+ }