tf-checkout-react 1.7.19 → 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.19",
2
+ "version": "1.7.23",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -23,6 +23,9 @@ interface IAddonComponentProps {
23
23
  values: any;
24
24
  errors: any;
25
25
  useStepperQty?: boolean;
26
+ siblingIds?: string[];
27
+ allAddonIds?: string[];
28
+ maxTotalQuantity?: number;
26
29
  onCustomFieldChange?: (
27
30
  addon: any,
28
31
  groupId: string | number,
@@ -31,16 +34,29 @@ interface IAddonComponentProps {
31
34
  ) => void;
32
35
  }
33
36
 
34
- const AddonStepper = ({ id, selectOptions, handleAddonChange, classNamePrefix }: any) => {
37
+ const AddonStepper = ({ id, selectOptions, handleAddonChange, classNamePrefix, siblingIds = [], allAddonIds = [], maxTotalQuantity }: any) => {
35
38
  const { values, setFieldValue } = useFormikContext<any>()
36
39
  const qty = Number(values[id] ?? 0)
37
40
  const max = selectOptions?.length > 0 ? selectOptions[selectOptions.length - 1].value : 0
38
41
 
42
+ const totalSelected = allAddonIds.length > 0
43
+ ? allAddonIds.reduce((sum: number, aid: string) => sum + Number(values[aid] ?? 0), 0)
44
+ : 0
45
+
39
46
  const change = (next: number) => {
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
+ }
53
+ }
40
54
  setFieldValue(id, next)
41
55
  handleAddonChange(id, next)
42
56
  }
43
57
 
58
+ const incrementDisabled = qty >= max || (maxTotalQuantity != null && totalSelected >= maxTotalQuantity && qty === 0)
59
+
44
60
  return (
45
61
  <div className={`${classNamePrefix}_stepper`}>
46
62
  <button
@@ -57,7 +73,7 @@ const AddonStepper = ({ id, selectOptions, handleAddonChange, classNamePrefix }:
57
73
  type="button"
58
74
  className={`${classNamePrefix}_stepper__btn`}
59
75
  onClick={() => change(qty + 1)}
60
- disabled={qty >= max}
76
+ disabled={incrementDisabled}
61
77
  aria-label="Increase quantity"
62
78
  >
63
79
  +
@@ -76,6 +92,9 @@ const AddonComponent = ({
76
92
  values,
77
93
  errors,
78
94
  useStepperQty = false,
95
+ siblingIds = [],
96
+ allAddonIds = [],
97
+ maxTotalQuantity,
79
98
  onCustomFieldChange = _identity,
80
99
  }: IAddonComponentProps) => {
81
100
  const { id, name, active, stock } = data
@@ -101,6 +120,9 @@ const AddonComponent = ({
101
120
  selectOptions={selectOptions}
102
121
  handleAddonChange={handleAddonChange}
103
122
  classNamePrefix={classNamePrefix}
123
+ siblingIds={siblingIds}
124
+ allAddonIds={allAddonIds}
125
+ maxTotalQuantity={maxTotalQuantity}
104
126
  />
105
127
  </div>
106
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,10 +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}
397
+ siblingIds={addon.variants.filter((v: any) => v.id !== variant.id).map((v: any) => v.id)}
364
398
  handleAddonChange={(id, value) => {
365
- console.log('handleAddonChange', id, value)
399
+ handleCrossGroupChange(id, value)
366
400
  onFieldChange(id, value, addon)
367
401
  const fieldUpdates = collectAddonFieldUpdates(
368
402
  addon,
@@ -383,9 +417,10 @@ export const SimpleAddonsContainer = ({
383
417
  <AddonComponent
384
418
  key={addon.id}
385
419
  data={addon}
386
- selectOptions={addonsOptions[addon.id]}
420
+ selectOptions={effectiveAddonsOptions[addon.id]}
387
421
  classNamePrefix={classNamePrefix}
388
422
  handleAddonChange={(id, value) => {
423
+ handleCrossGroupChange(id, value)
389
424
  onFieldChange(id, value, addon)
390
425
  const fieldUpdates = collectAddonFieldUpdates(addon, values)
391
426
  onAddOnSelect(id, value, addon, fieldUpdates)
@@ -414,7 +449,7 @@ export const SimpleAddonsContainer = ({
414
449
  })}
415
450
  </>
416
451
  </Form>
417
- )}
452
+ )}}
418
453
  </Formik>
419
454
  </div>
420
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
 
@@ -279,6 +280,7 @@ export const AddonsContainter = ({
279
280
  data={variant}
280
281
  selectOptions={addonsOptions[variant.id]}
281
282
  classNamePrefix={classNamePrefix}
283
+ siblingIds={addon.variants.map((v: any) => v.id).filter((vid: string) => vid !== variant.id)}
282
284
  handleAddonChange={(id, value) => {
283
285
  onAddOnSelect(id, value, addon)
284
286
  onFieldChange(id, value, addon)