ng-miam 9.2.7 → 9.2.9

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 (29) hide show
  1. package/bundles/ng-miam.umd.js +280 -60
  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/_models/recipe.js +1 -1
  6. package/esm2015/lib/_services/analytics.service.js +13 -2
  7. package/esm2015/lib/_services/basket-transfer.service.js +122 -12
  8. package/esm2015/lib/_services/recipes.service.js +110 -27
  9. package/esm2015/lib/_web-components/recipe-cards/recipe-card/recipe-card.component.js +34 -22
  10. package/esm2015/lib/environments/environment.js +3 -2
  11. package/esm2015/lib/environments/environment.prod.js +3 -2
  12. package/esm2015/lib/environments/version.js +2 -2
  13. package/fesm2015/ng-miam.js +275 -58
  14. package/fesm2015/ng-miam.js.map +1 -1
  15. package/lib/_models/recipe.d.ts +4 -0
  16. package/lib/_models/recipe.d.ts.map +1 -1
  17. package/lib/_services/analytics.service.d.ts.map +1 -1
  18. package/lib/_services/basket-transfer.service.d.ts +8 -2
  19. package/lib/_services/basket-transfer.service.d.ts.map +1 -1
  20. package/lib/_services/recipes.service.d.ts +27 -5
  21. package/lib/_services/recipes.service.d.ts.map +1 -1
  22. package/lib/_web-components/recipe-cards/recipe-card/recipe-card.component.d.ts +8 -6
  23. package/lib/_web-components/recipe-cards/recipe-card/recipe-card.component.d.ts.map +1 -1
  24. package/lib/environments/environment.d.ts +1 -0
  25. package/lib/environments/environment.d.ts.map +1 -1
  26. package/lib/environments/environment.prod.d.ts +1 -0
  27. package/lib/environments/environment.prod.d.ts.map +1 -1
  28. package/lib/environments/version.d.ts +1 -1
  29. package/package.json +1 -1
@@ -1685,7 +1685,8 @@
1685
1685
  miamWeb: 'https://miam.tech',
1686
1686
  mealzComponents: 'https://cdn.jsdelivr.net/npm/mealz-components@1.2/dist',
1687
1687
  mealzSsrApi: 'https://ssr-api.mealz.ai',
1688
- lang: 'fr'
1688
+ lang: 'fr',
1689
+ analyticsEnabled: true // Only used in DEV mode
1689
1690
  };
1690
1691
 
1691
1692
  var Ingredient = /** @class */ (function (_super) {
@@ -3501,7 +3502,7 @@
3501
3502
  EventJourney["EMPTY"] = "";
3502
3503
  })(EventJourney || (EventJourney = {}));
3503
3504
 
3504
- var VERSION = '9.2.4'; // TODO: replace by ##VERSION## and update it in the CI/CD
3505
+ var VERSION = '9.2.8'; // TODO: replace by ##VERSION## and update it in the CI/CD
3505
3506
 
3506
3507
  var ContextRegistryService = /** @class */ (function () {
3507
3508
  function ContextRegistryService() {
@@ -3533,6 +3534,11 @@
3533
3534
  }
3534
3535
  return location.href;
3535
3536
  }
3537
+ /**
3538
+ * Maps Angular environment to analytics environment
3539
+ * dev -> uat, uat -> uat, prod -> prod
3540
+ */
3541
+ var getAnalyticsEnvironment = function () { return environment$1.env === 'prod' ? 'prod' : 'uat'; };
3536
3542
  // Exported only for unit tests...
3537
3543
  // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
3538
3544
  function _onEmit(event) {
@@ -3577,7 +3583,8 @@
3577
3583
  if (!domain) {
3578
3584
  return mealzError('[Mealz] Analytics not initialized (domain cannot be null)');
3579
3585
  }
3580
- mealzSharedAnalytics.initSharedAnalytics(domain, VERSION, _onEmit);
3586
+ var analyticsEnvironment = getAnalyticsEnvironment();
3587
+ mealzSharedAnalytics.initSharedAnalytics(domain, VERSION, _onEmit, analyticsEnvironment);
3581
3588
  if (((_a = localStorage.getItem('_miam/affiliate')) === null || _a === void 0 ? void 0 : _a.length) > 0) {
3582
3589
  mealzSharedAnalytics.setAffiliate(localStorage.getItem('_miam/affiliate'));
3583
3590
  }
@@ -3587,6 +3594,10 @@
3587
3594
  if (this.contextRegistryService.disabledAnalytics && this.contextRegistryService.forbidProfiling) {
3588
3595
  return;
3589
3596
  }
3597
+ // Disable analytics only in development environment if environment variable analyticsEnabled is false
3598
+ if (environment$1.env === 'dev' && environment$1.analyticsEnabled === false) {
3599
+ return;
3600
+ }
3590
3601
  // Currently no way to know if it is search or shelves
3591
3602
  var journey = this.isMealzPage ? EventJourney.MEALZ : EventJourney.EMPTY;
3592
3603
  this.callMethodOrAddToQueue(function () { return mealzSharedAnalytics.sendEvent(name, url(path), journey, props); });
@@ -5053,6 +5064,10 @@
5053
5064
  ];
5054
5065
  _this.randomRecipeCount = 1;
5055
5066
  _this.recipes = [];
5067
+ // Batch suggestions system
5068
+ _this.pendingContexts = new Map();
5069
+ _this.contextResults = new Map();
5070
+ _this.batchSuggestionsDebounceTimer = null;
5056
5071
  _this.register();
5057
5072
  _this.appendDisplayedRecipeToUrlQuery();
5058
5073
  _this.initRandomSeed();
@@ -5237,33 +5252,6 @@
5237
5252
  this.randomRecipeCount++;
5238
5253
  return this.filter({ reviewed: true, exclude_no_picture: true }, { number: this.randomRecipeCount, size: 1 }, includes, fields, null, true);
5239
5254
  };
5240
- // Debounce to let enough time for the pos to be defined
5241
- RecipesService.prototype.getSuggestion = function (context, includes, fields) {
5242
- var _this = this;
5243
- if (includes === void 0) { includes = []; }
5244
- if (fields === void 0) { fields = {}; }
5245
- var suggestionFields = '';
5246
- Object.keys(fields).forEach(function (key) {
5247
- suggestionFields += "&fields[" + key + "]=" + fields[key].join(',');
5248
- });
5249
- return rxjs.combineLatest([
5250
- this.suppliersService.supplier$,
5251
- this.posService.posWasInitialized().pipe(operators.skipWhile(function (wasInitialized) { return !wasInitialized; }), operators.switchMap(function () { return _this.posService.pos$; }))
5252
- ]).pipe(operators.skipWhile(function (results) { return !results[0]; }), operators.debounceTime(100), operators.switchMap(function (results) {
5253
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
5254
- var body = _this.buildSuggestionBody(context);
5255
- var supplierFilter = "supplier_id=" + results[0].id;
5256
- if (results[1]) {
5257
- supplierFilter = "supplier_id=" + results[0].id + "&pos_id=" + results[1].id;
5258
- }
5259
- var url = MIAM_API_HOST$2 + ("recipes/suggestions?" + supplierFilter + "&allow-empty=true" + ((includes.length > 0) ? ('&include=' + includes.join(',')) : '') + suggestionFields + _this.buildfilterUrlFromPreferences());
5260
- return _this.http.post(url, body);
5261
- }), operators.map(function (returnedRecipes) {
5262
- var recipes = _this.newCollection();
5263
- recipes.fill(returnedRecipes);
5264
- return recipes.data;
5265
- }));
5266
- };
5267
5255
  RecipesService.prototype.searchRecipeByExtId = function (recipeExtId) {
5268
5256
  var _this = this;
5269
5257
  var url = MIAM_API_HOST$2 + "recipes/external/" + recipeExtId;
@@ -5461,6 +5449,113 @@
5461
5449
  return "&filter[" + k + "]=" + v;
5462
5450
  }).join('');
5463
5451
  };
5452
+ /**
5453
+ * Queue a context for the next batch suggestions request
5454
+ */
5455
+ RecipesService.prototype.queueSuggestionContext = function (context) {
5456
+ var _this = this;
5457
+ this.pendingContexts.set(context.contextId, context);
5458
+ if (this.batchSuggestionsDebounceTimer) {
5459
+ clearTimeout(this.batchSuggestionsDebounceTimer);
5460
+ }
5461
+ this.batchSuggestionsDebounceTimer = setTimeout(function () {
5462
+ _this.fetchBatchSuggestions();
5463
+ _this.batchSuggestionsDebounceTimer = null;
5464
+ }, 100);
5465
+ };
5466
+ /**
5467
+ * Observe suggestion result for a given context id.
5468
+ */
5469
+ RecipesService.prototype.observeSuggestion = function (contextId) {
5470
+ if (!this.contextResults.has(contextId)) {
5471
+ this.contextResults.set(contextId, new rxjs.BehaviorSubject(null));
5472
+ }
5473
+ return this.contextResults.get(contextId).asObservable();
5474
+ };
5475
+ /**
5476
+ * Fetch suggestions for all queued contexts in a single API call.
5477
+ */
5478
+ RecipesService.prototype.fetchBatchSuggestions = function () {
5479
+ var _this = this;
5480
+ if (this.pendingContexts.size === 0) {
5481
+ return;
5482
+ }
5483
+ var queuedContexts = Array.from(this.pendingContexts.values());
5484
+ rxjs.combineLatest([
5485
+ this.suppliersService.supplier$,
5486
+ this.posService.posWasInitialized().pipe(operators.skipWhile(function (wasInitialized) { return !wasInitialized; }), operators.switchMap(function () { return _this.posService.pos$; }))
5487
+ ]).pipe(operators.skipWhile(function (results) { return !results[0]; }), operators.take(1), operators.switchMap(function (results) {
5488
+ var url = _this.buildSuggestionsBatchUrl(results[0], results[1]);
5489
+ var body = _this.buildSuggestionsBatchBody(queuedContexts);
5490
+ return _this.http.post(url, body);
5491
+ }), operators.catchError(function (error) {
5492
+ _this.handleBatchSuggestionsError(error);
5493
+ return rxjs.of(null);
5494
+ })).subscribe(function (returnedRecipes) {
5495
+ if (!returnedRecipes) {
5496
+ _this.handleBatchSuggestionsError(new Error('No recipes returned from batch suggestions API'));
5497
+ return;
5498
+ }
5499
+ var suggestionsCollection = _this.newCollection();
5500
+ suggestionsCollection.fill(returnedRecipes);
5501
+ _this.distributeBatchSuggestions(suggestionsCollection.data, queuedContexts);
5502
+ });
5503
+ };
5504
+ RecipesService.prototype.buildSuggestionsBatchBody = function (contexts) {
5505
+ return {
5506
+ contexts: contexts.map(function (ctx) { return ({
5507
+ 'context-id': ctx.contextId,
5508
+ 'item-ext-ids': ctx.itemExtIds
5509
+ }); })
5510
+ };
5511
+ };
5512
+ RecipesService.prototype.buildSuggestionsBatchUrl = function (supplier, pos) {
5513
+ var url = MIAM_API_HOST$2 + "recipes/suggestions-batch?supplier-id=" + supplier.id;
5514
+ if (pos === null || pos === void 0 ? void 0 : pos.id) {
5515
+ url += "&point-of-sale-id=" + pos.id;
5516
+ }
5517
+ if (pos === null || pos === void 0 ? void 0 : pos.extId) {
5518
+ url += "&point-of-sale-ext-id=" + pos.extId;
5519
+ }
5520
+ url += '&personalized=true';
5521
+ url += this.buildfilterUrlFromPreferences();
5522
+ return url;
5523
+ };
5524
+ RecipesService.prototype.handleBatchSuggestionsError = function (error) {
5525
+ var _this = this;
5526
+ console.error('Batch suggestions API error:', error);
5527
+ this.pendingContexts.forEach(function (ctx) {
5528
+ _this.emitSuggestionForContext(ctx.contextId, null);
5529
+ });
5530
+ this.pendingContexts.clear();
5531
+ };
5532
+ /**
5533
+ * Distribute batch suggestions to their respective contexts
5534
+ */
5535
+ RecipesService.prototype.distributeBatchSuggestions = function (response, queuedContexts) {
5536
+ var _this = this;
5537
+ var recipeByContextId = new Map();
5538
+ response.forEach(function (recipe) {
5539
+ var contextId = recipe.attributes['context-id'];
5540
+ if (contextId) {
5541
+ recipeByContextId.set(contextId, recipe);
5542
+ }
5543
+ });
5544
+ queuedContexts.forEach(function (ctx) {
5545
+ var suggestion = recipeByContextId.get(ctx.contextId) || null;
5546
+ _this.emitSuggestionForContext(ctx.contextId, suggestion);
5547
+ _this.pendingContexts.delete(ctx.contextId);
5548
+ });
5549
+ };
5550
+ /**
5551
+ * Emit suggestion for a specific context
5552
+ */
5553
+ RecipesService.prototype.emitSuggestionForContext = function (contextId, suggestion) {
5554
+ if (!this.contextResults.has(contextId)) {
5555
+ this.contextResults.set(contextId, new rxjs.BehaviorSubject(null));
5556
+ }
5557
+ this.contextResults.get(contextId).next(suggestion);
5558
+ };
5464
5559
  return RecipesService;
5465
5560
  }(i2$2.Service));
5466
5561
  RecipesService.ɵfac = function RecipesService_Factory(t) { return new (t || RecipesService)(i0__namespace.ɵɵinject(i1__namespace.HttpClient), i0__namespace.ɵɵinject(AnalyticsService), i0__namespace.ɵɵinject(RecipeProviderService), i0__namespace.ɵɵinject(RecipeStatusService), i0__namespace.ɵɵinject(RecipeTypeService), i0__namespace.ɵɵinject(SuppliersService), i0__namespace.ɵɵinject(PointOfSalesService), i0__namespace.ɵɵinject(IngredientsService), i0__namespace.ɵɵinject(RecipeStepsService), i0__namespace.ɵɵinject(SponsorService), i0__namespace.ɵɵinject(PackageService), i0__namespace.ɵɵinject(TagsService), i0__namespace.ɵɵinject(RecipeLikesService), i0__namespace.ɵɵinject(SeoService), i0__namespace.ɵɵinject(PreferencesService), i0__namespace.ɵɵinject(StoreLocatorService)); };
@@ -9625,7 +9720,8 @@
9625
9720
  };
9626
9721
  BasketTransferService.prototype.setSessionData = function (params) {
9627
9722
  sessionStorage.setItem('_miam/transferredBasketToken', params.basketToken);
9628
- sessionStorage.setItem('_miam/posOfSaleExtId', params.posExtId);
9723
+ // ITM specific: use pdvref if posExtId is not set
9724
+ sessionStorage.setItem('_miam/pointOfSaleExtId', params.posExtId || params.pdvref);
9629
9725
  };
9630
9726
  BasketTransferService.prototype.clearTransferSessionData = function () {
9631
9727
  sessionStorage.removeItem('_miam/transferredBasketToken');
@@ -9660,8 +9756,33 @@
9660
9756
  BasketTransferService.prototype.navigateToTransferUrl = function () {
9661
9757
  var transferUrl = sessionStorage.getItem('_miam/transferUrl');
9662
9758
  if (transferUrl) {
9759
+ // Adjust pdvref only for ITM (supplier 23) when navigating
9760
+ var finalUrl_1 = transferUrl;
9761
+ if (this.isITMSupplier()) {
9762
+ try {
9763
+ var urlObj = new URL(transferUrl);
9764
+ var rawPdvref = urlObj.searchParams.get('pdvref');
9765
+ if (rawPdvref) {
9766
+ var padded = this.padPdvref(rawPdvref);
9767
+ if (padded && padded !== rawPdvref) {
9768
+ urlObj.searchParams.set('pdvref', padded);
9769
+ }
9770
+ }
9771
+ finalUrl_1 = urlObj.toString();
9772
+ }
9773
+ catch (err) {
9774
+ // Fallback for non-standard URLs
9775
+ var match = transferUrl.match(/([?&])pdvref=([^&]+)/);
9776
+ if (match) {
9777
+ var padded = this.padPdvref(match[2]);
9778
+ if (padded) {
9779
+ finalUrl_1 = transferUrl.replace(/([?&])pdvref=[^&]+/, "$1pdvref=" + padded);
9780
+ }
9781
+ }
9782
+ }
9783
+ }
9663
9784
  // Apparently Safari blocks window.open(..., "_blank") if called in an async function and setTimeout makes it run on the main thread
9664
- setTimeout(function () { return window.open(transferUrl, '_blank'); });
9785
+ setTimeout(function () { return window.open(finalUrl_1, '_blank'); });
9665
9786
  }
9666
9787
  };
9667
9788
  BasketTransferService.prototype.abortTransfer = function () {
@@ -9684,7 +9805,9 @@
9684
9805
  };
9685
9806
  BasketTransferService.prototype.tryToTransferBasket = function (params) {
9686
9807
  var _this = this;
9687
- 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) {
9808
+ return this.callHookbackIfNotLogged().pipe(operators.skipWhile(function (isLogged) { return !isLogged; }),
9809
+ // ITM specific: use pdvref if posExtId is not set
9810
+ 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) {
9688
9811
  _this.previousBasketEntries = deepCloneWithClass(entries);
9689
9812
  return pos;
9690
9813
  })); })); }), operators.switchMap(function (pos) { return _this.transferBasketForPos(pos, params.basketToken); }), operators.take(1)); }));
@@ -9722,7 +9845,8 @@
9722
9845
  };
9723
9846
  BasketTransferService.prototype.createTransferAction = function (entries) {
9724
9847
  var _this = this;
9725
- var transferActions = this.filterNewAndUpdatedEntries(entries).map(function (basketEntry) {
9848
+ var filteredEntries = this.filterNewAndUpdatedEntries(entries);
9849
+ var transferActions = filteredEntries.map(function (basketEntry) {
9726
9850
  var transferAction = new BasketTransferAction(basketEntry, {}, _this.basketsService, undefined, _this.suppliersService);
9727
9851
  _this.handleActionErrors(transferAction);
9728
9852
  return transferAction;
@@ -9739,26 +9863,46 @@
9739
9863
  var _this = this;
9740
9864
  return this.userService.isLogged$.pipe(operators.take(1), operators.map(function (isLogged) { return _this.contextService.hookCallback(isLogged, true); }));
9741
9865
  };
9742
- BasketTransferService.prototype.forcePosIfUnset = function (transferPosExtId) {
9866
+ BasketTransferService.prototype.ensureTransferPosSelected = function (transferPosExtId) {
9743
9867
  var _this = this;
9744
9868
  return this.posService.posWasInitialized().pipe(operators.takeUntil(this.transferComplete$), operators.switchMap(function () { return _this.posService.pos$.pipe(operators.take(1)); }), operators.switchMap(function (pos) {
9745
9869
  var posSet = pos && pos.extId === transferPosExtId;
9746
9870
  if (!posSet) {
9747
- _this.contextService.forcePosCallback(transferPosExtId);
9871
+ // Special handling for ITM (supplier ID 23)
9872
+ if (_this.isITMSupplier()) {
9873
+ return _this.handleITMPosChange(transferPosExtId);
9874
+ }
9875
+ else {
9876
+ if (transferPosExtId) {
9877
+ _this.contextService.forcePosCallback(transferPosExtId);
9878
+ }
9879
+ }
9748
9880
  }
9749
9881
  return rxjs.of(posSet);
9750
9882
  }));
9751
9883
  };
9884
+ BasketTransferService.prototype.getCookie = function (name) {
9885
+ var _a;
9886
+ var value = "; " + document.cookie;
9887
+ var parts = value.split("; " + name + "=");
9888
+ if (parts.length === 2) {
9889
+ return ((_a = parts.pop()) === null || _a === void 0 ? void 0 : _a.split(';').shift()) || null;
9890
+ }
9891
+ return null;
9892
+ };
9752
9893
  BasketTransferService.prototype.getTransferData = function () {
9753
9894
  var _a;
9754
9895
  var currentUrl = window.location.href;
9755
9896
  var urlParams = new URL(currentUrl).searchParams;
9756
9897
  var basketToken = urlParams.get('transferred_basket_token') || sessionStorage.getItem('_miam/transferredBasketToken');
9757
- var posExtId = urlParams.get('point_of_sale_ext_id') || urlParams.get('magasin_id') || sessionStorage.getItem('_miam/posOfSaleExtId');
9898
+ var posExtId = urlParams.get('point_of_sale_ext_id') ||
9899
+ urlParams.get('magasin_id') ||
9900
+ sessionStorage.getItem('_miam/pointOfSaleExtId');
9758
9901
  var affiliate = (_a = urlParams.get('affiliate')) === null || _a === void 0 ? void 0 : _a.toLowerCase();
9759
- if (basketToken && posExtId) {
9902
+ var pdvref = urlParams.get('pdvref');
9903
+ if (basketToken && (posExtId || pdvref)) {
9760
9904
  this.removeTransferParamsFromUrl();
9761
- return { basketToken: basketToken, posExtId: posExtId, affiliate: affiliate };
9905
+ return { basketToken: basketToken, posExtId: posExtId, affiliate: affiliate, pdvref: pdvref };
9762
9906
  }
9763
9907
  else {
9764
9908
  return null;
@@ -9773,10 +9917,73 @@
9773
9917
  urlParams.delete('point_of_sale_ext_id');
9774
9918
  urlParams.delete('magasin_id');
9775
9919
  urlParams.delete('affiliate');
9920
+ urlParams.delete('pdvref'); // Remove ITM specific parameter
9776
9921
  var newUrl = currentUrl.split('?')[0] + (urlParams.toString().length > 0 ? '?' + urlParams.toString() : '');
9777
9922
  history.replaceState({}, document.title, newUrl);
9778
9923
  }
9779
9924
  };
9925
+ // ITM specific methods
9926
+ BasketTransferService.prototype.isITMSupplier = function () {
9927
+ var currentPos = this.posService.pos$.getValue();
9928
+ return currentPos && currentPos.relationships.supplier.data.id === '23';
9929
+ };
9930
+ BasketTransferService.prototype.padPdvref = function (pdvref) {
9931
+ if (!pdvref) {
9932
+ return pdvref;
9933
+ }
9934
+ // Pad pdvref to exactly 5 characters with leading zeros only if shorter than 5
9935
+ return pdvref.length < 5 ? pdvref.padStart(5, '0') : pdvref;
9936
+ };
9937
+ BasketTransferService.prototype.handleITMPosChange = function (transferPosExtId) {
9938
+ var _this = this;
9939
+ var expectedPosId = transferPosExtId;
9940
+ return this.waitForITMCookie(expectedPosId).pipe(operators.catchError(function (error) {
9941
+ console.warn('ITM cookie check failed, falling back to normal POS callback:', error);
9942
+ if (expectedPosId) {
9943
+ _this.contextService.forcePosCallback(transferPosExtId);
9944
+ }
9945
+ return rxjs.of(false);
9946
+ }));
9947
+ };
9948
+ BasketTransferService.prototype.waitForITMCookie = function (transferPosExtId) {
9949
+ var _this = this;
9950
+ return new rxjs.Observable(function (observer) {
9951
+ var maxRetries = 50; // 5 seconds total (50 * 100ms)
9952
+ var retryCount = 0;
9953
+ var checkCookie = function () {
9954
+ retryCount++;
9955
+ var itmPdvCookie = _this.getCookie('itm_pdv');
9956
+ if (itmPdvCookie) {
9957
+ try {
9958
+ var decodedCookie = decodeURIComponent(itmPdvCookie);
9959
+ var pdvData = JSON.parse(decodedCookie);
9960
+ var cookiePosRef = pdvData.ref;
9961
+ // Check if the cookie POS matches the required transfer POS
9962
+ if (cookiePosRef === transferPosExtId) {
9963
+ // Refresh the page to ensure the new POS context is loaded
9964
+ observer.next(true);
9965
+ observer.complete();
9966
+ window.location.reload();
9967
+ return;
9968
+ }
9969
+ }
9970
+ catch (error) {
9971
+ console.warn('Failed to parse itm_pdv cookie:', error);
9972
+ }
9973
+ }
9974
+ // Check if we've exceeded max retries
9975
+ if (retryCount >= maxRetries) {
9976
+ console.error("Failed to detect ITM POS change after " + maxRetries + " attempts (" + maxRetries * 100 + "ms)");
9977
+ observer.error(new Error("ITM POS change timeout: expected POS " + transferPosExtId + " not detected in cookie"));
9978
+ return;
9979
+ }
9980
+ // If cookie doesn't match or doesn't exist, check again in 100ms
9981
+ setTimeout(checkCookie, 100);
9982
+ };
9983
+ // Start checking immediately
9984
+ checkCookie();
9985
+ });
9986
+ };
9780
9987
  return BasketTransferService;
9781
9988
  }());
9782
9989
  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)); };
@@ -9923,7 +10130,8 @@
9923
10130
  miamWeb: 'https://miam.tech',
9924
10131
  mealzComponents: 'https://cdn.jsdelivr.net/npm/mealz-components@1.2/dist',
9925
10132
  mealzSsrApi: 'https://ssr-api.mealz.ai',
9926
- lang: 'fr'
10133
+ lang: 'fr',
10134
+ analyticsEnabled: true // Only used in DEV mode
9927
10135
  };
9928
10136
 
9929
10137
  var MiamInterceptor = /** @class */ (function () {
@@ -21120,6 +21328,9 @@
21120
21328
  RecipeCardComponent.prototype.ngOnInit = function () {
21121
21329
  var _this = this;
21122
21330
  this.subscriptions.push(this.recipeService.displayedRecipeChanged$.subscribe(function () { return _this.cdr.detectChanges(); }));
21331
+ if (this.contextId) {
21332
+ this.subscribeToSuggestions();
21333
+ }
21123
21334
  };
21124
21335
  RecipeCardComponent.prototype.currentPath = function () {
21125
21336
  return '';
@@ -21132,8 +21343,11 @@
21132
21343
  else if (this.recipeId) {
21133
21344
  this.loadRecipeFromId();
21134
21345
  }
21135
- else if (simpleChanges.productIds && !this.randomModeEnable) {
21136
- this.loadRecipeFromContext();
21346
+ else if (simpleChanges.productIds && !this.randomModeEnable && this.contextId) {
21347
+ this.registerSuggestionContext();
21348
+ }
21349
+ else if (this.randomModeEnable) {
21350
+ this.fetchRandomRecipe();
21137
21351
  }
21138
21352
  };
21139
21353
  RecipeCardComponent.prototype.ngAfterViewInit = function () {
@@ -21228,17 +21442,14 @@
21228
21442
  _this.afterRecipeLoad(result);
21229
21443
  }));
21230
21444
  };
21231
- /**
21232
- * Get a suggestion based on context (either productIds or randomMode). Hide the card if none is returned
21233
- */
21234
- RecipeCardComponent.prototype.loadRecipeFromContext = function () {
21445
+ /*
21446
+ * Subscribe to context suggestions; hide card if none
21447
+ */
21448
+ RecipeCardComponent.prototype.subscribeToSuggestions = function () {
21235
21449
  var _this = this;
21236
- this.subscriptions.push(this.fetchSuggestionOrRandom().pipe(operators.skipWhile(function (results) { return !results; }), operators.catchError(function (err) {
21237
- _this.hide.emit();
21238
- return rxjs.of(err);
21239
- })).subscribe(function (results) {
21240
- if ((results === null || results === void 0 ? void 0 : results.length) > 0) {
21241
- _this.afterRecipeLoad(results[0]);
21450
+ this.subscriptions.push(this.recipeService.observeSuggestion(this.contextId).pipe(operators.skip(1)).subscribe(function (suggestion) {
21451
+ if (suggestion) {
21452
+ _this.afterRecipeLoad(suggestion);
21242
21453
  }
21243
21454
  else {
21244
21455
  _this.isloaded = true;
@@ -21255,13 +21466,8 @@
21255
21466
  this.isloaded = true;
21256
21467
  this.cdr.detectChanges();
21257
21468
  };
21258
- RecipeCardComponent.prototype.fetchSuggestionOrRandom = function () {
21259
- if (this.randomModeEnable) {
21260
- return this.recipeService.getRandom(recipeIncludes$4, recipeSparseFields$4);
21261
- }
21262
- else {
21263
- return this.recipeService.getSuggestion(this.productIds, recipeIncludes$4, recipeSparseFields$4);
21264
- }
21469
+ RecipeCardComponent.prototype.fetchRandomRecipe = function () {
21470
+ return this.recipeService.getRandom(recipeIncludes$4, recipeSparseFields$4);
21265
21471
  };
21266
21472
  /**
21267
21473
  * Update guests from the value in the basket if the recipe is in the basket
@@ -21293,10 +21499,22 @@
21293
21499
  var tags = ((_b = (_a = this.recipe) === null || _a === void 0 ? void 0 : _a.relationships.tags) === null || _b === void 0 ? void 0 : _b.data) || [];
21294
21500
  this.isDrink = tags.some(function (tag) { return ['meal_type_boisson', 'meal_type_cocktail'].includes(tag.id); });
21295
21501
  };
21502
+ /**
21503
+ * Registers recipe suggestion context with product IDs for batch processing
21504
+ */
21505
+ RecipeCardComponent.prototype.registerSuggestionContext = function () {
21506
+ if (!this.contextId || !this.productIds || this.productIds.length === 0) {
21507
+ return;
21508
+ }
21509
+ this.recipeService.queueSuggestionContext({
21510
+ contextId: this.contextId,
21511
+ itemExtIds: this.productIds.map(function (product) { return product.id; })
21512
+ });
21513
+ };
21296
21514
  return RecipeCardComponent;
21297
21515
  }(EventTracerComponent));
21298
21516
  RecipeCardComponent.ɵfac = function RecipeCardComponent_Factory(t) { return new (t || RecipeCardComponent)(i0__namespace.ɵɵdirectiveInject(AnalyticsService), i0__namespace.ɵɵdirectiveInject(i0__namespace.ChangeDetectorRef), i0__namespace.ɵɵdirectiveInject(RecipesService), i0__namespace.ɵɵdirectiveInject(BasketsService), i0__namespace.ɵɵdirectiveInject(UserService), i0__namespace.ɵɵdirectiveInject(ContextService), i0__namespace.ɵɵdirectiveInject(i0__namespace.ElementRef)); };
21299
- RecipeCardComponent.ɵcmp = i0__namespace.ɵɵdefineComponent({ type: RecipeCardComponent, selectors: [["ng-miam-recipe-card"]], inputs: { recipeId: "recipeId", recipe: "recipe", randomModeEnable: "randomModeEnable", productIds: "productIds", previewAllowed: "previewAllowed", helpButtonAllowed: "helpButtonAllowed", displayInfos: "displayInfos", displayPricing: "displayPricing", displayGuests: "displayGuests", addRecipeMode: "addRecipeMode", replaceMode: "replaceMode", displayVariant: "displayVariant", serves: "serves" }, outputs: { removedFromFavorite: "removedFromFavorite", displayed: "displayed", removeFromMealsPlanner: "removeFromMealsPlanner", addToMealsPlanner: "addToMealsPlanner", openCatalog: "openCatalog", hide: "hide" }, features: [i0__namespace.ɵɵInheritDefinitionFeature, i0__namespace.ɵɵNgOnChangesFeature], decls: 3, vars: 10, consts: function () {
21517
+ RecipeCardComponent.ɵcmp = i0__namespace.ɵɵdefineComponent({ type: RecipeCardComponent, selectors: [["ng-miam-recipe-card"]], inputs: { recipeId: "recipeId", recipe: "recipe", randomModeEnable: "randomModeEnable", productIds: "productIds", previewAllowed: "previewAllowed", helpButtonAllowed: "helpButtonAllowed", displayInfos: "displayInfos", displayPricing: "displayPricing", displayGuests: "displayGuests", addRecipeMode: "addRecipeMode", replaceMode: "replaceMode", displayVariant: "displayVariant", contextId: "contextId", serves: "serves" }, outputs: { removedFromFavorite: "removedFromFavorite", displayed: "displayed", removeFromMealsPlanner: "removeFromMealsPlanner", addToMealsPlanner: "addToMealsPlanner", openCatalog: "openCatalog", hide: "hide" }, features: [i0__namespace.ɵɵInheritDefinitionFeature, i0__namespace.ɵɵNgOnChangesFeature], decls: 3, vars: 10, consts: function () {
21300
21518
  var i18n_0;
21301
21519
  if (typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode) {
21302
21520
  var MSG_EXTERNAL_9004334984468055592$$LIB__WEB_COMPONENTS_RECIPE_CARDS_RECIPE_CARD_RECIPE_CARD_COMPONENT_TS___1 = goog.getMsg("Changer");
@@ -21380,6 +21598,8 @@
21380
21598
  type: i0.Input
21381
21599
  }], displayVariant: [{
21382
21600
  type: i0.Input
21601
+ }], contextId: [{
21602
+ type: i0.Input
21383
21603
  }], serves: [{
21384
21604
  type: i0.Input
21385
21605
  }], removedFromFavorite: [{