tf-checkout-react 1.6.6-beta.3 → 1.6.6-beta.31

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 (110) hide show
  1. package/README.md +61 -40
  2. package/dist/adapters/customFields.d.ts +1 -0
  3. package/dist/api/checkout.d.ts +1 -0
  4. package/dist/api/common.d.ts +1 -0
  5. package/dist/api/index.d.ts +1 -0
  6. package/dist/api/preRegistrationComplete.d.ts +1 -1
  7. package/dist/components/addonsContainer/AddonComponent.d.ts +5 -1
  8. package/dist/components/addonsContainer/SimpleAddonsContainer.d.ts +17 -0
  9. package/dist/components/addonsContainer/index.d.ts +5 -1
  10. package/dist/components/billing-info-container/index.d.ts +8 -1
  11. package/dist/components/billing-info-container/utils.d.ts +25 -1
  12. package/dist/components/common/DatePickerField.d.ts +7 -1
  13. package/dist/components/countdown/index.d.ts +1 -1
  14. package/dist/components/forgotPasswordModal/index.d.ts +2 -1
  15. package/dist/components/myTicketsContainer/index.d.ts +3 -2
  16. package/dist/components/orderDetailsContainer/index.d.ts +7 -1
  17. package/dist/components/paymentContainer/OrderDetails.d.ts +8 -0
  18. package/dist/components/paymentContainer/handlePayment.d.ts +15 -0
  19. package/dist/components/paymentContainer/index.d.ts +10 -5
  20. package/dist/components/preRegistration/FieldsSection.d.ts +7 -1
  21. package/dist/components/preRegistration/PreRegistrationComplete.d.ts +6 -0
  22. package/dist/components/preRegistration/constants.d.ts +2 -2
  23. package/dist/components/preRegistration/index.d.ts +6 -0
  24. package/dist/components/resetPasswordContainer/index.d.ts +2 -2
  25. package/dist/components/stripePayment/index.d.ts +18 -3
  26. package/dist/components/ticketsContainer/InfoIcon.d.ts +5 -0
  27. package/dist/components/ticketsContainer/TicketsSection.d.ts +3 -2
  28. package/dist/components/ticketsContainer/TimeSlotsSection.d.ts +25 -0
  29. package/dist/components/ticketsContainer/index.d.ts +18 -5
  30. package/dist/components/timerWidget/index.d.ts +2 -1
  31. package/dist/constants/index.d.ts +5 -0
  32. package/dist/index.d.ts +4 -1
  33. package/dist/tf-checkout-react.cjs.development.js +5196 -3599
  34. package/dist/tf-checkout-react.cjs.development.js.map +1 -1
  35. package/dist/tf-checkout-react.cjs.production.min.js +1 -1
  36. package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
  37. package/dist/tf-checkout-react.esm.js +5199 -3605
  38. package/dist/tf-checkout-react.esm.js.map +1 -1
  39. package/dist/tf-checkout-styles.css +1 -1
  40. package/dist/types/add_on.d.ts +1 -0
  41. package/dist/types/checkoutPageConfigs.d.ts +1 -1
  42. package/dist/types/order-data.d.ts +2 -1
  43. package/dist/utils/auth.d.ts +8 -0
  44. package/dist/utils/customFields.d.ts +11 -0
  45. package/dist/utils/getDomain.d.ts +1 -1
  46. package/dist/utils/index.d.ts +1 -1
  47. package/dist/utils/setConfigs.d.ts +1 -0
  48. package/package.json +3 -2
  49. package/src/adapters/customFields.ts +7 -1
  50. package/src/api/auth.ts +2 -1
  51. package/src/api/checkout.ts +8 -4
  52. package/src/api/common.ts +49 -2
  53. package/src/api/interceptors.ts +7 -23
  54. package/src/api/preRegistrationComplete.ts +1 -1
  55. package/src/api/publicRequest.ts +10 -0
  56. package/src/components/addonsContainer/AddonComponent.tsx +71 -11
  57. package/src/components/addonsContainer/SimpleAddonsContainer.tsx +388 -0
  58. package/src/components/addonsContainer/index.tsx +189 -58
  59. package/src/components/billing-info-container/index.tsx +704 -390
  60. package/src/components/billing-info-container/{utils.ts → utils.tsx} +119 -0
  61. package/src/components/common/CheckboxField/index.tsx +1 -1
  62. package/src/components/common/DatePickerField.tsx +25 -10
  63. package/src/components/common/SnackbarAlert.tsx +32 -34
  64. package/src/components/confirmationContainer/index.tsx +1 -1
  65. package/src/components/countdown/index.tsx +22 -22
  66. package/src/components/delegationsContainer/IssueComponent.tsx +2 -1
  67. package/src/components/forgotPasswordModal/index.tsx +44 -13
  68. package/src/components/loginForm/index.tsx +1 -1
  69. package/src/components/loginModal/index.tsx +2 -2
  70. package/src/components/loginModal/style.css +3 -1
  71. package/src/components/myTicketsContainer/index.tsx +13 -9
  72. package/src/components/orderDetailsContainer/index.tsx +188 -173
  73. package/src/components/paymentContainer/OrderDetails.tsx +170 -0
  74. package/src/components/paymentContainer/handlePayment.ts +86 -0
  75. package/src/components/paymentContainer/index.tsx +253 -226
  76. package/src/components/paymentContainer/style.css +113 -0
  77. package/src/components/preRegistration/FieldsSection.tsx +8 -0
  78. package/src/components/preRegistration/PreRegistrationComplete.tsx +128 -118
  79. package/src/components/preRegistration/PreRegistrationInformations.tsx +21 -15
  80. package/src/components/preRegistration/constants.tsx +10 -4
  81. package/src/components/preRegistration/index.tsx +194 -174
  82. package/src/components/registerForm/constants.tsx +3 -1
  83. package/src/components/registerForm/index.tsx +3 -3
  84. package/src/components/resetPasswordContainer/index.tsx +12 -13
  85. package/src/components/seatMapContainer/TicketsSection.tsx +2 -2
  86. package/src/components/stripePayment/index.tsx +129 -24
  87. package/src/components/ticketsContainer/InfoIcon.tsx +35 -0
  88. package/src/components/ticketsContainer/PromoCodeSection.tsx +34 -28
  89. package/src/components/ticketsContainer/TicketRow.tsx +1 -1
  90. package/src/components/ticketsContainer/TicketsSection.tsx +178 -52
  91. package/src/components/ticketsContainer/TimeSlotsSection.tsx +120 -0
  92. package/src/components/ticketsContainer/index.tsx +209 -99
  93. package/src/components/timerWidget/index.tsx +15 -3
  94. package/src/constants/index.ts +2 -0
  95. package/src/hoc/CustomFields/index.tsx +9 -1
  96. package/src/index.ts +7 -2
  97. package/src/types/add_on.ts +1 -0
  98. package/src/types/api/common.d.ts +27 -0
  99. package/src/types/api/orders.d.ts +19 -3
  100. package/src/types/api/payment.d.ts +5 -2
  101. package/src/types/api/preRegistrationComplete.d.ts +2 -2
  102. package/src/types/checkoutPageConfigs.ts +1 -1
  103. package/src/types/order-data.ts +2 -1
  104. package/src/types/pre-registration-complete.d.ts +6 -1
  105. package/src/utils/auth.ts +32 -0
  106. package/src/utils/cookies.ts +42 -11
  107. package/src/utils/customFields.ts +22 -0
  108. package/src/utils/getDomain.ts +10 -4
  109. package/src/utils/index.ts +1 -1
  110. package/src/utils/setConfigs.ts +3 -1
@@ -0,0 +1,388 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
3
+ import { CircularProgress } from '@mui/material'
4
+ import { Form, Formik } from 'formik'
5
+ import _identity from 'lodash/identity'
6
+ import _map from 'lodash/map'
7
+ import React, { useEffect, useMemo, useState } from 'react'
8
+ import { Tooltip } from 'react-tooltip'
9
+
10
+ import { getAddons, getCart } from '../../api'
11
+ import { FEES_STYLES } from '../../constants'
12
+ import { currencyNormalizerCreator } from '../../normalizers'
13
+ import { CONFIGS, createMarkup } from '../../utils'
14
+ import InfoIcon from '../ticketsContainer/InfoIcon'
15
+ import { addonsWithGroupsAdapter, cartAdapter } from './adapters'
16
+ import AddonComponent from './AddonComponent'
17
+ import { getNormalizedPrice } from './normalizers'
18
+ import {
19
+ generateSelectOptions,
20
+ getAddonSelectOptions,
21
+ getSortedAddons,
22
+ getTicketRelatedAddons,
23
+ } from './utils'
24
+
25
+ export interface ISimpleAddonContainerProps {
26
+ classNamePrefix?: string;
27
+ onGetAddonsPageInfoSuccess?: (res: any) => void;
28
+ onGetAddonsPageInfoError?: (error: any) => void;
29
+ descriptionTrigger?: 'click' | 'hover' | 'always';
30
+ addOnDataWithCustomFields: any;
31
+ configs: any;
32
+ eventId: string;
33
+ onAddOnSelect?: (id: string, value: string, addon: any) => void;
34
+ handleConfirm?: (values: any) => void;
35
+ }
36
+
37
+ export interface ObjectLiteral {
38
+ [key: string]: any;
39
+ }
40
+
41
+ export const SimpleAddonsContainer = ({
42
+ classNamePrefix = 'add_on',
43
+ onGetAddonsPageInfoSuccess = _identity,
44
+ onGetAddonsPageInfoError = _identity,
45
+ descriptionTrigger = 'click',
46
+ addOnDataWithCustomFields,
47
+ configs,
48
+ eventId,
49
+ onAddOnSelect = _identity,
50
+ handleConfirm = _identity,
51
+ }: ISimpleAddonContainerProps) => {
52
+ const [addons, setAddons] = useState<any>([])
53
+ const [addonsOptions, setAddonsOptions] = useState<any>({})
54
+ const [groupsWithSelectedVariants, setGroupsWithSelectedVariants] = useState<any>({})
55
+ const [groupsWithInitialVariantsValues, setGroupsWithInitialVariantsValues] =
56
+ useState<any>({})
57
+ const [loading, setLoading] = useState(true)
58
+
59
+ const [visibleDescription, setVisibleDescription] = useState<string | null>(null)
60
+
61
+ const handleDescriptionToggle = (ticketId: string) => {
62
+ setVisibleDescription(current => (current === ticketId ? null : ticketId))
63
+ }
64
+
65
+ useEffect(() => {
66
+ const getAddonsPageInfo = async () => {
67
+ try {
68
+ if (eventId) {
69
+ setLoading(true)
70
+
71
+ // Get choosed ticket info (id, count) from Cart request for addons options calculations
72
+ const cart = await getCart()
73
+ const { id: choosedTicketID, quantity } = cartAdapter(cart)
74
+ const choosedTicketCount = Number(quantity)
75
+
76
+ // Get and collect addons data
77
+ const addonsData = await getAddons(eventId)
78
+ const adaptedAddons = addonsWithGroupsAdapter(addonsData)
79
+ const ticketRelatedAddons = getTicketRelatedAddons(
80
+ adaptedAddons,
81
+ choosedTicketID
82
+ )
83
+ const sortedTicketAddons = getSortedAddons(ticketRelatedAddons)
84
+
85
+ setAddons(sortedTicketAddons)
86
+
87
+ // Collect addons and addon group options
88
+ const {
89
+ addonsWithOptions,
90
+ groupsWithSelectedVariantsInfo,
91
+ groupsWithVariants,
92
+ } = getAddonSelectOptions(adaptedAddons, choosedTicketCount)
93
+
94
+ setAddonsOptions(addonsWithOptions)
95
+ setGroupsWithSelectedVariants(groupsWithSelectedVariantsInfo)
96
+ setGroupsWithInitialVariantsValues(groupsWithVariants)
97
+
98
+ // Success callback props
99
+ onGetAddonsPageInfoSuccess(addonsData)
100
+ }
101
+ } catch (e) {
102
+ // Callback error props
103
+ onGetAddonsPageInfoError(e)
104
+ } finally {
105
+ setLoading(false)
106
+ }
107
+ }
108
+
109
+ getAddonsPageInfo()
110
+ }, [eventId, onGetAddonsPageInfoError, onGetAddonsPageInfoSuccess])
111
+
112
+ const recreateGroupVariantsSelectOptions = (groupId: any, changedGroupd: any) => {
113
+ const { choosedVariants, limit, selectedCount } = changedGroupd
114
+ const remainingGroupStock = limit - selectedCount
115
+ const recreatedVariantsOptions: ObjectLiteral = {}
116
+
117
+ // Regenerate variants allowed stock counts
118
+ for (const variant in choosedVariants) {
119
+ const variantId = variant
120
+ const variantCurrSelectedValue = choosedVariants[variant]
121
+ let allowedOptionCount
122
+
123
+ // Formula for regenerating
124
+ if (
125
+ remainingGroupStock >=
126
+ groupsWithInitialVariantsValues[groupId][variantId] - variantCurrSelectedValue
127
+ ) {
128
+ allowedOptionCount = groupsWithInitialVariantsValues[groupId][variantId]
129
+ } else {
130
+ allowedOptionCount = remainingGroupStock + variantCurrSelectedValue
131
+ }
132
+
133
+ recreatedVariantsOptions[variantId] = generateSelectOptions(0, allowedOptionCount)
134
+ }
135
+
136
+ setAddonsOptions((prevState: any) =>
137
+ Object.assign({}, prevState, recreatedVariantsOptions)
138
+ )
139
+ }
140
+
141
+ const onFieldChange = (id: any, value: any, addon: any) => {
142
+ // If changeableGroup exsists it means that group with limitation variant was changed
143
+ const changeableGroup = groupsWithSelectedVariants[addon.id]
144
+
145
+ if (changeableGroup) {
146
+ const currGroupId = addon.id
147
+ const currSelectedVariantId = id
148
+ const currSelectedVariantCount = Number(value)
149
+ const currSelectedVariantPrevCount =
150
+ groupsWithSelectedVariants[currGroupId].choosedVariants[currSelectedVariantId]
151
+
152
+ const currSelectedGroupCount =
153
+ changeableGroup.selectedCount +
154
+ (currSelectedVariantCount - currSelectedVariantPrevCount)
155
+
156
+ // Update Group info
157
+ const updatedGroupsWithSelectedVariants = {
158
+ ...groupsWithSelectedVariants,
159
+ [currGroupId]: {
160
+ ...groupsWithSelectedVariants[currGroupId],
161
+ selectedCount: currSelectedGroupCount,
162
+ choosedVariants: {
163
+ ...groupsWithSelectedVariants[currGroupId].choosedVariants,
164
+ [currSelectedVariantId]: currSelectedVariantCount,
165
+ },
166
+ },
167
+ }
168
+ setGroupsWithSelectedVariants(updatedGroupsWithSelectedVariants)
169
+
170
+ // Recreate Select Options for Addon Group Variants
171
+ recreateGroupVariantsSelectOptions(
172
+ currGroupId,
173
+ updatedGroupsWithSelectedVariants[currGroupId]
174
+ )
175
+ }
176
+ }
177
+
178
+ const initialValues = useMemo(() => {
179
+ const addOnsData: any = {}
180
+ if (addons?.length > 0 && addOnDataWithCustomFields?.fields?.length > 0) {
181
+ _map(addons, addon => {
182
+ _map(addOnDataWithCustomFields.fields, field => {
183
+ const { id, groupItems } = field
184
+ _map(groupItems, item => {
185
+ addOnsData[`${addon.id}-${id}-${item.name}`] = item.value
186
+ })
187
+ })
188
+ })
189
+ }
190
+
191
+ return addOnsData
192
+ }, [addons, addOnDataWithCustomFields])
193
+
194
+ if (loading) {
195
+ return (
196
+ <div className={`${classNamePrefix}_loader`}>
197
+ <CircularProgress size={50} />
198
+ </div>
199
+ )
200
+ }
201
+
202
+ if (addons?.length === 0) {
203
+ return null
204
+ }
205
+
206
+ return (
207
+ <div className={`${classNamePrefix}_container`}>
208
+ <div className={`${classNamePrefix}_block`}>
209
+ <div className={`${classNamePrefix}_line_block`}>
210
+ {addons?.length > 0 && (
211
+ <div className={`${classNamePrefix}_title`}>UPGRADES & ADD-ONS</div>
212
+ )}
213
+ </div>
214
+ {addons?.length > 0 && (
215
+ <div className={`${classNamePrefix}_subtitle`}>
216
+ PLEASE SELECT FROM THE OPTIONAL ADD-ONS BELOW
217
+ </div>
218
+ )}
219
+ <Formik
220
+ initialValues={initialValues}
221
+ onSubmit={values => {
222
+ handleConfirm(values)
223
+ }}
224
+ validate={() => {
225
+ // Real-time validation can be handled here if needed
226
+ }}
227
+ >
228
+ {({ values, errors, setFieldTouched }) => (
229
+ <Form autoComplete="off" className="form_holder">
230
+ <>
231
+ {addons.map((addon: any) => {
232
+ const price = addon.feeIncluded ? addon.price : addon.cost
233
+ const isAddonFree = Number(addon?.price) === 0
234
+
235
+ const addOnNormalizedCost = isAddonFree
236
+ ? 'FREE'
237
+ : currencyNormalizerCreator(
238
+ getNormalizedPrice(addon?.cost ?? 0),
239
+ addon.currency
240
+ )
241
+
242
+ const addonNormalizedPrice = isAddonFree
243
+ ? 'FREE'
244
+ : currencyNormalizerCreator(
245
+ getNormalizedPrice(
246
+ CONFIGS.FEES_STYLE === FEES_STYLES.DISPLAY_BOTH
247
+ ? addon?.price ?? price
248
+ : price
249
+ ),
250
+ addon.currency
251
+ )
252
+
253
+ return (
254
+ <div key={addon.id} className={`${classNamePrefix}_product_block`}>
255
+ <div className={`${classNamePrefix}_product_images`}>
256
+ {addon.imageUrl && (
257
+ <div className={`${classNamePrefix}_product_image_block`}>
258
+ <img src={addon.imageUrl} alt="No Data" />
259
+ </div>
260
+ )}
261
+ </div>
262
+ <div className={`${classNamePrefix}_product_info_block`}>
263
+ <div className={`${classNamePrefix}_product_title`}>
264
+ {addon.name}
265
+ {addon.description && descriptionTrigger !== 'always' && (
266
+ <>
267
+ <span
268
+ aria-hidden
269
+ className="info-icon"
270
+ onClick={
271
+ descriptionTrigger === 'click'
272
+ ? () => handleDescriptionToggle(addon.id)
273
+ : undefined
274
+ }
275
+ onMouseEnter={
276
+ descriptionTrigger === 'hover'
277
+ ? () => setVisibleDescription(addon.id)
278
+ : undefined
279
+ }
280
+ onMouseLeave={
281
+ descriptionTrigger === 'hover'
282
+ ? () => setVisibleDescription(null)
283
+ : undefined
284
+ }
285
+ style={{
286
+ marginLeft: 8,
287
+ cursor: 'pointer',
288
+ display: 'flex',
289
+ }}
290
+ data-tooltip-id={`tooltip-${addon.id}`}
291
+ data-tooltip-content="View Add-On info"
292
+ >
293
+ <InfoIcon size={14} />
294
+ </span>
295
+ <Tooltip id={`tooltip-${addon.id}`} place="top">
296
+ {addon.description || 'No description available'}
297
+ </Tooltip>
298
+ </>
299
+ )}
300
+ </div>
301
+ <div className={`${classNamePrefix}_product_price`}>
302
+ {CONFIGS.FEES_STYLE === FEES_STYLES.TRADITIONAL
303
+ ? addonNormalizedPrice
304
+ : addOnNormalizedCost}
305
+ {!isAddonFree &&
306
+ CONFIGS.FEES_STYLE === FEES_STYLES.TRADITIONAL && (
307
+ <span className={`${classNamePrefix}_product_fee`}>
308
+ {addon.feeIncluded ? '(incl. Fees)' : '(excl. Fees)'}
309
+ </span>
310
+ )}
311
+ {!isAddonFree &&
312
+ CONFIGS.FEES_STYLE === FEES_STYLES.DISPLAY_BOTH && (
313
+ <>
314
+ <span className={`${classNamePrefix}_product_fee`}>
315
+ {`(${addonNormalizedPrice} with fees)`}
316
+ </span>
317
+ </>
318
+ )}
319
+ </div>
320
+ </div>
321
+ {(visibleDescription === addon.id ||
322
+ descriptionTrigger === 'always') && (
323
+ <div
324
+ className={`${classNamePrefix}_product_desc`}
325
+ dangerouslySetInnerHTML={createMarkup(addon.description)}
326
+ />
327
+ )}
328
+ <div className={`${classNamePrefix}_product_select_container`}>
329
+ {addon.variants ? (
330
+ addon.variants.map((variant: any) => (
331
+ // Group Variants
332
+ <AddonComponent
333
+ key={variant.id}
334
+ data={variant}
335
+ selectOptions={addonsOptions[variant.id]}
336
+ classNamePrefix={classNamePrefix}
337
+ handleAddonChange={(id, value) => {
338
+ onAddOnSelect(id, value, addon)
339
+ onFieldChange(id, value, addon)
340
+ }}
341
+ addOnDataWithCustomFields={addOnDataWithCustomFields}
342
+ configs={configs}
343
+ values={values}
344
+ errors={errors}
345
+ />
346
+ ))
347
+ ) : (
348
+ // Simple Addon
349
+ <AddonComponent
350
+ key={addon.id}
351
+ data={addon}
352
+ selectOptions={addonsOptions[addon.id]}
353
+ classNamePrefix={classNamePrefix}
354
+ handleAddonChange={(id, value) => {
355
+ onAddOnSelect(id, value, addon)
356
+ onFieldChange(id, value, addon)
357
+
358
+ _map(addOnDataWithCustomFields.fields, fieldGroup => {
359
+ const { id, groupItems } = fieldGroup
360
+ _map(groupItems, field => {
361
+ setFieldTouched(
362
+ `${addon.id}-${id}-${field.name}`,
363
+ true,
364
+ true
365
+ )
366
+ })
367
+ })
368
+ }}
369
+ addOnDataWithCustomFields={addOnDataWithCustomFields}
370
+ configs={configs}
371
+ values={values}
372
+ errors={errors}
373
+ />
374
+ )}
375
+ </div>
376
+ </div>
377
+ )
378
+ })}
379
+ </>
380
+ </Form>
381
+ )}
382
+ </Formik>
383
+ </div>
384
+ </div>
385
+ )
386
+ }
387
+
388
+ export default SimpleAddonsContainer