tf-checkout-react 1.6.6 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) 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 +26 -1
  16. package/dist/components/common/DatePickerField.d.ts +7 -1
  17. package/dist/components/common/PhoneNumberField.d.ts +1 -1
  18. package/dist/components/confirmationContainer/index.d.ts +4 -1
  19. package/dist/components/countdown/index.d.ts +1 -1
  20. package/dist/components/forgotPasswordModal/index.d.ts +2 -1
  21. package/dist/components/myTicketsContainer/index.d.ts +3 -2
  22. package/dist/components/orderDetailsContainer/index.d.ts +8 -1
  23. package/dist/components/paymentContainer/OrderDetails.d.ts +9 -0
  24. package/dist/components/paymentContainer/handlePayment.d.ts +15 -0
  25. package/dist/components/paymentContainer/index.d.ts +12 -6
  26. package/dist/components/preRegistration/FieldsSection.d.ts +7 -1
  27. package/dist/components/preRegistration/PreRegistrationComplete.d.ts +8 -0
  28. package/dist/components/preRegistration/constants.d.ts +2 -2
  29. package/dist/components/preRegistration/index.d.ts +6 -0
  30. package/dist/components/resetPasswordContainer/index.d.ts +2 -2
  31. package/dist/components/ticketsContainer/InfoIcon.d.ts +5 -0
  32. package/dist/components/ticketsContainer/TicketsSection.d.ts +3 -2
  33. package/dist/components/ticketsContainer/TimeSlotsSection.d.ts +25 -0
  34. package/dist/components/ticketsContainer/index.d.ts +29 -5
  35. package/dist/components/timerWidget/index.d.ts +2 -1
  36. package/dist/constants/index.d.ts +5 -0
  37. package/dist/index.d.ts +4 -1
  38. package/dist/tf-checkout-react.cjs.development.js +11284 -9565
  39. package/dist/tf-checkout-react.cjs.development.js.map +1 -1
  40. package/dist/tf-checkout-react.cjs.production.min.js +1 -1
  41. package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
  42. package/dist/tf-checkout-react.esm.js +11293 -9577
  43. package/dist/tf-checkout-react.esm.js.map +1 -1
  44. package/dist/tf-checkout-styles.css +1 -1
  45. package/dist/types/add_on.d.ts +1 -0
  46. package/dist/types/checkoutPageConfigs.d.ts +1 -1
  47. package/dist/types/order-data.d.ts +3 -1
  48. package/dist/utils/auth.d.ts +8 -0
  49. package/dist/utils/createCheckoutDataBodyWithDefaultHolder.d.ts +1 -0
  50. package/dist/utils/customFields.d.ts +11 -0
  51. package/dist/utils/getDomain.d.ts +1 -1
  52. package/dist/utils/index.d.ts +1 -1
  53. package/dist/utils/setConfigs.d.ts +1 -0
  54. package/package.json +14 -8
  55. package/src/adapters/customFields.ts +7 -1
  56. package/src/api/auth.ts +2 -1
  57. package/src/api/checkout.ts +9 -4
  58. package/src/api/common.ts +49 -2
  59. package/src/api/index.ts +1 -0
  60. package/src/api/interceptors.ts +7 -23
  61. package/src/api/preRegistrationComplete.ts +1 -1
  62. package/src/api/publicRequest.ts +10 -0
  63. package/src/components/addonsContainer/AddonComponent.tsx +96 -11
  64. package/src/components/addonsContainer/SimpleAddonsContainer.tsx +420 -0
  65. package/src/components/addonsContainer/index.tsx +198 -47
  66. package/src/components/billing-info-container/hooks/index.ts +3 -0
  67. package/src/components/billing-info-container/hooks/usePaymentContext.ts +22 -0
  68. package/src/components/billing-info-container/hooks/usePaymentRedirect.ts +147 -0
  69. package/src/components/billing-info-container/hooks/useStripePayment.ts +121 -0
  70. package/src/components/billing-info-container/index.tsx +859 -418
  71. package/src/components/billing-info-container/{utils.ts → utils.tsx} +124 -1
  72. package/src/components/common/CheckboxField/index.tsx +1 -1
  73. package/src/components/common/CustomField.tsx +39 -3
  74. package/src/components/common/DatePickerField.tsx +25 -10
  75. package/src/components/common/PhoneNumberField.tsx +4 -2
  76. package/src/components/common/SnackbarAlert.tsx +32 -34
  77. package/src/components/confirmationContainer/config.ts +3 -3
  78. package/src/components/confirmationContainer/index.tsx +20 -1
  79. package/src/components/confirmationContainer/social-buttons.tsx +5 -3
  80. package/src/components/confirmationContainer/style.css +9 -5
  81. package/src/components/countdown/index.tsx +22 -22
  82. package/src/components/delegationsContainer/IssueComponent.tsx +2 -1
  83. package/src/components/forgotPasswordModal/index.tsx +44 -13
  84. package/src/components/loginForm/index.tsx +1 -1
  85. package/src/components/loginModal/index.tsx +19 -27
  86. package/src/components/loginModal/style.css +3 -1
  87. package/src/components/myTicketsContainer/index.tsx +13 -9
  88. package/src/components/orderDetailsContainer/index.tsx +206 -174
  89. package/src/components/paymentContainer/OrderDetails.tsx +257 -0
  90. package/src/components/paymentContainer/handlePayment.ts +86 -0
  91. package/src/components/paymentContainer/index.tsx +299 -259
  92. package/src/components/paymentContainer/style.css +141 -0
  93. package/src/components/preRegistration/FieldsSection.tsx +8 -0
  94. package/src/components/preRegistration/PreRegistrationComplete.tsx +138 -118
  95. package/src/components/preRegistration/PreRegistrationInformations.tsx +21 -15
  96. package/src/components/preRegistration/constants.tsx +10 -4
  97. package/src/components/preRegistration/index.tsx +233 -179
  98. package/src/components/preRegistration/style.css +3 -0
  99. package/src/components/registerForm/constants.tsx +3 -1
  100. package/src/components/registerForm/index.tsx +3 -3
  101. package/src/components/registerModal/index.tsx +47 -72
  102. package/src/components/resetPasswordContainer/index.tsx +20 -14
  103. package/src/components/seatMapContainer/TicketsSection.tsx +2 -2
  104. package/src/components/signupModal/index.tsx +13 -6
  105. package/src/components/ticketResale/index.tsx +7 -0
  106. package/src/components/ticketsContainer/InfoIcon.tsx +35 -0
  107. package/src/components/ticketsContainer/PromoCodeSection.tsx +34 -28
  108. package/src/components/ticketsContainer/TicketRow.tsx +1 -1
  109. package/src/components/ticketsContainer/TicketsSection.tsx +189 -57
  110. package/src/components/ticketsContainer/TimeSlotsSection.tsx +120 -0
  111. package/src/components/ticketsContainer/index.tsx +268 -106
  112. package/src/components/timerWidget/index.tsx +15 -3
  113. package/src/components/timerWidget/style.css +2 -1
  114. package/src/constants/index.ts +2 -0
  115. package/src/env.ts +14 -6
  116. package/src/hoc/CustomFields/index.tsx +9 -1
  117. package/src/index.ts +7 -2
  118. package/src/types/add_on.ts +1 -0
  119. package/src/types/api/cart.d.ts +8 -0
  120. package/src/types/api/checkout.d.ts +58 -7
  121. package/src/types/api/common.d.ts +30 -0
  122. package/src/types/api/orders.d.ts +19 -3
  123. package/src/types/api/payment.d.ts +6 -2
  124. package/src/types/api/preRegistrationComplete.d.ts +2 -2
  125. package/src/types/checkoutPageConfigs.ts +1 -1
  126. package/src/types/order-data.ts +3 -1
  127. package/src/types/pre-registration-complete.d.ts +6 -1
  128. package/src/utils/auth.ts +32 -0
  129. package/src/utils/cookies.ts +42 -11
  130. package/src/utils/createCheckoutDataBodyWithDefaultHolder.ts +3 -1
  131. package/src/utils/customFields.ts +22 -0
  132. package/src/utils/getDomain.ts +10 -4
  133. package/src/utils/index.ts +1 -1
  134. package/src/utils/setConfigs.ts +3 -1
  135. package/dist/components/stripePayment/index.d.ts +0 -24
  136. package/src/components/stripePayment/index.tsx +0 -281
  137. package/src/components/stripePayment/style.css +0 -60
package/README.md CHANGED
@@ -3,9 +3,12 @@
3
3
   
4
4
 
5
5
  <details open>
6
- <summary><strong>Table of Contents</strong></summary>
6
+ <summary>
7
+ <strong>Table of Contents</strong>
8
+ </summary>
7
9
 
8
10
  - [tf-checkout-react](#tf-checkout-react)
11
+ - [Code style and formatting](#code-style-and-formatting)
9
12
  - [Introduction](#introduction)
10
13
  - [Intergrations](#intergrations)
11
14
  - [WebFlow](#webflow)
@@ -21,11 +24,11 @@
21
24
  - [Register](#register)
22
25
  - [Forgot Password](#forgot-password)
23
26
  - [Promo Code](#promo-code)
24
- - [__Note that package automatically calls component in `TicketsContainer`__](#note-that-package-automatically-calls-component-in-ticketscontainer)
27
+ - [**Note that package automatically calls component in `TicketsContainer`**](#note-that-package-automatically-calls-component-in-ticketscontainer)
25
28
  - [Access Code](#access-code)
26
- - [__Note that package automatically calls component in `TicketsContainer`__](#note-that-package-automatically-calls-component-in-ticketscontainer-1)
29
+ - [**Note that package automatically calls component in `TicketsContainer`**](#note-that-package-automatically-calls-component-in-ticketscontainer-1)
27
30
  - [Waiting List](#waiting-list)
28
- - [__Note that package automatically calls component in `TicketsContainer`__](#note-that-package-automatically-calls-component-in-ticketscontainer-2)
31
+ - [**Note that package automatically calls component in `TicketsContainer`**](#note-that-package-automatically-calls-component-in-ticketscontainer-2)
29
32
  - [Pixel Usage](#pixel-usage)
30
33
  - [Components](#components)
31
34
  - [`TicketsContainer`](#ticketscontainer)
@@ -38,33 +41,53 @@
38
41
  - [Order Details Container](#order-details-container)
39
42
  - [Ticket Resale Container](#ticket-resale-container)
40
43
  - [Commands](#commands)
41
- - [Rollup](#rollup)
42
- - [TypeScript](#typescript)
43
- - [GitHub Actions](#github-actions)
44
+ - [Rollup](#rollup)
45
+ - [Optimizations](#optimizations)
46
+ - [TypeScript](#typescript)
47
+ - [GitHub Actions](#github-actions)
44
48
 
45
49
  </details>
46
50
 
51
+ ## Code style and formatting
52
+
53
+ 1. **Install Prettier ESLint extension (v5.1.0)**
54
+ - VSCode: <https://marketplace.visualstudio.com/items?itemName=rvest.vs-code-prettier-eslint>
55
+ - JetBrains' products: <https://blog.jetbrains.com/webstorm/2016/08/using-external-tools/>
56
+ Notes:
57
+ - The Prettier extension is not required.
58
+ - The ESLint extension is not required. However, it is needed to have lint errors show while editing your file.
59
+ 2. **Set Prettier ESLint default formatter**
60
+
61
+ - VSCode: Open commands (CMD/Win + Stift + P) -> Format document with -> Configure default formatter
62
+ - JetBrains' products: <https://blog.jetbrains.com/webstorm/2016/08/using-external-tools/>
63
+
64
+ 3. **Enable format on save**
65
+
66
+ - VSCode: Open settings (CMD + ,) -> Search "Format On Save"
67
+ - JetBrains' products: <https://blog.jetbrains.com/webstorm/2016/08/using-external-tools/>
68
+
47
69
  &nbsp;
70
+
48
71
  # Introduction
49
72
 
50
- This package includes TicketFairy's checkout functionality, as well as various related functionalities. These functionalities include login/register, order management, resale, referrals, and more.
73
+ This package includes TicketFairy's checkout functionality, as well as various related functionalities. These functionalities include login/register, order management, resale, referrals, and more.
51
74
 
52
75
  This package provides a set of components and functionalities designed to manage various aspects of the TicketFairy event experience. These include:
53
76
 
54
77
  - `AccountSettings`: A component for managing user account settings, such as email address and password.
55
78
  - `AddonsContainter`: A component for displaying a list of available add-ons and allowing the user to purchase them.
56
- - `BillingInfoContainer`: A component for managing billing information, such as addresses and ticket holders.
79
+ - `BillingInfoContainer`: A component for managing billing information, such as addresses and ticket holders. Features enhanced field rendering, improved validation, and better user experience.
57
80
  - `ConfirmationContainer`: A component for displaying a confirmation page after a purchase is made.
58
81
  - `IDVerification`: A component for verifying the identity of the user during the checkout process.
59
82
  - `MyTicketsContainer`: A component for displaying a list of purchased orders.
60
83
  - `OrderDetailsContainer`: A component for displaying detailed information about a purchase, such as the ticket types, add-ons and pricing.
61
- - `PaymentContainer`: A component for managing payment processing during the checkout process.
84
+ - `PaymentContainer`: A component for managing payment processing during the checkout process. Includes enhanced Stripe integration, improved payment validation, and better error handling.
62
85
  - `ResetPasswordContainer`: A component for resetting a user's password.
63
86
  - `SeatMapContainer`: A component for displaying and selecting seats on a venue map.
64
87
  - `TicketResaleContainer`: A component for managing the resale of tickets or add-ons by the user.
65
- - `TicketsContainer`: A component for displaying a list of available tickets and allowing the user to purchase them.
88
+ - `TicketsContainer`: A component for displaying a list of available tickets and allowing the user to purchase them. Features optimized API calls, better state management, and enhanced user interactions.
66
89
 
67
- Together, these components and functionalities provide a comprehensive set of tools to manage the checkout process and related activities for a TicketFairy-powered event.
90
+ Together, these components and functionalities provide a comprehensive set of tools to manage the checkout process and related activities for a TicketFairy-powered event.
68
91
  &nbsp;
69
92
  &nbsp;
70
93
 
@@ -74,7 +97,6 @@ Together, these components and functionalities provide a comprehensive set of to
74
97
 
75
98
  &nbsp;
76
99
 
77
-
78
100
  # Prerequisites
79
101
 
80
102
  - node >= v16.19.0
@@ -82,13 +104,13 @@ Together, these components and functionalities provide a comprehensive set of to
82
104
 
83
105
  # Installation
84
106
 
85
- ```
107
+ ```bash
86
108
  npm i tf-checkout-react
87
109
  ```
88
110
 
89
111
  or
90
112
 
91
- ```
113
+ ```bash
92
114
  yarn add tf-checkout-react
93
115
  ```
94
116
 
@@ -107,11 +129,13 @@ Project will run under `localhost:3002`. Port can be changed from `package.json`
107
129
 
108
130
  ## Set configuration
109
131
 
110
- In order to make this package work properly, you need to set some configurations, otherwise the default configurations will be used. Currently only configuration which is needed for production, is `BASE_URL`. Other configurations written below are only for development/test environments.
132
+ In order to make this package work properly, you need to set some configurations, otherwise the default configurations will be used.
133
+ Currently only configuration which is needed for production, is `BASE_URL`.
134
+ Other configurations written below are only for development/test environments.
111
135
 
112
136
  Import `setConfigs` function from the package.
113
137
 
114
- ```
138
+ ```js
115
139
  import { setConfigs } from 'tf-checkout-react'
116
140
  ```
117
141
 
@@ -130,21 +154,298 @@ Call it in the root and pass neccesary options. Here are available options:
130
154
 
131
155
  &nbsp;
132
156
 
157
+ # Single Page Checkout Implementation
158
+
159
+ ## Overview
160
+
161
+ While the default implementation uses separate pages for each checkout step (`TicketsContainer` → `BillingInfoContainer` → `PaymentContainer` → `ConfirmationContainer`), the package also supports a **single page checkout flow** where all components are rendered on the same page with conditional visibility and state management.
162
+
163
+ ## Key Differences from Default Flow
164
+
165
+ ### **Default Multi-Page Flow:**
166
+
167
+ - Each component handles its own routing and navigation
168
+ - State is managed through URL parameters and localStorage
169
+ - Components are mounted/unmounted as user navigates
170
+ - Each step is a separate page/route
171
+
172
+ ### **Single Page Flow:**
173
+
174
+ - All components are conditionally rendered on the same page
175
+ - State management requires careful coordination between components
176
+ - Components remain mounted but visibility is controlled
177
+ - Navigation is handled through state changes rather than routing
178
+
179
+ ## Implementation Patterns
180
+
181
+ ### **1. State Management**
182
+
183
+ ```jsx
184
+ import React, { useState } from 'react'
185
+ import {
186
+ TicketsContainer,
187
+ BillingInfoContainer,
188
+ PaymentContainer,
189
+ ConfirmationContainer
190
+ } from 'tf-checkout-react'
191
+
192
+ const SinglePageCheckout = () => {
193
+ const [currentStep, setCurrentStep] = useState('tickets')
194
+ const [checkoutData, setCheckoutData] = useState({})
195
+ const [cartData, setCartData] = useState(null)
196
+
197
+ const handleTicketsSuccess = (data) => {
198
+ setCartData(data)
199
+ setCurrentStep('billing')
200
+ }
201
+
202
+ const handleBillingSuccess = (data) => {
203
+ setCheckoutData(prev => ({ ...prev, billing: data }))
204
+ setCurrentStep('payment')
205
+ }
206
+
207
+ const handlePaymentSuccess = (data) => {
208
+ setCheckoutData(prev => ({ ...prev, payment: data }))
209
+ setCurrentStep('confirmation')
210
+ }
211
+
212
+ return (
213
+ <div className="single-page-checkout">
214
+ {currentStep === 'tickets' && (
215
+ <TicketsContainer
216
+ eventId={eventId}
217
+ onAddToCartSuccess={handleTicketsSuccess}
218
+ // Disable auto-navigation
219
+ enableBillingInfoAutoCreate={false}
220
+ />
221
+ )}
222
+
223
+ {currentStep === 'billing' && (
224
+ <BillingInfoContainer
225
+ handleSubmit={handleBillingSuccess}
226
+ // Skip automatic payment redirect
227
+ skipPage={false}
228
+ />
229
+ )}
230
+
231
+ {currentStep === 'payment' && (
232
+ <PaymentContainer
233
+ checkoutData={checkoutData}
234
+ handlePayment={handlePaymentSuccess}
235
+ />
236
+ )}
237
+
238
+ {currentStep === 'confirmation' && (
239
+ <ConfirmationContainer
240
+ orderHash={checkoutData.payment?.orderHash}
241
+ />
242
+ )}
243
+ </div>
244
+ )
245
+ }
246
+ ```
247
+
248
+ ### **2. Progressive Enhancement Pattern**
249
+
250
+ ```jsx
251
+ const ProgressiveCheckout = () => {
252
+ const [completedSteps, setCompletedSteps] = useState(new Set())
253
+ const [activeStep, setActiveStep] = useState('tickets')
254
+
255
+ const markStepComplete = (step) => {
256
+ setCompletedSteps(prev => new Set([...prev, step]))
257
+ }
258
+
259
+ const isStepAccessible = (step) => {
260
+ const stepOrder = ['tickets', 'billing', 'payment', 'confirmation']
261
+ const stepIndex = stepOrder.indexOf(step)
262
+ const prevStep = stepOrder[stepIndex - 1]
263
+ return stepIndex === 0 || completedSteps.has(prevStep)
264
+ }
265
+
266
+ return (
267
+ <div className="progressive-checkout">
268
+ {/* Step Navigation */}
269
+ <div className="checkout-steps">
270
+ {['tickets', 'billing', 'payment', 'confirmation'].map(step => (
271
+ <button
272
+ key={step}
273
+ disabled={!isStepAccessible(step)}
274
+ className={`step ${activeStep === step ? 'active' : ''} ${completedSteps.has(step) ? 'completed' : ''}`}
275
+ onClick={() => setActiveStep(step)}
276
+ >
277
+ {step.charAt(0).toUpperCase() + step.slice(1)}
278
+ </button>
279
+ ))}
280
+ </div>
281
+
282
+ {/* Component Rendering */}
283
+ <div className="checkout-content">
284
+ {activeStep === 'tickets' && (
285
+ <TicketsContainer
286
+ onAddToCartSuccess={(data) => {
287
+ markStepComplete('tickets')
288
+ setActiveStep('billing')
289
+ }}
290
+ />
291
+ )}
292
+ {/* ... other components */}
293
+ </div>
294
+ </div>
295
+ )
296
+ }
297
+ ```
298
+
299
+ ### **3. Accordion/Collapsible Pattern**
300
+
301
+ ```jsx
302
+ const AccordionCheckout = () => {
303
+ const [openSections, setOpenSections] = useState(new Set(['tickets']))
304
+ const [completedSections, setCompletedSections] = useState(new Set())
305
+
306
+ const toggleSection = (section) => {
307
+ setOpenSections(prev => {
308
+ const newSet = new Set(prev)
309
+ if (newSet.has(section)) {
310
+ newSet.delete(section)
311
+ } else {
312
+ newSet.add(section)
313
+ }
314
+ return newSet
315
+ })
316
+ }
317
+
318
+ return (
319
+ <div className="accordion-checkout">
320
+ <div className="checkout-section">
321
+ <div
322
+ className="section-header"
323
+ onClick={() => toggleSection('tickets')}
324
+ >
325
+ <h3>Select Tickets</h3>
326
+ {completedSections.has('tickets') && <span>✓</span>}
327
+ </div>
328
+ {openSections.has('tickets') && (
329
+ <TicketsContainer
330
+ onAddToCartSuccess={(data) => {
331
+ setCompletedSections(prev => new Set([...prev, 'tickets']))
332
+ setOpenSections(new Set(['billing']))
333
+ }}
334
+ />
335
+ )}
336
+ </div>
337
+
338
+ <div className="checkout-section">
339
+ <div
340
+ className="section-header"
341
+ onClick={() => toggleSection('billing')}
342
+ >
343
+ <h3>Billing Information</h3>
344
+ {completedSections.has('billing') && <span>✓</span>}
345
+ </div>
346
+ {openSections.has('billing') && (
347
+ <BillingInfoContainer
348
+ handleSubmit={(values, helpers, eventId, res) => {
349
+ setCompletedSections(prev => new Set([...prev, 'billing']))
350
+ setOpenSections(new Set(['payment']))
351
+ }}
352
+ />
353
+ )}
354
+ </div>
355
+
356
+ {/* ... other sections */}
357
+ </div>
358
+ )
359
+ }
360
+ ```
361
+
362
+ ## Important Considerations
363
+
364
+ ### **Component Props Modifications**
365
+
366
+ - **`enableBillingInfoAutoCreate: false`** - Prevents automatic navigation to billing page
367
+ - **`skipPage: false`** - Controls whether billing page can be skipped
368
+ - **Custom callback handlers** - Override default navigation behavior
369
+
370
+ ### **State Persistence**
371
+
372
+ ```jsx
373
+ // Save state to localStorage for page refreshes
374
+ useEffect(() => {
375
+ localStorage.setItem('checkoutState', JSON.stringify({
376
+ currentStep,
377
+ checkoutData,
378
+ cartData
379
+ }))
380
+ }, [currentStep, checkoutData, cartData])
381
+
382
+ // Restore state on component mount
383
+ useEffect(() => {
384
+ const savedState = localStorage.getItem('checkoutState')
385
+ if (savedState) {
386
+ const { currentStep, checkoutData, cartData } = JSON.parse(savedState)
387
+ setCurrentStep(currentStep)
388
+ setCheckoutData(checkoutData)
389
+ setCartData(cartData)
390
+ }
391
+ }, [])
392
+ ```
393
+
394
+ ### **Error Handling**
395
+
396
+ ```jsx
397
+ const [errors, setErrors] = useState({})
398
+
399
+ const handleStepError = (step, error) => {
400
+ setErrors(prev => ({ ...prev, [step]: error }))
401
+ // Optionally navigate back to error step
402
+ setCurrentStep(step)
403
+ }
404
+
405
+ // Pass error handlers to each component
406
+ <BillingInfoContainer
407
+ onSubmitError={(error) => handleStepError('billing', error)}
408
+ handleSubmit={handleBillingSuccess}
409
+ />
410
+ ```
411
+
412
+ ### **Timer Coordination**
413
+
414
+ When using timers across multiple components in single page flow:
415
+
416
+ ```jsx
417
+ const [globalTimer, setGlobalTimer] = useState(null)
418
+
419
+ // Share timer state across components
420
+ <TicketsContainer enableTimer={false} />
421
+ <BillingInfoContainer enableTimer={false} />
422
+ <PaymentContainer enableTimer={true} onCountdownFinish={handleTimeout} />
423
+
424
+ // Or implement global timer
425
+ <TimerWidget
426
+ onCountdownFinish={handleGlobalTimeout}
427
+ className="global-timer"
428
+ />
429
+ ```
430
+
431
+ &nbsp;
432
+
133
433
  # Functionalities
134
434
 
135
435
  ## Login
136
436
 
437
+ The `LoginModal` component is designed to be used inside package to authenticate users. <br /> To use the `LoginModal`, simply include it in your React component and pass in the required **onLogin** and **onClose** callbacks as props.
137
438
 
138
- The `LoginModal` component is designed to be used inside package to authenticate users. <br /> To use the `LoginModal`, simply include it in your React component and pass in the required __onLogin__ and __onClose__ callbacks as props.
139
-
140
- You can authenticate users from the Billing page too, here you can either provide __onLogin__ callback as a prop to the [`BillingInfoContainer`](#billinginfocontainer) component so that you can open your custom component for authentication or you can ommit it and the package inside provided `LoginModal` component will be called and opened.
439
+ You can authenticate users from the Billing page too, here you can either provide **onLogin** callback as a prop to the [`BillingInfoContainer`](#billinginfocontainer) component so that you can open your custom component for authentication or
440
+ you can ommit it and the package inside provided `LoginModal` component will be called and opened.
141
441
 
142
- Package can detect whether a user is logged in or not by checking for the presence of the __X-TF-ECOMMERCE__ cookie, which is automatically set by the system when the user successfully logs in. If the __X-TF-ECOMMERCE__ cookie is present, the package assumes that the user is logged in and displays the appropriate content.
442
+ Package can detect whether a user is logged in or not by checking for the presence of the **X-TF-ECOMMERCE** cookie, which is automatically set by the system when the user successfully logs in.
443
+ If the **X-TF-ECOMMERCE** cookie is present, the package assumes that the user is logged in and displays the appropriate content.
143
444
 
144
- The `LoginModal` component also is used in [`MyTicketsContainer`](#myticketscontainer) and [`TicketsContainer`](#ticketscontainer).
445
+ The `LoginModal` component also is used in [`MyTicketsContainer`](#myticketscontainer) and [`TicketsContainer`](#ticketscontainer).
145
446
 
146
- To detect whether a user is logged in or not, you can use the __useCookieListener__ hook provided by the package.
147
- Here's an example of how to use the __useCookieListener__ hook to automatically detect whether the user is logged in:
447
+ To detect whether a user is logged in or not, you can use the **useCookieListener** hook provided by the package.
448
+ Here's an example of how to use the **useCookieListener** hook to automatically detect whether the user is logged in:
148
449
 
149
450
  ```jsx
150
451
  import { useEffect, useRef, useState } from 'react'
@@ -154,7 +455,7 @@ const MyComponent = () => {
154
455
  const [isLogged, setIsLogged] = useState(false)
155
456
 
156
457
  // Listen for changes to the __X-TF-ECOMMERCE__ cookie
157
- useCookieListener("X_TF_ECOMMERCE", value => setIsLogged(Boolean(value)))
458
+ useCookieListener('X_TF_ECOMMERCE', value => setIsLogged(Boolean(value)))
158
459
 
159
460
  // ... rest of component logic
160
461
  }
@@ -187,9 +488,12 @@ const MyComponent = () => {
187
488
 
188
489
  ## Register
189
490
 
190
- The `RegisterModal` component is designed to be used inside package to allows users to register for an account. <br />
491
+ The `RegisterModal` component is designed to be used inside package to allows users to register for an account. <br />
191
492
 
192
- When the user submits the form, the component calls the register API function to create the user's account. If account creation is successful, the component then retrieves the user's profile data. The __onGetProfileDataSuccess__ and __onGetProfileDataError__ callbacks are then called depending on whether the profile data retrieval succeeds or fails. If profile data retrieval succeeds, the component maps the profile data to a format used by the application and saves the resulting data to the browser's localStorage. Finally, the __onClose__ callback is called to close the modal.
493
+ When the user submits the form, the component calls the register API function to create the user's account.
494
+ If account creation is successful, the component then retrieves the user's profile data. The **onGetProfileDataSuccess** and **onGetProfileDataError** callbacks are then called depending on whether the profile data retrieval succeeds or fails.
495
+ If profile data retrieval succeeds, the component maps the profile data to a format used by the application and saves the resulting data to the browser's localStorage.
496
+ Finally, the **onClose** callback is called to close the modal.
193
497
 
194
498
  <details open>
195
499
  <summary><b>Register Modal Props Interface:</b></summary>
@@ -208,7 +512,9 @@ When the user submits the form, the component calls the register API function to
208
512
 
209
513
  ## Forgot Password
210
514
 
211
- The `ForgotPasswordModal` component is a modal dialog for users to reset their passwords. To use it, simply import the component, manage its open state, and provide callback functions for closing the modal, navigating back to the login page or component, handling successful password reset requests, and handling errors in password reset requests. Optionally, you can also display a "Powered By" image within the modal by setting the __showPoweredByImage__ prop to true.
515
+ The `ForgotPasswordModal` component is a modal dialog for users to reset their passwords.
516
+ To use it, simply import the component, manage its open state, and provide callback functions for closing the modal, navigating back to the login page or component, handling successful password reset requests, and handling errors in password reset requests.
517
+ Optionally, you can also display a "Powered By" image within the modal by setting the **showPoweredByImage** prop to true.
212
518
 
213
519
  <details open>
214
520
  <summary><b>Forgot Password Modal Props Interface:</b></summary>
@@ -226,13 +532,14 @@ The `ForgotPasswordModal` component is a modal dialog for users to reset their p
226
532
 
227
533
  ## Promo Code
228
534
 
229
- The `PromoCodeSection` is a React component for handling promo code input, validation, and displaying success or error messages. It accepts various props to control its appearance and behavior, such as the promo code value, validation status, input visibility, and callback functions for updating the state which you can see in the below provided table.
535
+ The `PromoCodeSection` is a React component for handling promo code input, validation, and displaying success or error messages.
536
+ It accepts various props to control its appearance and behavior, such as the promo code value, validation status, input visibility, and callback functions for updating the state which you can see in the below provided table.
230
537
 
231
538
  To use this component, simply import it and include it in your JSX with the required props, managing the component's state and callback functions in the parent component as needed.
232
539
 
233
- ### __Note that package automatically calls component in [`TicketsContainer`](#ticketscontainer)__
234
- <br />
540
+ ### **Note that package automatically calls component in [`TicketsContainer`](#ticketscontainer)**
235
541
 
542
+ <br />
236
543
 
237
544
  <details open>
238
545
  <summary><b>Promo Code Props Interface:</b></summary>
@@ -257,11 +564,14 @@ To use this component, simply import it and include it in your JSX with the requ
257
564
 
258
565
  ## Access Code
259
566
 
260
- The `AccessCodeSection` is a React component designed for handling access code input and submission. It allows users to enter an access code and triggers an update to the ticket information based on the submitted access code. The component accepts a set of props to manage the access code value and provide callback functions for updating the state which you can see in below table.
567
+ The `AccessCodeSection` is a React component designed for handling access code input and submission.
568
+ It allows users to enter an access code and triggers an update to the ticket information based on the submitted access code.
569
+ The component accepts a set of props to manage the access code value and provide callback functions for updating the state which you can see in below table.
261
570
 
262
- To integrate the `AccessCodeSection` component, import it into your JSX and provide the required props, such as the access code value, and callback functions for updating the state. Make sure to manage the component's state and callback functions within the parent component as needed. <br />
571
+ To integrate the `AccessCodeSection` component, import it into your JSX and provide the required props, such as the access code value, and callback functions for updating the state.
572
+ Make sure to manage the component's state and callback functions within the parent component as needed. <br />
263
573
 
264
- ### __Note that package automatically calls component in [`TicketsContainer`](#ticketscontainer)__
574
+ ### **Note that package automatically calls component in [`TicketsContainer`](#ticketscontainer)**
265
575
 
266
576
  <br />
267
577
 
@@ -280,10 +590,11 @@ To integrate the `AccessCodeSection` component, import it into your JSX and prov
280
590
 
281
591
  ## Waiting List
282
592
 
283
- The `WaitingList` component is a React component designed to handle user registration for a waiting list. It displays a form that allows users to input their information, including first name, last name, email, ticket type, and quantity. Upon submission, the component adds the user to the waiting list and displays a success message.
593
+ The `WaitingList` component is a React component designed to handle user registration for a waiting list.
594
+ It displays a form that allows users to input their information, including first name, last name, email, ticket type, and quantity.
595
+ Upon submission, the component adds the user to the waiting list and displays a success message.
284
596
 
285
-
286
- ### __Note that package automatically calls component in [`TicketsContainer`](#ticketscontainer)__
597
+ ### **Note that package automatically calls component in [`TicketsContainer`](#ticketscontainer)**
287
598
 
288
599
  <br />
289
600
 
@@ -317,33 +628,40 @@ Here is the list of pages where the `usePixel` function is automatically used:
317
628
 
318
629
  # Components
319
630
 
320
-
321
631
  ## `TicketsContainer`
322
632
 
323
633
  Tickets component will retrieve and show a list of tickets corresponding to selected event,
324
634
  which allows the user to select the desired ticket type and quantity.
325
635
 
326
- The __"Get Tickets"__ button which name is also customizable, allows the user to add the selected tickets to their cart and proceed to the checkout process.<br />
636
+ The **"Get Tickets"** button which name is also customizable, allows the user to add the selected tickets to their cart and proceed to the checkout process.<br />
327
637
  Other buttons can be displayed to handle various actions, such as viewing the user's orders or logging out.
328
638
 
329
639
  Tickets component provides a section for entering an [Access Code](#access-code) or [Promo Code](#promo-code) that applies a discount to the ticket price or hide/unhide some tickets via [Access Code](#access-code).<br />
330
- It also containes `WaitingLsit` that manages and displays waiting list functionality for the event.<br />
640
+ It also contains `WaitingList` that manages and displays waiting list functionality for the event.<br />
331
641
  Props interface partially extends [Promo Code Props Interface](#promo-code), [Access Code Props Interface](#access-code), [Waiting List Props Interface](#waiting-list).
332
642
 
333
643
  Tickets component displays a list of the top influencers who have promoted the event.
334
644
 
645
+ **Recent Improvements:**
646
+
647
+ - Fixed duplicate API calls issue by optimizing useEffect dependencies
648
+ - Enhanced error handling and loading states
649
+ - Improved time slot management for events
650
+ - Better integration with promo codes and access codes
651
+ - Optimized component re-rendering patterns
652
+
335
653
  Tickets component is flexible and customizable, allowing for different layouts and behaviors depending on the event's requirements.
336
654
 
337
- ___Example of usage___:
338
- ```jsx
655
+ **_Example of usage_**:
339
656
 
657
+ ```jsx
340
658
  import { TicketsContainer } from 'tf-checkout-react'
341
659
 
342
660
  <TicketsContainer
343
661
  theme="light"
344
662
  eventId={event?.id}
345
- handleNotInvitedModalClose={() => { }}
346
- handleInvalidLinkModalClose={() => { }}
663
+ handleNotInvitedModalClose={() => {}}
664
+ handleInvalidLinkModalClose={() => {}}
347
665
  onAddToCartSuccess={() => {}}
348
666
  isPromotionsEnabled={event?.is_promotions_enabled}
349
667
  isAccessCodeEnabled={event?.is_access_code}
@@ -351,7 +669,9 @@ import { TicketsContainer } from 'tf-checkout-react'
351
669
  hideSessionButtons={true}
352
670
  enableAddOns={false}
353
671
  showGroupNameBlock={true}
354
- tableTicketsHeaderComponent={<div className="tickets-container-header">RESERVE TABLES</div>}
672
+ tableTicketsHeaderComponent={
673
+ <div className="tickets-container-header">RESERVE TABLES</div>
674
+ }
355
675
  onPendingVerification={() => {}}
356
676
  />
357
677
  ```
@@ -431,9 +751,18 @@ Add-Ons component will retrieve and show a list of add-ons corresponding to sele
431
751
  &nbsp;
432
752
 
433
753
  ## `BillingInfoContainer`
434
- The component is responsible for managing the billing information during the checkout process. It provides a form that allows users to enter their billing information, including addresses and ticket holders' information.
435
754
 
436
- Component includes also phone field, which validation functionality is provided by Twilio and integrated into the component. It provides an additional layer of verification and security during the ticket purchase process.
755
+ The component is responsible for managing the billing information during the checkout process. It provides a form that allows users to enter their billing information, including addresses and ticket holders' information.
756
+
757
+ Component includes phone field validation functionality provided by Twilio, which adds an additional layer of verification and security during the ticket purchase process.
758
+
759
+ **Recent Improvements:**
760
+
761
+ - Enhanced architecture with better separation of concerns
762
+ - Improved form validation and error handling
763
+ - Better TypeScript typing throughout the component
764
+ - Optimized API call patterns to prevent duplicate requests
765
+ - Enhanced field rendering system for better customization
437
766
 
438
767
  Props interface extends [Login Modal Interface](#login), [Register Modal Interface](#register), [Forgot Password Modal Interface](#forgot-password).
439
768
 
@@ -480,7 +809,16 @@ Props interface extends [Login Modal Interface](#login), [Register Modal Interfa
480
809
  &nbsp;
481
810
 
482
811
  ## `PaymentContainer`
483
- The component provides a form for users to enter their payment information and checkout. It accepts various props to customize the form and handle the checkout process.
812
+
813
+ The component provides a form for users to enter their payment information and checkout. It accepts various props to customize the form and handle the checkout process.
814
+
815
+ **Recent Improvements:**
816
+
817
+ - Enhanced Stripe integration with better error handling
818
+ - Improved payment field validation and user feedback
819
+ - Better handling of payment method creation and confirmation
820
+ - Enhanced payment plan support with improved UI
821
+ - Optimized payment flow for better user experience
484
822
 
485
823
  <details open>
486
824
 
@@ -512,7 +850,8 @@ The component provides a form for users to enter their payment information and c
512
850
  &nbsp;
513
851
 
514
852
  ## `ConfirmationContainer`
515
- The component is responsible for displaying the confirmation page after a successful payment.
853
+
854
+ The component is responsible for displaying the confirmation page after a successful payment.
516
855
 
517
856
  <details open>
518
857
 
@@ -539,7 +878,8 @@ The component is responsible for displaying the confirmation page after a succes
539
878
  &nbsp;
540
879
 
541
880
  ## `MyTicketsContainer`
542
- The component is responsible for rendering a list of orders with details and some customization options.
881
+
882
+ The component is responsible for rendering a list of orders with details and some customization options.
543
883
 
544
884
  <details open>
545
885
 
@@ -636,8 +976,8 @@ Container renders information about accepting or declining of resold tickets. It
636
976
  <details open>
637
977
  <summary><small id="1">1. Share buttons</small></summary>
638
978
 
639
- ```
640
- IShareButton {
979
+ ```ts
980
+ interface IShareButton {
641
981
  mainLabel: string;
642
982
  subLabel: string;
643
983
  platform: string;
@@ -645,7 +985,7 @@ IShareButton {
645
985
  }
646
986
  ```
647
987
 
648
- ```
988
+ ```yaml
649
989
  Default share options if `showDefaultShareButtons` is true, are: "Share on Facebook", "Tweet to your Followers", "Message friends on Facebook" and "Message friends on WhatsApp".
650
990
  ```
651
991
 
@@ -654,15 +994,15 @@ Default share options if `showDefaultShareButtons` is true, are: "Share on Faceb
654
994
  <details open>
655
995
  <summary><small id="2">2. Confirmation Labels</small></summary>
656
996
 
657
- ```
658
- IConfirmationLabels {
997
+ ```ts
998
+ interface IConfirmationLabels {
659
999
  confirmationTitle?: string;
660
1000
  confirmationMain?: string;
661
1001
  confirmationHelper?: string
662
1002
  }
663
1003
  ```
664
1004
 
665
- ```
1005
+ ```js
666
1006
  const defaultConfirmationLabels = {
667
1007
  confirmationTitle = "Your Tickets are Confirmed!",
668
1008
  confirmationMain = "Your tickets are available in My Tickets section",
@@ -675,7 +1015,7 @@ const defaultConfirmationLabels = {
675
1015
  <details open>
676
1016
  <summary><small id="3">3. Tickets table columns</small></summary>
677
1017
 
678
- ```
1018
+ ```ts
679
1019
  interface ITicketsTableColumns {
680
1020
  id?: string | number;
681
1021
  key: keyof ITicketTypes & keyof IActionColumns;
@@ -688,7 +1028,7 @@ interface IActionColumns {
688
1028
  }
689
1029
  ```
690
1030
 
691
- ```
1031
+ ```ts
692
1032
  const defaultTicketsTableColumns = [
693
1033
  { key: 'ticket_type', label: 'Ticket Type' },
694
1034
  { key: 'holder_name', label: 'Ticket Holder' },
@@ -726,7 +1066,7 @@ To do a one-off build, use `npm run build` or `yarn build`.
726
1066
 
727
1067
  &nbsp;
728
1068
 
729
- ### Rollup
1069
+ ## Rollup
730
1070
 
731
1071
  TSDX uses [Rollup](https://rollupjs.org) as a bundler and generates multiple rollup configs for various module formats and build settings. See [Optimizations](#optimizations) for details.
732
1072
 
@@ -742,3 +1082,5 @@ Two actions are added by default:
742
1082
 
743
1083
  - `main` which installs deps w/ cache, lints, tests, and builds on all pushes against a Node and OS matrix
744
1084
  - `size` which comments cost comparison of your library on every pull request using [`size-limit`](https://github.com/ai/size-limit)
1085
+
1086
+ ## Optimizations