@eventlook/sdk 1.7.0 → 1.7.2-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 (78) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/.prettierignore +3 -0
  3. package/CLAUDE.md +33 -0
  4. package/dist/cjs/{index-0a8uUeDg.js → index-DmK9RPSa.js} +26553 -25757
  5. package/dist/cjs/index-DmK9RPSa.js.map +1 -0
  6. package/dist/cjs/index.js +3 -1
  7. package/dist/cjs/index.js.map +1 -1
  8. package/dist/cjs/{index.umd-BvTBfvwB.js → index.umd-DUMMTVwU.js} +2 -2
  9. package/dist/cjs/{index.umd-BvTBfvwB.js.map → index.umd-DUMMTVwU.js.map} +1 -1
  10. package/dist/cjs/{mui-tel-input.es-Bjml407E.js → mui-tel-input.es-Dk9M_v4X.js} +6 -6
  11. package/dist/{esm/mui-tel-input.es-Bt2rE3An.js.map → cjs/mui-tel-input.es-Dk9M_v4X.js.map} +1 -1
  12. package/dist/esm/{index-ByLnhSXB.js → index-C0HcmMMr.js} +27111 -26333
  13. package/dist/esm/index-C0HcmMMr.js.map +1 -0
  14. package/dist/esm/index.js +3 -1
  15. package/dist/esm/index.js.map +1 -1
  16. package/dist/esm/{index.umd-DepuOxm3.js → index.umd-BqJOlKvJ.js} +4 -4
  17. package/dist/esm/{index.umd-DepuOxm3.js.map → index.umd-BqJOlKvJ.js.map} +1 -1
  18. package/dist/esm/{mui-tel-input.es-Bt2rE3An.js → mui-tel-input.es-Cb4Lpqx7.js} +21 -21
  19. package/dist/{cjs/mui-tel-input.es-Bjml407E.js.map → esm/mui-tel-input.es-Cb4Lpqx7.js.map} +1 -1
  20. package/dist/types/form/paydroid/PaydroidCashlessSection.d.ts +7 -0
  21. package/dist/types/form/paydroid/PaydroidError.d.ts +3 -0
  22. package/dist/types/form/paydroid/PaydroidErrorAccount.d.ts +3 -0
  23. package/dist/types/form/paydroid/PaydroidErrorTicket.d.ts +3 -0
  24. package/dist/types/form/paydroid/PaydroidPage.d.ts +6 -0
  25. package/dist/types/form/paydroid/PaydroidStatusCard.d.ts +10 -0
  26. package/dist/types/form/paydroid/PaydroidSuccess.d.ts +3 -0
  27. package/dist/types/form/paydroid/PaydroidSuccessTopup.d.ts +3 -0
  28. package/dist/types/form/tickets/PrimaryTicketDialog.d.ts +10 -0
  29. package/dist/types/locales/cs.d.ts +38 -0
  30. package/dist/types/locales/en.d.ts +40 -1
  31. package/dist/types/locales/es.d.ts +40 -1
  32. package/dist/types/locales/pl.d.ts +40 -1
  33. package/dist/types/locales/sk.d.ts +40 -1
  34. package/dist/types/locales/uk.d.ts +40 -1
  35. package/dist/types/modules/paydroid.d.ts +4 -0
  36. package/dist/types/modules/ticket.d.ts +1 -0
  37. package/dist/types/utils/data/page.d.ts +7 -0
  38. package/dist/types/utils/page.d.ts +1 -0
  39. package/dist/types/utils/paydroid.d.ts +6 -0
  40. package/dist/types/utils/types/global.type.d.ts +1 -0
  41. package/dist/types/utils/types/order.type.d.ts +2 -0
  42. package/dist/types/utils/types/paydroid.d.ts +23 -0
  43. package/dist/types/utils/types/release-category.type.d.ts +1 -0
  44. package/dist/types/utils/types/release.type.d.ts +2 -0
  45. package/dist/types/utils/types/ticket.type.d.ts +1 -0
  46. package/package.json +3 -1
  47. package/src/form/PaymentSuccess.tsx +6 -2
  48. package/src/form/TicketForm.tsx +28 -1
  49. package/src/form/paydroid/PaydroidCashlessSection.tsx +311 -0
  50. package/src/form/paydroid/PaydroidError.tsx +26 -0
  51. package/src/form/paydroid/PaydroidErrorAccount.tsx +26 -0
  52. package/src/form/paydroid/PaydroidErrorTicket.tsx +26 -0
  53. package/src/form/paydroid/PaydroidPage.tsx +22 -0
  54. package/src/form/paydroid/PaydroidStatusCard.tsx +91 -0
  55. package/src/form/paydroid/PaydroidSuccess.tsx +26 -0
  56. package/src/form/paydroid/PaydroidSuccessTopup.tsx +26 -0
  57. package/src/form/tickets/PrimaryTicketDialog.tsx +144 -0
  58. package/src/form/tickets/ReleaseWithMerchandise.tsx +89 -8
  59. package/src/form/tickets/TicketSelectionMobile.tsx +80 -12
  60. package/src/locales/cs.tsx +45 -0
  61. package/src/locales/en.tsx +47 -1
  62. package/src/locales/es.tsx +48 -1
  63. package/src/locales/pl.tsx +47 -1
  64. package/src/locales/sk.tsx +49 -1
  65. package/src/locales/uk.tsx +47 -2
  66. package/src/modules/paydroid.ts +33 -0
  67. package/src/modules/ticket.ts +13 -0
  68. package/src/utils/data/page.ts +7 -0
  69. package/src/utils/page.ts +4 -0
  70. package/src/utils/paydroid.ts +35 -0
  71. package/src/utils/types/global.type.ts +1 -0
  72. package/src/utils/types/order.type.ts +2 -0
  73. package/src/utils/types/paydroid.ts +26 -0
  74. package/src/utils/types/release-category.type.ts +1 -0
  75. package/src/utils/types/release.type.ts +2 -0
  76. package/src/utils/types/ticket.type.ts +1 -0
  77. package/dist/cjs/index-0a8uUeDg.js.map +0 -1
  78. package/dist/esm/index-ByLnhSXB.js.map +0 -1
@@ -61,6 +61,8 @@ import TicketSelectionMap from '@form/tickets/TicketSelectionMap';
61
61
  import PaymentOverviewDrawer from './PaymentOverviewDrawer';
62
62
  import { getPlaceAsString } from '@utils/place';
63
63
  import Services from '@form/services';
64
+ import PaydroidPage from './paydroid/PaydroidPage';
65
+ import { isPaydroidPage } from '@utils/page';
64
66
 
65
67
  interface Props {
66
68
  event: IEvent;
@@ -102,6 +104,7 @@ const TicketForm: React.FC<Props> = ({
102
104
  const { data: eventProducts, isLoading } = useActiveEventProducts(event.id);
103
105
  const [paymentRedirect, setPaymentRedirect] = useState<string | null>(null);
104
106
  const [hasGopayId, setHasGopayId] = useState<boolean>(hasGopayIdSsr);
107
+ const [page, setPage] = useState<string | null>(null);
105
108
  const [isPaying, setIsPaying] = useState<boolean>(false);
106
109
  const [formStep, setFormStep] = useState<number>(1);
107
110
  const [isPaymentOverviewDrawerOpen, setIsPaymentOverviewDrawerOpen] = useState<boolean>(false);
@@ -302,6 +305,26 @@ const TicketForm: React.FC<Props> = ({
302
305
  // }
303
306
  // return true;
304
307
  // }),
308
+ tickets: Yup.object().test('primary-ticket-numbers', function (tickets) {
309
+ if (!tickets || typeof tickets !== 'object') return true;
310
+
311
+ const ticketsRecord = tickets as Record<string, ITicketFormTicket[]>;
312
+ for (const arr of Object.values(ticketsRecord)) {
313
+ if (!Array.isArray(arr)) continue;
314
+ for (const ticket of arr) {
315
+ if (!ticket.primaryTicketNumbers) continue;
316
+ const expected = Number(ticket.quantity || 0);
317
+ const numbers = ticket.primaryTicketNumbers;
318
+ if (numbers.length !== expected) {
319
+ return this.createError({ message: t('form.validation.primary_ticket_required') });
320
+ }
321
+ if (numbers.some((n) => !n || !/^\d+$/.test(n))) {
322
+ return this.createError({ message: t('form.validation.primary_ticket_numeric') });
323
+ }
324
+ }
325
+ }
326
+ return true;
327
+ }),
305
328
  shipping: Yup.object()
306
329
  .shape({
307
330
  shippingMethodId: Yup.number().nullable(),
@@ -398,6 +421,7 @@ const TicketForm: React.FC<Props> = ({
398
421
  extraFields: item.extraFields,
399
422
  eventTimeslotId: item.eventTimeslotId,
400
423
  location: item.location,
424
+ primaryTicketNumbers: item.primaryTicketNumbers,
401
425
  }));
402
426
  return acc;
403
427
  },
@@ -492,6 +516,7 @@ const TicketForm: React.FC<Props> = ({
492
516
  const paymentId = searchParams.id;
493
517
  const iframeCampaignId = Number(searchParams.iframeCampaignId);
494
518
  setHasGopayId(!!paymentId);
519
+ setPage(searchParams.page || null);
495
520
  if (!isNaN(iframeCampaignId)) {
496
521
  methods.setValue('iframeCampaignId', iframeCampaignId);
497
522
  }
@@ -538,7 +563,9 @@ const TicketForm: React.FC<Props> = ({
538
563
 
539
564
  return (
540
565
  <Box id={EVENTLOOK_ORDER_FORM_CONTAINER_ID}>
541
- {hasGopayId ? (
566
+ {isPaydroidPage(page) ? (
567
+ <PaydroidPage page={page} />
568
+ ) : hasGopayId ? (
542
569
  <PaymentSuccess setIsPaying={setIsPaying} isIframe={isIframe} pixels={pixels} />
543
570
  ) : isPaying ? (
544
571
  <PaymentPending />
@@ -0,0 +1,311 @@
1
+ import { Image, varBounce } from '@components';
2
+ import FormProvider, { RHFTextField, RHFCheckbox } from '@components/hook-form';
3
+ import { Box, InputAdornment, Link, Stack, Typography, useTheme } from '@mui/material';
4
+ import { LoadingButton } from '@mui/lab';
5
+ import { m } from 'motion/react';
6
+ import React, { useEffect, useState } from 'react';
7
+ import { useForm } from 'react-hook-form';
8
+ import { yupResolver } from '@hookform/resolvers/yup';
9
+ import * as Yup from 'yup';
10
+ import useGlobal from '@hooks/useGlobal';
11
+ import { Currencies } from '@utils/data/currency';
12
+ import { Page } from '@utils/data/page';
13
+ import { postPaydroidCreateAccount, postPaydroidTopupAccount } from '@modules/paydroid';
14
+ import {
15
+ getRedirectUrl,
16
+ transformToCreateAccountData,
17
+ transformToTopupAccountData,
18
+ } from '@utils/paydroid';
19
+ import { IOrderPaid } from '@utils/types/order.type';
20
+
21
+ const PAYDROID_FONT = "'InterVariable', sans-serif";
22
+
23
+ interface Props {
24
+ data: IOrderPaid;
25
+ }
26
+
27
+ interface PaydroidForm {
28
+ amount: string;
29
+ terms: boolean;
30
+ }
31
+
32
+ const PaydroidCashlessSection: React.FC<Props> = ({ data }) => {
33
+ const { t, showSnackbar, options } = useGlobal();
34
+ const theme = useTheme();
35
+ const [loading, setLoading] = useState(false);
36
+
37
+ useEffect(() => {
38
+ const fonts = [
39
+ {
40
+ id: 'paydroid-inter-font',
41
+ href: 'https://eventigo.s3-central.vshosting.cloud/production/external/fonts/inter/inter.css',
42
+ },
43
+ ];
44
+
45
+ fonts.forEach(({ id, href }) => {
46
+ if (!document.getElementById(id)) {
47
+ const link = document.createElement('link');
48
+ link.id = id;
49
+ link.rel = 'stylesheet';
50
+ link.href = href;
51
+ document.head.appendChild(link);
52
+ }
53
+ });
54
+ }, []);
55
+
56
+ const schema = Yup.object().shape({
57
+ amount: Yup.string().required(t('form.validation.required')),
58
+ terms: Yup.boolean().oneOf([true], t('form.validation.terms_and_conditions')).required(),
59
+ });
60
+
61
+ const methods = useForm<PaydroidForm>({
62
+ resolver: yupResolver(schema),
63
+ defaultValues: {
64
+ amount: '800',
65
+ terms: false,
66
+ },
67
+ });
68
+
69
+ const { handleSubmit, watch } = methods;
70
+ const termsAccepted = watch('terms');
71
+
72
+ const onSubmit = async (values: PaydroidForm) => {
73
+ if (!options?.paydroidApiKey) {
74
+ showSnackbar(t('event.tickets.payment_success.paydroid.missing_api_key'), {
75
+ variant: 'error',
76
+ });
77
+ return;
78
+ }
79
+
80
+ setLoading(true);
81
+ try {
82
+ await postPaydroidCreateAccount(options.paydroidApiKey, transformToCreateAccountData(data));
83
+
84
+ const { data: topupData } = await postPaydroidTopupAccount(
85
+ options.paydroidApiKey,
86
+ transformToTopupAccountData(values.amount, data)
87
+ );
88
+
89
+ window.location.href = topupData.url;
90
+ } catch (error: any) {
91
+ console.log(error);
92
+ showSnackbar(error, { variant: 'error' });
93
+ setLoading(false);
94
+ window.location.href = getRedirectUrl(Page.PAYDROID_ERROR_TICKET);
95
+ }
96
+ };
97
+
98
+ const handleSkip = async () => {
99
+ if (!options?.paydroidApiKey) {
100
+ showSnackbar(t('event.tickets.payment_success.paydroid.missing_api_key'), {
101
+ variant: 'error',
102
+ });
103
+ return;
104
+ }
105
+
106
+ setLoading(true);
107
+ try {
108
+ await postPaydroidCreateAccount(options.paydroidApiKey, transformToCreateAccountData(data));
109
+ window.location.href = getRedirectUrl(Page.PAYDROID_SUCCESS);
110
+ } catch (error: any) {
111
+ showSnackbar(error, { variant: 'error' });
112
+ setLoading(false);
113
+ window.location.href = getRedirectUrl(Page.PAYDROID_ERROR_ACCOUNT);
114
+ }
115
+ };
116
+
117
+ const tp = (key: string) => t(`event.tickets.payment_success.paydroid.${key}`);
118
+
119
+ const termsLabel = (
120
+ <Typography component="span" variant="body2" color="text.secondary">
121
+ {tp('terms_prefix')}{' '}
122
+ <Link
123
+ href="https://www.paydroid.cz/obchodni-podminky"
124
+ target="_blank"
125
+ rel="noopener"
126
+ color="inherit"
127
+ >
128
+ {tp('terms_conditions')}
129
+ </Link>{' '}
130
+ {tp('terms_middle')}{' '}
131
+ <Link
132
+ href="https://www.paydroid.cz/ochrana-osobnich-udaju"
133
+ target="_blank"
134
+ rel="noopener"
135
+ color="inherit"
136
+ >
137
+ {tp('terms_privacy')}
138
+ </Link>
139
+ </Typography>
140
+ );
141
+
142
+ return (
143
+ <m.div variants={varBounce().in}>
144
+ <Box
145
+ py={6}
146
+ sx={{
147
+ bgcolor: 'background.neutral',
148
+ width: '100vw',
149
+ position: 'relative',
150
+ left: '50%',
151
+ ml: '-50vw',
152
+ }}
153
+ >
154
+ <Stack
155
+ direction="row"
156
+ spacing={2}
157
+ justifyContent="center"
158
+ alignItems="center"
159
+ sx={{ mb: 4 }}
160
+ >
161
+ <Image
162
+ src={`https://eventigo.s3-central.vshosting.cloud/production/eventlook-logo${theme.palette.mode === 'dark' ? '-white.svg' : '.png'}`}
163
+ alt="EventLook"
164
+ sx={{ height: 32 }}
165
+ />
166
+ <Typography component="span" fontSize={20} fontWeight={500} color="text.secondary">
167
+ +
168
+ </Typography>
169
+ <Image
170
+ src={`https://eventigo.s3-central.vshosting.cloud/production/external/logo-paydroid-horizontal-${theme.palette.mode === 'dark' ? 'white' : 'black'}.svg`}
171
+ alt="Paydroid Cashless"
172
+ sx={{ height: 32 }}
173
+ />
174
+ </Stack>
175
+
176
+ <Box
177
+ sx={{
178
+ maxWidth: 520,
179
+ mx: 'auto',
180
+ bgcolor: 'background.paper',
181
+ borderRadius: 3,
182
+ px: { xs: 3, sm: 5 },
183
+ py: { xs: 4, sm: 5 },
184
+ textAlign: 'center',
185
+ }}
186
+ >
187
+ <Typography
188
+ sx={{
189
+ fontFamily: PAYDROID_FONT,
190
+ fontWeight: 900,
191
+ fontSize: { xs: 24, sm: 32 },
192
+ lineHeight: 1.15,
193
+ textTransform: 'uppercase',
194
+ wordSpacing: '0.15em',
195
+ }}
196
+ >
197
+ {tp('heading')}
198
+ </Typography>
199
+
200
+ <Typography
201
+ sx={{
202
+ fontFamily: PAYDROID_FONT,
203
+ fontWeight: 900,
204
+ fontSize: { xs: 24, sm: 32 },
205
+ lineHeight: 1.15,
206
+ textTransform: 'uppercase',
207
+ color: 'primary.main',
208
+ mb: 2,
209
+ }}
210
+ >
211
+ {tp('heading_cta')}
212
+ </Typography>
213
+
214
+ <Typography
215
+ variant="body2"
216
+ color="text.secondary"
217
+ sx={{ maxWidth: 380, mx: 'auto', mb: 4 }}
218
+ >
219
+ {tp('subtitle')}
220
+ </Typography>
221
+
222
+ <FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
223
+ <Typography variant="subtitle1" fontWeight={700} mb={1.5} textAlign="left">
224
+ {tp('amount_label')}
225
+ </Typography>
226
+
227
+ <RHFTextField
228
+ name="amount"
229
+ label={tp('amount_placeholder')}
230
+ slotProps={{
231
+ input: {
232
+ endAdornment: (
233
+ <InputAdornment position="end">{Currencies[data.currency]}</InputAdornment>
234
+ ),
235
+ },
236
+ }}
237
+ onChange={(e) => {
238
+ methods.setValue('amount', e.target.value.replace(/\D/g, ''));
239
+ }}
240
+ sx={{
241
+ width: '100%',
242
+ mb: 3,
243
+ '& .MuiInputBase-root': {
244
+ borderRadius: 2,
245
+ },
246
+ }}
247
+ />
248
+
249
+ <Box textAlign="left">
250
+ <RHFCheckbox name="terms" label={termsLabel} />
251
+ </Box>
252
+
253
+ <Stack
254
+ flexDirection={{ xs: 'column', sm: 'row' }}
255
+ gap={2}
256
+ justifyContent="center"
257
+ mt={3}
258
+ >
259
+ <LoadingButton
260
+ variant="outlined"
261
+ color="inherit"
262
+ size="large"
263
+ onClick={handleSkip}
264
+ loading={loading}
265
+ disabled={!termsAccepted}
266
+ sx={{
267
+ textTransform: 'none',
268
+ color: 'text.secondary',
269
+ borderColor: 'divider',
270
+ borderRadius: 2,
271
+ fontSize: 12,
272
+ }}
273
+ >
274
+ {tp('skip')}
275
+ </LoadingButton>
276
+
277
+ <LoadingButton
278
+ type="submit"
279
+ variant="contained"
280
+ size="large"
281
+ disabled={!termsAccepted}
282
+ loading={loading}
283
+ sx={{
284
+ bgcolor: (theme) => (theme.palette.mode === 'dark' ? 'grey.200' : '#1A1A1A'),
285
+ color: (theme) => (theme.palette.mode === 'dark' ? 'grey.800' : 'white'),
286
+ textTransform: 'none',
287
+ borderRadius: 2,
288
+ px: 5,
289
+ fontSize: 12,
290
+ fontWeight: 600,
291
+ '&:hover': {
292
+ bgcolor: (theme) => (theme.palette.mode === 'dark' ? 'grey.300' : '#333'),
293
+ },
294
+ '&.Mui-disabled': {
295
+ bgcolor: (theme) => (theme.palette.mode === 'dark' ? 'grey.200' : '#1A1A1A'),
296
+ opacity: 0.5,
297
+ color: (theme) => (theme.palette.mode === 'dark' ? 'grey.800' : 'white'),
298
+ },
299
+ }}
300
+ >
301
+ {tp('submit')}
302
+ </LoadingButton>
303
+ </Stack>
304
+ </FormProvider>
305
+ </Box>
306
+ </Box>
307
+ </m.div>
308
+ );
309
+ };
310
+
311
+ export default PaydroidCashlessSection;
@@ -0,0 +1,26 @@
1
+ import { Iconify } from '@components/iconify';
2
+ import React from 'react';
3
+ import useGlobal from '@hooks/useGlobal';
4
+ import PaydroidStatusCard from './PaydroidStatusCard';
5
+
6
+ const PaydroidError: React.FC = () => {
7
+ const { t } = useGlobal();
8
+ const tp = (key: string) => t(`event.tickets.payment_success.paydroid.${key}`);
9
+
10
+ return (
11
+ <PaydroidStatusCard
12
+ icon={
13
+ <Iconify
14
+ icon="eva:close-circle-fill"
15
+ sx={{ color: 'error.main', width: 120, height: 120 }}
16
+ />
17
+ }
18
+ heading={tp('error_title')}
19
+ subtitle={tp('error_subtitle')}
20
+ buttonLabel={tp('retry_button')}
21
+ onButtonClick={() => window.history.back()}
22
+ />
23
+ );
24
+ };
25
+
26
+ export default PaydroidError;
@@ -0,0 +1,26 @@
1
+ import { Iconify } from '@components/iconify';
2
+ import React from 'react';
3
+ import useGlobal from '@hooks/useGlobal';
4
+ import PaydroidStatusCard from './PaydroidStatusCard';
5
+
6
+ const PaydroidErrorAccount: React.FC = () => {
7
+ const { t } = useGlobal();
8
+ const tp = (key: string) => t(`event.tickets.payment_success.paydroid.${key}`);
9
+
10
+ return (
11
+ <PaydroidStatusCard
12
+ icon={
13
+ <Iconify
14
+ icon="eva:alert-triangle-fill"
15
+ sx={{ color: 'warning.main', width: 120, height: 120 }}
16
+ />
17
+ }
18
+ heading={tp('error_account_title')}
19
+ subtitle={tp('error_account_subtitle')}
20
+ buttonLabel={tp('error_account_button')}
21
+ onButtonClick={() => window.open('https://app.paydroid.cz', '_blank')}
22
+ />
23
+ );
24
+ };
25
+
26
+ export default PaydroidErrorAccount;
@@ -0,0 +1,26 @@
1
+ import { Iconify } from '@components/iconify';
2
+ import React from 'react';
3
+ import useGlobal from '@hooks/useGlobal';
4
+ import PaydroidStatusCard from './PaydroidStatusCard';
5
+
6
+ const PaydroidErrorTicket: React.FC = () => {
7
+ const { t } = useGlobal();
8
+ const tp = (key: string) => t(`event.tickets.payment_success.paydroid.${key}`);
9
+
10
+ return (
11
+ <PaydroidStatusCard
12
+ icon={
13
+ <Iconify
14
+ icon="eva:close-circle-fill"
15
+ sx={{ color: 'error.main', width: 120, height: 120 }}
16
+ />
17
+ }
18
+ heading={tp('error_ticket_title')}
19
+ subtitle={tp('error_ticket_subtitle')}
20
+ buttonLabel={tp('retry_button')}
21
+ onButtonClick={() => window.history.back()}
22
+ />
23
+ );
24
+ };
25
+
26
+ export default PaydroidErrorTicket;
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { Page } from '@utils/data/page';
3
+ import PaydroidSuccess from './PaydroidSuccess';
4
+ import PaydroidSuccessTopup from './PaydroidSuccessTopup';
5
+ import PaydroidError from './PaydroidError';
6
+ import PaydroidErrorAccount from './PaydroidErrorAccount';
7
+ import PaydroidErrorTicket from './PaydroidErrorTicket';
8
+
9
+ interface Props {
10
+ page: string | null;
11
+ }
12
+
13
+ const PaydroidPage: React.FC<Props> = ({ page }) => {
14
+ if (page === Page.PAYDROID_SUCCESS) return <PaydroidSuccess />;
15
+ if (page === Page.PAYDROID_TOPUP_SUCCESS) return <PaydroidSuccessTopup />;
16
+ if (page === Page.PAYDROID_ERROR) return <PaydroidError />;
17
+ if (page === Page.PAYDROID_ERROR_ACCOUNT) return <PaydroidErrorAccount />;
18
+ if (page === Page.PAYDROID_ERROR_TICKET) return <PaydroidErrorTicket />;
19
+ return null;
20
+ };
21
+
22
+ export default PaydroidPage;
@@ -0,0 +1,91 @@
1
+ import { Image } from '@components';
2
+ import { Box, Button, Typography, useTheme } from '@mui/material';
3
+ import React from 'react';
4
+
5
+ const PAYDROID_FONT = "'InterVariable', sans-serif";
6
+
7
+ interface Props {
8
+ icon: React.ReactNode;
9
+ heading: string;
10
+ subtitle: string;
11
+ buttonLabel: string;
12
+ onButtonClick: () => void;
13
+ }
14
+
15
+ const PaydroidStatusCard: React.FC<Props> = ({
16
+ icon,
17
+ heading,
18
+ subtitle,
19
+ buttonLabel,
20
+ onButtonClick,
21
+ }) => {
22
+ const theme = useTheme();
23
+ const logoVariant = theme.palette.mode === 'dark' ? 'white' : 'black';
24
+
25
+ return (
26
+ <Box sx={{ display: 'flex', justifyContent: 'center', py: 6 }}>
27
+ <Box
28
+ sx={{
29
+ bgcolor: 'background.paper',
30
+ borderRadius: 4,
31
+ px: { xs: 4, sm: 6 },
32
+ py: { xs: 5, sm: 6 },
33
+ maxWidth: 480,
34
+ width: '100%',
35
+ textAlign: 'center',
36
+ }}
37
+ >
38
+ <Box sx={{ mb: 3 }}>{icon}</Box>
39
+
40
+ <Typography
41
+ sx={{
42
+ fontFamily: PAYDROID_FONT,
43
+ fontWeight: 900,
44
+ fontSize: { xs: 22, sm: 28 },
45
+ lineHeight: 1.15,
46
+ textTransform: 'uppercase',
47
+ letterSpacing: '-0.02em',
48
+ mb: 2,
49
+ }}
50
+ >
51
+ {heading}
52
+ </Typography>
53
+
54
+ <Typography
55
+ variant="body2"
56
+ color="text.secondary"
57
+ sx={{ maxWidth: 340, mx: 'auto', mb: 4 }}
58
+ >
59
+ {subtitle}
60
+ </Typography>
61
+
62
+ <Button
63
+ onClick={onButtonClick}
64
+ variant="outlined"
65
+ color="inherit"
66
+ sx={{
67
+ borderColor: 'divider',
68
+ color: 'text.secondary',
69
+ textTransform: 'none',
70
+ borderRadius: 2,
71
+ mb: 4,
72
+ fontSize: 13,
73
+ }}
74
+ >
75
+ {buttonLabel}
76
+ </Button>
77
+
78
+ <Box>
79
+ <Image
80
+ src={`https://eventigo.s3-central.vshosting.cloud/production/external/logo-paydroid-horizontal-${logoVariant}.svg`}
81
+ alt="Paydroid Cashless"
82
+ objectFit="contain"
83
+ sx={{ height: 32 }}
84
+ />
85
+ </Box>
86
+ </Box>
87
+ </Box>
88
+ );
89
+ };
90
+
91
+ export default PaydroidStatusCard;
@@ -0,0 +1,26 @@
1
+ import { Iconify } from '@components/iconify';
2
+ import React from 'react';
3
+ import useGlobal from '@hooks/useGlobal';
4
+ import PaydroidStatusCard from './PaydroidStatusCard';
5
+
6
+ const PaydroidSuccess: React.FC = () => {
7
+ const { t } = useGlobal();
8
+ const tp = (key: string) => t(`event.tickets.payment_success.paydroid.${key}`);
9
+
10
+ return (
11
+ <PaydroidStatusCard
12
+ icon={
13
+ <Iconify
14
+ icon="ion:ticket"
15
+ sx={{ color: '#1A237E', width: 120, height: 120, transform: 'rotate(15deg)' }}
16
+ />
17
+ }
18
+ heading={tp('success_title')}
19
+ subtitle={tp('success_subtitle')}
20
+ buttonLabel={tp('faq_button')}
21
+ onButtonClick={() => window.open('https://www.paydroid.cz/nejcastejsi-dotazy', '_blank')}
22
+ />
23
+ );
24
+ };
25
+
26
+ export default PaydroidSuccess;
@@ -0,0 +1,26 @@
1
+ import { Iconify } from '@components/iconify';
2
+ import React from 'react';
3
+ import useGlobal from '@hooks/useGlobal';
4
+ import PaydroidStatusCard from './PaydroidStatusCard';
5
+
6
+ const PaydroidSuccessTopup: React.FC = () => {
7
+ const { t } = useGlobal();
8
+ const tp = (key: string) => t(`event.tickets.payment_success.paydroid.${key}`);
9
+
10
+ return (
11
+ <PaydroidStatusCard
12
+ icon={
13
+ <Iconify
14
+ icon="eva:checkmark-circle-2-fill"
15
+ sx={{ color: 'success.main', width: 120, height: 120 }}
16
+ />
17
+ }
18
+ heading={tp('topup_success_title')}
19
+ subtitle={tp('topup_success_subtitle')}
20
+ buttonLabel={tp('faq_button')}
21
+ onButtonClick={() => window.open('https://www.paydroid.cz/nejcastejsi-dotazy', '_blank')}
22
+ />
23
+ );
24
+ };
25
+
26
+ export default PaydroidSuccessTopup;