@ordergroove/offers 2.27.10 → 2.27.12-alpha-PR-651-2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ordergroove/offers",
3
- "version": "2.27.10",
3
+ "version": "2.27.12-alpha-PR-651-2.0+647b5a6d",
4
4
  "description": "offer state component",
5
5
  "author": "Eugenio Lattanzio <eugenio63@gmail.com>",
6
6
  "homepage": "https://github.com/ordergroove/plush-toys#readme",
@@ -45,5 +45,5 @@
45
45
  "devDependencies": {
46
46
  "@ordergroove/offers-templates": "^0.4.14"
47
47
  },
48
- "gitHead": "d77d371f9090d52b3aff92314743d3782676adb6"
48
+ "gitHead": "647b5a6d8eb2c3d2ceb1196b2ca16533a9ae158e"
49
49
  }
@@ -337,32 +337,29 @@ describe('offerId', () => {
337
337
 
338
338
  describe('optedin', () => {
339
339
  it('should return optins given action SETUP_CART', () => {
340
- const actual = optedin(
341
- {},
342
- {
343
- type: constants.SETUP_CART,
344
- payload: {
345
- items: [
346
- {
347
- key: 'yum item key 1',
348
- selling_plan_allocation: {
349
- selling_plan: {
350
- id: 'yum selling plan id 1'
351
- }
340
+ const actual = optedin([], {
341
+ type: constants.SETUP_CART,
342
+ payload: {
343
+ items: [
344
+ {
345
+ key: 'yum item key 1',
346
+ selling_plan_allocation: {
347
+ selling_plan: {
348
+ id: 'yum selling plan id 1'
352
349
  }
353
- },
354
- {
355
- key: 'yum item key 2',
356
- selling_plan_allocation: {
357
- selling_plan: {
358
- id: 'yum selling plan id 2'
359
- }
350
+ }
351
+ },
352
+ {
353
+ key: 'yum item key 2',
354
+ selling_plan_allocation: {
355
+ selling_plan: {
356
+ id: 'yum selling plan id 2'
360
357
  }
361
358
  }
362
- ]
363
- }
359
+ }
360
+ ]
364
361
  }
365
- );
362
+ });
366
363
 
367
364
  expect(actual).toEqual([
368
365
  {
@@ -22,7 +22,11 @@ const PRODUCTS_URL = `${SHOPIFY_ROOT}products/`;
22
22
 
23
23
  const syncProductId = debounce(100, false, function(form, offer) {
24
24
  const { id } = Object.fromEntries([...new FormData(form).entries()]);
25
- offer.setAttribute('product', id);
25
+ if (id) {
26
+ offer.setAttribute('product', id);
27
+ } else {
28
+ offer.removeAttribute('product');
29
+ }
26
30
  });
27
31
 
28
32
  async function setupPdp(store, offer) {
@@ -34,18 +38,34 @@ async function setupPdp(store, offer) {
34
38
  console.warn('OG: Unable to fetch product details for PDP', err);
35
39
  }
36
40
  }
37
- const form = offer.closest('form');
41
+ // try closest form (safer)
42
+ let form = offer.closest('form');
43
+
44
+ // sometimes template is so closest does not work
45
+ // <div>
46
+ // <og-offer ..>
47
+ // </div>
48
+ // <div>
49
+ // <form action="/cart/add"/>
50
+ // </div>
51
+ if (!form) {
52
+ let ref = offer.parentElement;
53
+ // look up parents element of offer that contains the form. This will fix eventually category offers.
54
+ while (ref) {
55
+ form = ref.querySelector('form[action="/cart/add"]');
56
+ if (form) break;
57
+ if (ref.tagName.toLowerCase() === 'body') break;
58
+ ref = ref.parentElement;
59
+ }
60
+ }
61
+
38
62
  if (form) {
63
+ // since syncProductId is debounced not matter which comes first mutation or onchange
64
+ form.addEventListener('change', ev => syncProductId(form, offer));
39
65
  const mo = new MutationObserver(() => syncProductId(form, offer));
40
66
  mo.observe(form, { subtree: true, childList: true });
41
67
  } else {
42
- for (let it of document.querySelectorAll('form[action="/cart/add"] [name=id]')) {
43
- const input = it as HTMLFormElement;
44
- if (input.getAttribute('value') === offer.getAttribute('product')) {
45
- const mo = new MutationObserver(() => syncProductId(input.form, offer));
46
- mo.observe(input.form, { subtree: true, childList: true });
47
- }
48
- }
68
+ console.info('no /cart/add form found for og-offer', offer);
49
69
  }
50
70
  }
51
71
 
@@ -323,6 +343,7 @@ export default function shopifyMiddleware(store) {
323
343
  } else {
324
344
  setupPdp(store, action.payload.offer);
325
345
  }
346
+ break;
326
347
  default:
327
348
  }
328
349
 
@@ -165,13 +165,17 @@ export const offerId = (state = '', action) => 'native-shopify-offer';
165
165
  export const optedin = (state = [], action) => {
166
166
  if (constants.SETUP_CART === action.type) {
167
167
  const cart = action.payload;
168
- return cart.items.reduce(
169
- (acc, cur) =>
170
- cur.selling_plan_allocation
171
- ? [...acc, { id: cur.key, frequency: `${cur.selling_plan_allocation.selling_plan.id}` }]
172
- : acc,
173
- []
174
- );
168
+ return state
169
+ .filter(it => !it.id.includes(':'))
170
+ .concat(
171
+ cart.items.reduce(
172
+ (acc, cur) =>
173
+ cur.selling_plan_allocation
174
+ ? [...acc, { id: cur.key, frequency: `${cur.selling_plan_allocation.selling_plan.id}` }]
175
+ : acc,
176
+ []
177
+ )
178
+ );
175
179
  }
176
180
  if (constants.RECEIVE_OFFER === action.type) {
177
181
  const { autoship, autoship_by_default, in_stock, offer: offerEl } = action.payload;
@@ -186,6 +190,20 @@ export const optedin = (state = [], action) => {
186
190
  state
187
191
  );
188
192
  }
193
+
194
+ if (constants.SETUP_PRODUCT === action.type) {
195
+ const productIds = action.payload.variants.map(variant => variant.id).map(id => `${id}`);
196
+ const sellingPlanGroup = getOGSellingPlanGroup(action.payload);
197
+ const frequencies = sellingPlanGroup?.selling_plans?.map(({ id }) => `${id}`);
198
+ // if the product is in the list of variants and its frequency isn't a valid selling plan, replace with the first valid selling plan
199
+ return state.map(cur => ({
200
+ ...cur,
201
+ frequency:
202
+ productIds.some(id => id === cur.id) && !frequencies.some(freq => freq === cur.frequency)
203
+ ? frequencies[0]
204
+ : cur.frequency
205
+ }));
206
+ }
189
207
  return coreOptedin(state, action);
190
208
  };
191
209