tf-checkout-react 1.0.99 → 1.0.100-beta.2

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 (117) hide show
  1. package/README.md +278 -1
  2. package/dist/api/index.d.ts +31 -26
  3. package/dist/components/account-settings/index.d.ts +3 -0
  4. package/dist/components/billing-info-container/index.d.ts +5 -5
  5. package/dist/components/billing-info-container/utils.d.ts +1 -0
  6. package/dist/components/common/CustomField.d.ts +1 -1
  7. package/dist/components/common/DatePickerField.d.ts +14 -0
  8. package/dist/components/common/RedirectModal.d.ts +7 -0
  9. package/dist/components/common/SnackbarAlert.d.ts +13 -0
  10. package/dist/components/confirmationContainer/index.d.ts +2 -1
  11. package/dist/components/countdown/index.d.ts +4 -1
  12. package/dist/components/myTicketsContainer/tableConfig.d.ts +0 -1
  13. package/dist/components/orderDetailsContainer/index.d.ts +5 -1
  14. package/dist/components/orderDetailsContainer/ticketsTable.d.ts +4 -1
  15. package/dist/components/paymentContainer/index.d.ts +3 -1
  16. package/dist/components/rsvpContainer/index.d.ts +7 -0
  17. package/dist/components/stripePayment/index.d.ts +2 -1
  18. package/dist/components/ticketResale/index.d.ts +5 -3
  19. package/dist/components/ticketsContainer/AccessCodeSection.d.ts +7 -0
  20. package/dist/components/ticketsContainer/PromoCodeSection.d.ts +6 -9
  21. package/dist/components/ticketsContainer/TicketsSection.d.ts +5 -3
  22. package/dist/components/ticketsContainer/index.d.ts +13 -2
  23. package/dist/components/timerWidget/index.d.ts +3 -3
  24. package/dist/env.d.ts +1 -0
  25. package/dist/images/cross.svg +44 -0
  26. package/dist/images/done.svg +3 -3
  27. package/dist/index.d.ts +2 -0
  28. package/dist/tf-checkout-react.cjs.development.js +1400 -575
  29. package/dist/tf-checkout-react.cjs.development.js.map +1 -1
  30. package/dist/tf-checkout-react.cjs.production.min.js +1 -1
  31. package/dist/tf-checkout-react.cjs.production.min.js.map +1 -1
  32. package/dist/tf-checkout-react.esm.js +1409 -586
  33. package/dist/tf-checkout-react.esm.js.map +1 -1
  34. package/dist/tf-checkout-styles.css +1 -1
  35. package/dist/utils/cookies.d.ts +3 -0
  36. package/dist/utils/createCheckoutDataBodyWithDefaultHolder.d.ts +6 -1
  37. package/dist/utils/downloadPDF.d.ts +1 -1
  38. package/dist/utils/getDomain.d.ts +1 -0
  39. package/dist/utils/index.d.ts +2 -0
  40. package/package.json +89 -89
  41. package/src/.DS_Store +0 -0
  42. package/src/.d.ts +2 -2
  43. package/src/api/index.ts +313 -278
  44. package/src/assets/images/cross.svg +44 -0
  45. package/src/assets/images/done.svg +3 -3
  46. package/src/components/.DS_Store +0 -0
  47. package/src/components/account-settings/index.tsx +161 -0
  48. package/src/components/account-settings/style.css +200 -0
  49. package/src/components/billing-info-container/index.tsx +821 -777
  50. package/src/components/billing-info-container/style.css +106 -106
  51. package/src/components/billing-info-container/utils.ts +233 -223
  52. package/src/components/common/CheckboxField.tsx +41 -41
  53. package/src/components/common/CustomField.tsx +87 -84
  54. package/src/components/common/DatePickerField.tsx +98 -0
  55. package/src/components/common/FormikPhoneNumberField.tsx +51 -51
  56. package/src/components/common/Loader.tsx +9 -9
  57. package/src/components/common/RadioField.tsx +35 -35
  58. package/src/components/common/RedirectModal.tsx +43 -0
  59. package/src/components/common/SelectField.tsx +80 -80
  60. package/src/components/common/SnackbarAlert.tsx +54 -0
  61. package/src/components/common/dist/PhoneNumberField.js +96 -0
  62. package/src/components/common/index.tsx +4 -4
  63. package/src/components/confirmModal/index.tsx +51 -51
  64. package/src/components/confirmModal/style.css +21 -21
  65. package/src/components/confirmationContainer/config.ts +72 -72
  66. package/src/components/confirmationContainer/index.tsx +197 -194
  67. package/src/components/confirmationContainer/social-buttons.tsx +94 -94
  68. package/src/components/confirmationContainer/style.css +202 -202
  69. package/src/components/countdown/index.tsx +100 -89
  70. package/src/components/countdown/style.css +9 -9
  71. package/src/components/index.ts +7 -7
  72. package/src/components/loginModal/index.tsx +171 -209
  73. package/src/components/loginModal/style.css +71 -71
  74. package/src/components/myTicketsContainer/index.tsx +201 -137
  75. package/src/components/myTicketsContainer/row.tsx +41 -41
  76. package/src/components/myTicketsContainer/style.css +40 -40
  77. package/src/components/myTicketsContainer/tableConfig.tsx +32 -34
  78. package/src/components/orderDetailsContainer/index.tsx +289 -249
  79. package/src/components/orderDetailsContainer/style.css +73 -73
  80. package/src/components/orderDetailsContainer/ticketsTable.tsx +177 -124
  81. package/src/components/paymentContainer/index.tsx +352 -284
  82. package/src/components/registerModal/index.tsx +183 -190
  83. package/src/components/rsvpContainer/index.tsx +126 -0
  84. package/src/components/stripePayment/index.tsx +258 -253
  85. package/src/components/stripePayment/style.css +60 -60
  86. package/src/components/ticketResale/index.tsx +74 -56
  87. package/src/components/ticketResaleModal/index.tsx +213 -210
  88. package/src/components/ticketResaleModal/style.css +28 -28
  89. package/src/components/ticketsContainer/AccessCodeSection.tsx +50 -0
  90. package/src/components/ticketsContainer/PromoCodeSection.tsx +89 -99
  91. package/src/components/ticketsContainer/ReferralLogic.tsx +31 -33
  92. package/src/components/ticketsContainer/TicketRow.tsx +89 -83
  93. package/src/components/ticketsContainer/TicketsSection.tsx +87 -81
  94. package/src/components/ticketsContainer/index.tsx +506 -409
  95. package/src/components/ticketsContainer/style.css +181 -181
  96. package/src/components/ticketsContainer/utils.ts +11 -11
  97. package/src/components/timerWidget/index.tsx +87 -70
  98. package/src/components/timerWidget/style.css +34 -26
  99. package/src/components/waitingList/index.tsx +178 -178
  100. package/src/components/waitingList/style.css +26 -26
  101. package/src/env.ts +20 -19
  102. package/src/index.ts +15 -13
  103. package/src/normalizers/index.ts +45 -45
  104. package/src/types/billing-info-data.ts +37 -37
  105. package/src/types/payment-field.ts +7 -7
  106. package/src/types/referral-promotion.ts +7 -7
  107. package/src/utils/cookies.ts +42 -0
  108. package/src/utils/createCheckoutDataBodyWithDefaultHolder.ts +71 -59
  109. package/src/utils/downloadPDF.tsx +52 -30
  110. package/src/utils/formikErrorFocus.ts +24 -24
  111. package/src/utils/getDomain.ts +15 -0
  112. package/src/utils/getImage.ts +14 -14
  113. package/src/utils/getQueryVariable.ts +13 -13
  114. package/src/utils/index.ts +7 -5
  115. package/src/utils/setConfigs.ts +26 -26
  116. package/src/utils/showZero.tsx +10 -10
  117. package/src/validators/index.ts +20 -20
@@ -0,0 +1,50 @@
1
+ import React from 'react'
2
+ import Button from 'react-bootstrap/Button'
3
+
4
+ export interface IAccessCodeSectionProps {
5
+ code: string;
6
+ setCode: (value: string) => void;
7
+ updateTickets: (value: boolean, type?: string) => void;
8
+ }
9
+
10
+ // This section is seperate because additional changes layter may be applied to Access Code
11
+
12
+ export const AccessCodeSection = ({
13
+ code,
14
+ setCode,
15
+ updateTickets
16
+ }: IAccessCodeSectionProps) => {
17
+ const isAccessCodeHasValue = !!code.trim()
18
+
19
+ return (
20
+ <div className="access-code-block">
21
+ <div className="access-code-block">
22
+ <p className="access-code-text">
23
+ Access code required
24
+ </p>
25
+ </div>
26
+ <input
27
+ className="access-code-input"
28
+ placeholder=""
29
+ onChange={e => {
30
+ setCode(e.target.value)
31
+ }}
32
+ onKeyPress={event => {
33
+ if (event.key === 'Enter' && isAccessCodeHasValue) {
34
+ updateTickets(true)
35
+ }
36
+ }}
37
+ />
38
+ <Button
39
+ className="access-submit-button"
40
+ onClick={() => {
41
+ if (isAccessCodeHasValue) {
42
+ updateTickets(true)
43
+ }
44
+ }}
45
+ >
46
+ ENTER
47
+ </Button>
48
+ </div>
49
+ )
50
+ }
@@ -1,99 +1,89 @@
1
- import React from 'react'
2
- import Button from 'react-bootstrap/Button'
3
- import SVG from 'react-inlinesvg'
4
- import { getImage } from '../../utils/getImage'
5
- import { Loader } from '../common/index'
6
-
7
- export interface IPromoCodeSectionProps {
8
- promoCode: string;
9
- promoCodeIsApplied: boolean;
10
- showPromoInput: boolean;
11
- isPromotionsEnabled: boolean;
12
- isAllTicketsSoldOut: boolean;
13
- isAccessCodeEnabled?: boolean;
14
- isPromoLoading?: boolean;
15
- setPromoCode: (value: string) => void;
16
- setPromoCodeUpdated: (value: string) => void;
17
- setShowPromoInput: (value: boolean) => void;
18
- }
19
-
20
- export const PromoCodeSection = ({
21
- promoCode,
22
- promoCodeIsApplied,
23
- showPromoInput,
24
- isPromotionsEnabled,
25
- setPromoCode,
26
- setPromoCodeUpdated,
27
- setShowPromoInput,
28
- isAccessCodeEnabled,
29
- isPromoLoading,
30
- }: IPromoCodeSectionProps) => {
31
- const isPromoCodeHasValue = !!promoCode.trim()
32
-
33
- const renderInputField = () => {
34
- return (
35
- <div className="promo-code-block">
36
- <div className="promo-code-block">
37
- <p className="promo-code-text">
38
- { isAccessCodeEnabled ? 'Access code required' : 'Promo code'}
39
- </p>
40
-
41
- </div>
42
- <input
43
- className="promo-code-input"
44
- placeholder=""
45
- onChange={e => {
46
- setPromoCode(e.target.value)
47
- }}
48
- onKeyPress={event => {
49
- if (event.key === 'Enter' && isPromoCodeHasValue) {
50
- setPromoCodeUpdated(promoCode)
51
- setShowPromoInput(false)
52
- }
53
- }}
54
- />
55
- <Button
56
- className="promo-submit-button"
57
- onClick={() => {
58
- if (isPromoCodeHasValue) {
59
- setPromoCodeUpdated(promoCode)
60
- setShowPromoInput(false)
61
- }
62
- }}
63
- >
64
- {isAccessCodeEnabled ? 'ENTER' : 'APPLY'}
65
- </Button>
66
- </div>
67
- )
68
- }
69
-
70
- return isPromoLoading ? <Loader /> : (
71
- <div >
72
- {promoCodeIsApplied ? (
73
- <div className="alert-info">
74
- <SVG
75
- src={getImage('done.svg')}
76
- preProcessor={(code) => code.replace(/fill=".*?"/g, 'fill="currentColor"')}
77
- />
78
- <p className="promo-code-success">PROMO CODE APPLIED SUCCESSFULLY</p>
79
- </div>
80
- ) : null}
81
- {showPromoInput && (
82
- renderInputField()
83
- )}
84
- {isPromotionsEnabled && !showPromoInput && !isAccessCodeEnabled ? (
85
- <Button
86
- className="promo-code-button"
87
- placeholder="Promo Codes"
88
- onClick={() => {
89
- setShowPromoInput(true)
90
- }}
91
- >
92
- Got a promo code? Click here
93
- </Button>
94
- ) : !isPromotionsEnabled && !showPromoInput && isAccessCodeEnabled && !promoCodeIsApplied ? renderInputField() :
95
- null
96
- }
97
- </div>
98
- )
99
- }
1
+ import React from 'react'
2
+ import Button from 'react-bootstrap/Button'
3
+ import SVG from 'react-inlinesvg'
4
+ import { getImage } from '../../utils/getImage'
5
+
6
+ export interface IPromoCodeSectionProps {
7
+ code: string;
8
+ codeIsApplied: boolean;
9
+ showPromoInput: boolean;
10
+ setCode: (value: string) => void;
11
+ setShowPromoInput: (value: boolean) => void;
12
+ updateTickets: (value: boolean, type: string) => void;
13
+ setCodeIsApplied: (value: boolean) => void;
14
+ }
15
+
16
+ export const PromoCodeSection = ({
17
+ code,
18
+ codeIsApplied,
19
+ showPromoInput,
20
+ setCode,
21
+ setShowPromoInput,
22
+ updateTickets,
23
+ setCodeIsApplied
24
+ }: IPromoCodeSectionProps) => {
25
+ const isPromoCodeHasValue = !!code.trim()
26
+
27
+ const renderInputField = () => {
28
+ return (
29
+ <div className="promo-code-block">
30
+ <div className="promo-code-block">
31
+ <p className="promo-code-text">Promo code</p>
32
+ </div>
33
+ <input
34
+ className="promo-code-input"
35
+ placeholder=""
36
+ onChange={e => {
37
+ setCode(e.target.value)
38
+ }}
39
+ onKeyPress={event => {
40
+ if (event.key === 'Enter' && isPromoCodeHasValue) {
41
+ setShowPromoInput(false)
42
+ updateTickets(true, 'promo')
43
+ }
44
+ }}
45
+ />
46
+ <Button
47
+ className="promo-submit-button"
48
+ onClick={() => {
49
+ if (isPromoCodeHasValue) {
50
+ setShowPromoInput(false)
51
+ updateTickets(true, 'promo')
52
+ }
53
+ }}
54
+ >
55
+ APPLY
56
+ </Button>
57
+ </div>
58
+ )
59
+ }
60
+
61
+ return (
62
+ <div>
63
+ {codeIsApplied ? (
64
+ <div className="alert-info">
65
+ <SVG
66
+ src={getImage('done.svg')}
67
+ preProcessor={code =>
68
+ code.replace(/fill=".*?"/g, 'fill="currentColor"')
69
+ }
70
+ />
71
+ <p className="promo-code-success">PROMO CODE APPLIED SUCCESSFULLY</p>
72
+ </div>
73
+ ) : null}
74
+ {!showPromoInput && (
75
+ <Button
76
+ className="promo-code-button"
77
+ placeholder="Promo Codes"
78
+ onClick={() => {
79
+ setCodeIsApplied(false)
80
+ setShowPromoInput(true)
81
+ }}
82
+ >
83
+ Got a promo code? Click here
84
+ </Button>
85
+ )}
86
+ {showPromoInput && renderInputField()}
87
+ </div>
88
+ )
89
+ }
@@ -1,33 +1,31 @@
1
- import { useEffect } from 'react'
2
- import { postReferralVisits } from '../../api'
3
-
4
- interface IReferralLogicProps {
5
- eventId: string | number;
6
- }
7
-
8
- export const ReferralLogic = (props: IReferralLogicProps) => {
9
- const { eventId } = props
10
- const isWindowDefined = typeof window !== 'undefined'
11
-
12
- useEffect(() => {
13
- if (isWindowDefined) {
14
- const params: URLSearchParams = new URL(`${window.location}`).searchParams
15
- const referralId = params.get('ttf_r') || ''
16
- const isAlreadyCounted = !!localStorage.getItem('referral_key')
17
-
18
- if (referralId && eventId && !isAlreadyCounted) {
19
- (async () => {
20
- try {
21
- await postReferralVisits(`${eventId}`, referralId)
22
- localStorage.setItem(
23
- 'referral_key',
24
- [eventId, '.', referralId].join('')
25
- )
26
- } catch (error) {}
27
- })()
28
- }
29
- }
30
- }, [])
31
-
32
- return null
33
- }
1
+ import { useEffect } from 'react'
2
+ import { postReferralVisits } from '../../api'
3
+
4
+ interface IReferralLogicProps {
5
+ eventId: string | number;
6
+ }
7
+
8
+ export const ReferralLogic = (props: IReferralLogicProps) => {
9
+ const { eventId } = props
10
+ const isWindowDefined = typeof window !== 'undefined'
11
+
12
+ useEffect(() => {
13
+ if (isWindowDefined) {
14
+ const params: URLSearchParams = new URL(`${window.location}`).searchParams
15
+ const referralId = params.get('ttf_r') || ''
16
+ const referralValue = [eventId, '.', referralId].join('')
17
+ const isAlreadyCounted = localStorage.getItem('referral_key') === referralValue
18
+
19
+ if (referralId && eventId && !isAlreadyCounted) {
20
+ (async () => {
21
+ try {
22
+ await postReferralVisits(`${eventId}`, referralId)
23
+ localStorage.setItem('referral_key', referralValue)
24
+ } catch (error) {}
25
+ })()
26
+ }
27
+ }
28
+ }, [])
29
+
30
+ return null
31
+ }
@@ -1,83 +1,89 @@
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 = !ticketTier.salesStarted || ticketTier.salesEnded
29
- const options = getTicketSelectOptions(
30
- ticketTier.maxQuantity,
31
- ticketTier.minQuantity,
32
- ticketTier.multiplier
33
- )
34
- const ticketsClosedMessage = !ticketTier.salesStarted ? 'Sales not started' : 'Sales Ended'
35
-
36
- const onSaleContent = isSalesClosed ? ticketsClosedMessage : (
37
- <div className="get-tickets">
38
- <Box className="get-tickets__selectbox">
39
- <FormControl fullWidth>
40
- <Select
41
- sx={{
42
- borderRadius: 0,
43
- }}
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.displayTicket) {
76
- returnValue = onSaleContent
77
- }
78
- if (_get(prevTicketTier, 'in_stock')) {
79
- returnValue = 'SOON'
80
- }
81
-
82
- return <>{returnValue} </>
83
- }
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 = !ticketTier.salesStarted || ticketTier.salesEnded
29
+ const options = getTicketSelectOptions(
30
+ ticketTier.maxQuantity,
31
+ ticketTier.minQuantity,
32
+ ticketTier.multiplier
33
+ )
34
+ const ticketsClosedMessage = !ticketTier.salesStarted ? 'Sales not started' : 'Sales Ended'
35
+
36
+ const onSaleContent = (
37
+ <div className="get-tickets">
38
+ <Box className="get-tickets__selectbox">
39
+ <FormControl fullWidth>
40
+ <Select
41
+ sx={{
42
+ borderRadius: 0,
43
+ }}
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
+ // ticketTier.soldOut === false --> means that ticket is in the stock
72
+ const isSoldOut =
73
+ ticketTier.sold_out ||
74
+ !ticketTier.displayTicket ||
75
+ ticketTier.soldOut ||
76
+ ticketTier.soldOut === false
77
+
78
+ if (isSoldOut) {
79
+ returnValue = soldOutMessage
80
+ } else if (isSalesClosed) {
81
+ returnValue = ticketsClosedMessage
82
+ } else if (ticketTier.displayTicket && ticketTier.maxQuantity) {
83
+ returnValue = onSaleContent
84
+ } else if (_get(prevTicketTier, 'in_stock')) {
85
+ returnValue = 'SOON'
86
+ }
87
+
88
+ return <>{returnValue} </>
89
+ }
@@ -1,81 +1,87 @@
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
- const ticketIsFree = (+ticket.cost || +ticket.price) === 0
42
- const ticketPrice = isSoldOut ? 'SOLD OUT' : ticketIsFree ? 'FREE' : `$ ${(+ticket.cost || +ticket.price).toFixed(2)}`
43
-
44
- return (
45
- <div
46
- key={ticket.id || ticket.name}
47
- className={`event-detail__tier ${isSoldOut ? 'disabled' : ''}`}
48
- >
49
- <div className="event-detail__tier-name">
50
- {ticket.displayName || ticket.name}
51
- </div>
52
- <div className="event-tickets-container">
53
- <div className="event-detail__tier-price">
54
- {ticketIsDiscounted && (
55
- <p className="old-price">$ {(+ticket.oldPrice).toFixed(2)}</p>
56
- )}
57
- <p>{ticketPrice}</p>
58
- {!isSoldOut && !ticketIsFree && (
59
- <p className="fees">
60
- {ticket.feeIncluded ? '(incl. Fees)' : '(excl. Fees)'}
61
- </p>
62
- )}
63
- </div>
64
- <div
65
- className="event-detail__tier-state"
66
- style={{ minWidth: 55 }}
67
- >
68
- <TicketRow
69
- ticketTier={ticket}
70
- prevTicketTier={arr[i - 1]}
71
- selectedTickets={selectedTickets}
72
- handleTicketSelect={ticketSelect}
73
- />
74
- </div>
75
- </div>
76
- </div>
77
- )
78
- })}
79
- </>
80
- )
81
- }
1
+ import React, { ReactNode } 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
+ sortBySoldOut: boolean;
12
+ ticketsHeaderComponent?: ReactNode,
13
+ hideTicketsHeader: boolean,
14
+ }
15
+
16
+ export const TicketsSection = ({
17
+ ticketsList,
18
+ selectedTickets,
19
+ handleTicketSelect,
20
+ sortBySoldOut,
21
+ ticketsHeaderComponent,
22
+ hideTicketsHeader
23
+ }: ITicketsSectionProps) => {
24
+ const sortedTicketsList = sortBySoldOut
25
+ ? _sortBy(_sortBy(ticketsList, 'sortOrder'), 'soldOut')
26
+ : _sortBy(ticketsList, 'sortOrder')
27
+ return (
28
+ <>
29
+ {!hideTicketsHeader && ticketsHeaderComponent}
30
+ {sortedTicketsList.map((ticket, i, arr) => {
31
+ const isSoldOut =
32
+ ticket.sold_out || !ticket.displayTicket || ticket.soldOut
33
+ const ticketSelect = (event: any) => {
34
+ const { value } = event.target
35
+ handleTicketSelect(ticket.id, value)
36
+ }
37
+
38
+ let ticketIsDiscounted = false
39
+ if (
40
+ ticket.oldPrice &&
41
+ !isSoldOut &&
42
+ ticket.oldPrice !== ticket.price
43
+ ) {
44
+ ticketIsDiscounted = true
45
+ }
46
+
47
+ const ticketIsFree = +ticket.price === 0
48
+ const ticketPrice = isSoldOut ? 'SOLD OUT' : ticketIsFree ? 'FREE' : `$ ${(+ticket.price).toFixed(2)}`
49
+
50
+ return (
51
+ <div
52
+ key={ticket.id || ticket.name}
53
+ className={`event-detail__tier ${isSoldOut ? 'disabled' : ''}`}
54
+ >
55
+ <div className="event-detail__tier-name">
56
+ {ticket.displayName || ticket.name}
57
+ </div>
58
+ <div className="event-tickets-container">
59
+ <div className="event-detail__tier-price">
60
+ {ticketIsDiscounted && (
61
+ <p className="old-price">$ {(+ticket.oldPrice).toFixed(2)}</p>
62
+ )}
63
+ <p>{ticketPrice}</p>
64
+ {!isSoldOut && !ticketIsFree && (
65
+ <p className="fees">
66
+ {ticket.feeIncluded ? '(incl. Fees)' : '(excl. Fees)'}
67
+ </p>
68
+ )}
69
+ </div>
70
+ <div
71
+ className="event-detail__tier-state"
72
+ style={{ minWidth: 55 }}
73
+ >
74
+ <TicketRow
75
+ ticketTier={ticket}
76
+ prevTicketTier={arr[i - 1]}
77
+ selectedTickets={selectedTickets}
78
+ handleTicketSelect={ticketSelect}
79
+ />
80
+ </div>
81
+ </div>
82
+ </div>
83
+ )
84
+ })}
85
+ </>
86
+ )
87
+ }