@eventlook/sdk 1.4.48 → 1.4.49-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/.env.example +1 -0
  2. package/dist/cjs/_virtual/_commonjsHelpers.js +8 -0
  3. package/dist/cjs/_virtual/_commonjsHelpers.js.map +1 -0
  4. package/dist/cjs/_virtual/index.js +6 -0
  5. package/dist/cjs/_virtual/index.js.map +1 -0
  6. package/dist/cjs/_virtual/index2.js +6 -0
  7. package/dist/cjs/_virtual/index2.js.map +1 -0
  8. package/dist/cjs/_virtual/index3.js +6 -0
  9. package/dist/cjs/_virtual/index3.js.map +1 -0
  10. package/dist/cjs/_virtual/react-is.development.js +6 -0
  11. package/dist/cjs/_virtual/react-is.development.js.map +1 -0
  12. package/dist/cjs/_virtual/react-is.development2.js +6 -0
  13. package/dist/cjs/_virtual/react-is.development2.js.map +1 -0
  14. package/dist/cjs/_virtual/react-is.production.js +6 -0
  15. package/dist/cjs/_virtual/react-is.production.js.map +1 -0
  16. package/dist/cjs/_virtual/react-is.production.min.js +6 -0
  17. package/dist/cjs/_virtual/react-is.production.min.js.map +1 -0
  18. package/dist/cjs/components/hook-form/FormProvider.js +2 -2
  19. package/dist/cjs/components/hook-form/FormProvider.js.map +1 -1
  20. package/dist/cjs/form/ChildEventDialog.js +3 -3
  21. package/dist/cjs/form/ChildEventDialog.js.map +1 -1
  22. package/dist/cjs/form/ContactPerson.js +1 -1
  23. package/dist/cjs/form/ContactPerson.js.map +1 -1
  24. package/dist/cjs/form/PaymentOverviewBox.js +47 -61
  25. package/dist/cjs/form/PaymentOverviewBox.js.map +1 -1
  26. package/dist/cjs/form/PaymentOverviewDrawer.js +157 -0
  27. package/dist/cjs/form/PaymentOverviewDrawer.js.map +1 -0
  28. package/dist/cjs/form/PaymentPending.js +15 -3
  29. package/dist/cjs/form/PaymentPending.js.map +1 -1
  30. package/dist/cjs/form/ReleaseWithMerchandise.js +57 -48
  31. package/dist/cjs/form/ReleaseWithMerchandise.js.map +1 -1
  32. package/dist/cjs/form/Shipping.js +21 -18
  33. package/dist/cjs/form/Shipping.js.map +1 -1
  34. package/dist/cjs/form/TicketForm.js +94 -33
  35. package/dist/cjs/form/TicketForm.js.map +1 -1
  36. package/dist/cjs/form/TicketQuantityControl.js +51 -0
  37. package/dist/cjs/form/TicketQuantityControl.js.map +1 -0
  38. package/dist/cjs/form/TicketSelection.js +5 -6
  39. package/dist/cjs/form/TicketSelection.js.map +1 -1
  40. package/dist/cjs/form/TicketSelectionMobile.js +98 -0
  41. package/dist/cjs/form/TicketSelectionMobile.js.map +1 -0
  42. package/dist/cjs/form/TicketWithMerchandiseSelection.js +3 -5
  43. package/dist/cjs/form/TicketWithMerchandiseSelection.js.map +1 -1
  44. package/dist/cjs/form/index.js +1 -1
  45. package/dist/cjs/form/index.js.map +1 -1
  46. package/dist/cjs/form/merchandise/MerchandiseSelection.js +14 -0
  47. package/dist/cjs/form/merchandise/MerchandiseSelection.js.map +1 -0
  48. package/dist/cjs/form/merchandise/MerchandiseSlider.js +40 -0
  49. package/dist/cjs/form/merchandise/MerchandiseSlider.js.map +1 -0
  50. package/dist/cjs/form/merchendise/MerchandiseSelection.js +19 -0
  51. package/dist/cjs/form/merchendise/MerchandiseSelection.js.map +1 -0
  52. package/dist/cjs/form/merchendise/MerchandiseSlider.js +75 -0
  53. package/dist/cjs/form/merchendise/MerchandiseSlider.js.map +1 -0
  54. package/dist/cjs/form/payment/FeeBox.js +4 -16
  55. package/dist/cjs/form/payment/FeeBox.js.map +1 -1
  56. package/dist/cjs/form/payment/PaymentOverviewCheckbox.js +33 -28
  57. package/dist/cjs/form/payment/PaymentOverviewCheckbox.js.map +1 -1
  58. package/dist/cjs/form/product/ProductCard.js +139 -36
  59. package/dist/cjs/form/product/ProductCard.js.map +1 -1
  60. package/dist/cjs/form/product/ProductVariantsDialog.js +157 -96
  61. package/dist/cjs/form/product/ProductVariantsDialog.js.map +1 -1
  62. package/dist/cjs/form/services/index.js +133 -0
  63. package/dist/cjs/form/services/index.js.map +1 -0
  64. package/dist/cjs/form/style.js +7 -3
  65. package/dist/cjs/form/style.js.map +1 -1
  66. package/dist/cjs/form/tickets/ReleaseDescription.js +23 -0
  67. package/dist/cjs/form/tickets/ReleaseDescription.js.map +1 -0
  68. package/dist/cjs/form/tickets/ReleaseWithMerchandise.js +141 -0
  69. package/dist/cjs/form/tickets/ReleaseWithMerchandise.js.map +1 -0
  70. package/dist/cjs/form/tickets/TicketQuantityControl.js +52 -0
  71. package/dist/cjs/form/tickets/TicketQuantityControl.js.map +1 -0
  72. package/dist/cjs/form/tickets/TicketSelection.js +139 -0
  73. package/dist/cjs/form/tickets/TicketSelection.js.map +1 -0
  74. package/dist/cjs/form/tickets/TicketSelectionMap.js +73 -0
  75. package/dist/cjs/form/tickets/TicketSelectionMap.js.map +1 -0
  76. package/dist/cjs/form/tickets/TicketSelectionMobile.js +90 -0
  77. package/dist/cjs/form/tickets/TicketSelectionMobile.js.map +1 -0
  78. package/dist/cjs/form/tickets/TicketWithMerchandiseSelection.js +117 -0
  79. package/dist/cjs/form/tickets/TicketWithMerchandiseSelection.js.map +1 -0
  80. package/dist/cjs/hooks/useConsentScrollOnDrawerOpen.js +59 -0
  81. package/dist/cjs/hooks/useConsentScrollOnDrawerOpen.js.map +1 -0
  82. package/dist/cjs/hooks/useScrollToFirstError.js +64 -0
  83. package/dist/cjs/hooks/useScrollToFirstError.js.map +1 -0
  84. package/dist/cjs/locales/cs.js +18 -3
  85. package/dist/cjs/locales/cs.js.map +1 -1
  86. package/dist/cjs/locales/en.js +17 -2
  87. package/dist/cjs/locales/en.js.map +1 -1
  88. package/dist/cjs/locales/es.js +16 -1
  89. package/dist/cjs/locales/es.js.map +1 -1
  90. package/dist/cjs/locales/pl.js +16 -1
  91. package/dist/cjs/locales/pl.js.map +1 -1
  92. package/dist/cjs/locales/sk.js +17 -2
  93. package/dist/cjs/locales/sk.js.map +1 -1
  94. package/dist/cjs/locales/uk.js +16 -1
  95. package/dist/cjs/locales/uk.js.map +1 -1
  96. package/dist/cjs/utils/data/global.js +2 -0
  97. package/dist/cjs/utils/data/global.js.map +1 -1
  98. package/dist/esm/_virtual/_commonjsHelpers.js +6 -0
  99. package/dist/esm/_virtual/_commonjsHelpers.js.map +1 -0
  100. package/dist/esm/_virtual/index.js +4 -0
  101. package/dist/esm/_virtual/index.js.map +1 -0
  102. package/dist/esm/_virtual/index2.js +4 -0
  103. package/dist/esm/_virtual/index2.js.map +1 -0
  104. package/dist/esm/_virtual/index3.js +4 -0
  105. package/dist/esm/_virtual/index3.js.map +1 -0
  106. package/dist/esm/_virtual/react-is.development.js +4 -0
  107. package/dist/esm/_virtual/react-is.development.js.map +1 -0
  108. package/dist/esm/_virtual/react-is.development2.js +4 -0
  109. package/dist/esm/_virtual/react-is.development2.js.map +1 -0
  110. package/dist/esm/_virtual/react-is.production.js +4 -0
  111. package/dist/esm/_virtual/react-is.production.js.map +1 -0
  112. package/dist/esm/_virtual/react-is.production.min.js +4 -0
  113. package/dist/esm/_virtual/react-is.production.min.js.map +1 -0
  114. package/dist/esm/components/hook-form/FormProvider.js +2 -2
  115. package/dist/esm/components/hook-form/FormProvider.js.map +1 -1
  116. package/dist/esm/form/ChildEventDialog.js +3 -3
  117. package/dist/esm/form/ChildEventDialog.js.map +1 -1
  118. package/dist/esm/form/ContactPerson.js +1 -1
  119. package/dist/esm/form/ContactPerson.js.map +1 -1
  120. package/dist/esm/form/PaymentOverviewBox.js +48 -62
  121. package/dist/esm/form/PaymentOverviewBox.js.map +1 -1
  122. package/dist/esm/form/PaymentOverviewDrawer.js +153 -0
  123. package/dist/esm/form/PaymentOverviewDrawer.js.map +1 -0
  124. package/dist/esm/form/PaymentPending.js +16 -4
  125. package/dist/esm/form/PaymentPending.js.map +1 -1
  126. package/dist/esm/form/ReleaseWithMerchandise.js +58 -49
  127. package/dist/esm/form/ReleaseWithMerchandise.js.map +1 -1
  128. package/dist/esm/form/Shipping.js +21 -18
  129. package/dist/esm/form/Shipping.js.map +1 -1
  130. package/dist/esm/form/TicketForm.js +96 -35
  131. package/dist/esm/form/TicketForm.js.map +1 -1
  132. package/dist/esm/form/TicketQuantityControl.js +47 -0
  133. package/dist/esm/form/TicketQuantityControl.js.map +1 -0
  134. package/dist/esm/form/TicketSelection.js +5 -6
  135. package/dist/esm/form/TicketSelection.js.map +1 -1
  136. package/dist/esm/form/TicketSelectionMobile.js +94 -0
  137. package/dist/esm/form/TicketSelectionMobile.js.map +1 -0
  138. package/dist/esm/form/TicketWithMerchandiseSelection.js +4 -6
  139. package/dist/esm/form/TicketWithMerchandiseSelection.js.map +1 -1
  140. package/dist/esm/form/index.js +1 -1
  141. package/dist/esm/form/index.js.map +1 -1
  142. package/dist/esm/form/merchandise/MerchandiseSelection.js +10 -0
  143. package/dist/esm/form/merchandise/MerchandiseSelection.js.map +1 -0
  144. package/dist/esm/form/merchandise/MerchandiseSlider.js +36 -0
  145. package/dist/esm/form/merchandise/MerchandiseSlider.js.map +1 -0
  146. package/dist/esm/form/merchendise/MerchandiseSelection.js +15 -0
  147. package/dist/esm/form/merchendise/MerchandiseSelection.js.map +1 -0
  148. package/dist/esm/form/merchendise/MerchandiseSlider.js +71 -0
  149. package/dist/esm/form/merchendise/MerchandiseSlider.js.map +1 -0
  150. package/dist/esm/form/payment/FeeBox.js +5 -17
  151. package/dist/esm/form/payment/FeeBox.js.map +1 -1
  152. package/dist/esm/form/payment/PaymentOverviewCheckbox.js +35 -30
  153. package/dist/esm/form/payment/PaymentOverviewCheckbox.js.map +1 -1
  154. package/dist/esm/form/product/ProductCard.js +140 -37
  155. package/dist/esm/form/product/ProductCard.js.map +1 -1
  156. package/dist/esm/form/product/ProductVariantsDialog.js +159 -98
  157. package/dist/esm/form/product/ProductVariantsDialog.js.map +1 -1
  158. package/dist/esm/form/services/index.js +129 -0
  159. package/dist/esm/form/services/index.js.map +1 -0
  160. package/dist/esm/form/style.js +7 -3
  161. package/dist/esm/form/style.js.map +1 -1
  162. package/dist/esm/form/tickets/ReleaseDescription.js +19 -0
  163. package/dist/esm/form/tickets/ReleaseDescription.js.map +1 -0
  164. package/dist/esm/form/tickets/ReleaseWithMerchandise.js +137 -0
  165. package/dist/esm/form/tickets/ReleaseWithMerchandise.js.map +1 -0
  166. package/dist/esm/form/tickets/TicketQuantityControl.js +48 -0
  167. package/dist/esm/form/tickets/TicketQuantityControl.js.map +1 -0
  168. package/dist/esm/form/tickets/TicketSelection.js +135 -0
  169. package/dist/esm/form/tickets/TicketSelection.js.map +1 -0
  170. package/dist/esm/form/tickets/TicketSelectionMap.js +69 -0
  171. package/dist/esm/form/tickets/TicketSelectionMap.js.map +1 -0
  172. package/dist/esm/form/tickets/TicketSelectionMobile.js +86 -0
  173. package/dist/esm/form/tickets/TicketSelectionMobile.js.map +1 -0
  174. package/dist/esm/form/tickets/TicketWithMerchandiseSelection.js +113 -0
  175. package/dist/esm/form/tickets/TicketWithMerchandiseSelection.js.map +1 -0
  176. package/dist/esm/hooks/useConsentScrollOnDrawerOpen.js +55 -0
  177. package/dist/esm/hooks/useConsentScrollOnDrawerOpen.js.map +1 -0
  178. package/dist/esm/hooks/useScrollToFirstError.js +60 -0
  179. package/dist/esm/hooks/useScrollToFirstError.js.map +1 -0
  180. package/dist/esm/locales/cs.js +18 -3
  181. package/dist/esm/locales/cs.js.map +1 -1
  182. package/dist/esm/locales/en.js +17 -2
  183. package/dist/esm/locales/en.js.map +1 -1
  184. package/dist/esm/locales/es.js +16 -1
  185. package/dist/esm/locales/es.js.map +1 -1
  186. package/dist/esm/locales/pl.js +16 -1
  187. package/dist/esm/locales/pl.js.map +1 -1
  188. package/dist/esm/locales/sk.js +17 -2
  189. package/dist/esm/locales/sk.js.map +1 -1
  190. package/dist/esm/locales/uk.js +16 -1
  191. package/dist/esm/locales/uk.js.map +1 -1
  192. package/dist/esm/utils/data/global.js +2 -1
  193. package/dist/esm/utils/data/global.js.map +1 -1
  194. package/dist/types/components/Image.d.ts +4 -4
  195. package/dist/types/form/PaymentOverviewDrawer.d.ts +8 -0
  196. package/dist/types/form/merchendise/MerchandiseSelection.d.ts +9 -0
  197. package/dist/types/form/merchendise/MerchandiseSlider.d.ts +10 -0
  198. package/dist/types/form/merchendise/MerchendiseSlider.d.ts +0 -0
  199. package/dist/types/form/style.d.ts +1 -1
  200. package/package.json +5 -1
  201. package/rollup.config.mjs +2 -0
  202. package/src/components/hook-form/FormProvider.tsx +5 -2
  203. package/src/form/ChildEventDialog.tsx +3 -3
  204. package/src/form/ContactPerson.tsx +1 -1
  205. package/src/form/PaymentOverviewBox.tsx +89 -122
  206. package/src/form/PaymentOverviewDrawer.tsx +238 -0
  207. package/src/form/PaymentPending.tsx +19 -3
  208. package/src/form/Shipping.tsx +29 -17
  209. package/src/form/TicketForm.tsx +140 -39
  210. package/src/form/index.tsx +3 -1
  211. package/src/form/merchandise/MerchandiseSelection.tsx +24 -0
  212. package/src/form/merchandise/MerchandiseSlider.tsx +62 -0
  213. package/src/form/payment/FeeBox.tsx +4 -31
  214. package/src/form/payment/PaymentOverviewCheckbox.tsx +57 -56
  215. package/src/form/product/ProductCard.tsx +250 -59
  216. package/src/form/product/ProductVariantsDialog.tsx +253 -140
  217. package/src/form/services/index.tsx +263 -0
  218. package/src/form/style.ts +9 -3
  219. package/src/form/tickets/ReleaseDescription.tsx +46 -0
  220. package/src/form/tickets/ReleaseWithMerchandise.tsx +239 -0
  221. package/src/form/tickets/TicketQuantityControl.tsx +94 -0
  222. package/src/form/{TicketSelection.tsx → tickets/TicketSelection.tsx} +24 -128
  223. package/src/form/{TicketSelectionMap.tsx → tickets/TicketSelectionMap.tsx} +9 -1
  224. package/src/form/tickets/TicketSelectionMobile.tsx +177 -0
  225. package/src/form/{TicketWithMerchandiseSelection.tsx → tickets/TicketWithMerchandiseSelection.tsx} +3 -7
  226. package/src/hooks/useConsentScrollOnDrawerOpen.ts +73 -0
  227. package/src/hooks/useScrollToFirstError.ts +94 -0
  228. package/src/locales/cs.tsx +18 -3
  229. package/src/locales/en.tsx +17 -2
  230. package/src/locales/es.tsx +16 -1
  231. package/src/locales/pl.tsx +16 -1
  232. package/src/locales/sk.tsx +17 -2
  233. package/src/locales/uk.tsx +16 -1
  234. package/src/utils/data/global.ts +1 -0
  235. package/tsconfig.json +2 -1
  236. package/.claude/settings.local.json +0 -9
  237. package/src/form/MerchandiseSelection.tsx +0 -29
  238. package/src/form/ReleaseWithMerchandise.tsx +0 -230
@@ -14,7 +14,7 @@ import {
14
14
  Typography,
15
15
  } from '@mui/material';
16
16
  import dayjs from 'dayjs';
17
- import TicketSelection from '@form/TicketSelection';
17
+ import TicketSelection from '@form/tickets/TicketSelection';
18
18
  import ContactPerson from '@form/ContactPerson';
19
19
  import Payment from '@form/Payment';
20
20
  import EmailConfirmation from '@form/EmailConfirmation';
@@ -44,18 +44,23 @@ import {
44
44
  import ReleaseCountdown from '@form/ReleaseCountdown';
45
45
  import { cloneObject } from '@utils/global';
46
46
  import PaymentPending from '@form/PaymentPending';
47
- import MerchandiseSelection from '@form/MerchandiseSelection';
48
- import TicketWithMerchandiseSelection from '@form/TicketWithMerchandiseSelection';
47
+ import MerchandiseSelection from '@form/merchandise/MerchandiseSelection';
48
+ import TicketWithMerchandiseSelection from '@form/tickets/TicketWithMerchandiseSelection';
49
49
  import useActiveEventProducts from '@hooks/data/useActiveEventProducts';
50
50
  import Shipping from '@form/Shipping';
51
51
  import useErrors from '@hooks/useErrors';
52
52
  import { EventType } from '@utils/data/event';
53
53
  import TimeslotSelection from '@form/TimeslotSelection';
54
54
  import useGlobal from '@hooks/useGlobal';
55
+ import useConsentScrollOnDrawerOpen from '@hooks/useConsentScrollOnDrawerOpen';
56
+ import useScrollToFirstError from '@hooks/useScrollToFirstError';
55
57
  import { Trans } from '@components/Trans';
56
- import { EVENTLOOK_ORDER_FORM_ID } from '@utils/data/global.ts';
58
+ import { EVENTLOOK_ORDER_FORM_ID, EVENTLOOK_ORDER_FORM_CONTAINER_ID } from '@utils/data/global.ts';
57
59
  import ChildEventSection from './ChildEvents';
58
- import TicketSelectionMap from '@form/TicketSelectionMap.tsx';
60
+ import TicketSelectionMap from '@form/tickets/TicketSelectionMap';
61
+ import PaymentOverviewDrawer from './PaymentOverviewDrawer';
62
+ import { getPlaceAsString } from '@utils/place';
63
+ import Services from '@form/services';
59
64
 
60
65
  interface Props {
61
66
  event: IEvent;
@@ -63,14 +68,30 @@ interface Props {
63
68
  selectedReleaseId?: number;
64
69
  isIframe?: boolean;
65
70
  isInline?: boolean;
71
+ headerSlot?: React.ReactNode;
66
72
  }
67
73
 
74
+ const getCartItemCount = (formValues: ITicketForm) => {
75
+ const flatTickets = Object.values(formValues.tickets ?? {}).flat();
76
+ const ticketsCount = flatTickets.reduce((sum, ticket) => sum + (Number(ticket.quantity) || 0), 0);
77
+ const ticketsWithProductsCount = flatTickets.reduce(
78
+ (sum, ticket) => sum + ((ticket.products?.length ?? 0) > 0 ? 1 : 0),
79
+ 0
80
+ );
81
+ const productsCount = Object.values(formValues.products ?? {})
82
+ .flat()
83
+ .reduce((sum, product) => sum + (Number(product.quantity) || 0), 0);
84
+
85
+ return ticketsCount + ticketsWithProductsCount + productsCount;
86
+ };
87
+
68
88
  const TicketForm: React.FC<Props> = ({
69
89
  event,
70
90
  hasGopayIdSsr,
71
91
  selectedReleaseId,
72
92
  isIframe,
73
93
  isInline,
94
+ headerSlot,
74
95
  }) => {
75
96
  const { t, setGlobal, callbacks, links, user, options, showSnackbar, content, seatingIframeUrl } =
76
97
  useGlobal();
@@ -80,6 +101,7 @@ const TicketForm: React.FC<Props> = ({
80
101
  const [hasGopayId, setHasGopayId] = useState<boolean>(hasGopayIdSsr);
81
102
  const [isPaying, setIsPaying] = useState<boolean>(false);
82
103
  const [formStep, setFormStep] = useState<number>(1);
104
+ const [isPaymentOverviewDrawerOpen, setIsPaymentOverviewDrawerOpen] = useState<boolean>(false);
83
105
  const [showReleaseDate, setShowReleaseDate] = useState(
84
106
  dayjs(event.releaseDate).diff(dayjs()) > 0
85
107
  );
@@ -88,6 +110,13 @@ const TicketForm: React.FC<Props> = ({
88
110
  const hasFiredViewCart = useRef(false);
89
111
  const hasFiredBeginCheckout = useRef(false);
90
112
  const hasFiredPaymentMethod = useRef(false);
113
+ const termsAndConditionsRef = useRef<HTMLDivElement | null>(null);
114
+
115
+ useConsentScrollOnDrawerOpen({
116
+ isDrawerOpen: isPaymentOverviewDrawerOpen,
117
+ consentRef: termsAndConditionsRef,
118
+ });
119
+
91
120
  const item: IEcommerce = {
92
121
  currency: event.currency,
93
122
  items: [
@@ -274,11 +303,36 @@ const TicketForm: React.FC<Props> = ({
274
303
  // }
275
304
  // return true;
276
305
  // }),
277
- shipping: Yup.object().shape({
278
- shippingMethodId: Yup.number().nullable(),
279
- branchId: Yup.string().nullable(),
280
- price: Yup.number(),
281
- }),
306
+ shipping: Yup.object()
307
+ .shape({
308
+ shippingMethodId: Yup.number().nullable(),
309
+ branchId: Yup.string().nullable(),
310
+ price: Yup.number(),
311
+ })
312
+ .test('shipping-method-required', t('form.validation.required'), function (value) {
313
+ if (!event.hasMerchandise) {
314
+ return true;
315
+ }
316
+
317
+ const formValues = this.parent as ITicketForm;
318
+ const hasProducts = Object.values(formValues.products ?? {}).some((arr) => arr.length > 0);
319
+ const allTickets = Object.values(formValues.tickets ?? {}).flat();
320
+ const hasTicketProducts = allTickets.some((ticket) => (ticket.products?.length ?? 0) > 0);
321
+ const requiresShipping = hasProducts || hasTicketProducts;
322
+
323
+ if (!requiresShipping) {
324
+ return true;
325
+ }
326
+
327
+ if (value?.shippingMethodId !== null && value?.shippingMethodId !== undefined) {
328
+ return true;
329
+ }
330
+
331
+ return this.createError({
332
+ path: 'shipping.shippingMethodId',
333
+ message: t('form.validation.required'),
334
+ });
335
+ }),
282
336
  paymentMethodId: Yup.number().nullable().required(t('form.validation.required')),
283
337
  paymentMethodOptionId: Yup.number().nullable(),
284
338
  termsAndConditions: Yup.boolean().isTrue(t('form.validation.terms_and_conditions')),
@@ -306,15 +360,11 @@ const TicketForm: React.FC<Props> = ({
306
360
  defaultValues,
307
361
  });
308
362
  const values = methods.watch();
363
+ const cartItemCount = useMemo(() => getCartItemCount(values), [values.tickets, values.products]);
364
+ const onInvalid = useScrollToFirstError(methods);
309
365
 
310
366
  const onSubmit = async (values: ITicketForm) => {
311
- const allTickets = Object.values(values.tickets).flat();
312
- if (
313
- allTickets.length === 1 &&
314
- !allTickets[0].releaseId &&
315
- !allTickets[0].quantity &&
316
- !values.products.length
317
- ) {
367
+ if (cartItemCount <= 0) {
318
368
  showSnackbar(t('form.validation.count_tickets_or_products'), {
319
369
  variant: 'error',
320
370
  });
@@ -444,7 +494,7 @@ const TicketForm: React.FC<Props> = ({
444
494
  }, [window.location.search]);
445
495
 
446
496
  useEffect(() => {
447
- const subscription = methods.watch((value, { name }) => {
497
+ const subscription = methods.watch((value) => {
448
498
  if (
449
499
  JSON.stringify(defaultValues) !== JSON.stringify(value) &&
450
500
  !hasFiredBeginCheckout.current
@@ -471,7 +521,7 @@ const TicketForm: React.FC<Props> = ({
471
521
  useEffect(() => {
472
522
  if (hasGopayId || isPaying || paymentRedirect) {
473
523
  if (options?.autoscrollAfterViewChange) {
474
- const orderForm = document.getElementById(EVENTLOOK_ORDER_FORM_ID);
524
+ const orderForm = document.getElementById(EVENTLOOK_ORDER_FORM_CONTAINER_ID);
475
525
  if (orderForm) {
476
526
  orderForm.scrollIntoView({ behavior: 'smooth' });
477
527
  }
@@ -483,7 +533,7 @@ const TicketForm: React.FC<Props> = ({
483
533
  return <ReleaseCountdown event={event} setShowReleaseDate={setShowReleaseDate} />;
484
534
 
485
535
  return (
486
- <Box id={EVENTLOOK_ORDER_FORM_ID}>
536
+ <Box id={EVENTLOOK_ORDER_FORM_CONTAINER_ID}>
487
537
  {hasGopayId ? (
488
538
  <PaymentSuccess setIsPaying={setIsPaying} isIframe={isIframe} pixels={pixels} />
489
539
  ) : isPaying ? (
@@ -496,32 +546,65 @@ const TicketForm: React.FC<Props> = ({
496
546
  isInline={isInline}
497
547
  />
498
548
  ) : (
499
- // @ts-ignore
500
- <FormProvider methods={methods} onSubmit={methods.handleSubmit(onSubmit)}>
501
- <Typography
549
+ <FormProvider
550
+ methods={methods}
551
+ // @ts-ignore
552
+ onSubmit={methods.handleSubmit(onSubmit, onInvalid)}
553
+ formId={EVENTLOOK_ORDER_FORM_ID}
554
+ >
555
+ <Stack
502
556
  className="overview-card__event-info"
503
557
  display={{ md: 'none' }}
504
- variant="h4"
505
558
  sx={{
506
559
  mb: 2,
507
560
  }}
508
561
  >
509
- {event.name} - {dayjs(event.startDate).format('DD.MM.YYYY HH:mm')}
510
- </Typography>
511
- <Grid container spacing={2}>
562
+ <Typography variant="h3" component="h1">
563
+ {event.name} a
564
+ </Typography>
565
+ <Typography variant="h5" component="h2">
566
+ {dayjs(event.startDate).format('DD.MM.YYYY HH:mm')}
567
+ </Typography>
568
+ <Typography variant="body2" mt={1}>
569
+ {getPlaceAsString(event.place)}
570
+ </Typography>
571
+ {headerSlot ? <>{headerSlot}</> : null}
572
+ </Stack>
573
+ <Grid
574
+ container
575
+ spacing={2}
576
+ sx={{
577
+ pb: {
578
+ xs: isPaymentOverviewDrawerOpen ? getCartItemCount(values) * 3 + 18 : 0,
579
+ md: 0,
580
+ },
581
+ }}
582
+ >
512
583
  <Grid item xs={12} md={8}>
513
- <Stepper orientation="vertical">
584
+ <Stepper
585
+ orientation="vertical"
586
+ sx={(theme) => ({
587
+ [theme.breakpoints.down('sm')]: {
588
+ '& .MuiStepContent-root': {
589
+ borderLeftWidth: 0,
590
+ paddingLeft: 0,
591
+ marginLeft: 0,
592
+ },
593
+ '& .MuiStepConnector-line': { borderLeftWidth: 0 },
594
+ },
595
+ })}
596
+ >
514
597
  {event.type === EventType.RECURRING && (
515
598
  <Step active>
516
599
  <StepLabel>{t('event.tickets.stepper.6.title')}</StepLabel>
517
- <StepContent>
600
+ <StepContent sx={{ pr: { xs: 0 } }}>
518
601
  <TimeslotSelection event={event} />
519
602
  </StepContent>
520
603
  </Step>
521
604
  )}
522
605
  <Step active>
523
606
  <StepLabel>{t('event.tickets.stepper.1.title')}</StepLabel>
524
- <StepContent>
607
+ <StepContent sx={{ pr: { xs: 0 } }}>
525
608
  {event.mapId && seatingIframeUrl ? (
526
609
  <TicketSelectionMap event={event} />
527
610
  ) : event.hasMerchandise ? (
@@ -534,7 +617,7 @@ const TicketForm: React.FC<Props> = ({
534
617
  {event.hasMerchandise && eventProducts.length && (
535
618
  <Step active>
536
619
  <StepLabel>{t('event.tickets.stepper.4.title')}</StepLabel>
537
- <StepContent>
620
+ <StepContent sx={{ pr: { xs: 0 } }}>
538
621
  <MerchandiseSelection
539
622
  eventProducts={eventProducts}
540
623
  eventId={event.id}
@@ -543,24 +626,30 @@ const TicketForm: React.FC<Props> = ({
543
626
  </StepContent>
544
627
  </Step>
545
628
  )}
629
+ <Step active>
630
+ <StepLabel>{t('event.tickets.stepper.8.title')}</StepLabel>
631
+ <StepContent sx={{ pr: { xs: 0 } }}>
632
+ <Services event={event} />
633
+ </StepContent>
634
+ </Step>
546
635
  {event.children.length && (
547
636
  <Step active>
548
637
  <StepLabel>{t('event.tickets.stepper.7.title')}</StepLabel>
549
- <StepContent>
638
+ <StepContent sx={{ pr: { xs: 0 } }}>
550
639
  <ChildEventSection events={event.children} />
551
640
  </StepContent>
552
641
  </Step>
553
642
  )}
554
643
  <Step active>
555
644
  <StepLabel>{t('event.tickets.stepper.2.title')}</StepLabel>
556
- <StepContent>
645
+ <StepContent sx={{ pr: { xs: 0 } }}>
557
646
  <ContactPerson event={event} />
558
647
  </StepContent>
559
648
  </Step>
560
649
  {event.hasMerchandise && showShippingMethods() && (
561
650
  <Step active>
562
651
  <StepLabel>{t('event.tickets.stepper.5.title')}</StepLabel>
563
- <StepContent>
652
+ <StepContent sx={{ pr: { xs: 0 } }}>
564
653
  <Shipping event={event} />
565
654
  </StepContent>
566
655
  </Step>
@@ -571,12 +660,17 @@ const TicketForm: React.FC<Props> = ({
571
660
  `event.tickets.stepper.3.${values.isPaymentVerify ? 'title_verify' : 'title'}`
572
661
  )}
573
662
  </StepLabel>
574
- <StepContent>
663
+ <StepContent sx={{ pr: { xs: 0 } }}>
575
664
  <Payment event={event} />
576
665
  </StepContent>
577
666
  </Step>
578
667
  </Stepper>
579
- <Stack mt={2} ml={4}>
668
+ <Stack
669
+ ref={termsAndConditionsRef}
670
+ mt={2}
671
+ ml={{ xs: 1, md: 4 }}
672
+ sx={{ scrollMarginBottom: { xs: 220, md: 0 } }}
673
+ >
580
674
  <RHFCheckbox
581
675
  name="termsAndConditions"
582
676
  label={
@@ -596,15 +690,22 @@ const TicketForm: React.FC<Props> = ({
596
690
  />
597
691
  </Stack>
598
692
  </Grid>
599
- <Grid item xs={12} md={4}>
693
+ <Grid item xs={12} md={4} sx={{ display: { xs: 'none', md: 'block' } }}>
600
694
  <PaymentOverviewBox event={event} />
601
695
  </Grid>
602
696
  </Grid>
697
+
698
+ <PaymentOverviewDrawer
699
+ event={event}
700
+ totalPrice={values.total}
701
+ onOpenChange={setIsPaymentOverviewDrawerOpen}
702
+ />
703
+
603
704
  <EmailConfirmation
604
705
  open={formStep === 2 && !isIframe}
605
706
  onClose={() => setFormStep(1)}
606
707
  // @ts-ignore
607
- onConfirm={methods.handleSubmit(onSubmit)}
708
+ onConfirm={methods.handleSubmit(onSubmit, onInvalid)}
608
709
  />
609
710
  </FormProvider>
610
711
  )}
@@ -613,7 +714,7 @@ const TicketForm: React.FC<Props> = ({
613
714
  };
614
715
 
615
716
  const CustomLink: React.FC<PropsWithChildren<LinkProps>> = ({ href = '', children, ...other }) => (
616
- <Link href={href} {...other}>
717
+ <Link href={href} {...other} sx={{ color: 'inherit', textDecoration: 'underline' }}>
617
718
  {children}
618
719
  </Link>
619
720
  );
@@ -5,7 +5,7 @@ import 'dayjs/locale/es';
5
5
  import 'dayjs/locale/uk';
6
6
  import 'dayjs/locale/sk';
7
7
 
8
- import React, { useEffect } from 'react';
8
+ import React, { useEffect, ReactNode } from 'react';
9
9
  import TicketForm from '@form/TicketForm';
10
10
  import { GlobalProvider } from '@context/GlobalContext';
11
11
  import api from '@utils/axios';
@@ -33,6 +33,7 @@ export interface OrderFormProps {
33
33
  lang?: Languages;
34
34
  slots?: {
35
35
  showSnackbar: IGlobalContext['showSnackbar'];
36
+ headerSlot?: ReactNode;
36
37
  };
37
38
  user?: IUser;
38
39
  selectedReleaseId?: number;
@@ -112,6 +113,7 @@ const ClientRender: React.FC<OrderFormProps> = ({
112
113
  hasGopayIdSsr={options?.hasGopayId || false}
113
114
  isIframe={options?.isIframe}
114
115
  selectedReleaseId={selectedReleaseId}
116
+ headerSlot={slots?.headerSlot}
115
117
  />
116
118
  )}
117
119
  </GlobalProvider>
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import { Grid } from '@mui/material';
3
+ import { IEventProduct } from '@utils/types/event-product.type';
4
+ import CustomSkeleton from '@components/CustomSkeleton';
5
+ import MerchandiseSlider from './MerchandiseSlider';
6
+
7
+ interface Props {
8
+ eventProducts: IEventProduct[];
9
+ eventId: number;
10
+ isLoading?: boolean;
11
+ }
12
+
13
+ const MerchandiseSelection: React.FC<Props> = ({ eventProducts, eventId, isLoading }) =>
14
+ isLoading ? (
15
+ [...Array(3)].map((item) => (
16
+ <Grid key={item} item xs={12} md={4}>
17
+ <CustomSkeleton height={334} />
18
+ </Grid>
19
+ ))
20
+ ) : (
21
+ <MerchandiseSlider eventProducts={eventProducts} eventId={eventId} />
22
+ );
23
+
24
+ export default MerchandiseSelection;
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import useEmblaCarousel from 'embla-carousel-react';
3
+ import { Box, SxProps } from '@mui/material';
4
+ import { useTheme } from '@mui/material/styles';
5
+ import { IEventProduct } from '@utils/types/event-product.type';
6
+ import ProductCard from '@form/product/ProductCard';
7
+
8
+ interface Props {
9
+ sx?: SxProps;
10
+ eventProducts: IEventProduct[];
11
+ eventId: number;
12
+ }
13
+
14
+ const MerchandiseSlider: React.FC<Props> = ({ eventProducts, eventId, sx }) => {
15
+ const [emblaRef] = useEmblaCarousel();
16
+ const theme = useTheme();
17
+
18
+ return (
19
+ <Box sx={sx}>
20
+ <Box
21
+ sx={{
22
+ overflow: 'hidden',
23
+ padding: theme.spacing(8, 3),
24
+ margin: theme.spacing(-8, -3),
25
+ }}
26
+ >
27
+ <Box ref={emblaRef} className="embla" sx={{ overflow: 'visible' }}>
28
+ <Box
29
+ className="embla__container"
30
+ sx={{
31
+ display: 'flex',
32
+ }}
33
+ >
34
+ {eventProducts.map((eventProduct, index) => (
35
+ <Box
36
+ key={`event-slide-${index}`}
37
+ className="embla__slide"
38
+ sx={{
39
+ flex: `0 0 ${eventProducts.length > 1 ? '78%' : '100%'}`,
40
+ minWidth: 0,
41
+ maxWidth: 220,
42
+ margin: `0 ${theme.spacing(0.5)}`,
43
+ transition: 'opacity 0.2s ease',
44
+ [theme.breakpoints.up('sm')]: {
45
+ flex: '0 0 43%',
46
+ },
47
+ [theme.breakpoints.up('md')]: {
48
+ flex: '0 0 33.3333%',
49
+ },
50
+ }}
51
+ >
52
+ <ProductCard eventProduct={eventProduct} eventId={eventId} isOnlyMerchandise />
53
+ </Box>
54
+ ))}
55
+ </Box>
56
+ </Box>
57
+ </Box>
58
+ </Box>
59
+ );
60
+ };
61
+
62
+ export default MerchandiseSlider;
@@ -1,9 +1,7 @@
1
1
  import React from 'react';
2
- import { Box, Stack, Tooltip, Typography } from '@mui/material';
2
+ import { Box, Stack, Typography } from '@mui/material';
3
3
  import { fCurrency } from '@utils/formatNumber';
4
- import { Iconify } from '@components/iconify';
5
4
  import { IEvent } from '@utils/types/event.type';
6
- import useResponsive from '@hooks/useResponsive';
7
5
  import { useFormContext } from 'react-hook-form';
8
6
  import { ITicketForm } from '@utils/types/ticket.type';
9
7
  import useGlobal from '@hooks/useGlobal.ts';
@@ -15,7 +13,6 @@ interface Props {
15
13
 
16
14
  const FeeBox: React.FC<Props> = ({ event, align = 'left' }) => {
17
15
  const { t, lang } = useGlobal();
18
- const xs = useResponsive('only', 'xs');
19
16
  const { watch } = useFormContext<ITicketForm>();
20
17
  const values = watch();
21
18
  const isRight = align === 'right';
@@ -44,35 +41,11 @@ const FeeBox: React.FC<Props> = ({ event, align = 'left' }) => {
44
41
  alignItems="center"
45
42
  spacing={1}
46
43
  >
47
- <Stack direction="row" alignItems="center" spacing={1}>
48
- <Tooltip
49
- title={t('form.labels.price_including_service_fee', {
50
- fee: fCurrency(values.totalFee ?? 0, lang, event.currency),
51
- })}
52
- placement={xs ? 'top' : 'left'}
53
- arrow
54
- sx={{ cursor: 'help' }}
55
- >
56
- <Stack alignItems="center">
57
- <Iconify icon="carbon:information-filled" />
58
- </Stack>
59
- </Tooltip>
60
- <Typography variant="subtitle1" sx={{ textAlign: 'right' }}>
61
- {t('form.labels.total')}:
62
- </Typography>
63
- </Stack>
44
+ <Typography variant="subtitle1" sx={{ textAlign: 'right' }}>
45
+ {t('form.labels.total')}:
46
+ </Typography>
64
47
  <Typography variant="subtitle1">{fCurrency(values.total, lang, event.currency)}</Typography>
65
48
  </Stack>
66
- {!!values.totalFee && (
67
- <Typography
68
- variant="caption"
69
- sx={{
70
- color: (theme) => theme.palette.grey.A700,
71
- }}
72
- >
73
- {t('form.labels.with_fee')}
74
- </Typography>
75
- )}
76
49
  </Box>
77
50
  );
78
51
  };
@@ -1,14 +1,6 @@
1
- import React, { JSX, useState } from 'react';
2
- import {
3
- Dialog,
4
- DialogContent,
5
- DialogTitle,
6
- IconButton,
7
- Link,
8
- Stack,
9
- Typography,
10
- } from '@mui/material';
11
- import { RHFCheckbox } from '@components/hook-form';
1
+ import React, { JSX } from 'react';
2
+ import { Box, Button, Stack, Typography } from '@mui/material';
3
+ import { Controller, useFormContext } from 'react-hook-form';
12
4
  import useGlobal from '@hooks/useGlobal.ts';
13
5
  import { Iconify } from '@components';
14
6
 
@@ -16,70 +8,79 @@ interface Props {
16
8
  checkboxName: string;
17
9
  label: string;
18
10
  value: string | JSX.Element;
19
- modal: {
20
- title: string;
21
- description: string | JSX.Element;
22
- };
23
11
  }
24
12
 
25
- const PaymentOverviewCheckbox: React.FC<Props> = ({ checkboxName, label, value, modal }) => {
13
+ const PaymentOverviewCheckbox: React.FC<Props> = ({ checkboxName, label, value }) => {
26
14
  const { t } = useGlobal();
27
- const [open, setOpen] = useState(false);
28
-
29
- const handleOpen = (e: React.MouseEvent<HTMLAnchorElement>) => {
30
- e.preventDefault();
31
- e.stopPropagation();
32
- setOpen(true);
33
- };
34
- const handleClose = () => setOpen(false);
15
+ const { control } = useFormContext();
35
16
 
36
17
  return (
37
18
  <>
38
- <RHFCheckbox
19
+ <Controller
39
20
  name={checkboxName}
40
- label={
21
+ control={control}
22
+ render={({ field }) => (
41
23
  <Stack
42
24
  direction="row"
43
25
  justifyContent="space-between"
44
26
  alignItems="center"
27
+ useFlexGap
45
28
  spacing={1}
46
- sx={{ width: '100%' }}
29
+ sx={{ width: '100%', mb: 0.5 }}
47
30
  >
48
- <Typography variant="caption" sx={{ flex: 1 }}>
31
+ <Typography variant="body2" sx={{ flex: 1 }}>
49
32
  {label}
50
33
  </Typography>
51
- <Stack alignItems="flex-end">
52
- <Typography variant="caption" fontWeight="600">
34
+ <Box
35
+ sx={{
36
+ position: 'relative',
37
+ display: 'flex',
38
+ alignItems: 'center',
39
+ }}
40
+ >
41
+ <Typography
42
+ variant="body2"
43
+ sx={{
44
+ mr: field.value ? 0 : 1,
45
+ ...(field.value
46
+ ? {
47
+ position: 'absolute',
48
+ right: 0,
49
+ }
50
+ : {}),
51
+ }}
52
+ >
53
53
  {value}
54
54
  </Typography>
55
- <Link variant="caption" onClick={handleOpen}>
56
- {t('more_info')}
57
- </Link>
58
- </Stack>
55
+ <Button
56
+ variant="outlined"
57
+ color="primary"
58
+ size="small"
59
+ startIcon={<Iconify icon="carbon:add" />}
60
+ onClick={(event) => {
61
+ event.preventDefault();
62
+ event.stopPropagation();
63
+ field.onChange(true);
64
+ }}
65
+ sx={{
66
+ borderRadius: 1,
67
+ textTransform: 'none',
68
+ px: 1,
69
+ width: 96,
70
+ minWidth: 96,
71
+ color: 'text.primary',
72
+ visibility: field.value ? 'hidden' : 'visible',
73
+ pointerEvents: field.value ? 'none' : 'auto',
74
+ }}
75
+ tabIndex={field.value ? -1 : 0}
76
+ aria-hidden={field.value}
77
+ >
78
+ {t('add')}
79
+ </Button>
80
+ </Box>
59
81
  </Stack>
60
- }
61
- sx={{
62
- width: 'calc(100% + 11px)',
63
- mb: 0.5,
64
- '& > .MuiTypography-root': {
65
- width: '100%',
66
- },
67
- }}
82
+ )}
68
83
  />
69
-
70
- <Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth>
71
- <DialogTitle
72
- sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}
73
- >
74
- {modal.title}
75
- <IconButton onClick={handleClose} size="small">
76
- <Iconify icon="carbon:close" />
77
- </IconButton>
78
- </DialogTitle>
79
- <DialogContent>
80
- <Typography variant="body2">{modal.description}</Typography>
81
- </DialogContent>
82
- </Dialog>
83
84
  </>
84
85
  );
85
86
  };