tf-checkout-react 1.0.47 → 1.0.51

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 (33) hide show
  1. package/dist/components/billing-info-container/index.d.ts +1 -1
  2. package/dist/components/billing-info-container/utils.d.ts +6 -0
  3. package/dist/components/common/CheckboxField.d.ts +2 -2
  4. package/dist/components/common/CustomField.d.ts +2 -1
  5. package/dist/components/common/SelectField.d.ts +20 -0
  6. package/dist/components/paymentContainer/index.d.ts +1 -1
  7. package/dist/components/stripePayment/index.d.ts +2 -1
  8. package/dist/tf-checkout-react.cjs.development.css +2 -2
  9. package/dist/tf-checkout-react.cjs.development.js +427 -264
  10. package/dist/tf-checkout-react.cjs.development.js.map +1 -1
  11. package/dist/tf-checkout-react.cjs.production.min.js +1 -1
  12. package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
  13. package/dist/tf-checkout-react.esm.js +434 -271
  14. package/dist/tf-checkout-react.esm.js.map +1 -1
  15. package/dist/types/billing-info-data.d.ts +3 -0
  16. package/dist/utils/formikErrorFocus.d.ts +2 -0
  17. package/dist/utils/getQueryVariable.d.ts +1 -0
  18. package/package.json +1 -1
  19. package/src/.DS_Store +0 -0
  20. package/src/components/.DS_Store +0 -0
  21. package/src/components/billing-info-container/index.tsx +124 -133
  22. package/src/components/billing-info-container/style.css +4 -0
  23. package/src/components/billing-info-container/utils.ts +44 -0
  24. package/src/components/common/CheckboxField.tsx +7 -2
  25. package/src/components/common/CustomField.tsx +21 -8
  26. package/src/components/common/SelectField.tsx +89 -0
  27. package/src/components/paymentContainer/index.tsx +31 -3
  28. package/src/components/stripePayment/index.tsx +48 -19
  29. package/src/components/stripePayment/style.css +10 -0
  30. package/src/components/waitingList/index.tsx +36 -25
  31. package/src/types/billing-info-data.ts +3 -0
  32. package/src/utils/formikErrorFocus.ts +24 -0
  33. package/src/utils/getQueryVariable.ts +13 -0
@@ -7,6 +7,7 @@ export interface IGroupItem {
7
7
  required?: boolean;
8
8
  component?: ReactNode | JSX.Element | HTMLElement;
9
9
  onValidate?: (value: any) => void;
10
+ uniqueId?: string;
10
11
  [key: string]: any;
11
12
  }
12
13
  export interface IFieldData {
@@ -15,10 +16,12 @@ export interface IFieldData {
15
16
  groupLabel?: string | JSX.Element | HTMLElement;
16
17
  groupLabelClassName?: string;
17
18
  id: number;
19
+ uniqueId?: string;
18
20
  }
19
21
  export interface IBillingInfoData {
20
22
  id: number | string;
21
23
  fields: IFieldData[];
22
24
  label?: string | JSX.Element;
23
25
  labelClassName?: string;
26
+ uniqueId?: string;
24
27
  }
@@ -0,0 +1,2 @@
1
+ /// <reference types="react" />
2
+ export declare const ErrorFocus: import("react").ComponentType<{}>;
@@ -0,0 +1 @@
1
+ export declare const getQueryVariable: (variable: string) => string | false;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.47",
2
+ "version": "1.0.51",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
package/src/.DS_Store ADDED
Binary file
Binary file
@@ -26,14 +26,15 @@ import {
26
26
  register,
27
27
  setCustomHeader,
28
28
  getStates,
29
- getConditions,
30
29
  } from '../../api'
31
30
  import { LoginModal } from '../loginModal'
32
31
  import { RegisterModal } from '../registerModal'
33
32
  import {
33
+ assingUniqueIds,
34
34
  createCheckoutDataBody,
35
35
  createRegisterFormData,
36
36
  getInitialValues,
37
+ getValidateFunctions,
37
38
  setLoggedUserData,
38
39
  } from './utils'
39
40
  import { CustomField } from '../common/CustomField'
@@ -41,30 +42,20 @@ import axios from 'axios'
41
42
  import { CheckboxField } from '../common/CheckboxField'
42
43
  import { CircularProgress } from '@mui/material'
43
44
  import { nanoid } from 'nanoid'
45
+ import { getQueryVariable } from '../../utils/getQueryVariable'
46
+ import { SelectField } from '../common/SelectField'
47
+ import { ErrorFocus } from '../../utils/formikErrorFocus'
44
48
 
45
49
  // const TTFLOGO = require('./logo-ttf.png')
46
50
 
47
- const getQueryVariable = (variable: string) => {
48
- if (typeof window !== 'undefined') {
49
- const query = window.location.search.substring(1)
50
- const vars = query.split('&')
51
- for (let i = 0; i < vars.length; i++) {
52
- const pair = vars[i].split('=')
53
- if (pair[0] === variable) {
54
- return pair[1]
55
- }
56
- }
57
- }
58
- return false
59
- }
60
-
61
51
  export interface IBillingInfoPage {
62
52
  data?: IBillingInfoData[];
63
53
  ticketHoldersFields?: IBillingInfoData;
64
54
  handleSubmit?: (
65
55
  values: FormikValues,
66
56
  formikHelpers: FormikHelpers<FormikValues>,
67
- res?: any
57
+ eventId: any,
58
+ res: any
68
59
  ) => void;
69
60
 
70
61
  onRegisterSuccess?: (value: {
@@ -155,7 +146,7 @@ const LogicRunner: FC<{
155
146
  lastName: parsedData?.last_name,
156
147
  email: parsedData?.email || '',
157
148
  phone: parsedData?.phone || '',
158
- confirmEmail: '',
149
+ confirmEmail: parsedData?.email || '',
159
150
  state: parsedData?.state || '',
160
151
  street_address: parsedData?.street_address || '',
161
152
  country: parsedData?.country || 1,
@@ -177,8 +168,6 @@ const LogicRunner: FC<{
177
168
  return null
178
169
  }
179
170
 
180
- const SectionContainer: FC = ({ children }) => <>{children}</>
181
-
182
171
  export const BillingInfoContainer = ({
183
172
  data = [],
184
173
  ticketHoldersFields = {
@@ -213,6 +202,10 @@ export const BillingInfoContainer = ({
213
202
  ? window.localStorage.getItem('access_token') || ''
214
203
  : ''
215
204
 
205
+ const [dataWithUniqueIds, setDataWithUniqueIds] = useState<
206
+ IBillingInfoData[]
207
+ >(data)
208
+
216
209
  const [cartInfoData, setCartInfo] = useState<any>({})
217
210
  const [countries, setCountries] = useState<any>([])
218
211
  const [states, setStates] = useState<any>([])
@@ -221,7 +214,6 @@ export const BillingInfoContainer = ({
221
214
  const [userExpired, setUserExpired] = useState(false)
222
215
  const [showModalRegister, setShowModalRegister] = useState(false)
223
216
  const [ticketsQuantity, setTicketsQuantity] = useState<string[]>([])
224
- const [conditions, setConditions] = useState<{id: string, text: string}[]>([])
225
217
  const [userValues, setUserValues] = useState<any>({
226
218
  firstName: '',
227
219
  lastName: '',
@@ -249,7 +241,11 @@ export const BillingInfoContainer = ({
249
241
  const showTicketHolderName = getQueryVariable('names_required') === 'true'
250
242
  const eventId = getQueryVariable('event_id')
251
243
  const optedInFieldValue: boolean = _get(cartInfoData, 'optedIn', false)
252
- const hideOptIn: boolean = _get(cartInfoData, 'hide_ttf_opt_in', false)
244
+ const hideTtfOptIn: boolean = _get(cartInfoData, 'hide_ttf_opt_in', true)
245
+
246
+ if (!_get(dataWithUniqueIds, '[0].uniqueId')) {
247
+ setDataWithUniqueIds(assingUniqueIds(data))
248
+ }
253
249
 
254
250
  const getQuantity = (cart: any = []) => {
255
251
  let qty: any = 0
@@ -261,15 +257,6 @@ export const BillingInfoContainer = ({
261
257
 
262
258
  //just once
263
259
  useEffect(() => {
264
- // fetch conditions data
265
- const fetchConditions = async () => {
266
- if (eventId) {
267
- const res = await getConditions(eventId)
268
- const conditionsInfo = _get(res, 'data.data.attributes')
269
- setConditions(conditionsInfo ? conditionsInfo.map((item: string) => ({ id: nanoid(), text: item })) : [])
270
- }
271
- }
272
- fetchConditions()
273
260
  // fetch countries data
274
261
  const fetchCountries = async () => {
275
262
  try {
@@ -300,7 +287,9 @@ export const BillingInfoContainer = ({
300
287
  const cartInfo = _get(res, 'data.data.attributes')
301
288
  setCartInfo(cartInfo)
302
289
  const { cart = [] } = cartInfo
303
- setTicketsQuantity(new Array(getQuantity(cart)).fill(null).map(() => nanoid()))
290
+ setTicketsQuantity(
291
+ new Array(getQuantity(cart)).fill(null).map(() => nanoid())
292
+ )
304
293
  onGetCartSuccess(res.data)
305
294
  } catch (e) {
306
295
  if (axios.isAxiosError(e)) {
@@ -338,7 +327,7 @@ export const BillingInfoContainer = ({
338
327
  <>
339
328
  <Formik
340
329
  initialValues={getInitialValues(
341
- data,
330
+ dataWithUniqueIds,
342
331
  {
343
332
  ...initialValues,
344
333
  email: emailLogged,
@@ -371,7 +360,12 @@ export const BillingInfoContainer = ({
371
360
  showDOB
372
361
  )
373
362
  const res = await postOnCheckout(checkoutBody, access_token)
374
- handleSubmit(values, formikHelpers as FormikHelpers<any>, res)
363
+ handleSubmit(
364
+ values,
365
+ formikHelpers as FormikHelpers<any>,
366
+ eventId,
367
+ res
368
+ )
375
369
  return
376
370
  }
377
371
 
@@ -440,7 +434,12 @@ export const BillingInfoContainer = ({
440
434
  checkoutBody,
441
435
  access_token_register
442
436
  )
443
- handleSubmit(values, formikHelpers as FormikHelpers<any>, res)
437
+ handleSubmit(
438
+ values,
439
+ formikHelpers as FormikHelpers<any>,
440
+ eventId,
441
+ res
442
+ )
444
443
  } catch (e) {
445
444
  if (axios.isAxiosError(e)) {
446
445
  if (e.response?.data.error === 'invalid_token') {
@@ -458,6 +457,7 @@ export const BillingInfoContainer = ({
458
457
  >
459
458
  {(props: FormikProps<any>) => (
460
459
  <Form onSubmit={props.handleSubmit}>
460
+ <ErrorFocus />
461
461
  <LogicRunner
462
462
  values={props.values}
463
463
  setStates={setStates}
@@ -491,8 +491,8 @@ export const BillingInfoContainer = ({
491
491
  </div>
492
492
  </div>
493
493
  )}
494
- {_map(data, item => {
495
- const { id, label, labelClassName, fields } = item
494
+ {_map(dataWithUniqueIds, item => {
495
+ const { label, labelClassName, fields } = item
496
496
  if (
497
497
  label === 'Ticket Holders' &&
498
498
  !showTicketHolderName &&
@@ -501,7 +501,7 @@ export const BillingInfoContainer = ({
501
501
  return null
502
502
  }
503
503
  return (
504
- <SectionContainer key={id}>
504
+ <React.Fragment key={item.uniqueId}>
505
505
  <p className={labelClassName}>{label}</p>
506
506
  {_map(fields, group => {
507
507
  const {
@@ -511,7 +511,7 @@ export const BillingInfoContainer = ({
511
511
  groupLabelClassName,
512
512
  } = group
513
513
  return (
514
- <SectionContainer key={group.id}>
514
+ <React.Fragment key={group.uniqueId}>
515
515
  {!isLoggedIn && (
516
516
  <div className={groupLabelClassName}>
517
517
  {groupLabel}
@@ -535,7 +535,7 @@ export const BillingInfoContainer = ({
535
535
  if (el.name === 'holderAge' && !showDOB) {
536
536
  return false
537
537
  }
538
- if (el.name === 'brand_opt_in' && hideOptIn) {
538
+ if (el.name === 'ttf_opt_in' && hideTtfOptIn) {
539
539
  return false
540
540
  }
541
541
  return true
@@ -544,110 +544,101 @@ export const BillingInfoContainer = ({
544
544
  ['password', 'confirmPassword'].includes(
545
545
  element.name
546
546
  ) && isLoggedIn ? null : (
547
- <div
548
- className={element.className}
549
- key={element.name}
550
- >
551
- {element.component ? (
552
- element.component
553
- ) : (
554
- <Field
555
- name={element.name}
556
- label={element.label}
557
- type={element.type}
558
- validate={combineValidators(
559
- element.required
560
- ? requiredValidator
561
- : () => {},
562
- element.onValidate
563
- ? element.onValidate
564
- : () => {}
565
- )}
566
- component={
567
- element.type === 'checkbox'
568
- ? CheckboxField
569
- : CustomField
570
- }
571
- selectOptions={
572
- element.name === 'country'
573
- ? countries
574
- : element.name === 'state'
575
- ? states
576
- : []
577
- }
578
- />
579
- )}
580
- </div>
547
+ <React.Fragment key={element.uniqueId}>
548
+ {element.name === 'email' ? (
549
+ <div className="email-checking">
550
+ {`IMPORTANT: Please double check that your
551
+ email address is correct. It's where we
552
+ send your confirmation and e-tickets to!`}
553
+ </div>
554
+ ) : null}
555
+ <div className={element.className}>
556
+ {element.component ? (
557
+ element.component
558
+ ) : (
559
+ <Field
560
+ name={element.name}
561
+ label={element.label}
562
+ type={element.type}
563
+ validate={getValidateFunctions(
564
+ element,
565
+ states
566
+ )}
567
+ component={
568
+ element.type === 'checkbox'
569
+ ? CheckboxField
570
+ : element.type === 'select'
571
+ ? SelectField
572
+ : CustomField
573
+ }
574
+ selectOptions={
575
+ element.name === 'country'
576
+ ? countries
577
+ : element.name === 'state'
578
+ ? states
579
+ : []
580
+ }
581
+ theme={theme}
582
+ />
583
+ )}
584
+ </div>
585
+ </React.Fragment>
581
586
  )
582
587
  )}
583
588
  </div>
584
- </SectionContainer>
589
+ </React.Fragment>
585
590
  )
586
591
  })}
587
- </SectionContainer>
592
+ </React.Fragment>
588
593
  )
589
594
  })}
590
-
591
595
  {showTicketHolderName && (
592
- <>
593
- <p>{ticketHoldersFields.label}</p>
594
- {_map(ticketsQuantity, (_item, index) => (
595
- <div key={_item}>
596
- <h5>Ticket {index + 1}</h5>
597
- {_map(ticketHoldersFields.fields, group => {
598
- const { groupClassname, groupItems } = group
599
- return (
600
- <div key={group.id}>
601
- <div className={groupClassname}>
602
- {_map(groupItems, element => (
603
- <div
604
- className={element.className}
605
- key={`${element.name}-${index}`}
606
- >
607
- <Field
608
- name={`${element.name}-${index}`}
609
- key={`${element.name}-${index}`}
610
- label={element.label}
611
- type={element.type}
612
- required={true}
613
- component={
614
- element.type === 'checkbox'
615
- ? CheckboxField
616
- : CustomField
617
- }
618
- validate={combineValidators(
619
- element.required
620
- ? requiredValidator
621
- : () => {},
622
- element.onValidate
623
- ? element.onValidate
624
- : () => {}
625
- )}
626
- />
627
- </div>
628
- ))}
596
+ <React.Fragment>
597
+ <div className="ticket-holders-fields">
598
+ <p>{ticketHoldersFields.label}</p>
599
+ {_map(ticketsQuantity, (_item, index) => (
600
+ <div key={_item}>
601
+ <h5>Ticket {index + 1}</h5>
602
+ {_map(ticketHoldersFields.fields, group => {
603
+ const { groupClassname, groupItems } = group
604
+ return (
605
+ <div key={group.uniqueId}>
606
+ <div className={groupClassname}>
607
+ {_map(groupItems, element => (
608
+ <div
609
+ className={element.className}
610
+ key={element.uniqueId}
611
+ >
612
+ <Field
613
+ name={`${element.name}-${index}`}
614
+ label={element.label}
615
+ type={element.type}
616
+ required={true}
617
+ component={
618
+ element.type === 'checkbox'
619
+ ? CheckboxField
620
+ : CustomField
621
+ }
622
+ validate={combineValidators(
623
+ element.required
624
+ ? requiredValidator
625
+ : () => {},
626
+ element.onValidate
627
+ ? element.onValidate
628
+ : () => {}
629
+ )}
630
+ />
631
+ </div>
632
+ ))}
633
+ </div>
629
634
  </div>
630
- </div>
631
- )
632
- })}
633
- </div>
634
- ))}
635
- </>
636
- )}
637
- {conditions?.map(checkbox => (
638
- <div className={'billing-info-container__singleField'} key={checkbox.id}>
639
- <div className="width-fc">
640
- <Field
641
- name={checkbox.id}
642
- label={checkbox.text}
643
- type={'checkbox'}
644
- required={true}
645
- component={CheckboxField}
646
- validate={combineValidators(requiredValidator)}
647
- />
635
+ )
636
+ })}
637
+ </div>
638
+ ))}
648
639
  </div>
649
- </div>
650
- ))}
640
+ </React.Fragment>
641
+ )}
651
642
  <div className="button-container">
652
643
  <LoadingButton
653
644
  type="submit"
@@ -99,4 +99,8 @@ button {
99
99
  .billing-info-container .main-header {
100
100
  font-size: 1.5rem;
101
101
  }
102
+ }
103
+
104
+ .email-checking {
105
+ margin-bottom: 15px;
102
106
  }
@@ -1,8 +1,13 @@
1
1
  import _map from 'lodash/map'
2
+ import _get from 'lodash/get'
2
3
  import _forEach from 'lodash/forEach'
3
4
  import _flatMapDeep from 'lodash/flatMapDeep'
5
+ import _isArray from 'lodash/isArray'
4
6
 
5
7
  import { ENV } from '../../env'
8
+ import { IGroupItem } from '../../types'
9
+ import { combineValidators, requiredValidator } from '../../validators'
10
+ import { nanoid } from 'nanoid'
6
11
 
7
12
  export interface ILoggedInValues {
8
13
  emailLogged?: string;
@@ -81,6 +86,7 @@ export const setLoggedUserData = (data: IUserData) => ({
81
86
  first_name: data.firstName,
82
87
  last_name: data.lastName,
83
88
  email: data.email,
89
+ confirmEmail: data.email,
84
90
  city: data?.city || '',
85
91
  country: data?.country || '',
86
92
  phone: data?.phone || '',
@@ -150,3 +156,41 @@ export const createCheckoutDataBody = (
150
156
  }
151
157
  return body
152
158
  }
159
+
160
+ export const getValidateFunctions = (
161
+ element: IGroupItem,
162
+ states: Array<{ [key: string]: any }>
163
+ ) => {
164
+ const validationFunctions: any[] = []
165
+
166
+ if (element.required) {
167
+ if (
168
+ element.name !== 'state' ||
169
+ (element.name === 'state' && states.length)
170
+ ) {
171
+ validationFunctions.push(requiredValidator)
172
+ }
173
+ }
174
+
175
+ if (element.onValidate) {
176
+ validationFunctions.push(element.onValidate)
177
+ }
178
+
179
+ return combineValidators(...validationFunctions)
180
+ }
181
+
182
+ export const assingUniqueIds = (data: any): any => {
183
+ if (_get(data[0], 'uniqueId')) {
184
+ return data
185
+ }
186
+
187
+ return _map(data, (item: any) => {
188
+ _forEach(item, (itemValue: string, key) => {
189
+ if (_isArray(itemValue)) {
190
+ item[key] = assingUniqueIds(itemValue)
191
+ }
192
+ })
193
+
194
+ return { ...item, uniqueId: nanoid() }
195
+ })
196
+ }
@@ -6,7 +6,7 @@ import { FieldInputProps } from 'formik'
6
6
 
7
7
  export interface ICheckboxField {
8
8
  label: string | number | JSX.Element;
9
- field: FieldInputProps<any>;
9
+ field?: FieldInputProps<any>;
10
10
  }
11
11
 
12
12
  interface IOtherProps {
@@ -16,9 +16,14 @@ interface IOtherProps {
16
16
  export const CheckboxField = ({
17
17
  label,
18
18
  field,
19
+ selectOptions,
20
+ theme,
19
21
  ...rest
20
22
  }: ICheckboxField & IOtherProps) => (
21
23
  <FormGroup>
22
- <FormControlLabel control={<Checkbox {...field} {...rest} />} label={label} />
24
+ <FormControlLabel
25
+ control={<Checkbox {...field} {...rest} />}
26
+ label={label}
27
+ />
23
28
  </FormGroup>
24
29
  )
@@ -2,6 +2,7 @@ import React from 'react'
2
2
  import TextField from '@mui/material/TextField'
3
3
  import _map from 'lodash/map'
4
4
  import _get from 'lodash/get'
5
+ import _includes from 'lodash/includes'
5
6
 
6
7
  import { FieldInputProps, FormikProps } from 'formik'
7
8
  import { makeStyles } from '@mui/styles'
@@ -17,6 +18,7 @@ export interface ICustomField {
17
18
 
18
19
  field: FieldInputProps<any>;
19
20
  form: FormikProps<any>;
21
+ theme: 'dark' | 'light';
20
22
 
21
23
  // optional
22
24
  type?: string;
@@ -29,9 +31,9 @@ interface IOtherProps {
29
31
 
30
32
  const useStyles = makeStyles({
31
33
  input: {
32
- "&::placeholder": {
33
- color: "gray",
34
- }
34
+ '&::placeholder': {
35
+ color: 'gray',
36
+ },
35
37
  },
36
38
  })
37
39
 
@@ -41,11 +43,14 @@ export const CustomField = ({
41
43
  field,
42
44
  selectOptions = [] as ISelectOption[],
43
45
  form: { touched, errors },
46
+ theme,
44
47
  }: ICustomField & IOtherProps) => {
45
48
  const isSelectField = type === 'select'
46
49
  const isShrink = Boolean(field.value) || type === 'date' || type === 'select'
47
- const isTouched = Boolean(_get(touched, field.name))
48
50
  const error = _get(errors, field.name)
51
+ const isTouched =
52
+ Boolean(_get(touched, field.name)) ||
53
+ (_includes(field.name, 'holder') && !!error)
49
54
  const classes = useStyles()
50
55
 
51
56
  return (
@@ -60,15 +65,23 @@ export const CustomField = ({
60
65
  InputLabelProps={{ shrink: isShrink }}
61
66
  InputProps={{
62
67
  classes: {
63
- input: classes.input
64
- }
68
+ input: classes.input,
69
+ },
70
+ }}
71
+ SelectProps={{
72
+ native: true,
73
+ className: theme,
74
+ MenuProps: { className: theme },
65
75
  }}
66
- SelectProps={{ native: true }}
67
76
  {...field}
68
77
  >
69
78
  {isSelectField
70
79
  ? _map(selectOptions, option => (
71
- <option key={option.value} value={option.value} disabled={option.disabled}>
80
+ <option
81
+ key={option.value}
82
+ value={option.value}
83
+ disabled={option.disabled}
84
+ >
72
85
  {option.label}
73
86
  </option>
74
87
  ))