tf-checkout-react 1.7.20 → 1.7.30
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 +1 -0
- package/dist/components/addonsContainer/AddonComponent.d.ts +3 -1
- package/dist/components/addonsContainer/SimpleAddonsContainer.d.ts +3 -1
- package/dist/components/addonsContainer/index.d.ts +1 -0
- package/dist/tf-checkout-react.cjs.development.js +133 -174
- 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 +133 -174
- package/dist/tf-checkout-react.esm.js.map +1 -1
- package/dist/types/checkoutPageConfigs.d.ts +1 -0
- package/package.json +1 -1
- package/src/api/index.ts +1 -0
- package/src/components/addonsContainer/AddonComponent.tsx +20 -4
- package/src/components/addonsContainer/SimpleAddonsContainer.tsx +39 -5
- package/src/components/addonsContainer/index.tsx +1 -0
- package/src/components/billing-info-container/hooks/usePaymentRedirect.ts +0 -2
- package/src/components/billing-info-container/index.tsx +2 -16
- package/src/components/paymentContainer/index.tsx +1 -29
- package/src/components/registerForm/index.tsx +0 -1
- package/src/types/checkoutPageConfigs.ts +1 -0
package/package.json
CHANGED
package/src/api/index.ts
CHANGED
|
@@ -24,6 +24,8 @@ interface IAddonComponentProps {
|
|
|
24
24
|
errors: any;
|
|
25
25
|
useStepperQty?: boolean;
|
|
26
26
|
siblingIds?: string[];
|
|
27
|
+
allAddonIds?: string[];
|
|
28
|
+
maxTotalQuantity?: number;
|
|
27
29
|
onCustomFieldChange?: (
|
|
28
30
|
addon: any,
|
|
29
31
|
groupId: string | number,
|
|
@@ -32,19 +34,29 @@ interface IAddonComponentProps {
|
|
|
32
34
|
) => void;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
const AddonStepper = ({ id, selectOptions, handleAddonChange, classNamePrefix, siblingIds = [] }: any) => {
|
|
37
|
+
const AddonStepper = ({ id, selectOptions, handleAddonChange, classNamePrefix, siblingIds = [], allAddonIds = [], maxTotalQuantity }: any) => {
|
|
36
38
|
const { values, setFieldValue } = useFormikContext<any>()
|
|
37
39
|
const qty = Number(values[id] ?? 0)
|
|
38
40
|
const max = selectOptions?.length > 0 ? selectOptions[selectOptions.length - 1].value : 0
|
|
39
41
|
|
|
42
|
+
const totalSelected = allAddonIds.length > 0
|
|
43
|
+
? allAddonIds.reduce((sum: number, aid: string) => sum + Number(values[aid] ?? 0), 0)
|
|
44
|
+
: 0
|
|
45
|
+
|
|
40
46
|
const change = (next: number) => {
|
|
41
|
-
if (next >
|
|
42
|
-
|
|
47
|
+
if (next > qty) {
|
|
48
|
+
if (maxTotalQuantity != null) {
|
|
49
|
+
allAddonIds.forEach((aid: string) => { if (aid !== id) setFieldValue(aid, 0) })
|
|
50
|
+
} else {
|
|
51
|
+
siblingIds.forEach((siblingId: string) => setFieldValue(siblingId, 0))
|
|
52
|
+
}
|
|
43
53
|
}
|
|
44
54
|
setFieldValue(id, next)
|
|
45
55
|
handleAddonChange(id, next)
|
|
46
56
|
}
|
|
47
57
|
|
|
58
|
+
const incrementDisabled = qty >= max || (maxTotalQuantity != null && totalSelected >= maxTotalQuantity && qty === 0)
|
|
59
|
+
|
|
48
60
|
return (
|
|
49
61
|
<div className={`${classNamePrefix}_stepper`}>
|
|
50
62
|
<button
|
|
@@ -61,7 +73,7 @@ const AddonStepper = ({ id, selectOptions, handleAddonChange, classNamePrefix, s
|
|
|
61
73
|
type="button"
|
|
62
74
|
className={`${classNamePrefix}_stepper__btn`}
|
|
63
75
|
onClick={() => change(qty + 1)}
|
|
64
|
-
disabled={
|
|
76
|
+
disabled={incrementDisabled}
|
|
65
77
|
aria-label="Increase quantity"
|
|
66
78
|
>
|
|
67
79
|
+
|
|
@@ -81,6 +93,8 @@ const AddonComponent = ({
|
|
|
81
93
|
errors,
|
|
82
94
|
useStepperQty = false,
|
|
83
95
|
siblingIds = [],
|
|
96
|
+
allAddonIds = [],
|
|
97
|
+
maxTotalQuantity,
|
|
84
98
|
onCustomFieldChange = _identity,
|
|
85
99
|
}: IAddonComponentProps) => {
|
|
86
100
|
const { id, name, active, stock } = data
|
|
@@ -107,6 +121,8 @@ const AddonComponent = ({
|
|
|
107
121
|
handleAddonChange={handleAddonChange}
|
|
108
122
|
classNamePrefix={classNamePrefix}
|
|
109
123
|
siblingIds={siblingIds}
|
|
124
|
+
allAddonIds={allAddonIds}
|
|
125
|
+
maxTotalQuantity={maxTotalQuantity}
|
|
110
126
|
/>
|
|
111
127
|
</div>
|
|
112
128
|
) : (
|
|
@@ -31,6 +31,8 @@ export interface ISimpleAddonContainerProps {
|
|
|
31
31
|
configs: any;
|
|
32
32
|
eventId: string;
|
|
33
33
|
useStepperQty?: boolean;
|
|
34
|
+
maxTotalQuantity?: number;
|
|
35
|
+
addonMaxQuantityGroups?: number;
|
|
34
36
|
onAddOnSelect?: (id: string, value: string, addon: any, fieldUpdates: any) => void;
|
|
35
37
|
handleConfirm?: (values: any) => void;
|
|
36
38
|
}
|
|
@@ -48,6 +50,7 @@ export const SimpleAddonsContainer = ({
|
|
|
48
50
|
configs,
|
|
49
51
|
eventId,
|
|
50
52
|
useStepperQty = false,
|
|
53
|
+
addonMaxQuantityGroups,
|
|
51
54
|
onAddOnSelect = _identity,
|
|
52
55
|
handleConfirm = _identity,
|
|
53
56
|
}: ISimpleAddonContainerProps) => {
|
|
@@ -56,6 +59,7 @@ export const SimpleAddonsContainer = ({
|
|
|
56
59
|
const [groupsWithSelectedVariants, setGroupsWithSelectedVariants] = useState<any>({})
|
|
57
60
|
const [groupsWithInitialVariantsValues, setGroupsWithInitialVariantsValues] =
|
|
58
61
|
useState<any>({})
|
|
62
|
+
const [crossGroupSelections, setCrossGroupSelections] = useState<ObjectLiteral>({})
|
|
59
63
|
const [loading, setLoading] = useState(true)
|
|
60
64
|
|
|
61
65
|
const [visibleDescription, setVisibleDescription] = useState<string | null>(null)
|
|
@@ -206,6 +210,34 @@ export const SimpleAddonsContainer = ({
|
|
|
206
210
|
}
|
|
207
211
|
}
|
|
208
212
|
|
|
213
|
+
// Cross-group cap: when addonMaxQuantityGroups is set, limits total selections
|
|
214
|
+
// across ALL addon groups to that number by capping each stepper's max.
|
|
215
|
+
const effectiveAddonsOptions = useMemo(() => {
|
|
216
|
+
if (!addonMaxQuantityGroups) return addonsOptions
|
|
217
|
+
|
|
218
|
+
const totalSelected = Object.values(crossGroupSelections).reduce(
|
|
219
|
+
(sum: number, v: any) => sum + Number(v), 0
|
|
220
|
+
)
|
|
221
|
+
const globalRemaining = addonMaxQuantityGroups - totalSelected
|
|
222
|
+
const result: ObjectLiteral = {}
|
|
223
|
+
|
|
224
|
+
for (const id in addonsOptions) {
|
|
225
|
+
const opts = addonsOptions[id] || []
|
|
226
|
+
const sdkMax = opts.length ? opts[opts.length - 1].value : 0
|
|
227
|
+
const currSelected = Number(crossGroupSelections[id] || 0)
|
|
228
|
+
const allowedMax = Math.max(0, Math.min(sdkMax, globalRemaining + currSelected))
|
|
229
|
+
result[id] = opts.filter((opt: any) => opt.value <= allowedMax)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return result
|
|
233
|
+
}, [addonsOptions, crossGroupSelections, addonMaxQuantityGroups])
|
|
234
|
+
|
|
235
|
+
const handleCrossGroupChange = (id: any, value: any) => {
|
|
236
|
+
if (addonMaxQuantityGroups) {
|
|
237
|
+
setCrossGroupSelections((prev: ObjectLiteral) => ({ ...prev, [id]: Number(value) }))
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
209
241
|
const initialValues = useMemo(() => {
|
|
210
242
|
const addOnsData: any = {}
|
|
211
243
|
if (addons?.length > 0 && addOnDataWithCustomFields?.fields?.length > 0) {
|
|
@@ -252,7 +284,8 @@ export const SimpleAddonsContainer = ({
|
|
|
252
284
|
// Real-time validation can be handled here if needed
|
|
253
285
|
}}
|
|
254
286
|
>
|
|
255
|
-
{({ values, errors, setFieldTouched }) =>
|
|
287
|
+
{({ values, errors, setFieldTouched }) => {
|
|
288
|
+
return (
|
|
256
289
|
<Form autoComplete="off" className="form_holder">
|
|
257
290
|
<>
|
|
258
291
|
{addons.map((addon: any) => {
|
|
@@ -359,11 +392,11 @@ export const SimpleAddonsContainer = ({
|
|
|
359
392
|
<AddonComponent
|
|
360
393
|
key={variant.id}
|
|
361
394
|
data={variant}
|
|
362
|
-
selectOptions={
|
|
395
|
+
selectOptions={effectiveAddonsOptions[variant.id]}
|
|
363
396
|
classNamePrefix={classNamePrefix}
|
|
364
397
|
siblingIds={addon.variants.filter((v: any) => v.id !== variant.id).map((v: any) => v.id)}
|
|
365
398
|
handleAddonChange={(id, value) => {
|
|
366
|
-
|
|
399
|
+
handleCrossGroupChange(id, value)
|
|
367
400
|
onFieldChange(id, value, addon)
|
|
368
401
|
const fieldUpdates = collectAddonFieldUpdates(
|
|
369
402
|
addon,
|
|
@@ -384,9 +417,10 @@ export const SimpleAddonsContainer = ({
|
|
|
384
417
|
<AddonComponent
|
|
385
418
|
key={addon.id}
|
|
386
419
|
data={addon}
|
|
387
|
-
selectOptions={
|
|
420
|
+
selectOptions={effectiveAddonsOptions[addon.id]}
|
|
388
421
|
classNamePrefix={classNamePrefix}
|
|
389
422
|
handleAddonChange={(id, value) => {
|
|
423
|
+
handleCrossGroupChange(id, value)
|
|
390
424
|
onFieldChange(id, value, addon)
|
|
391
425
|
const fieldUpdates = collectAddonFieldUpdates(addon, values)
|
|
392
426
|
onAddOnSelect(id, value, addon, fieldUpdates)
|
|
@@ -415,7 +449,7 @@ export const SimpleAddonsContainer = ({
|
|
|
415
449
|
})}
|
|
416
450
|
</>
|
|
417
451
|
</Form>
|
|
418
|
-
)}
|
|
452
|
+
)}}
|
|
419
453
|
</Formik>
|
|
420
454
|
</div>
|
|
421
455
|
</div>
|
|
@@ -50,7 +50,6 @@ export const usePaymentRedirect = ({
|
|
|
50
50
|
const clientSecret = urlParams.get('payment_intent_client_secret')
|
|
51
51
|
|
|
52
52
|
if (isPaymentReturn && clientSecret && stripeRef.current) {
|
|
53
|
-
console.log('Detected payment redirect return, checking status')
|
|
54
53
|
setLoading(true)
|
|
55
54
|
|
|
56
55
|
try {
|
|
@@ -68,7 +67,6 @@ export const usePaymentRedirect = ({
|
|
|
68
67
|
)
|
|
69
68
|
|
|
70
69
|
if (paymentIntent?.status === 'succeeded') {
|
|
71
|
-
console.log('Payment succeeded after redirect, continuing flow')
|
|
72
70
|
|
|
73
71
|
// Clean up stored context
|
|
74
72
|
localStorage.removeItem('stripe_payment_context')
|
|
@@ -495,6 +495,7 @@ const BillingInfoContainer = React.memo(
|
|
|
495
495
|
const collectMandatoryBusinessCategory = configs?.collect_mandatory_business_category
|
|
496
496
|
const collectOptionalBusinessCategory = configs?.collect_optional_business_category
|
|
497
497
|
const eventHasAddons = configs?.has_add_on
|
|
498
|
+
const addonMaxQuantityGroups = configs?.addon_max_quantity_groups ?? undefined
|
|
498
499
|
const hideBusinessCategoryField =
|
|
499
500
|
!collectMandatoryBusinessCategory && !collectOptionalBusinessCategory
|
|
500
501
|
|
|
@@ -636,8 +637,6 @@ const BillingInfoContainer = React.memo(
|
|
|
636
637
|
is_from_resale: additionalConfigs?.resale,
|
|
637
638
|
},
|
|
638
639
|
})
|
|
639
|
-
console.log('Stripe in [useEffect] fetchCheckoutUpdate', checkoutUpdateResponse)
|
|
640
|
-
|
|
641
640
|
if (checkoutUpdateResponse.success) {
|
|
642
641
|
const checkoutAttributes = checkoutUpdateResponse.data.attributes
|
|
643
642
|
const cartPriceBreakdown = _get(
|
|
@@ -649,10 +648,6 @@ const BillingInfoContainer = React.memo(
|
|
|
649
648
|
'checkoutData',
|
|
650
649
|
JSON.stringify({ hash: '', total: _get(cartPriceBreakdown, 'total', 0) })
|
|
651
650
|
)
|
|
652
|
-
console.log(
|
|
653
|
-
'Stripe in [useEffect] fetchCheckoutUpdate | checkoutAttributes',
|
|
654
|
-
checkoutAttributes
|
|
655
|
-
)
|
|
656
651
|
setCheckoutUpdateData(checkoutAttributes)
|
|
657
652
|
onCheckoutUpdateSuccess({ expires_at: expirationTime, ...cartPriceBreakdown })
|
|
658
653
|
}
|
|
@@ -923,7 +918,6 @@ const BillingInfoContainer = React.memo(
|
|
|
923
918
|
},
|
|
924
919
|
[eventId, isSinglePageCheckout, onCheckoutUpdateError, onCheckoutUpdateSuccess]
|
|
925
920
|
)
|
|
926
|
-
console.log({ checkoutData })
|
|
927
921
|
|
|
928
922
|
const handleAddOnSelect = useCallback(
|
|
929
923
|
async (selectedAddOns: { [key: string]: number }) => {
|
|
@@ -1150,11 +1144,6 @@ const BillingInfoContainer = React.memo(
|
|
|
1150
1144
|
is_from_resale: additionalConfigs?.resale,
|
|
1151
1145
|
},
|
|
1152
1146
|
})
|
|
1153
|
-
console.log(
|
|
1154
|
-
'Stripe checkoutUpdateResponse in billing-info-container',
|
|
1155
|
-
checkoutUpdateResponse
|
|
1156
|
-
)
|
|
1157
|
-
|
|
1158
1147
|
setCheckoutUpdateData(checkoutUpdateResponse.data.attributes)
|
|
1159
1148
|
|
|
1160
1149
|
let paymentResponse = null
|
|
@@ -1167,7 +1156,6 @@ const BillingInfoContainer = React.memo(
|
|
|
1167
1156
|
|
|
1168
1157
|
if (paymentDataResponse.success) {
|
|
1169
1158
|
const { attributes } = paymentDataResponse.data
|
|
1170
|
-
console.log('Stripe confirmPayment success in billing-info-container')
|
|
1171
1159
|
setReviewData(attributes)
|
|
1172
1160
|
|
|
1173
1161
|
const { order_details, cart } = attributes
|
|
@@ -1196,9 +1184,6 @@ const BillingInfoContainer = React.memo(
|
|
|
1196
1184
|
const isFreeTickets =
|
|
1197
1185
|
(!Number(total) && !Number(updatedOrderData.total)) ||
|
|
1198
1186
|
!Number(updatedOrderData?.pay_now || 0)
|
|
1199
|
-
const paymentMethod = attributes.payment_method || {}
|
|
1200
|
-
const paymentPlanAvailable = paymentMethod.stripe_payment_plan_enabled
|
|
1201
|
-
console.log({ paymentPlanAvailable })
|
|
1202
1187
|
// Process payment using the hook
|
|
1203
1188
|
paymentResponse = await processPayment(
|
|
1204
1189
|
paymentDataResponse,
|
|
@@ -1353,6 +1338,7 @@ const BillingInfoContainer = React.memo(
|
|
|
1353
1338
|
addOnDataWithCustomFields={addOnDataWithCustomFields}
|
|
1354
1339
|
configs={configs}
|
|
1355
1340
|
onAddOnSelect={onAddOnSelect}
|
|
1341
|
+
addonMaxQuantityGroups={addonMaxQuantityGroups}
|
|
1356
1342
|
/>
|
|
1357
1343
|
) : !addOnsIncludedOnInvitation &&
|
|
1358
1344
|
includeAddons &&
|
|
@@ -20,10 +20,9 @@ import _get from 'lodash/get'
|
|
|
20
20
|
import _identity from 'lodash/identity'
|
|
21
21
|
import _isEmpty from 'lodash/isEmpty'
|
|
22
22
|
import _map from 'lodash/map'
|
|
23
|
-
import { nanoid } from 'nanoid'
|
|
24
23
|
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
|
25
24
|
|
|
26
|
-
import {
|
|
25
|
+
import { getPaymentData } from '../../api'
|
|
27
26
|
import { FEES_STYLES } from '../../constants'
|
|
28
27
|
import { usePixel } from '../../hooks/usePixel'
|
|
29
28
|
import { createFixedFloatNormalizer, currencyNormalizerCreator } from '../../normalizers'
|
|
@@ -177,7 +176,6 @@ export const PaymentContainer = ({
|
|
|
177
176
|
const [error, setError] = useState(null)
|
|
178
177
|
const [paymentIsLoading, setPaymentIsLoading] = useState(false)
|
|
179
178
|
const [paymentDataIsLoading, setPaymentDataIsLoading] = useState(true)
|
|
180
|
-
const [conditions, setConditions] = useState<{ id: string, text: string }[]>([])
|
|
181
179
|
const [currency, setCurrency] = useState('')
|
|
182
180
|
const [showPaymentPlanSection, setShowPaymentPlanSection] = useState(false)
|
|
183
181
|
|
|
@@ -201,7 +199,6 @@ export const PaymentContainer = ({
|
|
|
201
199
|
const pageUrl = isBrowser ? window.location.href.split('?')[0] : ''
|
|
202
200
|
usePixel(eventId, { page: 'review', pageUrl })
|
|
203
201
|
|
|
204
|
-
console.log({ conditions })
|
|
205
202
|
|
|
206
203
|
useEffect(() => {
|
|
207
204
|
const fetchPaymentData = async () => {
|
|
@@ -270,27 +267,6 @@ export const PaymentContainer = ({
|
|
|
270
267
|
onGetPaymentDataSuccess,
|
|
271
268
|
])
|
|
272
269
|
|
|
273
|
-
//just once
|
|
274
|
-
useEffect(() => {
|
|
275
|
-
// fetch conditions data
|
|
276
|
-
const fetchConditions = async () => {
|
|
277
|
-
if (eventId) {
|
|
278
|
-
const conditionsResponse = await getConditions(eventId)
|
|
279
|
-
const conditionsInfo = conditionsResponse.data.attributes
|
|
280
|
-
setConditions(
|
|
281
|
-
conditionsInfo
|
|
282
|
-
? conditionsInfo.map((item: { text: any }) => ({
|
|
283
|
-
id: nanoid(),
|
|
284
|
-
text: item.text,
|
|
285
|
-
checked: false,
|
|
286
|
-
}))
|
|
287
|
-
: []
|
|
288
|
-
)
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
fetchConditions()
|
|
292
|
-
}, [eventId])
|
|
293
|
-
|
|
294
270
|
const showPaymentForm = () => {
|
|
295
271
|
if (hidePaymentForm) {
|
|
296
272
|
return false
|
|
@@ -375,10 +351,6 @@ export const PaymentContainer = ({
|
|
|
375
351
|
|
|
376
352
|
useEffect(() => {
|
|
377
353
|
const paymentMethod = reviewData.payment_method || {}
|
|
378
|
-
console.log({
|
|
379
|
-
paymentMethod,
|
|
380
|
-
enablePaymentPlan,
|
|
381
|
-
})
|
|
382
354
|
const paymentPlanAvailable =
|
|
383
355
|
paymentMethod.stripe_payment_plan_enabled && enablePaymentPlan
|
|
384
356
|
setPaymentPlanIsAvailable(paymentPlanAvailable)
|
|
@@ -114,7 +114,6 @@ export const RegistrationForm: FC<IRegistrationProps> = ({
|
|
|
114
114
|
onRegisterAccountSuccess(profileRes)
|
|
115
115
|
} catch (e) {
|
|
116
116
|
if (axios.isAxiosError(e)) {
|
|
117
|
-
console.log(e)
|
|
118
117
|
const errorMessage = _get(e, 'response.data.message') || 'Error'
|
|
119
118
|
onRegisterAccountError(e)
|
|
120
119
|
setshowErrorModal(true)
|