ng-miam 10.7.1 → 10.9.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.
Files changed (59) hide show
  1. package/bundles/ng-miam.umd.js +474 -114
  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/_components/product-card/product-card.component.js +11 -3
  6. package/esm2015/lib/_constants/error-toast-codes.js +8 -0
  7. package/esm2015/lib/_models/basket-actions/add-ingredient-from-replace-action.js +4 -2
  8. package/esm2015/lib/_models/ingredient.js +1 -1
  9. package/esm2015/lib/_services/analytics.service.js +9 -4
  10. package/esm2015/lib/_services/context-registry.service.js +2 -1
  11. package/esm2015/lib/_services/context.service.js +9 -2
  12. package/esm2015/lib/_services/new-recipe-details.service.js +49 -14
  13. package/esm2015/lib/_services/recipe-details-products.service.js +36 -5
  14. package/esm2015/lib/_services/recipe-details.service.js +31 -10
  15. package/esm2015/lib/_services/recipes.service.js +5 -1
  16. package/esm2015/lib/_services/replace-item.service.js +115 -60
  17. package/esm2015/lib/_services/store-out-of-stock.service.js +24 -5
  18. package/esm2015/lib/_types/builded/mealz-interface.js +1 -1
  19. package/esm2015/lib/_types/builded/mealz-internal-interface.js +1 -1
  20. package/esm2015/lib/_utils/attach-product-show-tracking.js +57 -0
  21. package/esm2015/lib/_utils/product-show-tracker.js +62 -0
  22. package/esm2015/lib/_web-components/basket-preview/basket-preview-product/basket-preview-product.component.js +3 -1
  23. package/esm2015/lib/environments/environment.js +2 -2
  24. package/esm2015/lib/environments/environment.prod.js +2 -2
  25. package/esm2015/lib/environments/version.js +2 -2
  26. package/fesm2015/ng-miam.js +402 -102
  27. package/fesm2015/ng-miam.js.map +1 -1
  28. package/lib/_components/product-card/product-card.component.d.ts +1 -0
  29. package/lib/_components/product-card/product-card.component.d.ts.map +1 -1
  30. package/lib/_constants/error-toast-codes.d.ts +5 -0
  31. package/lib/_constants/error-toast-codes.d.ts.map +1 -0
  32. package/lib/_models/basket-actions/add-ingredient-from-replace-action.d.ts.map +1 -1
  33. package/lib/_models/ingredient.d.ts +2 -0
  34. package/lib/_models/ingredient.d.ts.map +1 -1
  35. package/lib/_services/analytics.service.d.ts.map +1 -1
  36. package/lib/_services/context-registry.service.d.ts +5 -0
  37. package/lib/_services/context-registry.service.d.ts.map +1 -1
  38. package/lib/_services/context.service.d.ts.map +1 -1
  39. package/lib/_services/new-recipe-details.service.d.ts +3 -1
  40. package/lib/_services/new-recipe-details.service.d.ts.map +1 -1
  41. package/lib/_services/recipe-details-products.service.d.ts +5 -1
  42. package/lib/_services/recipe-details-products.service.d.ts.map +1 -1
  43. package/lib/_services/recipe-details.service.d.ts.map +1 -1
  44. package/lib/_services/recipes.service.d.ts.map +1 -1
  45. package/lib/_services/replace-item.service.d.ts +26 -15
  46. package/lib/_services/replace-item.service.d.ts.map +1 -1
  47. package/lib/_services/store-out-of-stock.service.d.ts +7 -0
  48. package/lib/_services/store-out-of-stock.service.d.ts.map +1 -1
  49. package/lib/_types/builded/mealz-interface.d.ts +7 -0
  50. package/lib/_types/builded/mealz-interface.d.ts.map +1 -1
  51. package/lib/_types/builded/mealz-internal-interface.d.ts +9 -0
  52. package/lib/_types/builded/mealz-internal-interface.d.ts.map +1 -1
  53. package/lib/_utils/attach-product-show-tracking.d.ts +14 -0
  54. package/lib/_utils/attach-product-show-tracking.d.ts.map +1 -0
  55. package/lib/_utils/product-show-tracker.d.ts +26 -0
  56. package/lib/_utils/product-show-tracker.d.ts.map +1 -0
  57. package/lib/_web-components/basket-preview/basket-preview-product/basket-preview-product.component.d.ts.map +1 -1
  58. package/lib/environments/version.d.ts +1 -1
  59. package/package.json +1 -1
@@ -1641,13 +1641,13 @@
1641
1641
  env: 'prod',
1642
1642
  miamAPI: 'https://api.miam.tech',
1643
1643
  miamWeb: 'https://miam.tech',
1644
- mealzComponents: 'https://cdn.jsdelivr.net/npm/mealz-components@2.11/dist',
1644
+ mealzComponents: 'https://cdn.jsdelivr.net/npm/mealz-components@2.12/dist',
1645
1645
  mealzSsrApi: 'https://ssr-api.mealz.ai',
1646
1646
  lang: 'fr',
1647
1647
  analyticsEnabled: true // Only used in DEV mode
1648
1648
  };
1649
1649
 
1650
- var WINDOW_SINGLETON_KEY = '__mealzRecipeCardShowTracker__';
1650
+ var WINDOW_SINGLETON_KEY$1 = '__mealzRecipeCardShowTracker__';
1651
1651
  /**
1652
1652
  * Tracks recipe.show events and prevents duplicates (first show, or again after scroll).
1653
1653
  * Shared across SDK and Lit recipe cards via {@link WINDOW_SINGLETON_KEY} on window.
@@ -1672,7 +1672,7 @@
1672
1672
  var w = typeof window !== 'undefined'
1673
1673
  ? window
1674
1674
  : undefined;
1675
- var fromWindow = w === null || w === void 0 ? void 0 : w[WINDOW_SINGLETON_KEY];
1675
+ var fromWindow = w === null || w === void 0 ? void 0 : w[WINDOW_SINGLETON_KEY$1];
1676
1676
  if (fromWindow) {
1677
1677
  RecipeCardShowTracker.instance = fromWindow;
1678
1678
  return fromWindow;
@@ -1680,7 +1680,7 @@
1680
1680
  if (!RecipeCardShowTracker.instance) {
1681
1681
  RecipeCardShowTracker.instance = new RecipeCardShowTracker();
1682
1682
  if (w) {
1683
- w[WINDOW_SINGLETON_KEY] = RecipeCardShowTracker.instance;
1683
+ w[WINDOW_SINGLETON_KEY$1] = RecipeCardShowTracker.instance;
1684
1684
  }
1685
1685
  }
1686
1686
  return RecipeCardShowTracker.instance;
@@ -1740,7 +1740,7 @@
1740
1740
  this.hasScrolled = false;
1741
1741
  RecipeCardShowTracker.instance = null;
1742
1742
  if (typeof window !== 'undefined') {
1743
- delete window[WINDOW_SINGLETON_KEY];
1743
+ delete window[WINDOW_SINGLETON_KEY$1];
1744
1744
  }
1745
1745
  };
1746
1746
  RecipeCardShowTracker.prototype.setupScrollListener = function () {
@@ -1843,6 +1843,136 @@
1843
1843
  };
1844
1844
  }
1845
1845
 
1846
+ var WINDOW_SINGLETON_KEY = '__mealzProductShowTracker__';
1847
+ /**
1848
+ * Dedupes product.show per recipe visit (recipeId:itemId).
1849
+ * Cleared at the start of each openRecipeDetails visit and by ContextService.loadAndSetupRecipe
1850
+ * at the start of each recipe-to-basket visit.
1851
+ */
1852
+ var ProductShowTracker = /** @class */ (function () {
1853
+ function ProductShowTracker() {
1854
+ var _this = this;
1855
+ this.trackedKeys = new Set();
1856
+ this.handlePageUnload = function () {
1857
+ _this.destroy();
1858
+ };
1859
+ if (typeof window !== 'undefined') {
1860
+ window.addEventListener('beforeunload', this.handlePageUnload);
1861
+ }
1862
+ }
1863
+ ProductShowTracker.getInstance = function () {
1864
+ var windowRef = typeof window !== 'undefined' ? window : undefined;
1865
+ var fromWindow = windowRef === null || windowRef === void 0 ? void 0 : windowRef[WINDOW_SINGLETON_KEY];
1866
+ if (fromWindow) {
1867
+ ProductShowTracker.instance = fromWindow;
1868
+ return fromWindow;
1869
+ }
1870
+ if (!ProductShowTracker.instance) {
1871
+ ProductShowTracker.instance = new ProductShowTracker();
1872
+ if (windowRef) {
1873
+ windowRef[WINDOW_SINGLETON_KEY] = ProductShowTracker.instance;
1874
+ }
1875
+ }
1876
+ return ProductShowTracker.instance;
1877
+ };
1878
+ ProductShowTracker.prototype.trackProductShow = function (analyticsPath, props) {
1879
+ var _a, _b;
1880
+ var trackingKey = props.recipe_id + ":" + props.item_id;
1881
+ if (this.trackedKeys.has(trackingKey)) {
1882
+ return;
1883
+ }
1884
+ this.trackedKeys.add(trackingKey);
1885
+ (_b = (_a = window.mealzInternal) === null || _a === void 0 ? void 0 : _a.analytics) === null || _b === void 0 ? void 0 : _b.sendEvent('product.show', analyticsPath, props);
1886
+ };
1887
+ ProductShowTracker.prototype.clearForRecipe = function (recipeId) {
1888
+ var e_1, _c;
1889
+ var prefix = recipeId + ":";
1890
+ try {
1891
+ for (var _d = __values(this.trackedKeys), _e = _d.next(); !_e.done; _e = _d.next()) {
1892
+ var key = _e.value;
1893
+ if (key.startsWith(prefix)) {
1894
+ this.trackedKeys.delete(key);
1895
+ }
1896
+ }
1897
+ }
1898
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1899
+ finally {
1900
+ try {
1901
+ if (_e && !_e.done && (_c = _d.return)) _c.call(_d);
1902
+ }
1903
+ finally { if (e_1) throw e_1.error; }
1904
+ }
1905
+ };
1906
+ ProductShowTracker.prototype.clearAll = function () {
1907
+ this.trackedKeys.clear();
1908
+ };
1909
+ ProductShowTracker.prototype.destroy = function () {
1910
+ if (typeof window !== 'undefined') {
1911
+ window.removeEventListener('beforeunload', this.handlePageUnload);
1912
+ delete window[WINDOW_SINGLETON_KEY];
1913
+ }
1914
+ this.trackedKeys.clear();
1915
+ ProductShowTracker.instance = null;
1916
+ };
1917
+ return ProductShowTracker;
1918
+ }());
1919
+ ProductShowTracker.instance = null;
1920
+
1921
+ var PRODUCT_SHOW_ANALYTICS_PATH_SUFFIX = '/shopping';
1922
+ var PRODUCT_SHOW_VISIBILITY_THRESHOLD = 0.8;
1923
+ var PRODUCT_SHOW_DEBOUNCE_MS = 1000;
1924
+ var SKIP_PRODUCT_SHOW_STATUSES = ['unavailable', 'out_of_stock', 'ignored', 'deleted', 'often_deleted'];
1925
+ function buildProductShowProps(product, recipeId) {
1926
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
1927
+ var basketEntry = product === null || product === void 0 ? void 0 : product.basketEntry;
1928
+ var selectedItem = basketEntry === null || basketEntry === void 0 ? void 0 : basketEntry.selectedItem;
1929
+ var item = (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id) != null ? selectedItem : product === null || product === void 0 ? void 0 : product.item;
1930
+ if ((item === null || item === void 0 ? void 0 : item.id) == null) {
1931
+ return null;
1932
+ }
1933
+ var itemAttributes = item.attributes || {};
1934
+ var entryName = (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id) != null
1935
+ ? ((_c = (_a = basketEntry.name) !== null && _a !== void 0 ? _a : (_b = basketEntry.attributes) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : '')
1936
+ : ((_h = (_f = (_e = (_d = product.ingredient) === null || _d === void 0 ? void 0 : _d.attributes) === null || _e === void 0 ? void 0 : _e.name) !== null && _f !== void 0 ? _f : (_g = product.ingredient) === null || _g === void 0 ? void 0 : _g.name) !== null && _h !== void 0 ? _h : '');
1937
+ var productBasePrice = ((_j = product === null || product === void 0 ? void 0 : product.price) === null || _j === void 0 ? void 0 : _j.unit) != null ? String(product.price.unit) : '0.0';
1938
+ return {
1939
+ entry_name: entryName,
1940
+ item_id: String(item.id),
1941
+ ext_item_id: String((_k = itemAttributes['ext-id']) !== null && _k !== void 0 ? _k : ''),
1942
+ item_ean: String((_m = (_l = item.ean) !== null && _l !== void 0 ? _l : itemAttributes.ean) !== null && _m !== void 0 ? _m : ''),
1943
+ recipe_id: recipeId,
1944
+ product_base_price: productBasePrice,
1945
+ index: (_p = (_o = product === null || product === void 0 ? void 0 : product.ingredient) === null || _o === void 0 ? void 0 : _o.index) === null || _p === void 0 ? void 0 : _p.toString()
1946
+ };
1947
+ }
1948
+ function isProductShowEligible(status) {
1949
+ return !!status && !SKIP_PRODUCT_SHOW_STATUSES.includes(status);
1950
+ }
1951
+ function getProductShowStatus(product) {
1952
+ var _a, _b;
1953
+ return (_b = (_a = product.basketEntry) === null || _a === void 0 ? void 0 : _a.status) !== null && _b !== void 0 ? _b : product.status;
1954
+ }
1955
+ function attachProductShowTracking(options) {
1956
+ var element = options.element, product = options.product, recipeId = options.recipeId, _q = options.analyticsPath, analyticsPath = _q === void 0 ? "/recipes/" + recipeId + PRODUCT_SHOW_ANALYTICS_PATH_SUFFIX : _q;
1957
+ ProductShowTracker.getInstance();
1958
+ var listener = new ViewportListener(element, function () {
1959
+ if (!isProductShowEligible(getProductShowStatus(product))) {
1960
+ return;
1961
+ }
1962
+ var props = buildProductShowProps(product, recipeId);
1963
+ if (!props) {
1964
+ return;
1965
+ }
1966
+ ProductShowTracker.getInstance().trackProductShow(analyticsPath, props);
1967
+ }, {
1968
+ threshold: PRODUCT_SHOW_VISIBILITY_THRESHOLD,
1969
+ debounce: PRODUCT_SHOW_DEBOUNCE_MS
1970
+ });
1971
+ return {
1972
+ disconnect: function () { return listener.disconnect(); }
1973
+ };
1974
+ }
1975
+
1846
1976
  var Ingredient = /** @class */ (function (_super) {
1847
1977
  __extends(Ingredient, _super);
1848
1978
  function Ingredient() {
@@ -3646,7 +3776,7 @@
3646
3776
  EventJourney["EMPTY"] = "";
3647
3777
  })(EventJourney || (EventJourney = {}));
3648
3778
 
3649
- var VERSION = "10.7.1"; // TODO: replace by ##VERSION## and update it in the CI/CD
3779
+ var VERSION = "10.9.0"; // TODO: replace by ##VERSION## and update it in the CI/CD
3650
3780
 
3651
3781
  var ContextRegistryService = /** @class */ (function () {
3652
3782
  function ContextRegistryService() {
@@ -3655,6 +3785,7 @@
3655
3785
  this.guestsChanged = new i0.EventEmitter();
3656
3786
  this.recipePriceChanged = new i0.EventEmitter();
3657
3787
  this.addAllProductsWasClicked = new i0.EventEmitter();
3788
+ this.drawerErrorToast = new i0.EventEmitter();
3658
3789
  // CALLBACKS
3659
3790
  this.hookCallback = function (isLogged, isPosValid) {
3660
3791
  mealzWarn('[Mealz] hookCallback (used to force user login) not set');
@@ -3794,7 +3925,7 @@
3794
3925
  var detectedJourney = journey !== null && journey !== void 0 ? journey : detectJourney();
3795
3926
  var isBulk = actions.length > 1;
3796
3927
  actions.forEach(function (action) {
3797
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
3928
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
3798
3929
  try {
3799
3930
  var params = action.params;
3800
3931
  // Determine add_source: replacement if previousItem exists, otherwise unit or bulk based on actions count
@@ -3827,8 +3958,10 @@
3827
3958
  ext_item_id: (_j = item.attributes) === null || _j === void 0 ? void 0 : _j['ext-id'],
3828
3959
  item_ean: item.ean,
3829
3960
  product_quantity: quantity.toString(),
3961
+ product_base_price: ((_k = basketEntry === null || basketEntry === void 0 ? void 0 : basketEntry.price) !== null && _k !== void 0 ? _k : 0).toString(),
3830
3962
  recipe_id: recipeId,
3831
- add_source: addSource
3963
+ add_source: addSource,
3964
+ index: (_m = (_l = params.eventTrace) === null || _l === void 0 ? void 0 : _l.props) === null || _m === void 0 ? void 0 : _m.index
3832
3965
  }, detectedJourney);
3833
3966
  }
3834
3967
  catch (error) {
@@ -3840,13 +3973,16 @@
3840
3973
  var _this = this;
3841
3974
  var detectedJourney = journey !== null && journey !== void 0 ? journey : detectJourney();
3842
3975
  actions.forEach(function (action) {
3976
+ var _a;
3843
3977
  _this.sendEvent('entry.deleted', action.params.eventTrace.originPath, {
3844
3978
  entry_name: action.params.basketEntry.name,
3845
3979
  item_id: action.params.basketEntry.selectedItem.id,
3846
3980
  ext_item_id: action.params.basketEntry.selectedItem.attributes['ext-id'],
3847
3981
  item_ean: action.params.basketEntry.selectedItem.ean,
3848
3982
  product_quantity: action.params.basketEntry.quantity.toString(),
3849
- recipe_id: action.params.recipeId
3983
+ product_base_price: ((_a = action.params.basketEntry.price) !== null && _a !== void 0 ? _a : 0).toString(),
3984
+ recipe_id: action.params.recipeId,
3985
+ index: action.params.eventTrace.props.index
3850
3986
  }, detectedJourney);
3851
3987
  });
3852
3988
  };
@@ -5902,6 +6038,9 @@
5902
6038
  RecipesService.prototype.openRecipeDetails = function (recipeId, guests, initialTabIndex, path, categoryId) {
5903
6039
  if (path === void 0) { path = ''; }
5904
6040
  if (categoryId === void 0) { categoryId = null; }
6041
+ if (recipeId) {
6042
+ ProductShowTracker.getInstance().clearForRecipe(String(recipeId));
6043
+ }
5905
6044
  this.display(recipeId, { previewAllowed: true, previewMode: false, guests: guests });
5906
6045
  this.recipeDetailsTabIndex$.next(initialTabIndex);
5907
6046
  this.analyticsService.sendEvent('recipe.display', path, { recipe_id: recipeId, category_id: categoryId });
@@ -9269,6 +9408,7 @@
9269
9408
  var StoreOutOfStockService = /** @class */ (function () {
9270
9409
  function StoreOutOfStockService() {
9271
9410
  this.outOfStockEntries = [];
9411
+ this.outOfStockPersisted$ = new rxjs.Subject();
9272
9412
  this.fetchCurrentOutOfStocks();
9273
9413
  }
9274
9414
  StoreOutOfStockService.prototype.fetchCurrentOutOfStocks = function () {
@@ -9287,13 +9427,17 @@
9287
9427
  var _a;
9288
9428
  if (entry.status === 'active') {
9289
9429
  this.removeEntryFromStorage(entry);
9290
- return;
9430
+ return false;
9291
9431
  }
9292
9432
  if ((_a = entry === null || entry === void 0 ? void 0 : entry.selectedItem) === null || _a === void 0 ? void 0 : _a.id) {
9293
- return this.outOfStockEntries.includes(entry.selectedItem.id.toString());
9433
+ return this.isItemOutOfStock(entry.selectedItem.id);
9294
9434
  }
9295
9435
  return false;
9296
9436
  };
9437
+ StoreOutOfStockService.prototype.isItemOutOfStock = function (itemId) {
9438
+ this.fetchCurrentOutOfStocks();
9439
+ return this.outOfStockEntries.includes(itemId);
9440
+ };
9297
9441
  StoreOutOfStockService.prototype.removeEntryFromStorage = function (entry) {
9298
9442
  var _a;
9299
9443
  if ((_a = entry === null || entry === void 0 ? void 0 : entry.selectedItem) === null || _a === void 0 ? void 0 : _a.id) {
@@ -9301,12 +9445,25 @@
9301
9445
  sessionStorage.setItem('_miam/outOfStockEntry', JSON.stringify(this.outOfStockEntries));
9302
9446
  }
9303
9447
  };
9448
+ /**
9449
+ * Marks an entry as out of stock in session storage.
9450
+ */
9451
+ StoreOutOfStockService.prototype.persistOutOfStock = function (entry) {
9452
+ var _a;
9453
+ if (!((_a = entry.selectedItem) === null || _a === void 0 ? void 0 : _a.id)) {
9454
+ return;
9455
+ }
9456
+ entry.status = 'out_of_stock';
9457
+ this.addEntryToStorage(entry);
9458
+ this.outOfStockPersisted$.next(entry);
9459
+ };
9304
9460
  StoreOutOfStockService.prototype.addEntryToStorage = function (entry) {
9305
9461
  var _a;
9306
9462
  if ((_a = entry.selectedItem) === null || _a === void 0 ? void 0 : _a.id) {
9307
9463
  this.fetchCurrentOutOfStocks();
9308
- if (!this.outOfStockEntries.includes(entry.selectedItem.id)) {
9309
- this.outOfStockEntries.push(entry.selectedItem.id);
9464
+ var itemId = entry.selectedItem.id.toString();
9465
+ if (!this.outOfStockEntries.includes(itemId)) {
9466
+ this.outOfStockEntries.push(itemId);
9310
9467
  }
9311
9468
  sessionStorage.setItem('_miam/outOfStockEntry', JSON.stringify(this.outOfStockEntries));
9312
9469
  }
@@ -9651,11 +9808,17 @@
9651
9808
  productsToAdd_1.push(re);
9652
9809
  }
9653
9810
  }); });
9654
- var addRecipes = productsToAdd_1.map(function (re) { return new AddRecipeAction(re.entry, {
9655
- recipeId: _this.recipe.id,
9656
- ingredientId: re.ingredientId,
9657
- eventTrace: eventTrace,
9658
- }, _this.basketsService); });
9811
+ var addRecipes = productsToAdd_1.map(function (re) {
9812
+ var _a;
9813
+ return new AddRecipeAction(re.entry, {
9814
+ recipeId: _this.recipe.id,
9815
+ ingredientId: re.ingredientId,
9816
+ eventTrace: {
9817
+ originPath: eventTrace.originPath,
9818
+ props: Object.assign(Object.assign({}, eventTrace.props), { index: (_a = re.index) === null || _a === void 0 ? void 0 : _a.toString() })
9819
+ },
9820
+ }, _this.basketsService);
9821
+ });
9659
9822
  _this.basketSynchroService.addToActionList(addRecipes);
9660
9823
  var onTimeouts = addRecipes.map(function (action) { return action.onTimeout; });
9661
9824
  var onErrors = addRecipes.map(function (action) { return action.onError; });
@@ -9768,9 +9931,14 @@
9768
9931
  RecipeDetailsService.prototype.remainingProducts = function () {
9769
9932
  var _this = this;
9770
9933
  return this.remainingBasketEntries.reduce(function (result, be) {
9934
+ var _a;
9771
9935
  var p = _this.products.find(function (product) { return product.basketEntry.name === be.name; });
9772
9936
  if (p) {
9773
- result.push({ ingredientId: p.ingredient.id, entry: p.basketEntry });
9937
+ result.push({
9938
+ ingredientId: p.ingredient.id,
9939
+ entry: p.basketEntry,
9940
+ index: (_a = p.ingredient) === null || _a === void 0 ? void 0 : _a.index
9941
+ });
9774
9942
  }
9775
9943
  return result;
9776
9944
  }, []);
@@ -9834,6 +10002,7 @@
9834
10002
  }
9835
10003
  };
9836
10004
  RecipeDetailsService.prototype.categorizeProducts = function () {
10005
+ var e_1, _c, e_2, _d;
9837
10006
  var _this = this;
9838
10007
  // Iterate over each product in the entriesWithIngredients array
9839
10008
  this.products.forEach(function (product) {
@@ -9856,6 +10025,37 @@
9856
10025
  _this.updateRecipePrice(product);
9857
10026
  }
9858
10027
  });
10028
+ var displayIndex = 0;
10029
+ try {
10030
+ for (var _e = __values(this.productsByCategory.toPickProducts), _f = _e.next(); !_f.done; _f = _e.next()) {
10031
+ var product = _f.value;
10032
+ if (product.ingredient) {
10033
+ product.ingredient.index = displayIndex++;
10034
+ }
10035
+ }
10036
+ }
10037
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
10038
+ finally {
10039
+ try {
10040
+ if (_f && !_f.done && (_c = _e.return)) _c.call(_e);
10041
+ }
10042
+ finally { if (e_1) throw e_1.error; }
10043
+ }
10044
+ try {
10045
+ for (var _g = __values(this.productsByCategory.oftenIgnoredProducts), _h = _g.next(); !_h.done; _h = _g.next()) {
10046
+ var product = _h.value;
10047
+ if (product.ingredient) {
10048
+ product.ingredient.index = displayIndex++;
10049
+ }
10050
+ }
10051
+ }
10052
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
10053
+ finally {
10054
+ try {
10055
+ if (_h && !_h.done && (_d = _g.return)) _d.call(_g);
10056
+ }
10057
+ finally { if (e_2) throw e_2.error; }
10058
+ }
9859
10059
  this.sendEmitToUpdateRecipePrice();
9860
10060
  this.updateIngredientFromBasketLoading = false;
9861
10061
  this.ingredientToBasketLoading = false;
@@ -9876,9 +10076,8 @@
9876
10076
  RecipeDetailsService.prototype.setProductOutOfStockInSession = function (products) {
9877
10077
  var _this = this;
9878
10078
  products.forEach(function (_c) {
9879
- var entry = _c.entry;
9880
- entry.status = 'out_of_stock';
9881
- _this.storeOutOfStockService.addEntryToStorage(entry);
10079
+ var ingredientId = _c.ingredientId, entry = _c.entry;
10080
+ _this.storeOutOfStockService.persistOutOfStock(entry);
9882
10081
  });
9883
10082
  };
9884
10083
  return RecipeDetailsService;
@@ -9940,7 +10139,9 @@
9940
10139
  }
9941
10140
  this.basketEntry.addRelationship(this.updateMealzParams.item, 'selected-item');
9942
10141
  this.basketEntriesService.selectItem(this.basketEntry.id, this.updateMealzParams.item.id, this.quantity)
9943
- .pipe(operators.switchMap(function () { return _this.basketsService.refreshCurrentBasket(); }), operators.take(1)).subscribe();
10142
+ .pipe(operators.switchMap(function () { return _this.basketsService.refreshCurrentBasket(); }), operators.take(1)).subscribe({
10143
+ error: function () { return _this.onError.next(); }
10144
+ });
9944
10145
  };
9945
10146
  AddIngredientFromReplaceAction.prototype.createActionForRetailer = function () {
9946
10147
  var _this = this;
@@ -9988,8 +10189,16 @@
9988
10189
  return AddIngredientAction;
9989
10190
  }(BasketAction));
9990
10191
 
10192
+ var UNAVAILABLE_PRODUCT_ADD_ERROR_CODE = 'unavailableProductAdd';
10193
+ var UNAVAILABLE_PRODUCTS_ADD_ERROR_CODE = 'unavailableProductsAdd';
10194
+ function unavailableProductAddErrorCode(failureCount) {
10195
+ return failureCount <= 1
10196
+ ? UNAVAILABLE_PRODUCT_ADD_ERROR_CODE
10197
+ : UNAVAILABLE_PRODUCTS_ADD_ERROR_CODE;
10198
+ }
10199
+
9991
10200
  var ReplaceItemService = /** @class */ (function () {
9992
- function ReplaceItemService(basketsService, basketEntriesService, itemsService, recipeDetailsService, basketSynchroService, ignoredBasketsService, recipesService, analyticsService) {
10201
+ function ReplaceItemService(basketsService, basketEntriesService, itemsService, recipeDetailsService, basketSynchroService, ignoredBasketsService, recipesService, analyticsService, storeOutOfStockService, contextRegistryService) {
9993
10202
  var _this = this;
9994
10203
  this.basketsService = basketsService;
9995
10204
  this.basketEntriesService = basketEntriesService;
@@ -9999,6 +10208,8 @@
9999
10208
  this.ignoredBasketsService = ignoredBasketsService;
10000
10209
  this.recipesService = recipesService;
10001
10210
  this.analyticsService = analyticsService;
10211
+ this.storeOutOfStockService = storeOutOfStockService;
10212
+ this.contextRegistryService = contextRegistryService;
10002
10213
  this.basketEntry = new BasketEntry();
10003
10214
  this.itemsWithPricesList$ = new rxjs.BehaviorSubject([]);
10004
10215
  this.fetchingItemLoading$ = new rxjs.BehaviorSubject(false);
@@ -10032,14 +10243,20 @@
10032
10243
  _this.recipe = recipeDisplay === null || recipeDisplay === void 0 ? void 0 : recipeDisplay.recipe;
10033
10244
  });
10034
10245
  this.replaceProductFromPreviewOpen$.pipe(operators.filter(function (isOpen) { return !!isOpen; }), operators.switchMap(function () { return _this.fetchItems(); })).subscribe();
10246
+ this.storeOutOfStockService.outOfStockPersisted$.subscribe(function () {
10247
+ _this.refreshItemsOutOfStockFlags();
10248
+ });
10035
10249
  }
10036
- ReplaceItemService.prototype.handleItemSelection = function (item, searchString, onComplete, eventTrace, timeOutAction) {
10250
+ ReplaceItemService.prototype.handleItemSelection = function (item, searchString, onComplete, eventTrace) {
10037
10251
  var _this = this;
10038
10252
  var fromRecipeDetails = !!this.recipe;
10039
- this.timeOutAction = timeOutAction;
10253
+ this.onComplete = onComplete;
10040
10254
  this.onSelectItem(item, searchString, eventTrace)
10041
10255
  .pipe(operators.take(1))
10042
10256
  .subscribe(function (action) {
10257
+ if (!action) {
10258
+ return;
10259
+ }
10043
10260
  action.onSuccess.pipe(operators.take(1)).subscribe(function () {
10044
10261
  _this.recipeDetailsService.hasReplaced = true;
10045
10262
  if (eventTrace && fromRecipeDetails && !_this.addProductMode) {
@@ -10047,15 +10264,17 @@
10047
10264
  }
10048
10265
  if (_this.addProductMode || !fromRecipeDetails) {
10049
10266
  _this.basketsService.itemWillBeAdded(item.id).subscribe(function (addItem) {
10050
- if (!addItem && _this.replaceItemLoading$.value) {
10267
+ if (!addItem) {
10268
+ _this.replaceItemLoading$.next(undefined);
10051
10269
  onComplete(item.id);
10052
10270
  }
10053
10271
  });
10054
10272
  }
10055
10273
  else {
10056
10274
  _this.basketsService.ingredientWillBeAdded(_this.ingredient.id).subscribe(function (addIngredient) {
10057
- if (!addIngredient && _this.replaceItemLoading$.value) {
10058
- onComplete(_this.basketEntry.id);
10275
+ if (!addIngredient) {
10276
+ _this.replaceItemLoading$.next(undefined);
10277
+ onComplete(item.id);
10059
10278
  }
10060
10279
  });
10061
10280
  }
@@ -10097,7 +10316,8 @@
10097
10316
  var priceObservables = items.map(function (item) { return _this.itemsService.getPriceForItem(item.id).pipe(operators.map(function (price) { return ({ item: item, price: price }); })); });
10098
10317
  return (priceObservables.length === 0 ? rxjs.of([]) : rxjs.forkJoin(priceObservables)).pipe(operators.map(function (itemsWithPrices) {
10099
10318
  _this.fetchingItemLoading$.next(false);
10100
- return _this.itemsWithPricesList$.next(itemsWithPrices);
10319
+ var itemsWithOutOfStockFlags = _this.withOutOfStockFlags(itemsWithPrices);
10320
+ return _this.itemsWithPricesList$.next(itemsWithOutOfStockFlags);
10101
10321
  }));
10102
10322
  }));
10103
10323
  };
@@ -10128,18 +10348,13 @@
10128
10348
  * Adds the action to the synchronization service's action list for processing.
10129
10349
  */
10130
10350
  ReplaceItemService.prototype.handleAddProductMode = function (item, eventTrace) {
10131
- var _this = this;
10132
10351
  this.replaceItemLoading$.next(item);
10133
10352
  var newBasketEntry = new BasketEntry();
10134
10353
  newBasketEntry.quantity = 1;
10135
10354
  newBasketEntry.quantityToAdd = 0;
10136
10355
  this.replaceRelationship(newBasketEntry, item);
10137
10356
  var addIngredientWithoutRecipe = new AddIngredientAction(newBasketEntry, { eventTrace: eventTrace, item: item }, this.basketsService, this.basketEntriesService);
10138
- rxjs.merge(addIngredientWithoutRecipe.onTimeout, addIngredientWithoutRecipe.onError)
10139
- .pipe(operators.take(1))
10140
- .subscribe(function () {
10141
- _this.rollbackReplace();
10142
- });
10357
+ this.listenToAddActionFailure(addIngredientWithoutRecipe, item, newBasketEntry);
10143
10358
  return rxjs.of(addIngredientWithoutRecipe);
10144
10359
  };
10145
10360
  /**
@@ -10164,43 +10379,55 @@
10164
10379
  var priceObservables = items.map(function (item) { return _this.itemsService.getPriceForItem(item.id).pipe(operators.map(function (price) { return ({ item: item, price: price }); })); });
10165
10380
  return (priceObservables.length === 0 ? rxjs.of([]) : rxjs.forkJoin(priceObservables));
10166
10381
  }), operators.map(function (itemsWithPrices) {
10167
- _this.itemsWithPricesList$.next(_this.moveSelectedItemToFront(itemsWithPrices));
10382
+ var sortedItems = _this.withOutOfStockFlags(_this.moveSelectedItemToFront(itemsWithPrices));
10383
+ _this.itemsWithPricesList$.next(sortedItems);
10168
10384
  _this.fetchingItemLoading$.next(false);
10169
- return itemsWithPrices;
10385
+ return sortedItems;
10170
10386
  }));
10171
10387
  };
10172
10388
  /**
10173
- * Replace the current basket entry with the given item
10389
+ * Replace the current basket entry with the given item.
10390
+ * Removes the previous item from the retailer cart first; the add action is only enqueued after remove succeeds.
10174
10391
  */
10175
10392
  ReplaceItemService.prototype.selectItem = function (item) {
10176
10393
  var _this = this;
10177
- var _a, _b;
10394
+ var _a;
10178
10395
  var deletedBasketEntry = deepCloneWithClass(this.basketEntry);
10179
10396
  deletedBasketEntry.quantity = 0;
10180
10397
  deletedBasketEntry.selectedItem.extId = this.previousItem.extId;
10181
- var removeIngredient = new RemoveIngredientFromReplaceAction(deletedBasketEntry, {}, this.basketsService);
10182
- rxjs.merge(removeIngredient.onTimeout, removeIngredient.onError).pipe(operators.take(1)).subscribe(function () {
10183
- _this.rollbackReplace();
10184
- });
10185
- this.basketSynchroService.addToActionList([removeIngredient]);
10186
- var guests = +((_a = this.recipe) === null || _a === void 0 ? void 0 : _a.modifiedGuests) || +((_b = this.recipe) === null || _b === void 0 ? void 0 : _b.guests) || 4;
10187
- return (this.ingredient && this.recipe ?
10188
- this.basketsService.basketEntryFromIngredient(this.ingredient.id, guests, true, item.id) :
10189
- rxjs.of(this.basketEntry)).pipe(operators.switchMap(function (newEntry) {
10190
- var newBasketEntry = deepCloneWithClass(_this.basketEntry);
10191
- newBasketEntry.quantityToAdd = newEntry.quantityToAdd;
10192
- _this.replaceRelationship(newBasketEntry, item);
10193
- var addIngredientFromReplace = new AddIngredientFromReplaceAction(newBasketEntry, {
10194
- item: item
10195
- }, _this.basketsService, _this.basketEntriesService);
10196
- rxjs.merge(addIngredientFromReplace.onTimeout, addIngredientFromReplace.onError).pipe(operators.take(1)).subscribe(function () {
10197
- _this.rollbackReplace();
10398
+ var removeIngredient = new RemoveIngredientFromReplaceAction(deletedBasketEntry, { ingredientId: (_a = this.ingredient) === null || _a === void 0 ? void 0 : _a.id }, this.basketsService);
10399
+ return new rxjs.Observable(function (observer) {
10400
+ rxjs.merge(removeIngredient.onError, removeIngredient.onTimeout).pipe(operators.take(1)).subscribe(function () {
10401
+ _this.clearReplaceLoadingState();
10402
+ observer.complete();
10198
10403
  });
10199
- addIngredientFromReplace.onSuccess.pipe(operators.take(1)).subscribe(function () {
10200
- _this.recipeDetailsService.updateIngredientFromBasketLoading = false;
10404
+ removeIngredient.onSuccess.pipe(operators.take(1), operators.switchMap(function () { return _this.createAddIngredientFromReplaceAction(item); })).subscribe({
10405
+ next: function (addIngredientFromReplace) {
10406
+ _this.listenToAddActionFailure(addIngredientFromReplace, item);
10407
+ addIngredientFromReplace.onSuccess.pipe(operators.take(1)).subscribe(function () {
10408
+ _this.recipeDetailsService.updateIngredientFromBasketLoading = false;
10409
+ });
10410
+ observer.next(addIngredientFromReplace);
10411
+ observer.complete();
10412
+ },
10413
+ error: function () {
10414
+ _this.confirmMealzRemoveAfterReplaceAddFailure();
10415
+ _this.clearReplaceLoadingState();
10416
+ observer.complete();
10417
+ }
10201
10418
  });
10202
- return rxjs.of(addIngredientFromReplace);
10203
- }));
10419
+ _this.basketSynchroService.addToActionList([removeIngredient]);
10420
+ });
10421
+ };
10422
+ ReplaceItemService.prototype.withOutOfStockFlags = function (items) {
10423
+ var _this = this;
10424
+ return items.map(function (itemWithPrice) { return (Object.assign(Object.assign({}, itemWithPrice), { isOutOfStock: _this.storeOutOfStockService.isItemOutOfStock(itemWithPrice.item.id) })); });
10425
+ };
10426
+ ReplaceItemService.prototype.refreshItemsOutOfStockFlags = function () {
10427
+ if (this.itemsWithPricesList$.value.length === 0) {
10428
+ return;
10429
+ }
10430
+ this.itemsWithPricesList$.next(this.withOutOfStockFlags(this.itemsWithPricesList$.value));
10204
10431
  };
10205
10432
  ReplaceItemService.prototype.changeReplaceModalState = function (state, basketEntryToReplace) {
10206
10433
  if (basketEntryToReplace) {
@@ -10226,18 +10453,62 @@
10226
10453
  }
10227
10454
  basketEntry.addRelationship(item, 'selected-item');
10228
10455
  };
10456
+ ReplaceItemService.prototype.createAddIngredientFromReplaceAction = function (item) {
10457
+ var _this = this;
10458
+ var _a, _b;
10459
+ var guests = +((_a = this.recipe) === null || _a === void 0 ? void 0 : _a.modifiedGuests) || +((_b = this.recipe) === null || _b === void 0 ? void 0 : _b.guests) || 4;
10460
+ var newEntry$ = this.ingredient && this.recipe ?
10461
+ this.basketsService.basketEntryFromIngredient(this.ingredient.id, guests, true, item.id) :
10462
+ rxjs.of(this.basketEntry);
10463
+ return newEntry$.pipe(operators.map(function (newEntry) {
10464
+ var newBasketEntry = deepCloneWithClass(_this.basketEntry);
10465
+ newBasketEntry.quantityToAdd = newEntry.quantityToAdd;
10466
+ _this.replaceRelationship(newBasketEntry, item);
10467
+ return new AddIngredientFromReplaceAction(newBasketEntry, { item: item }, _this.basketsService, _this.basketEntriesService);
10468
+ }));
10469
+ };
10470
+ ReplaceItemService.prototype.listenToAddActionFailure = function (addAction, attemptedItem, basketEntry) {
10471
+ var _this = this;
10472
+ if (basketEntry === void 0) { basketEntry = this.basketEntry; }
10473
+ var isReplaceAdd = addAction instanceof AddIngredientFromReplaceAction;
10474
+ addAction.onTimeout.pipe(operators.take(1)).subscribe(function () {
10475
+ _this.handleAddTimeout(attemptedItem, basketEntry, isReplaceAdd);
10476
+ });
10477
+ addAction.onError.pipe(operators.take(1)).subscribe(function () {
10478
+ _this.clearReplaceLoadingState();
10479
+ });
10480
+ };
10229
10481
  /**
10230
- * Rolls back the replacement process by resetting loading states and
10231
- * restoring the previous selected item in the basket entry.
10482
+ * After a failed replace-add, the retailer already removed the old product but Mealz was never updated
10483
+ * (remove-from-replace is retailer-only). reloadBasket would re-fetch Mealz and still show the old product
10484
+ * as active. syncMealzBasketWithRetailerCart is too broad and risky while other actions may be pending.
10485
+ * A targeted remove-recipe aligns Mealz with the retailer for this ingredient only.
10232
10486
  */
10233
- ReplaceItemService.prototype.rollbackReplace = function () {
10487
+ ReplaceItemService.prototype.confirmMealzRemoveAfterReplaceAddFailure = function () {
10488
+ var _a;
10489
+ if (!((_a = this.ingredient) === null || _a === void 0 ? void 0 : _a.id)) {
10490
+ return;
10491
+ }
10492
+ var basketEntryToRemove = deepCloneWithClass(this.basketEntry);
10493
+ this.basketsService.removeIngredientFromRecipe(basketEntryToRemove, this.ingredient.id, 0).pipe(operators.take(1)).subscribe();
10494
+ };
10495
+ ReplaceItemService.prototype.handleAddTimeout = function (attemptedItem, basketEntry, isReplaceAdd) {
10496
+ if (basketEntry === void 0) { basketEntry = this.basketEntry; }
10497
+ if (isReplaceAdd === void 0) { isReplaceAdd = false; }
10498
+ if (isReplaceAdd) {
10499
+ this.confirmMealzRemoveAfterReplaceAddFailure();
10500
+ }
10501
+ this.clearReplaceLoadingState();
10502
+ this.replaceRelationship(basketEntry, attemptedItem);
10503
+ this.storeOutOfStockService.persistOutOfStock(basketEntry);
10504
+ this.contextRegistryService.drawerErrorToast.emit({
10505
+ code: UNAVAILABLE_PRODUCT_ADD_ERROR_CODE
10506
+ });
10507
+ };
10508
+ ReplaceItemService.prototype.clearReplaceLoadingState = function () {
10234
10509
  this.recipeDetailsService.ingredientToBasketLoading = false;
10235
10510
  this.recipeDetailsService.updateIngredientFromBasketLoading = false;
10236
10511
  this.replaceItemLoading$.next(undefined);
10237
- this.basketEntry.relationships['selected-item'].data = this.previousItem;
10238
- if (this.timeOutAction) {
10239
- this.timeOutAction();
10240
- }
10241
10512
  };
10242
10513
  /**
10243
10514
  * Creates a ParsedMethod for adding an ingredient to a basket.
@@ -10259,7 +10530,7 @@
10259
10530
  * Updates loading states, creates an AddIngredientAction for the new basket entry,
10260
10531
  * and adds it to the synchronization service's action list.
10261
10532
  */
10262
- ReplaceItemService.prototype.handleAddToBasketResponse = function (newEntry, searchString, eventTrace) {
10533
+ ReplaceItemService.prototype.handleAddToBasketResponse = function (newEntry, searchString, eventTrace, attemptedItem) {
10263
10534
  this.updateLoadingStates();
10264
10535
  var newBasketEntry = deepCloneWithClass(this.basketEntry);
10265
10536
  newBasketEntry.quantityToAdd = newEntry.quantityToAdd;
@@ -10270,19 +10541,11 @@
10270
10541
  previousItem: this.previousItem,
10271
10542
  searchString: searchString
10272
10543
  }, this.basketsService);
10273
- this.handleAddIngredientActionErrors(addIngredient);
10274
- // No need to send entry.added event, because it is done in the action
10544
+ this.handleAddIngredientActionErrors(addIngredient, attemptedItem);
10275
10545
  return rxjs.of(addIngredient);
10276
10546
  };
10277
- /**
10278
- * Listens for errors or timeouts in the given AddIngredientAction and
10279
- * calls rollbackReplace() when one is encountered.
10280
- */
10281
- ReplaceItemService.prototype.handleAddIngredientActionErrors = function (addIngredient) {
10282
- var _this = this;
10283
- rxjs.merge(addIngredient.onError, addIngredient.onTimeout).pipe(operators.take(1)).subscribe(function () {
10284
- _this.rollbackReplace();
10285
- });
10547
+ ReplaceItemService.prototype.handleAddIngredientActionErrors = function (addIngredient, attemptedItem) {
10548
+ this.listenToAddActionFailure(addIngredient, attemptedItem);
10286
10549
  };
10287
10550
  /**
10288
10551
  * Updates the loading states for ingredient and basket operations.
@@ -10327,7 +10590,7 @@
10327
10590
  */
10328
10591
  ReplaceItemService.prototype.addToBasket = function (item, searchString, eventTrace) {
10329
10592
  var _this = this;
10330
- return this.recipeDetailsService.canAddProductToBasket(this.getAddIngredientMethod(eventTrace, searchString), eventTrace, this.recipe).pipe(operators.filter(function (passed) { return passed; }), operators.switchMap(function () { return _this.basketsService.basketEntryFromIngredient(_this.ingredient.id, +_this.recipe.modifiedGuests, true, item.id); }), operators.switchMap(function (newEntry) { return _this.handleAddToBasketResponse(newEntry, searchString, eventTrace); }));
10593
+ return this.recipeDetailsService.canAddProductToBasket(this.getAddIngredientMethod(eventTrace, searchString), eventTrace, this.recipe).pipe(operators.filter(function (passed) { return passed; }), operators.switchMap(function () { return _this.basketsService.basketEntryFromIngredient(_this.ingredient.id, +_this.recipe.modifiedGuests, true, item.id); }), operators.switchMap(function (newEntry) { return _this.handleAddToBasketResponse(newEntry, searchString, eventTrace, item); }));
10331
10594
  };
10332
10595
  /**
10333
10596
  * Replaces the item in the given basket entry with the given item
@@ -10366,7 +10629,7 @@
10366
10629
  };
10367
10630
  return ReplaceItemService;
10368
10631
  }());
10369
- ReplaceItemService.ɵfac = function ReplaceItemService_Factory(t) { return new (t || ReplaceItemService)(i0__namespace.ɵɵinject(BasketsService), i0__namespace.ɵɵinject(BasketEntriesService), i0__namespace.ɵɵinject(ItemsService), i0__namespace.ɵɵinject(RecipeDetailsService), i0__namespace.ɵɵinject(BasketsSynchronizerService), i0__namespace.ɵɵinject(IgnoredIngredientsService), i0__namespace.ɵɵinject(RecipesService), i0__namespace.ɵɵinject(AnalyticsService)); };
10632
+ ReplaceItemService.ɵfac = function ReplaceItemService_Factory(t) { return new (t || ReplaceItemService)(i0__namespace.ɵɵinject(BasketsService), i0__namespace.ɵɵinject(BasketEntriesService), i0__namespace.ɵɵinject(ItemsService), i0__namespace.ɵɵinject(RecipeDetailsService), i0__namespace.ɵɵinject(BasketsSynchronizerService), i0__namespace.ɵɵinject(IgnoredIngredientsService), i0__namespace.ɵɵinject(RecipesService), i0__namespace.ɵɵinject(AnalyticsService), i0__namespace.ɵɵinject(StoreOutOfStockService), i0__namespace.ɵɵinject(ContextRegistryService)); };
10370
10633
  ReplaceItemService.ɵprov = i0__namespace.ɵɵdefineInjectable({ token: ReplaceItemService, factory: ReplaceItemService.ɵfac, providedIn: 'root' });
10371
10634
  (function () {
10372
10635
  (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(ReplaceItemService, [{
@@ -10374,17 +10637,19 @@
10374
10637
  args: [{
10375
10638
  providedIn: 'root'
10376
10639
  }]
10377
- }], function () { return [{ type: BasketsService }, { type: BasketEntriesService }, { type: ItemsService }, { type: RecipeDetailsService }, { type: BasketsSynchronizerService }, { type: IgnoredIngredientsService }, { type: RecipesService }, { type: AnalyticsService }]; }, null);
10640
+ }], function () { return [{ type: BasketsService }, { type: BasketEntriesService }, { type: ItemsService }, { type: RecipeDetailsService }, { type: BasketsSynchronizerService }, { type: IgnoredIngredientsService }, { type: RecipesService }, { type: AnalyticsService }, { type: StoreOutOfStockService }, { type: ContextRegistryService }]; }, null);
10378
10641
  })();
10379
10642
 
10380
10643
  var RecipeDetailsProductsService = /** @class */ (function () {
10381
- function RecipeDetailsProductsService(basketsService, priceService, ignoredBasketsService, replaceItemService, contextRegistryService, basketSynchroService) {
10644
+ function RecipeDetailsProductsService(basketsService, priceService, ignoredBasketsService, replaceItemService, contextRegistryService, basketSynchroService, storeOutOfStockService) {
10645
+ var _this = this;
10382
10646
  this.basketsService = basketsService;
10383
10647
  this.priceService = priceService;
10384
10648
  this.ignoredBasketsService = ignoredBasketsService;
10385
10649
  this.replaceItemService = replaceItemService;
10386
10650
  this.contextRegistryService = contextRegistryService;
10387
10651
  this.basketSynchroService = basketSynchroService;
10652
+ this.storeOutOfStockService = storeOutOfStockService;
10388
10653
  this.productsByCategory = {
10389
10654
  toPickProducts: [],
10390
10655
  oftenIgnoredProducts: []
@@ -10395,6 +10660,10 @@
10395
10660
  this.productsLoading$ = new rxjs.BehaviorSubject(false);
10396
10661
  this.ingredientToBasketLoading$ = new rxjs.BehaviorSubject(false);
10397
10662
  this.updateIngredientFromBasketLoading$ = new rxjs.BehaviorSubject(false);
10663
+ this.storeOutOfStockService.outOfStockPersisted$.subscribe(function () {
10664
+ _this.products$.value.forEach(function (product) { return _this.applyOutOfStockFromStorage(product); });
10665
+ _this.emitProductsUpdate();
10666
+ });
10398
10667
  }
10399
10668
  RecipeDetailsProductsService.prototype.initDefaultState = function () {
10400
10669
  this.resetProductsByCategory();
@@ -10439,6 +10708,7 @@
10439
10708
  return this.basketSynchroService.entryWillBeAdded((_a = basketEntry.selectedItem) === null || _a === void 0 ? void 0 : _a.extId);
10440
10709
  };
10441
10710
  RecipeDetailsProductsService.prototype.setProductsByCategory = function (products) {
10711
+ var e_1, _b, e_2, _c;
10442
10712
  var _this = this;
10443
10713
  this.resetProductsByCategory();
10444
10714
  // Iterate over each product in the entriesWithIngredients array
@@ -10446,6 +10716,7 @@
10446
10716
  var basketEntry = product.basketEntry;
10447
10717
  var status = basketEntry.status;
10448
10718
  _this.updateIngredientIgnoredStatus(product);
10719
+ _this.applyOutOfStockFromStorage(product);
10449
10720
  _this.updateProductAvailabilityStatus(product);
10450
10721
  _this.computeProductPriceDetails(product, _this.priceService.getPriceFromBasketEntry(basketEntry));
10451
10722
  // Check if the product is often ignored based on basketEntryStatus
@@ -10458,6 +10729,37 @@
10458
10729
  _this.updateRecipePrice(product);
10459
10730
  }
10460
10731
  });
10732
+ var displayIndex = 0;
10733
+ try {
10734
+ for (var _d = __values(this.productsByCategory.toPickProducts), _e = _d.next(); !_e.done; _e = _d.next()) {
10735
+ var product = _e.value;
10736
+ if (product.ingredient) {
10737
+ product.ingredient.index = displayIndex++;
10738
+ }
10739
+ }
10740
+ }
10741
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
10742
+ finally {
10743
+ try {
10744
+ if (_e && !_e.done && (_b = _d.return)) _b.call(_d);
10745
+ }
10746
+ finally { if (e_1) throw e_1.error; }
10747
+ }
10748
+ try {
10749
+ for (var _f = __values(this.productsByCategory.oftenIgnoredProducts), _g = _f.next(); !_g.done; _g = _f.next()) {
10750
+ var product = _g.value;
10751
+ if (product.ingredient) {
10752
+ product.ingredient.index = displayIndex++;
10753
+ }
10754
+ }
10755
+ }
10756
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
10757
+ finally {
10758
+ try {
10759
+ if (_g && !_g.done && (_c = _f.return)) _c.call(_f);
10760
+ }
10761
+ finally { if (e_2) throw e_2.error; }
10762
+ }
10461
10763
  this.sendEmitToUpdateRecipePrice();
10462
10764
  this.products$.next(products);
10463
10765
  this.updateIngredientFromBasketLoading$.next(false);
@@ -10490,6 +10792,7 @@
10490
10792
  if (currentProduct) {
10491
10793
  currentProduct.basketEntry.quantity = product.basketEntry.quantity;
10492
10794
  currentProduct.basketEntry.quantityToAdd = product.basketEntry.quantityToAdd;
10795
+ _this.applyOutOfStockFromStorage(currentProduct);
10493
10796
  if (currentProduct.price) {
10494
10797
  _this.computeProductPriceDetails(currentProduct, currentProduct.price);
10495
10798
  }
@@ -10510,6 +10813,17 @@
10510
10813
  }
10511
10814
  });
10512
10815
  };
10816
+ RecipeDetailsProductsService.prototype.emitProductsUpdate = function () {
10817
+ this.products$.next(__spread(this.products$.value));
10818
+ this.productsByCategory$.next(this.productsByCategory);
10819
+ this.ingredientToBasketLoading$.next(false);
10820
+ this.updateIngredientFromBasketLoading$.next(false);
10821
+ };
10822
+ RecipeDetailsProductsService.prototype.applyOutOfStockFromStorage = function (product) {
10823
+ if (this.storeOutOfStockService.isOutOfStockFromStorage(product.basketEntry)) {
10824
+ product.basketEntry.status = 'out_of_stock';
10825
+ }
10826
+ };
10513
10827
  RecipeDetailsProductsService.prototype.updateIngredientIgnoredStatus = function (product) {
10514
10828
  if (this.ignoredBasketsService.isIngredientIgnored(product.ingredient.id)) {
10515
10829
  product.basketEntry.status = 'ignored';
@@ -10518,7 +10832,7 @@
10518
10832
  RecipeDetailsProductsService.prototype.updateProductAvailabilityStatus = function (product) {
10519
10833
  var basketEntry = product.basketEntry;
10520
10834
  var id = basketEntry.id, selectedItem = basketEntry.selectedItem, recipesIds = basketEntry.recipesIds, status = basketEntry.status;
10521
- if (['often_deleted', 'deleted', 'ignored'].includes(status)) {
10835
+ if (['often_deleted', 'deleted', 'ignored', 'out_of_stock'].includes(status)) {
10522
10836
  return;
10523
10837
  }
10524
10838
  if (id === '-1') {
@@ -10571,7 +10885,7 @@
10571
10885
  };
10572
10886
  return RecipeDetailsProductsService;
10573
10887
  }());
10574
- RecipeDetailsProductsService.ɵfac = function RecipeDetailsProductsService_Factory(t) { return new (t || RecipeDetailsProductsService)(i0__namespace.ɵɵinject(BasketsService), i0__namespace.ɵɵinject(PriceService), i0__namespace.ɵɵinject(IgnoredIngredientsService), i0__namespace.ɵɵinject(ReplaceItemService), i0__namespace.ɵɵinject(ContextRegistryService), i0__namespace.ɵɵinject(BasketsSynchronizerService)); };
10888
+ RecipeDetailsProductsService.ɵfac = function RecipeDetailsProductsService_Factory(t) { return new (t || RecipeDetailsProductsService)(i0__namespace.ɵɵinject(BasketsService), i0__namespace.ɵɵinject(PriceService), i0__namespace.ɵɵinject(IgnoredIngredientsService), i0__namespace.ɵɵinject(ReplaceItemService), i0__namespace.ɵɵinject(ContextRegistryService), i0__namespace.ɵɵinject(BasketsSynchronizerService), i0__namespace.ɵɵinject(StoreOutOfStockService)); };
10575
10889
  RecipeDetailsProductsService.ɵprov = i0__namespace.ɵɵdefineInjectable({ token: RecipeDetailsProductsService, factory: RecipeDetailsProductsService.ɵfac, providedIn: 'root' });
10576
10890
  (function () {
10577
10891
  (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(RecipeDetailsProductsService, [{
@@ -10579,7 +10893,7 @@
10579
10893
  args: [{
10580
10894
  providedIn: 'root'
10581
10895
  }]
10582
- }], function () { return [{ type: BasketsService }, { type: PriceService }, { type: IgnoredIngredientsService }, { type: ReplaceItemService }, { type: ContextRegistryService }, { type: BasketsSynchronizerService }]; }, null);
10896
+ }], function () { return [{ type: BasketsService }, { type: PriceService }, { type: IgnoredIngredientsService }, { type: ReplaceItemService }, { type: ContextRegistryService }, { type: BasketsSynchronizerService }, { type: StoreOutOfStockService }]; }, null);
10583
10897
  })();
10584
10898
 
10585
10899
  var RecipeDetailsProductsPlannerService = /** @class */ (function () {
@@ -10954,7 +11268,7 @@
10954
11268
  };
10955
11269
  var NewRecipeDetailsService = /** @class */ (function () {
10956
11270
  /** ********* END VARIABLES FROM COMPONENT ********* **/
10957
- function NewRecipeDetailsService(analyticsService, basketsService, recipeService, pendingBasketMethodsService, posService, basketSynchroService, priceService, contextRegistryService, sponsorBlocksService, recipesService, seoService, storeLocatorService, recipeDetailsProductsService, recipeDetailsProductsPlannerService, ignoredBasketsService, locale) {
11271
+ function NewRecipeDetailsService(analyticsService, basketsService, recipeService, pendingBasketMethodsService, posService, basketSynchroService, priceService, contextRegistryService, sponsorBlocksService, recipesService, seoService, storeLocatorService, recipeDetailsProductsService, recipeDetailsProductsPlannerService, ignoredBasketsService, storeOutOfStockService, locale) {
10958
11272
  this.analyticsService = analyticsService;
10959
11273
  this.basketsService = basketsService;
10960
11274
  this.recipeService = recipeService;
@@ -10970,6 +11284,7 @@
10970
11284
  this.recipeDetailsProductsService = recipeDetailsProductsService;
10971
11285
  this.recipeDetailsProductsPlannerService = recipeDetailsProductsPlannerService;
10972
11286
  this.ignoredBasketsService = ignoredBasketsService;
11287
+ this.storeOutOfStockService = storeOutOfStockService;
10973
11288
  this.locale = locale;
10974
11289
  this.totalProducts$ = new rxjs.BehaviorSubject(0);
10975
11290
  this.allIngredientsToBasketLoading$ = new rxjs.BehaviorSubject(false);
@@ -11118,7 +11433,7 @@
11118
11433
  return _this.setupRecipe(recipeDisplay.recipe);
11119
11434
  }
11120
11435
  else {
11121
- _this.initDefaultState(); // This can also reset the state when no recipe is displayed
11436
+ _this.initDefaultState();
11122
11437
  _this.checkIfPosIsInitializedAndValid();
11123
11438
  return rxjs.of(null);
11124
11439
  }
@@ -11126,7 +11441,7 @@
11126
11441
  };
11127
11442
  NewRecipeDetailsService.prototype.listenToBasket = function () {
11128
11443
  var _this = this;
11129
- this.subscriptions.push(this.basketsService._basket$.pipe(operators.filter(function () { return !!_this.recipe; }), operators.switchMap(function () {
11444
+ this.subscriptions.push(this.basketsService._basket$.pipe(operators.filter(function () { var _a; return !!((_a = _this.recipesService.displayedRecipe$.value) === null || _a === void 0 ? void 0 : _a.recipe); }), operators.switchMap(function () {
11130
11445
  if (_this.recipesService.isRecipeDetailsFromPlanner) {
11131
11446
  return _this.loadPlannerProducts();
11132
11447
  }
@@ -11191,14 +11506,14 @@
11191
11506
  _this.basketsService.updateRecipesInBasket([_this.recipe.id], _this.recipe.modifiedGuests, eventTrace, true);
11192
11507
  _this.recipeDetailsProductsService.getIngredientsBasketEntries(_this.recipe.ingredients, _this.recipe.modifiedGuests, false).pipe(operators.take(1)).subscribe(function (products) {
11193
11508
  if (inBasket) {
11194
- var filteredProducts = products.filter(function (_a) {
11195
- var basketEntry = _a.basketEntry;
11509
+ var filteredProducts = products.filter(function (_b) {
11510
+ var basketEntry = _b.basketEntry;
11196
11511
  return basketEntry.status === 'active' &&
11197
11512
  basketEntry.id !== '-1' &&
11198
11513
  basketEntry.recipesIds.includes(+_this.recipe.id);
11199
11514
  });
11200
- var updateActions = filteredProducts.map(function (_a) {
11201
- var basketEntry = _a.basketEntry;
11515
+ var updateActions = filteredProducts.map(function (_b) {
11516
+ var basketEntry = _b.basketEntry;
11202
11517
  var newBasketEntry = deepCloneWithClass(basketEntry); // Clone for immutability
11203
11518
  return new UpdateRecipeFromGuestAction(newBasketEntry, {
11204
11519
  eventTrace: eventTrace,
@@ -11236,20 +11551,40 @@
11236
11551
  productsToAdd_1.push(re);
11237
11552
  }
11238
11553
  }); });
11239
- var addRecipes = productsToAdd_1.map(function (re) { return new AddRecipeAction(re.entry, {
11240
- recipeId: _this.recipe.id,
11241
- ingredientId: re.ingredientId,
11242
- eventTrace: eventTrace
11243
- }, _this.basketsService); });
11244
- var onTimeouts = addRecipes.map(function (action) { return action.onTimeout; });
11245
- var onErrors = addRecipes.map(function (action) { return action.onError; });
11246
- var onSuccesses = addRecipes.map(function (action) { return action.onSuccess; });
11247
- if (addRecipes.length > 0) {
11248
- rxjs.merge.apply(void 0, __spread(onSuccesses, onTimeouts, onErrors)).pipe(operators.take(addRecipes.length)) // Take the same number of emissions as actions
11554
+ var addRecipes_1 = productsToAdd_1.map(function (re) {
11555
+ var _a;
11556
+ return new AddRecipeAction(re.entry, {
11557
+ recipeId: _this.recipe.id,
11558
+ ingredientId: re.ingredientId,
11559
+ eventTrace: {
11560
+ originPath: eventTrace.originPath,
11561
+ props: Object.assign(Object.assign({}, eventTrace.props), { index: (_a = re.index) === null || _a === void 0 ? void 0 : _a.toString() })
11562
+ }
11563
+ }, _this.basketsService);
11564
+ });
11565
+ var failedAddCount_1 = 0;
11566
+ productsToAdd_1.forEach(function (productToAdd, index) {
11567
+ addRecipes_1[index].onTimeout.pipe(operators.take(1)).subscribe(function () {
11568
+ failedAddCount_1 += 1;
11569
+ _this.storeOutOfStockService.persistOutOfStock(productToAdd.entry);
11570
+ });
11571
+ });
11572
+ var onTimeouts = addRecipes_1.map(function (action) { return action.onTimeout; });
11573
+ var onErrors = addRecipes_1.map(function (action) { return action.onError; });
11574
+ var onSuccesses = addRecipes_1.map(function (action) { return action.onSuccess; });
11575
+ if (addRecipes_1.length > 0) {
11576
+ rxjs.merge.apply(void 0, __spread(onSuccesses, onTimeouts, onErrors)).pipe(operators.take(addRecipes_1.length)) // Take the same number of emissions as actions
11249
11577
  .subscribe({
11250
- complete: function () { return _this.allIngredientsToBasketLoading$.next(false); }
11578
+ complete: function () {
11579
+ _this.allIngredientsToBasketLoading$.next(false);
11580
+ if (failedAddCount_1 > 0) {
11581
+ _this.contextRegistryService.drawerErrorToast.emit({
11582
+ code: unavailableProductAddErrorCode(failedAddCount_1)
11583
+ });
11584
+ }
11585
+ }
11251
11586
  });
11252
- _this.basketSynchroService.addToActionList(addRecipes);
11587
+ _this.basketSynchroService.addToActionList(addRecipes_1);
11253
11588
  }
11254
11589
  else {
11255
11590
  _this.allIngredientsToBasketLoading$.next(false);
@@ -11279,7 +11614,13 @@
11279
11614
  searchString: null
11280
11615
  }, _this.basketsService); }), operators.tap(function (addIngredient) {
11281
11616
  _this.basketSynchroService.addToActionList([addIngredient]);
11282
- }), operators.switchMap(function (addIngredient) { return rxjs.merge(addIngredient.onError, addIngredient.onTimeout).pipe(operators.take(1), operators.tap(function () { return _this.recipeDetailsProductsService.ingredientToBasketLoading$.next(false); })); })).subscribe());
11617
+ }), operators.switchMap(function (addIngredient) { return rxjs.merge(addIngredient.onTimeout.pipe(operators.take(1), operators.tap(function () {
11618
+ _this.storeOutOfStockService.persistOutOfStock(product.basketEntry);
11619
+ _this.recipeDetailsProductsService.ingredientToBasketLoading$.next(false);
11620
+ _this.contextRegistryService.drawerErrorToast.emit({
11621
+ code: unavailableProductAddErrorCode(1)
11622
+ });
11623
+ })), addIngredient.onError.pipe(operators.take(1), operators.tap(function () { return _this.recipeDetailsProductsService.ingredientToBasketLoading$.next(false); }))); })).subscribe());
11283
11624
  };
11284
11625
  NewRecipeDetailsService.prototype.ingredientRemoved = function (ingredient, eventTrace) {
11285
11626
  var _this = this;
@@ -11337,9 +11678,14 @@
11337
11678
  NewRecipeDetailsService.prototype.remainingProducts = function () {
11338
11679
  var _this = this;
11339
11680
  return this.remainingBasketEntries.reduce(function (result, be) {
11681
+ var _a;
11340
11682
  var matchingProduct = _this.recipeDetailsProductsService.products$.value.find(function (product) { return product.basketEntry.name === be.name; });
11341
11683
  if (matchingProduct) {
11342
- result.push({ ingredientId: matchingProduct.ingredient.id, entry: matchingProduct.basketEntry });
11684
+ result.push({
11685
+ ingredientId: matchingProduct.ingredient.id,
11686
+ entry: matchingProduct.basketEntry,
11687
+ index: (_a = matchingProduct.ingredient) === null || _a === void 0 ? void 0 : _a.index
11688
+ });
11343
11689
  }
11344
11690
  return result;
11345
11691
  }, []);
@@ -11362,7 +11708,7 @@
11362
11708
  };
11363
11709
  return NewRecipeDetailsService;
11364
11710
  }());
11365
- NewRecipeDetailsService.ɵfac = function NewRecipeDetailsService_Factory(t) { return new (t || NewRecipeDetailsService)(i0__namespace.ɵɵinject(AnalyticsService), i0__namespace.ɵɵinject(BasketsService), i0__namespace.ɵɵinject(RecipesService), i0__namespace.ɵɵinject(PendingBasketMethodsService), i0__namespace.ɵɵinject(PointOfSalesService), i0__namespace.ɵɵinject(BasketsSynchronizerService), i0__namespace.ɵɵinject(PriceService), i0__namespace.ɵɵinject(ContextRegistryService), i0__namespace.ɵɵinject(SponsorBlockService), i0__namespace.ɵɵinject(RecipesService), i0__namespace.ɵɵinject(SeoService), i0__namespace.ɵɵinject(StoreLocatorService), i0__namespace.ɵɵinject(RecipeDetailsProductsService), i0__namespace.ɵɵinject(RecipeDetailsProductsPlannerService), i0__namespace.ɵɵinject(IgnoredIngredientsService), i0__namespace.ɵɵinject(i0.LOCALE_ID)); };
11711
+ NewRecipeDetailsService.ɵfac = function NewRecipeDetailsService_Factory(t) { return new (t || NewRecipeDetailsService)(i0__namespace.ɵɵinject(AnalyticsService), i0__namespace.ɵɵinject(BasketsService), i0__namespace.ɵɵinject(RecipesService), i0__namespace.ɵɵinject(PendingBasketMethodsService), i0__namespace.ɵɵinject(PointOfSalesService), i0__namespace.ɵɵinject(BasketsSynchronizerService), i0__namespace.ɵɵinject(PriceService), i0__namespace.ɵɵinject(ContextRegistryService), i0__namespace.ɵɵinject(SponsorBlockService), i0__namespace.ɵɵinject(RecipesService), i0__namespace.ɵɵinject(SeoService), i0__namespace.ɵɵinject(StoreLocatorService), i0__namespace.ɵɵinject(RecipeDetailsProductsService), i0__namespace.ɵɵinject(RecipeDetailsProductsPlannerService), i0__namespace.ɵɵinject(IgnoredIngredientsService), i0__namespace.ɵɵinject(StoreOutOfStockService), i0__namespace.ɵɵinject(i0.LOCALE_ID)); };
11366
11712
  NewRecipeDetailsService.ɵprov = i0__namespace.ɵɵdefineInjectable({ token: NewRecipeDetailsService, factory: NewRecipeDetailsService.ɵfac, providedIn: 'root' });
11367
11713
  (function () {
11368
11714
  (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(NewRecipeDetailsService, [{
@@ -11371,7 +11717,7 @@
11371
11717
  providedIn: 'root'
11372
11718
  }]
11373
11719
  }], function () {
11374
- return [{ type: AnalyticsService }, { type: BasketsService }, { type: RecipesService }, { type: PendingBasketMethodsService }, { type: PointOfSalesService }, { type: BasketsSynchronizerService }, { type: PriceService }, { type: ContextRegistryService }, { type: SponsorBlockService }, { type: RecipesService }, { type: SeoService }, { type: StoreLocatorService }, { type: RecipeDetailsProductsService }, { type: RecipeDetailsProductsPlannerService }, { type: IgnoredIngredientsService }, { type: undefined, decorators: [{
11720
+ return [{ type: AnalyticsService }, { type: BasketsService }, { type: RecipesService }, { type: PendingBasketMethodsService }, { type: PointOfSalesService }, { type: BasketsSynchronizerService }, { type: PriceService }, { type: ContextRegistryService }, { type: SponsorBlockService }, { type: RecipesService }, { type: SeoService }, { type: StoreLocatorService }, { type: RecipeDetailsProductsService }, { type: RecipeDetailsProductsPlannerService }, { type: IgnoredIngredientsService }, { type: StoreOutOfStockService }, { type: undefined, decorators: [{
11375
11721
  type: i0.Inject,
11376
11722
  args: [i0.LOCALE_ID]
11377
11723
  }] }];
@@ -11447,7 +11793,8 @@
11447
11793
  },
11448
11794
  eventSent$: this.analyticsService.eventEmitter,
11449
11795
  setAbTestKey: function (key) { return _this.analyticsService.setAbTestKey(key); },
11450
- attachRecipeCardShowTracking: attachRecipeCardShowTracking
11796
+ attachRecipeCardShowTracking: attachRecipeCardShowTracking,
11797
+ attachProductShowTracking: attachProductShowTracking
11451
11798
  },
11452
11799
  basket: {
11453
11800
  basketIsReady$: this.basketsService.basketStats$.pipe(operators.skipWhile(function (stats) { return !stats; }), operators.take(1), operators.map(function () { return true; })),
@@ -11761,6 +12108,9 @@
11761
12108
  config: {
11762
12109
  logLevel: this.logLevel$
11763
12110
  },
12111
+ drawer: {
12112
+ errorToast: function () { return _this.contextRegistryService.drawerErrorToast; }
12113
+ },
11764
12114
  planner: {
11765
12115
  itemToReplace$: this.recipeDetailsProductsPlannerService.itemToReplace$,
11766
12116
  itemsWithPricesList$: this.recipeDetailsProductsPlannerService.itemsWithPricesList$,
@@ -12157,6 +12507,7 @@
12157
12507
  if (!recipeId) {
12158
12508
  return rxjs.of(void 0);
12159
12509
  }
12510
+ ProductShowTracker.getInstance().clearForRecipe(recipeId);
12160
12511
  return this.recipesService.get(recipeId, { include: ['ingredients', 'recipe-steps', 'recipe-type', 'sponsors', 'tags', 'recipe-provider'] })
12161
12512
  .pipe(operators.take(1), operators.switchMap(function (recipe) {
12162
12513
  if (guests != null) {
@@ -13458,7 +13809,7 @@
13458
13809
  env: 'prod',
13459
13810
  miamAPI: 'https://api.miam.tech',
13460
13811
  miamWeb: 'https://miam.tech',
13461
- mealzComponents: 'https://cdn.jsdelivr.net/npm/mealz-components@2.11/dist',
13812
+ mealzComponents: 'https://cdn.jsdelivr.net/npm/mealz-components@2.12/dist',
13462
13813
  mealzSsrApi: 'https://ssr-api.mealz.ai',
13463
13814
  lang: 'fr',
13464
13815
  analyticsEnabled: true // Only used in DEV mode
@@ -16110,10 +16461,17 @@
16110
16461
  var _this = this;
16111
16462
  this.subscriptions.push(this.recipeDetailsService.productsByCategory$.subscribe(function () { return _this.isProductSponsored(); }), this.executeActionFromStorage(), this.loadOnRecipesActions(), this.loadOnIngredientsUpdate(), this.updateIngredientQuantityOnRecipeChange(), this.productIsBeingAdded(), this.scrollBackOnProductReplaced());
16112
16463
  this.getHeaderHeight();
16464
+ this.productShowTrackingHandle = attachProductShowTracking({
16465
+ element: this.elementRef.nativeElement,
16466
+ product: this.product,
16467
+ recipeId: this.recipeDetailsService.recipe.id,
16468
+ analyticsPath: this.path || undefined
16469
+ });
16113
16470
  };
16114
16471
  ProductCardComponent.prototype.ngOnDestroy = function () {
16115
- var _a;
16116
- (_a = this.subscriptions) === null || _a === void 0 ? void 0 : _a.forEach(function (sub) { return sub.unsubscribe(); });
16472
+ var _a, _b;
16473
+ (_a = this.productShowTrackingHandle) === null || _a === void 0 ? void 0 : _a.disconnect();
16474
+ (_b = this.subscriptions) === null || _b === void 0 ? void 0 : _b.forEach(function (sub) { return sub.unsubscribe(); });
16117
16475
  };
16118
16476
  ProductCardComponent.prototype.scrollBackOnProductReplaced = function () {
16119
16477
  var _this = this;
@@ -17066,12 +17424,14 @@
17066
17424
  }
17067
17425
  };
17068
17426
  BasketPreviewProductComponent.prototype.removeProduct = function () {
17427
+ var _a;
17069
17428
  this.analyticsService.sendEvent('entry.deleted', this.path, {
17070
17429
  entry_name: this.basketEntry.name,
17071
17430
  item_id: this.basketEntry.selectedItem.id,
17072
17431
  ext_item_id: this.basketEntry.selectedItem.attributes['ext-id'],
17073
17432
  item_ean: this.basketEntry.selectedItem.ean,
17074
17433
  product_quantity: this.basketEntry.quantity.toString(),
17434
+ product_base_price: ((_a = this.basketEntry.price) !== null && _a !== void 0 ? _a : 0).toString(),
17075
17435
  recipe_id: this.basketEntry.recipesIds.length > 0 ? this.basketEntry.recipesIds[0].toString() : null
17076
17436
  });
17077
17437
  var deletedBasketEntry = deepCloneWithClass(this.basketEntry);