tf-checkout-react 1.7.31 → 2.0.0-beta.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 (454) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +141 -1033
  3. package/dist/checkout.css +17 -0
  4. package/dist/index.d.mts +3946 -0
  5. package/dist/index.d.ts +3946 -30
  6. package/dist/index.esm.js +9176 -0
  7. package/dist/index.esm.js.map +1 -0
  8. package/dist/index.js +9330 -6
  9. package/dist/index.js.map +1 -0
  10. package/dist/styles/addons.css +75 -0
  11. package/dist/styles/auth.css +294 -0
  12. package/dist/styles/billing.css +98 -0
  13. package/dist/styles/confirmation.css +51 -0
  14. package/dist/styles/foundation.css +146 -0
  15. package/dist/styles/payment.css +179 -0
  16. package/dist/styles/primitives.css +356 -0
  17. package/dist/styles/seat-map.css +46 -0
  18. package/dist/styles/tickets.css +285 -0
  19. package/dist/styles/verification-confirmation.css +258 -0
  20. package/package.json +93 -78
  21. package/src/.d.ts +1 -1
  22. package/src/CardInput.tsx +374 -0
  23. package/src/EmbeddedCheckout.tsx +400 -0
  24. package/src/ResumedCheckout.tsx +132 -0
  25. package/src/auth/AuthModal.tsx +238 -0
  26. package/src/auth/ForgotPasswordForm.tsx +93 -0
  27. package/src/auth/LoginForm.tsx +104 -0
  28. package/src/auth/PasswordInput.tsx +33 -0
  29. package/src/auth/RegisterForm.tsx +333 -0
  30. package/src/auth/ResetPasswordForm.tsx +112 -0
  31. package/src/auth/index.ts +5 -0
  32. package/src/checkout.css +17 -0
  33. package/src/configure.ts +29 -0
  34. package/src/confirmer.ts +439 -0
  35. package/src/index.ts +41 -30
  36. package/src/instance.ts +21 -0
  37. package/src/sections/AddOns.tsx +241 -0
  38. package/src/sections/BillingInfo.tsx +790 -0
  39. package/src/sections/Confirmation.tsx +146 -0
  40. package/src/sections/IDVerification.tsx +76 -0
  41. package/src/sections/OrderConfirmation.tsx +277 -0
  42. package/src/sections/OrderIDVerification.tsx +117 -0
  43. package/src/sections/OrderSummary.tsx +84 -0
  44. package/src/sections/Payment.tsx +557 -0
  45. package/src/sections/SeatMap.tsx +512 -0
  46. package/src/sections/Tickets.tsx +573 -0
  47. package/src/sections/billing/BillingAddressFields.tsx +138 -0
  48. package/src/sections/billing/BuyerField.tsx +75 -0
  49. package/src/sections/billing/TicketHoldersCard.tsx +124 -0
  50. package/src/sections/billing/fieldRules.ts +43 -0
  51. package/src/sections/billing/types.ts +10 -0
  52. package/src/sections/index.ts +15 -0
  53. package/src/sections/seatMap.utils.ts +105 -0
  54. package/src/styles/addons.css +75 -0
  55. package/src/styles/auth.css +294 -0
  56. package/src/styles/billing.css +98 -0
  57. package/src/styles/confirmation.css +51 -0
  58. package/src/styles/foundation.css +146 -0
  59. package/src/styles/payment.css +179 -0
  60. package/src/styles/primitives.css +356 -0
  61. package/src/styles/seat-map.css +46 -0
  62. package/src/styles/tickets.css +285 -0
  63. package/src/styles/verification-confirmation.css +258 -0
  64. package/src/typings.d.ts +2 -2
  65. package/src/ui/Button.tsx +38 -0
  66. package/src/ui/Card.tsx +54 -0
  67. package/src/ui/CheckoutProvider.tsx +172 -0
  68. package/src/ui/CustomFields.tsx +195 -0
  69. package/src/ui/Field.tsx +114 -0
  70. package/src/ui/I18nProvider.tsx +36 -0
  71. package/src/ui/InstallmentPicker.tsx +69 -0
  72. package/src/ui/Loader.tsx +12 -0
  73. package/src/ui/PaymentMethods.tsx +133 -0
  74. package/src/ui/PriceLine.tsx +24 -0
  75. package/src/ui/QuantitySelect.tsx +50 -0
  76. package/src/ui/Stepper.tsx +36 -0
  77. package/src/ui/Timer.tsx +34 -0
  78. package/src/ui/TimerBanner.tsx +55 -0
  79. package/src/ui/cx.ts +3 -0
  80. package/src/ui/index.ts +54 -0
  81. package/src/ui/theme.ts +83 -0
  82. package/src/useCheckout.ts +35 -0
  83. package/src/xendit.ts +438 -0
  84. package/dist/adapters/customFields.d.ts +0 -12
  85. package/dist/adapters/index.d.ts +0 -1
  86. package/dist/api/auth.d.ts +0 -27
  87. package/dist/api/cart.d.ts +0 -2
  88. package/dist/api/checkout.d.ts +0 -3
  89. package/dist/api/common.d.ts +0 -11
  90. package/dist/api/guestTicketDelegation.d.ts +0 -47
  91. package/dist/api/index.d.ts +0 -82
  92. package/dist/api/interceptors.d.ts +0 -1
  93. package/dist/api/orders.d.ts +0 -2
  94. package/dist/api/payment.d.ts +0 -5
  95. package/dist/api/preRegistrationComplete.d.ts +0 -3
  96. package/dist/api/publicRequest.d.ts +0 -9
  97. package/dist/api/resale.d.ts +0 -5
  98. package/dist/components/account-settings/index.d.ts +0 -3
  99. package/dist/components/addonsContainer/AddonComponent.d.ts +0 -18
  100. package/dist/components/addonsContainer/SimpleAddonsContainer.d.ts +0 -20
  101. package/dist/components/addonsContainer/adapters/index.d.ts +0 -12
  102. package/dist/components/addonsContainer/index.d.ts +0 -22
  103. package/dist/components/addonsContainer/normalizers/index.d.ts +0 -1
  104. package/dist/components/addonsContainer/useAddons.d.ts +0 -23
  105. package/dist/components/addonsContainer/utils/index.d.ts +0 -16
  106. package/dist/components/billing-info-container/hooks/index.d.ts +0 -3
  107. package/dist/components/billing-info-container/hooks/usePaymentContext.d.ts +0 -5
  108. package/dist/components/billing-info-container/hooks/usePaymentRedirect.d.ts +0 -14
  109. package/dist/components/billing-info-container/hooks/useStripePayment.d.ts +0 -18
  110. package/dist/components/billing-info-container/index.d.ts +0 -69
  111. package/dist/components/billing-info-container/utils.d.ts +0 -59
  112. package/dist/components/common/Checkbox.d.ts +0 -11
  113. package/dist/components/common/CheckboxField/index.d.ts +0 -9
  114. package/dist/components/common/CopyField.d.ts +0 -12
  115. package/dist/components/common/CopyMessageModal.d.ts +0 -7
  116. package/dist/components/common/CustomField.d.ts +0 -26
  117. package/dist/components/common/DatePickerField.d.ts +0 -20
  118. package/dist/components/common/FieldSection/index.d.ts +0 -19
  119. package/dist/components/common/FieldSection/utils/index.d.ts +0 -8
  120. package/dist/components/common/FormikPhoneNumberField.d.ts +0 -11
  121. package/dist/components/common/Loader.d.ts +0 -2
  122. package/dist/components/common/ModalComponent/index.d.ts +0 -16
  123. package/dist/components/common/NativeSelectFeild/index.d.ts +0 -21
  124. package/dist/components/common/PhoneNumberField.d.ts +0 -14
  125. package/dist/components/common/PoweredBy.d.ts +0 -2
  126. package/dist/components/common/RadioField.d.ts +0 -11
  127. package/dist/components/common/RadioGroupField/index.d.ts +0 -17
  128. package/dist/components/common/RedirectModal.d.ts +0 -7
  129. package/dist/components/common/SelectField/index.d.ts +0 -19
  130. package/dist/components/common/SnackbarAlert.d.ts +0 -13
  131. package/dist/components/common/index.d.ts +0 -11
  132. package/dist/components/common/socials.d.ts +0 -10
  133. package/dist/components/confirmModal/index.d.ts +0 -10
  134. package/dist/components/confirmationContainer/config.d.ts +0 -1
  135. package/dist/components/confirmationContainer/index.d.ts +0 -46
  136. package/dist/components/confirmationContainer/social-buttons.d.ts +0 -16
  137. package/dist/components/countdown/index.d.ts +0 -14
  138. package/dist/components/delegationsContainer/IssueComponent.d.ts +0 -10
  139. package/dist/components/delegationsContainer/IssueTicketForm.d.ts +0 -9
  140. package/dist/components/delegationsContainer/TicketsAssignedTable.d.ts +0 -11
  141. package/dist/components/delegationsContainer/TicketsAvailableTable.d.ts +0 -11
  142. package/dist/components/delegationsContainer/index.d.ts +0 -10
  143. package/dist/components/forgotPasswordModal/index.d.ts +0 -12
  144. package/dist/components/idVerificationContainer/VerificationPendingModal.d.ts +0 -10
  145. package/dist/components/idVerificationContainer/constants.d.ts +0 -21
  146. package/dist/components/idVerificationContainer/index.d.ts +0 -16
  147. package/dist/components/index.d.ts +0 -12
  148. package/dist/components/loginForm/index.d.ts +0 -31
  149. package/dist/components/loginModal/SignUpForm.d.ts +0 -10
  150. package/dist/components/loginModal/constants.d.ts +0 -39
  151. package/dist/components/loginModal/index.d.ts +0 -22
  152. package/dist/components/myTicketsContainer/index.d.ts +0 -16
  153. package/dist/components/myTicketsContainer/row.d.ts +0 -3
  154. package/dist/components/myTicketsContainer/tableConfig.d.ts +0 -5
  155. package/dist/components/orderDetailsContainer/CustomFieldsForm.d.ts +0 -12
  156. package/dist/components/orderDetailsContainer/TicketHolderCustomFields.d.ts +0 -10
  157. package/dist/components/orderDetailsContainer/index.d.ts +0 -66
  158. package/dist/components/orderDetailsContainer/ticketsTable.d.ts +0 -46
  159. package/dist/components/orderDetailsContainer/utils/index.d.ts +0 -6
  160. package/dist/components/paymentContainer/OrderDetails.d.ts +0 -9
  161. package/dist/components/paymentContainer/PaymentPlanSection.d.ts +0 -10
  162. package/dist/components/paymentContainer/handlePayment.d.ts +0 -15
  163. package/dist/components/paymentContainer/index.d.ts +0 -39
  164. package/dist/components/preRegistration/FieldsSection.d.ts +0 -19
  165. package/dist/components/preRegistration/Influancers.d.ts +0 -2
  166. package/dist/components/preRegistration/PreRegistrationComplete.d.ts +0 -13
  167. package/dist/components/preRegistration/PreRegistrationInformations.d.ts +0 -2
  168. package/dist/components/preRegistration/Prewards.d.ts +0 -2
  169. package/dist/components/preRegistration/ShareOptions.d.ts +0 -2
  170. package/dist/components/preRegistration/constants.d.ts +0 -2
  171. package/dist/components/preRegistration/index.d.ts +0 -23
  172. package/dist/components/preRegistration/utils.d.ts +0 -12
  173. package/dist/components/registerForm/adapters/index.d.ts +0 -4
  174. package/dist/components/registerForm/constants.d.ts +0 -1
  175. package/dist/components/registerForm/index.d.ts +0 -16
  176. package/dist/components/registerModal/index.d.ts +0 -12
  177. package/dist/components/resetPasswordContainer/index.d.ts +0 -10
  178. package/dist/components/rsvpContainer/index.d.ts +0 -7
  179. package/dist/components/seatMapContainer/SeatMapComponent.d.ts +0 -8
  180. package/dist/components/seatMapContainer/TicketsSection.d.ts +0 -9
  181. package/dist/components/seatMapContainer/addToCart.d.ts +0 -14
  182. package/dist/components/seatMapContainer/index.d.ts +0 -2
  183. package/dist/components/seatMapContainer/utils.d.ts +0 -6
  184. package/dist/components/signupModal/index.d.ts +0 -12
  185. package/dist/components/ticketResale/index.d.ts +0 -12
  186. package/dist/components/ticketResaleModal/index.d.ts +0 -19
  187. package/dist/components/ticketsContainer/AccessCodeSection.d.ts +0 -7
  188. package/dist/components/ticketsContainer/InfoIcon.d.ts +0 -5
  189. package/dist/components/ticketsContainer/PromoCodeSection.d.ts +0 -15
  190. package/dist/components/ticketsContainer/ReferralLogic.d.ts +0 -5
  191. package/dist/components/ticketsContainer/TicketRow.d.ts +0 -13
  192. package/dist/components/ticketsContainer/TicketsSection.d.ts +0 -20
  193. package/dist/components/ticketsContainer/TimeSlotTicketRow.d.ts +0 -19
  194. package/dist/components/ticketsContainer/TimeSlotsSection.d.ts +0 -25
  195. package/dist/components/ticketsContainer/index.d.ts +0 -93
  196. package/dist/components/ticketsContainer/utils.d.ts +0 -13
  197. package/dist/components/timerWidget/index.d.ts +0 -16
  198. package/dist/components/waitingList/index.d.ts +0 -9
  199. package/dist/constants/index.d.ts +0 -7
  200. package/dist/env.d.ts +0 -16
  201. package/dist/hoc/CustomFields/index.d.ts +0 -3
  202. package/dist/hoc/index.d.ts +0 -1
  203. package/dist/hooks/index.d.ts +0 -1
  204. package/dist/hooks/useCookieListener.d.ts +0 -1
  205. package/dist/hooks/useEventListener.d.ts +0 -1
  206. package/dist/hooks/useLocalStorageListener.d.ts +0 -1
  207. package/dist/hooks/useOnline.d.ts +0 -1
  208. package/dist/hooks/usePixel.d.ts +0 -6
  209. package/dist/images/Polygon.png +0 -0
  210. package/dist/images/cross.svg +0 -44
  211. package/dist/images/done.svg +0 -3
  212. package/dist/images/edit.svg +0 -10
  213. package/dist/images/email.svg +0 -1
  214. package/dist/images/instagram.svg +0 -5
  215. package/dist/images/logo-ttf.png +0 -0
  216. package/dist/images/spotify.svg +0 -6
  217. package/dist/images/user.svg +0 -1
  218. package/dist/images/xmark.svg +0 -92
  219. package/dist/normalizers/index.d.ts +0 -4
  220. package/dist/tf-checkout-react.cjs.development.js +0 -16149
  221. package/dist/tf-checkout-react.cjs.development.js.map +0 -1
  222. package/dist/tf-checkout-react.cjs.production.min.js +0 -2
  223. package/dist/tf-checkout-react.cjs.production.min.js.map +0 -1
  224. package/dist/tf-checkout-react.esm.js +0 -16116
  225. package/dist/tf-checkout-react.esm.js.map +0 -1
  226. package/dist/tf-checkout-styles.css +0 -1
  227. package/dist/types/add_on.d.ts +0 -8
  228. package/dist/types/billing-info-data.d.ts +0 -27
  229. package/dist/types/checkoutPageConfigs.d.ts +0 -13
  230. package/dist/types/index.d.ts +0 -6
  231. package/dist/types/order-data.d.ts +0 -15
  232. package/dist/types/payment-field.d.ts +0 -6
  233. package/dist/types/payment-plan-configuration.d.ts +0 -18
  234. package/dist/types/referral-promotion.d.ts +0 -6
  235. package/dist/types/verification.d.ts +0 -12
  236. package/dist/utils/adaptStripeErrors.d.ts +0 -8
  237. package/dist/utils/auth.d.ts +0 -21
  238. package/dist/utils/cookies.d.ts +0 -3
  239. package/dist/utils/createCheckoutDataBodyWithDefaultHolder.d.ts +0 -23
  240. package/dist/utils/createMarkup.d.ts +0 -3
  241. package/dist/utils/customFields.d.ts +0 -35
  242. package/dist/utils/downloadPDF.d.ts +0 -1
  243. package/dist/utils/form.d.ts +0 -3
  244. package/dist/utils/formikErrorFocus.d.ts +0 -2
  245. package/dist/utils/getDomain.d.ts +0 -1
  246. package/dist/utils/getImage.d.ts +0 -1
  247. package/dist/utils/getQueryVariable.d.ts +0 -1
  248. package/dist/utils/htmlNodeFromString.d.ts +0 -1
  249. package/dist/utils/index.d.ts +0 -15
  250. package/dist/utils/isBrowser.d.ts +0 -1
  251. package/dist/utils/isValidNumber.d.ts +0 -1
  252. package/dist/utils/jsonUtils.d.ts +0 -1
  253. package/dist/utils/replaceVarInString.d.ts +0 -1
  254. package/dist/utils/setConfigs.d.ts +0 -11
  255. package/dist/utils/showZero.d.ts +0 -1
  256. package/dist/validators/index.d.ts +0 -8
  257. package/src/adapters/customFields.ts +0 -85
  258. package/src/adapters/index.ts +0 -1
  259. package/src/api/auth.ts +0 -88
  260. package/src/api/cart.ts +0 -28
  261. package/src/api/checkout.ts +0 -28
  262. package/src/api/common.ts +0 -190
  263. package/src/api/guestTicketDelegation.ts +0 -79
  264. package/src/api/index.ts +0 -346
  265. package/src/api/interceptors.ts +0 -77
  266. package/src/api/orders.ts +0 -30
  267. package/src/api/payment.ts +0 -77
  268. package/src/api/preRegistrationComplete.ts +0 -37
  269. package/src/api/publicRequest.ts +0 -47
  270. package/src/api/resale.ts +0 -28
  271. package/src/assets/images/Polygon.png +0 -0
  272. package/src/assets/images/cross.svg +0 -44
  273. package/src/assets/images/done.svg +0 -3
  274. package/src/assets/images/edit.svg +0 -10
  275. package/src/assets/images/email.svg +0 -1
  276. package/src/assets/images/instagram.svg +0 -5
  277. package/src/assets/images/logo-ttf.png +0 -0
  278. package/src/assets/images/spotify.svg +0 -6
  279. package/src/assets/images/user.svg +0 -1
  280. package/src/assets/images/xmark.svg +0 -92
  281. package/src/components/account-settings/index.tsx +0 -161
  282. package/src/components/account-settings/style.css +0 -200
  283. package/src/components/addonsContainer/AddonComponent.tsx +0 -204
  284. package/src/components/addonsContainer/SimpleAddonsContainer.tsx +0 -459
  285. package/src/components/addonsContainer/adapters/index.tsx +0 -62
  286. package/src/components/addonsContainer/index.tsx +0 -353
  287. package/src/components/addonsContainer/normalizers/index.ts +0 -5
  288. package/src/components/addonsContainer/useAddons.ts +0 -248
  289. package/src/components/addonsContainer/utils/index.tsx +0 -231
  290. package/src/components/billing-info-container/hooks/index.ts +0 -3
  291. package/src/components/billing-info-container/hooks/usePaymentContext.ts +0 -22
  292. package/src/components/billing-info-container/hooks/usePaymentRedirect.ts +0 -145
  293. package/src/components/billing-info-container/hooks/useStripePayment.ts +0 -119
  294. package/src/components/billing-info-container/index.tsx +0 -1695
  295. package/src/components/billing-info-container/style.css +0 -150
  296. package/src/components/billing-info-container/utils.tsx +0 -413
  297. package/src/components/common/Checkbox.tsx +0 -51
  298. package/src/components/common/CheckboxField/index.tsx +0 -41
  299. package/src/components/common/CopyField.tsx +0 -53
  300. package/src/components/common/CopyMessageModal.tsx +0 -34
  301. package/src/components/common/CustomField.tsx +0 -168
  302. package/src/components/common/DatePickerField.tsx +0 -126
  303. package/src/components/common/FieldSection/index.tsx +0 -141
  304. package/src/components/common/FieldSection/utils/index.tsx +0 -92
  305. package/src/components/common/FormikPhoneNumberField.tsx +0 -51
  306. package/src/components/common/Loader.tsx +0 -8
  307. package/src/components/common/ModalComponent/index.tsx +0 -68
  308. package/src/components/common/NativeSelectFeild/index.tsx +0 -86
  309. package/src/components/common/PhoneNumberField.tsx +0 -117
  310. package/src/components/common/PoweredBy.tsx +0 -15
  311. package/src/components/common/RadioField.tsx +0 -36
  312. package/src/components/common/RadioGroupField/index.tsx +0 -76
  313. package/src/components/common/RedirectModal.tsx +0 -43
  314. package/src/components/common/SelectField/index.tsx +0 -104
  315. package/src/components/common/SnackbarAlert.tsx +0 -52
  316. package/src/components/common/index.tsx +0 -11
  317. package/src/components/common/socials.tsx +0 -33
  318. package/src/components/confirmModal/index.tsx +0 -60
  319. package/src/components/confirmationContainer/config.ts +0 -79
  320. package/src/components/confirmationContainer/index.tsx +0 -349
  321. package/src/components/confirmationContainer/social-buttons.tsx +0 -149
  322. package/src/components/confirmationContainer/style.css +0 -206
  323. package/src/components/countdown/index.tsx +0 -100
  324. package/src/components/countdown/style.css +0 -10
  325. package/src/components/delegationsContainer/IssueComponent.tsx +0 -156
  326. package/src/components/delegationsContainer/IssueTicketForm.tsx +0 -109
  327. package/src/components/delegationsContainer/TicketsAssignedTable.tsx +0 -55
  328. package/src/components/delegationsContainer/TicketsAvailableTable.tsx +0 -54
  329. package/src/components/delegationsContainer/index.tsx +0 -83
  330. package/src/components/forgotPasswordModal/index.tsx +0 -138
  331. package/src/components/forgotPasswordModal/style.css +0 -47
  332. package/src/components/idVerificationContainer/VerificationPendingModal.tsx +0 -47
  333. package/src/components/idVerificationContainer/constants.ts +0 -27
  334. package/src/components/idVerificationContainer/index.tsx +0 -323
  335. package/src/components/index.ts +0 -12
  336. package/src/components/loginForm/index.tsx +0 -202
  337. package/src/components/loginModal/SignUpForm.tsx +0 -329
  338. package/src/components/loginModal/constants.ts +0 -46
  339. package/src/components/loginModal/index.tsx +0 -263
  340. package/src/components/loginModal/style.css +0 -116
  341. package/src/components/myTicketsContainer/index.tsx +0 -228
  342. package/src/components/myTicketsContainer/row.tsx +0 -46
  343. package/src/components/myTicketsContainer/style.css +0 -40
  344. package/src/components/myTicketsContainer/tableConfig.tsx +0 -80
  345. package/src/components/myTicketsContainer/types.d.ts +0 -41
  346. package/src/components/orderDetailsContainer/CustomFieldsForm.tsx +0 -75
  347. package/src/components/orderDetailsContainer/TicketHolderCustomFields.tsx +0 -100
  348. package/src/components/orderDetailsContainer/index.tsx +0 -586
  349. package/src/components/orderDetailsContainer/style.css +0 -77
  350. package/src/components/orderDetailsContainer/ticketsTable.tsx +0 -246
  351. package/src/components/orderDetailsContainer/utils/index.tsx +0 -55
  352. package/src/components/paymentContainer/OrderDetails.tsx +0 -277
  353. package/src/components/paymentContainer/PaymentPlanSection.tsx +0 -169
  354. package/src/components/paymentContainer/handlePayment.ts +0 -86
  355. package/src/components/paymentContainer/index.tsx +0 -643
  356. package/src/components/paymentContainer/style.css +0 -196
  357. package/src/components/preRegistration/FieldsSection.tsx +0 -150
  358. package/src/components/preRegistration/Influancers.tsx +0 -34
  359. package/src/components/preRegistration/PreRegistrationComplete.tsx +0 -186
  360. package/src/components/preRegistration/PreRegistrationInformations.tsx +0 -60
  361. package/src/components/preRegistration/Prewards.tsx +0 -41
  362. package/src/components/preRegistration/ShareOptions.tsx +0 -77
  363. package/src/components/preRegistration/constants.tsx +0 -169
  364. package/src/components/preRegistration/index.tsx +0 -330
  365. package/src/components/preRegistration/style.css +0 -3
  366. package/src/components/preRegistration/utils.ts +0 -163
  367. package/src/components/registerForm/adapters/index.tsx +0 -10
  368. package/src/components/registerForm/constants.tsx +0 -98
  369. package/src/components/registerForm/index.tsx +0 -188
  370. package/src/components/registerModal/index.tsx +0 -154
  371. package/src/components/registerModal/style.css +0 -18
  372. package/src/components/resetPasswordContainer/index.tsx +0 -102
  373. package/src/components/resetPasswordContainer/style.css +0 -36
  374. package/src/components/rsvpContainer/index.tsx +0 -126
  375. package/src/components/seatMapContainer/SeatMapComponent.tsx +0 -77
  376. package/src/components/seatMapContainer/TicketsSection.tsx +0 -286
  377. package/src/components/seatMapContainer/addToCart.ts +0 -66
  378. package/src/components/seatMapContainer/index.tsx +0 -443
  379. package/src/components/seatMapContainer/utils.ts +0 -133
  380. package/src/components/signupModal/index.tsx +0 -178
  381. package/src/components/signupModal/style.css +0 -58
  382. package/src/components/ticketResale/index.tsx +0 -86
  383. package/src/components/ticketResaleModal/index.tsx +0 -224
  384. package/src/components/ticketResaleModal/style.css +0 -28
  385. package/src/components/ticketsContainer/AccessCodeSection.tsx +0 -50
  386. package/src/components/ticketsContainer/InfoIcon.tsx +0 -35
  387. package/src/components/ticketsContainer/PromoCodeSection.tsx +0 -116
  388. package/src/components/ticketsContainer/ReferralLogic.tsx +0 -33
  389. package/src/components/ticketsContainer/TicketRow.tsx +0 -107
  390. package/src/components/ticketsContainer/TicketsSection.tsx +0 -350
  391. package/src/components/ticketsContainer/TimeSlotTicketRow.tsx +0 -243
  392. package/src/components/ticketsContainer/TimeSlotsSection.tsx +0 -194
  393. package/src/components/ticketsContainer/index.tsx +0 -986
  394. package/src/components/ticketsContainer/style.css +0 -178
  395. package/src/components/ticketsContainer/utils.ts +0 -35
  396. package/src/components/timerWidget/index.tsx +0 -97
  397. package/src/components/timerWidget/style.css +0 -35
  398. package/src/components/waitingList/index.tsx +0 -190
  399. package/src/components/waitingList/style.css +0 -27
  400. package/src/constants/index.ts +0 -3
  401. package/src/env.ts +0 -29
  402. package/src/hoc/CustomFields/index.tsx +0 -85
  403. package/src/hoc/index.ts +0 -1
  404. package/src/hooks/index.ts +0 -1
  405. package/src/hooks/useCookieListener.ts +0 -32
  406. package/src/hooks/useEventListener.ts +0 -32
  407. package/src/hooks/useLocalStorageListener.ts +0 -32
  408. package/src/hooks/useOnline.ts +0 -21
  409. package/src/hooks/usePixel.ts +0 -88
  410. package/src/normalizers/index.ts +0 -49
  411. package/src/types/add_on.ts +0 -8
  412. package/src/types/api/auth.d.ts +0 -63
  413. package/src/types/api/axiosResponse.d.ts +0 -6
  414. package/src/types/api/cart.d.ts +0 -73
  415. package/src/types/api/checkout.d.ts +0 -92
  416. package/src/types/api/common.d.ts +0 -153
  417. package/src/types/api/guestTicketDelegation.d.ts +0 -18
  418. package/src/types/api/orders.d.ts +0 -116
  419. package/src/types/api/payment.d.ts +0 -180
  420. package/src/types/api/preRegistration.d.ts +0 -11
  421. package/src/types/api/preRegistrationComplete.d.ts +0 -95
  422. package/src/types/api/ticketResale.d.ts +0 -13
  423. package/src/types/billing-info-data.ts +0 -37
  424. package/src/types/checkoutPageConfigs.ts +0 -13
  425. package/src/types/formFields.d.ts +0 -29
  426. package/src/types/index.ts +0 -6
  427. package/src/types/order-data.ts +0 -16
  428. package/src/types/payment-field.ts +0 -7
  429. package/src/types/payment-plan-configuration.ts +0 -19
  430. package/src/types/pre-registration-complete.d.ts +0 -47
  431. package/src/types/referral-promotion.ts +0 -7
  432. package/src/types/seatMap.d.ts +0 -159
  433. package/src/types/verification.ts +0 -12
  434. package/src/utils/adaptStripeErrors.ts +0 -26
  435. package/src/utils/auth.ts +0 -45
  436. package/src/utils/cookies.ts +0 -73
  437. package/src/utils/createCheckoutDataBodyWithDefaultHolder.ts +0 -81
  438. package/src/utils/createMarkup.ts +0 -1
  439. package/src/utils/customFields.ts +0 -80
  440. package/src/utils/downloadPDF.tsx +0 -42
  441. package/src/utils/form.ts +0 -34
  442. package/src/utils/formikErrorFocus.ts +0 -24
  443. package/src/utils/getDomain.ts +0 -21
  444. package/src/utils/getImage.ts +0 -14
  445. package/src/utils/getQueryVariable.ts +0 -13
  446. package/src/utils/htmlNodeFromString.ts +0 -6
  447. package/src/utils/index.ts +0 -15
  448. package/src/utils/isBrowser.ts +0 -2
  449. package/src/utils/isValidNumber.ts +0 -8
  450. package/src/utils/jsonUtils.ts +0 -8
  451. package/src/utils/replaceVarInString.ts +0 -9
  452. package/src/utils/setConfigs.ts +0 -24
  453. package/src/utils/showZero.tsx +0 -10
  454. package/src/validators/index.ts +0 -61
@@ -0,0 +1,573 @@
1
+ /**
2
+ * `<Tickets/>` — ticket selection. Lists the event's ticket types with a
3
+ * quantity dropdown, applies promo / access codes (re-pricing + unlocking
4
+ * tickets), offers a waiting-list sign-up on sold-out types, and primes the
5
+ * cart. Matches the old checkout: no running total, a `GET TICKETS` CTA.
6
+ */
7
+ import React, {
8
+ Fragment,
9
+ useEffect,
10
+ useRef,
11
+ useState,
12
+ type FC,
13
+ type ReactNode,
14
+ } from 'react'
15
+
16
+ import {
17
+ errorMessage,
18
+ hooks,
19
+ ticketQuantityRange,
20
+ type TicketType,
21
+ type WaitingListEntry,
22
+ } from 'tf-checkout-shared'
23
+
24
+ import { Button } from '../ui/Button'
25
+ import { Card, SectionHeader } from '../ui/Card'
26
+ import { useCheckoutContext } from '../ui/CheckoutProvider'
27
+ import { cx } from '../ui/cx'
28
+ import { Field, FieldRow, Input } from '../ui/Field'
29
+ import { Loader } from '../ui/Loader'
30
+ import { QuantitySelect } from '../ui/QuantitySelect'
31
+
32
+ /** Inline waiting-list sign-up for a sold-out type. */
33
+ const WaitingListForm: FC<{
34
+ ticket: TicketType
35
+ onJoin: (entry: WaitingListEntry) => Promise<void>
36
+ }> = ({ ticket, onJoin }) => {
37
+ const [form, setForm] = useState({ firstName: '', lastName: '', email: '' })
38
+ const [state, setState] = useState<'idle' | 'busy' | 'done' | 'error'>('idle')
39
+ const [error, setError] = useState('')
40
+ const ok = form.firstName.trim() && form.lastName.trim() && form.email.trim()
41
+
42
+ if (state === 'done')
43
+ return (
44
+ <p className="tf-checkout-note tf-checkout-tickets__wl-done">
45
+ You’re on the waiting list — we’ll email you if a spot opens.
46
+ </p>
47
+ )
48
+
49
+ return (
50
+ <div className="tf-checkout-tickets__wl">
51
+ <FieldRow>
52
+ <Field>
53
+ <Input
54
+ placeholder="First name"
55
+ value={form.firstName}
56
+ onChange={(e) => setForm((f) => ({ ...f, firstName: e.target.value }))}
57
+ />
58
+ </Field>
59
+ <Field>
60
+ <Input
61
+ placeholder="Last name"
62
+ value={form.lastName}
63
+ onChange={(e) => setForm((f) => ({ ...f, lastName: e.target.value }))}
64
+ />
65
+ </Field>
66
+ </FieldRow>
67
+ <Field>
68
+ <Input
69
+ placeholder="Email"
70
+ value={form.email}
71
+ onChange={(e) => setForm((f) => ({ ...f, email: e.target.value }))}
72
+ />
73
+ </Field>
74
+ <Button
75
+ onClick={() => {
76
+ setState('busy')
77
+ setError('')
78
+ onJoin({ ...form, ticketTypeId: ticket.id })
79
+ .then(() => setState('done'))
80
+ .catch((e) => {
81
+ setState('error')
82
+ setError(errorMessage(e))
83
+ })
84
+ }}
85
+ loading={state === 'busy'}
86
+ disabled={!ok || state === 'busy'}
87
+ variant="secondary"
88
+ >
89
+ Join the waiting list
90
+ </Button>
91
+ {error && <p className="tf-checkout-error-text">{error}</p>}
92
+ </div>
93
+ )
94
+ }
95
+
96
+ export interface TicketsProps {
97
+ eventId: string
98
+ /** Optional heading above the catalog. The legacy storefront does not show
99
+ * one, so the default is intentionally hidden. */
100
+ title?: ReactNode | false
101
+ /** Fired once the cart is primed (tickets added) — e.g. reveal `<AddOns/>`. */
102
+ onContinue?: () => void
103
+ /** CTA label. Old storefront uses "Get tickets". */
104
+ buttonLabel?: string
105
+ /** Force time-slot mode + supply the selectable session dates (ISO yyyy-mm-dd).
106
+ * Omit to auto-detect from the event (`isTimeSlotEvent` / `availableDates`). */
107
+ timeSlotDates?: string[]
108
+ /** Optional numbered badge (old checkout shows none — omitted by default). */
109
+ step?: ReactNode
110
+ /** SEATED events: fired when the buyer clicks "Select seats". Wire this to
111
+ * reveal `<SeatMap/>`. Without it the seat CTA is hidden (the seat-map ticket
112
+ * types then have no way to be bought — provide it for seated events). */
113
+ onSelectSeats?: () => void
114
+ /** Apply this code once when the ticket catalog mounts. */
115
+ initialPromoCode?: string
116
+ /** Attribute this visit once. URL values use `ttf_r` / `referrer_id`. */
117
+ referrer?: string | number
118
+ /** Also read promo/referral values from the current URL. Defaults true. */
119
+ readAttributionFromUrl?: boolean
120
+ className?: string
121
+ }
122
+
123
+ export const Tickets: FC<TicketsProps> = ({
124
+ eventId,
125
+ title = false,
126
+ onContinue,
127
+ buttonLabel = 'Get tickets',
128
+ timeSlotDates,
129
+ step,
130
+ onSelectSeats,
131
+ initialPromoCode,
132
+ referrer,
133
+ readAttributionFromUrl = true,
134
+ className,
135
+ }) => {
136
+ const checkout = useCheckoutContext()
137
+ const ticketsQuery = hooks.useTicketsWithMeta(eventId)
138
+ const promoMeta = ticketsQuery.data?.promo
139
+ const showWaitingList = ticketsQuery.data?.showWaitingList ?? false
140
+
141
+ const [qty, setQty] = useState<Record<string, number>>({})
142
+ const [slotDate, setSlotDate] = useState('')
143
+
144
+ // Time-slot / calendar events: pick a date, then buy from that session's slots.
145
+ const eventInfo = hooks.useEvent(eventId).data
146
+ const isTimeSlot = Boolean(timeSlotDates?.length || eventInfo?.isTimeSlotEvent)
147
+ const dates = timeSlotDates ?? eventInfo?.availableDates ?? []
148
+ useEffect(() => {
149
+ if (isTimeSlot && !slotDate && dates.length) setSlotDate(dates[0])
150
+ }, [isTimeSlot, slotDate, dates])
151
+ const slotQuery = hooks.useTimeSlotTickets(eventId, isTimeSlot ? slotDate : undefined)
152
+
153
+ const tickets = isTimeSlot ? (slotQuery.data ?? []) : (ticketsQuery.data?.tickets ?? [])
154
+ const [error, setError] = useState('')
155
+ const [code, setCode] = useState('')
156
+ const [codeState, setCodeState] = useState<'idle' | 'busy'>('idle')
157
+ const [promoOpen, setPromoOpen] = useState(false)
158
+ const [wlOpen, setWlOpen] = useState<Record<string, boolean>>({})
159
+ const [visibleDescription, setVisibleDescription] = useState<string | null>(null)
160
+ const attributionEvent = useRef<string | null>(null)
161
+
162
+ // Match hosted links: attribute referral visits and apply a carried promo
163
+ // once per event. Explicit props win; URL support can be disabled by hosts
164
+ // that manage routing/attribution themselves.
165
+ useEffect(() => {
166
+ if (attributionEvent.current === eventId) return
167
+ attributionEvent.current = eventId
168
+
169
+ let promo = initialPromoCode?.trim() ?? ''
170
+ let referral: string | number | undefined = referrer
171
+ if (readAttributionFromUrl && typeof window !== 'undefined') {
172
+ const params = new URLSearchParams(window.location.search)
173
+ promo ||= params.get('promo')?.trim() || params.get('promo_code')?.trim() || ''
174
+ referral ??= params.get('ttf_r') || params.get('referrer_id') || undefined
175
+ }
176
+
177
+ if (referral !== undefined && String(referral).trim()) {
178
+ checkout.attributeReferrer(eventId, referral).catch(() => undefined)
179
+ }
180
+ if (promo) {
181
+ setCode(promo)
182
+ setPromoOpen(true)
183
+ setCodeState('busy')
184
+ checkout
185
+ .applyPromoCode(eventId, promo)
186
+ .catch(() => undefined)
187
+ .finally(() => {
188
+ ticketsQuery.refetch().finally(() => setCodeState('idle'))
189
+ })
190
+ }
191
+ // Checkout actions and query functions are stable; this effect is scoped to
192
+ // one attribution pass per event rather than every render.
193
+ // eslint-disable-next-line react-hooks/exhaustive-deps
194
+ }, [eventId, initialPromoCode, referrer, readAttributionFromUrl])
195
+
196
+ // Seed the currency state once so a multi-currency event can offer a switcher
197
+ // on the ticket screen (before the cart is primed). No-op for single-currency.
198
+ useEffect(() => {
199
+ checkout.syncCurrency(eventId, undefined, { seed: true }).catch(() => undefined)
200
+ // eslint-disable-next-line react-hooks/exhaustive-deps
201
+ }, [eventId])
202
+
203
+ const changeCurrency = (code: string) => {
204
+ checkout
205
+ .syncCurrency(eventId, code)
206
+ .then((res) => {
207
+ if (res.requiresCatalogRefresh) {
208
+ setQty({})
209
+ ticketsQuery.refetch()
210
+ }
211
+ })
212
+ .catch(() => undefined)
213
+ }
214
+
215
+ // Remember each type's first-seen (pre-promo) price so a discount can strike it.
216
+ const originals = useRef<Record<string, number>>({})
217
+ useEffect(() => {
218
+ for (const t of tickets)
219
+ if (originals.current[t.id] == null) originals.current[t.id] = t.price
220
+ }, [tickets])
221
+
222
+ const selected = tickets.filter((t) => (qty[t.id] ?? 0) > 0)
223
+ // The current selection's kind — drives the CTA label and the mutual-exclusion
224
+ // rule below (a table order and a ticket order can't be combined).
225
+ const selectionIsTable = selected.some((t) => t.isTable)
226
+ const allowMultiple = eventInfo?.allowMultipleTicketTypePurchases === true
227
+
228
+ // Ported from the old checkout's `handleTicketSelect`: unless the event opts
229
+ // into multiple types (`allowMultipleTicketTypePurchases`), a new selection
230
+ // REPLACES the previous one — one ticket type per order. Even when multiple
231
+ // are allowed, switching between a table and a regular ticket clears the rest.
232
+ const selectQty = (t: TicketType, value: number) =>
233
+ setQty((prev) => {
234
+ const activeIds = Object.keys(prev).filter((k) => (prev[k] ?? 0) > 0)
235
+ const prevIsTable = activeIds.length
236
+ ? Boolean(tickets.find((x) => x.id === activeIds[0])?.isTable)
237
+ : t.isTable
238
+ const switchingKind = activeIds.length > 0 && prevIsTable !== t.isTable
239
+
240
+ if (!allowMultiple) return value > 0 ? { [t.id]: value } : {}
241
+ if (switchingKind && value > 0) return { [t.id]: value }
242
+ const next = { ...prev }
243
+ if (value > 0) next[t.id] = value
244
+ else delete next[t.id]
245
+ return next
246
+ })
247
+
248
+ const money = (sym: string, n: number) => `${sym} ${Number(n).toFixed(2)}`
249
+
250
+ // Seated events: the buyer picks on a seat map, so seat-map ticket types show
251
+ // read-only (no quantity dropdown) and the CTA becomes "Select seats". A type
252
+ // with `allowDirectPurchase` opts out and keeps its dropdown.
253
+ const isSeated = eventInfo?.isSeatedEvent ?? false
254
+ const seatMapRow = (t: TicketType) => isSeated && !t.allowDirectPurchase
255
+ const hasSeatMapTickets = tickets.some(seatMapRow)
256
+ // Types that can still be bought with a quantity dropdown (all of them for a
257
+ // non-seated event). When empty on a seated event, only "Select seats" shows.
258
+ const directPurchasable = tickets.filter((t) => !seatMapRow(t))
259
+ const seatCtaLabel = eventInfo?.tableMapEnabled ? 'Select on map' : 'Select seats'
260
+
261
+ // A "Tables" divider before the first table type — only when regular tickets
262
+ // actually precede it (a tables-first list gets no stray divider).
263
+ const firstTableIndex = tickets.findIndex((t) => t.isTable)
264
+ const firstTableId =
265
+ firstTableIndex > 0 && tickets.slice(0, firstTableIndex).some((t) => !t.isTable)
266
+ ? tickets[firstTableIndex].id
267
+ : undefined
268
+
269
+ const prime = () => {
270
+ setError('')
271
+ checkout
272
+ .setTickets(
273
+ eventId,
274
+ selected.map((t) => ({ ...t, quantity: qty[t.id] }))
275
+ )
276
+ .then(() => onContinue?.())
277
+ .catch((e) => setError(errorMessage(e)))
278
+ }
279
+
280
+ const applyCode = () => {
281
+ if (!code.trim()) return
282
+ setCodeState('busy')
283
+ checkout
284
+ .applyPromoCode(eventId, code.trim())
285
+ .catch(() => undefined)
286
+ .finally(() => {
287
+ ticketsQuery.refetch().finally(() => setCodeState('idle'))
288
+ })
289
+ }
290
+
291
+ const isAccess = promoMeta?.isAccessCodeEnabled
292
+ const showCodeInput = promoMeta?.isPromotionsEnabled || isAccess
293
+ const listQuery = isTimeSlot ? slotQuery : ticketsQuery
294
+
295
+ const renderRow = (t: TicketType) => {
296
+ const notStarted = !t.salesStarted
297
+ const unavailable = t.soldOut || t.salesEnded || notStarted
298
+ const original = originals.current[t.id]
299
+ const discounted = original != null && original > t.price
300
+ const canWaitlist =
301
+ t.soldOut && (t.waitingListEnabled || showWaitingList) && !t.salesEnded
302
+ const isFree = Number(t.price) === 0
303
+ const sym = t.priceSymbol || t.currency
304
+ const range = ticketQuantityRange(t)
305
+ const ticketIndex = tickets.findIndex((candidate) => candidate.id === t.id)
306
+ const previousTicket = ticketIndex > 0 ? tickets[ticketIndex - 1] : undefined
307
+ const startsNamedGroup =
308
+ Boolean(t.groupName) && t.groupName !== previousTicket?.groupName
309
+ return (
310
+ <Fragment key={t.id}>
311
+ {startsNamedGroup ? (
312
+ <div className="tf-checkout-tickets__group">{t.groupName}</div>
313
+ ) : (
314
+ t.id === firstTableId && (
315
+ <div className="tf-checkout-tickets__group">Reserve tables</div>
316
+ )
317
+ )}
318
+ <div className="tf-checkout-tickets__row-wrap">
319
+ <div className="tf-checkout-tickets__row">
320
+ <div className="tf-checkout-tickets__info">
321
+ <div className="tf-checkout-tickets__name">
322
+ <span>{t.name}</span>
323
+ {t.descriptionRich && (
324
+ <button
325
+ type="button"
326
+ className="tf-checkout-tickets__description-toggle"
327
+ aria-expanded={visibleDescription === t.id}
328
+ aria-controls={`ticket-description-${t.id}`}
329
+ onClick={() =>
330
+ setVisibleDescription((current) => (current === t.id ? null : t.id))
331
+ }
332
+ >
333
+ {visibleDescription === t.id ? 'Hide info' : 'View info'}
334
+ </button>
335
+ )}
336
+ </div>
337
+ <div className="tf-checkout-tickets__price">
338
+ {discounted && (
339
+ <span className="tf-checkout-tickets__old">
340
+ {money(sym, original!)}
341
+ </span>
342
+ )}
343
+ <span
344
+ className={cx(
345
+ 'tf-checkout-tickets__amount',
346
+ isFree && 'tf-checkout-tickets__amount--free'
347
+ )}
348
+ >
349
+ {isFree ? 'FREE' : money(sym, t.price)}
350
+ </span>
351
+ {/* Fees sub-line (the "(… with fees)" the old checkout shows) —
352
+ omitted for free/sold-out types. */}
353
+ {!isFree && !t.soldOut && (
354
+ <span className="tf-checkout-tickets__fees">
355
+ ({money(sym, t.priceWithFees)} with fees)
356
+ </span>
357
+ )}
358
+ {t.depositPercent != null && (
359
+ <span className="tf-checkout-tickets__deposit">
360
+ {t.depositPercent.toFixed(2)}% DEPOSIT
361
+ </span>
362
+ )}
363
+ </div>
364
+ </div>
365
+ {/* Seat-map types are read-only here — no quantity control; the buyer
366
+ picks them on the map via "Select seats". */}
367
+ {seatMapRow(t) ? null : unavailable ? (
368
+ <span className="tf-checkout-tickets__soldout">
369
+ {t.soldOut
370
+ ? 'Sold out'
371
+ : notStarted
372
+ ? 'Sales not started'
373
+ : 'Sales Ended'}
374
+ </span>
375
+ ) : (
376
+ <div className="tf-checkout-tickets__qty">
377
+ {/* Tables pick a number of GUESTS (bounded by minGuests/maxGuests),
378
+ not a count of tickets — the label makes that explicit, matching
379
+ the old checkout's "GUESTS" affordance. */}
380
+ {t.isTable && <span className="tf-checkout-tickets__guests">Guests</span>}
381
+ <QuantitySelect
382
+ value={qty[t.id] ?? 0}
383
+ min={range.min}
384
+ max={range.max}
385
+ step={range.step}
386
+ onChange={(v) => selectQty(t, v)}
387
+ />
388
+ </div>
389
+ )}
390
+ </div>
391
+ {t.descriptionRich && visibleDescription === t.id && (
392
+ <div
393
+ id={`ticket-description-${t.id}`}
394
+ className="tf-checkout-tickets__description"
395
+ dangerouslySetInnerHTML={{ __html: t.descriptionRich }}
396
+ />
397
+ )}
398
+ {canWaitlist &&
399
+ (wlOpen[t.id] ? (
400
+ <WaitingListForm
401
+ ticket={t}
402
+ onJoin={(entry) => checkout.joinWaitingList(eventId, entry)}
403
+ />
404
+ ) : (
405
+ <button
406
+ type="button"
407
+ className="tf-checkout-tickets__wl-toggle"
408
+ onClick={() => setWlOpen((w) => ({ ...w, [t.id]: true }))}
409
+ >
410
+ Join the waiting list
411
+ </button>
412
+ ))}
413
+ </div>
414
+ </Fragment>
415
+ )
416
+ }
417
+
418
+ // Time-slot layout groups the date's tickets under their time heading.
419
+ const timeGroups: { time: string; items: TicketType[] }[] = []
420
+ if (isTimeSlot)
421
+ for (const t of tickets) {
422
+ const time = t.timeSlot?.time ?? ''
423
+ const g = timeGroups.find((x) => x.time === time)
424
+ if (g) g.items.push(t)
425
+ else timeGroups.push({ time, items: [t] })
426
+ }
427
+
428
+ return (
429
+ <Card className={cx('tf-checkout-tickets', className)}>
430
+ {(title !== false || step != null) && (
431
+ <SectionHeader
432
+ step={step}
433
+ title={title || ''}
434
+ pills={listQuery.isFetching && !listQuery.isLoading ? <Loader /> : undefined}
435
+ />
436
+ )}
437
+
438
+ {listQuery.isLoading && (
439
+ <div className="tf-checkout-tickets__loading">
440
+ <Loader className="tf-checkout-tickets__loading-spinner" />
441
+ </div>
442
+ )}
443
+
444
+ {listQuery.error && (
445
+ <p className="tf-checkout-error-text">{(listQuery.error as Error).message}</p>
446
+ )}
447
+
448
+ {isTimeSlot && dates.length > 0 && (
449
+ <div className="tf-checkout-tickets__currency">
450
+ <span className="tf-checkout-tickets__currency-label">Date</span>
451
+ <select
452
+ className="tf-checkout-select"
453
+ value={slotDate}
454
+ onChange={(e) => {
455
+ setSlotDate(e.target.value)
456
+ setQty({})
457
+ }}
458
+ >
459
+ {dates.map((d) => (
460
+ <option key={d} value={d}>
461
+ {d}
462
+ </option>
463
+ ))}
464
+ </select>
465
+ </div>
466
+ )}
467
+
468
+ {checkout.currency && checkout.currency.available.length > 1 && (
469
+ <div className="tf-checkout-tickets__currency">
470
+ <span className="tf-checkout-tickets__currency-label">Currency</span>
471
+ <select
472
+ className="tf-checkout-select"
473
+ value={checkout.currency.currency}
474
+ onChange={(e) => changeCurrency(e.target.value)}
475
+ >
476
+ {checkout.currency.available.map((c) => (
477
+ <option key={c.code} value={c.code}>
478
+ {c.name} ({c.code})
479
+ </option>
480
+ ))}
481
+ </select>
482
+ </div>
483
+ )}
484
+
485
+ {isTimeSlot && !slotQuery.isLoading && tickets.length === 0 && slotDate && (
486
+ <p className="tf-checkout-note">No sessions available on this date.</p>
487
+ )}
488
+
489
+ {isTimeSlot
490
+ ? timeGroups.map((g) => (
491
+ <Fragment key={g.time}>
492
+ {g.time && <div className="tf-checkout-tickets__slot-time">{g.time}</div>}
493
+ {g.items.map(renderRow)}
494
+ </Fragment>
495
+ ))
496
+ : tickets.map(renderRow)}
497
+
498
+ {/* Promo / access code */}
499
+ {showCodeInput && (
500
+ <div className="tf-checkout-tickets__promo">
501
+ {!isAccess && !promoOpen ? (
502
+ <button
503
+ type="button"
504
+ className="tf-checkout-tickets__promo-toggle"
505
+ onClick={() => setPromoOpen(true)}
506
+ >
507
+ Got a promo code? Click here
508
+ </button>
509
+ ) : (
510
+ <>
511
+ <FieldRow>
512
+ <Field>
513
+ <Input
514
+ placeholder={isAccess ? 'Access code' : 'Promo code'}
515
+ value={code}
516
+ onChange={(e) => setCode(e.target.value)}
517
+ onKeyDown={(e) => e.key === 'Enter' && applyCode()}
518
+ />
519
+ </Field>
520
+ <Button
521
+ variant="secondary"
522
+ onClick={applyCode}
523
+ loading={codeState === 'busy'}
524
+ disabled={codeState === 'busy' || !code.trim()}
525
+ >
526
+ {isAccess ? 'ENTER' : 'APPLY'}
527
+ </Button>
528
+ </FieldRow>
529
+ {promoMeta?.promoCodeMessage && (
530
+ <p
531
+ className={cx(
532
+ 'tf-checkout-note',
533
+ promoMeta.promoCodeValid === false && 'tf-checkout-error-text'
534
+ )}
535
+ >
536
+ {promoMeta.promoCodeMessage}
537
+ </p>
538
+ )}
539
+ </>
540
+ )}
541
+ </div>
542
+ )}
543
+
544
+ {/* Direct-purchase CTA — hidden on a fully-seated event (nothing to buy by
545
+ quantity; the seat map is the only path). */}
546
+ {directPurchasable.length > 0 && (
547
+ <Button
548
+ block
549
+ onClick={prime}
550
+ loading={checkout.isBusy}
551
+ disabled={checkout.isBusy || selected.length === 0}
552
+ >
553
+ {checkout.isBusy
554
+ ? 'Reserving…'
555
+ : selectionIsTable
556
+ ? 'Reserve tables'
557
+ : buttonLabel}
558
+ </Button>
559
+ )}
560
+
561
+ {/* Seated events: hand off to the seat map instead of quantity selection. */}
562
+ {hasSeatMapTickets && (
563
+ <Button block onClick={() => onSelectSeats?.()}>
564
+ {seatCtaLabel}
565
+ </Button>
566
+ )}
567
+
568
+ {(error || checkout.error) && (
569
+ <p className="tf-checkout-error-text">{error || checkout.error}</p>
570
+ )}
571
+ </Card>
572
+ )
573
+ }