tf-checkout-react 1.7.30 → 2.0.0-beta.0

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 (453) 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 +3930 -0
  5. package/dist/index.d.ts +3930 -30
  6. package/dist/index.esm.js +9123 -0
  7. package/dist/index.esm.js.map +1 -0
  8. package/dist/index.js +9277 -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 +231 -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 +743 -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 +541 -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 +119 -0
  50. package/src/sections/billing/types.ts +10 -0
  51. package/src/sections/index.ts +15 -0
  52. package/src/sections/seatMap.utils.ts +105 -0
  53. package/src/styles/addons.css +75 -0
  54. package/src/styles/auth.css +294 -0
  55. package/src/styles/billing.css +98 -0
  56. package/src/styles/confirmation.css +51 -0
  57. package/src/styles/foundation.css +146 -0
  58. package/src/styles/payment.css +179 -0
  59. package/src/styles/primitives.css +356 -0
  60. package/src/styles/seat-map.css +46 -0
  61. package/src/styles/tickets.css +285 -0
  62. package/src/styles/verification-confirmation.css +258 -0
  63. package/src/typings.d.ts +2 -2
  64. package/src/ui/Button.tsx +38 -0
  65. package/src/ui/Card.tsx +54 -0
  66. package/src/ui/CheckoutProvider.tsx +172 -0
  67. package/src/ui/CustomFields.tsx +195 -0
  68. package/src/ui/Field.tsx +114 -0
  69. package/src/ui/I18nProvider.tsx +36 -0
  70. package/src/ui/InstallmentPicker.tsx +69 -0
  71. package/src/ui/Loader.tsx +12 -0
  72. package/src/ui/PaymentMethods.tsx +133 -0
  73. package/src/ui/PriceLine.tsx +24 -0
  74. package/src/ui/QuantitySelect.tsx +50 -0
  75. package/src/ui/Stepper.tsx +36 -0
  76. package/src/ui/Timer.tsx +34 -0
  77. package/src/ui/TimerBanner.tsx +55 -0
  78. package/src/ui/cx.ts +3 -0
  79. package/src/ui/index.ts +54 -0
  80. package/src/ui/theme.ts +83 -0
  81. package/src/useCheckout.ts +35 -0
  82. package/src/xendit.ts +438 -0
  83. package/dist/adapters/customFields.d.ts +0 -12
  84. package/dist/adapters/index.d.ts +0 -1
  85. package/dist/api/auth.d.ts +0 -27
  86. package/dist/api/cart.d.ts +0 -2
  87. package/dist/api/checkout.d.ts +0 -3
  88. package/dist/api/common.d.ts +0 -11
  89. package/dist/api/guestTicketDelegation.d.ts +0 -47
  90. package/dist/api/index.d.ts +0 -82
  91. package/dist/api/interceptors.d.ts +0 -1
  92. package/dist/api/orders.d.ts +0 -2
  93. package/dist/api/payment.d.ts +0 -5
  94. package/dist/api/preRegistrationComplete.d.ts +0 -3
  95. package/dist/api/publicRequest.d.ts +0 -9
  96. package/dist/api/resale.d.ts +0 -5
  97. package/dist/components/account-settings/index.d.ts +0 -3
  98. package/dist/components/addonsContainer/AddonComponent.d.ts +0 -18
  99. package/dist/components/addonsContainer/SimpleAddonsContainer.d.ts +0 -20
  100. package/dist/components/addonsContainer/adapters/index.d.ts +0 -12
  101. package/dist/components/addonsContainer/index.d.ts +0 -22
  102. package/dist/components/addonsContainer/normalizers/index.d.ts +0 -1
  103. package/dist/components/addonsContainer/useAddons.d.ts +0 -23
  104. package/dist/components/addonsContainer/utils/index.d.ts +0 -16
  105. package/dist/components/billing-info-container/hooks/index.d.ts +0 -3
  106. package/dist/components/billing-info-container/hooks/usePaymentContext.d.ts +0 -5
  107. package/dist/components/billing-info-container/hooks/usePaymentRedirect.d.ts +0 -14
  108. package/dist/components/billing-info-container/hooks/useStripePayment.d.ts +0 -18
  109. package/dist/components/billing-info-container/index.d.ts +0 -69
  110. package/dist/components/billing-info-container/utils.d.ts +0 -59
  111. package/dist/components/common/Checkbox.d.ts +0 -11
  112. package/dist/components/common/CheckboxField/index.d.ts +0 -9
  113. package/dist/components/common/CopyField.d.ts +0 -12
  114. package/dist/components/common/CopyMessageModal.d.ts +0 -7
  115. package/dist/components/common/CustomField.d.ts +0 -26
  116. package/dist/components/common/DatePickerField.d.ts +0 -20
  117. package/dist/components/common/FieldSection/index.d.ts +0 -19
  118. package/dist/components/common/FieldSection/utils/index.d.ts +0 -8
  119. package/dist/components/common/FormikPhoneNumberField.d.ts +0 -11
  120. package/dist/components/common/Loader.d.ts +0 -2
  121. package/dist/components/common/ModalComponent/index.d.ts +0 -16
  122. package/dist/components/common/NativeSelectFeild/index.d.ts +0 -21
  123. package/dist/components/common/PhoneNumberField.d.ts +0 -14
  124. package/dist/components/common/PoweredBy.d.ts +0 -2
  125. package/dist/components/common/RadioField.d.ts +0 -11
  126. package/dist/components/common/RadioGroupField/index.d.ts +0 -17
  127. package/dist/components/common/RedirectModal.d.ts +0 -7
  128. package/dist/components/common/SelectField/index.d.ts +0 -19
  129. package/dist/components/common/SnackbarAlert.d.ts +0 -13
  130. package/dist/components/common/index.d.ts +0 -11
  131. package/dist/components/common/socials.d.ts +0 -10
  132. package/dist/components/confirmModal/index.d.ts +0 -10
  133. package/dist/components/confirmationContainer/config.d.ts +0 -1
  134. package/dist/components/confirmationContainer/index.d.ts +0 -46
  135. package/dist/components/confirmationContainer/social-buttons.d.ts +0 -16
  136. package/dist/components/countdown/index.d.ts +0 -14
  137. package/dist/components/delegationsContainer/IssueComponent.d.ts +0 -10
  138. package/dist/components/delegationsContainer/IssueTicketForm.d.ts +0 -9
  139. package/dist/components/delegationsContainer/TicketsAssignedTable.d.ts +0 -11
  140. package/dist/components/delegationsContainer/TicketsAvailableTable.d.ts +0 -11
  141. package/dist/components/delegationsContainer/index.d.ts +0 -10
  142. package/dist/components/forgotPasswordModal/index.d.ts +0 -12
  143. package/dist/components/idVerificationContainer/VerificationPendingModal.d.ts +0 -10
  144. package/dist/components/idVerificationContainer/constants.d.ts +0 -21
  145. package/dist/components/idVerificationContainer/index.d.ts +0 -16
  146. package/dist/components/index.d.ts +0 -12
  147. package/dist/components/loginForm/index.d.ts +0 -31
  148. package/dist/components/loginModal/SignUpForm.d.ts +0 -10
  149. package/dist/components/loginModal/constants.d.ts +0 -39
  150. package/dist/components/loginModal/index.d.ts +0 -22
  151. package/dist/components/myTicketsContainer/index.d.ts +0 -16
  152. package/dist/components/myTicketsContainer/row.d.ts +0 -3
  153. package/dist/components/myTicketsContainer/tableConfig.d.ts +0 -5
  154. package/dist/components/orderDetailsContainer/CustomFieldsForm.d.ts +0 -12
  155. package/dist/components/orderDetailsContainer/TicketHolderCustomFields.d.ts +0 -10
  156. package/dist/components/orderDetailsContainer/index.d.ts +0 -66
  157. package/dist/components/orderDetailsContainer/ticketsTable.d.ts +0 -46
  158. package/dist/components/orderDetailsContainer/utils/index.d.ts +0 -6
  159. package/dist/components/paymentContainer/OrderDetails.d.ts +0 -9
  160. package/dist/components/paymentContainer/PaymentPlanSection.d.ts +0 -10
  161. package/dist/components/paymentContainer/handlePayment.d.ts +0 -15
  162. package/dist/components/paymentContainer/index.d.ts +0 -39
  163. package/dist/components/preRegistration/FieldsSection.d.ts +0 -19
  164. package/dist/components/preRegistration/Influancers.d.ts +0 -2
  165. package/dist/components/preRegistration/PreRegistrationComplete.d.ts +0 -13
  166. package/dist/components/preRegistration/PreRegistrationInformations.d.ts +0 -2
  167. package/dist/components/preRegistration/Prewards.d.ts +0 -2
  168. package/dist/components/preRegistration/ShareOptions.d.ts +0 -2
  169. package/dist/components/preRegistration/constants.d.ts +0 -2
  170. package/dist/components/preRegistration/index.d.ts +0 -23
  171. package/dist/components/preRegistration/utils.d.ts +0 -12
  172. package/dist/components/registerForm/adapters/index.d.ts +0 -4
  173. package/dist/components/registerForm/constants.d.ts +0 -1
  174. package/dist/components/registerForm/index.d.ts +0 -16
  175. package/dist/components/registerModal/index.d.ts +0 -12
  176. package/dist/components/resetPasswordContainer/index.d.ts +0 -10
  177. package/dist/components/rsvpContainer/index.d.ts +0 -7
  178. package/dist/components/seatMapContainer/SeatMapComponent.d.ts +0 -8
  179. package/dist/components/seatMapContainer/TicketsSection.d.ts +0 -9
  180. package/dist/components/seatMapContainer/addToCart.d.ts +0 -14
  181. package/dist/components/seatMapContainer/index.d.ts +0 -2
  182. package/dist/components/seatMapContainer/utils.d.ts +0 -6
  183. package/dist/components/signupModal/index.d.ts +0 -12
  184. package/dist/components/ticketResale/index.d.ts +0 -12
  185. package/dist/components/ticketResaleModal/index.d.ts +0 -19
  186. package/dist/components/ticketsContainer/AccessCodeSection.d.ts +0 -7
  187. package/dist/components/ticketsContainer/InfoIcon.d.ts +0 -5
  188. package/dist/components/ticketsContainer/PromoCodeSection.d.ts +0 -15
  189. package/dist/components/ticketsContainer/ReferralLogic.d.ts +0 -5
  190. package/dist/components/ticketsContainer/TicketRow.d.ts +0 -13
  191. package/dist/components/ticketsContainer/TicketsSection.d.ts +0 -20
  192. package/dist/components/ticketsContainer/TimeSlotTicketRow.d.ts +0 -19
  193. package/dist/components/ticketsContainer/TimeSlotsSection.d.ts +0 -25
  194. package/dist/components/ticketsContainer/index.d.ts +0 -93
  195. package/dist/components/ticketsContainer/utils.d.ts +0 -13
  196. package/dist/components/timerWidget/index.d.ts +0 -16
  197. package/dist/components/waitingList/index.d.ts +0 -9
  198. package/dist/constants/index.d.ts +0 -7
  199. package/dist/env.d.ts +0 -16
  200. package/dist/hoc/CustomFields/index.d.ts +0 -3
  201. package/dist/hoc/index.d.ts +0 -1
  202. package/dist/hooks/index.d.ts +0 -1
  203. package/dist/hooks/useCookieListener.d.ts +0 -1
  204. package/dist/hooks/useEventListener.d.ts +0 -1
  205. package/dist/hooks/useLocalStorageListener.d.ts +0 -1
  206. package/dist/hooks/useOnline.d.ts +0 -1
  207. package/dist/hooks/usePixel.d.ts +0 -6
  208. package/dist/images/Polygon.png +0 -0
  209. package/dist/images/cross.svg +0 -44
  210. package/dist/images/done.svg +0 -3
  211. package/dist/images/edit.svg +0 -10
  212. package/dist/images/email.svg +0 -1
  213. package/dist/images/instagram.svg +0 -5
  214. package/dist/images/logo-ttf.png +0 -0
  215. package/dist/images/spotify.svg +0 -6
  216. package/dist/images/user.svg +0 -1
  217. package/dist/images/xmark.svg +0 -92
  218. package/dist/normalizers/index.d.ts +0 -4
  219. package/dist/tf-checkout-react.cjs.development.js +0 -16149
  220. package/dist/tf-checkout-react.cjs.development.js.map +0 -1
  221. package/dist/tf-checkout-react.cjs.production.min.js +0 -2
  222. package/dist/tf-checkout-react.cjs.production.min.js.map +0 -1
  223. package/dist/tf-checkout-react.esm.js +0 -16116
  224. package/dist/tf-checkout-react.esm.js.map +0 -1
  225. package/dist/tf-checkout-styles.css +0 -1
  226. package/dist/types/add_on.d.ts +0 -8
  227. package/dist/types/billing-info-data.d.ts +0 -27
  228. package/dist/types/checkoutPageConfigs.d.ts +0 -13
  229. package/dist/types/index.d.ts +0 -6
  230. package/dist/types/order-data.d.ts +0 -15
  231. package/dist/types/payment-field.d.ts +0 -6
  232. package/dist/types/payment-plan-configuration.d.ts +0 -18
  233. package/dist/types/referral-promotion.d.ts +0 -6
  234. package/dist/types/verification.d.ts +0 -12
  235. package/dist/utils/adaptStripeErrors.d.ts +0 -8
  236. package/dist/utils/auth.d.ts +0 -21
  237. package/dist/utils/cookies.d.ts +0 -3
  238. package/dist/utils/createCheckoutDataBodyWithDefaultHolder.d.ts +0 -23
  239. package/dist/utils/createMarkup.d.ts +0 -3
  240. package/dist/utils/customFields.d.ts +0 -35
  241. package/dist/utils/downloadPDF.d.ts +0 -1
  242. package/dist/utils/form.d.ts +0 -3
  243. package/dist/utils/formikErrorFocus.d.ts +0 -2
  244. package/dist/utils/getDomain.d.ts +0 -1
  245. package/dist/utils/getImage.d.ts +0 -1
  246. package/dist/utils/getQueryVariable.d.ts +0 -1
  247. package/dist/utils/htmlNodeFromString.d.ts +0 -1
  248. package/dist/utils/index.d.ts +0 -15
  249. package/dist/utils/isBrowser.d.ts +0 -1
  250. package/dist/utils/isValidNumber.d.ts +0 -1
  251. package/dist/utils/jsonUtils.d.ts +0 -1
  252. package/dist/utils/replaceVarInString.d.ts +0 -1
  253. package/dist/utils/setConfigs.d.ts +0 -11
  254. package/dist/utils/showZero.d.ts +0 -1
  255. package/dist/validators/index.d.ts +0 -8
  256. package/src/adapters/customFields.ts +0 -85
  257. package/src/adapters/index.ts +0 -1
  258. package/src/api/auth.ts +0 -88
  259. package/src/api/cart.ts +0 -28
  260. package/src/api/checkout.ts +0 -28
  261. package/src/api/common.ts +0 -190
  262. package/src/api/guestTicketDelegation.ts +0 -79
  263. package/src/api/index.ts +0 -346
  264. package/src/api/interceptors.ts +0 -77
  265. package/src/api/orders.ts +0 -30
  266. package/src/api/payment.ts +0 -77
  267. package/src/api/preRegistrationComplete.ts +0 -37
  268. package/src/api/publicRequest.ts +0 -47
  269. package/src/api/resale.ts +0 -28
  270. package/src/assets/images/Polygon.png +0 -0
  271. package/src/assets/images/cross.svg +0 -44
  272. package/src/assets/images/done.svg +0 -3
  273. package/src/assets/images/edit.svg +0 -10
  274. package/src/assets/images/email.svg +0 -1
  275. package/src/assets/images/instagram.svg +0 -5
  276. package/src/assets/images/logo-ttf.png +0 -0
  277. package/src/assets/images/spotify.svg +0 -6
  278. package/src/assets/images/user.svg +0 -1
  279. package/src/assets/images/xmark.svg +0 -92
  280. package/src/components/account-settings/index.tsx +0 -161
  281. package/src/components/account-settings/style.css +0 -200
  282. package/src/components/addonsContainer/AddonComponent.tsx +0 -204
  283. package/src/components/addonsContainer/SimpleAddonsContainer.tsx +0 -459
  284. package/src/components/addonsContainer/adapters/index.tsx +0 -62
  285. package/src/components/addonsContainer/index.tsx +0 -353
  286. package/src/components/addonsContainer/normalizers/index.ts +0 -5
  287. package/src/components/addonsContainer/useAddons.ts +0 -248
  288. package/src/components/addonsContainer/utils/index.tsx +0 -231
  289. package/src/components/billing-info-container/hooks/index.ts +0 -3
  290. package/src/components/billing-info-container/hooks/usePaymentContext.ts +0 -22
  291. package/src/components/billing-info-container/hooks/usePaymentRedirect.ts +0 -145
  292. package/src/components/billing-info-container/hooks/useStripePayment.ts +0 -119
  293. package/src/components/billing-info-container/index.tsx +0 -1695
  294. package/src/components/billing-info-container/style.css +0 -150
  295. package/src/components/billing-info-container/utils.tsx +0 -413
  296. package/src/components/common/Checkbox.tsx +0 -51
  297. package/src/components/common/CheckboxField/index.tsx +0 -41
  298. package/src/components/common/CopyField.tsx +0 -53
  299. package/src/components/common/CopyMessageModal.tsx +0 -34
  300. package/src/components/common/CustomField.tsx +0 -168
  301. package/src/components/common/DatePickerField.tsx +0 -126
  302. package/src/components/common/FieldSection/index.tsx +0 -141
  303. package/src/components/common/FieldSection/utils/index.tsx +0 -92
  304. package/src/components/common/FormikPhoneNumberField.tsx +0 -51
  305. package/src/components/common/Loader.tsx +0 -8
  306. package/src/components/common/ModalComponent/index.tsx +0 -68
  307. package/src/components/common/NativeSelectFeild/index.tsx +0 -86
  308. package/src/components/common/PhoneNumberField.tsx +0 -117
  309. package/src/components/common/PoweredBy.tsx +0 -15
  310. package/src/components/common/RadioField.tsx +0 -36
  311. package/src/components/common/RadioGroupField/index.tsx +0 -76
  312. package/src/components/common/RedirectModal.tsx +0 -43
  313. package/src/components/common/SelectField/index.tsx +0 -104
  314. package/src/components/common/SnackbarAlert.tsx +0 -52
  315. package/src/components/common/index.tsx +0 -11
  316. package/src/components/common/socials.tsx +0 -33
  317. package/src/components/confirmModal/index.tsx +0 -60
  318. package/src/components/confirmationContainer/config.ts +0 -79
  319. package/src/components/confirmationContainer/index.tsx +0 -349
  320. package/src/components/confirmationContainer/social-buttons.tsx +0 -149
  321. package/src/components/confirmationContainer/style.css +0 -206
  322. package/src/components/countdown/index.tsx +0 -100
  323. package/src/components/countdown/style.css +0 -10
  324. package/src/components/delegationsContainer/IssueComponent.tsx +0 -156
  325. package/src/components/delegationsContainer/IssueTicketForm.tsx +0 -109
  326. package/src/components/delegationsContainer/TicketsAssignedTable.tsx +0 -55
  327. package/src/components/delegationsContainer/TicketsAvailableTable.tsx +0 -54
  328. package/src/components/delegationsContainer/index.tsx +0 -83
  329. package/src/components/forgotPasswordModal/index.tsx +0 -138
  330. package/src/components/forgotPasswordModal/style.css +0 -47
  331. package/src/components/idVerificationContainer/VerificationPendingModal.tsx +0 -47
  332. package/src/components/idVerificationContainer/constants.ts +0 -27
  333. package/src/components/idVerificationContainer/index.tsx +0 -323
  334. package/src/components/index.ts +0 -12
  335. package/src/components/loginForm/index.tsx +0 -202
  336. package/src/components/loginModal/SignUpForm.tsx +0 -329
  337. package/src/components/loginModal/constants.ts +0 -46
  338. package/src/components/loginModal/index.tsx +0 -263
  339. package/src/components/loginModal/style.css +0 -116
  340. package/src/components/myTicketsContainer/index.tsx +0 -228
  341. package/src/components/myTicketsContainer/row.tsx +0 -46
  342. package/src/components/myTicketsContainer/style.css +0 -40
  343. package/src/components/myTicketsContainer/tableConfig.tsx +0 -80
  344. package/src/components/myTicketsContainer/types.d.ts +0 -41
  345. package/src/components/orderDetailsContainer/CustomFieldsForm.tsx +0 -75
  346. package/src/components/orderDetailsContainer/TicketHolderCustomFields.tsx +0 -100
  347. package/src/components/orderDetailsContainer/index.tsx +0 -586
  348. package/src/components/orderDetailsContainer/style.css +0 -77
  349. package/src/components/orderDetailsContainer/ticketsTable.tsx +0 -246
  350. package/src/components/orderDetailsContainer/utils/index.tsx +0 -55
  351. package/src/components/paymentContainer/OrderDetails.tsx +0 -277
  352. package/src/components/paymentContainer/PaymentPlanSection.tsx +0 -169
  353. package/src/components/paymentContainer/handlePayment.ts +0 -86
  354. package/src/components/paymentContainer/index.tsx +0 -643
  355. package/src/components/paymentContainer/style.css +0 -196
  356. package/src/components/preRegistration/FieldsSection.tsx +0 -150
  357. package/src/components/preRegistration/Influancers.tsx +0 -34
  358. package/src/components/preRegistration/PreRegistrationComplete.tsx +0 -186
  359. package/src/components/preRegistration/PreRegistrationInformations.tsx +0 -60
  360. package/src/components/preRegistration/Prewards.tsx +0 -41
  361. package/src/components/preRegistration/ShareOptions.tsx +0 -77
  362. package/src/components/preRegistration/constants.tsx +0 -169
  363. package/src/components/preRegistration/index.tsx +0 -330
  364. package/src/components/preRegistration/style.css +0 -3
  365. package/src/components/preRegistration/utils.ts +0 -163
  366. package/src/components/registerForm/adapters/index.tsx +0 -10
  367. package/src/components/registerForm/constants.tsx +0 -98
  368. package/src/components/registerForm/index.tsx +0 -188
  369. package/src/components/registerModal/index.tsx +0 -154
  370. package/src/components/registerModal/style.css +0 -18
  371. package/src/components/resetPasswordContainer/index.tsx +0 -102
  372. package/src/components/resetPasswordContainer/style.css +0 -36
  373. package/src/components/rsvpContainer/index.tsx +0 -126
  374. package/src/components/seatMapContainer/SeatMapComponent.tsx +0 -77
  375. package/src/components/seatMapContainer/TicketsSection.tsx +0 -286
  376. package/src/components/seatMapContainer/addToCart.ts +0 -66
  377. package/src/components/seatMapContainer/index.tsx +0 -443
  378. package/src/components/seatMapContainer/utils.ts +0 -133
  379. package/src/components/signupModal/index.tsx +0 -178
  380. package/src/components/signupModal/style.css +0 -58
  381. package/src/components/ticketResale/index.tsx +0 -86
  382. package/src/components/ticketResaleModal/index.tsx +0 -224
  383. package/src/components/ticketResaleModal/style.css +0 -28
  384. package/src/components/ticketsContainer/AccessCodeSection.tsx +0 -50
  385. package/src/components/ticketsContainer/InfoIcon.tsx +0 -35
  386. package/src/components/ticketsContainer/PromoCodeSection.tsx +0 -116
  387. package/src/components/ticketsContainer/ReferralLogic.tsx +0 -33
  388. package/src/components/ticketsContainer/TicketRow.tsx +0 -107
  389. package/src/components/ticketsContainer/TicketsSection.tsx +0 -350
  390. package/src/components/ticketsContainer/TimeSlotTicketRow.tsx +0 -243
  391. package/src/components/ticketsContainer/TimeSlotsSection.tsx +0 -194
  392. package/src/components/ticketsContainer/index.tsx +0 -986
  393. package/src/components/ticketsContainer/style.css +0 -178
  394. package/src/components/ticketsContainer/utils.ts +0 -35
  395. package/src/components/timerWidget/index.tsx +0 -97
  396. package/src/components/timerWidget/style.css +0 -35
  397. package/src/components/waitingList/index.tsx +0 -190
  398. package/src/components/waitingList/style.css +0 -27
  399. package/src/constants/index.ts +0 -3
  400. package/src/env.ts +0 -29
  401. package/src/hoc/CustomFields/index.tsx +0 -85
  402. package/src/hoc/index.ts +0 -1
  403. package/src/hooks/index.ts +0 -1
  404. package/src/hooks/useCookieListener.ts +0 -32
  405. package/src/hooks/useEventListener.ts +0 -32
  406. package/src/hooks/useLocalStorageListener.ts +0 -32
  407. package/src/hooks/useOnline.ts +0 -21
  408. package/src/hooks/usePixel.ts +0 -88
  409. package/src/normalizers/index.ts +0 -49
  410. package/src/types/add_on.ts +0 -8
  411. package/src/types/api/auth.d.ts +0 -63
  412. package/src/types/api/axiosResponse.d.ts +0 -6
  413. package/src/types/api/cart.d.ts +0 -73
  414. package/src/types/api/checkout.d.ts +0 -92
  415. package/src/types/api/common.d.ts +0 -153
  416. package/src/types/api/guestTicketDelegation.d.ts +0 -18
  417. package/src/types/api/orders.d.ts +0 -116
  418. package/src/types/api/payment.d.ts +0 -180
  419. package/src/types/api/preRegistration.d.ts +0 -11
  420. package/src/types/api/preRegistrationComplete.d.ts +0 -95
  421. package/src/types/api/ticketResale.d.ts +0 -13
  422. package/src/types/billing-info-data.ts +0 -37
  423. package/src/types/checkoutPageConfigs.ts +0 -13
  424. package/src/types/formFields.d.ts +0 -29
  425. package/src/types/index.ts +0 -6
  426. package/src/types/order-data.ts +0 -16
  427. package/src/types/payment-field.ts +0 -7
  428. package/src/types/payment-plan-configuration.ts +0 -19
  429. package/src/types/pre-registration-complete.d.ts +0 -47
  430. package/src/types/referral-promotion.ts +0 -7
  431. package/src/types/seatMap.d.ts +0 -159
  432. package/src/types/verification.ts +0 -12
  433. package/src/utils/adaptStripeErrors.ts +0 -26
  434. package/src/utils/auth.ts +0 -45
  435. package/src/utils/cookies.ts +0 -73
  436. package/src/utils/createCheckoutDataBodyWithDefaultHolder.ts +0 -81
  437. package/src/utils/createMarkup.ts +0 -1
  438. package/src/utils/customFields.ts +0 -80
  439. package/src/utils/downloadPDF.tsx +0 -42
  440. package/src/utils/form.ts +0 -34
  441. package/src/utils/formikErrorFocus.ts +0 -24
  442. package/src/utils/getDomain.ts +0 -21
  443. package/src/utils/getImage.ts +0 -14
  444. package/src/utils/getQueryVariable.ts +0 -13
  445. package/src/utils/htmlNodeFromString.ts +0 -6
  446. package/src/utils/index.ts +0 -15
  447. package/src/utils/isBrowser.ts +0 -2
  448. package/src/utils/isValidNumber.ts +0 -8
  449. package/src/utils/jsonUtils.ts +0 -8
  450. package/src/utils/replaceVarInString.ts +0 -9
  451. package/src/utils/setConfigs.ts +0 -24
  452. package/src/utils/showZero.tsx +0 -10
  453. 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
+ }