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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.7.20",
2
+ "version": "1.7.23",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -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 > 0) {
42
- siblingIds.forEach((siblingId: string) => setFieldValue(siblingId, 0))
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={qty >= max}
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={addonsOptions[variant.id]}
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
- console.log('handleAddonChange', id, value)
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={addonsOptions[addon.id]}
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>
@@ -38,6 +38,7 @@ export interface IAddonContainterProps {
38
38
 
39
39
  onAddOnSelect?: (id: string, value: string, addon: any) => void;
40
40
  useStepperQty?: boolean;
41
+ addonMaxQuantityGroups?: number;
41
42
  }
42
43
 
43
44