@ordergroove/offers 2.46.0 → 2.46.1-alpha-PR-1285-2.53

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.
@@ -14,16 +14,18 @@ import {
14
14
  SETUP_PRODUCT
15
15
  } from '../core/constants';
16
16
 
17
- import { makeSubscribedSelector } from '../core/selectors';
17
+ import { isShopifyDiscountFunctionInUseSelector, makeSubscribedSelector } from '../core/selectors';
18
18
  import { getOrCreateHidden, safeProductId } from '../core/utils';
19
19
  import { getTrackingKey } from './shopifyTrackingMiddleware';
20
20
  import { ShopifyCart, ShopifyProductEntity } from './types/shopify';
21
- import { SetupProductPayload, SetupCartPayload, OfferElement } from '../core/types/reducer';
21
+ import { SetupProductPayload, SetupCartPayload, OfferElement, State } from '../core/types/reducer';
22
+ import { type Store } from 'redux';
22
23
 
23
24
  const SHOPIFY_ROOT = window.Shopify?.routes?.root || '/';
24
25
  const CART_PAGE_URL = '/cart';
25
26
  const CART_JS_URL = `${SHOPIFY_ROOT}cart.js`;
26
27
  const CART_CHANGE_URL = `${SHOPIFY_ROOT}cart/change.js`;
28
+ const CART_UPDATE_URL = `${SHOPIFY_ROOT}cart/update.js`;
27
29
  const PRODUCTS_URL = `${SHOPIFY_ROOT}products/`;
28
30
 
29
31
  /**
@@ -189,23 +191,42 @@ export async function synchronizeCartOptin(action: any, store: any) {
189
191
  const qty = item.quantity;
190
192
  const productId = safeProductId(key);
191
193
 
192
- const res = await fetch(CART_CHANGE_URL, {
194
+ const changeRes = await fetch(CART_CHANGE_URL, {
193
195
  method: 'POST',
194
196
  credentials: 'same-origin',
195
197
  headers: { 'Content-Type': 'application/json' },
196
198
  body: JSON.stringify({
197
199
  id: key,
198
200
  quantity: qty,
199
- attributes: Object.fromEntries([trackingEvent]),
200
201
  properties: item.properties,
201
202
  selling_plan: selling_plan || null,
202
203
  sections: sectionsToUpdate.map((el: HTMLElement) => el.id.replace(/^shopify-section-/, ''))
203
204
  })
204
205
  });
205
206
 
206
- if (res.status !== 200) throw new Error('Cart not updated');
207
+ if (changeRes.status !== 200) throw new Error('Cart not updated');
208
+
209
+ const offerIdAttribute = getOfferIdAttribute(store);
210
+ const attributes = {
211
+ ...Object.fromEntries([trackingEvent]),
212
+ ...(offerIdAttribute ? { [OFFER_ATTRIBUTE_NAME]: offerIdAttribute } : {})
213
+ };
214
+
215
+ if (Object.keys(attributes).length > 0) {
216
+ // update the cart attributes
217
+ const updateRes = await fetch(CART_UPDATE_URL, {
218
+ method: 'POST',
219
+ credentials: 'same-origin',
220
+ headers: { 'Content-Type': 'application/json' },
221
+ body: JSON.stringify({
222
+ attributes
223
+ })
224
+ });
225
+
226
+ if (updateRes.status !== 200) throw new Error('Cart attributes not updated');
227
+ }
207
228
 
208
- const newCart: ShopifyCart = await res.json();
229
+ const newCart: ShopifyCart = await changeRes.json();
209
230
 
210
231
  // If both carts have same length we can update the item.key
211
232
  // to the original offer element, at least provide
@@ -332,12 +353,23 @@ export function getSubscribedFrequency(productId, store) {
332
353
  return sellingPlanId;
333
354
  }
334
355
 
356
+ const OFFER_ATTRIBUTE_NAME = '__ordergroove_offer_id';
357
+
358
+ function getOfferIdAttribute(store: Store<State>) {
359
+ const state = store.getState();
360
+ // if the Shopify Discount Function is being used, we need to pass along the offer ID as a cart attribute so the discount is calculated correctly
361
+ if (isShopifyDiscountFunctionInUseSelector(state)) {
362
+ return state.offerId;
363
+ }
364
+ return null;
365
+ }
366
+
335
367
  /**
336
368
  * // update <input type="hidden" name="selling_plan"/> if available
337
369
  *
338
370
  * @param store
339
371
  */
340
- function synchronizeSellingPlan(store: any, offerElement?: OfferElement) {
372
+ export function synchronizeSellingPlan(store: any, offerElement?: OfferElement) {
341
373
  if (offerElement?.isCart) return; // hidden inputs are used when product page, not cart.
342
374
  if (!offerElement?.shouldEnableOffer) return; // do not set a selling plan if we're hiding the offer
343
375
 
@@ -348,6 +380,12 @@ function synchronizeSellingPlan(store: any, offerElement?: OfferElement) {
348
380
 
349
381
  getOrCreateHidden(productIdInput.form, 'selling_plan', sellingPlanId);
350
382
  getOrCreateHidden(productIdInput.form, `attributes[og__session]`, store.getState().sessionId);
383
+
384
+ const offerIdAttribute = getOfferIdAttribute(store);
385
+ if (offerIdAttribute) {
386
+ getOrCreateHidden(productIdInput.form, `attributes[${OFFER_ATTRIBUTE_NAME}]`, offerIdAttribute);
387
+ }
388
+
351
389
  if (offerElement) {
352
390
  // use this to update the product attributes in future
353
391
  }
@@ -36,6 +36,7 @@ import type {
36
36
  OfferElement,
37
37
  OptedInState,
38
38
  OptInItem,
39
+ PriceState,
39
40
  ReceiveOfferPayload,
40
41
  SetupProductPayload
41
42
  } from '../core/types/reducer';
@@ -289,6 +290,25 @@ export const optedin = (state: OptedInState = [], action): OptedInState => {
289
290
  return coreOptedin(state, action);
290
291
  };
291
292
 
293
+ export const price = (state: PriceState = {}, action): PriceState => {
294
+ if (constants.SETUP_PRODUCT === action.type) {
295
+ const {
296
+ payload: { product }
297
+ } = action as { payload: SetupProductPayload };
298
+ return (
299
+ product.variants?.reduce(
300
+ (acc, cur) => ({
301
+ ...acc,
302
+ [cur.id]: { value: cur.price }
303
+ }),
304
+ state
305
+ ) || state
306
+ );
307
+ }
308
+
309
+ return state;
310
+ };
311
+
292
312
  export const productOffer = (state = {}, _action) => state;
293
313
 
294
314
  export const productPlans = (state = {}, action) => {
@@ -352,6 +372,7 @@ const reducer = combineReducers({
352
372
  optedout,
353
373
  previewStandardOffer,
354
374
  previewUpsellOffer,
375
+ price,
355
376
  productOffer,
356
377
  productPlans,
357
378
  productToSubscribe,
@@ -8,4 +8,5 @@ export interface ProductPlanEntity {
8
8
  prepaidSavingsPerShipment?: string;
9
9
  prepaidSavingsTotal?: string;
10
10
  prepaidExtraSavingsPercentage?: string;
11
+ hasPriceAdjustments?: boolean;
11
12
  }