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
@@ -1,10 +1,22 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import './style.css'
2
3
 
4
+ import _get from 'lodash/get'
3
5
  import _sortBy from 'lodash/sortBy'
4
- import React, { ReactNode } from 'react'
6
+ import React, { ReactNode, useState } from 'react'
7
+ import { Tooltip } from 'react-tooltip'
5
8
 
9
+ import { FEES_STYLES } from '../../constants'
10
+ import { CONFIGS } from '../../utils'
11
+ import InfoIcon from './InfoIcon'
6
12
  import { TicketRow } from './TicketRow'
7
13
 
14
+ function decodeHTML(html: string): string {
15
+ const textArea = document.createElement('textarea')
16
+ textArea.innerHTML = html
17
+ return textArea.value
18
+ }
19
+
8
20
  interface ITicketsSectionProps {
9
21
  event: any;
10
22
  ticketsList: any;
@@ -17,12 +29,13 @@ interface ITicketsSectionProps {
17
29
  ticketsHeaderComponent?: ReactNode;
18
30
  tableTicketsHeaderComponent?: ReactNode;
19
31
  showGroupNameBlock?: boolean;
20
- currencySybmol?: string;
32
+ currencySymbol?: string;
21
33
  isSeatMapAllowed?: boolean;
34
+ descriptionTrigger?: 'click' | 'hover';
22
35
  }
23
36
 
24
37
  export const TicketsSection = ({
25
- event = { currency: {} },
38
+ event,
26
39
  ticketsList,
27
40
  selectedTickets,
28
41
  handleTicketSelect,
@@ -32,26 +45,37 @@ export const TicketsSection = ({
32
45
  hideTicketsHeader,
33
46
  hideTableTicketsHeader,
34
47
  showGroupNameBlock,
35
- currencySybmol,
48
+ currencySymbol,
36
49
  isSeatMapAllowed,
37
50
  tableTickets,
51
+ descriptionTrigger = 'click',
38
52
  }: ITicketsSectionProps) => {
39
- const {
40
- currency: { symbol },
41
- } = event
53
+ const symbol = _get(event, 'currency.symbol')
42
54
  const sortedTicketsList = sortBySoldOut
43
55
  ? _sortBy(_sortBy(ticketsList, 'sortOrder'), 'soldOut')
44
56
  : _sortBy(ticketsList, 'sortOrder')
45
57
  const showGroup = !!sortedTicketsList.find(ticket => ticket.groupName)
46
- const priceSymbol = currencySybmol ? currencySybmol : symbol
58
+ const priceSymbol = currencySymbol || symbol
59
+
60
+ const [visibleDescription, setVisibleDescription] = useState<string | null>(null)
61
+
62
+ const handleDescriptionToggle = (ticketId: string) => {
63
+ setVisibleDescription(current => (current === ticketId ? null : ticketId))
64
+ }
65
+
47
66
  return (
48
67
  <>
49
68
  {!hideTicketsHeader && ticketsHeaderComponent}
50
69
  {sortedTicketsList.map((ticket, i, arr) => {
51
- const ticketPrice = `${priceSymbol} ${(+ticket.price).toFixed(2)}`
52
- const ticketOldPrice = `${priceSymbol} ${(+ticket.oldPrice).toFixed(2)}`
70
+ const ticketPriceWithoutFees = `${priceSymbol} ${(+ticket.cost).toFixed(2)}`
71
+ const ticketPriceWithFees = `${priceSymbol} ${(+ticket.basePrice).toFixed(2)}`
72
+ const ticketOldPriceWithFees = `${priceSymbol} ${(+ticket.oldBasePrice).toFixed(2)}`
73
+ const ticketOldPriceWithoutFees = `${priceSymbol} ${(+ticket.oldCost).toFixed(2)}`
53
74
 
54
- const isSoldOut = ticket.sold_out || !ticket.displayTicket || ticket.soldOut
75
+ const isSoldOut =
76
+ ticket.sold_out ||
77
+ !(ticket.displayTicket || ticket.slotGroupId) ||
78
+ ticket.soldOut
55
79
  const ticketSelect = (event: any) => {
56
80
  const { value } = event.target
57
81
  handleTicketSelect(ticket.id, value)
@@ -63,11 +87,15 @@ export const TicketsSection = ({
63
87
  }
64
88
 
65
89
  const ticketIsFree = +ticket.price === 0
90
+ const discountTicketPriceElem = CONFIGS.FEES_STYLE === FEES_STYLES.DISPLAY_BOTH || !ticket.feeIncluded ?
91
+ ticketOldPriceWithoutFees : ticketOldPriceWithFees
66
92
  const ticketPriceElem = isSoldOut
67
93
  ? 'SOLD OUT'
68
94
  : ticketIsFree
69
- ? 'FREE'
70
- : ticketPrice
95
+ ? 'FREE'
96
+ : (CONFIGS.FEES_STYLE === FEES_STYLES.DISPLAY_BOTH || !ticket.feeIncluded)
97
+ ? ticketPriceWithoutFees
98
+ : ticketPriceWithFees
71
99
  const isNewGroupTicket = ticket?.groupName !== arr[i - 1]?.groupName
72
100
 
73
101
  return (
@@ -77,17 +105,59 @@ export const TicketsSection = ({
77
105
  {ticket.groupName || ''}
78
106
  </div>
79
107
  ) : null}
80
- <div className={`event-detail__tier ${isSoldOut ? 'disabled' : ''}`}>
108
+ <div
109
+ className={`event-detail__tier ${isSoldOut ? 'disabled' : ''}`}
110
+ id={ticket.id || ticket.name}
111
+ >
81
112
  <div className="event-detail__tier-name">
82
113
  {ticket.displayName || ticket.name}
114
+ {ticket.descriptionRich && (
115
+ <>
116
+ <span
117
+ aria-hidden
118
+ className="info-icon"
119
+ onClick={
120
+ descriptionTrigger === 'click'
121
+ ? () => handleDescriptionToggle(ticket.id)
122
+ : undefined
123
+ }
124
+ onMouseEnter={
125
+ descriptionTrigger === 'hover'
126
+ ? () => setVisibleDescription(ticket.id)
127
+ : undefined
128
+ }
129
+ onMouseLeave={
130
+ descriptionTrigger === 'hover'
131
+ ? () => setVisibleDescription(null)
132
+ : undefined
133
+ }
134
+ data-tooltip-id={`tooltip-${ticket.id}`}
135
+ data-tooltip-content="View ticket info"
136
+ style={{
137
+ marginLeft: 8,
138
+ cursor: 'pointer',
139
+ display: 'flex',
140
+ }}
141
+ >
142
+ <InfoIcon />
143
+ </span>
144
+
145
+ <Tooltip id={`tooltip-${ticket.id}`} place="top">
146
+ {ticket.description || 'No description available'}
147
+ </Tooltip>
148
+ </>
149
+ )}
83
150
  </div>
84
151
  <div className="event-tickets-container">
85
152
  <div className="event-detail__tier-price">
86
- {ticketIsDiscounted && <p className="old-price">{ticketOldPrice}</p>}
153
+ {ticketIsDiscounted && <p className="old-price">{discountTicketPriceElem}</p>}
87
154
  <p className={isSoldOut ? 'sold-out' : ''}>{ticketPriceElem}</p>
88
155
  {!isSoldOut && !ticketIsFree && (
89
156
  <p className="fees">
90
- {ticket.feeIncluded ? '(incl. Fees)' : '(excl. Fees)'}
157
+ {CONFIGS.FEES_STYLE === FEES_STYLES.TRADITIONAL &&
158
+ (ticket.feeIncluded ? '(incl. Fees)' : '(excl. Fees)')}
159
+ {CONFIGS.FEES_STYLE === FEES_STYLES.DISPLAY_BOTH &&
160
+ `(${ticketPriceWithFees} with fees)`}
91
161
  </p>
92
162
  )}
93
163
  </div>
@@ -101,16 +171,30 @@ export const TicketsSection = ({
101
171
  />
102
172
  </div>
103
173
  </div>
174
+ {visibleDescription === ticket.id && (
175
+ <div className="ticket-description">
176
+ <div
177
+ dangerouslySetInnerHTML={{
178
+ __html: decodeHTML(ticket.descriptionRich),
179
+ }}
180
+ />
181
+ </div>
182
+ )}
104
183
  </div>
105
184
  </React.Fragment>
106
185
  )
107
186
  })}
108
187
  {!hideTableTicketsHeader && tableTicketsHeaderComponent}
109
188
  {tableTickets.map((ticket: any, i: any, arr: any) => {
110
- const ticketPrice = `${priceSymbol} ${(+ticket.price).toFixed(2)}`
111
- const ticketOldPrice = `${priceSymbol} ${(+ticket.oldPrice).toFixed(2)}`
189
+ const ticketPriceWithoutFees = `${priceSymbol} ${(+ticket.cost).toFixed(2)}`
190
+ const ticketPriceWithFees = `${priceSymbol} ${(+ticket.basePrice).toFixed(2)}`
191
+ const ticketOldPriceWithFees = `${priceSymbol} ${(+ticket.oldBasePrice).toFixed(2)}`
192
+ const ticketOldPriceWithoutFees = `${priceSymbol} ${(+ticket.oldCost).toFixed(2)}`
112
193
 
113
- const isSoldOut = ticket.sold_out || !ticket.displayTicket || ticket.soldOut
194
+ const isSoldOut =
195
+ ticket.sold_out ||
196
+ !(ticket.displayTicket || ticket.slotGroupId) ||
197
+ ticket.soldOut
114
198
  const ticketSelect = (event: any) => {
115
199
  const { value } = event.target
116
200
  handleTicketSelect(ticket.id, value, true)
@@ -122,53 +206,101 @@ export const TicketsSection = ({
122
206
  }
123
207
 
124
208
  const ticketIsFree = +ticket.price === 0
209
+ const discountTicketPriceElem = CONFIGS.FEES_STYLE === FEES_STYLES.DISPLAY_BOTH || !ticket.feeIncluded ?
210
+ ticketOldPriceWithoutFees : ticketOldPriceWithFees
125
211
  const ticketPriceElem = isSoldOut
126
212
  ? 'SOLD OUT'
127
213
  : ticketIsFree
128
- ? 'FREE'
129
- : ticketPrice
214
+ ? 'FREE'
215
+ : (CONFIGS.FEES_STYLE === FEES_STYLES.DISPLAY_BOTH || !ticket.feeIncluded)
216
+ ? ticketPriceWithoutFees
217
+ : ticketPriceWithFees
130
218
  const isNewGroupTicket = ticket?.groupName !== arr[i - 1]?.groupName
131
219
 
132
220
  return (
133
- <>
134
- <React.Fragment key={ticket.id || ticket.name}>
135
- {showGroupNameBlock && showGroup && isNewGroupTicket ? (
136
- <div className="event-detail__tier group-title">
137
- {ticket.groupName || ''}
138
- </div>
139
- ) : null}
140
- <div className={`event-detail__tier ${isSoldOut ? 'disabled' : ''}`}>
141
- <div className="event-detail__tier-name">
142
- {ticket.displayName || ticket.name}
221
+ <React.Fragment key={ticket.id || ticket.name}>
222
+ {showGroupNameBlock && showGroup && isNewGroupTicket ? (
223
+ <div className="event-detail__tier group-title">
224
+ {ticket.groupName || ''}
225
+ </div>
226
+ ) : null}
227
+ <div
228
+ className={`event-detail__tier ${isSoldOut ? 'disabled' : ''}`}
229
+ id={ticket.id || ticket.name}
230
+ >
231
+ <div className="event-detail__tier-name">
232
+ {ticket.displayName || ticket.name}
233
+ {ticket.descriptionRich && (
234
+ <>
235
+ <span
236
+ aria-hidden
237
+ className="info-icon"
238
+ onClick={
239
+ descriptionTrigger === 'click'
240
+ ? () => handleDescriptionToggle(ticket.id)
241
+ : undefined
242
+ }
243
+ onMouseEnter={
244
+ descriptionTrigger === 'hover'
245
+ ? () => setVisibleDescription(ticket.id)
246
+ : undefined
247
+ }
248
+ onMouseLeave={
249
+ descriptionTrigger === 'hover'
250
+ ? () => setVisibleDescription(null)
251
+ : undefined
252
+ }
253
+ style={{ marginLeft: 8, cursor: 'pointer', display: 'flex' }}
254
+ data-tooltip-id={`tooltip-${ticket.id}`}
255
+ data-tooltip-content="View ticket info"
256
+ >
257
+ <InfoIcon />
258
+ </span>
259
+ <Tooltip id={`tooltip-${ticket.id}`} place="top">
260
+ {ticket.description || 'No description available'}
261
+ </Tooltip>
262
+ </>
263
+ )}
264
+ </div>
265
+ <div className="event-tickets-container">
266
+ <div className="event-detail__tier-price">
267
+ {ticketIsDiscounted && <p className="old-price">{discountTicketPriceElem}</p>}
268
+ <p className={isSoldOut ? 'sold-out' : ''}>{ticketPriceElem}</p>
269
+ {!isSoldOut && !ticketIsFree && (
270
+ <p className="fees">
271
+ {CONFIGS.FEES_STYLE === FEES_STYLES.TRADITIONAL &&
272
+ (ticket.feeIncluded ? '(incl. Fees)' : '(excl. Fees)')}
273
+ {CONFIGS.FEES_STYLE === FEES_STYLES.DISPLAY_BOTH &&
274
+ `(${ticketPriceWithFees} with fees)`}
275
+ </p>
276
+ )}
277
+ {ticket.depositPercent && (
278
+ <p className="deposits">{ticket.depositPercent + '% DEPOSIT'}</p>
279
+ )}
143
280
  </div>
144
- <div className="event-tickets-container">
145
- <div className="event-detail__tier-price">
146
- {ticketIsDiscounted && <p className="old-price">{ticketOldPrice}</p>}
147
- <p className={isSoldOut ? 'sold-out' : ''}>{ticketPriceElem}</p>
148
- {!isSoldOut && !ticketIsFree && (
149
- <p className="fees">
150
- {ticket.feeIncluded ? '(incl. Fees)' : '(excl. Fees)'}
151
- </p>
152
- )}
153
- {ticket.depositPercent && (
154
- <p className="deposits">{ticket.depositPercent + '% DEPOSIT'}</p>
155
- )}
156
- </div>
157
- <div className="event-detail__tier-state" style={{ minWidth: 55 }}>
158
- <TicketRow
159
- tableType={true}
160
- ticketTier={ticket}
161
- prevTicketTier={arr[i - 1]}
162
- selectedTickets={selectedTickets}
163
- handleTicketSelect={ticketSelect}
164
- isSeatMapAllowed={isSeatMapAllowed}
165
- event={event}
166
- />
167
- </div>
281
+ <div className="event-detail__tier-state" style={{ minWidth: 55 }}>
282
+ <TicketRow
283
+ tableType={true}
284
+ ticketTier={ticket}
285
+ prevTicketTier={arr[i - 1]}
286
+ selectedTickets={selectedTickets}
287
+ handleTicketSelect={ticketSelect}
288
+ isSeatMapAllowed={isSeatMapAllowed}
289
+ event={event}
290
+ />
168
291
  </div>
169
292
  </div>
170
- </React.Fragment>
171
- </>
293
+ {visibleDescription === ticket.id && (
294
+ <div className="ticket-description">
295
+ <div
296
+ dangerouslySetInnerHTML={{
297
+ __html: decodeHTML(ticket.descriptionRich),
298
+ }}
299
+ />
300
+ </div>
301
+ )}
302
+ </div>
303
+ </React.Fragment>
172
304
  )
173
305
  })}
174
306
  </>
@@ -0,0 +1,120 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { Box, CircularProgress, TextField } from '@mui/material'
3
+ import { LocalizationProvider, StaticDatePicker as DatePicker } from '@mui/x-date-pickers'
4
+ import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment'
5
+ import _isEmpty from 'lodash/isEmpty'
6
+ import _map from 'lodash/map'
7
+ import moment from 'moment-timezone'
8
+ import React, { ReactNode, useState } from 'react'
9
+
10
+ import { TicketsSection } from './TicketsSection'
11
+
12
+ interface Props {
13
+ event: any;
14
+ eventId: number;
15
+ availableDates: string[];
16
+ selectedDate: string | null;
17
+ timeSlotGroups: { [key: string]: any[] };
18
+ setTimeSlotGroups: (value: { [key: string]: any[] }) => void;
19
+ setSelectedDate: (value: string | null) => void;
20
+ getTimeSlots: (date: string | null, type?: string) => Promise<void>;
21
+
22
+ selectedTickets: any;
23
+ handleTicketSelect: any;
24
+ sortBySoldOut: boolean;
25
+ hideTicketsHeader: boolean;
26
+ ticketsHeaderComponent?: ReactNode;
27
+ showGroupNameBlock?: boolean;
28
+ currencySymbol?: string;
29
+ isSeatMapAllowed?: boolean;
30
+ }
31
+
32
+ const TimeSlotsSection: React.FC<Props> = ({
33
+ event,
34
+ availableDates,
35
+ selectedDate,
36
+ timeSlotGroups,
37
+ setSelectedDate,
38
+ getTimeSlots,
39
+ selectedTickets,
40
+ handleTicketSelect,
41
+ sortBySoldOut,
42
+ hideTicketsHeader,
43
+ ticketsHeaderComponent,
44
+ showGroupNameBlock,
45
+ currencySymbol,
46
+ isSeatMapAllowed,
47
+ }) => {
48
+ const [loading, setLoading] = useState(false)
49
+
50
+ const handleDateChange = async (date: string | null) => {
51
+ setSelectedDate(date)
52
+ if (date) {
53
+ setLoading(true)
54
+ try {
55
+ await getTimeSlots(date)
56
+ } catch (error) {
57
+ console.error('Error fetching time slots:', error)
58
+ } finally {
59
+ setLoading(false)
60
+ }
61
+ }
62
+ }
63
+
64
+ const isDateDisabled = (date: string) => {
65
+ const formattedDate = moment(date).format('YYYY-MM-DD')
66
+ return !availableDates.includes(formattedDate)
67
+ }
68
+
69
+ return (
70
+ <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
71
+ <LocalizationProvider dateAdapter={AdapterMoment}>
72
+ <DatePicker
73
+ value={selectedDate}
74
+ onChange={handleDateChange}
75
+ shouldDisableDate={isDateDisabled}
76
+ renderInput={params => <TextField {...params} />}
77
+ showToolbar={false}
78
+ componentsProps={{ actionBar: { actions: [] } }}
79
+ disablePast
80
+ />
81
+ </LocalizationProvider>
82
+ {loading ? (
83
+ <CircularProgress sx={{ marginTop: 2 }} />
84
+ ) : (
85
+ <Box
86
+ sx={{
87
+ marginTop: 2,
88
+ width: '100%',
89
+ display: 'flex',
90
+ flexDirection: 'column',
91
+ gap: 2,
92
+ }}
93
+ >
94
+ {_map(Object.keys(timeSlotGroups).sort(), timeKey => (
95
+ <div key={timeKey} className="time-slot-block">
96
+ <div className="time-slot-date">{moment(timeKey).format('hh:mm A')}</div>
97
+ <TicketsSection
98
+ event={event}
99
+ ticketsList={timeSlotGroups[timeKey]}
100
+ tableTickets={[]}
101
+ selectedTickets={selectedTickets}
102
+ handleTicketSelect={handleTicketSelect}
103
+ sortBySoldOut={sortBySoldOut}
104
+ ticketsHeaderComponent={ticketsHeaderComponent}
105
+ tableTicketsHeaderComponent={null}
106
+ hideTableTicketsHeader={true}
107
+ hideTicketsHeader={hideTicketsHeader || _isEmpty(timeSlotGroups[timeKey])}
108
+ showGroupNameBlock={showGroupNameBlock}
109
+ currencySymbol={currencySymbol}
110
+ isSeatMapAllowed={isSeatMapAllowed}
111
+ />
112
+ </div>
113
+ ))}
114
+ </Box>
115
+ )}
116
+ </Box>
117
+ )
118
+ }
119
+
120
+ export default TimeSlotsSection