@ordergroove/offers 2.48.6 → 2.48.7-alpha-PR-1482-3.31
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/bundle-report.html +15 -12
- package/dist/offers.js +40 -34
- package/dist/offers.js.map +4 -4
- package/package.json +2 -2
- package/src/__tests__/offers.spec.js +1 -0
- package/src/components/BenefitMessages.js +66 -0
- package/src/components/__tests__/BenefitMessages.spec.js +221 -0
- package/src/components/__tests__/OG.fspec.js +1 -0
- package/src/core/__tests__/reducer.spec.js +4 -0
- package/src/core/actions.js +11 -0
- package/src/core/constants.js +1 -0
- package/src/core/reducer.ts +13 -1
- package/src/core/types/reducer.ts +5 -1
- package/src/index.js +1 -0
- package/src/make-api.js +12 -0
- package/src/shopify/shopifyReducer.ts +3 -1
- package/tsconfig.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ordergroove/offers",
|
|
3
|
-
"version": "2.48.
|
|
3
|
+
"version": "2.48.7-alpha-PR-1482-3.31+dbac0c59c",
|
|
4
4
|
"description": "offer state component",
|
|
5
5
|
"author": "Eugenio Lattanzio <eugenio63@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/ordergroove/plush-toys#readme",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"@ordergroove/offers-templates": "^0.10.4",
|
|
51
51
|
"@types/lodash.memoize": "^4.1.9"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "dbac0c59cdfab98862e3f758ab96d6872c48cf28"
|
|
54
54
|
}
|
|
@@ -20,6 +20,7 @@ describe('Offers API', () => {
|
|
|
20
20
|
register: jasmine.any(Function),
|
|
21
21
|
resolveSettings: jasmine.any(Function),
|
|
22
22
|
setAuthUrl: jasmine.any(Function),
|
|
23
|
+
setBenefitMessages: jasmine.any(Function),
|
|
23
24
|
setEnvironment: jasmine.any(Function),
|
|
24
25
|
setLocale: jasmine.any(Function),
|
|
25
26
|
setMerchantId: jasmine.any(Function),
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { LitElement, html } from 'lit-element';
|
|
2
|
+
import { connect } from '../core/connect';
|
|
3
|
+
import { withProduct } from '../core/resolveProperties';
|
|
4
|
+
import { safeProductId } from '../core/utils';
|
|
5
|
+
|
|
6
|
+
export class BenefitMessages extends withProduct(LitElement) {
|
|
7
|
+
static get properties() {
|
|
8
|
+
return {
|
|
9
|
+
...super.properties,
|
|
10
|
+
messages: { type: Array, attribute: false }
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
createRenderRoot() {
|
|
15
|
+
return this;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
render() {
|
|
19
|
+
if (!this.messages?.length) return html``;
|
|
20
|
+
return html`
|
|
21
|
+
<ul class="og-benefit-messages">
|
|
22
|
+
${this.messages.map(
|
|
23
|
+
msg => html`
|
|
24
|
+
<li>${msg}</li>
|
|
25
|
+
`
|
|
26
|
+
)}
|
|
27
|
+
</ul>
|
|
28
|
+
`;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Walks the product's applicable incentives (initial first, then ongoing) and
|
|
34
|
+
* returns the deduped list of messages — one per unique incentive id that
|
|
35
|
+
* (a) was present in the offer response's `incentives_display_enhanced` and
|
|
36
|
+
* (b) has a configured benefit message. Either array (initial / ongoing) may
|
|
37
|
+
* be absent. Returns an empty array when no qualifying incentive has a
|
|
38
|
+
* matching message.
|
|
39
|
+
*/
|
|
40
|
+
export const mapStateToProps = (state, ownProps) => {
|
|
41
|
+
const productId = safeProductId(ownProps?.product?.id);
|
|
42
|
+
const productIncentives = (state.incentives || {})[productId];
|
|
43
|
+
const benefitMap = state.benefitMessages || {};
|
|
44
|
+
|
|
45
|
+
if (!productIncentives) return { messages: [] };
|
|
46
|
+
|
|
47
|
+
const seen = new Set();
|
|
48
|
+
const messages = [];
|
|
49
|
+
|
|
50
|
+
[productIncentives.initial, productIncentives.ongoing].forEach(list => {
|
|
51
|
+
(list || []).forEach(incentive => {
|
|
52
|
+
if (!incentive?.enhanced) return;
|
|
53
|
+
const id = incentive.id;
|
|
54
|
+
if (!id || seen.has(id)) return;
|
|
55
|
+
seen.add(id);
|
|
56
|
+
const msg = benefitMap[id];
|
|
57
|
+
if (msg) messages.push(msg);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return { messages };
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const ConnectedBenefitMessages = connect(mapStateToProps)(BenefitMessages);
|
|
65
|
+
|
|
66
|
+
export default ConnectedBenefitMessages;
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { BenefitMessages, mapStateToProps } from '../BenefitMessages';
|
|
2
|
+
import { appendToBody } from './utils';
|
|
3
|
+
|
|
4
|
+
customElements.define('og-benefit-messages-test', BenefitMessages);
|
|
5
|
+
|
|
6
|
+
describe('BenefitMessages', () => {
|
|
7
|
+
it('renders one li per message inside a ul', async () => {
|
|
8
|
+
const el = new BenefitMessages();
|
|
9
|
+
el.messages = ['Free shipping', 'Cancel anytime', '5% off every order'];
|
|
10
|
+
await appendToBody(el);
|
|
11
|
+
|
|
12
|
+
const ul = el.querySelector('ul.og-benefit-messages');
|
|
13
|
+
expect(ul).toBeTruthy();
|
|
14
|
+
const items = el.querySelectorAll('li');
|
|
15
|
+
expect(items.length).toBe(3);
|
|
16
|
+
expect(items[0].textContent.trim()).toBe('Free shipping');
|
|
17
|
+
expect(items[1].textContent.trim()).toBe('Cancel anytime');
|
|
18
|
+
expect(items[2].textContent.trim()).toBe('5% off every order');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('renders nothing when messages is an empty array', async () => {
|
|
22
|
+
const el = new BenefitMessages();
|
|
23
|
+
el.messages = [];
|
|
24
|
+
await appendToBody(el);
|
|
25
|
+
|
|
26
|
+
expect(el.querySelector('ul')).toBeNull();
|
|
27
|
+
expect(el.querySelectorAll('li').length).toBe(0);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('renders nothing when messages is undefined', async () => {
|
|
31
|
+
const el = new BenefitMessages();
|
|
32
|
+
await appendToBody(el);
|
|
33
|
+
|
|
34
|
+
expect(el.querySelector('ul')).toBeNull();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('escapes message strings as text (no HTML interpolation)', async () => {
|
|
38
|
+
const el = new BenefitMessages();
|
|
39
|
+
el.messages = ['<img src=x onerror="alert(1)">'];
|
|
40
|
+
await appendToBody(el);
|
|
41
|
+
|
|
42
|
+
const li = el.querySelector('li');
|
|
43
|
+
expect(li).toBeTruthy();
|
|
44
|
+
expect(li.querySelector('img')).toBeNull();
|
|
45
|
+
expect(li.textContent.trim()).toBe('<img src=x onerror="alert(1)">');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('re-renders correctly after disconnect and reconnect', async () => {
|
|
49
|
+
const el = new BenefitMessages();
|
|
50
|
+
el.messages = ['First'];
|
|
51
|
+
await appendToBody(el);
|
|
52
|
+
expect(el.querySelector('li').textContent.trim()).toBe('First');
|
|
53
|
+
|
|
54
|
+
el.remove();
|
|
55
|
+
|
|
56
|
+
el.messages = ['After remount A', 'After remount B'];
|
|
57
|
+
await appendToBody(el);
|
|
58
|
+
|
|
59
|
+
const items = el.querySelectorAll('li');
|
|
60
|
+
expect(items.length).toBe(2);
|
|
61
|
+
expect(items[0].textContent.trim()).toBe('After remount A');
|
|
62
|
+
expect(items[1].textContent.trim()).toBe('After remount B');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('BenefitMessages mapStateToProps', () => {
|
|
67
|
+
const state = ({ incentivesForProduct, benefitMessages, productId = 'prod-1' } = {}) => ({
|
|
68
|
+
incentives: incentivesForProduct ? { [productId]: incentivesForProduct } : {},
|
|
69
|
+
benefitMessages: benefitMessages || {}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('returns messages for the product, initial first then ongoing', () => {
|
|
73
|
+
expect(
|
|
74
|
+
mapStateToProps(
|
|
75
|
+
state({
|
|
76
|
+
incentivesForProduct: {
|
|
77
|
+
initial: [{ enhanced: true, id: 'inc-init' }],
|
|
78
|
+
ongoing: [{ enhanced: true, id: 'inc-ongoing' }]
|
|
79
|
+
},
|
|
80
|
+
benefitMessages: {
|
|
81
|
+
'inc-init': 'First-order bonus',
|
|
82
|
+
'inc-ongoing': 'Every-order discount'
|
|
83
|
+
}
|
|
84
|
+
}),
|
|
85
|
+
{ product: { id: 'prod-1' } }
|
|
86
|
+
)
|
|
87
|
+
).toEqual({ messages: ['First-order bonus', 'Every-order discount'] });
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('dedupes by incentive id when the same id appears in both initial and ongoing', () => {
|
|
91
|
+
expect(
|
|
92
|
+
mapStateToProps(
|
|
93
|
+
state({
|
|
94
|
+
incentivesForProduct: {
|
|
95
|
+
initial: [{ enhanced: true, id: 'inc-shared' }],
|
|
96
|
+
ongoing: [
|
|
97
|
+
{ enhanced: true, id: 'inc-shared' },
|
|
98
|
+
{ enhanced: true, id: 'inc-extra' }
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
benefitMessages: {
|
|
102
|
+
'inc-shared': 'Shared',
|
|
103
|
+
'inc-extra': 'Extra'
|
|
104
|
+
}
|
|
105
|
+
}),
|
|
106
|
+
{ product: { id: 'prod-1' } }
|
|
107
|
+
)
|
|
108
|
+
).toEqual({ messages: ['Shared', 'Extra'] });
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('skips incentives that have no configured message', () => {
|
|
112
|
+
expect(
|
|
113
|
+
mapStateToProps(
|
|
114
|
+
state({
|
|
115
|
+
incentivesForProduct: {
|
|
116
|
+
initial: [
|
|
117
|
+
{ enhanced: true, id: 'inc-1' },
|
|
118
|
+
{ enhanced: true, id: 'inc-2' }
|
|
119
|
+
],
|
|
120
|
+
ongoing: [{ enhanced: true, id: 'inc-3' }]
|
|
121
|
+
},
|
|
122
|
+
benefitMessages: {
|
|
123
|
+
'inc-2': 'Only this one is configured'
|
|
124
|
+
}
|
|
125
|
+
}),
|
|
126
|
+
{ product: { id: 'prod-1' } }
|
|
127
|
+
)
|
|
128
|
+
).toEqual({ messages: ['Only this one is configured'] });
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('handles missing initial array (only ongoing)', () => {
|
|
132
|
+
expect(
|
|
133
|
+
mapStateToProps(
|
|
134
|
+
state({
|
|
135
|
+
incentivesForProduct: { ongoing: [{ enhanced: true, id: 'inc-1' }] },
|
|
136
|
+
benefitMessages: { 'inc-1': 'Ongoing only' }
|
|
137
|
+
}),
|
|
138
|
+
{ product: { id: 'prod-1' } }
|
|
139
|
+
)
|
|
140
|
+
).toEqual({ messages: ['Ongoing only'] });
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('handles missing ongoing array (only initial)', () => {
|
|
144
|
+
expect(
|
|
145
|
+
mapStateToProps(
|
|
146
|
+
state({
|
|
147
|
+
incentivesForProduct: { initial: [{ enhanced: true, id: 'inc-1' }] },
|
|
148
|
+
benefitMessages: { 'inc-1': 'Initial only' }
|
|
149
|
+
}),
|
|
150
|
+
{ product: { id: 'prod-1' } }
|
|
151
|
+
)
|
|
152
|
+
).toEqual({ messages: ['Initial only'] });
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('returns [] when both initial and ongoing are empty', () => {
|
|
156
|
+
expect(
|
|
157
|
+
mapStateToProps(
|
|
158
|
+
state({
|
|
159
|
+
incentivesForProduct: { initial: [], ongoing: [] },
|
|
160
|
+
benefitMessages: { 'inc-1': 'Should not appear' }
|
|
161
|
+
}),
|
|
162
|
+
{ product: { id: 'prod-1' } }
|
|
163
|
+
)
|
|
164
|
+
).toEqual({ messages: [] });
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('returns [] when the product has no incentives entry', () => {
|
|
168
|
+
expect(
|
|
169
|
+
mapStateToProps(
|
|
170
|
+
{ incentives: {}, benefitMessages: { 'inc-1': 'Should not appear' } },
|
|
171
|
+
{ product: { id: 'prod-1' } }
|
|
172
|
+
)
|
|
173
|
+
).toEqual({ messages: [] });
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('returns [] when state has no benefitMessages key', () => {
|
|
177
|
+
expect(
|
|
178
|
+
mapStateToProps(
|
|
179
|
+
{ incentives: { 'prod-1': { initial: [{ enhanced: true, id: 'inc-1' }], ongoing: [] } } },
|
|
180
|
+
{ product: { id: 'prod-1' } }
|
|
181
|
+
)
|
|
182
|
+
).toEqual({ messages: [] });
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('returns [] when no incentive has a matching message', () => {
|
|
186
|
+
expect(
|
|
187
|
+
mapStateToProps(
|
|
188
|
+
state({
|
|
189
|
+
incentivesForProduct: {
|
|
190
|
+
initial: [{ enhanced: true, id: 'inc-1' }],
|
|
191
|
+
ongoing: [{ enhanced: true, id: 'inc-2' }]
|
|
192
|
+
},
|
|
193
|
+
benefitMessages: { 'inc-other': 'Unrelated' }
|
|
194
|
+
}),
|
|
195
|
+
{ product: { id: 'prod-1' } }
|
|
196
|
+
)
|
|
197
|
+
).toEqual({ messages: [] });
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('returns [] when ownProps has no product', () => {
|
|
201
|
+
expect(mapStateToProps({ benefitMessages: { 'inc-1': 'm' } }, {})).toEqual({ messages: [] });
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('skips incentives that were not in incentives_display_enhanced', () => {
|
|
205
|
+
expect(
|
|
206
|
+
mapStateToProps(
|
|
207
|
+
state({
|
|
208
|
+
incentivesForProduct: {
|
|
209
|
+
initial: [{ id: 'inc-non-enhanced' }, { enhanced: true, id: 'inc-enhanced' }],
|
|
210
|
+
ongoing: []
|
|
211
|
+
},
|
|
212
|
+
benefitMessages: {
|
|
213
|
+
'inc-non-enhanced': 'Should not appear',
|
|
214
|
+
'inc-enhanced': 'Should appear'
|
|
215
|
+
}
|
|
216
|
+
}),
|
|
217
|
+
{ product: { id: 'prod-1' } }
|
|
218
|
+
)
|
|
219
|
+
).toEqual({ messages: ['Should appear'] });
|
|
220
|
+
});
|
|
221
|
+
});
|
|
@@ -68,6 +68,7 @@ describe('og.offers', function () {
|
|
|
68
68
|
register: jasmine.any(Function),
|
|
69
69
|
resolveSettings: jasmine.any(Function),
|
|
70
70
|
setAuthUrl: jasmine.any(Function),
|
|
71
|
+
setBenefitMessages: jasmine.any(Function),
|
|
71
72
|
setEnvironment: jasmine.any(Function),
|
|
72
73
|
setLocale: jasmine.any(Function),
|
|
73
74
|
setMerchantId: jasmine.any(Function),
|
|
@@ -1140,6 +1140,7 @@ describe('reducers', () => {
|
|
|
1140
1140
|
type: 'Discount Percent',
|
|
1141
1141
|
value: 10.0,
|
|
1142
1142
|
id: '8285f16f826e4cf29b49f073e45e32ab',
|
|
1143
|
+
enhanced: true,
|
|
1143
1144
|
threshold_field: null,
|
|
1144
1145
|
threshold_value: null,
|
|
1145
1146
|
criteria: {
|
|
@@ -1154,6 +1155,7 @@ describe('reducers', () => {
|
|
|
1154
1155
|
type: 'Discount Percent',
|
|
1155
1156
|
value: 20.0,
|
|
1156
1157
|
id: 'threshold-id',
|
|
1158
|
+
enhanced: true,
|
|
1157
1159
|
threshold_field: 'order',
|
|
1158
1160
|
threshold_value: '10.00',
|
|
1159
1161
|
criteria: {
|
|
@@ -1168,6 +1170,7 @@ describe('reducers', () => {
|
|
|
1168
1170
|
type: 'Discount Amount',
|
|
1169
1171
|
value: 5.0,
|
|
1170
1172
|
id: '10205e185a5c4ccf83de75459241623a',
|
|
1173
|
+
enhanced: true,
|
|
1171
1174
|
threshold_field: null,
|
|
1172
1175
|
threshold_value: null,
|
|
1173
1176
|
criteria: {
|
|
@@ -1184,6 +1187,7 @@ describe('reducers', () => {
|
|
|
1184
1187
|
type: 'Discount Percent',
|
|
1185
1188
|
value: 11.0,
|
|
1186
1189
|
id: '0f98a321d29e47d2a17fe3a8a7522d26',
|
|
1190
|
+
enhanced: true,
|
|
1187
1191
|
threshold_field: null,
|
|
1188
1192
|
threshold_value: null,
|
|
1189
1193
|
criteria: {
|
package/src/core/actions.js
CHANGED
|
@@ -296,6 +296,17 @@ export const setConfig = payload => ({
|
|
|
296
296
|
payload
|
|
297
297
|
});
|
|
298
298
|
|
|
299
|
+
/**
|
|
300
|
+
* Set benefit messages keyed by incentive public id. Each value is the
|
|
301
|
+
* already-locale-resolved message text to display when the incentive applies
|
|
302
|
+
* to the product being rendered. Replaces the entire map on each call.
|
|
303
|
+
* @param {{ [incentivePublicId: string]: string }} payload
|
|
304
|
+
*/
|
|
305
|
+
export const setBenefitMessages = payload => ({
|
|
306
|
+
type: constants.SET_BENEFIT_MESSAGES,
|
|
307
|
+
payload
|
|
308
|
+
});
|
|
309
|
+
|
|
299
310
|
export const addTemplate = (selector, markup, config) => ({
|
|
300
311
|
type: constants.ADD_TEMPLATE,
|
|
301
312
|
payload: { selector, markup, config }
|
package/src/core/constants.js
CHANGED
|
@@ -32,6 +32,7 @@ export const CHECKOUT = 'CHECKOUT';
|
|
|
32
32
|
export const RECEIVE_FETCH = 'RECEIVE_FETCH';
|
|
33
33
|
export const SET_LOCALE = 'SET_LOCALE';
|
|
34
34
|
export const SET_CONFIG = 'SET_CONFIG';
|
|
35
|
+
export const SET_BENEFIT_MESSAGES = 'SET_BENEFIT_MESSAGES';
|
|
35
36
|
export const SET_PREVIEW_STANDARD_OFFER = 'SET_PREVIEW_STANDARD_OFFER';
|
|
36
37
|
export const SET_PREVIEW_UPSELL_OFFER = 'SET_PREVIEW_UPSELL_OFFER';
|
|
37
38
|
export const SET_PREVIEW_PREPAID_OFFER = 'SET_PREVIEW_PREPAID_OFFER';
|
package/src/core/reducer.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { experimentsReducer } from './experiments';
|
|
|
9
9
|
import {
|
|
10
10
|
AutoshipByDefaultState,
|
|
11
11
|
AutoshipEligibleState,
|
|
12
|
+
BenefitMessagesState,
|
|
12
13
|
ConfigState,
|
|
13
14
|
Incentive,
|
|
14
15
|
IncentiveObject,
|
|
@@ -176,6 +177,7 @@ const mapIncentive = (
|
|
|
176
177
|
// for standard incentives, include the criteria so we know which kind of incentive (e.g. PSI, prepaid, etc)
|
|
177
178
|
...(enhanced
|
|
178
179
|
? {
|
|
180
|
+
enhanced: true,
|
|
179
181
|
criteria: enhanced.criteria
|
|
180
182
|
? enhanced.criteria
|
|
181
183
|
: // when there is no criteria in the enhanced incentive, it means it's a program wide incentive
|
|
@@ -570,6 +572,15 @@ export const prepaidShipmentsSelected = (
|
|
|
570
572
|
|
|
571
573
|
export const price = (state: PriceState = {}, _action) => state;
|
|
572
574
|
|
|
575
|
+
export const benefitMessages = (state: BenefitMessagesState = {}, action): BenefitMessagesState => {
|
|
576
|
+
switch (action.type) {
|
|
577
|
+
case constants.SET_BENEFIT_MESSAGES:
|
|
578
|
+
return { ...(action.payload || {}) };
|
|
579
|
+
default:
|
|
580
|
+
return state;
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
|
|
573
584
|
export default combineReducers({
|
|
574
585
|
optedin,
|
|
575
586
|
optedout,
|
|
@@ -599,5 +610,6 @@ export default combineReducers({
|
|
|
599
610
|
templates,
|
|
600
611
|
productPlans,
|
|
601
612
|
prepaidShipmentsSelected,
|
|
602
|
-
price
|
|
613
|
+
price,
|
|
614
|
+
benefitMessages
|
|
603
615
|
});
|
|
@@ -17,11 +17,15 @@ export type NextUpcomingOrderState = Partial<
|
|
|
17
17
|
|
|
18
18
|
export type IncentivesState = Record<string, IncentiveObject>;
|
|
19
19
|
|
|
20
|
+
export type BenefitMessagesState = Record<string, string>;
|
|
21
|
+
|
|
20
22
|
export type Incentive = ApiIncentive & {
|
|
21
23
|
id: string;
|
|
22
24
|
/**
|
|
23
|
-
*
|
|
25
|
+
* True when the incentive id was present in `incentives_display_enhanced`
|
|
26
|
+
* on the offer response. The fields below are only populated in that case.
|
|
24
27
|
*/
|
|
28
|
+
enhanced?: boolean;
|
|
25
29
|
threshold_field?: string | null;
|
|
26
30
|
threshold_value?: string | null;
|
|
27
31
|
criteria?: {
|
package/src/index.js
CHANGED
|
@@ -28,6 +28,7 @@ export const previewMode = offers.previewMode;
|
|
|
28
28
|
export const register = offers.register;
|
|
29
29
|
export const resolveSettings = offers.resolveSettings;
|
|
30
30
|
export const setAuthUrl = offers.setAuthUrl;
|
|
31
|
+
export const setBenefitMessages = offers.setBenefitMessages;
|
|
31
32
|
export const setEnvironment = offers.setEnvironment;
|
|
32
33
|
export const setLocale = offers.setLocale;
|
|
33
34
|
export const setMerchantId = offers.setMerchantId;
|
package/src/make-api.js
CHANGED
|
@@ -12,6 +12,7 @@ import { ConnectedOptinToggle } from './components/OptinToggle';
|
|
|
12
12
|
import { ConnectedOptinStatus } from './components/OptinStatus';
|
|
13
13
|
import { ConnectedText } from './components/Text';
|
|
14
14
|
import { ConnectedIncentiveText } from './components/IncentiveText';
|
|
15
|
+
import { ConnectedBenefitMessages } from './components/BenefitMessages';
|
|
15
16
|
import { ConnectedSelectFrequency } from './components/SelectFrequency';
|
|
16
17
|
import { ConnectedNextUpcomingOrder } from './components/NextUpcomingOrder';
|
|
17
18
|
import { ConnectedOffer } from './components/Offer';
|
|
@@ -38,6 +39,7 @@ export default function makeApi(store) {
|
|
|
38
39
|
customElements.define('og-when', ConnectedWhen);
|
|
39
40
|
customElements.define('og-text', ConnectedText);
|
|
40
41
|
customElements.define('og-incentive-text', ConnectedIncentiveText);
|
|
42
|
+
customElements.define('og-benefit-messages', ConnectedBenefitMessages);
|
|
41
43
|
customElements.define('og-offer', ConnectedOffer);
|
|
42
44
|
customElements.define('og-select-frequency', ConnectedSelectFrequency);
|
|
43
45
|
customElements.define('og-optout-button', ConnectedOptoutButton);
|
|
@@ -121,6 +123,16 @@ export default function makeApi(store) {
|
|
|
121
123
|
store.dispatch(actions.setLocale(locale));
|
|
122
124
|
return this;
|
|
123
125
|
},
|
|
126
|
+
/**
|
|
127
|
+
* Set benefit messages keyed by incentive public id. Each value is the
|
|
128
|
+
* already-locale-resolved message text to display when the incentive
|
|
129
|
+
* applies to the product being rendered. Replaces the entire map.
|
|
130
|
+
* @param {{ [incentivePublicId: string]: string }} messages
|
|
131
|
+
*/
|
|
132
|
+
setBenefitMessages(messages) {
|
|
133
|
+
store.dispatch(actions.setBenefitMessages(messages));
|
|
134
|
+
return this;
|
|
135
|
+
},
|
|
124
136
|
addTemplate(tagName, content, configOption) {
|
|
125
137
|
store.dispatch(actions.addTemplate(tagName, content, configOption));
|
|
126
138
|
return this;
|
|
@@ -5,6 +5,7 @@ import baseReducer, {
|
|
|
5
5
|
autoshipByDefault,
|
|
6
6
|
auth,
|
|
7
7
|
authUrl,
|
|
8
|
+
benefitMessages,
|
|
8
9
|
defaultFrequencies,
|
|
9
10
|
eligibilityGroups,
|
|
10
11
|
environment,
|
|
@@ -433,7 +434,8 @@ const reducer = combineReducers({
|
|
|
433
434
|
productToSubscribe,
|
|
434
435
|
sessionId,
|
|
435
436
|
templates,
|
|
436
|
-
prepaidShipmentsSelected
|
|
437
|
+
prepaidShipmentsSelected,
|
|
438
|
+
benefitMessages
|
|
437
439
|
});
|
|
438
440
|
|
|
439
441
|
export default function shopifyReducer(state, action) {
|