@ordergroove/offers 2.44.1-alpha-PR-1167-2.36 → 2.45.0
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/CHANGELOG.md +13 -0
- package/dist/bundle-report.html +9 -9
- package/dist/offers.js +2 -2
- package/dist/offers.js.map +3 -3
- package/package.json +2 -2
- package/src/core/__tests__/selectors.spec.js +91 -1
- package/src/core/actions.js +1 -0
- package/src/core/reducer.ts +1 -0
- package/src/core/selectors.ts +38 -5
- package/src/core/types/reducer.ts +1 -1
- package/src/shopify/__tests__/reducers/config.spec.js +143 -9
- package/src/shopify/reducers/config.ts +30 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ordergroove/offers",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.45.0",
|
|
4
4
|
"description": "offer state component",
|
|
5
5
|
"author": "Eugenio Lattanzio <eugenio63@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/ordergroove/plush-toys#readme",
|
|
@@ -49,5 +49,5 @@
|
|
|
49
49
|
"@ordergroove/offers-templates": "^0.9.7",
|
|
50
50
|
"@types/lodash.memoize": "^4.1.9"
|
|
51
51
|
},
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "221fe44cdecde025a85ff117df9639fb5068dfd5"
|
|
53
53
|
}
|
|
@@ -4,7 +4,8 @@ import {
|
|
|
4
4
|
isSameProduct,
|
|
5
5
|
templatesSelector,
|
|
6
6
|
makeProductSpecificDefaultFrequencySelector,
|
|
7
|
-
makeProductPrepaidShipmentOptionsSelector
|
|
7
|
+
makeProductPrepaidShipmentOptionsSelector,
|
|
8
|
+
makeProductFrequenciesSelector
|
|
8
9
|
} from '../selectors';
|
|
9
10
|
import { stringifyFrequency } from '../api';
|
|
10
11
|
|
|
@@ -141,3 +142,92 @@ describe('makeProductPrepaidShipmentOptionsSelector', () => {
|
|
|
141
142
|
).toEqual([3, 6, 12]);
|
|
142
143
|
});
|
|
143
144
|
});
|
|
145
|
+
|
|
146
|
+
describe('makeProductFrequenciesSelector', () => {
|
|
147
|
+
const productFrequencies = {
|
|
148
|
+
123: {
|
|
149
|
+
frequencies: ['default-group-plan-1', 'default-group-plan-2', 'default-group-plan-3'],
|
|
150
|
+
frequenciesEveryPeriod: ['1_3', '2_3', '3_3'],
|
|
151
|
+
frequenciesText: ['month', '2 months', '3 months'],
|
|
152
|
+
defaultFrequency: 'default-group-plan-1'
|
|
153
|
+
},
|
|
154
|
+
456: {
|
|
155
|
+
frequencies: ['other-group-plan-1', 'other-group-plan-2', 'other-group-plan-3'],
|
|
156
|
+
frequenciesEveryPeriod: ['2_3', '4_3', '6_3'],
|
|
157
|
+
frequenciesText: ['2 months', '4 months', '6 months'],
|
|
158
|
+
defaultFrequency: 'other-group-plan-1'
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
// note: in real life, these "global" frequencies are likely the same as the one of the sets in productFrequencies
|
|
162
|
+
// for unit testing, they are different so it is obvious which set of fields was returned
|
|
163
|
+
const frequencies = ['fallback-group-plan-1', 'fallback-group-plan-2', 'fallback-group-plan-3'];
|
|
164
|
+
const frequenciesEveryPeriod = ['1_2', '2_2', '3_2'];
|
|
165
|
+
const frequenciesText = ['week', '2 weeks', '3 weeks'];
|
|
166
|
+
const defaultFrequency = 'fallback-group-plan-1';
|
|
167
|
+
const config = { productFrequencies, frequencies, frequenciesEveryPeriod, frequenciesText, defaultFrequency };
|
|
168
|
+
|
|
169
|
+
it('returns product frequencies for product ID', () => {
|
|
170
|
+
const selectorProduct1 = makeProductFrequenciesSelector(123);
|
|
171
|
+
expect(
|
|
172
|
+
selectorProduct1({
|
|
173
|
+
config
|
|
174
|
+
})
|
|
175
|
+
).toEqual({
|
|
176
|
+
frequencies: ['default-group-plan-1', 'default-group-plan-2', 'default-group-plan-3'],
|
|
177
|
+
frequenciesEveryPeriod: ['1_3', '2_3', '3_3'],
|
|
178
|
+
frequenciesText: ['month', '2 months', '3 months'],
|
|
179
|
+
defaultFrequency: 'default-group-plan-1'
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const selectorProduct2 = makeProductFrequenciesSelector(456);
|
|
183
|
+
expect(selectorProduct2({ config })).toEqual({
|
|
184
|
+
frequencies: ['other-group-plan-1', 'other-group-plan-2', 'other-group-plan-3'],
|
|
185
|
+
frequenciesEveryPeriod: ['2_3', '4_3', '6_3'],
|
|
186
|
+
frequenciesText: ['2 months', '4 months', '6 months'],
|
|
187
|
+
defaultFrequency: 'other-group-plan-1'
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// product ID does not exist
|
|
191
|
+
const selectorProduct3 = makeProductFrequenciesSelector(789);
|
|
192
|
+
expect(selectorProduct3({ config })).toEqual({});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('falls back to old frequency fields if productFrequencies is not defined', () => {
|
|
196
|
+
const selector = makeProductFrequenciesSelector(123);
|
|
197
|
+
expect(
|
|
198
|
+
selector({
|
|
199
|
+
config: {
|
|
200
|
+
...config,
|
|
201
|
+
productFrequencies: null
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
).toEqual({
|
|
205
|
+
frequencies,
|
|
206
|
+
frequenciesEveryPeriod,
|
|
207
|
+
frequenciesText,
|
|
208
|
+
defaultFrequency
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('does not use old frequency fields if productFrequencies is defined but empty', () => {
|
|
213
|
+
const selector = makeProductFrequenciesSelector(123);
|
|
214
|
+
expect(
|
|
215
|
+
selector({
|
|
216
|
+
config: {
|
|
217
|
+
...config,
|
|
218
|
+
productFrequencies: {}
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
).toEqual({});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('returns object with undefined fields when everything is undefined', () => {
|
|
225
|
+
const selector = makeProductFrequenciesSelector(123);
|
|
226
|
+
expect(selector({ config: {} })).toEqual({
|
|
227
|
+
frequencies: undefined,
|
|
228
|
+
frequenciesEveryPeriod: undefined,
|
|
229
|
+
frequenciesText: undefined,
|
|
230
|
+
defaultFrequency: undefined
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
});
|
package/src/core/actions.js
CHANGED
|
@@ -189,6 +189,7 @@ export const requestSessionId = () => (dispatch, getState) => {
|
|
|
189
189
|
};
|
|
190
190
|
|
|
191
191
|
export const receiveOffer = (response, offer, productId) => (dispatch, getState) => {
|
|
192
|
+
// this is a thunk so that we access the state for the selector
|
|
192
193
|
const frequencyConfig = makeProductFrequenciesSelector(productId)(getState());
|
|
193
194
|
dispatch({
|
|
194
195
|
type: constants.RECEIVE_OFFER,
|
package/src/core/reducer.ts
CHANGED
|
@@ -419,6 +419,7 @@ export const config = (
|
|
|
419
419
|
return {
|
|
420
420
|
...state,
|
|
421
421
|
...action.payload,
|
|
422
|
+
// these are not populated by default; only if the merchant calls the config method on the Offers API
|
|
422
423
|
defaultFrequency: action.payload.defaultFrequency
|
|
423
424
|
? stringifyFrequency(action.payload.defaultFrequency)
|
|
424
425
|
: state.defaultFrequency,
|
package/src/core/selectors.ts
CHANGED
|
@@ -3,7 +3,7 @@ import memoize from 'lodash.memoize';
|
|
|
3
3
|
import { stringifyFrequency } from './api';
|
|
4
4
|
import platform from '../platform';
|
|
5
5
|
import { mapFrequencyToSellingPlan, safeProductId } from './utils';
|
|
6
|
-
import { OfferElement, State } from './types/reducer';
|
|
6
|
+
import { OfferElement, ProductFrequencyConfig, State } from './types/reducer';
|
|
7
7
|
|
|
8
8
|
memoize.Cache = Map;
|
|
9
9
|
|
|
@@ -151,7 +151,7 @@ export const makeProductPrepaidShipmentOptionsSelector = memoize((productId: str
|
|
|
151
151
|
);
|
|
152
152
|
|
|
153
153
|
/**
|
|
154
|
-
* If the product has a product-specific default frequency, return that frequency
|
|
154
|
+
* If the product has a product-specific default frequency configured in OG, return that frequency
|
|
155
155
|
*/
|
|
156
156
|
export const makeProductSpecificDefaultFrequencySelector = memoize((productId: string) =>
|
|
157
157
|
createSelector(
|
|
@@ -168,15 +168,48 @@ export const makeProductFrequencyOptionsSelector = memoize((productId: string) =
|
|
|
168
168
|
createSelector(makeProductFrequenciesSelector(productId), productFrequencies => productFrequencies.frequencies)
|
|
169
169
|
);
|
|
170
170
|
|
|
171
|
+
/**
|
|
172
|
+
* returns the default frequency for the product from the config state
|
|
173
|
+
* all products have a defaultFrequency stored in state, even if a specific frequency is not configured in OG's database
|
|
174
|
+
* this takes more into account, e.g. whether the customer had opted into a specific frequency previously - see the config reducer for how this is calculated
|
|
175
|
+
*/
|
|
171
176
|
export const makeProductDefaultFrequencySelector = memoize((productId: string) =>
|
|
172
177
|
createSelector(makeProductFrequenciesSelector(productId), productFrequencies => productFrequencies.defaultFrequency)
|
|
173
178
|
);
|
|
174
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Get the configured frequencies for the given product IDs
|
|
182
|
+
* Using this selector should be preferred over accessing config values directly
|
|
183
|
+
*/
|
|
175
184
|
export const makeProductFrequenciesSelector = memoize((productId: string) =>
|
|
176
185
|
createSelector(
|
|
177
|
-
(state: State) => state?.config?.productFrequencies
|
|
178
|
-
|
|
179
|
-
|
|
186
|
+
(state: State) => state?.config?.productFrequencies,
|
|
187
|
+
(state: State) => state?.config?.frequencies,
|
|
188
|
+
(state: State) => state?.config?.frequenciesEveryPeriod,
|
|
189
|
+
(state: State) => state?.config?.frequenciesText,
|
|
190
|
+
(state: State) => state?.config?.defaultFrequency,
|
|
191
|
+
(
|
|
192
|
+
productFrequencies,
|
|
193
|
+
oldFrequencies,
|
|
194
|
+
oldFrequenciesEveryPeriod,
|
|
195
|
+
oldFrequenciesText,
|
|
196
|
+
oldDefaultFrequency
|
|
197
|
+
): ProductFrequencyConfig => {
|
|
198
|
+
if (productFrequencies) {
|
|
199
|
+
// for Shopify, always use productFrequencies
|
|
200
|
+
// this is necessary to handle cases where different product variants have different selling plans associated with them
|
|
201
|
+
return productFrequencies[safeProductId(productId)] || {};
|
|
202
|
+
} else {
|
|
203
|
+
// productFrequencies are only populated for Shopify
|
|
204
|
+
// fall back to the old "global" frequency values if it is not set
|
|
205
|
+
// these would only be present if the merchant explicitly called `offers.config({ frequencies: [...] })`, so they generally won't be defined
|
|
206
|
+
return {
|
|
207
|
+
frequencies: oldFrequencies,
|
|
208
|
+
frequenciesEveryPeriod: oldFrequenciesEveryPeriod,
|
|
209
|
+
frequenciesText: oldFrequenciesText,
|
|
210
|
+
defaultFrequency: oldDefaultFrequency
|
|
211
|
+
};
|
|
212
|
+
}
|
|
180
213
|
}
|
|
181
214
|
)
|
|
182
215
|
);
|
|
@@ -49,7 +49,7 @@ export type ConfigState = Partial<{
|
|
|
49
49
|
productFrequencies: Record<string, ProductFrequencyConfig>;
|
|
50
50
|
}>;
|
|
51
51
|
|
|
52
|
-
type ProductFrequencyConfig = {
|
|
52
|
+
export type ProductFrequencyConfig = {
|
|
53
53
|
frequencies?: string[];
|
|
54
54
|
frequenciesEveryPeriod?: string[];
|
|
55
55
|
frequenciesText?: string[];
|
|
@@ -69,7 +69,10 @@ describe('config', () => {
|
|
|
69
69
|
'yum product id': jasmine.objectContaining({
|
|
70
70
|
defaultFrequency: 'yum selling plan id 2'
|
|
71
71
|
})
|
|
72
|
-
}
|
|
72
|
+
},
|
|
73
|
+
// fallback value in case a merchant was accessing our config directly
|
|
74
|
+
// productFrequencies should be used instead
|
|
75
|
+
defaultFrequency: 'yum selling plan id 2'
|
|
73
76
|
})
|
|
74
77
|
);
|
|
75
78
|
});
|
|
@@ -432,6 +435,136 @@ describe('config', () => {
|
|
|
432
435
|
);
|
|
433
436
|
});
|
|
434
437
|
|
|
438
|
+
const multiVariantSellingPlanPayload = {
|
|
439
|
+
product: {
|
|
440
|
+
id: 'product-id',
|
|
441
|
+
variants: [
|
|
442
|
+
{
|
|
443
|
+
id: 'variant-id-1',
|
|
444
|
+
selling_plan_allocations: [
|
|
445
|
+
{
|
|
446
|
+
selling_plan_id: 'default-group-plan-1',
|
|
447
|
+
selling_plan_group_id: 'default-group-id'
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
selling_plan_id: 'default-group-plan-2',
|
|
451
|
+
selling_plan_group_id: 'default-group-id'
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
selling_plan_id: 'default-group-plan-3',
|
|
455
|
+
selling_plan_group_id: 'default-group-id'
|
|
456
|
+
}
|
|
457
|
+
]
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
id: 'variant-id-2',
|
|
461
|
+
selling_plan_allocations: [
|
|
462
|
+
{
|
|
463
|
+
selling_plan_id: 'psi-group-plan-1',
|
|
464
|
+
selling_plan_group_id: 'psi-group-id'
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
selling_plan_id: 'psi-group-plan-2',
|
|
468
|
+
selling_plan_group_id: 'psi-group-id'
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
selling_plan_id: 'psi-group-plan-3',
|
|
472
|
+
selling_plan_group_id: 'psi-group-id'
|
|
473
|
+
}
|
|
474
|
+
]
|
|
475
|
+
}
|
|
476
|
+
],
|
|
477
|
+
selling_plan_groups: [
|
|
478
|
+
{
|
|
479
|
+
id: 'default-group-id',
|
|
480
|
+
name: 'Subscribe and Save',
|
|
481
|
+
options: [{ name: 'Delivery every', position: 1, values: ['month', '2 months', '3 months'] }],
|
|
482
|
+
selling_plans: [
|
|
483
|
+
{
|
|
484
|
+
id: 'default-group-plan-1',
|
|
485
|
+
name: 'Delivered every month. Get 10% off today and all future orders.',
|
|
486
|
+
options: [{ name: 'Delivery every', position: 1, value: 'month' }],
|
|
487
|
+
price_adjustments: [{ order_count: null, position: 1, value_type: 'percentage', value: 10 }]
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
id: 'default-group-plan-2',
|
|
491
|
+
name: 'Delivered every 2 months. Get 10% off today and all future orders.',
|
|
492
|
+
options: [{ name: 'Delivery every', position: 1, value: '2 months' }],
|
|
493
|
+
price_adjustments: [{ order_count: null, position: 1, value_type: 'percentage', value: 10 }]
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
id: 'default-group-plan-3',
|
|
497
|
+
name: 'Delivered every 3 months. Get 10% off today and all future orders.',
|
|
498
|
+
options: [{ name: 'Delivery every', position: 1, value: '3 months' }],
|
|
499
|
+
price_adjustments: [{ order_count: null, position: 1, value_type: 'percentage', value: 10 }]
|
|
500
|
+
}
|
|
501
|
+
],
|
|
502
|
+
app_id: 'ordergroove-subscribe-and-save'
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
id: 'psi-group-id',
|
|
506
|
+
name: 'test-incentive-group',
|
|
507
|
+
options: [{ name: 'Delivery every', position: 1, values: ['week', '2 weeks', '3 weeks'] }],
|
|
508
|
+
selling_plans: [
|
|
509
|
+
{
|
|
510
|
+
id: 'psi-group-plan-1',
|
|
511
|
+
name: 'Delivered every week. Get 10% off today and 21% off future orders.',
|
|
512
|
+
options: [{ name: 'Delivery every', position: 1, value: 'week' }],
|
|
513
|
+
price_adjustments: [{ order_count: null, position: 1, value_type: 'percentage', value: 10 }]
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
id: 'psi-group-plan-2',
|
|
517
|
+
name: 'Delivered every 2 weeks. Get 10% off today and 21% off future orders.',
|
|
518
|
+
options: [{ name: 'Delivery every', position: 1, value: '2 weeks' }],
|
|
519
|
+
price_adjustments: [{ order_count: null, position: 1, value_type: 'percentage', value: 10 }]
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
id: 'psi-group-plan-3',
|
|
523
|
+
name: 'Delivered every 3 weeks. Get 10% off today and 21% off future orders.',
|
|
524
|
+
options: [{ name: 'Delivery every', position: 1, value: '3 weeks' }],
|
|
525
|
+
price_adjustments: [{ order_count: null, position: 1, value_type: 'percentage', value: 10 }]
|
|
526
|
+
}
|
|
527
|
+
],
|
|
528
|
+
app_id: 'ordergroove-subscribe-and-save'
|
|
529
|
+
}
|
|
530
|
+
]
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
it('should populate frequencies for each product variant', () => {
|
|
535
|
+
const actual = config(
|
|
536
|
+
{
|
|
537
|
+
productFrequencies: {}
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
type: constants.SETUP_PRODUCT,
|
|
541
|
+
payload: multiVariantSellingPlanPayload
|
|
542
|
+
}
|
|
543
|
+
);
|
|
544
|
+
|
|
545
|
+
expect(actual).toEqual(
|
|
546
|
+
jasmine.objectContaining({
|
|
547
|
+
productFrequencies: {
|
|
548
|
+
'variant-id-1': {
|
|
549
|
+
frequencies: ['default-group-plan-1', 'default-group-plan-2', 'default-group-plan-3'],
|
|
550
|
+
frequenciesEveryPeriod: ['1_3', '2_3', '3_3'],
|
|
551
|
+
frequenciesText: ['month', '2 months', '3 months']
|
|
552
|
+
},
|
|
553
|
+
'variant-id-2': {
|
|
554
|
+
frequencies: ['psi-group-plan-1', 'psi-group-plan-2', 'psi-group-plan-3'],
|
|
555
|
+
frequenciesEveryPeriod: ['1_2', '2_2', '3_2'],
|
|
556
|
+
frequenciesText: ['week', '2 weeks', '3 weeks']
|
|
557
|
+
}
|
|
558
|
+
},
|
|
559
|
+
// fallback values in case a merchant was accessing our config directly
|
|
560
|
+
// productFrequencies should be used instead
|
|
561
|
+
frequencies: ['default-group-plan-1', 'default-group-plan-2', 'default-group-plan-3'],
|
|
562
|
+
frequenciesEveryPeriod: ['1_3', '2_3', '3_3'],
|
|
563
|
+
frequenciesText: ['month', '2 months', '3 months']
|
|
564
|
+
})
|
|
565
|
+
);
|
|
566
|
+
});
|
|
567
|
+
|
|
435
568
|
it('should set prepaidSellingPlans', () => {
|
|
436
569
|
const sellingPlanGroups = [
|
|
437
570
|
{
|
|
@@ -591,13 +724,14 @@ describe('config', () => {
|
|
|
591
724
|
}
|
|
592
725
|
}
|
|
593
726
|
});
|
|
594
|
-
expect(actual).toEqual(
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
727
|
+
expect(actual).toEqual(
|
|
728
|
+
jasmine.objectContaining({
|
|
729
|
+
productFrequencies: {
|
|
730
|
+
123: jasmine.objectContaining({
|
|
731
|
+
defaultFrequency: 'yum selling plan id 1'
|
|
732
|
+
})
|
|
733
|
+
}
|
|
734
|
+
})
|
|
735
|
+
);
|
|
602
736
|
});
|
|
603
737
|
});
|
|
@@ -18,7 +18,9 @@ import { ShopifySellingPlanGroupsEntity, ShopifyVariantsEntity } from '../types/
|
|
|
18
18
|
const config = (
|
|
19
19
|
state: ConfigState = {
|
|
20
20
|
offerType: 'radio',
|
|
21
|
-
productFrequencies: {}
|
|
21
|
+
productFrequencies: {},
|
|
22
|
+
frequencies: [],
|
|
23
|
+
frequenciesEveryPeriod: []
|
|
22
24
|
},
|
|
23
25
|
action
|
|
24
26
|
): ConfigState => {
|
|
@@ -27,18 +29,22 @@ const config = (
|
|
|
27
29
|
payload: { product, currency }
|
|
28
30
|
} = action as { payload: SetupProductPayload };
|
|
29
31
|
let configToAdd: ConfigState = {};
|
|
30
|
-
let productFrequencies = product.variants?.reduce(
|
|
32
|
+
let productFrequencies: ConfigState['productFrequencies'] = product.variants?.reduce(
|
|
31
33
|
(acc, variant) => reduceSellingPlansToFrequencies(acc, variant, product.selling_plan_groups, state),
|
|
32
34
|
{}
|
|
33
35
|
);
|
|
34
36
|
|
|
37
|
+
let updatedProductFrequencies = {
|
|
38
|
+
...state.productFrequencies,
|
|
39
|
+
...productFrequencies
|
|
40
|
+
};
|
|
41
|
+
|
|
35
42
|
configToAdd = {
|
|
36
43
|
...configToAdd,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
44
|
+
productFrequencies: updatedProductFrequencies,
|
|
45
|
+
// populate the old frequency fields for backwards compatibility
|
|
46
|
+
// these are only needed if someone was reading our config state directly, which shouldn't be common but is possible
|
|
47
|
+
...Object.values(updatedProductFrequencies)[0]
|
|
42
48
|
};
|
|
43
49
|
|
|
44
50
|
// prepaid selling plans
|
|
@@ -68,21 +74,25 @@ const config = (
|
|
|
68
74
|
const productId = safeProductId(product?.id);
|
|
69
75
|
const currentProductFrequencies = state.productFrequencies[productId];
|
|
70
76
|
|
|
77
|
+
let updatedProductFrequencies: ConfigState['productFrequencies'] = {
|
|
78
|
+
...state.productFrequencies,
|
|
79
|
+
[productId]: {
|
|
80
|
+
...currentProductFrequencies,
|
|
81
|
+
defaultFrequency: getUpdatedDefaultFrequency(
|
|
82
|
+
productId,
|
|
83
|
+
defaultFrequency,
|
|
84
|
+
prepaidSellingPlans,
|
|
85
|
+
currentProductFrequencies?.frequencies,
|
|
86
|
+
currentProductFrequencies?.frequenciesEveryPeriod
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
71
91
|
return {
|
|
72
92
|
...state,
|
|
73
|
-
productFrequencies:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
...currentProductFrequencies,
|
|
77
|
-
defaultFrequency: getUpdatedDefaultFrequency(
|
|
78
|
-
productId,
|
|
79
|
-
defaultFrequency,
|
|
80
|
-
prepaidSellingPlans,
|
|
81
|
-
currentProductFrequencies?.frequencies,
|
|
82
|
-
currentProductFrequencies?.frequenciesEveryPeriod
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
}
|
|
93
|
+
productFrequencies: updatedProductFrequencies,
|
|
94
|
+
// populate the old frequency fields for backwards compatibility
|
|
95
|
+
...Object.values(updatedProductFrequencies)[0]
|
|
86
96
|
};
|
|
87
97
|
}
|
|
88
98
|
|