ng-miam 9.2.8 → 9.2.10

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 (35) hide show
  1. package/bundles/ng-miam.umd.js +354 -40
  2. package/bundles/ng-miam.umd.js.map +1 -1
  3. package/bundles/ng-miam.umd.min.js +1 -1
  4. package/bundles/ng-miam.umd.min.js.map +1 -1
  5. package/esm2015/lib/_services/analytics.service.js +53 -21
  6. package/esm2015/lib/_services/basket-transfer.service.js +122 -12
  7. package/esm2015/lib/_services/baskets.service.js +20 -6
  8. package/esm2015/lib/_services/recipe-details.service.js +10 -2
  9. package/esm2015/lib/_utils/index.js +2 -1
  10. package/esm2015/lib/_utils/journey.util.js +138 -0
  11. package/esm2015/lib/_web-components/basket-preview/replace-item/replace-item.component.js +3 -3
  12. package/esm2015/lib/_web-components/recipe-details/sponsor-storytelling/sponsor-storytelling.component.js +1 -1
  13. package/esm2015/lib/environments/environment.js +3 -2
  14. package/esm2015/lib/environments/environment.prod.js +3 -2
  15. package/esm2015/lib/environments/version.js +2 -2
  16. package/fesm2015/ng-miam.js +342 -41
  17. package/fesm2015/ng-miam.js.map +1 -1
  18. package/lib/_services/analytics.service.d.ts +8 -8
  19. package/lib/_services/analytics.service.d.ts.map +1 -1
  20. package/lib/_services/basket-transfer.service.d.ts +8 -2
  21. package/lib/_services/basket-transfer.service.d.ts.map +1 -1
  22. package/lib/_services/baskets.service.d.ts +1 -1
  23. package/lib/_services/baskets.service.d.ts.map +1 -1
  24. package/lib/_services/recipe-details.service.d.ts +1 -1
  25. package/lib/_services/recipe-details.service.d.ts.map +1 -1
  26. package/lib/_utils/index.d.ts +1 -0
  27. package/lib/_utils/index.d.ts.map +1 -1
  28. package/lib/_utils/journey.util.d.ts +42 -0
  29. package/lib/_utils/journey.util.d.ts.map +1 -0
  30. package/lib/environments/environment.d.ts +1 -0
  31. package/lib/environments/environment.d.ts.map +1 -1
  32. package/lib/environments/environment.prod.d.ts +1 -0
  33. package/lib/environments/environment.prod.d.ts.map +1 -1
  34. package/lib/environments/version.d.ts +1 -1
  35. package/package.json +1 -1
@@ -725,6 +725,155 @@
725
725
  event.preventDefault();
726
726
  };
727
727
 
728
+ /**
729
+ * Journey detection utility
730
+ *
731
+ * Allows to determine the journey name based on elements present on the page.
732
+ * You can define custom mappings between CSS selectors, URL parameters, and URLs.
733
+ */
734
+ /**
735
+ * Default journey mappings
736
+ * You can extend or override these mappings as needed
737
+ */
738
+ var defaultJourneyMappings = {
739
+ 'meals-space-catalog-search': {
740
+ selector: ['.mealz-catalog__title', '.miam-recipe-catalog__content__title__search__text'],
741
+ urlParam: 'search'
742
+ },
743
+ 'meals-space-home': ['mealz-catalog-home', '.miam-catalog-header'],
744
+ 'meals-space-category-search': {
745
+ selector: ['mealz-catalog-category', '.miam-catalog-header__category-label'],
746
+ urlParam: 'search'
747
+ },
748
+ 'meals-space-category': ['mealz-catalog-category', '.miam-catalog-header__category-label'],
749
+ 'meals-space-all-recipes': ['mealz-catalog-all-recipes', '.miam-recipe-catalog__content__title__all-recipes__text'],
750
+ 'my-space-favorites': ['mealz-catalog-favorites', '#favorites-panel'],
751
+ 'my-space-history': 'mealz-catalog-history'
752
+ };
753
+ /**
754
+ * Checks if a URL parameter exists in the current URL
755
+ *
756
+ * @param paramName - The name of the URL parameter to check
757
+ * @param location - Optional location object (defaults to window.location)
758
+ * @returns True if the parameter exists (even if empty), false otherwise
759
+ */
760
+ var hasUrlParam = function (paramName, location) {
761
+ var loc = location !== null && location !== void 0 ? location : (typeof window !== 'undefined' ? window.location : null);
762
+ if (!loc) {
763
+ return false;
764
+ }
765
+ var urlParams = new URLSearchParams(loc.search);
766
+ return urlParams.has(paramName);
767
+ };
768
+ /**
769
+ * Checks if the current URL matches a pattern
770
+ *
771
+ * @param pattern - URL string or RegExp pattern to match
772
+ * @param location - Optional location object (defaults to window.location)
773
+ * @returns True if the URL matches the pattern, false otherwise
774
+ */
775
+ var matchesUrl = function (pattern, location) {
776
+ var loc = location !== null && location !== void 0 ? location : (typeof window !== 'undefined' ? window.location : null);
777
+ if (!loc) {
778
+ return false;
779
+ }
780
+ var fullUrl = loc.href;
781
+ var pathname = loc.pathname;
782
+ if (pattern instanceof RegExp) {
783
+ return pattern.test(fullUrl) || pattern.test(pathname);
784
+ }
785
+ // String pattern: check if it's a full URL or a path
786
+ if (pattern.startsWith('http://') || pattern.startsWith('https://')) {
787
+ return fullUrl.includes(pattern);
788
+ }
789
+ // Treat as pathname pattern
790
+ return pathname.includes(pattern);
791
+ };
792
+ /**
793
+ * Normalizes a journey configuration to a standard format
794
+ *
795
+ * @param config - The journey configuration (can be string, string[], or object)
796
+ * @returns Normalized configuration object
797
+ */
798
+ var normalizeJourneyConfig = function (config) {
799
+ if (typeof config === 'string') {
800
+ return { selector: config };
801
+ }
802
+ if (Array.isArray(config)) {
803
+ return { selector: config };
804
+ }
805
+ return config;
806
+ };
807
+ /**
808
+ * Detects the journey name based on elements present on the page
809
+ *
810
+ * @param mappings - Optional custom mappings. If not provided, uses default mappings
811
+ * @param document - Optional document object (defaults to window.document)
812
+ * @param location - Optional location object (defaults to window.location)
813
+ * @returns The detected journey name, or null if no match is found
814
+ */
815
+ var detectJourney = function (mappings, document, location) {
816
+ var e_1, _b;
817
+ var doc = document !== null && document !== void 0 ? document : (typeof window !== 'undefined' ? window.document : null);
818
+ if (!doc) {
819
+ return null;
820
+ }
821
+ var journeyMappings = mappings !== null && mappings !== void 0 ? mappings : defaultJourneyMappings;
822
+ try {
823
+ // Check each journey mapping
824
+ for (var _c = __values(Object.entries(journeyMappings)), _d = _c.next(); !_d.done; _d = _c.next()) {
825
+ var _e = __read(_d.value, 2), journeyName = _e[0], config = _e[1];
826
+ var normalizedConfig = normalizeJourneyConfig(config);
827
+ var selectorArray = Array.isArray(normalizedConfig.selector)
828
+ ? normalizedConfig.selector
829
+ : [normalizedConfig.selector];
830
+ // Check if at least one selector matches an element on the page
831
+ var hasSelectorMatch = selectorArray.some(function (selector) {
832
+ try {
833
+ return doc.querySelector(selector) !== null;
834
+ }
835
+ catch (_a) {
836
+ // Invalid selector, skip it
837
+ return false;
838
+ }
839
+ });
840
+ if (!hasSelectorMatch) {
841
+ continue;
842
+ }
843
+ // Check URL parameter if specified
844
+ if (normalizedConfig.urlParam) {
845
+ if (!hasUrlParam(normalizedConfig.urlParam, location)) {
846
+ continue;
847
+ }
848
+ }
849
+ // Check URL pattern if specified
850
+ if (normalizedConfig.url) {
851
+ if (!matchesUrl(normalizedConfig.url, location)) {
852
+ continue;
853
+ }
854
+ }
855
+ // All conditions met, return this journey
856
+ return journeyName;
857
+ }
858
+ }
859
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
860
+ finally {
861
+ try {
862
+ if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
863
+ }
864
+ finally { if (e_1) throw e_1.error; }
865
+ }
866
+ return null;
867
+ };
868
+ /**
869
+ * Registers custom journey mappings
870
+ * Merges with default mappings (custom mappings take precedence)
871
+ *
872
+ * @param customMappings - Custom journey mappings to add or override
873
+ * @returns Combined mappings (default + custom)
874
+ */
875
+ var createJourneyMappings = function (customMappings) { return (Object.assign(Object.assign({}, defaultJourneyMappings), customMappings)); };
876
+
728
877
  var CapitalizeFirstLetterPipe = /** @class */ (function () {
729
878
  function CapitalizeFirstLetterPipe() {
730
879
  }
@@ -1685,7 +1834,8 @@
1685
1834
  miamWeb: 'https://miam.tech',
1686
1835
  mealzComponents: 'https://cdn.jsdelivr.net/npm/mealz-components@1.2/dist',
1687
1836
  mealzSsrApi: 'https://ssr-api.mealz.ai',
1688
- lang: 'fr'
1837
+ lang: 'fr',
1838
+ analyticsEnabled: true // Only used in DEV mode
1689
1839
  };
1690
1840
 
1691
1841
  var Ingredient = /** @class */ (function (_super) {
@@ -3501,7 +3651,7 @@
3501
3651
  EventJourney["EMPTY"] = "";
3502
3652
  })(EventJourney || (EventJourney = {}));
3503
3653
 
3504
- var VERSION = '9.2.4'; // TODO: replace by ##VERSION## and update it in the CI/CD
3654
+ var VERSION = '9.2.8'; // TODO: replace by ##VERSION## and update it in the CI/CD
3505
3655
 
3506
3656
  var ContextRegistryService = /** @class */ (function () {
3507
3657
  function ContextRegistryService() {
@@ -3533,6 +3683,11 @@
3533
3683
  }
3534
3684
  return location.href;
3535
3685
  }
3686
+ /**
3687
+ * Maps Angular environment to analytics environment
3688
+ * dev -> uat, uat -> uat, prod -> prod
3689
+ */
3690
+ var getAnalyticsEnvironment = function () { return environment$1.env === 'prod' ? 'prod' : 'uat'; };
3536
3691
  // Exported only for unit tests...
3537
3692
  // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
3538
3693
  function _onEmit(event) {
@@ -3577,60 +3732,84 @@
3577
3732
  if (!domain) {
3578
3733
  return mealzError('[Mealz] Analytics not initialized (domain cannot be null)');
3579
3734
  }
3580
- mealzSharedAnalytics.initSharedAnalytics(domain, VERSION, _onEmit);
3735
+ var analyticsEnvironment = getAnalyticsEnvironment();
3736
+ mealzSharedAnalytics.initSharedAnalytics(domain, VERSION, _onEmit, analyticsEnvironment);
3581
3737
  if (((_a = localStorage.getItem('_miam/affiliate')) === null || _a === void 0 ? void 0 : _a.length) > 0) {
3582
3738
  mealzSharedAnalytics.setAffiliate(localStorage.getItem('_miam/affiliate'));
3583
3739
  }
3584
3740
  this.alreadyInitialized$.next(true);
3585
3741
  };
3586
- AnalyticsService.prototype.sendEvent = function (name, path, props) {
3742
+ AnalyticsService.prototype.sendEvent = function (name, path, props, journey) {
3587
3743
  if (this.contextRegistryService.disabledAnalytics && this.contextRegistryService.forbidProfiling) {
3588
3744
  return;
3589
3745
  }
3590
- // Currently no way to know if it is search or shelves
3591
- var journey = this.isMealzPage ? EventJourney.MEALZ : EventJourney.EMPTY;
3592
- this.callMethodOrAddToQueue(function () { return mealzSharedAnalytics.sendEvent(name, url(path), journey, props); });
3746
+ // Disable analytics only in development environment if environment variable analyticsEnabled is false
3747
+ if (environment$1.env === 'dev' && environment$1.analyticsEnabled === false) {
3748
+ return;
3749
+ }
3750
+ // Use provided journey or determine from context
3751
+ var eventJourney = journey || (this.isMealzPage ? EventJourney.MEALZ : EventJourney.EMPTY);
3752
+ this.callMethodOrAddToQueue(function () { return mealzSharedAnalytics.sendEvent(name, url(path), eventJourney, props); });
3593
3753
  };
3594
3754
  /** ************************************************* SEND EVENT FOR BASKET ACTIONS ************************************************* **/
3595
- AnalyticsService.prototype.sendRemoveRecipesEvents = function (actions) {
3755
+ AnalyticsService.prototype.sendRemoveRecipesEvents = function (actions, journey) {
3596
3756
  var _this = this;
3757
+ var detectedJourney = journey !== null && journey !== void 0 ? journey : detectJourney();
3597
3758
  actions.forEach(function (action) {
3598
- _this.sendEvent('recipe.remove', action.params.eventTrace.originPath, { recipe_id: action.params.recipeId });
3759
+ _this.sendEvent('recipe.remove', action.params.eventTrace.originPath, { recipe_id: action.params.recipeId }, detectedJourney);
3599
3760
  });
3600
3761
  };
3601
- AnalyticsService.prototype.sendAddRecipesEvents = function (actions) {
3762
+ AnalyticsService.prototype.sendAddRecipesEvents = function (actions, journey) {
3602
3763
  var _this = this;
3764
+ var detectedJourney = journey !== null && journey !== void 0 ? journey : detectJourney();
3603
3765
  actions.forEach(function (action) {
3604
- _this.sendEvent('recipe.add', '', { recipe_id: action.params.recipeId });
3766
+ _this.sendEvent('recipe.add', action.params.eventTrace.originPath, { recipe_id: action.params.recipeId }, detectedJourney);
3605
3767
  });
3606
3768
  };
3607
- AnalyticsService.prototype.sendUpdateGuestsEvents = function (actions) {
3769
+ AnalyticsService.prototype.sendUpdateGuestsEvents = function (actions, journey) {
3608
3770
  var _this = this;
3771
+ var detectedJourney = journey !== null && journey !== void 0 ? journey : detectJourney();
3609
3772
  actions.forEach(function (action) {
3610
- _this.sendEvent('recipe.change-guests', action.params.eventTrace.originPath, { recipe_id: action.params.recipeId });
3773
+ _this.sendEvent('recipe.change-guests', action.params.eventTrace.originPath, { recipe_id: action.params.recipeId }, detectedJourney);
3611
3774
  });
3612
3775
  };
3613
- AnalyticsService.prototype.sendEventsOfResetBasket = function (basket, eventTrace) {
3776
+ AnalyticsService.prototype.sendEventsOfResetBasket = function (basket, eventTrace, journey) {
3614
3777
  var _this = this;
3778
+ var detectedJourney = journey !== null && journey !== void 0 ? journey : detectJourney();
3615
3779
  basket.recipeInfos.forEach(function (info) {
3616
- _this.sendEvent('recipe.remove', eventTrace.originPath, { recipe_id: info.id });
3780
+ _this.sendEvent('recipe.remove', eventTrace.originPath, { recipe_id: info.id }, detectedJourney);
3617
3781
  });
3618
3782
  };
3619
- AnalyticsService.prototype.sendAddProductsEvents = function (actions) {
3783
+ AnalyticsService.prototype.sendAddProductsEvents = function (actions, journey) {
3620
3784
  var _this = this;
3785
+ var detectedJourney = journey !== null && journey !== void 0 ? journey : detectJourney();
3786
+ var isBulk = actions.length > 1;
3621
3787
  actions.forEach(function (action) {
3788
+ // Determine add_source: replacement if previousItem exists, otherwise unit or bulk based on actions count
3789
+ var addSource;
3790
+ if (action.params.previousItem) {
3791
+ addSource = 'replacement';
3792
+ }
3793
+ else if (isBulk) {
3794
+ addSource = 'bulk';
3795
+ }
3796
+ else {
3797
+ addSource = 'unit';
3798
+ }
3622
3799
  _this.sendEvent('entry.added', action.params.eventTrace.originPath, {
3623
3800
  entry_name: action.params.basketEntry.name,
3624
3801
  item_id: action.params.basketEntry.selectedItem.id,
3625
3802
  ext_item_id: action.params.basketEntry.selectedItem.attributes['ext-id'],
3626
3803
  item_ean: action.params.basketEntry.selectedItem.ean,
3627
3804
  product_quantity: action.params.basketEntry.quantity.toString(),
3628
- recipe_id: action.params.recipeId
3629
- });
3805
+ recipe_id: action.params.recipeId,
3806
+ add_source: addSource
3807
+ }, detectedJourney);
3630
3808
  });
3631
3809
  };
3632
- AnalyticsService.prototype.sendRemoveProductsEvents = function (actions) {
3810
+ AnalyticsService.prototype.sendRemoveProductsEvents = function (actions, journey) {
3633
3811
  var _this = this;
3812
+ var detectedJourney = journey !== null && journey !== void 0 ? journey : detectJourney();
3634
3813
  actions.forEach(function (action) {
3635
3814
  _this.sendEvent('entry.deleted', action.params.eventTrace.originPath, {
3636
3815
  entry_name: action.params.basketEntry.name,
@@ -3639,11 +3818,12 @@
3639
3818
  item_ean: action.params.basketEntry.selectedItem.ean,
3640
3819
  product_quantity: action.params.basketEntry.quantity.toString(),
3641
3820
  recipe_id: action.params.recipeId
3642
- });
3821
+ }, detectedJourney);
3643
3822
  });
3644
3823
  };
3645
- AnalyticsService.prototype.sendProductsChangeQuantityEvents = function (actions) {
3824
+ AnalyticsService.prototype.sendProductsChangeQuantityEvents = function (actions, journey) {
3646
3825
  var _this = this;
3826
+ var detectedJourney = journey !== null && journey !== void 0 ? journey : detectJourney();
3647
3827
  actions.forEach(function (action) {
3648
3828
  _this.sendEvent('entry.change-quantity', action.params.eventTrace.originPath, {
3649
3829
  entry_name: action.params.basketEntry.name,
@@ -3652,7 +3832,7 @@
3652
3832
  item_ean: action.params.basketEntry.selectedItem.ean,
3653
3833
  product_quantity: action.params.newQuantity.toString(),
3654
3834
  recipe_id: action.params.recipeId
3655
- });
3835
+ }, detectedJourney);
3656
3836
  });
3657
3837
  };
3658
3838
  AnalyticsService.prototype.callMethodOrAddToQueue = function (method) {
@@ -5950,7 +6130,11 @@
5950
6130
  BasketsService.prototype.fetchCurrentBasket = function (posId) {
5951
6131
  var _this = this;
5952
6132
  var getUrl = "current?point_of_sale_id=" + posId + "&fields[baskets]=" + BASKET_SPARSE_FIELDS.baskets.join(',');
5953
- return this.get(getUrl).pipe(operators.switchMap(function (basket) { return _this.updateLocalBasket(basket); }), operators.tap(function () { return _this.posService.emitBasketLoadedForNewPos(); }));
6133
+ return this.get(getUrl).pipe(operators.switchMap(function (basket) { return _this.updateLocalBasket(basket); }), operators.tap(function () {
6134
+ if (_this.posService.emitBasketLoadedForNewPos) {
6135
+ _this.posService.emitBasketLoadedForNewPos();
6136
+ }
6137
+ }));
5954
6138
  };
5955
6139
  BasketsService.prototype.resetBasket = function (eventTrace) {
5956
6140
  var _this = this;
@@ -6169,11 +6353,11 @@
6169
6353
  }); });
6170
6354
  this.basketActionsQueue.next(toAdd);
6171
6355
  };
6172
- BasketsService.prototype.addItemToBasket = function (item, eventTrace) {
6356
+ BasketsService.prototype.addItemToBasket = function (item, eventTrace, previousItem) {
6173
6357
  var toAdd = this.basketActionsQueue.value;
6174
6358
  toAdd.push({
6175
6359
  type: BasketActionType.ADD_ITEM,
6176
- params: { item: item, eventTrace: eventTrace }
6360
+ params: { item: item, eventTrace: eventTrace, previousItem: previousItem }
6177
6361
  });
6178
6362
  this.basketActionsQueue.next(toAdd);
6179
6363
  };
@@ -6422,8 +6606,13 @@
6422
6606
  ("&guests=" + modifiedGuests + "&forced_quantity=" + action.params.basketEntry.quantity);
6423
6607
  return _this.http.patch(patchUrl, {});
6424
6608
  });
6425
- _this.analyticsService.sendAddProductsEvents(ingredientsToAdd);
6426
6609
  return rxjs.forkJoin(requests);
6610
+ }), operators.tap(function () {
6611
+ // Determine journey: item-replacement if previousItem exists (indicates replacement), otherwise meals-space-recipe-details
6612
+ var journey = ingredientsToAdd.some(function (action) { return action.params.previousItem; })
6613
+ ? 'item-replacement'
6614
+ : 'meals-space-recipe-details';
6615
+ _this.analyticsService.sendAddProductsEvents(ingredientsToAdd, journey);
6427
6616
  }), operators.switchMap(function () { return _this.reloadBasket(); }), operators.switchMap(function () { return rxjs.of(null); }), // Just to keep the return type as Observable<void> to match with the other methods
6428
6617
  operators.catchError(function () { return rxjs.of(null); }));
6429
6618
  };
@@ -6442,8 +6631,13 @@
6442
6631
  ("&name=" + action.params.item.attributes.name);
6443
6632
  return _this.http.post(encodeURI(postUrl.trim()), {});
6444
6633
  });
6445
- _this.analyticsService.sendAddProductsEvents(itemsToAdd);
6446
6634
  return rxjs.forkJoin(requests);
6635
+ }), operators.tap(function () {
6636
+ // Determine journey: item-replacement if previousItem exists (indicates replacement), otherwise meals-space-recipe-details
6637
+ var journey = itemsToAdd.some(function (action) { return action.params.previousItem; })
6638
+ ? 'item-replacement'
6639
+ : 'meals-space-recipe-details';
6640
+ _this.analyticsService.sendAddProductsEvents(itemsToAdd, journey);
6447
6641
  }), operators.switchMap(function () { return _this.reloadBasket(); }), operators.switchMap(function () { return rxjs.of(null); }), // Just to keep the return type as Observable<void> to match with the other methods
6448
6642
  operators.catchError(function () { return rxjs.of(null); }));
6449
6643
  };
@@ -9709,7 +9903,8 @@
9709
9903
  };
9710
9904
  BasketTransferService.prototype.setSessionData = function (params) {
9711
9905
  sessionStorage.setItem('_miam/transferredBasketToken', params.basketToken);
9712
- sessionStorage.setItem('_miam/posOfSaleExtId', params.posExtId);
9906
+ // ITM specific: use pdvref if posExtId is not set
9907
+ sessionStorage.setItem('_miam/pointOfSaleExtId', params.posExtId || params.pdvref);
9713
9908
  };
9714
9909
  BasketTransferService.prototype.clearTransferSessionData = function () {
9715
9910
  sessionStorage.removeItem('_miam/transferredBasketToken');
@@ -9744,8 +9939,33 @@
9744
9939
  BasketTransferService.prototype.navigateToTransferUrl = function () {
9745
9940
  var transferUrl = sessionStorage.getItem('_miam/transferUrl');
9746
9941
  if (transferUrl) {
9942
+ // Adjust pdvref only for ITM (supplier 23) when navigating
9943
+ var finalUrl_1 = transferUrl;
9944
+ if (this.isITMSupplier()) {
9945
+ try {
9946
+ var urlObj = new URL(transferUrl);
9947
+ var rawPdvref = urlObj.searchParams.get('pdvref');
9948
+ if (rawPdvref) {
9949
+ var padded = this.padPdvref(rawPdvref);
9950
+ if (padded && padded !== rawPdvref) {
9951
+ urlObj.searchParams.set('pdvref', padded);
9952
+ }
9953
+ }
9954
+ finalUrl_1 = urlObj.toString();
9955
+ }
9956
+ catch (err) {
9957
+ // Fallback for non-standard URLs
9958
+ var match = transferUrl.match(/([?&])pdvref=([^&]+)/);
9959
+ if (match) {
9960
+ var padded = this.padPdvref(match[2]);
9961
+ if (padded) {
9962
+ finalUrl_1 = transferUrl.replace(/([?&])pdvref=[^&]+/, "$1pdvref=" + padded);
9963
+ }
9964
+ }
9965
+ }
9966
+ }
9747
9967
  // Apparently Safari blocks window.open(..., "_blank") if called in an async function and setTimeout makes it run on the main thread
9748
- setTimeout(function () { return window.open(transferUrl, '_blank'); });
9968
+ setTimeout(function () { return window.open(finalUrl_1, '_blank'); });
9749
9969
  }
9750
9970
  };
9751
9971
  BasketTransferService.prototype.abortTransfer = function () {
@@ -9768,7 +9988,9 @@
9768
9988
  };
9769
9989
  BasketTransferService.prototype.tryToTransferBasket = function (params) {
9770
9990
  var _this = this;
9771
- return this.callHookbackIfNotLogged().pipe(operators.skipWhile(function (isLogged) { return !isLogged; }), operators.switchMap(function () { return _this.forcePosIfUnset(params.posExtId); }), operators.skipWhile(function (isPosSet) { return !isPosSet; }), operators.switchMap(function () { return _this.posService.waitForPos.pipe(operators.take(1), operators.switchMap(function (pos) { return _this.basketsService.waitForBasket.pipe(operators.take(1), operators.switchMap(function () { return _this.basketsService.waitForBasketEntries.pipe(operators.take(1), operators.map(function (entries) {
9991
+ return this.callHookbackIfNotLogged().pipe(operators.skipWhile(function (isLogged) { return !isLogged; }),
9992
+ // ITM specific: use pdvref if posExtId is not set
9993
+ operators.switchMap(function () { return _this.ensureTransferPosSelected(params.posExtId || params.pdvref); }), operators.skipWhile(function (isPosSet) { return !isPosSet; }), operators.switchMap(function () { return _this.posService.waitForPos.pipe(operators.take(1), operators.switchMap(function (pos) { return _this.basketsService.waitForBasket.pipe(operators.take(1), operators.switchMap(function () { return _this.basketsService.waitForBasketEntries.pipe(operators.take(1), operators.map(function (entries) {
9772
9994
  _this.previousBasketEntries = deepCloneWithClass(entries);
9773
9995
  return pos;
9774
9996
  })); })); }), operators.switchMap(function (pos) { return _this.transferBasketForPos(pos, params.basketToken); }), operators.take(1)); }));
@@ -9806,7 +10028,8 @@
9806
10028
  };
9807
10029
  BasketTransferService.prototype.createTransferAction = function (entries) {
9808
10030
  var _this = this;
9809
- var transferActions = this.filterNewAndUpdatedEntries(entries).map(function (basketEntry) {
10031
+ var filteredEntries = this.filterNewAndUpdatedEntries(entries);
10032
+ var transferActions = filteredEntries.map(function (basketEntry) {
9810
10033
  var transferAction = new BasketTransferAction(basketEntry, {}, _this.basketsService, undefined, _this.suppliersService);
9811
10034
  _this.handleActionErrors(transferAction);
9812
10035
  return transferAction;
@@ -9823,26 +10046,46 @@
9823
10046
  var _this = this;
9824
10047
  return this.userService.isLogged$.pipe(operators.take(1), operators.map(function (isLogged) { return _this.contextService.hookCallback(isLogged, true); }));
9825
10048
  };
9826
- BasketTransferService.prototype.forcePosIfUnset = function (transferPosExtId) {
10049
+ BasketTransferService.prototype.ensureTransferPosSelected = function (transferPosExtId) {
9827
10050
  var _this = this;
9828
10051
  return this.posService.posWasInitialized().pipe(operators.takeUntil(this.transferComplete$), operators.switchMap(function () { return _this.posService.pos$.pipe(operators.take(1)); }), operators.switchMap(function (pos) {
9829
10052
  var posSet = pos && pos.extId === transferPosExtId;
9830
10053
  if (!posSet) {
9831
- _this.contextService.forcePosCallback(transferPosExtId);
10054
+ // Special handling for ITM (supplier ID 23)
10055
+ if (_this.isITMSupplier()) {
10056
+ return _this.handleITMPosChange(transferPosExtId);
10057
+ }
10058
+ else {
10059
+ if (transferPosExtId) {
10060
+ _this.contextService.forcePosCallback(transferPosExtId);
10061
+ }
10062
+ }
9832
10063
  }
9833
10064
  return rxjs.of(posSet);
9834
10065
  }));
9835
10066
  };
10067
+ BasketTransferService.prototype.getCookie = function (name) {
10068
+ var _a;
10069
+ var value = "; " + document.cookie;
10070
+ var parts = value.split("; " + name + "=");
10071
+ if (parts.length === 2) {
10072
+ return ((_a = parts.pop()) === null || _a === void 0 ? void 0 : _a.split(';').shift()) || null;
10073
+ }
10074
+ return null;
10075
+ };
9836
10076
  BasketTransferService.prototype.getTransferData = function () {
9837
10077
  var _a;
9838
10078
  var currentUrl = window.location.href;
9839
10079
  var urlParams = new URL(currentUrl).searchParams;
9840
10080
  var basketToken = urlParams.get('transferred_basket_token') || sessionStorage.getItem('_miam/transferredBasketToken');
9841
- var posExtId = urlParams.get('point_of_sale_ext_id') || urlParams.get('magasin_id') || sessionStorage.getItem('_miam/posOfSaleExtId');
10081
+ var posExtId = urlParams.get('point_of_sale_ext_id') ||
10082
+ urlParams.get('magasin_id') ||
10083
+ sessionStorage.getItem('_miam/pointOfSaleExtId');
9842
10084
  var affiliate = (_a = urlParams.get('affiliate')) === null || _a === void 0 ? void 0 : _a.toLowerCase();
9843
- if (basketToken && posExtId) {
10085
+ var pdvref = urlParams.get('pdvref');
10086
+ if (basketToken && (posExtId || pdvref)) {
9844
10087
  this.removeTransferParamsFromUrl();
9845
- return { basketToken: basketToken, posExtId: posExtId, affiliate: affiliate };
10088
+ return { basketToken: basketToken, posExtId: posExtId, affiliate: affiliate, pdvref: pdvref };
9846
10089
  }
9847
10090
  else {
9848
10091
  return null;
@@ -9857,10 +10100,73 @@
9857
10100
  urlParams.delete('point_of_sale_ext_id');
9858
10101
  urlParams.delete('magasin_id');
9859
10102
  urlParams.delete('affiliate');
10103
+ urlParams.delete('pdvref'); // Remove ITM specific parameter
9860
10104
  var newUrl = currentUrl.split('?')[0] + (urlParams.toString().length > 0 ? '?' + urlParams.toString() : '');
9861
10105
  history.replaceState({}, document.title, newUrl);
9862
10106
  }
9863
10107
  };
10108
+ // ITM specific methods
10109
+ BasketTransferService.prototype.isITMSupplier = function () {
10110
+ var currentPos = this.posService.pos$.getValue();
10111
+ return currentPos && currentPos.relationships.supplier.data.id === '23';
10112
+ };
10113
+ BasketTransferService.prototype.padPdvref = function (pdvref) {
10114
+ if (!pdvref) {
10115
+ return pdvref;
10116
+ }
10117
+ // Pad pdvref to exactly 5 characters with leading zeros only if shorter than 5
10118
+ return pdvref.length < 5 ? pdvref.padStart(5, '0') : pdvref;
10119
+ };
10120
+ BasketTransferService.prototype.handleITMPosChange = function (transferPosExtId) {
10121
+ var _this = this;
10122
+ var expectedPosId = transferPosExtId;
10123
+ return this.waitForITMCookie(expectedPosId).pipe(operators.catchError(function (error) {
10124
+ console.warn('ITM cookie check failed, falling back to normal POS callback:', error);
10125
+ if (expectedPosId) {
10126
+ _this.contextService.forcePosCallback(transferPosExtId);
10127
+ }
10128
+ return rxjs.of(false);
10129
+ }));
10130
+ };
10131
+ BasketTransferService.prototype.waitForITMCookie = function (transferPosExtId) {
10132
+ var _this = this;
10133
+ return new rxjs.Observable(function (observer) {
10134
+ var maxRetries = 50; // 5 seconds total (50 * 100ms)
10135
+ var retryCount = 0;
10136
+ var checkCookie = function () {
10137
+ retryCount++;
10138
+ var itmPdvCookie = _this.getCookie('itm_pdv');
10139
+ if (itmPdvCookie) {
10140
+ try {
10141
+ var decodedCookie = decodeURIComponent(itmPdvCookie);
10142
+ var pdvData = JSON.parse(decodedCookie);
10143
+ var cookiePosRef = pdvData.ref;
10144
+ // Check if the cookie POS matches the required transfer POS
10145
+ if (cookiePosRef === transferPosExtId) {
10146
+ // Refresh the page to ensure the new POS context is loaded
10147
+ observer.next(true);
10148
+ observer.complete();
10149
+ window.location.reload();
10150
+ return;
10151
+ }
10152
+ }
10153
+ catch (error) {
10154
+ console.warn('Failed to parse itm_pdv cookie:', error);
10155
+ }
10156
+ }
10157
+ // Check if we've exceeded max retries
10158
+ if (retryCount >= maxRetries) {
10159
+ console.error("Failed to detect ITM POS change after " + maxRetries + " attempts (" + maxRetries * 100 + "ms)");
10160
+ observer.error(new Error("ITM POS change timeout: expected POS " + transferPosExtId + " not detected in cookie"));
10161
+ return;
10162
+ }
10163
+ // If cookie doesn't match or doesn't exist, check again in 100ms
10164
+ setTimeout(checkCookie, 100);
10165
+ };
10166
+ // Start checking immediately
10167
+ checkCookie();
10168
+ });
10169
+ };
9864
10170
  return BasketTransferService;
9865
10171
  }());
9866
10172
  BasketTransferService.ɵfac = function BasketTransferService_Factory(t) { return new (t || BasketTransferService)(i0__namespace.ɵɵinject(AnalyticsService), i0__namespace.ɵɵinject(BasketsService), i0__namespace.ɵɵinject(ContextService), i0__namespace.ɵɵinject(PointOfSalesService), i0__namespace.ɵɵinject(i1__namespace.HttpClient), i0__namespace.ɵɵinject(UserService), i0__namespace.ɵɵinject(RecipesService), i0__namespace.ɵɵinject(SuppliersService), i0__namespace.ɵɵinject(BasketsSynchronizerService), i0__namespace.ɵɵinject(StatesService)); };
@@ -10007,7 +10313,8 @@
10007
10313
  miamWeb: 'https://miam.tech',
10008
10314
  mealzComponents: 'https://cdn.jsdelivr.net/npm/mealz-components@1.2/dist',
10009
10315
  mealzSsrApi: 'https://ssr-api.mealz.ai',
10010
- lang: 'fr'
10316
+ lang: 'fr',
10317
+ analyticsEnabled: true // Only used in DEV mode
10011
10318
  };
10012
10319
 
10013
10320
  var MiamInterceptor = /** @class */ (function () {
@@ -10796,6 +11103,13 @@
10796
11103
  }
10797
11104
  }, eventTrace).subscribe(function (passed) {
10798
11105
  if (passed) {
11106
+ // Send analytics event for add all products button click
11107
+ _this.analyticsService.sendEvent('entry.add-all', eventTrace.originPath, {
11108
+ recipe_id: _this.recipe.id,
11109
+ entry_count: _this.remainingBasketEntries.length.toString(),
11110
+ total_products: _this.recipe.ingredients.length.toString(),
11111
+ total_price: _this.recipePrice.remaining.toFixed(2).toString()
11112
+ }, detectJourney());
10799
11113
  _this.allIngredientsToBasketLoading = true;
10800
11114
  var productsToAdd_1 = [];
10801
11115
  _this.remainingProducts().forEach(function (re) { return _this.basketSynchroService.entryWillBeAdded(re.entry.selectedItem.extId).pipe(operators.take(1)).subscribe(function (result) {
@@ -18188,13 +18502,13 @@
18188
18502
  ReplaceItemComponent.prototype.onSelectItem = function (item) {
18189
18503
  this.replaceItemLoading = item;
18190
18504
  this.cdr.detectChanges();
18505
+ this.previousItem = this.basketEntry.selectedItem;
18191
18506
  if (this.addProductMode) {
18192
18507
  return this.itemAddition(item);
18193
18508
  }
18194
18509
  if (this.ignoreSelected) {
18195
18510
  this.ignoredBasketsService.removeIngredientFromIgnored(this.ingredient.id);
18196
18511
  }
18197
- this.previousItem = this.basketEntry.selectedItem;
18198
18512
  if (this.basketEntry.status === 'active') {
18199
18513
  this.selectItem(item);
18200
18514
  }
@@ -18294,7 +18608,7 @@
18294
18608
  this.recipeDetailsService.updateIngredientFromBasketLoading = this.basketEntry.status !== 'initial';
18295
18609
  };
18296
18610
  ReplaceItemComponent.prototype.itemAddition = function (item) {
18297
- this.basketsService.addItemToBasket(item, this.eventTrace);
18611
+ this.basketsService.addItemToBasket(item, this.eventTrace, this.previousItem);
18298
18612
  this.emitWhenRequestsEnded(item.id);
18299
18613
  };
18300
18614
  ReplaceItemComponent.prototype.emitWhenRequestsEnded = function (itemId) {
@@ -26504,7 +26818,7 @@
26504
26818
  i0__namespace.ɵɵadvance(1);
26505
26819
  i0__namespace.ɵɵproperty("ngForOf", ctx.sponsorBlocks);
26506
26820
  }
26507
- }, directives: [i2__namespace.NgForOf, SponsorBlockContainerComponent, i2__namespace.NgStyle], styles: [".sponsor-storytelling{border-radius:8px;width:100%;height:-moz-fit-content;height:fit-content;display:grid;grid-template-columns:repeat(10,1fr);grid-template-rows:auto;gap:24px}"], encapsulation: 2, changeDetection: 0 });
26821
+ }, directives: [i2__namespace.NgForOf, SponsorBlockContainerComponent, i2__namespace.NgStyle], styles: [".sponsor-storytelling{border-radius:8px;width:100%;height:-moz-fit-content;height:fit-content;display:grid;grid-template-columns:repeat(10,1fr);grid-template-rows:auto;gap:0 24px}"], encapsulation: 2, changeDetection: 0 });
26508
26822
  (function () {
26509
26823
  (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(SponsorStorytellingComponent, [{
26510
26824
  type: i0.Component,