@eventlook/sdk 1.5.0-beta.6 → 1.5.0-beta.8
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.
- package/.claude/settings.local.json +6 -10
- package/.env.example +1 -0
- package/README.md +18 -16
- package/dist/cjs/{index-DvUR1fp8.js → index-CUIxdwQn.js} +3340 -577
- package/dist/cjs/index-CUIxdwQn.js.map +1 -0
- package/dist/cjs/index-D5rQiSGP.js +38574 -0
- package/dist/cjs/index-D5rQiSGP.js.map +1 -0
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/{index.umd-6SU6nkkJ.js → index.umd-BoFEW91M.js} +9 -19
- package/dist/cjs/index.umd-BoFEW91M.js.map +1 -0
- package/dist/cjs/index.umd-BzSM62qM.js +13397 -0
- package/dist/cjs/index.umd-BzSM62qM.js.map +1 -0
- package/dist/esm/index-Cm7V8Zl3.js +38571 -0
- package/dist/esm/index-Cm7V8Zl3.js.map +1 -0
- package/dist/esm/{index-BlTqx0jm.js → index-fvLIN6eP.js} +3327 -563
- package/dist/esm/index-fvLIN6eP.js.map +1 -0
- package/dist/esm/index.js +2 -2
- package/dist/esm/{index.umd-Dn0hjh7E.js → index.umd-BKBHcCnm.js} +9 -19
- package/dist/esm/index.umd-BKBHcCnm.js.map +1 -0
- package/dist/esm/index.umd-bIV_YpEF.js +13395 -0
- package/dist/esm/index.umd-bIV_YpEF.js.map +1 -0
- package/dist/types/components/hook-form/FormProvider.d.ts +2 -1
- package/dist/types/form/PaymentOverviewBox.d.ts +2 -0
- package/dist/types/form/PaymentOverviewDrawer.d.ts +10 -0
- package/dist/types/form/TicketForm.d.ts +1 -0
- package/dist/types/form/index.d.ts +2 -1
- package/dist/types/form/merchandise/MerchandiseSelection.d.ts +9 -0
- package/dist/types/form/merchandise/MerchandiseSlider.d.ts +10 -0
- package/dist/types/form/payment/PaymentOverviewCheckbox.d.ts +0 -4
- package/dist/types/form/product/ProductVariantsDialog.d.ts +3 -1
- package/dist/types/form/services/index.d.ts +7 -0
- package/dist/types/form/style.d.ts +1 -0
- package/dist/types/form/tickets/ReleaseDescription.d.ts +10 -0
- package/dist/types/form/tickets/ReleaseWithMerchandise.d.ts +12 -0
- package/dist/types/form/tickets/TicketQuantityControl.d.ts +13 -0
- package/dist/types/form/tickets/TicketSelectionMobile.d.ts +16 -0
- package/dist/types/hooks/useScrollToFirstError.d.ts +4 -0
- package/dist/types/locales/cs.d.ts +22 -0
- package/dist/types/locales/en.d.ts +22 -0
- package/dist/types/locales/es.d.ts +22 -0
- package/dist/types/locales/pl.d.ts +22 -0
- package/dist/types/locales/sk.d.ts +22 -0
- package/dist/types/locales/uk.d.ts +22 -0
- package/dist/types/utils/data/global.d.ts +1 -0
- package/dist/types/utils/data/ticket.d.ts +1 -0
- package/package.json +10 -4
- package/rollup.config.mjs +7 -12
- package/src/components/hook-form/FormProvider.tsx +5 -2
- package/src/form/ChildEventDialog.tsx +3 -3
- package/src/form/ContactPerson.tsx +1 -1
- package/src/form/PaymentOverviewBox.tsx +96 -123
- package/src/form/PaymentOverviewDrawer.tsx +445 -0
- package/src/form/PaymentPending.tsx +19 -4
- package/src/form/ReleaseWithMerchandise.tsx +4 -4
- package/src/form/Shipping.tsx +48 -33
- package/src/form/TicketForm.tsx +146 -41
- package/src/form/index.tsx +3 -1
- package/src/form/merchandise/MerchandiseSelection.tsx +24 -0
- package/src/form/merchandise/MerchandiseSlider.tsx +62 -0
- package/src/form/payment/FeeBox.tsx +4 -31
- package/src/form/payment/PaymentOverviewCheckbox.tsx +68 -69
- package/src/form/product/ProductCard.tsx +258 -59
- package/src/form/product/ProductVariantsDialog.tsx +292 -139
- package/src/form/services/index.tsx +262 -0
- package/src/form/style.ts +16 -4
- package/src/form/tickets/ReleaseDescription.tsx +46 -0
- package/src/form/tickets/ReleaseWithMerchandise.tsx +267 -0
- package/src/form/tickets/TicketQuantityControl.tsx +100 -0
- package/src/form/tickets/TicketSelection.tsx +236 -0
- package/src/form/{TicketSelectionMap.tsx → tickets/TicketSelectionMap.tsx} +18 -2
- package/src/form/tickets/TicketSelectionMobile.tsx +188 -0
- package/src/form/{TicketWithMerchandiseSelection.tsx → tickets/TicketWithMerchandiseSelection.tsx} +52 -38
- package/src/hooks/useScrollToFirstError.ts +99 -0
- package/src/locales/cs.tsx +25 -3
- package/src/locales/en.tsx +23 -1
- package/src/locales/es.tsx +23 -1
- package/src/locales/pl.tsx +23 -1
- package/src/locales/sk.tsx +24 -2
- package/src/locales/uk.tsx +23 -1
- package/src/utils/data/global.ts +1 -0
- package/src/utils/data/ticket.ts +1 -0
- package/tsconfig.json +1 -1
- package/README +0 -1
- package/dist/cjs/index-DvUR1fp8.js.map +0 -1
- package/dist/cjs/index.umd-6SU6nkkJ.js.map +0 -1
- package/dist/esm/index-BlTqx0jm.js.map +0 -1
- package/dist/esm/index.umd-Dn0hjh7E.js.map +0 -1
- package/src/form/TicketSelection.tsx +0 -307
- /package/dist/types/form/{TicketSelection.d.ts → tickets/TicketSelection.d.ts} +0 -0
- /package/dist/types/form/{TicketSelectionMap.d.ts → tickets/TicketSelectionMap.d.ts} +0 -0
- /package/dist/types/form/{TicketWithMerchandiseSelection.d.ts → tickets/TicketWithMerchandiseSelection.d.ts} +0 -0
package/src/form/TicketForm.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import PaymentSuccess from '@form/PaymentSuccess';
|
|
|
3
3
|
import FormProvider, { RHFCheckbox } from '@components/hook-form';
|
|
4
4
|
import {
|
|
5
5
|
Box,
|
|
6
|
+
Divider,
|
|
6
7
|
Grid,
|
|
7
8
|
Link,
|
|
8
9
|
LinkProps,
|
|
@@ -14,7 +15,7 @@ import {
|
|
|
14
15
|
Typography,
|
|
15
16
|
} from '@mui/material';
|
|
16
17
|
import dayjs from 'dayjs';
|
|
17
|
-
import TicketSelection from '@form/TicketSelection';
|
|
18
|
+
import TicketSelection from '@form/tickets/TicketSelection';
|
|
18
19
|
import ContactPerson from '@form/ContactPerson';
|
|
19
20
|
import Payment from '@form/Payment';
|
|
20
21
|
import EmailConfirmation from '@form/EmailConfirmation';
|
|
@@ -44,18 +45,22 @@ import {
|
|
|
44
45
|
import ReleaseCountdown from '@form/ReleaseCountdown';
|
|
45
46
|
import { cloneObject } from '@utils/global';
|
|
46
47
|
import PaymentPending from '@form/PaymentPending';
|
|
47
|
-
import MerchandiseSelection from '@form/MerchandiseSelection';
|
|
48
|
-
import TicketWithMerchandiseSelection from '@form/TicketWithMerchandiseSelection';
|
|
48
|
+
import MerchandiseSelection from '@form/merchandise/MerchandiseSelection';
|
|
49
|
+
import TicketWithMerchandiseSelection from '@form/tickets/TicketWithMerchandiseSelection';
|
|
49
50
|
import useActiveEventProducts from '@hooks/data/useActiveEventProducts';
|
|
50
51
|
import Shipping from '@form/Shipping';
|
|
51
52
|
import useErrors from '@hooks/useErrors';
|
|
52
53
|
import { EventType } from '@utils/data/event';
|
|
53
54
|
import TimeslotSelection from '@form/TimeslotSelection';
|
|
54
55
|
import useGlobal from '@hooks/useGlobal';
|
|
56
|
+
import useScrollToFirstError from '@hooks/useScrollToFirstError';
|
|
55
57
|
import { Trans } from '@components/Trans';
|
|
56
|
-
import { EVENTLOOK_ORDER_FORM_ID } from '@utils/data/global';
|
|
58
|
+
import { EVENTLOOK_ORDER_FORM_ID, EVENTLOOK_ORDER_FORM_CONTAINER_ID } from '@utils/data/global';
|
|
57
59
|
import ChildEventSection from './ChildEvents';
|
|
58
|
-
import TicketSelectionMap from '@form/TicketSelectionMap';
|
|
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,33 @@ interface Props {
|
|
|
63
68
|
selectedReleaseId?: number;
|
|
64
69
|
isIframe?: boolean;
|
|
65
70
|
isInline?: boolean;
|
|
71
|
+
headerSlot?: React.ReactNode;
|
|
66
72
|
}
|
|
67
73
|
|
|
74
|
+
const getCartUniqueItemCount = (formValues: ITicketForm) => {
|
|
75
|
+
const flatTickets = Object.values(formValues.tickets ?? {}).flat();
|
|
76
|
+
const ticketsCount = flatTickets.reduce(
|
|
77
|
+
(sum, ticket) => sum + (Number(ticket.quantity) > 0 ? 1 : 0),
|
|
78
|
+
0
|
|
79
|
+
);
|
|
80
|
+
const ticketsWithProductsCount = flatTickets.reduce(
|
|
81
|
+
(sum, ticket) => sum + ((ticket.products?.length ?? 0) > 0 ? 1 : 0),
|
|
82
|
+
0
|
|
83
|
+
);
|
|
84
|
+
const productsCount = Object.values(formValues.products ?? {})
|
|
85
|
+
.flat()
|
|
86
|
+
.reduce((sum, product) => sum + (Number(product.quantity) || 0), 0);
|
|
87
|
+
|
|
88
|
+
return ticketsCount + ticketsWithProductsCount + productsCount;
|
|
89
|
+
};
|
|
90
|
+
|
|
68
91
|
const TicketForm: React.FC<Props> = ({
|
|
69
92
|
event,
|
|
70
93
|
hasGopayIdSsr,
|
|
71
94
|
selectedReleaseId,
|
|
72
95
|
isIframe,
|
|
73
96
|
isInline,
|
|
97
|
+
headerSlot,
|
|
74
98
|
}) => {
|
|
75
99
|
const { t, setGlobal, callbacks, links, user, options, showSnackbar, content, seatingIframeUrl } =
|
|
76
100
|
useGlobal();
|
|
@@ -80,6 +104,7 @@ const TicketForm: React.FC<Props> = ({
|
|
|
80
104
|
const [hasGopayId, setHasGopayId] = useState<boolean>(hasGopayIdSsr);
|
|
81
105
|
const [isPaying, setIsPaying] = useState<boolean>(false);
|
|
82
106
|
const [formStep, setFormStep] = useState<number>(1);
|
|
107
|
+
const [isPaymentOverviewDrawerOpen, setIsPaymentOverviewDrawerOpen] = useState<boolean>(false);
|
|
83
108
|
const [showReleaseDate, setShowReleaseDate] = useState(
|
|
84
109
|
dayjs(event.releaseDate).diff(dayjs()) > 0
|
|
85
110
|
);
|
|
@@ -88,6 +113,8 @@ const TicketForm: React.FC<Props> = ({
|
|
|
88
113
|
const hasFiredViewCart = useRef(false);
|
|
89
114
|
const hasFiredBeginCheckout = useRef(false);
|
|
90
115
|
const hasFiredPaymentMethod = useRef(false);
|
|
116
|
+
const termsAndConditionsRef = useRef<HTMLDivElement | null>(null);
|
|
117
|
+
|
|
91
118
|
const item: IEcommerce = {
|
|
92
119
|
currency: event.currency,
|
|
93
120
|
items: [
|
|
@@ -274,11 +301,36 @@ const TicketForm: React.FC<Props> = ({
|
|
|
274
301
|
// }
|
|
275
302
|
// return true;
|
|
276
303
|
// }),
|
|
277
|
-
shipping: Yup.object()
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
304
|
+
shipping: Yup.object()
|
|
305
|
+
.shape({
|
|
306
|
+
shippingMethodId: Yup.number().nullable(),
|
|
307
|
+
branchId: Yup.string().nullable(),
|
|
308
|
+
price: Yup.number(),
|
|
309
|
+
})
|
|
310
|
+
.test('shipping-method-required', t('form.validation.required'), function (value) {
|
|
311
|
+
if (!event.hasMerchandise) {
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const formValues = this.parent as ITicketForm;
|
|
316
|
+
const hasProducts = Object.values(formValues.products ?? {}).some((arr) => arr.length > 0);
|
|
317
|
+
const allTickets = Object.values(formValues.tickets ?? {}).flat();
|
|
318
|
+
const hasTicketProducts = allTickets.some((ticket) => (ticket.products?.length ?? 0) > 0);
|
|
319
|
+
const requiresShipping = hasProducts || hasTicketProducts;
|
|
320
|
+
|
|
321
|
+
if (!requiresShipping) {
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (value?.shippingMethodId !== null && value?.shippingMethodId !== undefined) {
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return this.createError({
|
|
330
|
+
path: 'shipping.shippingMethodId',
|
|
331
|
+
message: t('form.validation.required'),
|
|
332
|
+
});
|
|
333
|
+
}),
|
|
282
334
|
paymentMethodId: Yup.number().nullable().required(t('form.validation.required')),
|
|
283
335
|
paymentMethodOptionId: Yup.number().nullable(),
|
|
284
336
|
termsAndConditions: Yup.boolean().isTrue(t('form.validation.terms_and_conditions')),
|
|
@@ -306,15 +358,11 @@ const TicketForm: React.FC<Props> = ({
|
|
|
306
358
|
defaultValues,
|
|
307
359
|
});
|
|
308
360
|
const values = methods.watch();
|
|
361
|
+
const cartItemCount = getCartUniqueItemCount(values);
|
|
362
|
+
const onInvalid = useScrollToFirstError(methods);
|
|
309
363
|
|
|
310
364
|
const onSubmit = async (values: ITicketForm) => {
|
|
311
|
-
|
|
312
|
-
if (
|
|
313
|
-
allTickets.length === 1 &&
|
|
314
|
-
!allTickets[0].releaseId &&
|
|
315
|
-
!allTickets[0].quantity &&
|
|
316
|
-
!values.products.length
|
|
317
|
-
) {
|
|
365
|
+
if (cartItemCount <= 0) {
|
|
318
366
|
showSnackbar(t('form.validation.count_tickets_or_products'), {
|
|
319
367
|
variant: 'error',
|
|
320
368
|
});
|
|
@@ -444,7 +492,7 @@ const TicketForm: React.FC<Props> = ({
|
|
|
444
492
|
}, [window.location.search]);
|
|
445
493
|
|
|
446
494
|
useEffect(() => {
|
|
447
|
-
const subscription = methods.watch((value
|
|
495
|
+
const subscription = methods.watch((value) => {
|
|
448
496
|
if (
|
|
449
497
|
JSON.stringify(defaultValues) !== JSON.stringify(value) &&
|
|
450
498
|
!hasFiredBeginCheckout.current
|
|
@@ -471,7 +519,7 @@ const TicketForm: React.FC<Props> = ({
|
|
|
471
519
|
useEffect(() => {
|
|
472
520
|
if (hasGopayId || isPaying || paymentRedirect) {
|
|
473
521
|
if (options?.autoscrollAfterViewChange) {
|
|
474
|
-
const orderForm = document.getElementById(
|
|
522
|
+
const orderForm = document.getElementById(EVENTLOOK_ORDER_FORM_CONTAINER_ID);
|
|
475
523
|
if (orderForm) {
|
|
476
524
|
orderForm.scrollIntoView({ behavior: 'smooth' });
|
|
477
525
|
}
|
|
@@ -483,7 +531,7 @@ const TicketForm: React.FC<Props> = ({
|
|
|
483
531
|
return <ReleaseCountdown event={event} setShowReleaseDate={setShowReleaseDate} />;
|
|
484
532
|
|
|
485
533
|
return (
|
|
486
|
-
<Box id={
|
|
534
|
+
<Box id={EVENTLOOK_ORDER_FORM_CONTAINER_ID}>
|
|
487
535
|
{hasGopayId ? (
|
|
488
536
|
<PaymentSuccess setIsPaying={setIsPaying} isIframe={isIframe} pixels={pixels} />
|
|
489
537
|
) : isPaying ? (
|
|
@@ -496,32 +544,65 @@ const TicketForm: React.FC<Props> = ({
|
|
|
496
544
|
isInline={isInline}
|
|
497
545
|
/>
|
|
498
546
|
) : (
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
547
|
+
<FormProvider
|
|
548
|
+
methods={methods}
|
|
549
|
+
// @ts-ignore -- handleSubmit type mismatch with FormProvider onSubmit prop
|
|
550
|
+
onSubmit={methods.handleSubmit(onSubmit, onInvalid)}
|
|
551
|
+
formId={EVENTLOOK_ORDER_FORM_ID}
|
|
552
|
+
>
|
|
553
|
+
<Stack
|
|
502
554
|
className="overview-card__event-info"
|
|
503
555
|
display={{ md: 'none' }}
|
|
504
|
-
variant="h4"
|
|
505
556
|
sx={{
|
|
506
557
|
mb: 2,
|
|
507
558
|
}}
|
|
508
559
|
>
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
560
|
+
<Typography variant="h3" component="h1">
|
|
561
|
+
{event.name}
|
|
562
|
+
</Typography>
|
|
563
|
+
<Typography variant="h5" component="h2">
|
|
564
|
+
{dayjs(event.startDate).format('DD.MM.YYYY HH:mm')}
|
|
565
|
+
</Typography>
|
|
566
|
+
<Typography variant="body2" mt={1}>
|
|
567
|
+
{getPlaceAsString(event.place)}
|
|
568
|
+
</Typography>
|
|
569
|
+
{headerSlot ? <>{headerSlot}</> : null}
|
|
570
|
+
</Stack>
|
|
571
|
+
<Grid
|
|
572
|
+
container
|
|
573
|
+
spacing={2}
|
|
574
|
+
sx={{
|
|
575
|
+
pb: {
|
|
576
|
+
xs: isPaymentOverviewDrawerOpen ? cartItemCount * 4 + 18 : 0,
|
|
577
|
+
md: 0,
|
|
578
|
+
},
|
|
579
|
+
}}
|
|
580
|
+
>
|
|
512
581
|
<Grid size={{ xs: 12, md: 8 }}>
|
|
513
|
-
<Stepper
|
|
582
|
+
<Stepper
|
|
583
|
+
orientation="vertical"
|
|
584
|
+
sx={(theme) => ({
|
|
585
|
+
[theme.breakpoints.down('sm')]: {
|
|
586
|
+
'& .MuiStepContent-root': {
|
|
587
|
+
borderLeftWidth: 0,
|
|
588
|
+
paddingLeft: 0,
|
|
589
|
+
marginLeft: 0,
|
|
590
|
+
},
|
|
591
|
+
'& .MuiStepConnector-line': { borderLeftWidth: 0 },
|
|
592
|
+
},
|
|
593
|
+
})}
|
|
594
|
+
>
|
|
514
595
|
{event.type === EventType.RECURRING && (
|
|
515
596
|
<Step active>
|
|
516
597
|
<StepLabel>{t('event.tickets.stepper.6.title')}</StepLabel>
|
|
517
|
-
<StepContent>
|
|
598
|
+
<StepContent sx={{ pr: { xs: 0 } }}>
|
|
518
599
|
<TimeslotSelection event={event} />
|
|
519
600
|
</StepContent>
|
|
520
601
|
</Step>
|
|
521
602
|
)}
|
|
522
603
|
<Step active>
|
|
523
604
|
<StepLabel>{t('event.tickets.stepper.1.title')}</StepLabel>
|
|
524
|
-
<StepContent>
|
|
605
|
+
<StepContent sx={{ pr: { xs: 0 } }}>
|
|
525
606
|
{event.mapId && seatingIframeUrl ? (
|
|
526
607
|
<TicketSelectionMap event={event} />
|
|
527
608
|
) : event.hasMerchandise ? (
|
|
@@ -534,7 +615,7 @@ const TicketForm: React.FC<Props> = ({
|
|
|
534
615
|
{event.hasMerchandise && eventProducts.length && (
|
|
535
616
|
<Step active>
|
|
536
617
|
<StepLabel>{t('event.tickets.stepper.4.title')}</StepLabel>
|
|
537
|
-
<StepContent>
|
|
618
|
+
<StepContent sx={{ pr: { xs: 0 } }}>
|
|
538
619
|
<MerchandiseSelection
|
|
539
620
|
eventProducts={eventProducts}
|
|
540
621
|
eventId={event.id}
|
|
@@ -543,24 +624,30 @@ const TicketForm: React.FC<Props> = ({
|
|
|
543
624
|
</StepContent>
|
|
544
625
|
</Step>
|
|
545
626
|
)}
|
|
627
|
+
<Step active>
|
|
628
|
+
<StepLabel>{t('event.tickets.stepper.8.title')}</StepLabel>
|
|
629
|
+
<StepContent sx={{ pr: { xs: 0 } }}>
|
|
630
|
+
<Services event={event} />
|
|
631
|
+
</StepContent>
|
|
632
|
+
</Step>
|
|
546
633
|
{event.children.length && (
|
|
547
634
|
<Step active>
|
|
548
635
|
<StepLabel>{t('event.tickets.stepper.7.title')}</StepLabel>
|
|
549
|
-
<StepContent>
|
|
636
|
+
<StepContent sx={{ pr: { xs: 0 } }}>
|
|
550
637
|
<ChildEventSection events={event.children} />
|
|
551
638
|
</StepContent>
|
|
552
639
|
</Step>
|
|
553
640
|
)}
|
|
554
641
|
<Step active>
|
|
555
642
|
<StepLabel>{t('event.tickets.stepper.2.title')}</StepLabel>
|
|
556
|
-
<StepContent>
|
|
643
|
+
<StepContent sx={{ pr: { xs: 0 } }}>
|
|
557
644
|
<ContactPerson event={event} />
|
|
558
645
|
</StepContent>
|
|
559
646
|
</Step>
|
|
560
647
|
{event.hasMerchandise && showShippingMethods() && (
|
|
561
648
|
<Step active>
|
|
562
649
|
<StepLabel>{t('event.tickets.stepper.5.title')}</StepLabel>
|
|
563
|
-
<StepContent>
|
|
650
|
+
<StepContent sx={{ pr: { xs: 0 } }}>
|
|
564
651
|
<Shipping event={event} />
|
|
565
652
|
</StepContent>
|
|
566
653
|
</Step>
|
|
@@ -571,12 +658,17 @@ const TicketForm: React.FC<Props> = ({
|
|
|
571
658
|
`event.tickets.stepper.3.${values.isPaymentVerify ? 'title_verify' : 'title'}`
|
|
572
659
|
)}
|
|
573
660
|
</StepLabel>
|
|
574
|
-
<StepContent>
|
|
661
|
+
<StepContent sx={{ pr: { xs: 0 } }}>
|
|
575
662
|
<Payment event={event} />
|
|
576
663
|
</StepContent>
|
|
577
664
|
</Step>
|
|
578
665
|
</Stepper>
|
|
579
|
-
<Stack
|
|
666
|
+
<Stack
|
|
667
|
+
ref={termsAndConditionsRef}
|
|
668
|
+
mt={2}
|
|
669
|
+
ml={{ xs: 1, md: 4 }}
|
|
670
|
+
sx={{ scrollMarginBottom: { xs: 220, md: 0 } }}
|
|
671
|
+
>
|
|
580
672
|
<RHFCheckbox
|
|
581
673
|
name="termsAndConditions"
|
|
582
674
|
label={
|
|
@@ -596,15 +688,28 @@ const TicketForm: React.FC<Props> = ({
|
|
|
596
688
|
/>
|
|
597
689
|
</Stack>
|
|
598
690
|
</Grid>
|
|
599
|
-
<Grid size={{ xs:
|
|
600
|
-
<
|
|
691
|
+
<Grid size={12} sx={{ display: { xs: 'block', md: 'none' } }}>
|
|
692
|
+
<Divider sx={{ borderStyle: 'dashed' }} />
|
|
693
|
+
</Grid>
|
|
694
|
+
<Grid size={{ xs: 12, md: 4 }} sx={{ mt: { xs: 0, md: 0 } }}>
|
|
695
|
+
<PaymentOverviewBox event={event} withoutPadding />
|
|
601
696
|
</Grid>
|
|
602
697
|
</Grid>
|
|
698
|
+
|
|
699
|
+
{!isIframe && (
|
|
700
|
+
<PaymentOverviewDrawer
|
|
701
|
+
event={event}
|
|
702
|
+
totalPrice={values.total}
|
|
703
|
+
termsAndConditionsRef={termsAndConditionsRef}
|
|
704
|
+
onOpenChange={setIsPaymentOverviewDrawerOpen}
|
|
705
|
+
/>
|
|
706
|
+
)}
|
|
707
|
+
|
|
603
708
|
<EmailConfirmation
|
|
604
709
|
open={formStep === 2 && !isIframe}
|
|
605
710
|
onClose={() => setFormStep(1)}
|
|
606
|
-
// @ts-ignore -- handleSubmit
|
|
607
|
-
onConfirm={methods.handleSubmit(onSubmit)}
|
|
711
|
+
// @ts-ignore -- handleSubmit type mismatch with onConfirm prop
|
|
712
|
+
onConfirm={methods.handleSubmit(onSubmit, onInvalid)}
|
|
608
713
|
/>
|
|
609
714
|
</FormProvider>
|
|
610
715
|
)}
|
|
@@ -613,7 +718,7 @@ const TicketForm: React.FC<Props> = ({
|
|
|
613
718
|
};
|
|
614
719
|
|
|
615
720
|
const CustomLink: React.FC<PropsWithChildren<LinkProps>> = ({ href = '', children, ...other }) => (
|
|
616
|
-
<Link href={href} {...other}>
|
|
721
|
+
<Link href={href} {...other} sx={{ color: 'inherit', textDecoration: 'underline' }}>
|
|
617
722
|
{children}
|
|
618
723
|
</Link>
|
|
619
724
|
);
|
package/src/form/index.tsx
CHANGED
|
@@ -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} size={{ 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, -2.5),
|
|
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,
|
|
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';
|
|
@@ -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
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
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
|
};
|