tf-checkout-react 1.7.3 → 1.7.5
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.
- package/dist/components/common/PhoneNumberField.d.ts +1 -2
- package/dist/components/confirmationContainer/index.d.ts +5 -1
- package/dist/components/loginModal/SignUpForm.d.ts +10 -0
- package/dist/components/loginModal/constants.d.ts +39 -0
- package/dist/components/preRegistration/PreRegistrationComplete.d.ts +1 -1
- package/dist/components/seatMapContainer/addToCart.d.ts +2 -2
- package/dist/components/ticketsContainer/TimeSlotTicketRow.d.ts +19 -0
- package/dist/tf-checkout-react.cjs.development.js +817 -85
- package/dist/tf-checkout-react.cjs.development.js.map +1 -1
- package/dist/tf-checkout-react.cjs.production.min.js +1 -1
- package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
- package/dist/tf-checkout-react.esm.js +818 -86
- package/dist/tf-checkout-react.esm.js.map +1 -1
- package/dist/tf-checkout-styles.css +1 -1
- package/package.json +4 -3
- package/src/api/publicRequest.ts +1 -0
- package/src/components/billing-info-container/index.tsx +1 -1
- package/src/components/common/CustomField.tsx +16 -5
- package/src/components/common/PhoneNumberField.tsx +7 -10
- package/src/components/confirmationContainer/index.tsx +29 -4
- package/src/components/loginModal/SignUpForm.tsx +329 -0
- package/src/components/loginModal/constants.ts +46 -0
- package/src/components/loginModal/index.tsx +94 -26
- package/src/components/loginModal/style.css +38 -0
- package/src/components/myTicketsContainer/index.tsx +2 -0
- package/src/components/preRegistration/PreRegistrationComplete.tsx +3 -1
- package/src/components/ticketsContainer/TimeSlotTicketRow.tsx +224 -0
- package/src/components/ticketsContainer/TimeSlotsSection.tsx +98 -24
- package/src/components/ticketsContainer/index.tsx +1 -1
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
import { Box, CircularProgress, TextField } from '@mui/material'
|
|
3
3
|
import { LocalizationProvider, StaticDatePicker as DatePicker } from '@mui/x-date-pickers'
|
|
4
4
|
import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment'
|
|
5
|
-
import
|
|
5
|
+
import _get from 'lodash/get'
|
|
6
6
|
import _map from 'lodash/map'
|
|
7
|
+
import _sortBy from 'lodash/sortBy'
|
|
7
8
|
import moment from 'moment-timezone'
|
|
8
|
-
import React, { ReactNode, useState } from 'react'
|
|
9
|
+
import React, { ReactNode, useMemo, useState } from 'react'
|
|
9
10
|
|
|
10
|
-
import {
|
|
11
|
+
import { TimeSlotTicketRow } from './TimeSlotTicketRow'
|
|
11
12
|
|
|
12
13
|
interface Props {
|
|
13
14
|
event: any;
|
|
@@ -29,6 +30,16 @@ interface Props {
|
|
|
29
30
|
isSeatMapAllowed?: boolean;
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
interface TimeSlotOption {
|
|
34
|
+
timeKey: string;
|
|
35
|
+
ticketInstance: any;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface UniqueTicket {
|
|
39
|
+
ticket: any;
|
|
40
|
+
availableTimeSlots: TimeSlotOption[];
|
|
41
|
+
}
|
|
42
|
+
|
|
32
43
|
const TimeSlotsSection: React.FC<Props> = ({
|
|
33
44
|
event,
|
|
34
45
|
availableDates,
|
|
@@ -41,14 +52,14 @@ const TimeSlotsSection: React.FC<Props> = ({
|
|
|
41
52
|
sortBySoldOut,
|
|
42
53
|
hideTicketsHeader,
|
|
43
54
|
ticketsHeaderComponent,
|
|
44
|
-
showGroupNameBlock,
|
|
45
55
|
currencySymbol,
|
|
46
|
-
isSeatMapAllowed,
|
|
47
56
|
}) => {
|
|
48
57
|
const [loading, setLoading] = useState(false)
|
|
58
|
+
const [selectedTimeSlots, setSelectedTimeSlots] = useState<{ [key: string]: string }>({})
|
|
49
59
|
|
|
50
60
|
const handleDateChange = async (date: string | null) => {
|
|
51
61
|
setSelectedDate(date)
|
|
62
|
+
setSelectedTimeSlots({}) // Reset time slot selections when date changes
|
|
52
63
|
if (date) {
|
|
53
64
|
setLoading(true)
|
|
54
65
|
try {
|
|
@@ -66,6 +77,67 @@ const TimeSlotsSection: React.FC<Props> = ({
|
|
|
66
77
|
return !availableDates.includes(formattedDate)
|
|
67
78
|
}
|
|
68
79
|
|
|
80
|
+
// Group tickets by unique ticket type using displayName + price
|
|
81
|
+
const uniqueTickets = useMemo(() => {
|
|
82
|
+
const ticketMap: { [key: string]: UniqueTicket } = {}
|
|
83
|
+
|
|
84
|
+
// Iterate through all time slots
|
|
85
|
+
_map(timeSlotGroups, (tickets, timeKey) => {
|
|
86
|
+
tickets.forEach((ticket: any) => {
|
|
87
|
+
// Use displayName + price as the unique identifier for ticket types
|
|
88
|
+
// This handles cases where multiple ticket types share the same optionName
|
|
89
|
+
const ticketKey = `${ticket.displayName || ticket.name}_${ticket.price}`
|
|
90
|
+
|
|
91
|
+
if (!ticketMap[ticketKey]) {
|
|
92
|
+
ticketMap[ticketKey] = {
|
|
93
|
+
ticket: { ...ticket },
|
|
94
|
+
availableTimeSlots: [],
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Store both the time key and the ticket instance for this slot
|
|
99
|
+
if (!ticketMap[ticketKey].availableTimeSlots.find((slot: any) => slot.timeKey === timeKey)) {
|
|
100
|
+
ticketMap[ticketKey].availableTimeSlots.push({
|
|
101
|
+
timeKey,
|
|
102
|
+
ticketInstance: ticket,
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
// Convert to array and sort
|
|
109
|
+
const ticketsArray = Object.values(ticketMap)
|
|
110
|
+
return sortBySoldOut
|
|
111
|
+
? _sortBy(_sortBy(ticketsArray, t => t.ticket.sortOrder), t => t.ticket.soldOut)
|
|
112
|
+
: _sortBy(ticketsArray, t => t.ticket.sortOrder)
|
|
113
|
+
}, [timeSlotGroups, sortBySoldOut])
|
|
114
|
+
|
|
115
|
+
const handleTimeSlotSelect = (ticketKey: string, timeKey: string, ticketInstance: any) => {
|
|
116
|
+
setSelectedTimeSlots(prev => ({
|
|
117
|
+
...prev,
|
|
118
|
+
[ticketKey]: timeKey,
|
|
119
|
+
}))
|
|
120
|
+
|
|
121
|
+
// Reset quantity when time slot changes
|
|
122
|
+
if (selectedTickets[ticketInstance.id]) {
|
|
123
|
+
handleTicketSelect(ticketInstance.id, 0)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const handleTicketSelectWithTimeSlot = (ticketKey: string, quantity: number, ticketInstance: any) => {
|
|
128
|
+
const timeSlot = selectedTimeSlots[ticketKey]
|
|
129
|
+
if (!timeSlot && quantity > 0) {
|
|
130
|
+
return // Don't allow quantity selection without time slot
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (ticketInstance) {
|
|
134
|
+
handleTicketSelect(ticketInstance.id, quantity)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const symbol = _get(event, 'currency.symbol')
|
|
139
|
+
const priceSymbol = currencySymbol || symbol
|
|
140
|
+
|
|
69
141
|
return (
|
|
70
142
|
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
|
|
71
143
|
<LocalizationProvider dateAdapter={AdapterMoment}>
|
|
@@ -88,29 +160,31 @@ const TimeSlotsSection: React.FC<Props> = ({
|
|
|
88
160
|
width: '100%',
|
|
89
161
|
display: 'flex',
|
|
90
162
|
flexDirection: 'column',
|
|
91
|
-
gap: 2,
|
|
92
163
|
}}
|
|
93
164
|
>
|
|
94
|
-
{
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
165
|
+
{!hideTicketsHeader && ticketsHeaderComponent}
|
|
166
|
+
{uniqueTickets.map(({ ticket, availableTimeSlots }) => {
|
|
167
|
+
const ticketKey = `${ticket.displayName || ticket.name}_${ticket.price}`
|
|
168
|
+
const isSoldOut =
|
|
169
|
+
ticket.sold_out ||
|
|
170
|
+
!(ticket.displayTicket || ticket.slotGroupId) ||
|
|
171
|
+
ticket.soldOut
|
|
172
|
+
|
|
173
|
+
return (
|
|
174
|
+
<TimeSlotTicketRow
|
|
175
|
+
key={ticketKey}
|
|
176
|
+
ticketKey={ticketKey}
|
|
177
|
+
ticket={ticket}
|
|
178
|
+
availableTimeSlots={availableTimeSlots}
|
|
101
179
|
selectedTickets={selectedTickets}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
hideTicketsHeader={hideTicketsHeader || _isEmpty(timeSlotGroups[timeKey])}
|
|
108
|
-
showGroupNameBlock={showGroupNameBlock}
|
|
109
|
-
currencySymbol={currencySymbol}
|
|
110
|
-
isSeatMapAllowed={isSeatMapAllowed}
|
|
180
|
+
selectedTimeSlots={selectedTimeSlots}
|
|
181
|
+
handleTicketSelect={handleTicketSelectWithTimeSlot}
|
|
182
|
+
handleTimeSlotSelect={handleTimeSlotSelect}
|
|
183
|
+
priceSymbol={priceSymbol}
|
|
184
|
+
isSoldOut={isSoldOut}
|
|
111
185
|
/>
|
|
112
|
-
|
|
113
|
-
)
|
|
186
|
+
)
|
|
187
|
+
})}
|
|
114
188
|
</Box>
|
|
115
189
|
)}
|
|
116
190
|
</Box>
|
|
@@ -957,7 +957,7 @@ export const TicketsContainer = ({
|
|
|
957
957
|
</div>
|
|
958
958
|
)}
|
|
959
959
|
{showLoginModal ? (
|
|
960
|
-
<LoginModal onClose={handleOnClose} onLogin={handleOnLogin} />
|
|
960
|
+
<LoginModal onClose={handleOnClose} onLogin={handleOnLogin} showForgotPasswordButton />
|
|
961
961
|
) : null}
|
|
962
962
|
</div>
|
|
963
963
|
{showPoweredByImage ? <PoweredBy /> : null}
|