@eventlook/sdk 1.7.2 → 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 (84) hide show
  1. package/.prettierignore +3 -0
  2. package/CLAUDE.md +33 -0
  3. package/dist/cjs/{index-D1KZ-2U1.js → index-CXsZ9BsP.js} +26476 -25947
  4. package/dist/cjs/index-CXsZ9BsP.js.map +1 -0
  5. package/dist/cjs/index-DgOx9uHQ.js +41917 -0
  6. package/dist/cjs/index-DgOx9uHQ.js.map +1 -0
  7. package/dist/cjs/index.js +3 -1
  8. package/dist/cjs/index.js.map +1 -1
  9. package/dist/cjs/{index.umd-C2KzR75H.js → index.umd-DR37hmpO.js} +2 -2
  10. package/dist/cjs/{index.umd-C2KzR75H.js.map → index.umd-DR37hmpO.js.map} +1 -1
  11. package/dist/cjs/index.umd-TbjzhsUx.js +13397 -0
  12. package/dist/cjs/index.umd-TbjzhsUx.js.map +1 -0
  13. package/dist/cjs/{mui-tel-input.es-Bjml407E.js → mui-tel-input.es-Dk9M_v4X.js} +6 -6
  14. package/dist/{esm/mui-tel-input.es-Bt2rE3An.js.map → cjs/mui-tel-input.es-Dk9M_v4X.js.map} +1 -1
  15. package/dist/esm/index-Ds-63DcA.js +41896 -0
  16. package/dist/esm/index-Ds-63DcA.js.map +1 -0
  17. package/dist/esm/{index-DRYwiFvp.js → index-z31XSEKz.js} +26751 -26240
  18. package/dist/esm/index-z31XSEKz.js.map +1 -0
  19. package/dist/esm/index.js +3 -1
  20. package/dist/esm/index.js.map +1 -1
  21. package/dist/esm/{index.umd-BXOC8cuK.js → index.umd-5znOX_Ww.js} +4 -4
  22. package/dist/esm/{index.umd-BXOC8cuK.js.map → index.umd-5znOX_Ww.js.map} +1 -1
  23. package/dist/esm/index.umd-ddggyAGa.js +13395 -0
  24. package/dist/esm/index.umd-ddggyAGa.js.map +1 -0
  25. package/dist/esm/{mui-tel-input.es-Bt2rE3An.js → mui-tel-input.es-Cb4Lpqx7.js} +21 -21
  26. package/dist/{cjs/mui-tel-input.es-Bjml407E.js.map → esm/mui-tel-input.es-Cb4Lpqx7.js.map} +1 -1
  27. package/dist/types/form/Payment.d.ts +1 -0
  28. package/dist/types/form/paydroid/PaydroidCashlessSection.d.ts +7 -0
  29. package/dist/types/form/paydroid/PaydroidError.d.ts +3 -0
  30. package/dist/types/form/paydroid/PaydroidErrorAccount.d.ts +3 -0
  31. package/dist/types/form/paydroid/PaydroidErrorTicket.d.ts +3 -0
  32. package/dist/types/form/paydroid/PaydroidPage.d.ts +6 -0
  33. package/dist/types/form/paydroid/PaydroidStatusCard.d.ts +10 -0
  34. package/dist/types/form/paydroid/PaydroidSuccess.d.ts +3 -0
  35. package/dist/types/form/paydroid/PaydroidSuccessTopup.d.ts +3 -0
  36. package/dist/types/form/payment/StripeCheckoutProvider.d.ts +36 -0
  37. package/dist/types/hooks/data/useStripeConfig.d.ts +3 -0
  38. package/dist/types/locales/cs.d.ts +34 -0
  39. package/dist/types/locales/en.d.ts +34 -0
  40. package/dist/types/locales/es.d.ts +34 -0
  41. package/dist/types/locales/pl.d.ts +34 -0
  42. package/dist/types/locales/sk.d.ts +34 -0
  43. package/dist/types/locales/uk.d.ts +34 -0
  44. package/dist/types/modules/order.d.ts +3 -0
  45. package/dist/types/modules/paydroid.d.ts +4 -0
  46. package/dist/types/utils/data/page.d.ts +7 -0
  47. package/dist/types/utils/page.d.ts +1 -0
  48. package/dist/types/utils/paydroid.d.ts +6 -0
  49. package/dist/types/utils/types/global.type.d.ts +1 -0
  50. package/dist/types/utils/types/order.type.d.ts +4 -0
  51. package/dist/types/utils/types/paydroid.d.ts +23 -0
  52. package/dist/types/utils/types/payment-method.type.d.ts +1 -0
  53. package/package.json +6 -2
  54. package/src/form/Payment.tsx +42 -3
  55. package/src/form/PaymentOverviewBox.tsx +20 -7
  56. package/src/form/PaymentSuccess.tsx +6 -2
  57. package/src/form/TicketForm.tsx +269 -168
  58. package/src/form/paydroid/PaydroidCashlessSection.tsx +311 -0
  59. package/src/form/paydroid/PaydroidError.tsx +26 -0
  60. package/src/form/paydroid/PaydroidErrorAccount.tsx +26 -0
  61. package/src/form/paydroid/PaydroidErrorTicket.tsx +26 -0
  62. package/src/form/paydroid/PaydroidPage.tsx +22 -0
  63. package/src/form/paydroid/PaydroidStatusCard.tsx +91 -0
  64. package/src/form/paydroid/PaydroidSuccess.tsx +26 -0
  65. package/src/form/paydroid/PaydroidSuccessTopup.tsx +26 -0
  66. package/src/form/payment/StripeCheckoutProvider.tsx +154 -0
  67. package/src/hooks/data/useStripeConfig.ts +14 -0
  68. package/src/locales/cs.tsx +40 -0
  69. package/src/locales/en.tsx +38 -0
  70. package/src/locales/es.tsx +39 -0
  71. package/src/locales/pl.tsx +38 -0
  72. package/src/locales/sk.tsx +40 -0
  73. package/src/locales/uk.tsx +38 -0
  74. package/src/modules/order.ts +3 -0
  75. package/src/modules/paydroid.ts +33 -0
  76. package/src/utils/data/page.ts +7 -0
  77. package/src/utils/page.ts +4 -0
  78. package/src/utils/paydroid.ts +35 -0
  79. package/src/utils/types/global.type.ts +1 -0
  80. package/src/utils/types/order.type.ts +7 -0
  81. package/src/utils/types/paydroid.ts +26 -0
  82. package/src/utils/types/payment-method.type.ts +1 -0
  83. package/dist/cjs/index-D1KZ-2U1.js.map +0 -1
  84. package/dist/esm/index-DRYwiFvp.js.map +0 -1
@@ -0,0 +1,154 @@
1
+ 'use client';
2
+
3
+ import React, { MutableRefObject, useEffect, useMemo } from 'react';
4
+ import { useTheme } from '@mui/material';
5
+ import { loadStripe, Appearance } from '@stripe/stripe-js';
6
+ import { Elements, useElements, useStripe } from '@stripe/react-stripe-js';
7
+
8
+ /**
9
+ * Imperative handle the order form uses to drive the inline Stripe payment from
10
+ * its own submit handler (which lives outside the <Elements> tree).
11
+ */
12
+ export interface StripeCheckoutApi {
13
+ ready: boolean;
14
+ /** Validate + collect the card fields. Returns an error message, or null. */
15
+ submit: () => Promise<string | null>;
16
+ /** Confirm the server-created PaymentIntent. */
17
+ confirm: (clientSecret: string, returnUrl: string) => Promise<{ ok: boolean; error?: string }>;
18
+ }
19
+
20
+ // Locales the Stripe Elements UI supports; anything else falls back to auto.
21
+ const STRIPE_LOCALES = ['cs', 'de', 'en', 'es', 'fr', 'pl', 'sk', 'it'];
22
+
23
+ // Bridges the Stripe/Elements instances (only available inside <Elements>) up to
24
+ // a ref the form's submit handler can call.
25
+ const Bridge: React.FC<{ apiRef: MutableRefObject<StripeCheckoutApi | null> }> = ({ apiRef }) => {
26
+ const stripe = useStripe();
27
+ const elements = useElements();
28
+
29
+ useEffect(() => {
30
+ apiRef.current = {
31
+ ready: !!stripe && !!elements,
32
+ submit: async () => {
33
+ if (!elements) return 'Stripe not ready';
34
+ const { error } = await elements.submit();
35
+ return error?.message ?? null;
36
+ },
37
+ confirm: async (clientSecret, returnUrl) => {
38
+ if (!stripe || !elements) return { ok: false, error: 'Stripe not ready' };
39
+ // Resolve in-page when possible (incl. the 3-D Secure modal); Stripe
40
+ // only does a full redirect when the method strictly requires it.
41
+ const confirmParams = { return_url: returnUrl };
42
+
43
+ // Free (0-amount) orders confirm a SetupIntent (seti_…) — card
44
+ // verification for bot protection, no charge; paid orders confirm a
45
+ // PaymentIntent (pi_…).
46
+ if (clientSecret.startsWith('seti_')) {
47
+ const { error, setupIntent } = await stripe.confirmSetup({
48
+ elements,
49
+ clientSecret,
50
+ confirmParams,
51
+ redirect: 'if_required',
52
+ });
53
+ if (error) return { ok: false, error: error.message };
54
+ return { ok: setupIntent?.status === 'succeeded' };
55
+ }
56
+
57
+ const { error, paymentIntent } = await stripe.confirmPayment({
58
+ elements,
59
+ clientSecret,
60
+ confirmParams,
61
+ redirect: 'if_required',
62
+ });
63
+ if (error) return { ok: false, error: error.message };
64
+ const ok =
65
+ !!paymentIntent &&
66
+ (paymentIntent.status === 'succeeded' || paymentIntent.status === 'processing');
67
+ return { ok };
68
+ },
69
+ };
70
+ return () => {
71
+ apiRef.current = null;
72
+ };
73
+ }, [stripe, elements, apiRef]);
74
+
75
+ return null;
76
+ };
77
+
78
+ interface Props {
79
+ /** Mount Elements only when a Stripe method is offered and the key is loaded. */
80
+ active: boolean;
81
+ publishableKey: string | null;
82
+ /** 'payment' for paid orders, 'setup' for free (0-amount) card verification. */
83
+ mode: 'payment' | 'setup';
84
+ /** Charge amount in minor units (used by Elements; the server intent is authoritative). */
85
+ amount: number;
86
+ currency: string;
87
+ locale: string;
88
+ apiRef: MutableRefObject<StripeCheckoutApi | null>;
89
+ children: React.ReactNode;
90
+ }
91
+
92
+ /**
93
+ * Wraps the order form in a deferred-mode <Elements> provider so the Payment
94
+ * Element can be shown inline (expanded under the selected method) before the
95
+ * order — and its PaymentIntent — exists. When no Stripe method is on offer it
96
+ * renders children untouched and loads nothing.
97
+ */
98
+ const StripeCheckoutProvider: React.FC<Props> = ({
99
+ active,
100
+ publishableKey,
101
+ mode,
102
+ amount,
103
+ currency,
104
+ locale,
105
+ apiRef,
106
+ children,
107
+ }) => {
108
+ const theme = useTheme();
109
+ const stripePromise = useMemo(
110
+ () => (active && publishableKey ? loadStripe(publishableKey) : null),
111
+ [active, publishableKey]
112
+ );
113
+
114
+ if (!active || !stripePromise) return <>{children}</>;
115
+
116
+ const stripeLocale = STRIPE_LOCALES.includes(locale) ? locale : 'auto';
117
+
118
+ // Drive the Stripe Element off the host MUI theme so it matches light/dark and
119
+ // the brand colors instead of Stripe's default white card.
120
+ const appearance: Appearance = {
121
+ theme: theme.palette.mode === 'dark' ? 'night' : 'stripe',
122
+ variables: {
123
+ colorPrimary: theme.palette.primary.main,
124
+ colorBackground: theme.palette.background.paper,
125
+ colorText: theme.palette.text.primary,
126
+ colorTextSecondary: theme.palette.text.secondary,
127
+ colorDanger: theme.palette.error.main,
128
+ fontFamily: String(theme.typography.fontFamily ?? 'inherit'),
129
+ borderRadius: `${Number(theme.shape.borderRadius) || 8}px`,
130
+ },
131
+ };
132
+
133
+ return (
134
+ <Elements
135
+ stripe={stripePromise}
136
+ options={{
137
+ // Free orders verify the card (SetupIntent, no charge); paid orders
138
+ // charge it (PaymentIntent, needs an amount).
139
+ ...(mode === 'setup'
140
+ ? { mode: 'setup' as const }
141
+ : { mode: 'payment' as const, amount: Math.max(1, Math.round(amount)) }),
142
+ currency: currency.toLowerCase(),
143
+ paymentMethodTypes: ['card'],
144
+ locale: stripeLocale as 'auto',
145
+ appearance,
146
+ }}
147
+ >
148
+ <Bridge apiRef={apiRef} />
149
+ {children}
150
+ </Elements>
151
+ );
152
+ };
153
+
154
+ export default StripeCheckoutProvider;
@@ -0,0 +1,14 @@
1
+ import useSWR from 'swr';
2
+ import { getStripeConfig } from '@modules/order';
3
+
4
+ // Fetches the public Stripe publishable key, only when a Stripe method is on
5
+ // offer (pass enabled=false to skip the request entirely). Cached for the
6
+ // session — the key never changes.
7
+ export default function useStripeConfig(enabled: boolean) {
8
+ const { data } = useSWR(enabled ? ['stripe-config'] : null, () => getStripeConfig(), {
9
+ revalidateOnFocus: false,
10
+ revalidateIfStale: false,
11
+ });
12
+
13
+ return { publishableKey: data?.publishableKey ?? null };
14
+ }
@@ -44,6 +44,9 @@ const cs = {
44
44
  total: 'Celkem',
45
45
  with_fee: 'vč. servisního poplatku',
46
46
  service_fee: 'Servisní poplatek',
47
+ payment_processing_fee: 'Poplatek za platbu kartou',
48
+ card_payment_title: 'Platba kartou',
49
+ card_payment_error: 'Platbu se nepodařilo dokončit. Zkuste to prosím znovu.',
47
50
  shipping_fee: 'Doprava',
48
51
  ticket_insurance: 'Pojištění vstupenek',
49
52
  price_including_service_fee: 'Cena zahrnuje servisní poplatek v hodnotě {{fee}}.',
@@ -64,6 +67,7 @@ const cs = {
64
67
  'Tato kategorie je doplňková — zadejte číslo již zakoupené vstupenky.',
65
68
  primary_ticket_dialog_title: 'Zadejte číslo primární vstupenky',
66
69
  primary_ticket_dialog_input_label: 'Číslo primární vstupenky',
70
+ amount: 'Částka',
67
71
  },
68
72
  validation: {
69
73
  required: 'Toto pole je povinné.',
@@ -185,6 +189,42 @@ const cs = {
185
189
  button: 'Stáhnout vstupenku',
186
190
  products: 'Vaše produkty',
187
191
  },
192
+ paydroid: {
193
+ label: 'Paydroid Cashless',
194
+ heading: 'Vyhněte se frontám!',
195
+ heading_cta: 'Přednabijte si',
196
+ subtitle:
197
+ 'Na akci lze platit pouze bezhotovostně pomocí systému Paydroid Cashless. Přednabijte si částku teď a vyhněte se frontám!',
198
+ amount_label: 'Jakou částku chcete přednabít?',
199
+ amount_placeholder: 'Zadejte částku',
200
+ promo: 'Přednabijte si na akci částku vyšší než 1000 Kč a získejte pivo zdarma!',
201
+ terms_prefix: 'Souhlasím s',
202
+ terms_conditions: 'Obchodními podmínkami',
203
+ terms_middle: 'Paydroid Cashless a se',
204
+ terms_privacy: 'Zásadami zpracování osobních údajů',
205
+ terms: 'Souhlas VOP a GDPR Paydroid Cashless',
206
+ skip: 'chci pouze vstupenku v aplikaci',
207
+ submit: 'přednabít',
208
+ success_title: 'Vstupenku jsme přidali k vašemu účtu',
209
+ success_subtitle:
210
+ 'Teď už se stačí jen přihlásit do aplikace Paydroid Cashless. A pokud se budete chtít vyhnout frontám, přednabijte si v aplikaci!',
211
+ topup_success_title: 'Děkujeme za přednabitî!',
212
+ topup_success_subtitle:
213
+ 'Právě jsme připsali kredit na Váš účet Paydroid Cashless, nyní už se stačí pouze přihlásit v aplikaci.',
214
+ error_title: 'Přednabití se nezdařilo',
215
+ error_subtitle:
216
+ 'Nebyli jste nijak zpoplatněni, v případě jakýchkoliv problémů nás prosím kontaktujte.',
217
+ error_account_title: 'Nepodařilo se vytvořit účet',
218
+ error_account_subtitle:
219
+ 'Pravděpodobně jste zadali údaje, které se liší se záznamem v naší databázi.',
220
+ error_account_button: 'přihlásit se do aplikace',
221
+ error_ticket_title: 'Přidání vstupenky se nezdařilo',
222
+ error_ticket_subtitle:
223
+ 'Omlouváme se, vyzkoušejte to prosím později. V případě jakýchkoliv problémů nás prosím kontaktujte.',
224
+ faq_button: 'nejčastější dotazy',
225
+ retry_button: 'vyzkoušet znovu',
226
+ missing_api_key: 'Paydroid API klíč chybí',
227
+ },
188
228
  unpaid: 'Platba neproběhla',
189
229
  unpaid_description: 'Zkuste to prosím znovu kliknutím na tlačítko Zaplatit.',
190
230
  },
@@ -44,6 +44,9 @@ const en = {
44
44
  total: 'Total',
45
45
  with_fee: 'incl. service fee',
46
46
  service_fee: 'Service fee',
47
+ payment_processing_fee: 'Card processing fee',
48
+ card_payment_title: 'Card payment',
49
+ card_payment_error: 'The payment could not be completed. Please try again.',
47
50
  shipping_fee: 'Shipping',
48
51
  ticket_insurance: 'Ticket insurance',
49
52
  price_including_service_fee: 'The price includes a service fee of {{fee}}.',
@@ -64,6 +67,7 @@ const en = {
64
67
  'This is an addon category — enter the number of an already-purchased ticket.',
65
68
  primary_ticket_dialog_title: 'Enter primary ticket number',
66
69
  primary_ticket_dialog_input_label: 'Primary ticket number',
70
+ amount: 'Amount',
67
71
  },
68
72
  validation: {
69
73
  required: 'This field is required.',
@@ -185,6 +189,40 @@ const en = {
185
189
  button: 'Download ticket',
186
190
  products: 'Your products',
187
191
  },
192
+ paydroid: {
193
+ label: 'Paydroid Cashless',
194
+ heading: 'Skip the queues!',
195
+ heading_cta: 'Top up now',
196
+ subtitle:
197
+ 'The event accepts only cashless payments via Paydroid Cashless. Top up your balance now and skip the queues!',
198
+ amount_label: 'How much would you like to top up?',
199
+ amount_placeholder: 'Enter amount',
200
+ promo: 'Top up more than 1000 CZK and get a free beer!',
201
+ terms_prefix: 'I agree to the',
202
+ terms_conditions: 'Terms and Conditions',
203
+ terms_middle: 'of Paydroid Cashless and the',
204
+ terms_privacy: 'Privacy Policy',
205
+ terms: 'I agree to the T&C and GDPR of Paydroid Cashless',
206
+ skip: 'I just want the ticket in the app',
207
+ submit: 'top up',
208
+ success_title: 'We added the ticket to your account',
209
+ success_subtitle:
210
+ 'Just log in to the Paydroid Cashless app. And if you want to skip the queues, top up in the app!',
211
+ topup_success_title: 'Thank you for topping up!',
212
+ topup_success_subtitle:
213
+ 'We have credited your Paydroid Cashless account. Just log in to the app.',
214
+ error_title: 'Top-up failed',
215
+ error_subtitle: 'You have not been charged. Please contact us if you have any issues.',
216
+ error_account_title: 'Failed to create account',
217
+ error_account_subtitle: 'You may have entered details that differ from our records.',
218
+ error_account_button: 'log in to the app',
219
+ error_ticket_title: 'Failed to add ticket',
220
+ error_ticket_subtitle:
221
+ 'We are sorry, please try again later. Contact us if the issue persists.',
222
+ faq_button: 'frequently asked questions',
223
+ retry_button: 'try again',
224
+ missing_api_key: 'Paydroid API key is missing',
225
+ },
188
226
  unpaid: 'The payment was not successful.',
189
227
  unpaid_description: 'Please try again by clicking the Pay button.',
190
228
  },
@@ -44,6 +44,9 @@ const es = {
44
44
  total: 'Total',
45
45
  with_fee: 'incl. tarifa de servicio',
46
46
  service_fee: 'Tarifa de servicio',
47
+ payment_processing_fee: 'Comisión por pago con tarjeta',
48
+ card_payment_title: 'Pago con tarjeta',
49
+ card_payment_error: 'No se pudo completar el pago. Inténtalo de nuevo.',
47
50
  shipping_fee: 'Envío',
48
51
  ticket_insurance: 'Seguro de entrada',
49
52
  price_including_service_fee: 'El precio incluye una tarifa de servicio de {{fee}}.',
@@ -64,6 +67,7 @@ const es = {
64
67
  'Esta es una categoría complementaria — introduzca el número de una entrada ya comprada.',
65
68
  primary_ticket_dialog_title: 'Introduzca el número de la entrada principal',
66
69
  primary_ticket_dialog_input_label: 'Número de la entrada principal',
70
+ amount: 'Cantidad',
67
71
  },
68
72
  validation: {
69
73
  required: 'Este campo es obligatorio.',
@@ -185,6 +189,41 @@ const es = {
185
189
  button: 'Descargar entrada',
186
190
  products: 'Tus productos',
187
191
  },
192
+ paydroid: {
193
+ label: 'Paydroid Cashless',
194
+ heading: '¡Evita las colas!',
195
+ heading_cta: 'Recarga ahora',
196
+ subtitle:
197
+ 'El evento solo acepta pagos sin efectivo a través de Paydroid Cashless. ¡Recarga tu saldo ahora y evita las colas!',
198
+ amount_label: '¿Cuánto deseas recargar?',
199
+ amount_placeholder: 'Ingresa el monto',
200
+ promo: '¡Recarga más de 1000 CZK y obtén una cerveza gratis!',
201
+ terms_prefix: 'Acepto los',
202
+ terms_conditions: 'Términos y condiciones',
203
+ terms_middle: 'de Paydroid Cashless y la',
204
+ terms_privacy: 'Política de privacidad',
205
+ terms: 'Acepto los T&C y GDPR de Paydroid Cashless',
206
+ skip: 'solo quiero la entrada en la app',
207
+ submit: 'recargar',
208
+ success_title: 'Añadimos la entrada a tu cuenta',
209
+ success_subtitle:
210
+ 'Solo inicia sesión en la app Paydroid Cashless. ¡Y si quieres saltarte las colas, recarga en la app!',
211
+ topup_success_title: '¡Gracias por recargar!',
212
+ topup_success_subtitle:
213
+ 'Hemos acreditado tu cuenta Paydroid Cashless. Solo inicia sesión en la app.',
214
+ error_title: 'La recarga falló',
215
+ error_subtitle: 'No se te ha cobrado nada. Contáctanos si tienes algún problema.',
216
+ error_account_title: 'No se pudo crear la cuenta',
217
+ error_account_subtitle:
218
+ 'Es posible que hayas introducido datos diferentes a los de nuestros registros.',
219
+ error_account_button: 'iniciar sesión en la app',
220
+ error_ticket_title: 'No se pudo añadir la entrada',
221
+ error_ticket_subtitle:
222
+ 'Lo sentimos, inténtalo más tarde. Contáctanos si el problema persiste.',
223
+ faq_button: 'preguntas frecuentes',
224
+ retry_button: 'intentar de nuevo',
225
+ missing_api_key: 'Falta la clave API de Paydroid',
226
+ },
188
227
  unpaid: 'El pago no se realizó.',
189
228
  unpaid_description: 'Por favor, inténtelo de nuevo haciendo clic en el botón Pagar.',
190
229
  },
@@ -44,6 +44,9 @@ const pl = {
44
44
  total: 'Razem',
45
45
  with_fee: 'z opłatą serwisową',
46
46
  service_fee: 'Opłata serwisowa',
47
+ payment_processing_fee: 'Opłata za obsługę karty',
48
+ card_payment_title: 'Płatność kartą',
49
+ card_payment_error: 'Nie udało się zrealizować płatności. Spróbuj ponownie.',
47
50
  shipping_fee: 'Wysyłka',
48
51
  ticket_insurance: 'Ubezpieczenie biletu',
49
52
  price_including_service_fee: 'Cena zawiera opłatę serwisową {{fee}}.',
@@ -64,6 +67,7 @@ const pl = {
64
67
  'To jest kategoria dodatkowa — wprowadź numer już zakupionego biletu.',
65
68
  primary_ticket_dialog_title: 'Wprowadź numer biletu głównego',
66
69
  primary_ticket_dialog_input_label: 'Numer biletu głównego',
70
+ amount: 'Kwota',
67
71
  },
68
72
  validation: {
69
73
  required: 'To pole jest wymagane.',
@@ -184,6 +188,40 @@ const pl = {
184
188
  button: 'Pobierz bilet',
185
189
  products: 'Twoje produkty',
186
190
  },
191
+ paydroid: {
192
+ label: 'Paydroid Cashless',
193
+ heading: 'Unikaj kolejek!',
194
+ heading_cta: 'Doładuj teraz',
195
+ subtitle:
196
+ 'Na imprezie płatności są wyłącznie bezgotówkowe za pomocą systemu Paydroid Cashless. Doładuj konto teraz i unikaj kolejek!',
197
+ amount_label: 'Jaką kwotę chcesz doładować?',
198
+ amount_placeholder: 'Wpisz kwotę',
199
+ promo: 'Doładuj kwotę wyższą niż 1000 CZK i otrzymaj piwo gratis!',
200
+ terms_prefix: 'Zgadzam się z',
201
+ terms_conditions: 'Regulaminem',
202
+ terms_middle: 'Paydroid Cashless oraz z',
203
+ terms_privacy: 'Zasadami przetwarzania danych osobowych',
204
+ terms: 'Zgoda na regulamin i RODO Paydroid Cashless',
205
+ skip: 'chcę tylko bilet w aplikacji',
206
+ submit: 'doładuj',
207
+ success_title: 'Dodaliśmy bilet do Twojego konta',
208
+ success_subtitle:
209
+ 'Zaloguj się do aplikacji Paydroid Cashless. Jeśli chcesz uniknąć kolejek, doładuj konto w aplikacji!',
210
+ topup_success_title: 'Dziękujemy za doładowanie!',
211
+ topup_success_subtitle:
212
+ 'Właśnie dodaliśmy środki na Twoje konto Paydroid Cashless. Zaloguj się do aplikacji.',
213
+ error_title: 'Doładowanie nie powiodło się',
214
+ error_subtitle: 'Nie zostałeś obciążony. Skontaktuj się z nami w razie problemów.',
215
+ error_account_title: 'Nie udało się utworzyć konta',
216
+ error_account_subtitle: 'Prawdopodobnie podałeś dane różniące się od naszych zapisów.',
217
+ error_account_button: 'zaloguj się do aplikacji',
218
+ error_ticket_title: 'Nie udało się dodać biletu',
219
+ error_ticket_subtitle:
220
+ 'Przepraszamy, spróbuj ponownie później. Skontaktuj się z nami jeśli problem się powtórzy.',
221
+ faq_button: 'najczęstsze pytania',
222
+ retry_button: 'spróbuj ponownie',
223
+ missing_api_key: 'Brak klucza API Paydroid',
224
+ },
187
225
  unpaid: 'Płatność nie powiodła się.',
188
226
  unpaid_description: 'Spróbuj ponownie, klikając przycisk Zapłać.',
189
227
  },
@@ -44,6 +44,9 @@ const sk = {
44
44
  total: 'Spolu',
45
45
  with_fee: 'vrátane servisného poplatku',
46
46
  service_fee: 'Servisný poplatok',
47
+ payment_processing_fee: 'Poplatok za platbu kartou',
48
+ card_payment_title: 'Platba kartou',
49
+ card_payment_error: 'Platbu sa nepodarilo dokončiť. Skúste to znova.',
47
50
  shipping_fee: 'Doručenie',
48
51
  ticket_insurance: 'Poistenie vstupenky',
49
52
  price_including_service_fee: 'Cena zahŕňa servisný poplatok {{fee}}.',
@@ -64,6 +67,7 @@ const sk = {
64
67
  'Táto kategória je doplnková — zadajte číslo už zakúpenej vstupenky.',
65
68
  primary_ticket_dialog_title: 'Zadajte číslo primárnej vstupenky',
66
69
  primary_ticket_dialog_input_label: 'Číslo primárnej vstupenky',
70
+ amount: 'Čiastka',
67
71
  },
68
72
  validation: {
69
73
  required: 'Toto pole je povinné.',
@@ -185,6 +189,42 @@ const sk = {
185
189
  button: 'Stiahnuť vstupenku',
186
190
  products: 'Vaše produkty',
187
191
  },
192
+ paydroid: {
193
+ label: 'Paydroid Cashless',
194
+ heading: 'Vyhnite sa radom!',
195
+ heading_cta: 'Prednabite si',
196
+ subtitle:
197
+ 'Na akcii sa platí len bezhotovostne pomocou systému Paydroid Cashless. Prednabite si čiastku teraz a vyhnite sa radom!',
198
+ amount_label: 'Akú čiastku chcete prednabiť?',
199
+ amount_placeholder: 'Zadajte čiastku',
200
+ promo: 'Prednabite si na akciu čiastku vyššiu ako 1000 Kč a získajte pivo zadarmo!',
201
+ terms_prefix: 'Súhlasím s',
202
+ terms_conditions: 'Obchodnými podmienkami',
203
+ terms_middle: 'Paydroid Cashless a so',
204
+ terms_privacy: 'Zásadami spracovania osobných údajov',
205
+ terms: 'Súhlas VOP a GDPR Paydroid Cashless',
206
+ skip: 'chcem len vstupenku v aplikácii',
207
+ submit: 'prednabiť',
208
+ success_title: 'Vstupenku sme pridali k vášmu účtu',
209
+ success_subtitle:
210
+ 'Stačí sa prihlásiť do aplikácie Paydroid Cashless. A ak sa chcete vyhnúť radom, prednabite si v aplikácii!',
211
+ topup_success_title: 'Ďakujeme za prednabitie!',
212
+ topup_success_subtitle:
213
+ 'Práve sme pripísali kredit na Váš účet Paydroid Cashless, stačí sa prihlásiť v aplikácii.',
214
+ error_title: 'Prednabitie sa nepodarilo',
215
+ error_subtitle:
216
+ 'Neboli ste nijako spoplatnení, v prípade akýchkoľvek problémov nás prosím kontaktujte.',
217
+ error_account_title: 'Nepodarilo sa vytvoriť účet',
218
+ error_account_subtitle:
219
+ 'Pravdepodobne ste zadali údaje, ktoré sa líšia od záznamu v našej databáze.',
220
+ error_account_button: 'prihlásiť sa do aplikácie',
221
+ error_ticket_title: 'Pridanie vstupenky sa nepodarilo',
222
+ error_ticket_subtitle:
223
+ 'Ospravedlňujeme sa, skúste to neskôr. V prípade problémov nás prosím kontaktujte.',
224
+ faq_button: 'najčastejšie otázky',
225
+ retry_button: 'skúsiť znova',
226
+ missing_api_key: 'Paydroid API kľúč chýba',
227
+ },
188
228
  unpaid: 'Platba neprebehla.',
189
229
  unpaid_description: 'Skúste to prosím znova kliknutím na tlačidlo Zaplatiť.',
190
230
  },
@@ -44,6 +44,9 @@ const uk = {
44
44
  total: 'Всього',
45
45
  with_fee: 'вкл. сервісний збір',
46
46
  service_fee: 'Сервісний збір',
47
+ payment_processing_fee: 'Комісія за оплату карткою',
48
+ card_payment_title: 'Оплата карткою',
49
+ card_payment_error: 'Не вдалося завершити оплату. Спробуйте ще раз.',
47
50
  shipping_fee: 'Доставка',
48
51
  ticket_insurance: 'Страхування квитка',
49
52
  price_including_service_fee: 'Ціна включає сервісний збір {{fee}}.',
@@ -63,6 +66,7 @@ const uk = {
63
66
  primary_ticket_number_hint: 'Це додаткова категорія — введіть номер уже придбаного квитка.',
64
67
  primary_ticket_dialog_title: 'Введіть номер основного квитка',
65
68
  primary_ticket_dialog_input_label: 'Номер основного квитка',
69
+ amount: 'Сума',
66
70
  },
67
71
  validation: {
68
72
  required: "Це поле обов'язкове.",
@@ -184,6 +188,40 @@ const uk = {
184
188
  button: 'Завантажити квиток',
185
189
  products: 'Ваші продукти',
186
190
  },
191
+ paydroid: {
192
+ label: 'Paydroid Cashless',
193
+ heading: 'Уникайте черг!',
194
+ heading_cta: 'Поповніть баланс',
195
+ subtitle:
196
+ 'На заході оплата виключно безготівкова за допомогою системи Paydroid Cashless. Поповніть баланс зараз і уникайте черг!',
197
+ amount_label: 'Яку суму ви хочете поповнити?',
198
+ amount_placeholder: 'Введіть суму',
199
+ promo: 'Поповніть суму понад 1000 CZK та отримайте пиво безкоштовно!',
200
+ terms_prefix: 'Я погоджуюсь з',
201
+ terms_conditions: 'Умовами використання',
202
+ terms_middle: 'Paydroid Cashless та із',
203
+ terms_privacy: 'Правилами обробки персональних даних',
204
+ terms: 'Згода з умовами та GDPR Paydroid Cashless',
205
+ skip: 'лише квиток у додатку',
206
+ submit: 'поповнити',
207
+ success_title: 'Ми додали квиток до вашого облікового запису',
208
+ success_subtitle:
209
+ 'Просто увійдіть у додаток Paydroid Cashless. Якщо хочете уникнути черг — поповніть баланс у додатку!',
210
+ topup_success_title: 'Дякуємо за поповнення!',
211
+ topup_success_subtitle:
212
+ 'Ми щойно зарахували кошти на ваш рахунок Paydroid Cashless. Увійдіть у додаток.',
213
+ error_title: 'Поповнення не вдалося',
214
+ error_subtitle: 'З вас нічого не стягнуто. Зверніться до нас, якщо виникнуть проблеми.',
215
+ error_account_title: 'Не вдалося створити обліковий запис',
216
+ error_account_subtitle: 'Можливо, ви ввели дані, що відрізняються від наших записів.',
217
+ error_account_button: 'увійти в додаток',
218
+ error_ticket_title: 'Не вдалося додати квиток',
219
+ error_ticket_subtitle:
220
+ 'Вибачте, спробуйте пізніше. Зверніться до нас, якщо проблема повториться.',
221
+ faq_button: 'часті запитання',
222
+ retry_button: 'спробувати знову',
223
+ missing_api_key: 'API ключ Paydroid відсутній',
224
+ },
187
225
  unpaid: 'Платіж не здійснено.',
188
226
  unpaid_description: 'Спробуйте ще раз, натиснувши кнопку Оплатити.',
189
227
  },
@@ -18,3 +18,6 @@ export const getAllowedPaymentMethods = (currency: Currencies, eventId?: number)
18
18
 
19
19
  export const postOrderPaid = (data: IOrderPaidData): Promise<IResponse<IOrderPaid>> =>
20
20
  api.post('/v1/orders/paid', data).then((res) => res.data.data);
21
+
22
+ export const getStripeConfig = (): Promise<{ publishableKey: string | null }> =>
23
+ api.get('/v1/orders/stripe/config').then((res) => res.data.data.data);
@@ -0,0 +1,33 @@
1
+ import api from '@utils/axios';
2
+ import { IResponse } from '@utils/types/global.type';
3
+ import {
4
+ IPaydroidCreateAccountData,
5
+ IPaydroidTopupAccountData,
6
+ IPaydroidTopupAccountResponse,
7
+ } from '@utils/types/paydroid';
8
+
9
+ const domain = 'https://api.paydroid.cz';
10
+
11
+ export const postPaydroidCreateAccount = (
12
+ apiKey: string,
13
+ data: IPaydroidCreateAccountData
14
+ ): Promise<IResponse<null>> =>
15
+ api
16
+ .post(`${domain}/v1/requests/create-account`, data, {
17
+ headers: {
18
+ 'X-Api-Key': apiKey,
19
+ },
20
+ })
21
+ .then((res) => res.data.data);
22
+
23
+ export const postPaydroidTopupAccount = (
24
+ apiKey: string,
25
+ data: IPaydroidTopupAccountData
26
+ ): Promise<IResponse<IPaydroidTopupAccountResponse>> =>
27
+ api
28
+ .post(`${domain}/v1/requests/topup-account`, data, {
29
+ headers: {
30
+ 'X-Api-Key': apiKey,
31
+ },
32
+ })
33
+ .then((res) => res.data);
@@ -0,0 +1,7 @@
1
+ export enum Page {
2
+ PAYDROID_SUCCESS = 'paydroid-success',
3
+ PAYDROID_TOPUP_SUCCESS = 'paydroid-topup-success',
4
+ PAYDROID_ERROR = 'paydroid-error',
5
+ PAYDROID_ERROR_ACCOUNT = 'paydroid-error-account',
6
+ PAYDROID_ERROR_TICKET = 'paydroid-error-ticket',
7
+ }
@@ -0,0 +1,4 @@
1
+ import { Page } from '@utils/data/page';
2
+
3
+ export const isPaydroidPage = (page: string | null): boolean =>
4
+ Object.values(Page).includes(page as Page);
@@ -0,0 +1,35 @@
1
+ import { Page } from '@utils/data/page';
2
+ import { IOrderPaid } from '@utils/types/order.type';
3
+ import { IPaydroidCreateAccountData, IPaydroidTopupAccountData } from '@utils/types/paydroid';
4
+ import dayjs from 'dayjs';
5
+
6
+ export const getRedirectUrl = (page: Page): string => {
7
+ const base = window.location.origin + window.location.pathname;
8
+ return `${base}?page=${page}`;
9
+ };
10
+
11
+ export const transformToCreateAccountData = (data: IOrderPaid): IPaydroidCreateAccountData => ({
12
+ first_name: data.customer.firstName,
13
+ last_name: data.customer.lastName,
14
+ email: data.customer.email,
15
+ phone_number: data.customer.phone,
16
+ event_id: data.paydroidEventId || '',
17
+ tickets: data.tickets.map((ticket) => ({
18
+ number: ticket.number.toString(),
19
+ category: ticket.releaseCategoryName,
20
+ })),
21
+ ...(data.customer.birthdate
22
+ ? { date_of_birth: dayjs(data.customer.birthdate).format('YYYY-MM-DD') }
23
+ : {}),
24
+ });
25
+
26
+ export const transformToTopupAccountData = (
27
+ amount: string,
28
+ data: IOrderPaid
29
+ ): IPaydroidTopupAccountData => ({
30
+ email: data.customer.email,
31
+ event_id: data.paydroidEventId || '',
32
+ amount: Number(amount),
33
+ success_url: getRedirectUrl(Page.PAYDROID_TOPUP_SUCCESS),
34
+ failure_url: getRedirectUrl(Page.PAYDROID_ERROR),
35
+ });
@@ -35,6 +35,7 @@ export interface IGlobalContextOptions {
35
35
  termsAndConditionsCompanies?: string[];
36
36
  autoscrollAfterViewChange?: boolean;
37
37
  hasGopayId?: boolean;
38
+ paydroidApiKey?: string;
38
39
  }
39
40
 
40
41
  export interface IBase {
@@ -23,6 +23,11 @@ export interface IOrder extends IBase {
23
23
 
24
24
  export interface IOrderCreate {
25
25
  gwUrl: string;
26
+ // Inline Stripe (Payment Element): set when the selected method confirms
27
+ // in-page instead of redirecting; the publishable key is returned alongside
28
+ // so the SDK can mount Elements without host-app configuration.
29
+ clientSecret: string | null;
30
+ publishableKey: string | null;
26
31
  tickets: ICreateTicket[];
27
32
  orderEntity: IOrder;
28
33
  customer: ICustomer;
@@ -40,9 +45,11 @@ export interface IOrderPaid {
40
45
  orderNumber: number;
41
46
  tickets: IPaidTicket[];
42
47
  products: IPaidProduct[];
48
+ customer: ICustomer;
43
49
  extraFee: number;
44
50
  currency: Currencies;
45
51
  promoCodes: IPromoCode[] | null;
52
+ paydroidEventId: string | null;
46
53
  }
47
54
 
48
55
  export interface IAllowedPaymentMethod {