@ordergroove/offers 2.29.0 → 2.29.1-alpha-PR-707-2.113

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.
Files changed (37) hide show
  1. package/README.md +22 -1
  2. package/dist/bundle-report.html +72 -59
  3. package/dist/examples.js +262 -105
  4. package/dist/examples.js.map +2 -2
  5. package/dist/offers.js +82 -32
  6. package/dist/offers.js.map +3 -3
  7. package/examples/index.js +230 -218
  8. package/package.json +2 -2
  9. package/src/components/PrepaidData.js +110 -0
  10. package/src/components/PrepaidToggle.js +108 -0
  11. package/src/components/Price.js +6 -6
  12. package/src/components/Select.js +6 -1
  13. package/src/components/__tests__/PrepaidData.spec.js +173 -0
  14. package/src/components/__tests__/PrepaidToggle.spec.js +115 -0
  15. package/src/components/__tests__/Price.spec.js +96 -0
  16. package/src/core/__tests__/adapters.spec.js +232 -1
  17. package/src/core/__tests__/descriptors.spec.js +56 -0
  18. package/src/core/__tests__/reducer.spec.js +153 -1
  19. package/src/core/__tests__/selectors.spec.js +34 -1
  20. package/src/core/actions.js +5 -0
  21. package/src/core/adapters.js +48 -2
  22. package/src/core/constants.js +1 -0
  23. package/src/core/descriptors.js +7 -1
  24. package/src/core/reducer.js +35 -14
  25. package/src/core/selectors.js +32 -0
  26. package/src/core/utils.ts +16 -0
  27. package/src/make-api.js +4 -0
  28. package/src/shopify/__tests__/productPlan.spec.js +513 -0
  29. package/src/shopify/__tests__/shopifyReducer.spec.js +630 -19
  30. package/src/shopify/__tests__/utils.spec.js +25 -0
  31. package/src/shopify/reducers/productPlans.ts +134 -0
  32. package/src/shopify/shopifyMiddleware.ts +3 -0
  33. package/src/shopify/shopifyReducer.js +96 -47
  34. package/src/shopify/shopifyTrackingMiddleware.ts +1 -1
  35. package/src/shopify/types/productPlan.ts +11 -0
  36. package/src/shopify/types/shopify.ts +98 -0
  37. package/src/shopify/utils.ts +3 -0
package/examples/index.js CHANGED
@@ -11,7 +11,23 @@ window.og_settings = {
11
11
  UD729: {
12
12
  '3_1': ['30.00', '10%', '$27.00'],
13
13
  '1_2': ['30.00', '20%', '$24.00']
14
- }
14
+ },
15
+ UD728: [
16
+ {
17
+ frequency: '1_2',
18
+ prepaidShipments: '3',
19
+ regularPrice: '$15.00',
20
+ subscriptionPrice: '$13.50',
21
+ discountRate: '10%'
22
+ },
23
+ {
24
+ frequency: '3_1',
25
+ prepaidShipments: null,
26
+ regularPrice: '$15.00',
27
+ subscriptionPrice: '$12.00',
28
+ discountRate: '20%'
29
+ }
30
+ ]
15
31
  }
16
32
  };
17
33
 
@@ -63,162 +79,158 @@ const textCopy = {
63
79
  defaultFrequencyCopy: '(Recommended)'
64
80
  };
65
81
 
66
- const exampleTemplates = [
67
- [
68
- 'Offers example',
69
- {
70
- name: 'empty',
71
- selector: 'og-offer:not([location])',
72
- id: '1'
73
- },
74
- {
75
- name: 'built-in',
76
- selector: 'og-offer[location="initial"]',
77
- id: '2',
78
- config: {
79
- settings: {
80
- ...settings,
81
- offerType: 'radio'
82
- },
83
- textCopy: { ...textCopy }
84
- }
85
- },
86
- {
87
- name: 'checkbox',
88
- selector: 'og-offer[location="initial-checkbox"]',
89
- id: '3',
90
- config: {
91
- settings: {
92
- ...settings,
93
- offerType: 'toggle'
94
- },
95
- textCopy: {
96
- ...textCopy
97
- }
98
- }
99
- },
100
- {
101
- name: 'select',
102
- selector: 'og-offer[location="initial-select"]',
103
- id: '4',
104
- config: {
105
- settings: {
106
- ...settings,
107
- offerType: 'select'
108
- },
109
- textCopy: { ...textCopy }
110
- }
111
- },
112
- {
113
- name: 'cart',
114
- selector: 'og-offer[location="cart"]',
115
- id: '5',
116
- defaultPreviewMode: 'subscribed',
117
- config: {
118
- settings: {
119
- ...settings,
120
- offerType: 'cart'
121
- },
122
- textCopy: { ...textCopy }
82
+ const offersExamples = [
83
+ {
84
+ name: 'empty',
85
+ selector: 'og-offer:not([location])'
86
+ },
87
+ {
88
+ name: 'built-in',
89
+ selector: 'og-offer[location="initial"]',
90
+ config: {
91
+ settings: {
92
+ ...settings,
93
+ offerType: 'radio'
94
+ },
95
+ textCopy: { ...textCopy }
96
+ }
97
+ },
98
+ {
99
+ name: 'checkbox',
100
+ selector: 'og-offer[location="initial-checkbox"]',
101
+ config: {
102
+ settings: {
103
+ ...settings,
104
+ offerType: 'toggle'
105
+ },
106
+ textCopy: {
107
+ ...textCopy
123
108
  }
124
- },
125
- {
126
- name: 'side-by-side',
127
- selector: 'og-offer[location="side-by-side"]',
128
- id: '6',
129
- config: {
130
- settings: {
131
- ...settings,
132
- offerType: 'side-by-side'
133
- },
134
- textCopy: { ...textCopy },
135
- styles: {
136
- primaryColor: 'navy',
137
- defaultColor: 'pink'
138
- }
109
+ }
110
+ },
111
+ {
112
+ name: 'select',
113
+ selector: 'og-offer[location="initial-select"]',
114
+ config: {
115
+ settings: {
116
+ ...settings,
117
+ offerType: 'select'
118
+ },
119
+ textCopy: { ...textCopy }
120
+ }
121
+ },
122
+ {
123
+ name: 'cart',
124
+ selector: 'og-offer[location="cart"]',
125
+ defaultPreviewMode: 'subscribed',
126
+ config: {
127
+ settings: {
128
+ ...settings,
129
+ offerType: 'cart'
130
+ },
131
+ textCopy: { ...textCopy }
132
+ }
133
+ },
134
+ {
135
+ name: 'side-by-side',
136
+ selector: 'og-offer[location="side-by-side"]',
137
+ config: {
138
+ settings: {
139
+ ...settings,
140
+ offerType: 'side-by-side'
141
+ },
142
+ textCopy: { ...textCopy },
143
+ styles: {
144
+ primaryColor: 'navy',
145
+ defaultColor: 'pink'
139
146
  }
140
- },
141
- {
142
- name: 'read-only',
143
- selector: 'og-offer[location="read-only"]',
144
- id: '7',
145
- defaultPreviewMode: 'subscribed',
146
- config: {
147
- settings: {
148
- ...settings,
149
- offerType: 'read-only'
150
- },
151
- textCopy: { ...textCopy },
152
- styles: {
153
- primaryColor: 'navy',
154
- defaultColor: 'pink'
155
- }
147
+ }
148
+ },
149
+ {
150
+ name: 'read-only',
151
+ selector: 'og-offer[location="read-only"]',
152
+ defaultPreviewMode: 'subscribed',
153
+ config: {
154
+ settings: {
155
+ ...settings,
156
+ offerType: 'read-only'
157
+ },
158
+ textCopy: { ...textCopy },
159
+ styles: {
160
+ primaryColor: 'navy',
161
+ defaultColor: 'pink'
156
162
  }
157
- },
158
- {
159
- name: 'buttons',
160
- selector: 'og-offer[location="buttons"]',
161
- id: '8',
162
- config: {
163
- settings: {
164
- ...settings,
165
- offerType: 'buttons'
166
- },
167
- textCopy: { ...textCopy },
168
- styles: {
169
- primaryColor: 'navy',
170
- defaultColor: 'pink'
171
- }
163
+ }
164
+ },
165
+ {
166
+ name: 'buttons',
167
+ selector: 'og-offer[location="buttons"]',
168
+ config: {
169
+ settings: {
170
+ ...settings,
171
+ offerType: 'buttons'
172
+ },
173
+ textCopy: { ...textCopy },
174
+ styles: {
175
+ primaryColor: 'navy',
176
+ defaultColor: 'pink'
172
177
  }
173
- },
174
-
175
- {
176
- name: 'first-test',
177
- selector: 'og-offer[location="first-test"]',
178
- id: '9',
179
- config: {
180
- settings: {
181
- ...settings,
182
- offerType: 'toggle'
183
- },
184
- textCopy: {
185
- ...textCopy,
186
- offerOptOutLabel: '1st offerOptOutLabel'
187
- }
178
+ }
179
+ },
180
+ {
181
+ name: 'Prepaid',
182
+ selector: 'og-offer[location="initial"]',
183
+ config: {
184
+ settings: {
185
+ ...settings,
186
+ offerType: 'prepaid-enabled-radio'
187
+ },
188
+ textCopy: { ...textCopy }
189
+ }
190
+ },
191
+ {
192
+ name: 'first-test',
193
+ selector: 'og-offer[location="first-test"]',
194
+ config: {
195
+ settings: {
196
+ ...settings,
197
+ offerType: 'toggle'
198
+ },
199
+ textCopy: {
200
+ ...textCopy,
201
+ offerOptOutLabel: '1st offerOptOutLabel'
188
202
  }
189
- },
190
- {
191
- name: 'second-test no tooltip',
192
- selector: 'og-offer[location="second-test"]',
193
- id: '10',
194
- config: {
195
- settings: {
196
- ...settings,
197
- offerType: 'radio'
198
- },
199
- textCopy: {
200
- ...textCopy,
201
- showTooltip: false,
202
- offerOptOutLabel: '2st offerOptOutLabel'
203
- }
203
+ }
204
+ },
205
+ {
206
+ name: 'second-test no tooltip',
207
+ selector: 'og-offer[location="second-test"]',
208
+ config: {
209
+ settings: {
210
+ ...settings,
211
+ offerType: 'radio'
212
+ },
213
+ textCopy: {
214
+ ...textCopy,
215
+ showTooltip: false,
216
+ offerOptOutLabel: '2st offerOptOutLabel'
204
217
  }
205
- },
206
- {
207
- name: 'Select mode',
208
- selector: 'og-offer[location="select1"]',
209
- id: '11',
210
- markup: `
218
+ }
219
+ },
220
+ {
221
+ name: 'Select mode',
222
+ selector: 'og-offer[location="select1"]',
223
+ markup: `
211
224
  <og-optin-select>
212
225
  <option value="optedOut">Buy one time</option>
213
226
  <option value="2w" selected>2 weeks (recomended)</option>
214
227
  <option value="1m">1 month </option>
215
228
  </og-optin-select>`
216
- },
217
- {
218
- name: 'Custom markup',
219
- selector: 'og-offer[location="custom1"]',
220
- id: '12',
221
- markup: `
229
+ },
230
+ {
231
+ name: 'Custom markup',
232
+ selector: 'og-offer[location="custom1"]',
233
+ markup: `
222
234
  <og-when test="regularEligible">
223
235
  <p>
224
236
  <og-optout-button>Buy one time</og-optout-button>
@@ -266,13 +278,12 @@ Add item to order on
266
278
  <span slot="cancel">cancel</span>
267
279
  </og-upsell-modal>
268
280
  </og-when>`
269
- },
270
- {
271
- name: 'Upsell modal - radio',
272
- defaultPreviewMode: 'upsell',
273
- selector: 'og-offer[location="upsell-radio"]',
274
- id: '13',
275
- markup: `
281
+ },
282
+ {
283
+ name: 'Upsell modal - radio',
284
+ defaultPreviewMode: 'upsell',
285
+ selector: 'og-offer[location="upsell-radio"]',
286
+ markup: `
276
287
  <og-when test="upsellEligible">
277
288
  <og-upsell-button target="#upsell-radio">
278
289
  <a href="#">Add item to next order via radio</a>
@@ -291,13 +302,12 @@ Add item to order on
291
302
  </p>
292
303
  </og-upsell-modal>
293
304
  </og-when>`
294
- },
295
- {
296
- name: 'Upsell modal - select',
297
- defaultPreviewMode: 'upsell',
298
- selector: 'og-offer[location="upsell-select"]',
299
- id: '14',
300
- markup: `
305
+ },
306
+ {
307
+ name: 'Upsell modal - select',
308
+ defaultPreviewMode: 'upsell',
309
+ selector: 'og-offer[location="upsell-select"]',
310
+ markup: `
301
311
  <og-when test="upsellEligible">
302
312
  <og-upsell-button target="#upsell-select">
303
313
  <a href="#">Add item to next order via select</a>
@@ -306,13 +316,12 @@ Add item to order on
306
316
  <og-optin-select></og-optin-select>
307
317
  </og-upsell-modal>
308
318
  </og-when>`
309
- },
310
- {
311
- name: 'Upsell modal - toggle',
312
- defaultPreviewMode: 'upsell',
313
- selector: 'og-offer[location="upsell-toggle"]',
314
- id: '15',
315
- markup: `
319
+ },
320
+ {
321
+ name: 'Upsell modal - toggle',
322
+ defaultPreviewMode: 'upsell',
323
+ selector: 'og-offer[location="upsell-toggle"]',
324
+ markup: `
316
325
  <og-when test="upsellEligible">
317
326
  <og-upsell-button target="#upsell-toggle">
318
327
  <a href="#">Add item to next order via toggle</a>
@@ -325,13 +334,12 @@ Add item to order on
325
334
  <span slot="cancel">Nope</span>
326
335
  </og-upsell-modal>
327
336
  </og-when>
328
- `
329
- },
330
- {
331
- name: 'Product-specific default frequencies',
332
- selector: 'og-offer[location="psdf"]',
333
- id: '16',
334
- markup: `
337
+ `
338
+ },
339
+ {
340
+ name: 'Product-specific default frequencies',
341
+ selector: 'og-offer[location="psdf"]',
342
+ markup: `
335
343
  <og-when test="regularEligible">
336
344
  <og-select-frequency default-text=" Most common!">
337
345
  <option value="1w">1 week</option>
@@ -339,56 +347,60 @@ Add item to order on
339
347
  <option value="3w">3 weeks</option>
340
348
  </og-select-frequency>
341
349
  </og-when>
342
- `
343
- }
344
- ],
345
- [
346
- 'Individual components',
347
- {
348
- name: 'og-optin-button',
349
- selector: 'og-offer[location=og-optin-button]',
350
- id: '17',
351
- markup: `
350
+ `
351
+ }
352
+ ];
353
+
354
+ const componentExamples = [
355
+ {
356
+ name: 'og-optin-button',
357
+ selector: 'og-offer[location=og-optin-button]',
358
+ markup: `
352
359
  <og-optin-button>
353
360
  I want to subscribe to this product
354
361
  </og-optin-button>
355
- `
356
- },
357
- {
358
- name: 'Frequency Status',
359
- selector: 'og-offer[location="frequency"]',
360
- id: '18',
361
- markup: `
362
+ `
363
+ },
364
+ {
365
+ name: 'Frequency Status',
366
+ selector: 'og-offer[location="frequency"]',
367
+ markup: `
362
368
  <og-frequency-status>
363
369
  <span slot="not-subscribed">you are not subscribed </span>
364
370
  </og-frequency-status>`
365
- },
366
- {
367
- name: 'Tooltip',
368
- selector: 'og-offer[location="tooltip-placement"]',
369
- id: '19',
370
- markup: [
371
- ['top-left', 'top', 'top-right'],
372
- ['left', '', 'right'],
373
- ['bottom-left', 'bottom', 'bottom-right']
374
- ]
375
- .map(options =>
376
- options
377
- .map(
378
- it =>
379
- `<span class="tooltip-example">${
380
- it
381
- ? `<og-tooltip placement="${it}" style="width:100%">
382
- <div slot="trigger">${it}</div>
383
- <div slot="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
384
- </og-tooltip>`
385
- : ' &nbsp; '
386
- }</span>`
387
- )
388
- .join('\n')
389
- )
390
- .join('<br>\n')
391
- }
371
+ },
372
+ {
373
+ name: 'Tooltip',
374
+ selector: 'og-offer[location="tooltip-placement"]',
375
+ markup: [
376
+ ['top-left', 'top', 'top-right'],
377
+ ['left', '', 'right'],
378
+ ['bottom-left', 'bottom', 'bottom-right']
379
+ ]
380
+ .map(options =>
381
+ options
382
+ .map(
383
+ it =>
384
+ `<span class="tooltip-example">${
385
+ it
386
+ ? `<og-tooltip placement="${it}" style="width:100%">
387
+ <div slot="trigger">${it}</div>
388
+ <div slot="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
389
+ </og-tooltip>`
390
+ : ' &nbsp; '
391
+ }</span>`
392
+ )
393
+ .join('\n')
394
+ )
395
+ .join('<br>\n')
396
+ }
397
+ ];
398
+
399
+ const exampleTemplates = [
400
+ ['Offers example', ...offersExamples.map((x, idx) => ({ ...x, id: idx.toString() }))],
401
+ [
402
+ 'Individual components',
403
+ ...componentExamples.map((x, idx) => ({ ...x, id: (idx + offersExamples.length).toString() }))
392
404
  ]
393
405
  ];
394
406
  function updateTemplate(target) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ordergroove/offers",
3
- "version": "2.29.0",
3
+ "version": "2.29.1-alpha-PR-707-2.113+0ae21bc6",
4
4
  "description": "offer state component",
5
5
  "author": "Eugenio Lattanzio <eugenio63@gmail.com>",
6
6
  "homepage": "https://github.com/ordergroove/plush-toys#readme",
@@ -47,5 +47,5 @@
47
47
  "devDependencies": {
48
48
  "@ordergroove/offers-templates": "^0.4.20"
49
49
  },
50
- "gitHead": "f1717c291817ec17495295cbfa2ca873fd85e77a"
50
+ "gitHead": "0ae21bc6fbf1055284f1f51cc9591ae32075921d"
51
51
  }
@@ -0,0 +1,110 @@
1
+ import { css, html } from 'lit-element';
2
+ import { connect } from '../core/connect';
3
+
4
+ import { withProduct } from '../core/resolveProperties';
5
+ import { TemplateElement } from '../core/base';
6
+ import { makeProductPrepaidShipmentsOptedInSelector, makePrepaidShipmentsSelectedSelector } from '../core/selectors';
7
+ import { safeProductId } from '../core/utils';
8
+
9
+ export class PrepaidData extends withProduct(TemplateElement) {
10
+ static get properties() {
11
+ return {
12
+ ...super.properties,
13
+ shipmentsOptedIn: { type: Number },
14
+ productPlans: { type: Object },
15
+ prepaidShipmentsSelected: { type: Number },
16
+ totalPrice: { type: Boolean, reflect: true, attribute: 'total-price' },
17
+ perDeliveryPrice: { type: Boolean, reflect: true, attribute: 'per-delivery-price' },
18
+ totalSavings: { type: Boolean, reflect: true, attribute: 'total-savings' },
19
+ perDeliverySavings: { type: Boolean, reflect: true, attribute: 'per-delivery-savings' },
20
+ percentageSavings: { type: Boolean, reflect: true, attribute: 'percentage-savings' },
21
+ extraPercentageSavings: { type: Boolean, reflect: true, attribute: 'extra-percentage-savings' },
22
+ numberOfShipments: { type: Boolean, reflect: true, attribute: 'number-of-shipments' }
23
+ };
24
+ }
25
+
26
+ static get styles() {
27
+ return css`
28
+ :host {
29
+ display: inline-block;
30
+ text-indent: initial;
31
+ }
32
+ `;
33
+ }
34
+
35
+ get value() {
36
+ const realProductId = safeProductId(this.product);
37
+ const plans = this.productPlans[realProductId] || [];
38
+
39
+ const targetShipments = this.prepaidShipmentsSelected ? this.prepaidShipmentsSelected : this.shipmentsOptedIn;
40
+ let currentPlan = plans.find(plan => plan.prepaidShipments > 1 && plan.prepaidShipments === targetShipments);
41
+
42
+ if (!currentPlan) {
43
+ currentPlan = plans.find(plan => plan.prepaidShipments > 1);
44
+ if (!currentPlan) return '';
45
+ }
46
+
47
+ const {
48
+ discountRate,
49
+ subscriptionPrice,
50
+ prepaidShipments,
51
+ regularPrepaidPrice,
52
+ prepaidSavingsPerShipment,
53
+ prepaidSavingsTotal,
54
+ prepaidExtraSavingsPercentage
55
+ } = currentPlan;
56
+
57
+ if (this.totalPrice) {
58
+ return regularPrepaidPrice;
59
+ }
60
+
61
+ if (this.perDeliveryPrice) {
62
+ return subscriptionPrice;
63
+ }
64
+
65
+ if (this.totalSavings) {
66
+ return prepaidSavingsTotal;
67
+ }
68
+
69
+ if (this.perDeliverySavings) {
70
+ return prepaidSavingsPerShipment;
71
+ }
72
+
73
+ if (this.percentageSavings) {
74
+ return discountRate;
75
+ }
76
+
77
+ if (this.extraPercentageSavings) {
78
+ return prepaidExtraSavingsPercentage;
79
+ }
80
+
81
+ if (this.numberOfShipments) {
82
+ return prepaidShipments;
83
+ }
84
+
85
+ return '';
86
+ }
87
+
88
+ render() {
89
+ const value = this.value;
90
+ if (value)
91
+ return html`
92
+ <slot name="prepend"></slot>
93
+ ${value}
94
+ <slot name="append"></slot>
95
+ `;
96
+
97
+ return html`
98
+ <slot name="fallback"></slot>
99
+ `;
100
+ }
101
+ }
102
+ const mapStateToProps = (state, ownProps) => ({
103
+ shipmentsOptedIn: makeProductPrepaidShipmentsOptedInSelector(ownProps.product)(state),
104
+ prepaidShipmentsSelected: makePrepaidShipmentsSelectedSelector(ownProps.product)(state),
105
+ productPlans: state.productPlans
106
+ });
107
+
108
+ const ConnectedPrepaidData = connect(mapStateToProps)(PrepaidData);
109
+
110
+ export { ConnectedPrepaidData };