@eventlook/sdk 1.7.2-beta.0 → 1.7.3-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 (55) hide show
  1. package/dist/cjs/{index-DmK9RPSa.js → index-CXsZ9BsP.js} +50 -37
  2. package/dist/cjs/index-CXsZ9BsP.js.map +1 -0
  3. package/dist/cjs/index-DgOx9uHQ.js +41917 -0
  4. package/dist/cjs/index-DgOx9uHQ.js.map +1 -0
  5. package/dist/cjs/index.js +1 -1
  6. package/dist/cjs/{index.umd-DUMMTVwU.js → index.umd-DR37hmpO.js} +2 -2
  7. package/dist/cjs/{index.umd-DUMMTVwU.js.map → index.umd-DR37hmpO.js.map} +1 -1
  8. package/dist/cjs/index.umd-TbjzhsUx.js +13397 -0
  9. package/dist/cjs/index.umd-TbjzhsUx.js.map +1 -0
  10. package/dist/esm/index-Ds-63DcA.js +41896 -0
  11. package/dist/esm/index-Ds-63DcA.js.map +1 -0
  12. package/dist/esm/{index-C0HcmMMr.js → index-z31XSEKz.js} +50 -37
  13. package/dist/esm/index-z31XSEKz.js.map +1 -0
  14. package/dist/esm/index.js +1 -1
  15. package/dist/esm/{index.umd-BqJOlKvJ.js → index.umd-5znOX_Ww.js} +2 -2
  16. package/dist/esm/{index.umd-BqJOlKvJ.js.map → index.umd-5znOX_Ww.js.map} +1 -1
  17. package/dist/esm/index.umd-ddggyAGa.js +13395 -0
  18. package/dist/esm/index.umd-ddggyAGa.js.map +1 -0
  19. package/dist/types/form/Payment.d.ts +1 -0
  20. package/dist/types/form/payment/StripeCheckoutProvider.d.ts +36 -0
  21. package/dist/types/hooks/data/useStripeConfig.d.ts +3 -0
  22. package/dist/types/locales/cs.d.ts +3 -0
  23. package/dist/types/locales/en.d.ts +3 -0
  24. package/dist/types/locales/es.d.ts +3 -0
  25. package/dist/types/locales/pl.d.ts +3 -0
  26. package/dist/types/locales/sk.d.ts +3 -0
  27. package/dist/types/locales/uk.d.ts +3 -0
  28. package/dist/types/modules/order.d.ts +3 -0
  29. package/dist/types/utils/data/ticket.d.ts +1 -0
  30. package/dist/types/utils/types/order.type.d.ts +2 -0
  31. package/dist/types/utils/types/payment-method.type.d.ts +1 -0
  32. package/package.json +4 -2
  33. package/src/form/ChildEventCard.tsx +70 -64
  34. package/src/form/Payment.tsx +42 -3
  35. package/src/form/PaymentOverviewBox.tsx +20 -7
  36. package/src/form/TicketForm.tsx +262 -167
  37. package/src/form/payment/StripeCheckoutProvider.tsx +154 -0
  38. package/src/form/tickets/ReleaseWithMerchandise.tsx +7 -6
  39. package/src/form/tickets/TicketSelection.tsx +7 -6
  40. package/src/form/tickets/TicketSelectionMap.tsx +2 -2
  41. package/src/form/tickets/TicketSelectionMobile.tsx +4 -3
  42. package/src/form/tickets/TicketWithMerchandiseSelection.tsx +5 -4
  43. package/src/hooks/data/useStripeConfig.ts +14 -0
  44. package/src/locales/cs.tsx +3 -0
  45. package/src/locales/en.tsx +3 -0
  46. package/src/locales/es.tsx +3 -0
  47. package/src/locales/pl.tsx +3 -0
  48. package/src/locales/sk.tsx +3 -0
  49. package/src/locales/uk.tsx +3 -0
  50. package/src/modules/order.ts +3 -0
  51. package/src/utils/data/ticket.ts +10 -0
  52. package/src/utils/types/order.type.ts +5 -0
  53. package/src/utils/types/payment-method.type.ts +1 -0
  54. package/dist/cjs/index-DmK9RPSa.js.map +0 -1
  55. package/dist/esm/index-C0HcmMMr.js.map +0 -1
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { IEvent } from '@utils/types/event.type';
3
3
  interface Props {
4
4
  event: IEvent;
5
+ stripeReady?: boolean;
5
6
  }
6
7
  declare const Payment: React.FC<Props>;
7
8
  export default Payment;
@@ -0,0 +1,36 @@
1
+ import React, { MutableRefObject } from 'react';
2
+ /**
3
+ * Imperative handle the order form uses to drive the inline Stripe payment from
4
+ * its own submit handler (which lives outside the <Elements> tree).
5
+ */
6
+ export interface StripeCheckoutApi {
7
+ ready: boolean;
8
+ /** Validate + collect the card fields. Returns an error message, or null. */
9
+ submit: () => Promise<string | null>;
10
+ /** Confirm the server-created PaymentIntent. */
11
+ confirm: (clientSecret: string, returnUrl: string) => Promise<{
12
+ ok: boolean;
13
+ error?: string;
14
+ }>;
15
+ }
16
+ interface Props {
17
+ /** Mount Elements only when a Stripe method is offered and the key is loaded. */
18
+ active: boolean;
19
+ publishableKey: string | null;
20
+ /** 'payment' for paid orders, 'setup' for free (0-amount) card verification. */
21
+ mode: 'payment' | 'setup';
22
+ /** Charge amount in minor units (used by Elements; the server intent is authoritative). */
23
+ amount: number;
24
+ currency: string;
25
+ locale: string;
26
+ apiRef: MutableRefObject<StripeCheckoutApi | null>;
27
+ children: React.ReactNode;
28
+ }
29
+ /**
30
+ * Wraps the order form in a deferred-mode <Elements> provider so the Payment
31
+ * Element can be shown inline (expanded under the selected method) before the
32
+ * order — and its PaymentIntent — exists. When no Stripe method is on offer it
33
+ * renders children untouched and loads nothing.
34
+ */
35
+ declare const StripeCheckoutProvider: React.FC<Props>;
36
+ export default StripeCheckoutProvider;
@@ -0,0 +1,3 @@
1
+ export default function useStripeConfig(enabled: boolean): {
2
+ publishableKey: string | null;
3
+ };
@@ -44,6 +44,9 @@ declare const cs: {
44
44
  total: string;
45
45
  with_fee: string;
46
46
  service_fee: string;
47
+ payment_processing_fee: string;
48
+ card_payment_title: string;
49
+ card_payment_error: string;
47
50
  shipping_fee: string;
48
51
  ticket_insurance: string;
49
52
  price_including_service_fee: string;
@@ -44,6 +44,9 @@ declare const en: {
44
44
  total: string;
45
45
  with_fee: string;
46
46
  service_fee: string;
47
+ payment_processing_fee: string;
48
+ card_payment_title: string;
49
+ card_payment_error: string;
47
50
  shipping_fee: string;
48
51
  ticket_insurance: string;
49
52
  price_including_service_fee: string;
@@ -44,6 +44,9 @@ declare const es: {
44
44
  total: string;
45
45
  with_fee: string;
46
46
  service_fee: string;
47
+ payment_processing_fee: string;
48
+ card_payment_title: string;
49
+ card_payment_error: string;
47
50
  shipping_fee: string;
48
51
  ticket_insurance: string;
49
52
  price_including_service_fee: string;
@@ -44,6 +44,9 @@ declare const pl: {
44
44
  total: string;
45
45
  with_fee: string;
46
46
  service_fee: string;
47
+ payment_processing_fee: string;
48
+ card_payment_title: string;
49
+ card_payment_error: string;
47
50
  shipping_fee: string;
48
51
  ticket_insurance: string;
49
52
  price_including_service_fee: string;
@@ -44,6 +44,9 @@ declare const sk: {
44
44
  total: string;
45
45
  with_fee: string;
46
46
  service_fee: string;
47
+ payment_processing_fee: string;
48
+ card_payment_title: string;
49
+ card_payment_error: string;
47
50
  shipping_fee: string;
48
51
  ticket_insurance: string;
49
52
  price_including_service_fee: string;
@@ -44,6 +44,9 @@ declare const uk: {
44
44
  total: string;
45
45
  with_fee: string;
46
46
  service_fee: string;
47
+ payment_processing_fee: string;
48
+ card_payment_title: string;
49
+ card_payment_error: string;
47
50
  shipping_fee: string;
48
51
  ticket_insurance: string;
49
52
  price_including_service_fee: string;
@@ -5,3 +5,6 @@ import { Currencies } from '@utils/data/currency';
5
5
  export declare const postOrder: (data: ITicketBody) => Promise<IResponse<IOrderCreate>>;
6
6
  export declare const getAllowedPaymentMethods: (currency: Currencies, eventId?: number) => Promise<any>;
7
7
  export declare const postOrderPaid: (data: IOrderPaidData) => Promise<IResponse<IOrderPaid>>;
8
+ export declare const getStripeConfig: () => Promise<{
9
+ publishableKey: string | null;
10
+ }>;
@@ -1 +1,2 @@
1
1
  export declare const MAX_TICKETS_PER_ORDER = 10;
2
+ export declare const getMaxTicketsPerOrder: (eventId?: number) => number;
@@ -21,6 +21,8 @@ export interface IOrder extends IBase {
21
21
  }
22
22
  export interface IOrderCreate {
23
23
  gwUrl: string;
24
+ clientSecret: string | null;
25
+ publishableKey: string | null;
24
26
  tickets: ICreateTicket[];
25
27
  orderEntity: IOrder;
26
28
  customer: ICustomer;
@@ -12,6 +12,7 @@ export interface IPaymentMethod extends IBase {
12
12
  image: IFile;
13
13
  feeType: string;
14
14
  feeValue: number;
15
+ feeFixedValue: number;
15
16
  }
16
17
  export interface IPaymentOption extends IBase {
17
18
  category: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eventlook/sdk",
3
- "version": "1.7.2-beta.0",
3
+ "version": "1.7.3-beta.0",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "types": "dist/types/index.d.ts",
@@ -22,7 +22,7 @@
22
22
  "watch:push": "chokidar 'dist/**/*' -c 'yalc push --changed --force'",
23
23
  "dev": "concurrently --kill-others-on-fail --kill-others \"yarn watch:rollup\" \"yarn watch:types\" \"yarn watch:push\"",
24
24
  "dev:simple": "concurrently --kill-others-on-fail \"yarn watch:rollup\" \"yarn watch:types\"",
25
- "publish": "npm publish",
25
+ "release": "npm publish",
26
26
  "lint": "eslint .",
27
27
  "lint:fix": "eslint --fix .",
28
28
  "prettier": "prettier --write 'src/**/*.{js,jsx,ts,tsx}'",
@@ -56,6 +56,8 @@
56
56
  "@rollup/plugin-replace": "^6.0.3",
57
57
  "@rollup/plugin-typescript": "^12.3.0",
58
58
  "@seat-picker/seat-picker-sdk": "^1.2.0",
59
+ "@stripe/react-stripe-js": "^6.6.0",
60
+ "@stripe/stripe-js": "^9.7.0",
59
61
  "@types/js-cookie": "^3.0.6",
60
62
  "@types/lodash": "^4.17.24",
61
63
  "@types/numeral": "^2.0.5",
@@ -40,31 +40,34 @@ const ChildEventCard: React.FC<Props> = ({ event }) => {
40
40
  return (
41
41
  <>
42
42
  <Card sx={{ p: 2 }}>
43
- <Grid container spacing={6} alignItems="stretch">
44
- {/* LEFT SIDE: Image + Button */}
45
- <Grid size={{ xs: 12, md: 6 }} sx={{ display: 'flex', flexDirection: 'column' }}>
46
- <Image src={event.image.url} alt={event.name} ratio="16/9" borderRadius={2} />
47
- <Button
48
- variant="contained"
49
- onClick={() => setOpenVariantDialog(true)}
50
- fullWidth
51
- startIcon={
52
- eventNotEmpty ? <Iconify icon="eva:edit-fill" /> : <Iconify icon="eva:plus-fill" />
53
- }
54
- sx={{ mt: 2 }}
55
- >
56
- {eventNotEmpty ? t('change') : t('add')}
57
- </Button>
58
- </Grid>
59
-
60
- {/* RIGHT SIDE: Info block with bottom aligned date + organizer */}
61
- <Grid
62
- size={{ xs: 12, md: 6 }}
63
- sx={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}
64
- >
65
- <Stack spacing={2}>
66
- <Typography variant="h6">{event.name}</Typography>
43
+ <Stack spacing={2}>
44
+ <Typography variant="h6">{event.name}</Typography>
45
+ <Grid container spacing={6} alignItems="stretch">
46
+ {/* LEFT SIDE: Image + Button */}
47
+ <Grid size={{ xs: 12, md: 6 }} sx={{ display: 'flex', flexDirection: 'column' }}>
48
+ <Image src={event.image.url} alt={event.name} ratio="16/9" borderRadius={2} />
49
+ <Button
50
+ variant="contained"
51
+ onClick={() => setOpenVariantDialog(true)}
52
+ fullWidth
53
+ startIcon={
54
+ eventNotEmpty ? (
55
+ <Iconify icon="eva:edit-fill" />
56
+ ) : (
57
+ <Iconify icon="eva:plus-fill" />
58
+ )
59
+ }
60
+ sx={{ mt: 2 }}
61
+ >
62
+ {eventNotEmpty ? t('change') : t('add')}
63
+ </Button>
64
+ </Grid>
67
65
 
66
+ {/* RIGHT SIDE: Info block with bottom aligned date + organizer */}
67
+ <Grid
68
+ size={{ xs: 12, md: 6 }}
69
+ sx={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}
70
+ >
68
71
  <TextIconLabel
69
72
  icon={
70
73
  <Iconify
@@ -75,48 +78,51 @@ const ChildEventCard: React.FC<Props> = ({ event }) => {
75
78
  value={<Box>{getPlaceAsString(event.place)}</Box>}
76
79
  sx={{ typography: 'body3', color: 'text.secondary', alignItems: 'flex-start' }}
77
80
  />
78
- </Stack>
79
81
 
80
- {/* Bottom: Date & Organizer */}
81
- <Stack
82
- direction={{ xs: 'column', sm: 'row', md: 'column', lg: 'row' }}
83
- spacing={2}
84
- p={2}
85
- divider={
86
- <Divider
87
- orientation={xs || md ? 'horizontal' : 'vertical'}
88
- flexItem
89
- sx={{ borderStyle: 'dashed' }}
90
- />
91
- }
92
- sx={{
93
- backgroundColor: (theme) => theme.palette.grey.A100,
94
- borderRadius: 1,
95
- }}
96
- >
97
- <Box width={{ sm: '50%', md: '100%', lg: '50%' }}>
98
- <TextIconLabel
99
- icon={<Iconify icon={calendarIcon} sx={{ minWidth: 20, height: 20, mr: 1 }} />}
100
- value={t('form.labels.start_date')}
101
- sx={{ color: 'text.secondary' }}
102
- />
103
- <Typography variant="body2" fontWeight={700}>
104
- {dayjs(event.startDate).format('DD.MM.YYYY HH:mm')}
105
- </Typography>
106
- </Box>
107
- <Box width={{ sm: '50%', md: '100%', lg: '50%' }}>
108
- <TextIconLabel
109
- icon={<Iconify icon={userIcon} sx={{ minWidth: 20, height: 20, mr: 1 }} />}
110
- value={t('form.labels.organizer')}
111
- sx={{ color: 'text.secondary' }}
112
- />
113
- <Typography variant="body2" fontWeight={700}>
114
- {event.company.displayName}
115
- </Typography>
116
- </Box>
117
- </Stack>
82
+ {/* Bottom: Date & Organizer */}
83
+ <Stack
84
+ direction={{ xs: 'column', sm: 'row', md: 'column', lg: 'row' }}
85
+ spacing={2}
86
+ p={2}
87
+ divider={
88
+ <Divider
89
+ orientation={xs || md ? 'horizontal' : 'vertical'}
90
+ flexItem
91
+ sx={{ borderStyle: 'dashed' }}
92
+ />
93
+ }
94
+ sx={{
95
+ backgroundColor: (theme) =>
96
+ theme.palette.mode === 'light'
97
+ ? theme.palette.grey[100]
98
+ : theme.palette.grey[900],
99
+ borderRadius: 1,
100
+ }}
101
+ >
102
+ <Box width={{ sm: '50%', md: '100%', lg: '50%' }}>
103
+ <TextIconLabel
104
+ icon={<Iconify icon={calendarIcon} sx={{ minWidth: 20, height: 20, mr: 1 }} />}
105
+ value={t('form.labels.start_date')}
106
+ sx={{ color: 'text.secondary' }}
107
+ />
108
+ <Typography variant="body2" fontWeight={700}>
109
+ {dayjs(event.startDate).format('DD.MM.YYYY HH:mm')}
110
+ </Typography>
111
+ </Box>
112
+ <Box width={{ sm: '50%', md: '100%', lg: '50%' }}>
113
+ <TextIconLabel
114
+ icon={<Iconify icon={userIcon} sx={{ minWidth: 20, height: 20, mr: 1 }} />}
115
+ value={t('form.labels.organizer')}
116
+ sx={{ color: 'text.secondary' }}
117
+ />
118
+ <Typography variant="body2" fontWeight={700}>
119
+ {event.company.displayName}
120
+ </Typography>
121
+ </Box>
122
+ </Stack>
123
+ </Grid>
118
124
  </Grid>
119
- </Grid>
125
+ </Stack>
120
126
  </Card>
121
127
 
122
128
  <ChildEventDialog
@@ -2,6 +2,7 @@ import React, { KeyboardEvent, useEffect, useMemo, useState } from 'react';
2
2
  import {
3
3
  Box,
4
4
  Button,
5
+ CircularProgress,
5
6
  Divider,
6
7
  FormControl,
7
8
  FormControlLabel,
@@ -19,6 +20,7 @@ import { PaymentItem, PaymentWrapper, PaymentSwiftWrapper } from '@form/style';
19
20
  import Image from '@components/Image';
20
21
  import Label from '@components/Label';
21
22
  import PaymentSkeleton from '@form/payment/PaymentSkeleton';
23
+ import { PaymentElement } from '@stripe/react-stripe-js';
22
24
  import { RHFRadioGroup } from '@components/hook-form';
23
25
  import { postPromoCodeApply } from '@modules/promo-code';
24
26
  import { IEvent } from '@utils/types/event.type';
@@ -32,9 +34,12 @@ import { IEventProductForm } from '@utils/types/product.type';
32
34
 
33
35
  interface Props {
34
36
  event: IEvent;
37
+ // True once the Stripe Elements provider is mounted (key loaded), so the
38
+ // inline Payment Element can render under the selected Stripe method.
39
+ stripeReady?: boolean;
35
40
  }
36
41
 
37
- const Payment: React.FC<Props> = ({ event }) => {
42
+ const Payment: React.FC<Props> = ({ event, stripeReady }) => {
38
43
  const { t, lang } = useGlobal();
39
44
  const { showSnackbar } = useGlobal();
40
45
  const { data, isLoading } = useAllowedPaymentMethods(event.currency, event.id);
@@ -174,8 +179,12 @@ const Payment: React.FC<Props> = ({ event }) => {
174
179
 
175
180
  if (total === 0 && (hasTickets || hasProducts)) {
176
181
  setValue('isPaymentVerify', true);
177
- return data.filter((payment) =>
178
- ['PAYMENT_CARD', 'APPLE_PAY', 'GPAY', 'CLICK_TO_PAY'].includes(payment.type)
182
+ // Free orders only offer card-verification methods (incl. Stripe, which
183
+ // verifies via a SetupIntent) — bot protection without a charge.
184
+ return data.filter(
185
+ (payment) =>
186
+ ['PAYMENT_CARD', 'APPLE_PAY', 'GPAY', 'CLICK_TO_PAY'].includes(payment.type) ||
187
+ payment.provider === 'STRIPE'
179
188
  );
180
189
  } else {
181
190
  setValue('isPaymentVerify', false);
@@ -334,6 +343,36 @@ const Payment: React.FC<Props> = ({ event }) => {
334
343
  />
335
344
  </PaymentSwiftWrapper>
336
345
  )}
346
+ {payment.provider === 'STRIPE' &&
347
+ !!paymentMethodId &&
348
+ Number(paymentMethodId) === payment.id && (
349
+ <PaymentSwiftWrapper sx={{ pb: 3 }}>
350
+ <Divider sx={{ mb: 2 }} />
351
+ {stripeReady ? (
352
+ <PaymentElement options={{ layout: 'tabs' }} />
353
+ ) : Number(total) > 0 ? (
354
+ <Stack alignItems="center" sx={{ py: 3 }}>
355
+ <CircularProgress size={26} />
356
+ </Stack>
357
+ ) : (
358
+ <Stack
359
+ alignItems="center"
360
+ spacing={1}
361
+ sx={{ py: 3, px: 2, textAlign: 'center' }}
362
+ >
363
+ <Iconify
364
+ icon="carbon:shopping-cart"
365
+ width={28}
366
+ height={28}
367
+ sx={{ color: 'text.disabled' }}
368
+ />
369
+ <Typography variant="body2" sx={{ color: 'text.secondary' }}>
370
+ {t('form.validation.count_tickets_or_products')}
371
+ </Typography>
372
+ </Stack>
373
+ )}
374
+ </PaymentSwiftWrapper>
375
+ )}
337
376
  </PaymentItem>
338
377
  ))}
339
378
  </RadioGroup>
@@ -42,6 +42,7 @@ const PaymentOverviewBox: React.FC<Props> = ({ event, withoutPadding, hideBuyBut
42
42
  const insuranceAvailable = isInsuranceAvailable(event.currency);
43
43
  const { data: eventProducts } = useActiveEventProducts(event.id, true);
44
44
  const [shippingFee, setShippingFee] = useState(0);
45
+ const [paymentMethodFee, setPaymentMethodFee] = useState(0);
45
46
  const { setValue, watch } = useFormContext<ITicketForm>();
46
47
  const values = watch();
47
48
  const {
@@ -135,6 +136,10 @@ const PaymentOverviewBox: React.FC<Props> = ({ event, withoutPadding, hideBuyBut
135
136
  }, [event, flatProducts]);
136
137
 
137
138
  const getFee = useMemo(() => fCurrency(totalFee ?? 0, lang, event.currency), [totalFee]);
139
+ const getPaymentMethodFee = useMemo(
140
+ () => fCurrency(paymentMethodFee ?? 0, lang, event.currency),
141
+ [paymentMethodFee]
142
+ );
138
143
 
139
144
  const shoppingCartBody = useMemo<ICalculateShoppingCartDto>(
140
145
  () => ({
@@ -253,8 +258,10 @@ const PaymentOverviewBox: React.FC<Props> = ({ event, withoutPadding, hideBuyBut
253
258
  setValue('originalPrice', data.originalPrice);
254
259
  setValue('total', data.totalPrice || 0);
255
260
 
256
- const feeTotal = (data.serviceFee ?? 0) + (data.paymentMethodFee ?? 0);
257
- setValue('totalFee', feeTotal);
261
+ // The Stripe processing surcharge is shown as its own line, so keep the
262
+ // service fee and the payment-method fee separate.
263
+ setValue('totalFee', data.serviceFee ?? 0);
264
+ setPaymentMethodFee(data.paymentMethodFee ?? 0);
258
265
 
259
266
  setShippingFee(data.shippingFee);
260
267
  setValue('ticketInsurance', data.ticketInsurance.enabled);
@@ -482,13 +489,13 @@ const PaymentOverviewBox: React.FC<Props> = ({ event, withoutPadding, hideBuyBut
482
489
  className="overview-card__order-info"
483
490
  sx={{ p: { xs: withoutPadding ? 0 : 2, md: 2 } }}
484
491
  pt={{ xs: 0, sm: 2 }}
485
- spacing={0.75}
492
+ spacing={1.25}
486
493
  useFlexGap
487
494
  >
488
- {!!selectedTickets.length && !isMobile && <Divider sx={{ borderStyle: 'dashed' }} />}
495
+ {!!selectedTickets.length && !isMobile && <Divider sx={{ borderStyle: 'dashed', my: 1 }} />}
489
496
 
490
497
  {!!selectedTickets.length && (
491
- <Stack spacing={0.5}>
498
+ <Stack spacing={1}>
492
499
  {insuranceAvailable && (
493
500
  <PaymentOverviewCheckbox
494
501
  checkboxName="ticketInsurance"
@@ -515,7 +522,7 @@ const PaymentOverviewBox: React.FC<Props> = ({ event, withoutPadding, hideBuyBut
515
522
  </>
516
523
  }
517
524
  />
518
- <Divider sx={{ borderStyle: 'dashed' }} />
525
+ <Divider sx={{ borderStyle: 'dashed', mt: 0.5 }} />
519
526
  </Stack>
520
527
  )}
521
528
  {selectedTickets.map((ticket, index) => (
@@ -600,8 +607,14 @@ const PaymentOverviewBox: React.FC<Props> = ({ event, withoutPadding, hideBuyBut
600
607
  <Typography variant="body2">{getFee}</Typography>
601
608
  </Stack>
602
609
  )}
610
+ {!!total && !!paymentMethodFee && (
611
+ <Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}>
612
+ <Typography variant="body2">{t('form.labels.payment_processing_fee')}</Typography>
613
+ <Typography variant="body2">{getPaymentMethodFee}</Typography>
614
+ </Stack>
615
+ )}
603
616
  {((!!selectedTickets.length && isMobile) || !isMobile) && (
604
- <Divider sx={{ borderStyle: 'dashed' }} />
617
+ <Divider sx={{ borderStyle: 'dashed', my: 1 }} />
605
618
  )}
606
619
  {!hideBuyButton && (
607
620
  <>