tf-checkout-react 1.3.50 → 1.4.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 (50) hide show
  1. package/dist/api/index.d.ts +6 -1
  2. package/dist/components/common/Loader.d.ts +1 -1
  3. package/dist/components/idVerificationContainer/constants.d.ts +2 -0
  4. package/dist/components/index.d.ts +1 -0
  5. package/dist/components/seatMapContainer/SeatMapComponent.d.ts +8 -0
  6. package/dist/components/seatMapContainer/TicketsSection.d.ts +9 -0
  7. package/dist/components/seatMapContainer/addToCart.d.ts +21 -0
  8. package/dist/components/seatMapContainer/index.d.ts +2 -0
  9. package/dist/components/seatMapContainer/utils.d.ts +14 -0
  10. package/dist/components/stripePayment/index.d.ts +2 -2
  11. package/dist/components/ticketsContainer/TicketRow.d.ts +3 -1
  12. package/dist/components/ticketsContainer/TicketsSection.d.ts +5 -1
  13. package/dist/components/ticketsContainer/index.d.ts +6 -2
  14. package/dist/index.d.ts +1 -0
  15. package/dist/tf-checkout-react.cjs.development.js +1441 -130
  16. package/dist/tf-checkout-react.cjs.development.js.map +1 -1
  17. package/dist/tf-checkout-react.cjs.production.min.js +1 -1
  18. package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
  19. package/dist/tf-checkout-react.esm.js +1442 -132
  20. package/dist/tf-checkout-react.esm.js.map +1 -1
  21. package/dist/tf-checkout-styles.css +1 -1
  22. package/dist/types/order-data.d.ts +3 -0
  23. package/dist/utils/createCheckoutDataBodyWithDefaultHolder.d.ts +9 -2
  24. package/package.json +12 -4
  25. package/src/.d.ts +4 -3
  26. package/src/api/index.ts +89 -6
  27. package/src/components/billing-info-container/index.tsx +115 -103
  28. package/src/components/billing-info-container/utils.ts +1 -2
  29. package/src/components/common/Loader.tsx +6 -8
  30. package/src/components/confirmationContainer/index.tsx +11 -9
  31. package/src/components/idVerificationContainer/constants.ts +2 -0
  32. package/src/components/idVerificationContainer/index.tsx +54 -13
  33. package/src/components/index.ts +2 -1
  34. package/src/components/orderDetailsContainer/index.tsx +54 -23
  35. package/src/components/paymentContainer/index.tsx +167 -33
  36. package/src/components/seatMapContainer/SeatMapComponent.tsx +73 -0
  37. package/src/components/seatMapContainer/TicketsSection.tsx +254 -0
  38. package/src/components/seatMapContainer/addToCart.ts +82 -0
  39. package/src/components/seatMapContainer/index.tsx +408 -0
  40. package/src/components/seatMapContainer/utils.ts +138 -0
  41. package/src/components/stripePayment/index.tsx +23 -18
  42. package/src/components/ticketsContainer/TicketRow.tsx +28 -13
  43. package/src/components/ticketsContainer/TicketsSection.tsx +85 -2
  44. package/src/components/ticketsContainer/index.tsx +57 -12
  45. package/src/components/ticketsContainer/style.css +0 -3
  46. package/src/hooks/usePixel.ts +35 -1
  47. package/src/index.ts +2 -1
  48. package/src/types/order-data.ts +3 -0
  49. package/src/types/seatMap.d.ts +154 -0
  50. package/src/utils/createCheckoutDataBodyWithDefaultHolder.ts +6 -2
@@ -0,0 +1,254 @@
1
+ import { CSSProperties } from '@emotion/serialize'
2
+ import { createTheme, Select, SelectChangeEvent,ThemeOptions } from '@mui/material'
3
+ import CircularProgress from '@mui/material/CircularProgress'
4
+ import FormControl from '@mui/material/FormControl'
5
+ import InputLabel from '@mui/material/InputLabel'
6
+ import MenuItem from '@mui/material/MenuItem'
7
+ import { ThemeProvider } from '@mui/private-theming'
8
+ import _find from 'lodash/find'
9
+ import _identity from 'lodash/identity'
10
+ import _isEmpty from 'lodash/isEmpty'
11
+ import _keys from 'lodash/keys'
12
+ import _map from 'lodash/map'
13
+ import _some from 'lodash/some'
14
+ import React from 'react'
15
+ import { Button } from 'react-bootstrap'
16
+
17
+ import { createFixedFloatNormalizer } from '../../normalizers'
18
+ import { getButtonLabel, getTicketDropdownData } from './utils'
19
+
20
+ export const TicketsSection = (
21
+ props: ITicketsSectionProps & {
22
+ themeOptions?: ThemeOptions & {
23
+ input?: CSSProperties;
24
+ checkbox?: CSSProperties;
25
+ };
26
+ }
27
+ ) => {
28
+ const {
29
+ ticketTypeTierRelations,
30
+ reservedSeats,
31
+ theme = 'light',
32
+ getTicketsBtnLabel,
33
+ contentStyle = {},
34
+ isButtonScrollable = false,
35
+ themeOptions,
36
+ handleGetTicketClick,
37
+ handleCancelReservation,
38
+ ticketDeleteButtonContent = 'Delete',
39
+ selectedTickets,
40
+ handleTicketSelect,
41
+ currencySymbol,
42
+ tableMapEnabled = false,
43
+ guestCounts,
44
+ setGuestCounts,
45
+ isAddingToCart,
46
+ } = props
47
+
48
+ const bookButtonIsDisabled =
49
+ _some(selectedTickets, item => !item) ||
50
+ _isEmpty(reservedSeats) ||
51
+ reservedSeats.length !== _keys(selectedTickets).length
52
+ const themeMui = createTheme(themeOptions)
53
+
54
+ const ticketsDropdownsData = getTicketDropdownData(
55
+ reservedSeats,
56
+ ticketTypeTierRelations
57
+ )
58
+ const handleTicketChange = (event: SelectChangeEvent<string>, seatId: string) => {
59
+ const {
60
+ target: { value },
61
+ } = event
62
+
63
+ if (value !== 'default') {
64
+ handleTicketSelect(value, seatId)
65
+ }
66
+ }
67
+
68
+ return (
69
+ <ThemeProvider theme={themeMui}>
70
+ <div className={`get-tickets-page ${theme}`} style={contentStyle}>
71
+ <div className="tickets-section">
72
+ {_map(selectedTickets, (ticketItem: string, key: string) => {
73
+ const dropdownData =
74
+ _find(ticketsDropdownsData, item => item.seatId === key) ||
75
+ ({} as ITicketsDropdownsData)
76
+
77
+ const selectedTicketData = _find(
78
+ dropdownData.ticketsData,
79
+ ticket => ticket.ticket_type_id === ticketItem
80
+ ) as TicketTypeTierRelationsData
81
+
82
+ // guest count dropdown options
83
+ const startNum = Number(
84
+ selectedTicketData?.ticket_type_min_number_of_guests
85
+ )
86
+ const endNum = Number(
87
+ selectedTicketData?.ticket_type_max_number_of_guests
88
+ )
89
+ const numLength = endNum - startNum + 1
90
+ const showGuestCountDropdown = Boolean(startNum && endNum)
91
+
92
+ // prices
93
+ const guestPrice =
94
+ (guestCounts[dropdownData.seatId] - startNum) *
95
+ Number(selectedTicketData?.guest_price)
96
+
97
+ const finalPrice = createFixedFloatNormalizer(2)(
98
+ selectedTicketData?.ticket_type_price + guestPrice
99
+ )
100
+
101
+ return (
102
+ <div className="ticket" key={key}>
103
+ <div className="ticketsDropdowns">
104
+ <Select
105
+ value={ticketItem || 'default'}
106
+ onChange={event =>
107
+ handleTicketChange(event, dropdownData.seatId)
108
+ }
109
+ inputProps={{ 'aria-label': 'Without label' }}
110
+ MenuProps={{
111
+ PaperProps: {
112
+ sx: { maxHeight: 150 },
113
+ className: 'get-tickets-paper',
114
+ },
115
+ }}
116
+ displayEmpty
117
+ sx={{ borderRadius: 0 }}
118
+ >
119
+ <MenuItem value={'default'}>
120
+ {`Please select ${
121
+ tableMapEnabled ? 'Table Type' : 'Ticket Type'
122
+ }`}
123
+ </MenuItem>
124
+ {_map(dropdownData.ticketsData, (option, index) => {
125
+ if (option.ticket_type_id !== 'default') {
126
+ return (
127
+ <MenuItem value={option.ticket_type_id} key={index}>
128
+ {option.ticket_type_name}
129
+ </MenuItem>
130
+ )
131
+ }
132
+ return null
133
+ })}
134
+ </Select>
135
+ <Button
136
+ className="ticket-delete"
137
+ onClick={() => {
138
+ handleCancelReservation(
139
+ dropdownData.seatId,
140
+ dropdownData.tierId
141
+ )
142
+ }}
143
+ >
144
+ {ticketDeleteButtonContent}
145
+ </Button>
146
+ </div>
147
+ {selectedTicketData && (
148
+ <div style={{ display: 'flex', flexDirection: 'row' }}>
149
+ <div
150
+ style={{
151
+ width: '100%',
152
+ display: 'flex',
153
+ flexDirection: 'column',
154
+ justifyContent: 'center',
155
+ }}
156
+ >
157
+ <div className="ticketPrice">
158
+ Price:
159
+ <span className="ticketPrice-value">
160
+ {`${currencySymbol} ${finalPrice}`}
161
+ </span>
162
+ </div>
163
+ {!_isEmpty(selectedTicketData.ticket_type_deposit) && (
164
+ <div className="ticketDeposit">
165
+ Deposit:
166
+ <span className="ticketPrice-value">
167
+ {` ${selectedTicketData?.ticket_type_deposit}%`}
168
+ </span>
169
+ </div>
170
+ )}
171
+ </div>
172
+ {showGuestCountDropdown && (
173
+ <div
174
+ style={{
175
+ width: '100%',
176
+ display: 'flex',
177
+ justifyContent: 'end',
178
+ marginRight: 16,
179
+ }}
180
+ >
181
+ <FormControl
182
+ variant="outlined"
183
+ sx={{ m: 1, minWidth: 80 }}
184
+ >
185
+ <InputLabel
186
+ id="demo-simple-select-standard-label"
187
+ shrink
188
+ >
189
+ GUESTS
190
+ </InputLabel>
191
+ <Select
192
+ label="GUESTS"
193
+ labelId="demo-simple-select-standard-label"
194
+ value={guestCounts[dropdownData.seatId] || startNum}
195
+ onChange={event => {
196
+ setGuestCounts({
197
+ ...guestCounts,
198
+ [dropdownData.seatId]: Number(
199
+ event.target.value
200
+ ),
201
+ })
202
+ }}
203
+ inputProps={{ 'aria-label': 'Without label' }}
204
+ MenuProps={{
205
+ PaperProps: {
206
+ sx: { maxHeight: 150 },
207
+ className: 'get-tickets-paper',
208
+ },
209
+ }}
210
+ displayEmpty
211
+ sx={{ borderRadius: 0 }}
212
+ >
213
+ {_map(
214
+ Array.from(
215
+ { length: numLength },
216
+ (_, i) => startNum + i
217
+ ),
218
+ (option, index) => (
219
+ <MenuItem value={option} key={index}>
220
+ {option}
221
+ </MenuItem>
222
+ )
223
+ )}
224
+ </Select>
225
+ </FormControl>
226
+ </div>
227
+ )}
228
+ </div>
229
+ )}
230
+ </div>
231
+ )
232
+ })}
233
+ </div>
234
+ <div>
235
+ <Button
236
+ className={`book-button
237
+ ${bookButtonIsDisabled ? 'disabled' : ''}
238
+ ${isButtonScrollable ? 'is-scrollable' : ''}
239
+ `}
240
+ onClick={!bookButtonIsDisabled ? handleGetTicketClick : _identity}
241
+ disabled={isAddingToCart}
242
+ >
243
+ {isAddingToCart ? (
244
+ <CircularProgress size={20} style={{ marginLeft: 10 }} />
245
+ ) : (
246
+ getTicketsBtnLabel ||
247
+ getButtonLabel(reservedSeats.length, tableMapEnabled)
248
+ )}
249
+ </Button>
250
+ </div>
251
+ </div>
252
+ </ThemeProvider>
253
+ )
254
+ }
@@ -0,0 +1,82 @@
1
+ import _get from 'lodash/get'
2
+
3
+ import { addToCart, getCheckoutPageConfigs, postOnCheckout } from '../../api'
4
+ import { createCheckoutDataBodyWithDefaultHolder } from '../../utils'
5
+
6
+ interface IAddToCartFuncProps {
7
+ eventId: string | number;
8
+ data: any;
9
+ ticketQuantity: number;
10
+ enableBillingInfoAutoCreate?: boolean;
11
+ }
12
+
13
+ export const addToCartFunc = async ({
14
+ eventId,
15
+ data,
16
+ ticketQuantity,
17
+ enableBillingInfoAutoCreate = true,
18
+ }: IAddToCartFuncProps) => {
19
+ const isWindowDefined = typeof window !== 'undefined'
20
+
21
+ const result = await addToCart(eventId, data)
22
+ const pageConfigsDataResponse = await getCheckoutPageConfigs()
23
+
24
+ if (result.status === 200 && pageConfigsDataResponse.status === 200) {
25
+ const pageConfigsData =
26
+ _get(pageConfigsDataResponse, 'data.attributes') || {}
27
+
28
+ const {
29
+ skip_billing_page: skipBillingPage = false,
30
+ names_required: nameIsRequired = false,
31
+ age_required: ageIsRequired = false,
32
+ phone_required: phoneIsRequired = false,
33
+ hide_phone_field: hidePhoneField = false,
34
+ has_add_on: hasAddOn = false,
35
+ free_ticket: freeTicket = false,
36
+ collect_optional_wallet_address: collectOptionalWalletAddress = false,
37
+ collect_mandatory_wallet_address: collectMandatoryWalletAddress = false,
38
+ } = pageConfigsData
39
+
40
+ let hash = ''
41
+ let total = ''
42
+
43
+ isWindowDefined && window.localStorage.removeItem('add_ons')
44
+
45
+ if (skipBillingPage && !hasAddOn) {
46
+ // Get user data for checkout data
47
+ const userData =
48
+ isWindowDefined && window.localStorage.getItem('user_data')
49
+ ? JSON.parse(window.localStorage.getItem('user_data') || '')
50
+ : {}
51
+
52
+ const checkoutBody = createCheckoutDataBodyWithDefaultHolder(
53
+ ticketQuantity,
54
+ userData
55
+ )
56
+
57
+ const checkoutResult = enableBillingInfoAutoCreate
58
+ ? await postOnCheckout(checkoutBody, undefined, freeTicket)
59
+ : null
60
+
61
+ hash = _get(checkoutResult, 'data.data.attributes.hash') || ''
62
+ total = _get(checkoutResult, 'data.data.attributes.total') || ''
63
+ }
64
+
65
+ return {
66
+ skip_billing_page: skipBillingPage,
67
+ names_required: nameIsRequired,
68
+ phone_required: phoneIsRequired,
69
+ age_required: ageIsRequired,
70
+ hide_phone_field: hidePhoneField,
71
+ free_ticket: freeTicket,
72
+ collect_optional_wallet_address: collectOptionalWalletAddress,
73
+ collect_mandatory_wallet_address: collectMandatoryWalletAddress,
74
+ event_id: String(eventId),
75
+ hash,
76
+ total,
77
+ hasAddOn,
78
+ }
79
+ }
80
+
81
+ return null
82
+ }