tf-checkout-react 1.0.45 → 1.0.49
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/api/index.d.ts +2 -0
- package/dist/components/billing-info-container/index.d.ts +1 -1
- package/dist/components/billing-info-container/utils.d.ts +1 -1
- package/dist/components/common/CheckboxField.d.ts +3 -3
- package/dist/components/common/CustomField.d.ts +2 -1
- package/dist/components/paymentContainer/index.d.ts +1 -1
- package/dist/components/stripePayment/index.d.ts +2 -1
- package/dist/components/ticketsContainer/TicketRow.d.ts +10 -0
- package/dist/components/ticketsContainer/TicketsSection.d.ts +10 -0
- package/dist/components/ticketsContainer/index.d.ts +3 -1
- package/dist/components/ticketsContainer/utils.d.ts +4 -0
- package/dist/components/waitingList/index.d.ts +7 -0
- package/dist/tf-checkout-react.cjs.development.css +4 -3
- package/dist/tf-checkout-react.cjs.development.js +486 -184
- 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 +494 -189
- package/dist/tf-checkout-react.esm.js.map +1 -1
- package/dist/types/billing-info-data.d.ts +2 -2
- package/dist/utils/getQueryVariable.d.ts +1 -0
- package/dist/validators/index.d.ts +2 -1
- package/package.json +2 -1
- package/src/api/index.ts +5 -1
- package/src/components/billing-info-container/index.tsx +140 -133
- package/src/components/billing-info-container/utils.ts +3 -2
- package/src/components/common/CheckboxField.tsx +9 -3
- package/src/components/common/CustomField.tsx +17 -7
- package/src/components/paymentContainer/index.tsx +31 -3
- package/src/components/paymentContainer/style.css +8 -0
- package/src/components/stripePayment/index.tsx +48 -19
- package/src/components/stripePayment/style.css +6 -0
- package/src/components/ticketsContainer/TicketRow.tsx +86 -0
- package/src/components/ticketsContainer/TicketsSection.tsx +82 -0
- package/src/components/ticketsContainer/index.tsx +84 -208
- package/src/components/ticketsContainer/utils.ts +11 -0
- package/src/components/waitingList/index.tsx +172 -0
- package/src/components/waitingList/style.css +18 -0
- package/src/types/billing-info-data.ts +2 -2
- package/src/utils/getQueryVariable.ts +13 -0
- package/src/validators/index.ts +9 -3
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import { StripeCardNumberElementOptions } from '@stripe/stripe-js'
|
|
10
10
|
import _identity from 'lodash/identity'
|
|
11
11
|
import _get from 'lodash/get'
|
|
12
|
+
import { CheckboxField } from '../common/CheckboxField'
|
|
12
13
|
|
|
13
14
|
import './style.css'
|
|
14
15
|
import { getCurrencySymbolByCurrency } from '../../normalizers'
|
|
@@ -17,6 +18,7 @@ import CircularProgress from '@mui/material/CircularProgress'
|
|
|
17
18
|
const options: StripeCardNumberElementOptions = {
|
|
18
19
|
style: {
|
|
19
20
|
base: {
|
|
21
|
+
backgroundColor:'#232323',
|
|
20
22
|
fontSize: '18px',
|
|
21
23
|
color: '#ffffff',
|
|
22
24
|
letterSpacing: '1px',
|
|
@@ -42,13 +44,14 @@ export interface ICheckoutForm {
|
|
|
42
44
|
billing_info: { [key: string]: any };
|
|
43
45
|
isLoading: any;
|
|
44
46
|
handleSetLoading: (loading: any) => void;
|
|
47
|
+
conditions: any;
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
interface AddressTypes {
|
|
48
|
-
city: string
|
|
49
|
-
line1: string
|
|
50
|
-
state: string
|
|
51
|
-
postal_code: string
|
|
51
|
+
city: string;
|
|
52
|
+
line1: string;
|
|
53
|
+
state: string;
|
|
54
|
+
postal_code: string;
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
const CheckoutForm = ({
|
|
@@ -60,7 +63,8 @@ const CheckoutForm = ({
|
|
|
60
63
|
currency,
|
|
61
64
|
billing_info,
|
|
62
65
|
isLoading = false,
|
|
63
|
-
handleSetLoading = () => {}
|
|
66
|
+
handleSetLoading = () => {},
|
|
67
|
+
conditions = [],
|
|
64
68
|
}: ICheckoutForm) => {
|
|
65
69
|
const stripe = useStripe()
|
|
66
70
|
const elements = useElements()
|
|
@@ -71,9 +75,9 @@ const CheckoutForm = ({
|
|
|
71
75
|
handleSetLoading(true)
|
|
72
76
|
try {
|
|
73
77
|
event.preventDefault()
|
|
74
|
-
|
|
75
|
-
if(!postalCode) {
|
|
76
|
-
setStripeError(
|
|
78
|
+
|
|
79
|
+
if (!postalCode) {
|
|
80
|
+
setStripeError('Please enter your zip code.')
|
|
77
81
|
handleSetLoading(false)
|
|
78
82
|
return
|
|
79
83
|
}
|
|
@@ -84,7 +88,7 @@ const CheckoutForm = ({
|
|
|
84
88
|
handleSetLoading(false)
|
|
85
89
|
return
|
|
86
90
|
}
|
|
87
|
-
|
|
91
|
+
|
|
88
92
|
const card = elements.getElement(CardNumberElement)
|
|
89
93
|
const address: AddressTypes = {
|
|
90
94
|
city: billing_info.city,
|
|
@@ -100,7 +104,7 @@ const CheckoutForm = ({
|
|
|
100
104
|
address,
|
|
101
105
|
},
|
|
102
106
|
})
|
|
103
|
-
|
|
107
|
+
|
|
104
108
|
if (paymentMethodReq.error) {
|
|
105
109
|
setStripeError(paymentMethodReq.error.message || null)
|
|
106
110
|
handleSetLoading(false)
|
|
@@ -108,7 +112,7 @@ const CheckoutForm = ({
|
|
|
108
112
|
}
|
|
109
113
|
|
|
110
114
|
const { error } = await stripe.confirmCardPayment(stripe_client_secret, {
|
|
111
|
-
payment_method: paymentMethodReq.paymentMethod.id
|
|
115
|
+
payment_method: paymentMethodReq.paymentMethod.id,
|
|
112
116
|
})
|
|
113
117
|
|
|
114
118
|
if (error) {
|
|
@@ -116,26 +120,29 @@ const CheckoutForm = ({
|
|
|
116
120
|
handleSetLoading(false)
|
|
117
121
|
return
|
|
118
122
|
}
|
|
119
|
-
|
|
120
|
-
onSubmit(null)
|
|
121
123
|
|
|
122
|
-
|
|
124
|
+
onSubmit(null)
|
|
125
|
+
} catch (e) {
|
|
123
126
|
onSubmit(e)
|
|
124
127
|
}
|
|
125
128
|
}
|
|
126
129
|
|
|
127
130
|
const onChangePostalCode = (e: any) => {
|
|
128
131
|
setPostalCode(e.target.value)
|
|
129
|
-
}
|
|
132
|
+
}
|
|
130
133
|
|
|
131
134
|
useEffect(() => {
|
|
132
135
|
if (typeof window !== 'undefined') {
|
|
133
|
-
const userData = JSON.parse(
|
|
136
|
+
const userData = JSON.parse(
|
|
137
|
+
window.localStorage.getItem('user_data') || ''
|
|
138
|
+
)
|
|
134
139
|
const zipCode = _get(userData, 'zip', '')
|
|
135
140
|
zipCode && setPostalCode(zipCode)
|
|
136
141
|
}
|
|
137
142
|
}, [])
|
|
138
143
|
|
|
144
|
+
const buttonIsDiabled = !stripe || !!error || isLoading
|
|
145
|
+
|
|
139
146
|
return (
|
|
140
147
|
<div className="stripe_payment_container">
|
|
141
148
|
{!!stripeError && (
|
|
@@ -171,9 +178,31 @@ const CheckoutForm = ({
|
|
|
171
178
|
/>
|
|
172
179
|
</label>
|
|
173
180
|
</div>
|
|
174
|
-
|
|
175
|
-
<
|
|
176
|
-
{
|
|
181
|
+
{conditions?.map((checkbox: any) => (
|
|
182
|
+
<div
|
|
183
|
+
className={'billing-info-container__singleField'}
|
|
184
|
+
key={checkbox.id}
|
|
185
|
+
>
|
|
186
|
+
<div className="conditions-block">
|
|
187
|
+
<CheckboxField
|
|
188
|
+
name={checkbox.id}
|
|
189
|
+
label={checkbox.text}
|
|
190
|
+
required={true}
|
|
191
|
+
/>
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
))}
|
|
195
|
+
<div
|
|
196
|
+
className={`payment_button ${
|
|
197
|
+
buttonIsDiabled ? 'disabled-payment-button' : ''
|
|
198
|
+
}`}
|
|
199
|
+
>
|
|
200
|
+
<button disabled={buttonIsDiabled} type="submit">
|
|
201
|
+
{isLoading ? (
|
|
202
|
+
<CircularProgress />
|
|
203
|
+
) : (
|
|
204
|
+
`Pay ${getCurrencySymbolByCurrency(currency)}${total}`
|
|
205
|
+
)}
|
|
177
206
|
</button>
|
|
178
207
|
</div>
|
|
179
208
|
</form>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import './style.css'
|
|
3
|
+
import _has from 'lodash/has'
|
|
4
|
+
import _get from 'lodash/get'
|
|
5
|
+
import Box from '@mui/material/Box'
|
|
6
|
+
import FormControl from '@mui/material/FormControl'
|
|
7
|
+
import MenuItem from '@mui/material/MenuItem'
|
|
8
|
+
import Select from '@mui/material/Select'
|
|
9
|
+
|
|
10
|
+
import { getTicketSelectOptions } from './utils'
|
|
11
|
+
|
|
12
|
+
interface ITicketRowProps {
|
|
13
|
+
ticketTier: any;
|
|
14
|
+
prevTicketTier: any;
|
|
15
|
+
selectedTickets: any;
|
|
16
|
+
handleTicketSelect: any;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const TicketRow = ({
|
|
20
|
+
ticketTier,
|
|
21
|
+
prevTicketTier,
|
|
22
|
+
selectedTickets,
|
|
23
|
+
handleTicketSelect,
|
|
24
|
+
}: ITicketRowProps) => {
|
|
25
|
+
const soldOutMessage = ticketTier.soldOutMessage
|
|
26
|
+
? `${ticketTier.soldOutMessage}`.toUpperCase()
|
|
27
|
+
: 'SOLD OUT'
|
|
28
|
+
const isSalesClosed =
|
|
29
|
+
!ticketTier.salesStarted ||
|
|
30
|
+
ticketTier.salesEnded ||
|
|
31
|
+
!_has(ticketTier, 'maxQuantity') ||
|
|
32
|
+
ticketTier.maxQuantity === 0
|
|
33
|
+
const options = getTicketSelectOptions(
|
|
34
|
+
ticketTier.maxQuantity,
|
|
35
|
+
ticketTier.minQuantity,
|
|
36
|
+
ticketTier.multiplier
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
const onSaleContent = isSalesClosed ? null : (
|
|
40
|
+
<div className="get-tickets">
|
|
41
|
+
<Box className="get-tickets__selectbox">
|
|
42
|
+
<FormControl fullWidth>
|
|
43
|
+
<Select
|
|
44
|
+
value={
|
|
45
|
+
selectedTickets[ticketTier.id]
|
|
46
|
+
? selectedTickets[ticketTier.id]
|
|
47
|
+
: 0
|
|
48
|
+
}
|
|
49
|
+
onChange={handleTicketSelect}
|
|
50
|
+
displayEmpty
|
|
51
|
+
inputProps={{ 'aria-label': 'Without label' }}
|
|
52
|
+
MenuProps={{
|
|
53
|
+
PaperProps: {
|
|
54
|
+
sx: { maxHeight: 150 },
|
|
55
|
+
className: 'get-tickets-paper',
|
|
56
|
+
},
|
|
57
|
+
}}
|
|
58
|
+
>
|
|
59
|
+
{options.map((option, index) => (
|
|
60
|
+
<MenuItem key={index} value={option.value}>
|
|
61
|
+
{option.value}
|
|
62
|
+
</MenuItem>
|
|
63
|
+
))}
|
|
64
|
+
</Select>
|
|
65
|
+
</FormControl>
|
|
66
|
+
</Box>
|
|
67
|
+
</div>
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
let returnValue: any = ''
|
|
71
|
+
|
|
72
|
+
if (ticketTier.sold_out || !ticketTier.displayTicket || ticketTier.soldOut) {
|
|
73
|
+
returnValue = soldOutMessage
|
|
74
|
+
}
|
|
75
|
+
if (!+ticketTier.cost && !+ticketTier.price) {
|
|
76
|
+
returnValue = 'FREE'
|
|
77
|
+
}
|
|
78
|
+
if (ticketTier.displayTicket) {
|
|
79
|
+
returnValue = onSaleContent
|
|
80
|
+
}
|
|
81
|
+
if (_get(prevTicketTier, 'in_stock')) {
|
|
82
|
+
returnValue = 'SOON'
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return <>{returnValue} </>
|
|
86
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import './style.css'
|
|
3
|
+
|
|
4
|
+
import _sortBy from 'lodash/sortBy'
|
|
5
|
+
import { TicketRow } from './TicketRow'
|
|
6
|
+
|
|
7
|
+
interface ITicketsSectionProps {
|
|
8
|
+
ticketsList: any;
|
|
9
|
+
selectedTickets: any;
|
|
10
|
+
handleTicketSelect: any;
|
|
11
|
+
promoCodeIsApplied: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const TicketsSection = ({
|
|
15
|
+
ticketsList,
|
|
16
|
+
selectedTickets,
|
|
17
|
+
handleTicketSelect,
|
|
18
|
+
promoCodeIsApplied,
|
|
19
|
+
}: ITicketsSectionProps) => {
|
|
20
|
+
const sortedTicketsList = _sortBy(ticketsList, 'sortOrder')
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
{sortedTicketsList.map((ticket, i, arr) => {
|
|
24
|
+
const isSoldOut =
|
|
25
|
+
ticket.sold_out || !ticket.displayTicket || ticket.soldOut
|
|
26
|
+
const ticketSelect = (event: any) => {
|
|
27
|
+
const { value } = event.target
|
|
28
|
+
handleTicketSelect(ticket.id, value)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let ticketIsDiscounted = false
|
|
32
|
+
if (
|
|
33
|
+
ticket.oldPrice &&
|
|
34
|
+
promoCodeIsApplied &&
|
|
35
|
+
!isSoldOut &&
|
|
36
|
+
ticket.oldPrice !== ticket.price
|
|
37
|
+
) {
|
|
38
|
+
ticketIsDiscounted = true
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div
|
|
43
|
+
key={ticket.id || ticket.name}
|
|
44
|
+
className={`event-detail__tier ${isSoldOut ? 'disabled' : ''}`}
|
|
45
|
+
>
|
|
46
|
+
<div className="event-detail__tier-name">
|
|
47
|
+
{ticket.displayName || ticket.name}
|
|
48
|
+
</div>
|
|
49
|
+
<div className="event-tickets-container">
|
|
50
|
+
<div className="event-detail__tier-price">
|
|
51
|
+
{ticketIsDiscounted && (
|
|
52
|
+
<p className="old-price">$ {(+ticket.oldPrice).toFixed(2)}</p>
|
|
53
|
+
)}
|
|
54
|
+
<p>
|
|
55
|
+
{isSoldOut
|
|
56
|
+
? 'SOLD OUT'
|
|
57
|
+
: `$ ${(+ticket.cost || +ticket.price).toFixed(2)}`}
|
|
58
|
+
</p>
|
|
59
|
+
{!isSoldOut && (
|
|
60
|
+
<p className="fees">
|
|
61
|
+
{ticket.taxesIncluded ? '(incl. Fees)' : '(excl. Fees)'}
|
|
62
|
+
</p>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
<div
|
|
66
|
+
className="event-detail__tier-state"
|
|
67
|
+
style={{ minWidth: 55 }}
|
|
68
|
+
>
|
|
69
|
+
<TicketRow
|
|
70
|
+
ticketTier={ticket}
|
|
71
|
+
prevTicketTier={arr[i - 1]}
|
|
72
|
+
selectedTickets={selectedTickets}
|
|
73
|
+
handleTicketSelect={ticketSelect}
|
|
74
|
+
/>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
)
|
|
79
|
+
})}
|
|
80
|
+
</>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
@@ -3,150 +3,17 @@ import axios, { AxiosError } from 'axios'
|
|
|
3
3
|
import './style.css'
|
|
4
4
|
|
|
5
5
|
import { getTickets, addToCart, setCustomHeader } from '../../api'
|
|
6
|
-
import _sortBy from 'lodash/sortBy'
|
|
7
6
|
import _get from 'lodash/get'
|
|
8
|
-
import _has from 'lodash/has'
|
|
9
7
|
import _some from 'lodash/some'
|
|
10
8
|
import _find from 'lodash/find'
|
|
11
9
|
import _isEmpty from 'lodash/isEmpty'
|
|
12
10
|
import _filter from 'lodash/filter'
|
|
13
11
|
import _isObject from 'lodash/isObject'
|
|
14
|
-
import Box from '@mui/material/Box'
|
|
15
|
-
import FormControl from '@mui/material/FormControl'
|
|
16
|
-
import MenuItem from '@mui/material/MenuItem'
|
|
17
|
-
import Select from '@mui/material/Select'
|
|
18
12
|
import CircularProgress from '@mui/material/CircularProgress'
|
|
19
13
|
import Button from 'react-bootstrap/Button'
|
|
20
14
|
import jwt_decode from 'jwt-decode'
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
maxCount: number = 10,
|
|
24
|
-
minCount: number = 1,
|
|
25
|
-
multiplier: number = 1
|
|
26
|
-
) => {
|
|
27
|
-
const options = [{ label: 0, value: 0 }]
|
|
28
|
-
for (let i = minCount; i <= Math.min(50, maxCount); i += multiplier) {
|
|
29
|
-
options.push({ label: i, value: i })
|
|
30
|
-
}
|
|
31
|
-
return options
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const computeTierStateLabel = (
|
|
35
|
-
tier: any,
|
|
36
|
-
prevTier: any,
|
|
37
|
-
selectedTickets: any,
|
|
38
|
-
handleTicketSelect: any
|
|
39
|
-
) => {
|
|
40
|
-
const soldOutMessage = tier.soldOutMessage
|
|
41
|
-
? `${tier.soldOutMessage}`.toUpperCase()
|
|
42
|
-
: 'SOLD OUT'
|
|
43
|
-
const isSalesClosed =
|
|
44
|
-
!tier.salesStarted ||
|
|
45
|
-
tier.salesEnded ||
|
|
46
|
-
!_has(tier, 'maxQuantity') ||
|
|
47
|
-
tier.maxQuantity === 0
|
|
48
|
-
const options = getTicketSelectOptions(
|
|
49
|
-
tier.maxQuantity,
|
|
50
|
-
tier.minQuantity,
|
|
51
|
-
tier.multiplier
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
const onSaleContent = isSalesClosed ? null : (
|
|
55
|
-
<div className="get-tickets">
|
|
56
|
-
<Box className="get-tickets__selectbox">
|
|
57
|
-
<FormControl fullWidth>
|
|
58
|
-
<Select
|
|
59
|
-
value={selectedTickets[tier.id] ? selectedTickets[tier.id] : 0}
|
|
60
|
-
onChange={handleTicketSelect}
|
|
61
|
-
displayEmpty
|
|
62
|
-
inputProps={{ 'aria-label': 'Without label' }}
|
|
63
|
-
MenuProps={{
|
|
64
|
-
PaperProps: {
|
|
65
|
-
sx: { maxHeight: 150 },
|
|
66
|
-
className: 'get-tickets-paper',
|
|
67
|
-
},
|
|
68
|
-
}}
|
|
69
|
-
>
|
|
70
|
-
{options.map((option, index) => (
|
|
71
|
-
<MenuItem key={index} value={option.value}>
|
|
72
|
-
{option.value}
|
|
73
|
-
</MenuItem>
|
|
74
|
-
))}
|
|
75
|
-
</Select>
|
|
76
|
-
</FormControl>
|
|
77
|
-
</Box>
|
|
78
|
-
</div>
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
if (tier.sold_out || !tier.displayTicket || tier.soldOut)
|
|
82
|
-
return soldOutMessage
|
|
83
|
-
if (!+tier.cost && !+tier.price) return 'FREE'
|
|
84
|
-
if (tier.displayTicket) return onSaleContent
|
|
85
|
-
if (prevTier.in_stock) return 'SOON'
|
|
86
|
-
|
|
87
|
-
return ''
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const renderTiers = (
|
|
91
|
-
boxOffice: any,
|
|
92
|
-
selectedTickets: any,
|
|
93
|
-
handleTicketSelect: any,
|
|
94
|
-
promoCodeIsApplied: boolean
|
|
95
|
-
) => {
|
|
96
|
-
const sortedBoxOfiice = _sortBy(boxOffice, 'sortOrder')
|
|
97
|
-
const primaryTiers = sortedBoxOfiice.map((tier, i, arr) => {
|
|
98
|
-
const isSoldOut = tier.sold_out || !tier.displayTicket || tier.soldOut
|
|
99
|
-
const ticketSelect = (event: any) => {
|
|
100
|
-
const { value } = event.target
|
|
101
|
-
handleTicketSelect(tier.id, value)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
let ticketIsDiscounted = false
|
|
105
|
-
if (
|
|
106
|
-
tier.oldPrice &&
|
|
107
|
-
promoCodeIsApplied &&
|
|
108
|
-
!isSoldOut &&
|
|
109
|
-
tier.oldPrice !== tier.price
|
|
110
|
-
) {
|
|
111
|
-
ticketIsDiscounted = true
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return (
|
|
115
|
-
<div
|
|
116
|
-
key={tier.id || tier.name}
|
|
117
|
-
className={`event-detail__tier ${isSoldOut ? 'disabled' : ''}`}
|
|
118
|
-
>
|
|
119
|
-
<div className="event-detail__tier-name">
|
|
120
|
-
{tier.displayName || tier.name}
|
|
121
|
-
</div>
|
|
122
|
-
<div className="event-tickets-container">
|
|
123
|
-
<div className="event-detail__tier-price">
|
|
124
|
-
{ticketIsDiscounted && (
|
|
125
|
-
<p className="old-price">$ {(+tier.oldPrice).toFixed(2)}</p>
|
|
126
|
-
)}
|
|
127
|
-
<p>
|
|
128
|
-
{isSoldOut
|
|
129
|
-
? 'SOLD OUT'
|
|
130
|
-
: `$ ${(+tier.cost || +tier.price).toFixed(2)}`}
|
|
131
|
-
</p>
|
|
132
|
-
{!isSoldOut && (
|
|
133
|
-
<p className='fees'>{tier.taxesIncluded ? '(incl. Fees)' : '(excl. Fees)'}</p>
|
|
134
|
-
)}
|
|
135
|
-
</div>
|
|
136
|
-
<div className="event-detail__tier-state" style={{ minWidth: 55 }}>
|
|
137
|
-
{computeTierStateLabel(
|
|
138
|
-
tier,
|
|
139
|
-
arr[i - 1],
|
|
140
|
-
selectedTickets,
|
|
141
|
-
ticketSelect
|
|
142
|
-
)}
|
|
143
|
-
</div>
|
|
144
|
-
</div>
|
|
145
|
-
</div>
|
|
146
|
-
)
|
|
147
|
-
})
|
|
148
|
-
return primaryTiers
|
|
149
|
-
}
|
|
15
|
+
import { TicketsSection } from './TicketsSection'
|
|
16
|
+
import WaitingList from '../waitingList'
|
|
150
17
|
|
|
151
18
|
function Loader() {
|
|
152
19
|
return (
|
|
@@ -160,6 +27,7 @@ interface CartSuccess {
|
|
|
160
27
|
skip_billing_page: boolean;
|
|
161
28
|
names_required: boolean;
|
|
162
29
|
age_required: boolean;
|
|
30
|
+
event_id: string;
|
|
163
31
|
}
|
|
164
32
|
|
|
165
33
|
export interface IGetTickets {
|
|
@@ -170,6 +38,8 @@ export interface IGetTickets {
|
|
|
170
38
|
onAddToCartError: (e: AxiosError) => void;
|
|
171
39
|
onGetTicketsSuccess: (response: any) => void;
|
|
172
40
|
onGetTicketsError: (e: AxiosError) => void;
|
|
41
|
+
|
|
42
|
+
theme?: 'light' | 'dark';
|
|
173
43
|
}
|
|
174
44
|
|
|
175
45
|
export interface ITicket {
|
|
@@ -189,11 +59,13 @@ export const TicketsContainer = ({
|
|
|
189
59
|
onAddToCartError = () => {},
|
|
190
60
|
onGetTicketsSuccess = () => {},
|
|
191
61
|
onGetTicketsError = () => {},
|
|
62
|
+
theme = 'light',
|
|
192
63
|
}: IGetTickets) => {
|
|
193
64
|
const [selectedTickets, setSelectedTickets] = useState(
|
|
194
65
|
{} as ISelectedTickets
|
|
195
66
|
)
|
|
196
67
|
const [tickets, setTickets] = useState([] as ITicket[])
|
|
68
|
+
const [showWaitingList, setShowWaitingList] = useState(false)
|
|
197
69
|
const [isLoading, setIsLoading] = useState(false)
|
|
198
70
|
const [handleBookIsLoading, setHandleBookIsLoading] = useState(false)
|
|
199
71
|
const [promoCode, setPromoCode] = useState('')
|
|
@@ -223,11 +95,8 @@ export const TicketsContainer = ({
|
|
|
223
95
|
setCustomHeader(response)
|
|
224
96
|
const attributes = _get(response, 'data.data.attributes')
|
|
225
97
|
setPromoCodeIsApplied(attributes.ValidPromoCode)
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
item => _isObject(item)
|
|
229
|
-
)
|
|
230
|
-
setTickets(tickets)
|
|
98
|
+
setTickets(_get(attributes, 'tickets'))
|
|
99
|
+
setShowWaitingList(attributes.showWaitingList)
|
|
231
100
|
onGetTicketsSuccess(response.data)
|
|
232
101
|
}
|
|
233
102
|
} catch (e) {
|
|
@@ -290,6 +159,7 @@ export const TicketsContainer = ({
|
|
|
290
159
|
names_required:
|
|
291
160
|
result?.data?.data?.attributes?.names_required ?? false,
|
|
292
161
|
age_required: result?.data?.data?.attributes?.age_required ?? false,
|
|
162
|
+
event_id: String(eventId)
|
|
293
163
|
})
|
|
294
164
|
}
|
|
295
165
|
} catch (e) {
|
|
@@ -307,80 +177,86 @@ export const TicketsContainer = ({
|
|
|
307
177
|
)
|
|
308
178
|
|
|
309
179
|
return (
|
|
310
|
-
<div className=
|
|
180
|
+
<div className={`get-tickets-page ${theme}`} style={contentStyle}>
|
|
311
181
|
{isLoading ? (
|
|
312
182
|
<Loader />
|
|
313
183
|
) : (
|
|
314
|
-
|
|
315
|
-
{
|
|
316
|
-
tickets
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
</div>
|
|
325
|
-
) : null}
|
|
326
|
-
{showPromoInput && (
|
|
327
|
-
<div className="promo-code-block">
|
|
328
|
-
<input
|
|
329
|
-
placeholder="Promo Code"
|
|
330
|
-
onChange={e => {
|
|
331
|
-
setPromoCode(e.target.value)
|
|
332
|
-
}}
|
|
333
|
-
onKeyPress={event => {
|
|
334
|
-
if (event.key === 'Enter') {
|
|
335
|
-
setPromoCodeUpdated(promoCode)
|
|
336
|
-
}
|
|
337
|
-
}}
|
|
184
|
+
<>
|
|
185
|
+
{showWaitingList ? (
|
|
186
|
+
<WaitingList tickets={tickets} />
|
|
187
|
+
) : (
|
|
188
|
+
<div>
|
|
189
|
+
<TicketsSection
|
|
190
|
+
ticketsList={tickets}
|
|
191
|
+
selectedTickets={selectedTickets}
|
|
192
|
+
handleTicketSelect={handleTicketSelect}
|
|
193
|
+
promoCodeIsApplied={promoCodeIsApplied}
|
|
338
194
|
/>
|
|
339
|
-
|
|
340
|
-
className="
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
195
|
+
{promoCodeIsApplied ? (
|
|
196
|
+
<div className="alert-info">
|
|
197
|
+
Your promo code was applied successfully.
|
|
198
|
+
</div>
|
|
199
|
+
) : null}
|
|
200
|
+
{showPromoInput && (
|
|
201
|
+
<div className="promo-code-block">
|
|
202
|
+
<input
|
|
203
|
+
placeholder="Promo Code"
|
|
204
|
+
onChange={e => {
|
|
205
|
+
setPromoCode(e.target.value)
|
|
206
|
+
}}
|
|
207
|
+
onKeyPress={event => {
|
|
208
|
+
if (event.key === 'Enter') {
|
|
209
|
+
setPromoCodeUpdated(promoCode)
|
|
210
|
+
}
|
|
211
|
+
}}
|
|
212
|
+
/>
|
|
213
|
+
<Button
|
|
214
|
+
className="promo-apply-button"
|
|
215
|
+
placeholder="Promo Code"
|
|
216
|
+
onClick={() => {
|
|
217
|
+
setPromoCodeUpdated(promoCode)
|
|
218
|
+
}}
|
|
219
|
+
>
|
|
220
|
+
Apply
|
|
221
|
+
</Button>
|
|
222
|
+
</div>
|
|
223
|
+
)}
|
|
224
|
+
{!showPromoInput && !isAllTicketsSoldOut ? (
|
|
225
|
+
<Button
|
|
226
|
+
className="promo-code-button"
|
|
227
|
+
placeholder="Promo Codes"
|
|
228
|
+
onClick={() => {
|
|
229
|
+
setShowPromoInput(true)
|
|
230
|
+
}}
|
|
231
|
+
>
|
|
232
|
+
Got a promo code? Click here
|
|
233
|
+
</Button>
|
|
234
|
+
) : null}
|
|
235
|
+
<div className="test v1.0.19" style={{ display: 'none' }} />
|
|
236
|
+
{!isAllTicketsSoldOut && (
|
|
237
|
+
<Button
|
|
238
|
+
aria-hidden={true}
|
|
239
|
+
className={`book-button ${
|
|
240
|
+
handleBookIsLoading ||
|
|
241
|
+
_isEmpty(selectedTickets) ||
|
|
242
|
+
Object.values(selectedTickets)[0] === 0
|
|
243
|
+
? 'disabled'
|
|
244
|
+
: ''
|
|
245
|
+
}`}
|
|
246
|
+
onClick={
|
|
247
|
+
!handleBookIsLoading &&
|
|
248
|
+
!_isEmpty(selectedTickets) &&
|
|
249
|
+
Object.values(selectedTickets)[0] > 0
|
|
250
|
+
? handleBook
|
|
251
|
+
: () => {}
|
|
252
|
+
}
|
|
253
|
+
>
|
|
254
|
+
{getTicketsLabel || 'GET TICKETS'}
|
|
255
|
+
</Button>
|
|
256
|
+
)}
|
|
348
257
|
</div>
|
|
349
258
|
)}
|
|
350
|
-
|
|
351
|
-
<Button
|
|
352
|
-
className="promo-code-button"
|
|
353
|
-
placeholder="Promo Codes"
|
|
354
|
-
onClick={() => {
|
|
355
|
-
setShowPromoInput(true)
|
|
356
|
-
}}
|
|
357
|
-
>
|
|
358
|
-
Got a promo code? Click here
|
|
359
|
-
</Button>
|
|
360
|
-
) : null}
|
|
361
|
-
<div className="test v1.0.19" style={{ display: 'none' }} />
|
|
362
|
-
{!isAllTicketsSoldOut && (
|
|
363
|
-
<Button
|
|
364
|
-
aria-hidden={true}
|
|
365
|
-
className={`book-button ${
|
|
366
|
-
handleBookIsLoading ||
|
|
367
|
-
_isEmpty(selectedTickets) ||
|
|
368
|
-
Object.values(selectedTickets)[0] === 0
|
|
369
|
-
? 'disabled'
|
|
370
|
-
: ''
|
|
371
|
-
}`}
|
|
372
|
-
onClick={
|
|
373
|
-
!handleBookIsLoading &&
|
|
374
|
-
!_isEmpty(selectedTickets) &&
|
|
375
|
-
Object.values(selectedTickets)[0] > 0
|
|
376
|
-
? handleBook
|
|
377
|
-
: () => {}
|
|
378
|
-
}
|
|
379
|
-
>
|
|
380
|
-
{getTicketsLabel || 'GET TICKETS'}
|
|
381
|
-
</Button>
|
|
382
|
-
)}
|
|
383
|
-
</div>
|
|
259
|
+
</>
|
|
384
260
|
)}
|
|
385
261
|
</div>
|
|
386
262
|
)
|