tf-checkout-react 1.7.20 → 1.7.23
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/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 +71 -16
- 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 +71 -16
- package/dist/tf-checkout-react.esm.js.map +1 -1
- package/package.json +1 -1
- 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/package.json
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>
|