tf-checkout-react 1.6.6 → 1.7.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 (131) hide show
  1. package/README.md +401 -59
  2. package/dist/adapters/customFields.d.ts +1 -0
  3. package/dist/api/checkout.d.ts +2 -0
  4. package/dist/api/common.d.ts +1 -0
  5. package/dist/api/index.d.ts +2 -0
  6. package/dist/api/preRegistrationComplete.d.ts +1 -1
  7. package/dist/components/addonsContainer/AddonComponent.d.ts +6 -1
  8. package/dist/components/addonsContainer/SimpleAddonsContainer.d.ts +17 -0
  9. package/dist/components/addonsContainer/index.d.ts +6 -1
  10. package/dist/components/billing-info-container/hooks/index.d.ts +3 -0
  11. package/dist/components/billing-info-container/hooks/usePaymentContext.d.ts +5 -0
  12. package/dist/components/billing-info-container/hooks/usePaymentRedirect.d.ts +14 -0
  13. package/dist/components/billing-info-container/hooks/useStripePayment.d.ts +18 -0
  14. package/dist/components/billing-info-container/index.d.ts +13 -2
  15. package/dist/components/billing-info-container/utils.d.ts +25 -1
  16. package/dist/components/common/DatePickerField.d.ts +7 -1
  17. package/dist/components/confirmationContainer/index.d.ts +4 -1
  18. package/dist/components/countdown/index.d.ts +1 -1
  19. package/dist/components/forgotPasswordModal/index.d.ts +2 -1
  20. package/dist/components/myTicketsContainer/index.d.ts +3 -2
  21. package/dist/components/orderDetailsContainer/index.d.ts +8 -1
  22. package/dist/components/paymentContainer/OrderDetails.d.ts +9 -0
  23. package/dist/components/paymentContainer/handlePayment.d.ts +15 -0
  24. package/dist/components/paymentContainer/index.d.ts +12 -6
  25. package/dist/components/preRegistration/FieldsSection.d.ts +7 -1
  26. package/dist/components/preRegistration/PreRegistrationComplete.d.ts +6 -0
  27. package/dist/components/preRegistration/constants.d.ts +2 -2
  28. package/dist/components/preRegistration/index.d.ts +6 -0
  29. package/dist/components/resetPasswordContainer/index.d.ts +2 -2
  30. package/dist/components/ticketsContainer/InfoIcon.d.ts +5 -0
  31. package/dist/components/ticketsContainer/TicketsSection.d.ts +3 -2
  32. package/dist/components/ticketsContainer/TimeSlotsSection.d.ts +25 -0
  33. package/dist/components/ticketsContainer/index.d.ts +29 -5
  34. package/dist/components/timerWidget/index.d.ts +2 -1
  35. package/dist/constants/index.d.ts +5 -0
  36. package/dist/index.d.ts +4 -1
  37. package/dist/tf-checkout-react.cjs.development.js +11231 -9563
  38. package/dist/tf-checkout-react.cjs.development.js.map +1 -1
  39. package/dist/tf-checkout-react.cjs.production.min.js +1 -1
  40. package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
  41. package/dist/tf-checkout-react.esm.js +11194 -9529
  42. package/dist/tf-checkout-react.esm.js.map +1 -1
  43. package/dist/tf-checkout-styles.css +1 -1
  44. package/dist/types/add_on.d.ts +1 -0
  45. package/dist/types/checkoutPageConfigs.d.ts +1 -1
  46. package/dist/types/order-data.d.ts +3 -1
  47. package/dist/utils/auth.d.ts +8 -0
  48. package/dist/utils/customFields.d.ts +11 -0
  49. package/dist/utils/getDomain.d.ts +1 -1
  50. package/dist/utils/index.d.ts +1 -1
  51. package/dist/utils/setConfigs.d.ts +1 -0
  52. package/package.json +14 -8
  53. package/src/adapters/customFields.ts +7 -1
  54. package/src/api/auth.ts +2 -1
  55. package/src/api/checkout.ts +9 -4
  56. package/src/api/common.ts +49 -2
  57. package/src/api/index.ts +1 -0
  58. package/src/api/interceptors.ts +7 -23
  59. package/src/api/preRegistrationComplete.ts +1 -1
  60. package/src/api/publicRequest.ts +10 -0
  61. package/src/components/addonsContainer/AddonComponent.tsx +96 -11
  62. package/src/components/addonsContainer/SimpleAddonsContainer.tsx +420 -0
  63. package/src/components/addonsContainer/index.tsx +198 -47
  64. package/src/components/billing-info-container/hooks/index.ts +3 -0
  65. package/src/components/billing-info-container/hooks/usePaymentContext.ts +22 -0
  66. package/src/components/billing-info-container/hooks/usePaymentRedirect.ts +147 -0
  67. package/src/components/billing-info-container/hooks/useStripePayment.ts +121 -0
  68. package/src/components/billing-info-container/index.tsx +827 -406
  69. package/src/components/billing-info-container/{utils.ts → utils.tsx} +119 -0
  70. package/src/components/common/CheckboxField/index.tsx +1 -1
  71. package/src/components/common/CustomField.tsx +38 -2
  72. package/src/components/common/DatePickerField.tsx +25 -10
  73. package/src/components/common/SnackbarAlert.tsx +32 -34
  74. package/src/components/confirmationContainer/config.ts +3 -3
  75. package/src/components/confirmationContainer/index.tsx +20 -1
  76. package/src/components/confirmationContainer/social-buttons.tsx +5 -3
  77. package/src/components/confirmationContainer/style.css +9 -5
  78. package/src/components/countdown/index.tsx +22 -22
  79. package/src/components/delegationsContainer/IssueComponent.tsx +2 -1
  80. package/src/components/forgotPasswordModal/index.tsx +44 -13
  81. package/src/components/loginForm/index.tsx +1 -1
  82. package/src/components/loginModal/index.tsx +19 -27
  83. package/src/components/loginModal/style.css +3 -1
  84. package/src/components/myTicketsContainer/index.tsx +13 -9
  85. package/src/components/orderDetailsContainer/index.tsx +206 -174
  86. package/src/components/paymentContainer/OrderDetails.tsx +257 -0
  87. package/src/components/paymentContainer/handlePayment.ts +86 -0
  88. package/src/components/paymentContainer/index.tsx +299 -259
  89. package/src/components/paymentContainer/style.css +141 -0
  90. package/src/components/preRegistration/FieldsSection.tsx +8 -0
  91. package/src/components/preRegistration/PreRegistrationComplete.tsx +128 -118
  92. package/src/components/preRegistration/PreRegistrationInformations.tsx +21 -15
  93. package/src/components/preRegistration/constants.tsx +10 -4
  94. package/src/components/preRegistration/index.tsx +194 -174
  95. package/src/components/registerForm/constants.tsx +3 -1
  96. package/src/components/registerForm/index.tsx +3 -3
  97. package/src/components/registerModal/index.tsx +47 -72
  98. package/src/components/resetPasswordContainer/index.tsx +20 -14
  99. package/src/components/seatMapContainer/TicketsSection.tsx +2 -2
  100. package/src/components/signupModal/index.tsx +13 -6
  101. package/src/components/ticketResale/index.tsx +7 -0
  102. package/src/components/ticketsContainer/InfoIcon.tsx +35 -0
  103. package/src/components/ticketsContainer/PromoCodeSection.tsx +34 -28
  104. package/src/components/ticketsContainer/TicketRow.tsx +1 -1
  105. package/src/components/ticketsContainer/TicketsSection.tsx +189 -57
  106. package/src/components/ticketsContainer/TimeSlotsSection.tsx +120 -0
  107. package/src/components/ticketsContainer/index.tsx +268 -106
  108. package/src/components/timerWidget/index.tsx +15 -3
  109. package/src/constants/index.ts +2 -0
  110. package/src/env.ts +14 -6
  111. package/src/hoc/CustomFields/index.tsx +9 -1
  112. package/src/index.ts +7 -2
  113. package/src/types/add_on.ts +1 -0
  114. package/src/types/api/cart.d.ts +8 -0
  115. package/src/types/api/checkout.d.ts +58 -7
  116. package/src/types/api/common.d.ts +30 -0
  117. package/src/types/api/orders.d.ts +19 -3
  118. package/src/types/api/payment.d.ts +6 -2
  119. package/src/types/api/preRegistrationComplete.d.ts +2 -2
  120. package/src/types/checkoutPageConfigs.ts +1 -1
  121. package/src/types/order-data.ts +3 -1
  122. package/src/types/pre-registration-complete.d.ts +6 -1
  123. package/src/utils/auth.ts +32 -0
  124. package/src/utils/cookies.ts +42 -11
  125. package/src/utils/customFields.ts +22 -0
  126. package/src/utils/getDomain.ts +10 -4
  127. package/src/utils/index.ts +1 -1
  128. package/src/utils/setConfigs.ts +3 -1
  129. package/dist/components/stripePayment/index.d.ts +0 -24
  130. package/src/components/stripePayment/index.tsx +0 -281
  131. package/src/components/stripePayment/style.css +0 -60
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  /* eslint-disable max-len */
2
3
  import './style.css'
3
4
 
@@ -7,28 +8,23 @@ import CircularProgress from '@mui/material/CircularProgress'
7
8
  import Container from '@mui/material/Container'
8
9
  import { createTheme, ThemeProvider } from '@mui/material/styles'
9
10
  import { CSSProperties } from '@mui/styles'
10
- import { Elements } from '@stripe/react-stripe-js'
11
+ import { Elements, PaymentElement, useElements, useStripe } from '@stripe/react-stripe-js'
11
12
  import {
12
13
  loadStripe,
13
- StripeCardNumberElementOptions,
14
14
  StripeConstructorOptions,
15
15
  StripeElementsOptions,
16
16
  } from '@stripe/stripe-js'
17
+ import { StripePaymentElementOptions } from '@stripe/stripe-js'
17
18
  import { AxiosError } from 'axios'
18
19
  import _get from 'lodash/get'
19
20
  import _identity from 'lodash/identity'
20
21
  import _isEmpty from 'lodash/isEmpty'
21
22
  import _map from 'lodash/map'
22
23
  import { nanoid } from 'nanoid'
23
- import React, { useEffect, useState } from 'react'
24
+ import React, { useCallback, useEffect, useMemo, useState } from 'react'
24
25
 
25
- import {
26
- createPaymentPlan,
27
- getConditions,
28
- getPaymentData,
29
- handleFreeSuccess,
30
- handlePaymentSuccess,
31
- } from '../../api'
26
+ import { getConditions, getPaymentData } from '../../api'
27
+ import { FEES_STYLES } from '../../constants'
32
28
  import { usePixel } from '../../hooks/usePixel'
33
29
  import { createFixedFloatNormalizer, currencyNormalizerCreator } from '../../normalizers'
34
30
  import { IAddOn, IOrderData, IPaymentField } from '../../types'
@@ -39,24 +35,30 @@ import {
39
35
  import { CONFIGS, isBrowser } from '../../utils'
40
36
  import { getQueryVariable } from '../../utils/getQueryVariable'
41
37
  import { Checkbox, Loader } from '../common/index'
42
- import StripePayment from '../stripePayment'
43
38
  import TimerWidget from '../timerWidget'
39
+ import { handlePaymentMiddleWare } from './handlePayment'
44
40
  import { PaymentPlanSection } from './PaymentPlanSection'
45
41
 
46
- const publishableKey = CONFIGS.STRIPE_PUBLISHABLE_KEY || ''
47
-
48
- const getStripePromise = (reviewData: any) => {
49
- const stripePublishableKey =
50
- _get(reviewData, 'payment_method.stripe_publishable_key') || publishableKey
51
- const stripeAccount = _get(reviewData, 'payment_method.stripe_connected_account')
42
+ // Wrapper component to access Stripe hooks inside Elements context
43
+ const StripeWrapper = ({
44
+ options,
45
+ onStripeReady,
46
+ }: {
47
+ options?: StripePaymentElementOptions;
48
+ onStripeReady: (stripe: any, elements: any) => void;
49
+ }) => {
50
+ const stripe = useStripe()
51
+ const elements = useElements()
52
52
 
53
- const options: StripeConstructorOptions = {}
54
- if (stripeAccount) {
55
- options.stripeAccount = stripeAccount
56
- }
53
+ useEffect(() => {
54
+ if (stripe && elements) {
55
+ onStripeReady(stripe, elements)
56
+ }
57
+ }, [stripe, elements, onStripeReady])
57
58
 
58
- return loadStripe(stripePublishableKey, options)
59
+ return <PaymentElement options={options} />
59
60
  }
61
+
60
62
  export interface IPaymentPage {
61
63
  paymentFields: IPaymentField[];
62
64
  handlePayment: any;
@@ -67,19 +69,24 @@ export interface IPaymentPage {
67
69
  onGetPaymentDataSuccess: (value: any) => void;
68
70
  onGetPaymentDataError: (value: AxiosError) => void;
69
71
  onPaymentError: (value: AxiosError, slug?: string) => void;
70
- stripeCardOptions?: StripeCardNumberElementOptions;
71
- disableZipSection: boolean;
72
72
  themeOptions?: ThemeOptions & {
73
73
  input?: CSSProperties;
74
74
  checkbox?: CSSProperties;
75
75
  };
76
76
  elementsOptions?: StripeElementsOptions;
77
+ paymentElementOptions?: StripePaymentElementOptions;
77
78
  onCountdownFinish?: () => void;
78
79
  enableTimer?: boolean;
79
- enablePaymentPlan?: boolean;
80
- paymentButtonText?: string;
81
80
  paymentInfoLabel?: string;
82
81
  orderInfoLabel?: string;
82
+ displayPaymentButton?: boolean;
83
+ hidePaymentForm?: boolean;
84
+ hideFieldsBlock?: boolean;
85
+ isSinglePageCheckout?: boolean;
86
+ stripePublishableKey?: string;
87
+ stripeAccountId?: string;
88
+ onStripeReady?: (stripe: any, elements: any) => void;
89
+ enablePaymentPlan?: boolean;
83
90
  }
84
91
 
85
92
  const initialPaymentPlanConfiguration: IPaymentPlanConfig = {
@@ -107,10 +114,11 @@ const initialOrderValues: IOrderData = {
107
114
  quantity: '',
108
115
  price: '',
109
116
  total: '',
110
- currency: '',
117
+ currency: 'USD',
111
118
  guest_count: '',
112
119
  pay_now: '',
113
120
  add_ons: [] as IAddOn[],
121
+ cost: '',
114
122
  }
115
123
 
116
124
  const initialReviewValues = {
@@ -122,11 +130,15 @@ const initialReviewValues = {
122
130
  stripe_client_secret: '',
123
131
  stripe_payment_plan_enabled: false,
124
132
  stripe_payment_plan_configuration: {} as any,
133
+ stripe_publishable_key: '',
134
+ id: '',
135
+ name: '',
136
+ stripeConnectedAccount: '',
125
137
  },
126
138
  billing_info: {},
127
139
  event_details: {
128
140
  flagSeatMapAllowed: false,
129
- slug: ''
141
+ slug: '',
130
142
  },
131
143
  }
132
144
 
@@ -140,30 +152,36 @@ export const PaymentContainer = ({
140
152
  onGetPaymentDataSuccess = _identity,
141
153
  onGetPaymentDataError = _identity,
142
154
  onPaymentError = _identity,
143
- stripeCardOptions = {},
144
- disableZipSection = false,
145
155
  themeOptions,
146
156
  elementsOptions,
157
+ paymentElementOptions,
147
158
  onCountdownFinish = _identity,
148
159
  enableTimer = false,
149
- enablePaymentPlan = true,
150
- paymentButtonText,
151
160
  orderInfoLabel = 'Order Review',
152
161
  paymentInfoLabel = 'Order Confirmation',
162
+ displayPaymentButton = true,
163
+ hidePaymentForm = false,
164
+ hideFieldsBlock = false,
165
+ isSinglePageCheckout = false,
166
+ stripePublishableKey,
167
+ stripeAccountId,
168
+ onStripeReady = _identity,
169
+ enablePaymentPlan = true,
153
170
  }: IPaymentPage) => {
154
171
  const [reviewData, setReviewData] = useState(initialReviewValues)
155
172
  const [orderData, setOrderData] = useState(initialOrderValues)
156
173
  const [error, setError] = useState(null)
157
- const [showPaymentPlanSection, setShowPaymentPlanSection] = useState(false)
158
174
  const [paymentIsLoading, setPaymentIsLoading] = useState(false)
159
175
  const [paymentDataIsLoading, setPaymentDataIsLoading] = useState(true)
160
176
  const [conditions, setConditions] = useState<{ id: string, text: string }[]>([])
177
+ const [currency, setCurrency] = useState('')
178
+ const [showPaymentPlanSection, setShowPaymentPlanSection] = useState(false)
179
+
161
180
  const [paymentPlanIsAvailable, setPaymentPlanIsAvailable] = useState(false)
162
181
  const [paymentPlanConfig, setPaymentPlanConfig] = useState(
163
182
  initialPaymentPlanConfiguration
164
183
  )
165
184
  const [paymentPlanUseSavedCard, setPaymentPlanUseSavedCard] = useState(true)
166
- const [currency, setCurrency] = useState('')
167
185
 
168
186
  const showFormTitle = Boolean(formTitle)
169
187
  const showErrorText = Boolean(errorText)
@@ -171,40 +189,18 @@ export const PaymentContainer = ({
171
189
  const eventId =
172
190
  getQueryVariable('event_id') || _get(reviewData, 'cart[0].product_id') || ''
173
191
  const { hash, total } = checkoutData
174
- const isFreeTickets =
175
- (!Number(total) && !Number(orderData.total)) || !Number(orderData.pay_now)
192
+ const isFreeTickets = useMemo(
193
+ () => (!Number(total) && !Number(orderData.total)) || !Number(orderData.pay_now),
194
+ [total, orderData]
195
+ )
176
196
 
177
197
  const pageUrl = isBrowser ? window.location.href.split('?')[0] : ''
178
198
  usePixel(eventId, { page: 'review', pageUrl })
179
199
 
180
- useEffect(() => {
181
- const paymentMethod = reviewData.payment_method || {}
182
- const paymentPlanAvailable =
183
- paymentMethod.stripe_payment_plan_enabled && enablePaymentPlan
184
- setPaymentPlanIsAvailable(paymentPlanAvailable)
185
-
186
- if (paymentPlanAvailable) {
187
- const paymentPlanConfig =
188
- paymentMethod.stripe_payment_plan_configuration || initialPaymentPlanConfiguration
189
- setPaymentPlanConfig(paymentPlanConfig)
190
- setPaymentPlanUseSavedCard(!!paymentPlanConfig.saved_card?.stripe_payment_method_id)
191
- if (isBrowser) {
192
- const sessionData = window.localStorage.getItem('paymentConfiguration')
193
- const session = sessionData ? JSON.parse(sessionData) : {}
194
- if (!!session && session?.orderId == reviewData.order_details?.id) {
195
- setPaymentPlanUseSavedCard(session.paymentPlanUseSavedCard ?? false)
196
- setShowPaymentPlanSection(session.showPaymentPlanSection ?? false)
197
- }
198
- }
199
- }
200
- }, [enablePaymentPlan, reviewData])
200
+ console.log({ conditions })
201
201
 
202
202
  useEffect(() => {
203
- updateSessionInformation()
204
- }, [showPaymentPlanSection, paymentPlanUseSavedCard])
205
-
206
- useEffect(() => {
207
- (async () => {
203
+ const fetchPaymentData = async () => {
208
204
  try {
209
205
  const paymentDataResponse = await getPaymentData(hash)
210
206
  if (paymentDataResponse.success) {
@@ -220,6 +216,7 @@ export const PaymentContainer = ({
220
216
  ticketType: item?.name,
221
217
  quantity: item?.guest_count,
222
218
  price: item?.price,
219
+ cost: item?.cost,
223
220
  id: item.id,
224
221
  count: item?.quantity,
225
222
  }))
@@ -237,19 +234,37 @@ export const PaymentContainer = ({
237
234
  guest_count: order_details?.guest_count || '',
238
235
  debt: order_details?.debt || null,
239
236
  tableTypes: orderDataArray,
237
+ cost: ticket?.cost,
238
+ subtotal: order_details?.subtotal,
239
+ fees: order_details?.fees,
240
240
  }
241
241
  setOrderData(orderData)
242
242
  setCurrency(order_details?.currency)
243
243
  onGetPaymentDataSuccess(paymentDataResponse.data)
244
244
  }
245
245
  } catch (e) {
246
- setError(_get(e, 'response.data.message'))
247
- onGetPaymentDataError(e.response)
246
+ setError(_get(e, 'response.data.message', null))
247
+ onGetPaymentDataError((e as Record<string, unknown>).response as AxiosError)
248
248
  } finally {
249
249
  setPaymentDataIsLoading(false)
250
250
  }
251
- })()
252
- }, [checkoutData])
251
+ }
252
+
253
+ if (isSinglePageCheckout) {
254
+ if (!orderData?.total) {
255
+ setOrderData(current => ({ ...current, pay_now: 1, total: 1 }))
256
+ setPaymentDataIsLoading(false)
257
+ }
258
+ } else {
259
+ fetchPaymentData()
260
+ }
261
+ }, [
262
+ orderData,
263
+ hash,
264
+ isSinglePageCheckout,
265
+ onGetPaymentDataError,
266
+ onGetPaymentDataSuccess,
267
+ ])
253
268
 
254
269
  //just once
255
270
  useEffect(() => {
@@ -258,10 +273,6 @@ export const PaymentContainer = ({
258
273
  if (eventId) {
259
274
  const conditionsResponse = await getConditions(eventId)
260
275
  const conditionsInfo = conditionsResponse.data.attributes
261
- console.log(
262
- '🚀 ~ file: index.tsx:258 ~ fetchConditions ~ conditionsInfo:',
263
- conditionsResponse
264
- )
265
276
  setConditions(
266
277
  conditionsInfo
267
278
  ? conditionsInfo.map((item: { text: any }) => ({
@@ -274,60 +285,13 @@ export const PaymentContainer = ({
274
285
  }
275
286
  }
276
287
  fetchConditions()
277
- }, [])
278
-
279
- // 1. get payment data ---> v1/order/${hash}/review/ done
280
- // 2. handle payment ---> v1/order/${orderHash}/pay/
281
- // 3. redirect to confirmation page
282
- const handlePaymentMiddleWare = async (error: any, data?: object) => {
283
- try {
284
- if (error) {
285
- throw error
286
- }
287
- const {
288
- order_details: { order_hash },
289
- } = reviewData
290
-
291
- let paymentSuccessResponse
292
-
293
- if (isFreeTickets) {
294
- paymentSuccessResponse = await handleFreeSuccess(order_hash)
295
- } else if (paymentPlanIsAvailable && showPaymentPlanSection) {
296
- paymentSuccessResponse = await createPaymentPlan(
297
- order_hash,
298
- _get(data, 'paymentMethodId', '')
299
- )
300
- } else {
301
- paymentSuccessResponse = await handlePaymentSuccess(order_hash)
302
- }
288
+ }, [eventId])
303
289
 
304
- if (paymentSuccessResponse.status === 200) {
305
- handlePayment(paymentSuccessResponse)
306
- setPaymentIsLoading(false)
307
-
308
- // clear seat-map related data from localStorage
309
- localStorage.removeItem('reservationData')
310
- localStorage.removeItem(`reservationStart-${eventId}`)
311
- localStorage.removeItem('ownReservations')
312
- localStorage.removeItem('tierId')
313
-
314
- if (isBrowser) {
315
- (window as any)?.dataLayer?.push({
316
- event: 'Purchase',
317
- orderValue: orderData.total,
318
- orderCurrency: orderData.currency,
319
- orderId: orderData.id,
320
- })
321
- }
322
- }
323
- } catch (e) {
324
- setError(_get(e, 'response.data.message'))
325
- setPaymentIsLoading(false)
326
- onPaymentError(e.response || e, reviewData.event_details.slug)
290
+ const showPaymentForm = () => {
291
+ if (hidePaymentForm) {
292
+ return false
327
293
  }
328
- }
329
294
 
330
- const showPaymentForm = () => {
331
295
  let showPaymentForm = !isFreeTickets
332
296
 
333
297
  if (
@@ -340,18 +304,23 @@ export const PaymentContainer = ({
340
304
 
341
305
  return showPaymentForm
342
306
  }
343
- const updateSessionInformation = () => {
344
- if (isBrowser && !!orderData?.id) {
345
- window.localStorage.setItem(
346
- 'paymentConfiguration',
347
- JSON.stringify({
348
- paymentPlanUseSavedCard,
349
- showPaymentPlanSection,
350
- orderId: orderData?.id,
351
- })
352
- )
307
+
308
+ const getPublishableKey = () =>
309
+ stripePublishableKey || _get(reviewData, 'payment_method.stripe_publishable_key')
310
+
311
+ const getStripePromise = useCallback(() => {
312
+ const stripePublishableKey = getPublishableKey()
313
+ const stripeAccount =
314
+ stripeAccountId || _get(reviewData, 'payment_method.stripe_connected_account')
315
+
316
+ const options: StripeConstructorOptions = {}
317
+
318
+ if (stripeAccount) {
319
+ options.stripeAccount = stripeAccount
353
320
  }
354
- }
321
+
322
+ return loadStripe(stripePublishableKey, options)
323
+ }, [reviewData, stripePublishableKey])
355
324
 
356
325
  const themeMui = createTheme(themeOptions)
357
326
  const hasTableTypes = Boolean(Number(orderData.guest_count))
@@ -365,6 +334,10 @@ export const PaymentContainer = ({
365
334
  label: '',
366
335
  id: 'tableTypes',
367
336
  },
337
+ {
338
+ label: 'Add-ons',
339
+ id: 'add_ons',
340
+ },
368
341
  {
369
342
  label: 'Total (incl. fees, card processing and taxes)',
370
343
  id: 'total',
@@ -395,9 +368,51 @@ export const PaymentContainer = ({
395
368
  ]
396
369
  : paymentFields
397
370
  const isTable = orderData?.guest_count
371
+
372
+ useEffect(() => {
373
+ const paymentMethod = reviewData.payment_method || {}
374
+ console.log({
375
+ paymentMethod,
376
+ enablePaymentPlan,
377
+ })
378
+ const paymentPlanAvailable =
379
+ paymentMethod.stripe_payment_plan_enabled && enablePaymentPlan
380
+ setPaymentPlanIsAvailable(paymentPlanAvailable)
381
+
382
+ if (paymentPlanAvailable) {
383
+ const paymentPlanConfig =
384
+ paymentMethod.stripe_payment_plan_configuration || initialPaymentPlanConfiguration
385
+ setPaymentPlanConfig(paymentPlanConfig)
386
+ setPaymentPlanUseSavedCard(!!paymentPlanConfig.saved_card?.stripe_payment_method_id)
387
+ if (isBrowser) {
388
+ const sessionData = window.localStorage.getItem('paymentConfiguration')
389
+ const session = sessionData ? JSON.parse(sessionData) : {}
390
+ if (!!session && session?.orderId == reviewData.order_details?.id) {
391
+ setPaymentPlanUseSavedCard(session.paymentPlanUseSavedCard ?? false)
392
+ setShowPaymentPlanSection(session.showPaymentPlanSection ?? false)
393
+ }
394
+ }
395
+ }
396
+ }, [enablePaymentPlan, reviewData])
397
+
398
+ useEffect(() => {
399
+ if (isBrowser && !!orderData?.id) {
400
+ window.localStorage.setItem(
401
+ 'paymentConfiguration',
402
+ JSON.stringify({
403
+ paymentPlanUseSavedCard,
404
+ showPaymentPlanSection,
405
+ orderId: orderData?.id,
406
+ })
407
+ )
408
+ }
409
+ }, [showPaymentPlanSection, paymentPlanUseSavedCard, orderData?.id])
410
+
398
411
  return (
399
412
  <ThemeProvider theme={themeMui}>
400
- <div className="payment_page">
413
+ <div
414
+ className={`payment_page ${isSinglePageCheckout ? 'payment_page_single' : ''}`}
415
+ >
401
416
  {enableTimer && (
402
417
  <TimerWidget
403
418
  expires_at={_get(reviewData, 'expires_at', 0)}
@@ -405,113 +420,139 @@ export const PaymentContainer = ({
405
420
  onCountdownFinish={onCountdownFinish}
406
421
  />
407
422
  )}
408
- {error && (
409
- <Alert severity="error" onClose={onErrorClose} variant="filled">
410
- {error}
411
- </Alert>
412
- )}
423
+ {isSinglePageCheckout
424
+ ? null
425
+ : error && (
426
+ <Alert severity="error" onClose={onErrorClose} variant="filled">
427
+ {error}
428
+ </Alert>
429
+ )}
413
430
  {paymentDataIsLoading && <Loader />}
414
431
  {!paymentDataIsLoading && (
415
432
  <Container maxWidth="md">
416
433
  {showFormTitle && <h1>{isTable ? 'Get Your Tables' : formTitle}</h1>}
417
434
  <div className="order_info_text">{orderInfoLabel}</div>
418
- <div
419
- className="order_info_section"
420
- style={{ display: hasTableTypes ? 'block' : 'grid' }}
421
- >
422
- {_map(paymentFieldsData, field => {
423
- const { id, label, className = '', normalizer = _identity } = field
424
- let value = orderData[id as keyof IOrderData]
425
- let component = null
426
-
427
- if (field.id === 'add_ons' && _isEmpty(value)) {
428
- return false
429
- }
430
-
431
- if (
432
- field.id === 'total' &&
433
- paymentPlanIsAvailable &&
434
- showPaymentPlanSection
435
- ) {
436
- value = '' + paymentPlanConfig.total
437
- }
438
-
439
- if (field.id === 'tableTypes') {
440
- const valueArray = value as Array<any>
441
-
442
- component = (
443
- <div
444
- key={id}
445
- className="order_info_block"
446
- style={{
447
- display: 'flex',
448
- flexDirection: 'column',
449
- }}
450
- >
451
- {_map(valueArray, tableTypeItem => (
452
- <div
453
- key={tableTypeItem.id}
454
- style={{
455
- display: 'grid',
456
- gridTemplateColumns: '33% 33% 33%',
457
- gridColumnGap: '10%',
458
- }}
459
- >
460
- <div className="order_info_block">
461
- <div className="order_info_title">Table Type</div>
462
- <div className={`${className} order_info_text`}>
463
- {tableTypeItem.ticketType}
435
+ {!hideFieldsBlock && (
436
+ <div
437
+ className="order_info_section"
438
+ style={{ display: hasTableTypes ? 'block' : 'grid' }}
439
+ >
440
+ {_map(paymentFieldsData, field => {
441
+ const { id, label, className = '', normalizer = _identity } = field
442
+ let value = orderData[id as keyof IOrderData] || ''
443
+ let component = null
444
+
445
+ if (field.id === 'add_ons' && _isEmpty(value)) {
446
+ return false
447
+ }
448
+
449
+ if (
450
+ field.id === 'total' &&
451
+ paymentPlanIsAvailable &&
452
+ showPaymentPlanSection
453
+ ) {
454
+ value = '' + paymentPlanConfig.total
455
+ }
456
+
457
+ if (field.id === 'tableTypes') {
458
+ const valueArray = value as Array<any>
459
+
460
+ component = (
461
+ <div
462
+ key={id}
463
+ className="order_info_block"
464
+ style={{
465
+ display: 'flex',
466
+ flexDirection: 'column',
467
+ }}
468
+ >
469
+ {_map(valueArray, tableTypeItem => (
470
+ <div
471
+ key={tableTypeItem.id}
472
+ style={{
473
+ display: 'grid',
474
+ gridTemplateColumns: '33% 33% 33%',
475
+ gridColumnGap: '10%',
476
+ }}
477
+ >
478
+ <div className="order_info_block">
479
+ <div className="order_info_title">Table Type</div>
480
+ <div className={`${className} order_info_text`}>
481
+ {tableTypeItem.ticketType}
482
+ </div>
464
483
  </div>
465
- </div>
466
- <div className="order_info_block">
467
- <div className="order_info_title">Number of Tables</div>
468
- <div className={`${className} order_info_text`}>
469
- {tableTypeItem.count}
484
+ <div className="order_info_block">
485
+ <div className="order_info_title">Number of Tables</div>
486
+ <div className={`${className} order_info_text`}>
487
+ {tableTypeItem.count}
488
+ </div>
470
489
  </div>
471
- </div>
472
- <div className="order_info_block">
473
- <div className="order_info_title">Guest Count</div>
474
- <div className={`${className} order_info_text`}>
475
- {tableTypeItem.quantity}
490
+ <div className="order_info_block">
491
+ <div className="order_info_title">Guest Count</div>
492
+ <div className={`${className} order_info_text`}>
493
+ {tableTypeItem.quantity}
494
+ </div>
476
495
  </div>
477
496
  </div>
478
- </div>
479
- ))}
480
- </div>
481
- )
482
- }
483
-
484
- return (
485
- component || (
486
- <div key={id} className="order_info_block">
487
- <div className="order_info_title">{label}</div>
488
- <div className={`${className} order_info_text`}>
489
- {typeof value === 'string' || typeof value === 'number'
490
- ? normalizer(value, currency)
491
- : _map(value, item => (
492
- <div key={item.id} className="add-on-container">
493
- <span>{item.quantity}</span>
494
- <span className="add-on-x">{' x '}</span>
495
- <span>
496
- {item.groupName ? item.groupName + ' - ' : ''}
497
- </span>
498
- <span>{item.name}</span>
499
- <span>{' - '}</span>
500
- <span>
501
- {currencyNormalizerCreator(
502
- createFixedFloatNormalizer(2)(parseFloat(item.price)),
503
- currency
497
+ ))}
498
+ </div>
499
+ )
500
+ }
501
+
502
+ return (
503
+ component || (
504
+ <div key={id} className={`order_info_block ${className}`}>
505
+ <div className="order_info_title">{label}</div>
506
+ <div className={`${className} order_info_text`}>
507
+ {typeof value === 'string' || typeof value === 'number'
508
+ ? normalizer(value, currency, orderData)
509
+ : _map(value, item => (
510
+ <div>
511
+ <div key={item.id} className="add-on-container">
512
+ <span>{item.quantity}</span>
513
+ <span className="add-on-x">{' x '}</span>
514
+ <span>
515
+ {item.groupName ? item.groupName + ' - ' : ''}
516
+ </span>
517
+ <span>{item.name}</span>
518
+ <span>{' - '}</span>
519
+ <span>
520
+ {CONFIGS.FEES_STYLE === FEES_STYLES.TRADITIONAL &&
521
+ currencyNormalizerCreator(
522
+ createFixedFloatNormalizer(2)(
523
+ parseFloat(item.price)
524
+ ),
525
+ currency
526
+ ) + ' (incl. fees)'}
527
+ {CONFIGS.FEES_STYLE === FEES_STYLES.DISPLAY_BOTH &&
528
+ currencyNormalizerCreator(
529
+ createFixedFloatNormalizer(2)(
530
+ parseFloat(item.cost)
531
+ ),
532
+ currency
533
+ )}
534
+ </span>
535
+ <span className="add-on-each">{' each'}</span>
536
+ </div>
537
+ {CONFIGS.FEES_STYLE === FEES_STYLES.DISPLAY_BOTH && (
538
+ <p className="fees">
539
+ {`(${currencyNormalizerCreator(
540
+ createFixedFloatNormalizer(2)(
541
+ parseFloat(String(item.price))
542
+ ),
543
+ currency
544
+ )} with fees)`}
545
+ </p>
504
546
  )}
505
- </span>
506
- <span className="add-on-each">{' each'}</span>
507
- </div>
508
- ))}
547
+ </div>
548
+ ))}
549
+ </div>
509
550
  </div>
510
- </div>
551
+ )
511
552
  )
512
- )
513
- })}
514
- </div>
553
+ })}
554
+ </div>
555
+ )}
515
556
  {!isFreeTickets && paymentPlanIsAvailable && (
516
557
  <div className="payment_toggle">
517
558
  <Checkbox
@@ -521,7 +562,7 @@ export const PaymentContainer = ({
521
562
  </span>
522
563
  }
523
564
  required={true}
524
- onChange={(_: any) => {
565
+ onChange={() => {
525
566
  setShowPaymentPlanSection(!showPaymentPlanSection)
526
567
  }}
527
568
  checked={showPaymentPlanSection}
@@ -536,40 +577,22 @@ export const PaymentContainer = ({
536
577
  setPaymentPlanUseSavedCard={setPaymentPlanUseSavedCard}
537
578
  />
538
579
  )}
539
- {showPaymentForm() ? (
580
+ {showPaymentForm() && !!getPublishableKey() ? (
540
581
  <div className="payment_info">
541
582
  <div className="payment_info_label">{paymentInfoLabel}</div>
542
583
  {showErrorText && <p className="payment_info__error">{errorText}</p>}
543
584
  <div>
544
- <Elements
545
- stripe={getStripePromise(reviewData)}
546
- options={elementsOptions}
547
- >
548
- <StripePayment
549
- stripe_client_secret={
550
- paymentPlanIsAvailable && showPaymentPlanSection
551
- ? paymentPlanConfig.stripe_setup_intent_secret
552
- : _get(reviewData, 'payment_method.stripe_client_secret')
553
- }
554
- hasSeatMapActions={reviewData.event_details.flagSeatMapAllowed}
555
- total={orderData.guest_count ? orderData.pay_now : orderData.total}
556
- onSubmit={handlePaymentMiddleWare}
557
- error={error}
558
- orderId={orderData.id}
559
- currency={orderData.currency}
560
- billing_info={reviewData.billing_info}
561
- isLoading={paymentIsLoading}
562
- handleSetLoading={value => setPaymentIsLoading(value)}
563
- conditions={conditions}
564
- stripeCardOptions={stripeCardOptions}
565
- disableZipSection={disableZipSection}
566
- paymentButtonText={paymentButtonText}
567
- forPaymentPlan={paymentPlanIsAvailable && showPaymentPlanSection}
568
- />
569
- </Elements>
585
+ {elementsOptions && (
586
+ <Elements stripe={getStripePromise()} options={elementsOptions}>
587
+ <StripeWrapper
588
+ onStripeReady={onStripeReady}
589
+ options={paymentElementOptions}
590
+ />
591
+ </Elements>
592
+ )}
570
593
  </div>
571
594
  </div>
572
- ) : (
595
+ ) : displayPaymentButton ? (
573
596
  <div
574
597
  className={`payment_button ${
575
598
  paymentIsLoading ? 'disabled-payment-button' : ''
@@ -580,6 +603,7 @@ export const PaymentContainer = ({
580
603
  type="button"
581
604
  onClick={() => {
582
605
  setPaymentIsLoading(true)
606
+
583
607
  let data
584
608
 
585
609
  if (
@@ -593,7 +617,23 @@ export const PaymentContainer = ({
593
617
  }
594
618
  }
595
619
 
596
- handlePaymentMiddleWare(null, data)
620
+ handlePaymentMiddleWare(
621
+ data,
622
+ {},
623
+ {
624
+ reviewData,
625
+ isFreeTickets,
626
+ paymentPlanIsAvailable,
627
+ showPaymentPlanSection,
628
+ handlePayment,
629
+ setPaymentIsLoading,
630
+ setError,
631
+ orderData,
632
+ eventId,
633
+ isBrowser,
634
+ onPaymentError,
635
+ }
636
+ )
597
637
  }}
598
638
  >
599
639
  {paymentIsLoading ? (
@@ -605,7 +645,7 @@ export const PaymentContainer = ({
605
645
  )}
606
646
  </button>
607
647
  </div>
608
- )}
648
+ ) : null}
609
649
  </Container>
610
650
  )}
611
651
  </div>