@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.
Files changed (91) hide show
  1. package/.claude/settings.local.json +6 -10
  2. package/.env.example +1 -0
  3. package/README.md +18 -16
  4. package/dist/cjs/{index-DvUR1fp8.js → index-CUIxdwQn.js} +3340 -577
  5. package/dist/cjs/index-CUIxdwQn.js.map +1 -0
  6. package/dist/cjs/index-D5rQiSGP.js +38574 -0
  7. package/dist/cjs/index-D5rQiSGP.js.map +1 -0
  8. package/dist/cjs/index.js +2 -2
  9. package/dist/cjs/{index.umd-6SU6nkkJ.js → index.umd-BoFEW91M.js} +9 -19
  10. package/dist/cjs/index.umd-BoFEW91M.js.map +1 -0
  11. package/dist/cjs/index.umd-BzSM62qM.js +13397 -0
  12. package/dist/cjs/index.umd-BzSM62qM.js.map +1 -0
  13. package/dist/esm/index-Cm7V8Zl3.js +38571 -0
  14. package/dist/esm/index-Cm7V8Zl3.js.map +1 -0
  15. package/dist/esm/{index-BlTqx0jm.js → index-fvLIN6eP.js} +3327 -563
  16. package/dist/esm/index-fvLIN6eP.js.map +1 -0
  17. package/dist/esm/index.js +2 -2
  18. package/dist/esm/{index.umd-Dn0hjh7E.js → index.umd-BKBHcCnm.js} +9 -19
  19. package/dist/esm/index.umd-BKBHcCnm.js.map +1 -0
  20. package/dist/esm/index.umd-bIV_YpEF.js +13395 -0
  21. package/dist/esm/index.umd-bIV_YpEF.js.map +1 -0
  22. package/dist/types/components/hook-form/FormProvider.d.ts +2 -1
  23. package/dist/types/form/PaymentOverviewBox.d.ts +2 -0
  24. package/dist/types/form/PaymentOverviewDrawer.d.ts +10 -0
  25. package/dist/types/form/TicketForm.d.ts +1 -0
  26. package/dist/types/form/index.d.ts +2 -1
  27. package/dist/types/form/merchandise/MerchandiseSelection.d.ts +9 -0
  28. package/dist/types/form/merchandise/MerchandiseSlider.d.ts +10 -0
  29. package/dist/types/form/payment/PaymentOverviewCheckbox.d.ts +0 -4
  30. package/dist/types/form/product/ProductVariantsDialog.d.ts +3 -1
  31. package/dist/types/form/services/index.d.ts +7 -0
  32. package/dist/types/form/style.d.ts +1 -0
  33. package/dist/types/form/tickets/ReleaseDescription.d.ts +10 -0
  34. package/dist/types/form/tickets/ReleaseWithMerchandise.d.ts +12 -0
  35. package/dist/types/form/tickets/TicketQuantityControl.d.ts +13 -0
  36. package/dist/types/form/tickets/TicketSelectionMobile.d.ts +16 -0
  37. package/dist/types/hooks/useScrollToFirstError.d.ts +4 -0
  38. package/dist/types/locales/cs.d.ts +22 -0
  39. package/dist/types/locales/en.d.ts +22 -0
  40. package/dist/types/locales/es.d.ts +22 -0
  41. package/dist/types/locales/pl.d.ts +22 -0
  42. package/dist/types/locales/sk.d.ts +22 -0
  43. package/dist/types/locales/uk.d.ts +22 -0
  44. package/dist/types/utils/data/global.d.ts +1 -0
  45. package/dist/types/utils/data/ticket.d.ts +1 -0
  46. package/package.json +10 -4
  47. package/rollup.config.mjs +7 -12
  48. package/src/components/hook-form/FormProvider.tsx +5 -2
  49. package/src/form/ChildEventDialog.tsx +3 -3
  50. package/src/form/ContactPerson.tsx +1 -1
  51. package/src/form/PaymentOverviewBox.tsx +96 -123
  52. package/src/form/PaymentOverviewDrawer.tsx +445 -0
  53. package/src/form/PaymentPending.tsx +19 -4
  54. package/src/form/ReleaseWithMerchandise.tsx +4 -4
  55. package/src/form/Shipping.tsx +48 -33
  56. package/src/form/TicketForm.tsx +146 -41
  57. package/src/form/index.tsx +3 -1
  58. package/src/form/merchandise/MerchandiseSelection.tsx +24 -0
  59. package/src/form/merchandise/MerchandiseSlider.tsx +62 -0
  60. package/src/form/payment/FeeBox.tsx +4 -31
  61. package/src/form/payment/PaymentOverviewCheckbox.tsx +68 -69
  62. package/src/form/product/ProductCard.tsx +258 -59
  63. package/src/form/product/ProductVariantsDialog.tsx +292 -139
  64. package/src/form/services/index.tsx +262 -0
  65. package/src/form/style.ts +16 -4
  66. package/src/form/tickets/ReleaseDescription.tsx +46 -0
  67. package/src/form/tickets/ReleaseWithMerchandise.tsx +267 -0
  68. package/src/form/tickets/TicketQuantityControl.tsx +100 -0
  69. package/src/form/tickets/TicketSelection.tsx +236 -0
  70. package/src/form/{TicketSelectionMap.tsx → tickets/TicketSelectionMap.tsx} +18 -2
  71. package/src/form/tickets/TicketSelectionMobile.tsx +188 -0
  72. package/src/form/{TicketWithMerchandiseSelection.tsx → tickets/TicketWithMerchandiseSelection.tsx} +52 -38
  73. package/src/hooks/useScrollToFirstError.ts +99 -0
  74. package/src/locales/cs.tsx +25 -3
  75. package/src/locales/en.tsx +23 -1
  76. package/src/locales/es.tsx +23 -1
  77. package/src/locales/pl.tsx +23 -1
  78. package/src/locales/sk.tsx +24 -2
  79. package/src/locales/uk.tsx +23 -1
  80. package/src/utils/data/global.ts +1 -0
  81. package/src/utils/data/ticket.ts +1 -0
  82. package/tsconfig.json +1 -1
  83. package/README +0 -1
  84. package/dist/cjs/index-DvUR1fp8.js.map +0 -1
  85. package/dist/cjs/index.umd-6SU6nkkJ.js.map +0 -1
  86. package/dist/esm/index-BlTqx0jm.js.map +0 -1
  87. package/dist/esm/index.umd-Dn0hjh7E.js.map +0 -1
  88. package/src/form/TicketSelection.tsx +0 -307
  89. /package/dist/types/form/{TicketSelection.d.ts → tickets/TicketSelection.d.ts} +0 -0
  90. /package/dist/types/form/{TicketSelectionMap.d.ts → tickets/TicketSelectionMap.d.ts} +0 -0
  91. /package/dist/types/form/{TicketWithMerchandiseSelection.d.ts → tickets/TicketWithMerchandiseSelection.d.ts} +0 -0
@@ -1,307 +0,0 @@
1
- import React, { useEffect, useRef, useState } from 'react';
2
- import { useFormContext, useWatch } from 'react-hook-form';
3
- import {
4
- Box,
5
- Button,
6
- Divider,
7
- Grid,
8
- IconButton,
9
- MenuItem,
10
- Skeleton,
11
- Stack,
12
- Typography,
13
- } from '@mui/material';
14
- import { RHFSelect } from '@components/hook-form';
15
- import { ITicketForm, ITicketFormTicket } from '@utils/types/ticket.type';
16
- import useEventActiveReleases from '@hooks/data/useEventActiveReleases';
17
- import { fCurrency } from '@utils/formatNumber';
18
- import { Iconify } from '@components/iconify';
19
- import { groupBy } from '@utils/global';
20
- import { IReleaseShort } from '@utils/types/release.type';
21
- import FeeBox from '@form/payment/FeeBox';
22
- import { IEvent } from '@utils/types/event.type';
23
- import useResponsive from '@hooks/useResponsive';
24
- import ReleaseExtraFields from '@form/extra-field/ReleaseExtraFields';
25
- import { EventType } from '@utils/data/event';
26
- import useGlobal from '@hooks/useGlobal';
27
-
28
- interface Props {
29
- event: IEvent;
30
- }
31
-
32
- const TicketSelection: React.FC<Props> = ({ event }) => {
33
- const { t, lang } = useGlobal();
34
- const isMobile = useResponsive('down', 'md');
35
- const { setValue, watch } = useFormContext<ITicketForm>();
36
- const tickets = useWatch({
37
- name: `tickets.${event.id}`,
38
- defaultValue: [],
39
- }) as ITicketFormTicket[];
40
- const eventTimeslotId = watch('eventTimeslotId');
41
- const [soldOutReleaseCategoryNames, setSoldOutReleaseCategoryNames] = useState<string[]>([]);
42
- const isProcessingRef = useRef(false);
43
- const { data: activeReleases, mutate } = useEventActiveReleases(
44
- event.id,
45
- false,
46
- event.type === EventType.RECURRING ? eventTimeslotId : undefined
47
- );
48
-
49
- const showLoading = !activeReleases && event.type !== EventType.RECURRING;
50
-
51
- useEffect(() => {
52
- if (!isProcessingRef.current) selectedTickets();
53
- }, [tickets, activeReleases]);
54
-
55
- const isReleaseSelected = (id: number) => !!tickets.find((ticket) => ticket.releaseId === id);
56
-
57
- const getRelease = (releaseId: number) => {
58
- const release = activeReleases?.find((activeRelease) => activeRelease.id === releaseId);
59
- return release ? release : null;
60
- };
61
-
62
- const getExtraFields = (releaseId: number | '', index: number) => {
63
- if (!releaseId) return null;
64
-
65
- const release = getRelease(releaseId);
66
-
67
- if (!release || !release?.extraFields || release?.extraFields.length <= 0) return null;
68
-
69
- const addedRelease = tickets.find((ticket) => ticket.releaseId === release.id);
70
- const countTickets = addedRelease?.quantity || 0;
71
- return (
72
- <ReleaseExtraFields
73
- release={release}
74
- eventId={event.id}
75
- releaseIndex={index}
76
- quantity={countTickets}
77
- />
78
- );
79
- };
80
-
81
- const getAvailableTicketsForRelease = (release: ITicketFormTicket): number => {
82
- const selectedRelease = activeReleases?.find((item) => item.id === release.releaseId);
83
- const availableQuantity = selectedRelease ? selectedRelease.availableTickets : 0;
84
- return availableQuantity > 10 ? 10 : availableQuantity;
85
- };
86
-
87
- const countReleaseCategories = (): number => {
88
- const grouped = groupBy(activeReleases || [], 'releaseCategoryName');
89
- return Object.keys(grouped).length;
90
- };
91
-
92
- const selectedReleaseIsSoldOut = (releases: IReleaseShort[] | undefined) => {
93
- const lockedSelectedReleases: boolean[] | undefined = releases?.map((item, index) => {
94
- const nextRelease = releases?.find(
95
- (item2) =>
96
- item2.releaseCategoryName === item.releaseCategoryName && item2.order === item.order + 1
97
- );
98
- const selected = tickets.find((ticket) => ticket.releaseId === item.id);
99
- return !!nextRelease && item.locked && !!selected && index + 1 == tickets.length;
100
- });
101
- return lockedSelectedReleases && lockedSelectedReleases.includes(true);
102
- };
103
-
104
- const countUnlockedReleases = () => activeReleases?.filter((item) => !item.locked).length || 0;
105
-
106
- const countSelectedTickets = () => {
107
- let count = 0;
108
- for (const ticket of tickets) {
109
- count += +ticket.quantity;
110
- }
111
-
112
- return count;
113
- };
114
-
115
- const isQuantityDisabled = (value: number, releaseId: number | '') => {
116
- const releaseSelected = tickets.find((item) => item.releaseId === releaseId);
117
- return releaseSelected && releaseSelected.quantity
118
- ? countSelectedTickets() + value - releaseSelected.quantity > 10
119
- : countSelectedTickets() + value > 10;
120
- };
121
-
122
- const removeTicket = (indexToRemove: number) => {
123
- const activeReleases = tickets.filter((_ticket, index) => index !== indexToRemove);
124
- setValue(`tickets.${event.id}`, activeReleases);
125
- };
126
-
127
- const selectedTickets = async () => {
128
- const releases = await mutate();
129
- const allFilled = tickets.filter((item) => !item.releaseId || !item.quantity);
130
-
131
- const soldOutReleaseCategories = activeReleases?.filter((release) =>
132
- tickets.find(
133
- (ticket) =>
134
- release.id === ticket.releaseId &&
135
- ticket.quantity === release.availableTickets &&
136
- release.availableTickets !== 10
137
- )
138
- );
139
- setSoldOutReleaseCategoryNames(
140
- soldOutReleaseCategories?.map((item) => item.releaseCategoryName) || []
141
- );
142
-
143
- const hasSelectableRelease = activeReleases?.some(
144
- (release) => !isReleaseSelected(release.id) && !release.locked
145
- );
146
-
147
- const shouldAddRow =
148
- (soldOutReleaseCategories &&
149
- selectedReleaseIsSoldOut(releases) &&
150
- tickets.length < soldOutReleaseCategories.length + countUnlockedReleases() &&
151
- !allFilled.length) ||
152
- (activeReleases &&
153
- soldOutReleaseCategories?.length &&
154
- activeReleases?.length > tickets.length &&
155
- tickets.length < soldOutReleaseCategories.length + countUnlockedReleases() &&
156
- !allFilled.length) ||
157
- (tickets.length < countReleaseCategories() && !allFilled.length);
158
-
159
- const shouldRemoveEmptyRows =
160
- allFilled.length > 0 &&
161
- tickets.length > 1 &&
162
- !hasSelectableRelease &&
163
- (!soldOutReleaseCategories?.length || !selectedReleaseIsSoldOut(releases));
164
-
165
- if (shouldAddRow) {
166
- isProcessingRef.current = true;
167
- setValue(`tickets.${event.id}`, [
168
- ...tickets,
169
- {
170
- releaseId: '',
171
- quantity: '',
172
- itemName: '',
173
- price: 0,
174
- products: [],
175
- extraFields: [],
176
- },
177
- ]);
178
- setTimeout(() => (isProcessingRef.current = false), 0);
179
- } else if (shouldRemoveEmptyRows) {
180
- // Only remove completely empty rows (no releaseId), keep rows where user started selecting
181
- const nonEmptyTickets = tickets.filter((item) => item.releaseId);
182
- if (nonEmptyTickets.length < tickets.length) {
183
- isProcessingRef.current = true;
184
- setValue(`tickets.${event.id}`, nonEmptyTickets);
185
- setTimeout(() => (isProcessingRef.current = false), 0);
186
- }
187
- }
188
- };
189
-
190
- return (
191
- <Stack spacing={3} direction="column" divider={<Divider sx={{ borderStyle: 'dashed' }} />}>
192
- {tickets.map((item, index) => (
193
- <Box key={index}>
194
- <Grid container spacing={3}>
195
- <Grid size={{ xs: 12, md: 6 }}>
196
- {showLoading ? (
197
- <Skeleton
198
- variant="rounded"
199
- sx={{
200
- width: '100%',
201
- height: (theme) => theme.spacing(7.5),
202
- }}
203
- />
204
- ) : (
205
- <RHFSelect
206
- name={`tickets.${event.id}.${index}.releaseId`}
207
- value={item.releaseId}
208
- label={
209
- index > 0
210
- ? t('form.labels.add_another_release')
211
- : t('form.labels.release_category_price')
212
- }
213
- maxHeight="calc(100vh - 2rem)"
214
- onChange={(e) => {
215
- setValue(`tickets.${event.id}.${index}.releaseId`, Number(e.target.value));
216
- setValue(`tickets.${event.id}.${index}.extraFields`, []);
217
- }}
218
- >
219
- <MenuItem key={0} value="">
220
- {t('choose')}
221
- </MenuItem>
222
- {activeReleases?.map((activeRelease) => (
223
- <MenuItem
224
- key={activeRelease.id}
225
- value={activeRelease.id}
226
- disabled={
227
- isReleaseSelected(activeRelease.id) ||
228
- (activeRelease.locked &&
229
- !soldOutReleaseCategoryNames.includes(activeRelease.releaseCategoryName))
230
- }
231
- >
232
- {activeRelease.releaseCategoryName} - {activeRelease.name}:{' '}
233
- {activeRelease.price === 0
234
- ? t('free')
235
- : fCurrency(activeRelease.price, lang, event.currency)}
236
- </MenuItem>
237
- ))}
238
- </RHFSelect>
239
- )}
240
- </Grid>
241
- <Grid key={index} size={{ xs: 12, md: 6 }}>
242
- {showLoading ? (
243
- <Skeleton
244
- variant="rounded"
245
- sx={{
246
- width: '100%',
247
- height: (theme) => theme.spacing(7.5),
248
- }}
249
- />
250
- ) : (
251
- <Stack direction="row" alignItems="center" spacing={1}>
252
- <RHFSelect
253
- name={`tickets.${event.id}.${index}.quantity`}
254
- value={item.quantity}
255
- label={t('form.labels.quantity')}
256
- >
257
- {[...Array(getAvailableTicketsForRelease(item))].map((_, index2) => (
258
- <MenuItem
259
- key={index2}
260
- value={index2 + 1}
261
- disabled={isQuantityDisabled(index2 + 1, item.releaseId)}
262
- >
263
- {index2 + 1}
264
- </MenuItem>
265
- ))}
266
- {!item.releaseId && (
267
- <MenuItem disabled sx={{ textTransform: 'unset!important' }}>
268
- {t('event.tickets.stepper.1.quantity_select')}
269
- </MenuItem>
270
- )}
271
- </RHFSelect>
272
- {item.releaseId && item.quantity && (
273
- <Box>
274
- <IconButton color="primary" onClick={() => removeTicket(index)}>
275
- <Iconify icon="carbon:trash-can" />
276
- </IconButton>
277
- </Box>
278
- )}
279
- </Stack>
280
- )}
281
- </Grid>
282
- </Grid>
283
- {activeReleases && item.releaseId && (
284
- <Typography
285
- variant="caption"
286
- content="div"
287
- mt={2}
288
- mb={getRelease(item.releaseId)?.extraFields?.length ? 2 : 0}
289
- display="block"
290
- >
291
- {getRelease(item.releaseId)?.description ?? ''}
292
- </Typography>
293
- )}
294
- {getExtraFields(item.releaseId, index)}
295
- </Box>
296
- ))}
297
- <Box>
298
- <Typography variant="caption" component="div" fontStyle="italic" mb={2}>
299
- *{t('event.tickets.stepper.1.max_ticket_quantity')}
300
- </Typography>
301
- {isMobile && <FeeBox event={event} align="right" />}
302
- </Box>
303
- </Stack>
304
- );
305
- };
306
-
307
- export default TicketSelection;