tf-checkout-react 1.0.106 → 1.2.1

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 (77) hide show
  1. package/README.md +278 -1
  2. package/dist/api/index.d.ts +40 -28
  3. package/dist/components/account-settings/index.d.ts +3 -0
  4. package/dist/components/billing-info-container/index.d.ts +11 -8
  5. package/dist/components/common/PhoneNumberField.d.ts +9 -0
  6. package/dist/components/common/index.d.ts +1 -0
  7. package/dist/components/confirmationContainer/index.d.ts +2 -1
  8. package/dist/components/countdown/index.d.ts +2 -1
  9. package/dist/components/forgotPasswordModal/index.d.ts +11 -0
  10. package/dist/components/index.d.ts +1 -0
  11. package/dist/components/loginModal/index.d.ts +35 -2
  12. package/dist/components/myTicketsContainer/index.d.ts +2 -1
  13. package/dist/components/myTicketsContainer/tableConfig.d.ts +1 -1
  14. package/dist/components/orderDetailsContainer/index.d.ts +6 -1
  15. package/dist/components/orderDetailsContainer/ticketsTable.d.ts +2 -1
  16. package/dist/components/paymentContainer/index.d.ts +2 -1
  17. package/dist/components/resetPasswordContainer/index.d.ts +10 -0
  18. package/dist/components/signupModal/index.d.ts +14 -0
  19. package/dist/components/ticketsContainer/PromoCodeSection.d.ts +3 -2
  20. package/dist/components/ticketsContainer/TicketsSection.d.ts +1 -2
  21. package/dist/components/ticketsContainer/index.d.ts +7 -3
  22. package/dist/index.d.ts +2 -0
  23. package/dist/tf-checkout-react.cjs.development.js +2177 -1482
  24. package/dist/tf-checkout-react.cjs.development.js.map +1 -1
  25. package/dist/tf-checkout-react.cjs.production.min.js +1 -1
  26. package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
  27. package/dist/tf-checkout-react.esm.js +2166 -1473
  28. package/dist/tf-checkout-react.esm.js.map +1 -1
  29. package/dist/tf-checkout-styles.css +1 -1
  30. package/dist/utils/cookies.d.ts +3 -0
  31. package/dist/utils/createCheckoutDataBodyWithDefaultHolder.d.ts +6 -1
  32. package/dist/utils/downloadPDF.d.ts +1 -1
  33. package/dist/utils/getDomain.d.ts +1 -0
  34. package/dist/utils/index.d.ts +2 -0
  35. package/package.json +12 -1
  36. package/src/api/index.ts +100 -29
  37. package/src/components/account-settings/index.tsx +161 -0
  38. package/src/components/account-settings/style.css +200 -0
  39. package/src/components/billing-info-container/index.tsx +145 -99
  40. package/src/components/billing-info-container/style.css +1 -1
  41. package/src/components/billing-info-container/utils.ts +11 -3
  42. package/src/components/common/PhoneNumberField.tsx +68 -0
  43. package/src/components/common/SnackbarAlert.tsx +1 -1
  44. package/src/components/common/dist/PhoneNumberField.js +96 -0
  45. package/src/components/common/index.tsx +1 -0
  46. package/src/components/confirmationContainer/index.tsx +19 -9
  47. package/src/components/countdown/index.tsx +3 -1
  48. package/src/components/forgotPasswordModal/index.tsx +107 -0
  49. package/src/components/forgotPasswordModal/style.css +47 -0
  50. package/src/components/index.ts +1 -0
  51. package/src/components/loginModal/index.tsx +72 -71
  52. package/src/components/myTicketsContainer/index.tsx +99 -95
  53. package/src/components/myTicketsContainer/style.css +2 -2
  54. package/src/components/myTicketsContainer/tableConfig.tsx +3 -6
  55. package/src/components/orderDetailsContainer/index.tsx +80 -21
  56. package/src/components/orderDetailsContainer/style.css +7 -3
  57. package/src/components/orderDetailsContainer/ticketsTable.tsx +130 -83
  58. package/src/components/paymentContainer/index.tsx +114 -49
  59. package/src/components/registerModal/index.tsx +3 -10
  60. package/src/components/resetPasswordContainer/index.tsx +96 -0
  61. package/src/components/resetPasswordContainer/style.css +36 -0
  62. package/src/components/signupModal/index.tsx +195 -0
  63. package/src/components/signupModal/style.css +58 -0
  64. package/src/components/stripePayment/index.tsx +14 -12
  65. package/src/components/stripePayment/style.css +3 -3
  66. package/src/components/ticketResaleModal/index.tsx +12 -14
  67. package/src/components/ticketsContainer/PromoCodeSection.tsx +8 -7
  68. package/src/components/ticketsContainer/TicketRow.tsx +12 -6
  69. package/src/components/ticketsContainer/TicketsSection.tsx +0 -3
  70. package/src/components/ticketsContainer/index.tsx +155 -86
  71. package/src/env.ts +3 -3
  72. package/src/index.ts +3 -1
  73. package/src/utils/cookies.ts +42 -0
  74. package/src/utils/createCheckoutDataBodyWithDefaultHolder.ts +16 -4
  75. package/src/utils/downloadPDF.tsx +28 -6
  76. package/src/utils/getDomain.ts +15 -0
  77. package/src/utils/index.ts +2 -0
@@ -0,0 +1,195 @@
1
+ import React, { FC, useState } from 'react'
2
+ import axios, { AxiosError } from 'axios'
3
+ import { Field, Form, Formik } from 'formik'
4
+ import { Modal, Box, CircularProgress } from '@mui/material'
5
+ import { CustomField } from '../common/CustomField'
6
+ import * as Yup from 'yup'
7
+ import _get from 'lodash/get'
8
+ import { register, handleSetAccessToken } from '../../api'
9
+ import './style.css'
10
+ import { CONFIGS } from '../../utils'
11
+
12
+ interface ISignupProps {
13
+ onClose: () => void
14
+ onLogin: () => void
15
+ onRegisterSuccess: (value: {
16
+ accessToken: string;
17
+ refreshToken: string;
18
+ }) => void
19
+ onRegisterError: (e: AxiosError, email: string) => void
20
+ }
21
+
22
+ interface ValuesTypes {
23
+ firstName: string
24
+ lastName: string
25
+ email: string
26
+ password: string
27
+ confirmPassword: string
28
+ }
29
+
30
+ const style: React.CSSProperties = {
31
+ position: 'absolute',
32
+ top: '50%',
33
+ left: '50%',
34
+ transform: 'translate(-50%, -50%)',
35
+ minWidth: 480,
36
+ backgroundColor: '#fff',
37
+ border: '1px solid white',
38
+ outline: 'none',
39
+ padding: '14px',
40
+ }
41
+
42
+ const SignupSchema = Yup.object().shape({
43
+ firstName: Yup.string().required('Required'),
44
+ lastName: Yup.string().required('Required'),
45
+ email: Yup.string()
46
+ .email('Invalid email')
47
+ .required('Required'),
48
+ password: Yup.string()
49
+ .min(6, 'Password must have 5+ characters')
50
+ .required('Required'),
51
+ confirmPassword: Yup.string()
52
+ .required('Required')
53
+ .oneOf([Yup.ref('password'), null], 'Passwords must match'),
54
+ })
55
+
56
+ export const SignupModal: FC<ISignupProps> = ({
57
+ onClose = () => {},
58
+ onLogin = () => {},
59
+ onRegisterSuccess = () => {},
60
+ onRegisterError = () => {},
61
+ }) => {
62
+ const [loading, setLoading] = useState(false)
63
+
64
+ const onSignup = async (values: ValuesTypes) => {
65
+ try {
66
+ setLoading(true)
67
+ const formData = new FormData()
68
+ formData.set('first_name', values.firstName)
69
+ formData.set('last_name', values.lastName)
70
+ formData.set('email', values.email)
71
+ formData.set('password', values.password)
72
+ formData.set('password_confirmation', values.confirmPassword)
73
+ formData.append(
74
+ 'client_id',
75
+ CONFIGS.CLIENT_ID || 'e9d8f8922797b4621e562255afe90dbf'
76
+ )
77
+ formData.append(
78
+ 'client_secret',
79
+ CONFIGS.CLIENT_SECRET || 'b89c191eff22fdcf84ac9bfd88d005355a151ec2c83b26b9'
80
+ )
81
+
82
+ const res = await register(formData)
83
+
84
+ const access_token_register = _get(
85
+ res,
86
+ 'data.data.attributes.access_token'
87
+ )
88
+ const refreshToken = _get(
89
+ res,
90
+ 'data.data.attributes.refresh_token'
91
+ )
92
+ handleSetAccessToken(access_token_register)
93
+
94
+ const tokens = {
95
+ accessToken: access_token_register,
96
+ refreshToken,
97
+ }
98
+ onRegisterSuccess(tokens)
99
+ onClose()
100
+ } catch (e) {
101
+ if (axios.isAxiosError(e)) {
102
+ onRegisterError(e, values.email)
103
+ }
104
+ } finally {
105
+ setLoading(false)
106
+ }
107
+ }
108
+
109
+ const _onClose = loading ? () => {} : onClose
110
+
111
+ return (
112
+ <Modal
113
+ open={true}
114
+ onClose={_onClose}
115
+ aria-labelledby="modal-modal-title"
116
+ aria-describedby="modal-modal-description"
117
+ className="signup-modal"
118
+ >
119
+ <Box style={style}>
120
+ <div>
121
+ <Formik
122
+ initialValues={{
123
+ firstName: '',
124
+ lastName: '',
125
+ email: '',
126
+ password: '',
127
+ confirmPassword: '',
128
+ }}
129
+ validationSchema={SignupSchema}
130
+ onSubmit={onSignup}
131
+ >
132
+ {({ isValid, dirty, handleSubmit }) => (
133
+ <Form onSubmit={handleSubmit}>
134
+ <div className="signup-container">
135
+ <div className="title">Create an Account</div>
136
+ <div className="signup-container__twoFields">
137
+ <div className="is-half">
138
+ <Field
139
+ name="firstName"
140
+ label="First Name"
141
+ component={CustomField}
142
+ />
143
+ </div>
144
+ <div className="is-half">
145
+ <Field
146
+ name="lastName"
147
+ label="Last Name"
148
+ component={CustomField}
149
+ />
150
+ </div>
151
+ </div>
152
+ <div className="signup-container__singleField">
153
+ <div className="">
154
+ <Field
155
+ name="email"
156
+ label="Email"
157
+ component={CustomField}
158
+ />
159
+ </div>
160
+ </div>
161
+ <div className="signup-container__twoFields">
162
+ <div className="is-half">
163
+ <Field
164
+ name="password"
165
+ label="Password"
166
+ type="password"
167
+ component={CustomField}
168
+ />
169
+ </div>
170
+ <div className="is-half">
171
+ <Field
172
+ name="confirmPassword"
173
+ label="Confirm Password"
174
+ type="password"
175
+ component={CustomField}
176
+ />
177
+ </div>
178
+ </div>
179
+ </div>
180
+ <div className="signup-action-button">
181
+ <button type="submit" disabled={!(isValid && dirty)}>
182
+ {loading ? <CircularProgress size="22px" /> : 'Submit'}
183
+ </button>
184
+ </div>
185
+ <div className="login">
186
+ <span onClick={onLogin}>Login</span>
187
+ </div>
188
+ </Form>
189
+ )}
190
+ </Formik>
191
+ </div>
192
+ </Box>
193
+ </Modal>
194
+ )
195
+ }
@@ -0,0 +1,58 @@
1
+ .signup-modal .signup-container {
2
+ max-width: 800px;
3
+ margin: 0 auto;
4
+ }
5
+ .signup-modal .title {
6
+ background-color: #fff;
7
+ font-family: Inter;
8
+ font-weight: 700;
9
+ font-size: 18px;
10
+ }
11
+ .signup-modal .signup-container .is-half {
12
+ width: 49%;
13
+ }
14
+ .signup-modal .signup-container__twoFields {
15
+ display: flex;
16
+ justify-content: space-between;
17
+ margin-top: 15px;
18
+ }
19
+ .signup-modal .signup-container__singleField {
20
+ margin-top: 15px;
21
+ }
22
+ .signup-modal button {
23
+ margin-top: 10px;
24
+ }
25
+ .signup-modal .signup-action-button button {
26
+ padding: 10px;
27
+ width: 100%;
28
+ margin-top: 10px;
29
+ border: none;
30
+ border-radius: 0;
31
+ height: 45px;
32
+ font-weight: 600;
33
+ font-size: 26px;
34
+ line-height: 18px;
35
+ color: white;
36
+ cursor: pointer;
37
+ outline: none;
38
+ background-color: #212529;
39
+ text-transform: uppercase;
40
+ }
41
+ .signup-modal .signup-action-button button:hover:enabled {
42
+ background-color: #505050;
43
+ border-color: #505050;
44
+ }
45
+ .signup-modal .login {
46
+ text-align: center;
47
+ margin-top: 10px;
48
+ }
49
+ .signup-modal .login span {
50
+ cursor: pointer;
51
+ }
52
+ .signup-modal .login span:hover {
53
+ text-decoration: underline;
54
+ }
55
+ .signup-modal button[disabled] {
56
+ opacity: .7;
57
+ cursor: unset;
58
+ }
@@ -189,7 +189,7 @@ const CheckoutForm = ({
189
189
  )}
190
190
  <form onSubmit={handleSubmit}>
191
191
  <div className="card_form_inner">
192
- <label className="card_number_element">
192
+ <div className="card_number_element">
193
193
  <span className="card_label_text">Card number</span>
194
194
  <CardNumberElement
195
195
  options={{ ...options, ...stripeCardOptions, }}
@@ -198,17 +198,19 @@ const CheckoutForm = ({
198
198
  onBlur={_identity}
199
199
  onFocus={_identity}
200
200
  />
201
- </label>
202
- <label className="expiration_element">
203
- <span className="card_label_text">Expiration date</span>
204
- <CardExpiryElement options={{ ...options, ...stripeCardOptions }} />
205
- </label>
206
- <label className="cvc_element">
207
- <span className="card_label_text">CVC</span>
208
- <CardCvcElement options={{ ...options, ...stripeCardOptions }} />
209
- </label>
201
+ </div>
202
+ <div className="elements">
203
+ <div className="expiration_element">
204
+ <span className="card_label_text">Expiration date</span>
205
+ <CardExpiryElement options={{ ...options, ...stripeCardOptions }} />
206
+ </div>
207
+ <div className="cvc_element">
208
+ <span className="card_label_text">CVC</span>
209
+ <CardCvcElement options={{ ...options, ...stripeCardOptions }} />
210
+ </div>
211
+ </div>
210
212
  {!disableZipSection && (
211
- <label className="zip_element">
213
+ <div className="zip_element">
212
214
  <p className="card_label_text">ZIP</p>
213
215
  <input
214
216
  type="text"
@@ -216,7 +218,7 @@ const CheckoutForm = ({
216
218
  onChange={onChangePostalCode}
217
219
  placeholder="ZIP"
218
220
  />
219
- </label>
221
+ </div>
220
222
  )}
221
223
  </div>
222
224
  {checkboxes?.map((checkbox: any) => (
@@ -34,9 +34,9 @@
34
34
  opacity: 0.7;
35
35
  }
36
36
 
37
- .disabled-payment-button button{
37
+ .disabled-payment-button button {
38
38
  user-select: none;
39
- pointer-events:none;
39
+ pointer-events: none;
40
40
  opacity: 0.3;
41
41
  }
42
42
 
@@ -57,4 +57,4 @@
57
57
  margin-top: 5px;
58
58
  color: #ffffff;
59
59
  width: 100%;
60
- }
60
+ }
@@ -177,24 +177,22 @@ export const TicketResaleModal = ({
177
177
  </div>
178
178
  )}
179
179
  </div>
180
- {
181
- ticket_type_is_active && (
182
- <div>
183
- <Field
184
- name='to'
185
- label='I will sell my ticket to anyone who wants to buy it'
186
- type='radio'
187
- value='anyone'
188
- component={RadioField}
189
- />
190
- </div>
191
- )
192
- }
180
+ {ticket_type_is_active && (
181
+ <div>
182
+ <Field
183
+ name="to"
184
+ label="I will sell my ticket to anyone who wants to buy it"
185
+ type="radio"
186
+ value="anyone"
187
+ component={RadioField}
188
+ />
189
+ </div>
190
+ )}
193
191
  <div>
194
192
  <h4>Terms of Resale</h4>
195
193
  <p>I confirm that I want to sell this ticket and that, if someone chooses to buy it, I will no longer own it or have the right to ask for it back.</p>
196
194
  <p>I also understand that, if no one chooses to buy it, it remains my property, is valid for entry to <strong>{event_name}</strong> and I will not receive any refund.</p>
197
- <p>If my ticket is sold, the original card I used to buy my ticket will be refunded with the original amount paid, minus a small handling fee of <strong>{currency + resale_fee_amount}</strong>, and that any existing refunds due to me for referring sales for this event are no longer valid.</p>
195
+ <p>If my ticket is sold, the original card I used to buy my ticket will be refunded with the original amount paid, minus a small handling fee of <strong>{`${currency || ''} ${resale_fee_amount || ''}`}</strong>, and that any existing refunds due to me for referring sales for this event are no longer valid.</p>
198
196
  <Field
199
197
  name='confirm'
200
198
  label='I agree'
@@ -9,7 +9,8 @@ export interface IPromoCodeSectionProps {
9
9
  showPromoInput: boolean;
10
10
  setCode: (value: string) => void;
11
11
  setShowPromoInput: (value: boolean) => void;
12
- updateTickets: (value: boolean) => void;
12
+ updateTickets: (value: boolean, type: string) => void;
13
+ setCodeIsApplied: (value: boolean) => void;
13
14
  }
14
15
 
15
16
  export const PromoCodeSection = ({
@@ -18,7 +19,8 @@ export const PromoCodeSection = ({
18
19
  showPromoInput,
19
20
  setCode,
20
21
  setShowPromoInput,
21
- updateTickets
22
+ updateTickets,
23
+ setCodeIsApplied
22
24
  }: IPromoCodeSectionProps) => {
23
25
  const isPromoCodeHasValue = !!code.trim()
24
26
 
@@ -26,9 +28,7 @@ export const PromoCodeSection = ({
26
28
  return (
27
29
  <div className="promo-code-block">
28
30
  <div className="promo-code-block">
29
- <p className="promo-code-text">
30
- Promo code
31
- </p>
31
+ <p className="promo-code-text">Promo code</p>
32
32
  </div>
33
33
  <input
34
34
  className="promo-code-input"
@@ -39,7 +39,7 @@ export const PromoCodeSection = ({
39
39
  onKeyPress={event => {
40
40
  if (event.key === 'Enter' && isPromoCodeHasValue) {
41
41
  setShowPromoInput(false)
42
- updateTickets(true)
42
+ updateTickets(true, 'promo')
43
43
  }
44
44
  }}
45
45
  />
@@ -48,7 +48,7 @@ export const PromoCodeSection = ({
48
48
  onClick={() => {
49
49
  if (isPromoCodeHasValue) {
50
50
  setShowPromoInput(false)
51
- updateTickets(true)
51
+ updateTickets(true, 'promo')
52
52
  }
53
53
  }}
54
54
  >
@@ -76,6 +76,7 @@ export const PromoCodeSection = ({
76
76
  className="promo-code-button"
77
77
  placeholder="Promo Codes"
78
78
  onClick={() => {
79
+ setCodeIsApplied(false)
79
80
  setShowPromoInput(true)
80
81
  }}
81
82
  >
@@ -33,7 +33,7 @@ export const TicketRow = ({
33
33
  )
34
34
  const ticketsClosedMessage = !ticketTier.salesStarted ? 'Sales not started' : 'Sales Ended'
35
35
 
36
- const onSaleContent = isSalesClosed ? ticketsClosedMessage : (
36
+ const onSaleContent = (
37
37
  <div className="get-tickets">
38
38
  <Box className="get-tickets__selectbox">
39
39
  <FormControl fullWidth>
@@ -68,14 +68,20 @@ export const TicketRow = ({
68
68
  )
69
69
 
70
70
  let returnValue: any = ''
71
+ // ticketTier.soldOut === false --> means that ticket is in the stock
72
+ const isSoldOut =
73
+ ticketTier.sold_out ||
74
+ !ticketTier.displayTicket ||
75
+ ticketTier.soldOut ||
76
+ ticketTier.soldOut === false
71
77
 
72
- if (ticketTier.sold_out || !ticketTier.displayTicket || ticketTier.soldOut) {
78
+ if (isSoldOut) {
73
79
  returnValue = soldOutMessage
74
- }
75
- if (ticketTier.displayTicket) {
80
+ } else if (isSalesClosed) {
81
+ returnValue = ticketsClosedMessage
82
+ } else if (ticketTier.displayTicket && ticketTier.maxQuantity) {
76
83
  returnValue = onSaleContent
77
- }
78
- if (_get(prevTicketTier, 'in_stock')) {
84
+ } else if (_get(prevTicketTier, 'in_stock')) {
79
85
  returnValue = 'SOON'
80
86
  }
81
87
 
@@ -8,7 +8,6 @@ interface ITicketsSectionProps {
8
8
  ticketsList: any;
9
9
  selectedTickets: any;
10
10
  handleTicketSelect: any;
11
- codeIsApplied: boolean;
12
11
  sortBySoldOut: boolean;
13
12
  ticketsHeaderComponent?: ReactNode,
14
13
  hideTicketsHeader: boolean,
@@ -18,7 +17,6 @@ export const TicketsSection = ({
18
17
  ticketsList,
19
18
  selectedTickets,
20
19
  handleTicketSelect,
21
- codeIsApplied,
22
20
  sortBySoldOut,
23
21
  ticketsHeaderComponent,
24
22
  hideTicketsHeader
@@ -40,7 +38,6 @@ export const TicketsSection = ({
40
38
  let ticketIsDiscounted = false
41
39
  if (
42
40
  ticket.oldPrice &&
43
- codeIsApplied &&
44
41
  !isSoldOut &&
45
42
  ticket.oldPrice !== ticket.price
46
43
  ) {