@zenky/storefront-vue 0.9.32 → 0.9.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -8,6 +8,11 @@ var api = require('@zenky/api');
8
8
  var pinia = require('pinia');
9
9
  var ui = require('@zenky/ui');
10
10
  var events = require('@zenky/events');
11
+ var Pusher = require('pusher-js');
12
+
13
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
14
+
15
+ var Pusher__default = /*#__PURE__*/_interopDefaultLegacy(Pusher);
11
16
 
12
17
  function useDataDestroyer(destroyer, errorHandler) {
13
18
  const destroying = vue.ref(false);
@@ -45,6 +50,16 @@ exports.ZenkyInjection = void 0;
45
50
  ZenkyInjection["CategoryNotFound"] = "zenky:category:notFound";
46
51
  ZenkyInjection["Collection"] = "zenky:collection";
47
52
  ZenkyInjection["CollectionNotFound"] = "zenky:collection:notFound";
53
+ ZenkyInjection["Offer"] = "zenky:offer";
54
+ ZenkyInjection["OfferNotFound"] = "zenky:offer:notFound";
55
+ ZenkyInjection["CategoryContext"] = "zenky:context:category";
56
+ ZenkyInjection["CategoryContextNotFound"] = "zenky:context:category:notFound";
57
+ ZenkyInjection["GroupContext"] = "zenky:context:category";
58
+ ZenkyInjection["GroupContextNotFound"] = "zenky:context:category:notFound";
59
+ ZenkyInjection["VariantOptionContext"] = "zenky:context:variant_option";
60
+ ZenkyInjection["VariantOptionContextNotFound"] = "zenky:context:variant_option:notFound";
61
+ ZenkyInjection["VariantOptionValueContext"] = "zenky:context:variant_option_value";
62
+ ZenkyInjection["VariantOptionValueContextNotFound"] = "zenky:context:variant_option_value:notFound";
48
63
  })(exports.ZenkyInjection || (exports.ZenkyInjection = {}));
49
64
 
50
65
  async function useStateDataLoader(state, loader) {
@@ -1530,6 +1545,17 @@ function getFirstMedium(media, sizes = ['large', 'medium'], preferWebp = true) {
1530
1545
  return images.length > 0 ? images[0] : null;
1531
1546
  }
1532
1547
 
1548
+ function useOffersList(errorHandler) {
1549
+ return usePaginatedLoader(api.getOffers, getApiErrorHandler(errorHandler, function (e) {
1550
+ ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить список акций.'));
1551
+ }));
1552
+ }
1553
+ function useOfferItem(errorHandler) {
1554
+ return useItemLoader(api.getOffer, getApiErrorHandler(errorHandler, function (e) {
1555
+ ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить акцию.'));
1556
+ }));
1557
+ }
1558
+
1533
1559
  function useProductsPricesRange(categoryId, errorHandler) {
1534
1560
  return useDataLoader(async () => api.getProductsPricesRange(categoryId), getApiErrorHandler(errorHandler, function (e) {
1535
1561
  ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить диапазон цен.'));
@@ -1585,6 +1611,10 @@ var ProductsSourceType;
1585
1611
  (function (ProductsSourceType) {
1586
1612
  ProductsSourceType["Category"] = "category";
1587
1613
  ProductsSourceType["Collection"] = "collection";
1614
+ ProductsSourceType["CategoryContext"] = "category_context";
1615
+ ProductsSourceType["GroupContext"] = "group_context";
1616
+ ProductsSourceType["VariantOptionContext"] = "variant_option_context";
1617
+ ProductsSourceType["VariantOptionValueContext"] = "variant_option_value_context";
1588
1618
  })(ProductsSourceType || (ProductsSourceType = {}));
1589
1619
  var ProductsSorting;
1590
1620
  (function (ProductsSorting) {
@@ -1600,15 +1630,38 @@ var ProductsFiltersType;
1600
1630
  ProductsFiltersType["FeaturesGroups"] = "featuresGroups";
1601
1631
  })(ProductsFiltersType || (ProductsFiltersType = {}));
1602
1632
 
1603
- function getSourceParams(source) {
1633
+ function getSourceParams(source, promotion) {
1604
1634
  if (source === null || !source.id || !source.type) {
1605
1635
  return {};
1606
1636
  }
1637
+ else if (promotion !== null) {
1638
+ return {};
1639
+ }
1607
1640
  switch (source.type) {
1608
- case 'category':
1641
+ case ProductsSourceType.Category:
1609
1642
  return { category_id: source.id };
1610
- case 'collection':
1643
+ case ProductsSourceType.Collection:
1611
1644
  return { collection_id: source.id };
1645
+ case ProductsSourceType.CategoryContext:
1646
+ return {
1647
+ context_type: 'category',
1648
+ context_id: source.id,
1649
+ };
1650
+ case ProductsSourceType.GroupContext:
1651
+ return {
1652
+ context_type: 'group',
1653
+ context_id: source.id,
1654
+ };
1655
+ case ProductsSourceType.VariantOptionContext:
1656
+ return {
1657
+ context_type: 'variant_option',
1658
+ context_id: source.id,
1659
+ };
1660
+ case ProductsSourceType.VariantOptionValueContext:
1661
+ return {
1662
+ context_type: 'variant_option_value',
1663
+ context_id: source.id,
1664
+ };
1612
1665
  default:
1613
1666
  return {};
1614
1667
  }
@@ -1670,6 +1723,15 @@ function getLoaderParams(page, loader) {
1670
1723
  if (loader.search) {
1671
1724
  params.search = loader.search;
1672
1725
  }
1726
+ if (typeof loader.promotion === 'undefined' || loader.promotion === null) {
1727
+ return params;
1728
+ }
1729
+ params.promotion_reward = 'all';
1730
+ if (!loader.promotion.context_type || !loader.promotion.context_id) {
1731
+ return params;
1732
+ }
1733
+ params.context_type = loader.promotion.context_type;
1734
+ params.context_id = loader.promotion.context_id;
1673
1735
  return params;
1674
1736
  }
1675
1737
  function getProductsPaginationRequest(page, loader) {
@@ -1677,7 +1739,7 @@ function getProductsPaginationRequest(page, loader) {
1677
1739
  return null;
1678
1740
  }
1679
1741
  return {
1680
- ...getSourceParams(loader.source),
1742
+ ...getSourceParams(loader.source, loader.promotion),
1681
1743
  ...getSortingParams(loader.sorting),
1682
1744
  ...getFiltersParams(loader.filters),
1683
1745
  ...getPricesFiltersParams(loader.pricesFilters),
@@ -1718,6 +1780,7 @@ function useProductsList(config, errorHandler) {
1718
1780
  count: config.value.count,
1719
1781
  },
1720
1782
  with: config.value.with || '',
1783
+ promotion: config.value.promotion || null,
1721
1784
  }));
1722
1785
  const load = async (page, reset = false, callback) => {
1723
1786
  const request = getProductsPaginationRequest(page, loader.value);
@@ -1778,9 +1841,26 @@ function getFiltersFromUrl(param) {
1778
1841
  });
1779
1842
  return filters;
1780
1843
  }
1844
+ function getProductsListQueryParamsWithPromotion(params, promotion) {
1845
+ if (!promotion) {
1846
+ return params;
1847
+ }
1848
+ const clone = {
1849
+ ...params,
1850
+ promotion_id: promotion.id,
1851
+ reward_id: promotion.reward_id,
1852
+ };
1853
+ if (promotion.context_type) {
1854
+ clone.context_type = promotion.context_type;
1855
+ }
1856
+ if (promotion.context_id) {
1857
+ clone.context_id = promotion.context_id;
1858
+ }
1859
+ return clone;
1860
+ }
1781
1861
  function getProductsListQueryParams(config, request) {
1782
1862
  if (request === null) {
1783
- return {};
1863
+ return getProductsListQueryParamsWithPromotion({}, config.promotion);
1784
1864
  }
1785
1865
  const query = {};
1786
1866
  if (request.order_by && request.order_by !== config.sorting) {
@@ -1798,7 +1878,25 @@ function getProductsListQueryParams(config, request) {
1798
1878
  if (request.search) {
1799
1879
  query.search = request.search;
1800
1880
  }
1801
- return query;
1881
+ return getProductsListQueryParamsWithPromotion(query, config.promotion);
1882
+ }
1883
+ function getQueryParam(query, param) {
1884
+ return typeof query[param] !== 'undefined' && query[param] ? query[param] : null;
1885
+ }
1886
+ function getPromotionFromQuery(query) {
1887
+ const promotionId = getQueryParam(query, 'promotion_id');
1888
+ const rewardId = getQueryParam(query, 'reward_id');
1889
+ if (!promotionId || !rewardId) {
1890
+ return null;
1891
+ }
1892
+ const contextType = getQueryParam(query, 'context_type');
1893
+ const contextId = getQueryParam(query, 'context_id');
1894
+ return {
1895
+ id: promotionId,
1896
+ reward_id: rewardId,
1897
+ context_type: contextType,
1898
+ context_id: contextId,
1899
+ };
1802
1900
  }
1803
1901
  function getProductsListParamsFromQuery(query) {
1804
1902
  if (!query) {
@@ -1807,9 +1905,10 @@ function getProductsListParamsFromQuery(query) {
1807
1905
  return {
1808
1906
  sorting: typeof query.order_by !== 'undefined' ? query.order_by : null,
1809
1907
  f: typeof query.f === 'string' ? getFiltersFromUrl(query.f) : null,
1810
- min_price: typeof query.min_price !== 'undefined' && query.min_price ? query.min_price : null,
1811
- max_price: typeof query.max_price !== 'undefined' && query.max_price ? query.max_price : null,
1812
- search: typeof query.search !== 'undefined' && query.search ? query.search : null,
1908
+ min_price: getQueryParam(query, 'min_price'),
1909
+ max_price: getQueryParam(query, 'max_price'),
1910
+ search: getQueryParam(query, 'search'),
1911
+ promotion: getPromotionFromQuery(query),
1813
1912
  };
1814
1913
  }
1815
1914
 
@@ -1845,12 +1944,86 @@ function getProductsSource(source) {
1845
1944
  return getInjectedSource(exports.ZenkyInjection.Category, exports.ZenkyInjection.CategoryNotFound, injected);
1846
1945
  case ProductsSourceType.Collection:
1847
1946
  return getInjectedSource(exports.ZenkyInjection.Collection, exports.ZenkyInjection.CollectionNotFound, injected);
1947
+ case ProductsSourceType.CategoryContext:
1948
+ return getInjectedSource(exports.ZenkyInjection.CategoryContext, exports.ZenkyInjection.CategoryContextNotFound, injected);
1949
+ case ProductsSourceType.GroupContext:
1950
+ return getInjectedSource(exports.ZenkyInjection.GroupContext, exports.ZenkyInjection.GroupContextNotFound, injected);
1951
+ case ProductsSourceType.VariantOptionContext:
1952
+ return getInjectedSource(exports.ZenkyInjection.VariantOptionContext, exports.ZenkyInjection.VariantOptionContextNotFound, injected);
1953
+ case ProductsSourceType.VariantOptionValueContext:
1954
+ return getInjectedSource(exports.ZenkyInjection.VariantOptionValueContext, exports.ZenkyInjection.VariantOptionValueContextNotFound, injected);
1848
1955
  default:
1849
1956
  return null;
1850
1957
  }
1851
1958
  }
1852
1959
 
1960
+ exports.ZenkyWebsocketEvent = void 0;
1961
+ (function (ZenkyWebsocketEvent) {
1962
+ ZenkyWebsocketEvent["OrderPriceRecalculated"] = "orders.price.recalculated";
1963
+ ZenkyWebsocketEvent["OrderMustBeReloaded"] = "orders.reload";
1964
+ ZenkyWebsocketEvent["OrderRewardsMustBeReloaded"] = "orders.rewards.reload";
1965
+ ZenkyWebsocketEvent["DisplayOrderRewardsSelection"] = "orders.rewards.display_selection";
1966
+ ZenkyWebsocketEvent["PromotionsNotFound"] = "orders.promotions.not_found";
1967
+ })(exports.ZenkyWebsocketEvent || (exports.ZenkyWebsocketEvent = {}));
1968
+
1969
+ let instance = null;
1970
+ function createWebsocketsConnection(store) {
1971
+ if (instance !== null) {
1972
+ return instance;
1973
+ }
1974
+ else if (typeof store.settings === 'undefined' || store.settings === null) {
1975
+ throw new Error('You must provide store with settings.');
1976
+ }
1977
+ else if (typeof store.settings.websockets === 'undefined' || store.settings.websockets === null) {
1978
+ throw new Error('You must provide store with websockets settings.');
1979
+ }
1980
+ instance = new Pusher__default["default"](store.settings.websockets.app_key, {
1981
+ wsHost: store.settings.websockets.options.host,
1982
+ wsPort: store.settings.websockets.options.port,
1983
+ forceTLS: false,
1984
+ enableStats: false,
1985
+ enabledTransports: ['ws', 'wss'],
1986
+ });
1987
+ return instance;
1988
+ }
1989
+ function getWebsocketsConnection() {
1990
+ if (instance === null) {
1991
+ throw new Error('You must create websockets connection using [createWebsocketsConnection] function.');
1992
+ }
1993
+ return instance;
1994
+ }
1995
+ function subscribeToOrderEvents(order) {
1996
+ if (instance === null) {
1997
+ throw new Error('You must create websocket connection using `createWebsocketConnection` function!');
1998
+ }
1999
+ const channel = instance.subscribe(`orders.${order.id}.${order.token}`);
2000
+ channel.bind(exports.ZenkyWebsocketEvent.OrderPriceRecalculated, (data) => {
2001
+ events.useOrderPriceRecalculated().publish({ order, data });
2002
+ });
2003
+ channel.bind(exports.ZenkyWebsocketEvent.OrderMustBeReloaded, () => {
2004
+ events.useOrderShouldBeReloaded().publish({ order });
2005
+ });
2006
+ channel.bind(exports.ZenkyWebsocketEvent.OrderRewardsMustBeReloaded, () => {
2007
+ events.useOrderPromotionRewardsShouldBeReloaded().publish({ order });
2008
+ });
2009
+ channel.bind(exports.ZenkyWebsocketEvent.DisplayOrderRewardsSelection, (data) => {
2010
+ events.useDisplayOrderPromotionRewardSelection().publish({ order, data });
2011
+ events.usePromotionsCheckerCompleted().publish();
2012
+ });
2013
+ channel.bind(exports.ZenkyWebsocketEvent.PromotionsNotFound, () => {
2014
+ events.useOrderPromotionsNotFound().publish({ order });
2015
+ events.usePromotionsCheckerCompleted().publish();
2016
+ });
2017
+ events.useOrderSubmitted().subscribe('websockets.subscribe', ({ order: submittedOrder }) => {
2018
+ if (instance === null) {
2019
+ throw new Error('You must create websocket connection using `createWebsocketConnection` function!');
2020
+ }
2021
+ instance.unsubscribe(`orders.${submittedOrder.id}.${submittedOrder.token}`);
2022
+ });
2023
+ }
2024
+
1853
2025
  exports.createStorage = createStorage;
2026
+ exports.createWebsocketsConnection = createWebsocketsConnection;
1854
2027
  exports.getAddressForm = getAddressForm;
1855
2028
  exports.getApiErrorHandler = getApiErrorHandler;
1856
2029
  exports.getExistedAddress = getExistedAddress;
@@ -1865,6 +2038,8 @@ exports.getSelectedAddressDisplayValue = getSelectedAddressDisplayValue;
1865
2038
  exports.getStockAddress = getStockAddress;
1866
2039
  exports.getStockSchedule = getStockSchedule;
1867
2040
  exports.getStorage = getStorage;
2041
+ exports.getWebsocketsConnection = getWebsocketsConnection;
2042
+ exports.subscribeToOrderEvents = subscribeToOrderEvents;
1868
2043
  exports.useAddressFormValue = useAddressFormValue;
1869
2044
  exports.useArticleCategoriesList = useArticleCategoriesList;
1870
2045
  exports.useArticleItem = useArticleItem;
@@ -1895,6 +2070,8 @@ exports.useItemLoader = useItemLoader;
1895
2070
  exports.useListLoader = useListLoader;
1896
2071
  exports.useLogin = useLogin;
1897
2072
  exports.useLogout = useLogout;
2073
+ exports.useOfferItem = useOfferItem;
2074
+ exports.useOffersList = useOffersList;
1898
2075
  exports.useOrderItem = useOrderItem;
1899
2076
  exports.useOrdersList = useOrdersList;
1900
2077
  exports.usePaginatedLoader = usePaginatedLoader;
package/dist/esm/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import { ref, computed, watch, unref, inject } from 'vue';
2
2
  import { debounce, isBoolean } from 'lodash-es';
3
- import { getStore, getAddressSuggestions, getCategoriesTree, getProductsCollections, getApiErrorMessage, getCategoryFeatures, getCategoryFeaturesGroups, getArticles, getArticleCategories, getArticle, getAuthenticationStatus, setAxiosToken, getCustomerProfile, login, requestPasswordResetCode, resetPassword, register, resendConfirmationCode, confirm, getApiErrorCode, getCustomerAddresses, deleteAddress, updateAddress, getCustomerOrders, getOrder, getCustomerPaymentMethods, deleteCustomerPaymentMethod, ImageType, getProductsPricesRange, getProducts } from '@zenky/api';
3
+ import { getStore, getAddressSuggestions, getCategoriesTree, getProductsCollections, getApiErrorMessage, getCategoryFeatures, getCategoryFeaturesGroups, getArticles, getArticleCategories, getArticle, getAuthenticationStatus, setAxiosToken, getCustomerProfile, login, requestPasswordResetCode, resetPassword, register, resendConfirmationCode, confirm, getApiErrorCode, getCustomerAddresses, deleteAddress, updateAddress, getCustomerOrders, getOrder, getCustomerPaymentMethods, deleteCustomerPaymentMethod, ImageType, getOffers, getOffer, getProductsPricesRange, getProducts } from '@zenky/api';
4
4
  import { defineStore } from 'pinia';
5
5
  import { useNotification } from '@zenky/ui';
6
- import { useCustomerLoaded, useCustomerAuthenticated, useCustomerLoggedOut } from '@zenky/events';
6
+ import { useCustomerLoaded, useCustomerAuthenticated, useCustomerLoggedOut, useOrderPriceRecalculated, useOrderShouldBeReloaded, useOrderPromotionRewardsShouldBeReloaded, useDisplayOrderPromotionRewardSelection, usePromotionsCheckerCompleted, useOrderPromotionsNotFound, useOrderSubmitted } from '@zenky/events';
7
+ import Pusher from 'pusher-js';
7
8
 
8
9
  function useDataDestroyer(destroyer, errorHandler) {
9
10
  const destroying = ref(false);
@@ -41,6 +42,16 @@ var ZenkyInjection;
41
42
  ZenkyInjection["CategoryNotFound"] = "zenky:category:notFound";
42
43
  ZenkyInjection["Collection"] = "zenky:collection";
43
44
  ZenkyInjection["CollectionNotFound"] = "zenky:collection:notFound";
45
+ ZenkyInjection["Offer"] = "zenky:offer";
46
+ ZenkyInjection["OfferNotFound"] = "zenky:offer:notFound";
47
+ ZenkyInjection["CategoryContext"] = "zenky:context:category";
48
+ ZenkyInjection["CategoryContextNotFound"] = "zenky:context:category:notFound";
49
+ ZenkyInjection["GroupContext"] = "zenky:context:category";
50
+ ZenkyInjection["GroupContextNotFound"] = "zenky:context:category:notFound";
51
+ ZenkyInjection["VariantOptionContext"] = "zenky:context:variant_option";
52
+ ZenkyInjection["VariantOptionContextNotFound"] = "zenky:context:variant_option:notFound";
53
+ ZenkyInjection["VariantOptionValueContext"] = "zenky:context:variant_option_value";
54
+ ZenkyInjection["VariantOptionValueContextNotFound"] = "zenky:context:variant_option_value:notFound";
44
55
  })(ZenkyInjection || (ZenkyInjection = {}));
45
56
 
46
57
  async function useStateDataLoader(state, loader) {
@@ -1526,6 +1537,17 @@ function getFirstMedium(media, sizes = ['large', 'medium'], preferWebp = true) {
1526
1537
  return images.length > 0 ? images[0] : null;
1527
1538
  }
1528
1539
 
1540
+ function useOffersList(errorHandler) {
1541
+ return usePaginatedLoader(getOffers, getApiErrorHandler(errorHandler, function (e) {
1542
+ useNotification('error', 'Ошибка', getApiErrorMessage(e, 'Не удалось загрузить список акций.'));
1543
+ }));
1544
+ }
1545
+ function useOfferItem(errorHandler) {
1546
+ return useItemLoader(getOffer, getApiErrorHandler(errorHandler, function (e) {
1547
+ useNotification('error', 'Ошибка', getApiErrorMessage(e, 'Не удалось загрузить акцию.'));
1548
+ }));
1549
+ }
1550
+
1529
1551
  function useProductsPricesRange(categoryId, errorHandler) {
1530
1552
  return useDataLoader(async () => getProductsPricesRange(categoryId), getApiErrorHandler(errorHandler, function (e) {
1531
1553
  useNotification('error', 'Ошибка', getApiErrorMessage(e, 'Не удалось загрузить диапазон цен.'));
@@ -1581,6 +1603,10 @@ var ProductsSourceType;
1581
1603
  (function (ProductsSourceType) {
1582
1604
  ProductsSourceType["Category"] = "category";
1583
1605
  ProductsSourceType["Collection"] = "collection";
1606
+ ProductsSourceType["CategoryContext"] = "category_context";
1607
+ ProductsSourceType["GroupContext"] = "group_context";
1608
+ ProductsSourceType["VariantOptionContext"] = "variant_option_context";
1609
+ ProductsSourceType["VariantOptionValueContext"] = "variant_option_value_context";
1584
1610
  })(ProductsSourceType || (ProductsSourceType = {}));
1585
1611
  var ProductsSorting;
1586
1612
  (function (ProductsSorting) {
@@ -1596,15 +1622,38 @@ var ProductsFiltersType;
1596
1622
  ProductsFiltersType["FeaturesGroups"] = "featuresGroups";
1597
1623
  })(ProductsFiltersType || (ProductsFiltersType = {}));
1598
1624
 
1599
- function getSourceParams(source) {
1625
+ function getSourceParams(source, promotion) {
1600
1626
  if (source === null || !source.id || !source.type) {
1601
1627
  return {};
1602
1628
  }
1629
+ else if (promotion !== null) {
1630
+ return {};
1631
+ }
1603
1632
  switch (source.type) {
1604
- case 'category':
1633
+ case ProductsSourceType.Category:
1605
1634
  return { category_id: source.id };
1606
- case 'collection':
1635
+ case ProductsSourceType.Collection:
1607
1636
  return { collection_id: source.id };
1637
+ case ProductsSourceType.CategoryContext:
1638
+ return {
1639
+ context_type: 'category',
1640
+ context_id: source.id,
1641
+ };
1642
+ case ProductsSourceType.GroupContext:
1643
+ return {
1644
+ context_type: 'group',
1645
+ context_id: source.id,
1646
+ };
1647
+ case ProductsSourceType.VariantOptionContext:
1648
+ return {
1649
+ context_type: 'variant_option',
1650
+ context_id: source.id,
1651
+ };
1652
+ case ProductsSourceType.VariantOptionValueContext:
1653
+ return {
1654
+ context_type: 'variant_option_value',
1655
+ context_id: source.id,
1656
+ };
1608
1657
  default:
1609
1658
  return {};
1610
1659
  }
@@ -1666,6 +1715,15 @@ function getLoaderParams(page, loader) {
1666
1715
  if (loader.search) {
1667
1716
  params.search = loader.search;
1668
1717
  }
1718
+ if (typeof loader.promotion === 'undefined' || loader.promotion === null) {
1719
+ return params;
1720
+ }
1721
+ params.promotion_reward = 'all';
1722
+ if (!loader.promotion.context_type || !loader.promotion.context_id) {
1723
+ return params;
1724
+ }
1725
+ params.context_type = loader.promotion.context_type;
1726
+ params.context_id = loader.promotion.context_id;
1669
1727
  return params;
1670
1728
  }
1671
1729
  function getProductsPaginationRequest(page, loader) {
@@ -1673,7 +1731,7 @@ function getProductsPaginationRequest(page, loader) {
1673
1731
  return null;
1674
1732
  }
1675
1733
  return {
1676
- ...getSourceParams(loader.source),
1734
+ ...getSourceParams(loader.source, loader.promotion),
1677
1735
  ...getSortingParams(loader.sorting),
1678
1736
  ...getFiltersParams(loader.filters),
1679
1737
  ...getPricesFiltersParams(loader.pricesFilters),
@@ -1714,6 +1772,7 @@ function useProductsList(config, errorHandler) {
1714
1772
  count: config.value.count,
1715
1773
  },
1716
1774
  with: config.value.with || '',
1775
+ promotion: config.value.promotion || null,
1717
1776
  }));
1718
1777
  const load = async (page, reset = false, callback) => {
1719
1778
  const request = getProductsPaginationRequest(page, loader.value);
@@ -1774,9 +1833,26 @@ function getFiltersFromUrl(param) {
1774
1833
  });
1775
1834
  return filters;
1776
1835
  }
1836
+ function getProductsListQueryParamsWithPromotion(params, promotion) {
1837
+ if (!promotion) {
1838
+ return params;
1839
+ }
1840
+ const clone = {
1841
+ ...params,
1842
+ promotion_id: promotion.id,
1843
+ reward_id: promotion.reward_id,
1844
+ };
1845
+ if (promotion.context_type) {
1846
+ clone.context_type = promotion.context_type;
1847
+ }
1848
+ if (promotion.context_id) {
1849
+ clone.context_id = promotion.context_id;
1850
+ }
1851
+ return clone;
1852
+ }
1777
1853
  function getProductsListQueryParams(config, request) {
1778
1854
  if (request === null) {
1779
- return {};
1855
+ return getProductsListQueryParamsWithPromotion({}, config.promotion);
1780
1856
  }
1781
1857
  const query = {};
1782
1858
  if (request.order_by && request.order_by !== config.sorting) {
@@ -1794,7 +1870,25 @@ function getProductsListQueryParams(config, request) {
1794
1870
  if (request.search) {
1795
1871
  query.search = request.search;
1796
1872
  }
1797
- return query;
1873
+ return getProductsListQueryParamsWithPromotion(query, config.promotion);
1874
+ }
1875
+ function getQueryParam(query, param) {
1876
+ return typeof query[param] !== 'undefined' && query[param] ? query[param] : null;
1877
+ }
1878
+ function getPromotionFromQuery(query) {
1879
+ const promotionId = getQueryParam(query, 'promotion_id');
1880
+ const rewardId = getQueryParam(query, 'reward_id');
1881
+ if (!promotionId || !rewardId) {
1882
+ return null;
1883
+ }
1884
+ const contextType = getQueryParam(query, 'context_type');
1885
+ const contextId = getQueryParam(query, 'context_id');
1886
+ return {
1887
+ id: promotionId,
1888
+ reward_id: rewardId,
1889
+ context_type: contextType,
1890
+ context_id: contextId,
1891
+ };
1798
1892
  }
1799
1893
  function getProductsListParamsFromQuery(query) {
1800
1894
  if (!query) {
@@ -1803,9 +1897,10 @@ function getProductsListParamsFromQuery(query) {
1803
1897
  return {
1804
1898
  sorting: typeof query.order_by !== 'undefined' ? query.order_by : null,
1805
1899
  f: typeof query.f === 'string' ? getFiltersFromUrl(query.f) : null,
1806
- min_price: typeof query.min_price !== 'undefined' && query.min_price ? query.min_price : null,
1807
- max_price: typeof query.max_price !== 'undefined' && query.max_price ? query.max_price : null,
1808
- search: typeof query.search !== 'undefined' && query.search ? query.search : null,
1900
+ min_price: getQueryParam(query, 'min_price'),
1901
+ max_price: getQueryParam(query, 'max_price'),
1902
+ search: getQueryParam(query, 'search'),
1903
+ promotion: getPromotionFromQuery(query),
1809
1904
  };
1810
1905
  }
1811
1906
 
@@ -1841,9 +1936,82 @@ function getProductsSource(source) {
1841
1936
  return getInjectedSource(ZenkyInjection.Category, ZenkyInjection.CategoryNotFound, injected);
1842
1937
  case ProductsSourceType.Collection:
1843
1938
  return getInjectedSource(ZenkyInjection.Collection, ZenkyInjection.CollectionNotFound, injected);
1939
+ case ProductsSourceType.CategoryContext:
1940
+ return getInjectedSource(ZenkyInjection.CategoryContext, ZenkyInjection.CategoryContextNotFound, injected);
1941
+ case ProductsSourceType.GroupContext:
1942
+ return getInjectedSource(ZenkyInjection.GroupContext, ZenkyInjection.GroupContextNotFound, injected);
1943
+ case ProductsSourceType.VariantOptionContext:
1944
+ return getInjectedSource(ZenkyInjection.VariantOptionContext, ZenkyInjection.VariantOptionContextNotFound, injected);
1945
+ case ProductsSourceType.VariantOptionValueContext:
1946
+ return getInjectedSource(ZenkyInjection.VariantOptionValueContext, ZenkyInjection.VariantOptionValueContextNotFound, injected);
1844
1947
  default:
1845
1948
  return null;
1846
1949
  }
1847
1950
  }
1848
1951
 
1849
- export { AuthenticationEvent, AuthenticationResultType, AuthenticationStage, ZenkyInjection, createStorage, getAddressForm, getApiErrorHandler, getExistedAddress, getExistedAddressDisplayValue, getFirstMedium, getProductsListParamsFromQuery, getProductsListQueryParams, getProductsPaginationRequest, getProductsSource, getSelectedAddress, getSelectedAddressDisplayValue, getStockAddress, getStockSchedule, getStorage, useAddressFormValue, useArticleCategoriesList, useArticleItem, useArticlesList, useAuthenticationForm, useAuthenticationStatusChecker, useCategories, useCategoriesStore, useCategoriesTree, useCategory, useCategoryFeaturesGroupsList, useCategoryFeaturesList, useCollection, useCollections, useCollectionsStore, useCustomer, useCustomerStore, useDadata, useDataDestroyer, useDataLoader, useDeliveryAddressDestroyer, useDeliveryAddressesList, useEditAddressForm, useFeaturesFilters, useFeaturesGroupsFilters, useFlatCategoriesTree, useItemLoader, useListLoader, useLogin, useLogout, useOrderItem, useOrdersList, usePaginatedLoader, usePasswordReset, usePaymentMethodDestroyer, usePaymentMethodsList, usePhoneConfirmation, useProductsList, useProductsPricesRange, useProductsPricesRangeFilters, useRegistration, useReversedTree, useSplittedCategoriesTree, useStateDataLoader, useStoreStore, useSuggestionsRestrictedToCity };
1952
+ var ZenkyWebsocketEvent;
1953
+ (function (ZenkyWebsocketEvent) {
1954
+ ZenkyWebsocketEvent["OrderPriceRecalculated"] = "orders.price.recalculated";
1955
+ ZenkyWebsocketEvent["OrderMustBeReloaded"] = "orders.reload";
1956
+ ZenkyWebsocketEvent["OrderRewardsMustBeReloaded"] = "orders.rewards.reload";
1957
+ ZenkyWebsocketEvent["DisplayOrderRewardsSelection"] = "orders.rewards.display_selection";
1958
+ ZenkyWebsocketEvent["PromotionsNotFound"] = "orders.promotions.not_found";
1959
+ })(ZenkyWebsocketEvent || (ZenkyWebsocketEvent = {}));
1960
+
1961
+ let instance = null;
1962
+ function createWebsocketsConnection(store) {
1963
+ if (instance !== null) {
1964
+ return instance;
1965
+ }
1966
+ else if (typeof store.settings === 'undefined' || store.settings === null) {
1967
+ throw new Error('You must provide store with settings.');
1968
+ }
1969
+ else if (typeof store.settings.websockets === 'undefined' || store.settings.websockets === null) {
1970
+ throw new Error('You must provide store with websockets settings.');
1971
+ }
1972
+ instance = new Pusher(store.settings.websockets.app_key, {
1973
+ wsHost: store.settings.websockets.options.host,
1974
+ wsPort: store.settings.websockets.options.port,
1975
+ forceTLS: false,
1976
+ enableStats: false,
1977
+ enabledTransports: ['ws', 'wss'],
1978
+ });
1979
+ return instance;
1980
+ }
1981
+ function getWebsocketsConnection() {
1982
+ if (instance === null) {
1983
+ throw new Error('You must create websockets connection using [createWebsocketsConnection] function.');
1984
+ }
1985
+ return instance;
1986
+ }
1987
+ function subscribeToOrderEvents(order) {
1988
+ if (instance === null) {
1989
+ throw new Error('You must create websocket connection using `createWebsocketConnection` function!');
1990
+ }
1991
+ const channel = instance.subscribe(`orders.${order.id}.${order.token}`);
1992
+ channel.bind(ZenkyWebsocketEvent.OrderPriceRecalculated, (data) => {
1993
+ useOrderPriceRecalculated().publish({ order, data });
1994
+ });
1995
+ channel.bind(ZenkyWebsocketEvent.OrderMustBeReloaded, () => {
1996
+ useOrderShouldBeReloaded().publish({ order });
1997
+ });
1998
+ channel.bind(ZenkyWebsocketEvent.OrderRewardsMustBeReloaded, () => {
1999
+ useOrderPromotionRewardsShouldBeReloaded().publish({ order });
2000
+ });
2001
+ channel.bind(ZenkyWebsocketEvent.DisplayOrderRewardsSelection, (data) => {
2002
+ useDisplayOrderPromotionRewardSelection().publish({ order, data });
2003
+ usePromotionsCheckerCompleted().publish();
2004
+ });
2005
+ channel.bind(ZenkyWebsocketEvent.PromotionsNotFound, () => {
2006
+ useOrderPromotionsNotFound().publish({ order });
2007
+ usePromotionsCheckerCompleted().publish();
2008
+ });
2009
+ useOrderSubmitted().subscribe('websockets.subscribe', ({ order: submittedOrder }) => {
2010
+ if (instance === null) {
2011
+ throw new Error('You must create websocket connection using `createWebsocketConnection` function!');
2012
+ }
2013
+ instance.unsubscribe(`orders.${submittedOrder.id}.${submittedOrder.token}`);
2014
+ });
2015
+ }
2016
+
2017
+ export { AuthenticationEvent, AuthenticationResultType, AuthenticationStage, ZenkyInjection, ZenkyWebsocketEvent, createStorage, createWebsocketsConnection, getAddressForm, getApiErrorHandler, getExistedAddress, getExistedAddressDisplayValue, getFirstMedium, getProductsListParamsFromQuery, getProductsListQueryParams, getProductsPaginationRequest, getProductsSource, getSelectedAddress, getSelectedAddressDisplayValue, getStockAddress, getStockSchedule, getStorage, getWebsocketsConnection, subscribeToOrderEvents, useAddressFormValue, useArticleCategoriesList, useArticleItem, useArticlesList, useAuthenticationForm, useAuthenticationStatusChecker, useCategories, useCategoriesStore, useCategoriesTree, useCategory, useCategoryFeaturesGroupsList, useCategoryFeaturesList, useCollection, useCollections, useCollectionsStore, useCustomer, useCustomerStore, useDadata, useDataDestroyer, useDataLoader, useDeliveryAddressDestroyer, useDeliveryAddressesList, useEditAddressForm, useFeaturesFilters, useFeaturesGroupsFilters, useFlatCategoriesTree, useItemLoader, useListLoader, useLogin, useLogout, useOfferItem, useOffersList, useOrderItem, useOrdersList, usePaginatedLoader, usePasswordReset, usePaymentMethodDestroyer, usePaymentMethodsList, usePhoneConfirmation, useProductsList, useProductsPricesRange, useProductsPricesRangeFilters, useRegistration, useReversedTree, useSplittedCategoriesTree, useStateDataLoader, useStoreStore, useSuggestionsRestrictedToCity };
package/dist/zenky.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { Ref, ComputedRef } from 'vue';
2
2
  import * as _zenky_api from '@zenky/api';
3
- import { PaginationRequest, Pagination, PaginatedResponse, ResourceRequest, Address, City, NestedCategory, ProductsCollection, Feature, FeaturesGroupContainer, Article, ArticleCategory, Customer, AuthenticationPhone, Order, OrderCredentials, CustomerPaymentMethod, Medium, Image, Product, ProductsPricesRange, ProductsPaginationRequest, Schedule, Stock, Store, StoreSettings } from '@zenky/api';
3
+ import { PaginationRequest, Pagination, PaginatedResponse, ResourceRequest, Address, City, NestedCategory, ProductsCollection, Feature, FeaturesGroupContainer, Article, ArticleCategory, Customer, AuthenticationPhone, Order, OrderCredentials, CustomerPaymentMethod, Medium, Image, Offer, Product, ProductsPricesRange, ProductsPaginationRequest, Schedule, Stock, Store, StoreSettings } from '@zenky/api';
4
4
  import * as pinia from 'pinia';
5
+ import Pusher from 'pusher-js';
5
6
 
6
7
  declare type ApiErrorHandler = (e: any) => any;
7
8
  declare type OptionalApiErrorHandler = ApiErrorHandler | null | undefined;
@@ -22,7 +23,17 @@ declare enum ZenkyInjection {
22
23
  Category = "zenky:category",
23
24
  CategoryNotFound = "zenky:category:notFound",
24
25
  Collection = "zenky:collection",
25
- CollectionNotFound = "zenky:collection:notFound"
26
+ CollectionNotFound = "zenky:collection:notFound",
27
+ Offer = "zenky:offer",
28
+ OfferNotFound = "zenky:offer:notFound",
29
+ CategoryContext = "zenky:context:category",
30
+ CategoryContextNotFound = "zenky:context:category:notFound",
31
+ GroupContext = "zenky:context:category",
32
+ GroupContextNotFound = "zenky:context:category:notFound",
33
+ VariantOptionContext = "zenky:context:variant_option",
34
+ VariantOptionContextNotFound = "zenky:context:variant_option:notFound",
35
+ VariantOptionValueContext = "zenky:context:variant_option_value",
36
+ VariantOptionValueContextNotFound = "zenky:context:variant_option_value:notFound"
26
37
  }
27
38
 
28
39
  interface LoaderState {
@@ -1049,9 +1060,16 @@ declare const useCustomerStore: pinia.StoreDefinition<"zenky:storefront:customer
1049
1060
 
1050
1061
  declare function getFirstMedium(media: Medium | Medium[], sizes?: string[], preferWebp?: boolean): Image | null;
1051
1062
 
1063
+ declare function useOffersList(errorHandler?: OptionalApiErrorHandler): PaginatedLoader<Offer>;
1064
+ declare function useOfferItem(errorHandler?: OptionalApiErrorHandler): ItemLoader<Offer>;
1065
+
1052
1066
  declare enum ProductsSourceType {
1053
1067
  Category = "category",
1054
- Collection = "collection"
1068
+ Collection = "collection",
1069
+ CategoryContext = "category_context",
1070
+ GroupContext = "group_context",
1071
+ VariantOptionContext = "variant_option_context",
1072
+ VariantOptionValueContext = "variant_option_value_context"
1055
1073
  }
1056
1074
  declare enum ProductsSorting {
1057
1075
  Manual = "manual",
@@ -1084,6 +1102,7 @@ interface ProductsLoader {
1084
1102
  count: number;
1085
1103
  };
1086
1104
  with?: string;
1105
+ promotion?: ProductsPromotion | null;
1087
1106
  }
1088
1107
  declare type ProductsRequestCallback = (request: ProductsPaginationRequest | null) => void;
1089
1108
  interface ProductsListProvider {
@@ -1104,6 +1123,12 @@ declare enum ProductsFiltersType {
1104
1123
  Features = "features",
1105
1124
  FeaturesGroups = "featuresGroups"
1106
1125
  }
1126
+ interface ProductsPromotion {
1127
+ id: string;
1128
+ reward_id: string;
1129
+ context_type: string | null;
1130
+ context_id: string | null;
1131
+ }
1107
1132
  interface ProductsListConfig {
1108
1133
  source: ProductsSource | null;
1109
1134
  search?: string | null;
@@ -1113,6 +1138,7 @@ interface ProductsListConfig {
1113
1138
  count: number;
1114
1139
  filtersType: ProductsFiltersType | null;
1115
1140
  with?: string;
1141
+ promotion?: ProductsPromotion | null;
1116
1142
  }
1117
1143
 
1118
1144
  declare function useFeaturesFilters(categoryId: string | null, values: ProductsFilters | null): {
@@ -1164,4 +1190,16 @@ declare const useStoreStore: pinia.StoreDefinition<"zenky:storefront:store", Sto
1164
1190
  selectCity(cityId: string): City | null;
1165
1191
  }>;
1166
1192
 
1167
- export { AddressForm, AddressFormValue, AddressFormValueProvider, ApiErrorHandler, AuthenticationEvent, AuthenticationForm, AuthenticationFormProvider, AuthenticationResult, AuthenticationResultType, AuthenticationStage, AuthenticationStatusCheckerProvider, CategoriesProvider, CategoriesState, CategoriesTreeProvider, CategoryProvider, CollectionsState, ConfirmableDataDestroyer, ConfirmationProvider, CustomerStore, DadataProvider, DataDestroyer, DataDestroyerHandler, DataLoader, DataProvider, EditAddressFormProvider, EmitAuthenticationEvent, FlatCategoriesTreeProvider, FlattenNestedCategory, ItemLoader, ItemProvider, ListLoader, ListProvider, LoaderState, LoginProvider, LogoutProvider, OptionalApiErrorHandler, PaginatedItemsProvider, PaginatedLoader, PaginatedLoaderState, PasswordResetProvider, ProductsCollectionProvider, ProductsCollectionsProvider, RegistrationProvider, ReversedTreeProvider, SplittedCategoriesTreeProvider, StateDataLoader, StateDataLoaderState, StoreState, ZenkyInjection, ZenkyStorage, createStorage, getAddressForm, getApiErrorHandler, getExistedAddress, getExistedAddressDisplayValue, getFirstMedium, getProductsListParamsFromQuery, getProductsListQueryParams, getProductsPaginationRequest, getProductsSource, getSelectedAddress, getSelectedAddressDisplayValue, getStockAddress, getStockSchedule, getStorage, useAddressFormValue, useArticleCategoriesList, useArticleItem, useArticlesList, useAuthenticationForm, useAuthenticationStatusChecker, useCategories, useCategoriesStore, useCategoriesTree, useCategory, useCategoryFeaturesGroupsList, useCategoryFeaturesList, useCollection, useCollections, useCollectionsStore, useCustomer, useCustomerStore, useDadata, useDataDestroyer, useDataLoader, useDeliveryAddressDestroyer, useDeliveryAddressesList, useEditAddressForm, useFeaturesFilters, useFeaturesGroupsFilters, useFlatCategoriesTree, useItemLoader, useListLoader, useLogin, useLogout, useOrderItem, useOrdersList, usePaginatedLoader, usePasswordReset, usePaymentMethodDestroyer, usePaymentMethodsList, usePhoneConfirmation, useProductsList, useProductsPricesRange, useProductsPricesRangeFilters, useRegistration, useReversedTree, useSplittedCategoriesTree, useStateDataLoader, useStoreStore, useSuggestionsRestrictedToCity };
1193
+ declare enum ZenkyWebsocketEvent {
1194
+ OrderPriceRecalculated = "orders.price.recalculated",
1195
+ OrderMustBeReloaded = "orders.reload",
1196
+ OrderRewardsMustBeReloaded = "orders.rewards.reload",
1197
+ DisplayOrderRewardsSelection = "orders.rewards.display_selection",
1198
+ PromotionsNotFound = "orders.promotions.not_found"
1199
+ }
1200
+
1201
+ declare function createWebsocketsConnection(store: Store): Pusher;
1202
+ declare function getWebsocketsConnection(): Pusher;
1203
+ declare function subscribeToOrderEvents(order: Order): void;
1204
+
1205
+ export { AddressForm, AddressFormValue, AddressFormValueProvider, ApiErrorHandler, AuthenticationEvent, AuthenticationForm, AuthenticationFormProvider, AuthenticationResult, AuthenticationResultType, AuthenticationStage, AuthenticationStatusCheckerProvider, CategoriesProvider, CategoriesState, CategoriesTreeProvider, CategoryProvider, CollectionsState, ConfirmableDataDestroyer, ConfirmationProvider, CustomerStore, DadataProvider, DataDestroyer, DataDestroyerHandler, DataLoader, DataProvider, EditAddressFormProvider, EmitAuthenticationEvent, FlatCategoriesTreeProvider, FlattenNestedCategory, ItemLoader, ItemProvider, ListLoader, ListProvider, LoaderState, LoginProvider, LogoutProvider, OptionalApiErrorHandler, PaginatedItemsProvider, PaginatedLoader, PaginatedLoaderState, PasswordResetProvider, ProductsCollectionProvider, ProductsCollectionsProvider, RegistrationProvider, ReversedTreeProvider, SplittedCategoriesTreeProvider, StateDataLoader, StateDataLoaderState, StoreState, ZenkyInjection, ZenkyStorage, ZenkyWebsocketEvent, createStorage, createWebsocketsConnection, getAddressForm, getApiErrorHandler, getExistedAddress, getExistedAddressDisplayValue, getFirstMedium, getProductsListParamsFromQuery, getProductsListQueryParams, getProductsPaginationRequest, getProductsSource, getSelectedAddress, getSelectedAddressDisplayValue, getStockAddress, getStockSchedule, getStorage, getWebsocketsConnection, subscribeToOrderEvents, useAddressFormValue, useArticleCategoriesList, useArticleItem, useArticlesList, useAuthenticationForm, useAuthenticationStatusChecker, useCategories, useCategoriesStore, useCategoriesTree, useCategory, useCategoryFeaturesGroupsList, useCategoryFeaturesList, useCollection, useCollections, useCollectionsStore, useCustomer, useCustomerStore, useDadata, useDataDestroyer, useDataLoader, useDeliveryAddressDestroyer, useDeliveryAddressesList, useEditAddressForm, useFeaturesFilters, useFeaturesGroupsFilters, useFlatCategoriesTree, useItemLoader, useListLoader, useLogin, useLogout, useOfferItem, useOffersList, useOrderItem, useOrdersList, usePaginatedLoader, usePasswordReset, usePaymentMethodDestroyer, usePaymentMethodsList, usePhoneConfirmation, useProductsList, useProductsPricesRange, useProductsPricesRangeFilters, useRegistration, useReversedTree, useSplittedCategoriesTree, useStateDataLoader, useStoreStore, useSuggestionsRestrictedToCity };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenky/storefront-vue",
3
- "version": "0.9.32",
3
+ "version": "0.9.35",
4
4
  "description": "Zenky Storefront library for Vue 3.",
5
5
  "author": "Timur Zurbaev <hello@zurbaev.ru>",
6
6
  "license": "MIT",
@@ -19,11 +19,12 @@
19
19
  "Zenky"
20
20
  ],
21
21
  "peerDependencies": {
22
- "@zenky/api": "^0.9.37",
23
- "@zenky/events": "^1.0.0",
22
+ "@zenky/api": "^0.9.41",
23
+ "@zenky/events": "^1.0.2",
24
24
  "@zenky/ui": "^0.9.63",
25
25
  "lodash-es": "^4.17.21",
26
26
  "pinia": "^2.0.14",
27
+ "pusher-js": "^7.1.1-beta",
27
28
  "vue": "^3.2.36"
28
29
  },
29
30
  "devDependencies": {