tf-checkout-react 1.0.84 → 1.0.88

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.
@@ -11,6 +11,7 @@ import {
11
11
  } from '../../api'
12
12
  import _get from 'lodash/get'
13
13
  import _some from 'lodash/some'
14
+ import _every from 'lodash/every'
14
15
  import _find from 'lodash/find'
15
16
  import _isEmpty from 'lodash/isEmpty'
16
17
  import CircularProgress from '@mui/material/CircularProgress'
@@ -21,7 +22,7 @@ import WaitingList from '../waitingList'
21
22
  import { PromoCodeSection } from './PromoCodeSection'
22
23
  import { LoginModal } from '../loginModal'
23
24
  import Countdown from '../countdown'
24
- import { createCheckoutDataBodyWithDefaultHolder } from '../../utils'
25
+ import { createCheckoutDataBodyWithDefaultHolder, getQueryVariable } from '../../utils'
25
26
  import { ThemeProvider } from '@mui/private-theming'
26
27
  import { createTheme, ThemeOptions } from '@mui/material'
27
28
  import { CSSProperties } from '@mui/styles'
@@ -58,6 +59,7 @@ export interface IGetTickets {
58
59
  themeOptions?: ThemeOptions & { input?: CSSProperties; checkbox?: CSSProperties }
59
60
  isAccessCodeEnabled?: boolean;
60
61
  hideSessionButtons?: boolean;
62
+ hideWaitingList?: boolean;
61
63
  }
62
64
 
63
65
  export interface ITicket {
@@ -83,7 +85,8 @@ export const TicketsContainer = ({
83
85
  isPromotionsEnabled = true,
84
86
  themeOptions,
85
87
  isAccessCodeEnabled = false,
86
- hideSessionButtons = false
88
+ hideSessionButtons = false,
89
+ hideWaitingList = false
87
90
  }: IGetTickets) => {
88
91
  const [selectedTickets, setSelectedTickets] = useState(
89
92
  {} as ISelectedTickets
@@ -99,7 +102,7 @@ export const TicketsContainer = ({
99
102
  const [isLoading, setIsLoading] = useState(false)
100
103
  const [handleBookIsLoading, setHandleBookIsLoading] = useState(false)
101
104
  const [promoCode, setPromoCode] = useState('')
102
- const [promoCodeUpdated, setPromoCodeUpdated] = useState(queryPromoCode)
105
+ const [promoCodeUpdated, setPromoCodeUpdated] = useState(getQueryVariable('r') || queryPromoCode)
103
106
  const [showPromoInput, setShowPromoInput] = useState(false)
104
107
  const [promoCodeIsApplied, setPromoCodeIsApplied] = useState(false)
105
108
 
@@ -279,9 +282,14 @@ export const TicketsContainer = ({
279
282
  getTicketsApi()
280
283
  }
281
284
 
282
- const isAllTicketsSoldOut = !_some(
285
+ const isAllTicketsSoldOut = _every(
283
286
  tickets,
284
- item => !(item.sold_out || item.soldOut)
287
+ item => (item.sold_out || item.soldOut)
288
+ )
289
+
290
+ const isTicketOnSale = _some(
291
+ tickets,
292
+ item => (item.salesStarted && !item.salesEnded && !item.soldOut)
285
293
  )
286
294
 
287
295
  const themeMui = createTheme(themeOptions)
@@ -321,8 +329,8 @@ export const TicketsContainer = ({
321
329
  promoCodeIsApplied={promoCodeIsApplied}
322
330
  />
323
331
  {event?.salesEnded ? (
324
- <p>Sales for this event are closed.</p>
325
- ) : event?.salesStart ? (
332
+ <p className='event-closed-message'>Sales for this event are closed.</p>
333
+ ) : !event?.salesStarted && event?.salesStart ? (
326
334
  <Countdown
327
335
  startDate={event.salesStart}
328
336
  timezone={event.timezone}
@@ -331,7 +339,7 @@ export const TicketsContainer = ({
331
339
  callback={updateTickets}
332
340
  />
333
341
  ) : null}
334
- {showWaitingList && event.salesStarted && (
342
+ {showWaitingList && event.salesStarted && !hideWaitingList && (
335
343
  <WaitingList tickets={tickets} eventId={eventId} />
336
344
  )}
337
345
  <PromoCodeSection
@@ -345,7 +353,7 @@ export const TicketsContainer = ({
345
353
  isAccessCodeEnabled={isAccessCodeEnabled}
346
354
  isAllTicketsSoldOut={isAllTicketsSoldOut}
347
355
  />
348
- {!isAllTicketsSoldOut && (
356
+ {(isTicketOnSale || !event?.salesEnded) && (
349
357
  <Button
350
358
  aria-hidden={true}
351
359
  className={`book-button ${
@@ -174,3 +174,8 @@ body {
174
174
  .hidden {
175
175
  display: none;
176
176
  }
177
+
178
+ .event-closed-message {
179
+ font-family: 'Bebas Neue';
180
+ letter-spacing: 0.5px;
181
+ }
@@ -0,0 +1,70 @@
1
+ import React, { useState } from 'react'
2
+ import Countdown from 'react-countdown'
3
+ import { showZero } from '../../utils/showZero'
4
+ import './style.css'
5
+
6
+ export interface ITimerWidgetPage {
7
+ expires_at: number;
8
+ buyLoading?: boolean;
9
+ onCountdownFinish?: () => void;
10
+ }
11
+
12
+ export interface IRenderer {
13
+ minutes: number;
14
+ seconds: number;
15
+ completed: number;
16
+ handleCountdownFinish: () => void;
17
+ }
18
+
19
+ const TimerWidget = ({
20
+ expires_at,
21
+ buyLoading,
22
+ onCountdownFinish = () => {},
23
+ }: ITimerWidgetPage) => {
24
+ const [showTimer, setShowTimer] = useState(true)
25
+
26
+ const handleCountdownFinish = () => {
27
+ setShowTimer(false)
28
+ if (!buyLoading) {
29
+ onCountdownFinish()
30
+ }
31
+ }
32
+
33
+ const renderer = ({
34
+ minutes,
35
+ seconds,
36
+ completed,
37
+ handleCountdownFinish,
38
+ }: IRenderer) => {
39
+ if (completed) {
40
+ handleCountdownFinish()
41
+ return null
42
+ }
43
+ return (
44
+ <span>
45
+ {showZero(minutes)}:{showZero(seconds)}
46
+ </span>
47
+ )
48
+ }
49
+
50
+ return showTimer && !!expires_at ? (
51
+ <div className="timer">
52
+ <div className="toast-message">
53
+ <p>Please complete your purchase before the timer reaches zero.</p>
54
+ <p className="countdown">
55
+ <Countdown
56
+ date={Date.now() + expires_at * 1000}
57
+ renderer={(props: any) =>
58
+ renderer({
59
+ ...props,
60
+ handleCountdownFinish,
61
+ })
62
+ }
63
+ />
64
+ </p>
65
+ </div>
66
+ </div>
67
+ ) : null
68
+ }
69
+
70
+ export default TimerWidget
@@ -0,0 +1,26 @@
1
+ .timer {
2
+ position: absolute;
3
+ pointer-events: auto;
4
+ background-color: #000000;
5
+ overflow: hidden;
6
+ margin: 0 0 6px;
7
+ padding: 15px 15px 15px 50px;
8
+ width: 300px;
9
+ -moz-border-radius: 3px;
10
+ -webkit-border-radius: 3px;
11
+ border-radius: 3px;
12
+ background-position: 15px center;
13
+ background-repeat: no-repeat;
14
+ -moz-box-shadow: 0 0 12px #999;
15
+ -webkit-box-shadow: 0 0 12px #999;
16
+ box-shadow: 0 0 12px #999;
17
+ max-width: 300px;
18
+ color: #fff;
19
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=);
20
+ right: 15px;
21
+ }
22
+
23
+ .timer .countdown {
24
+ font-weight: bold;
25
+ margin-top: 10px;
26
+ }
@@ -33,8 +33,14 @@ const generateQuantity = (n: number) => {
33
33
  }
34
34
  return quantityList
35
35
  }
36
-
36
+
37
37
  const WaitingList = ({ tickets = {}, eventId }: WaitingListProps) => {
38
+ const isWindowDefined = typeof window !== 'undefined'
39
+ const userData =
40
+ isWindowDefined && window.localStorage.getItem('user_data')
41
+ ? JSON.parse(window.localStorage.getItem('user_data') || '')
42
+ : {}
43
+
38
44
  const [showSuccessMessage, setShowSuccessMessage] = useState(false)
39
45
  const [loading, setLoading] = useState(false)
40
46
  const ticketTypesList = Object.values(tickets).map((d: any) => ({
@@ -77,9 +83,9 @@ const WaitingList = ({ tickets = {}, eventId }: WaitingListProps) => {
77
83
  initialValues={{
78
84
  ticketTypeId: '',
79
85
  quantity: '',
80
- firstName: '',
81
- lastName: '',
82
- email: '',
86
+ firstName: userData.first_name || '',
87
+ lastName: userData.last_name || '',
88
+ email: userData.email || '',
83
89
  }}
84
90
  onSubmit={handleSubmit}
85
91
  >
@@ -90,7 +96,7 @@ const WaitingList = ({ tickets = {}, eventId }: WaitingListProps) => {
90
96
  <div className="field-item">
91
97
  <Field
92
98
  name="ticketTypeId"
93
- label="Ticket types"
99
+ label="Type of Ticket"
94
100
  type="select"
95
101
  component={CustomField}
96
102
  selectOptions={[
@@ -102,7 +108,7 @@ const WaitingList = ({ tickets = {}, eventId }: WaitingListProps) => {
102
108
  <div className="field-item">
103
109
  <Field
104
110
  name="quantity"
105
- label="Quantity"
111
+ label="Quantity Requested"
106
112
  type="select"
107
113
  component={CustomField}
108
114
  selectOptions={[
@@ -0,0 +1,10 @@
1
+ import _isNumber from 'lodash/isNumber'
2
+
3
+ export const showZero = (value = 0) => {
4
+ const intNumber = Number(value)
5
+ return _isNumber(intNumber)
6
+ ? intNumber >= 0 && intNumber < 10
7
+ ? '0' + intNumber
8
+ : intNumber
9
+ : null
10
+ }