@mframework/layer-commerce 0.0.3

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 (355) hide show
  1. package/README.md +101 -0
  2. package/app/cart/useCart.ts +1 -0
  3. package/app/components/ChevronIcon/ChevronIcon.config.ts +17 -0
  4. package/app/components/DateSelect/DateSelect.config.ts +15 -0
  5. package/app/components/Field/Field.config.ts +14 -0
  6. package/app/components/FieldDate/FieldDate.config.ts +16 -0
  7. package/app/components/Form/Form.type.ts +8 -0
  8. package/app/components/Product/Product.config.ts +19 -0
  9. package/app/components/Product/Stock.config.ts +15 -0
  10. package/app/components/ProductCustomizableOption/ProductCustomizableOption.config.ts +5 -0
  11. package/app/components/ProductGallery/ProductGallery.config.ts +15 -0
  12. package/app/components/ProductReviews/ProductReviews.config.ts +8 -0
  13. package/app/composables/_types.ts +18 -0
  14. package/app/composables/adapters/abstract/cartAdapter.ts +0 -0
  15. package/app/composables/adapters/abstract/categoryAdapter.ts +0 -0
  16. package/app/composables/adapters/abstract/customerAdapter.ts +0 -0
  17. package/app/composables/adapters/abstract/inventoryAdapter.ts +0 -0
  18. package/app/composables/adapters/abstract/orderAdapter.ts +0 -0
  19. package/app/composables/adapters/abstract/productAdapter.ts +7 -0
  20. package/app/composables/cart/registry.ts +20 -0
  21. package/app/composables/cart/types.ts +18 -0
  22. package/app/composables/cart/useCart.ts +15 -0
  23. package/app/composables/config.ts +19 -0
  24. package/app/composables/defs/apiDefinitions.ts +55 -0
  25. package/app/composables/defs/extension.feature +40 -0
  26. package/app/composables/defs/extension.mocks.ts +39 -0
  27. package/app/composables/defs/extension.test.ts +280 -0
  28. package/app/composables/defs/extension.ts +236 -0
  29. package/app/composables/defs/index.ts +3 -0
  30. package/app/composables/defs/typeHelpers.ts +8 -0
  31. package/app/composables/defs/types.ts +136 -0
  32. package/app/composables/domain/product.ts +12 -0
  33. package/app/composables/featured-products.ts +20 -0
  34. package/app/composables/helpers/contextualizedNormalizers.feature +14 -0
  35. package/app/composables/helpers/contextualizedNormalizers.test.ts +85 -0
  36. package/app/composables/helpers/contextualizedNormalizers.ts +20 -0
  37. package/app/composables/helpers/index.ts +1 -0
  38. package/app/composables/index.ts +9 -0
  39. package/app/composables/methods/auth.ts +83 -0
  40. package/app/composables/methods/cart.ts +119 -0
  41. package/app/composables/methods/category.ts +27 -0
  42. package/app/composables/methods/checkout.ts +54 -0
  43. package/app/composables/methods/customer.ts +52 -0
  44. package/app/composables/methods/helpers.ts +5 -0
  45. package/app/composables/methods/index.ts +75 -0
  46. package/app/composables/methods/order.ts +39 -0
  47. package/app/composables/methods/product.ts +95 -0
  48. package/app/composables/methods/settings.ts +16 -0
  49. package/app/composables/models/cart.ts +95 -0
  50. package/app/composables/models/category.ts +13 -0
  51. package/app/composables/models/checkout.ts +17 -0
  52. package/app/composables/models/customer.ts +16 -0
  53. package/app/composables/models/facets.ts +25 -0
  54. package/app/composables/models/index.ts +94 -0
  55. package/app/composables/models/order.ts +43 -0
  56. package/app/composables/models/product.ts +73 -0
  57. package/app/composables/models/shared.ts +75 -0
  58. package/app/composables/orders.ts +69 -0
  59. package/app/composables/products/registry.ts +86 -0
  60. package/app/composables/products/types.ts +8 -0
  61. package/app/composables/products/useEvents.ts +26 -0
  62. package/app/composables/products/useGiftCards.ts +29 -0
  63. package/app/composables/products/useProducts.ts +12 -0
  64. package/app/composables/products/useSubscriptions.ts +29 -0
  65. package/app/composables/products.ts +30 -0
  66. package/app/composables/registry.ts +24 -0
  67. package/app/composables/useAuth.ts +43 -0
  68. package/app/composables/useBreakpoints/index.ts +1 -0
  69. package/app/composables/useBreakpoints/useBreakpoints.ts +28 -0
  70. package/app/composables/useCache.ts +38 -0
  71. package/app/composables/useCart/__tests__/useCart.spec.ts +11 -0
  72. package/app/composables/useCart/index.ts +1 -0
  73. package/app/composables/useCart/types.ts +17 -0
  74. package/app/composables/useCart/useCart.ts +46 -0
  75. package/app/composables/useCartShippingMethods/__tests__/useCartShippingMethods.spec.ts +11 -0
  76. package/app/composables/useCartShippingMethods/index.ts +1 -0
  77. package/app/composables/useCartShippingMethods/types.ts +17 -0
  78. package/app/composables/useCartShippingMethods/useCartShippingMethods.ts +47 -0
  79. package/app/composables/useCatalog.ts +26 -0
  80. package/app/composables/useContent.ts +26 -0
  81. package/app/composables/useCustomer/__tests__/useCustomer.spec.ts +25 -0
  82. package/app/composables/useCustomer/index.ts +2 -0
  83. package/app/composables/useCustomer/types.ts +17 -0
  84. package/app/composables/useCustomer/useCustomer.ts +40 -0
  85. package/app/composables/useCustomerAddress/__tests__/useCustomerAddress.spec.ts +11 -0
  86. package/app/composables/useCustomerAddress/index.ts +2 -0
  87. package/app/composables/useCustomerAddress/types.ts +17 -0
  88. package/app/composables/useCustomerAddress/useCustomerAddress.ts +55 -0
  89. package/app/composables/useCustomerOrder/__tests__/useCustomerOrder.spec.ts +11 -0
  90. package/app/composables/useCustomerOrder/adress.ts +10 -0
  91. package/app/composables/useCustomerOrder/index.ts +2 -0
  92. package/app/composables/useCustomerOrder/product.ts +37 -0
  93. package/app/composables/useCustomerOrder/types.ts +40 -0
  94. package/app/composables/useCustomerOrder/useCustomerOrder.ts +63 -0
  95. package/app/composables/useCustomerOrders/__tests__/useCustomerOrders.spec.ts +11 -0
  96. package/app/composables/useCustomerOrders/index.ts +2 -0
  97. package/app/composables/useCustomerOrders/types.ts +20 -0
  98. package/app/composables/useCustomerOrders/useCustomerOrders.ts +56 -0
  99. package/app/composables/useCustomerReturns/__tests__/useCustomerReturns.spec.ts +11 -0
  100. package/app/composables/useCustomerReturns/index.ts +2 -0
  101. package/app/composables/useCustomerReturns/types.ts +17 -0
  102. package/app/composables/useCustomerReturns/useCustomerReturns.ts +41 -0
  103. package/app/composables/useHandleError/index.ts +1 -0
  104. package/app/composables/useHandleError/types.ts +11 -0
  105. package/app/composables/useHandleError/useHandleError.ts +27 -0
  106. package/app/composables/useInventory.ts +29 -0
  107. package/app/composables/useLoading.ts +21 -0
  108. package/app/composables/useNotification.ts +21 -0
  109. package/app/composables/usePageTitle.ts +20 -0
  110. package/app/composables/useProduct/index.ts +2 -0
  111. package/app/composables/useProduct/types.ts +17 -0
  112. package/app/composables/useProduct/useProduct.ts +42 -0
  113. package/app/composables/useProductAttribute/__tests__/useProduct.mock.ts +31 -0
  114. package/app/composables/useProductAttribute/__tests__/useProductAttribute.spec.ts +14 -0
  115. package/app/composables/useProductAttribute/index.ts +1 -0
  116. package/app/composables/useProductAttribute/useProductAttribute.ts +37 -0
  117. package/app/composables/useProductRecommended/__tests__/useProductRecommended.spec.ts +12 -0
  118. package/app/composables/useProductRecommended/index.ts +1 -0
  119. package/app/composables/useProductRecommended/types.ts +17 -0
  120. package/app/composables/useProductRecommended/useProductRecommended.ts +43 -0
  121. package/app/composables/useProductReviews/__tests__/productReviews.mock.ts +20 -0
  122. package/app/composables/useProductReviews/__tests__/useProductReviews.spec.ts +22 -0
  123. package/app/composables/useProductReviews/index.ts +2 -0
  124. package/app/composables/useProductReviews/types.ts +17 -0
  125. package/app/composables/useProductReviews/useProductReviews.ts +46 -0
  126. package/app/composables/useProducts/__tests__/useProducts.spec.ts +11 -0
  127. package/app/composables/useProducts/types.ts +22 -0
  128. package/app/composables/useProducts/useProducts.ts +41 -0
  129. package/app/composables/useTax.ts +27 -0
  130. package/app/composables/validationRules/index.ts +1 -0
  131. package/app/composables/validationRules/password.feature +67 -0
  132. package/app/composables/validationRules/password.test.ts +89 -0
  133. package/app/composables/validationRules/password.ts +25 -0
  134. package/app/normalizers/Cart.query.ts +729 -0
  135. package/app/normalizers/Cart.type.ts +285 -0
  136. package/app/normalizers/Category.query.ts +146 -0
  137. package/app/normalizers/Category.type.ts +55 -0
  138. package/app/normalizers/CheckEmail.query.ts +28 -0
  139. package/app/normalizers/Checkout.query.ts +253 -0
  140. package/app/normalizers/Checkout.type.ts +77 -0
  141. package/app/normalizers/CmsBlock.query.ts +57 -0
  142. package/app/normalizers/CmsBlock.type.ts +25 -0
  143. package/app/normalizers/CmsPage.query.ts +59 -0
  144. package/app/normalizers/CmsPage.type.ts +26 -0
  145. package/app/normalizers/Config.query.ts +224 -0
  146. package/app/normalizers/Config.type.ts +196 -0
  147. package/app/normalizers/ContactForm.query.ts +49 -0
  148. package/app/normalizers/CreditMemo.type.ts +49 -0
  149. package/app/normalizers/GiftCard.type.ts +24 -0
  150. package/app/normalizers/Invoice.type.ts +58 -0
  151. package/app/normalizers/Menu.query.ts +54 -0
  152. package/app/normalizers/Menu.type.ts +22 -0
  153. package/app/normalizers/MyAccount.query.ts +268 -0
  154. package/app/normalizers/MyAccount.type.ts +129 -0
  155. package/app/normalizers/NewsletterSubscription.query.ts +38 -0
  156. package/app/normalizers/Order.query.ts +741 -0
  157. package/app/normalizers/Order.type.ts +268 -0
  158. package/app/normalizers/Payment.type.ts +28 -0
  159. package/app/normalizers/ProductAlerts.query.ts +23 -0
  160. package/app/normalizers/ProductCompare.query.ts +226 -0
  161. package/app/normalizers/ProductCompare.type.ts +90 -0
  162. package/app/normalizers/ProductList.query.ts +1620 -0
  163. package/app/normalizers/ProductList.type.ts +726 -0
  164. package/app/normalizers/Region.query.ts +58 -0
  165. package/app/normalizers/Region.type.ts +23 -0
  166. package/app/normalizers/Return.type.ts +50 -0
  167. package/app/normalizers/Review.query.ts +81 -0
  168. package/app/normalizers/Review.type.ts +42 -0
  169. package/app/normalizers/Slider.query.ts +72 -0
  170. package/app/normalizers/Slider.type.ts +26 -0
  171. package/app/normalizers/StoreInPickUp.query.ts +54 -0
  172. package/app/normalizers/StoreInPickUp.type.ts +59 -0
  173. package/app/normalizers/Subscription.type.ts +25 -0
  174. package/app/normalizers/Transaction.type.ts +20 -0
  175. package/app/normalizers/UrlRewrites.query.ts +55 -0
  176. package/app/normalizers/UrlRewrites.type.ts +25 -0
  177. package/app/normalizers/Wishlist.query.ts +202 -0
  178. package/app/normalizers/Wishlist.type.ts +42 -0
  179. package/app/pages/brand/[...slug].vue +76 -0
  180. package/app/pages/brands.vue +67 -0
  181. package/app/pages/cart.vue +142 -0
  182. package/app/pages/compare.vue +166 -0
  183. package/app/pages/departments/[...slug].vue +353 -0
  184. package/app/pages/departments/category/[...slug].vue +114 -0
  185. package/app/pages/incentive/[...id].vue +66 -0
  186. package/app/pages/invoice/[id].vue +309 -0
  187. package/app/pages/order/[id].vue +327 -0
  188. package/app/pages/product/[...id].vue +309 -0
  189. package/app/pages/product/showcases/index.vue +86 -0
  190. package/app/pages/shipment/[...id].vue +176 -0
  191. package/app/pages/shop/[...slug].vue +158 -0
  192. package/app/pages/shops.vue +76 -0
  193. package/app/pages/subscription/[...id].vue +147 -0
  194. package/app/pages/transaction/[...id].vue +74 -0
  195. package/app/routes/CategoryPage/CategoryPage.config.ts +28 -0
  196. package/app/routes/CategoryPage/CategoryPage.type.ts +8 -0
  197. package/app/routes/Checkout/Checkout.config.ts +3 -0
  198. package/app/routes/Checkout/Checkout.type.ts +14 -0
  199. package/app/routes/MyAccount/MyAccount.config.ts +1 -0
  200. package/app/routes/SearchPage/SearchPage.config.ts +1 -0
  201. package/app/routes/UrlRewrites/UrlRewrites.config.ts +5 -0
  202. package/app/stores/Cart/Cart.type.ts +26 -0
  203. package/app/stores/MyAccount/MyAccount.action.ts +7 -0
  204. package/app/stores/Notification/Notification.action.ts +40 -0
  205. package/app/stores/Notification/Notification.type.ts +16 -0
  206. package/app/stores/Popup/Popup.action.ts +30 -0
  207. package/app/stores/Product/Product.dispatcher.ts +53 -0
  208. package/app/stores/Product/Product.reducer.ts +12 -0
  209. package/app/stores/ProductList/ProductList.dispatcher.ts +35 -0
  210. package/app/stores/ProductList/ProductList.reducer.ts +13 -0
  211. package/app/stores/Store.type.ts +31 -0
  212. package/app/stores/Wishlist/Wishlist.type.ts +12 -0
  213. package/app/stores/cart.ts +218 -0
  214. package/app/stores/cartStore.ts +224 -0
  215. package/app/stores/checkout.ts +18 -0
  216. package/app/stores/compare.ts +65 -0
  217. package/app/stores/currency.js +29 -0
  218. package/app/stores/digital-products.js +11 -0
  219. package/app/stores/orders.ts +172 -0
  220. package/app/stores/product.ts +34 -0
  221. package/app/stores/productList.ts +35 -0
  222. package/app/stores/productListInfo.ts +0 -0
  223. package/app/stores/products.ts +118 -0
  224. package/app/stores/recentlyViewedProducts.ts +56 -0
  225. package/app/stores/review.ts +33 -0
  226. package/app/stores/storeInPickUp.ts +21 -0
  227. package/app/stores/user.ts +20 -0
  228. package/app/stores/wishlist.ts +46 -0
  229. package/app/types/Account.type.ts +141 -0
  230. package/app/types/Breadcrumbs.type.ts +23 -0
  231. package/app/types/CMS.type.ts +33 -0
  232. package/app/types/Category.type.ts +67 -0
  233. package/app/types/Checkout.type.ts +58 -0
  234. package/app/types/Common.type.ts +77 -0
  235. package/app/types/Config.type.ts +47 -0
  236. package/app/types/Device.type.ts +37 -0
  237. package/app/types/Direction.type.ts +23 -0
  238. package/app/types/Downloadable.type.ts +24 -0
  239. package/app/types/Error.type.ts +22 -0
  240. package/app/types/Field.type.ts +151 -0
  241. package/app/types/Global.type.ts +156 -0
  242. package/app/types/Graphql.type.ts +4497 -0
  243. package/app/types/Layout.type.ts +18 -0
  244. package/app/types/Menu.type.ts +39 -0
  245. package/app/types/MiniCart.type.ts +61 -0
  246. package/app/types/NotificationList.type.ts +34 -0
  247. package/app/types/Order.type.ts +174 -0
  248. package/app/types/Price.type.ts +72 -0
  249. package/app/types/ProductCompare.type.ts +24 -0
  250. package/app/types/ProductList.type.ts +351 -0
  251. package/app/types/Rating.type.ts +42 -0
  252. package/app/types/Router.type.ts +67 -0
  253. package/app/types/Slider.type.ts +25 -0
  254. package/app/types/StockStatus.type.ts +21 -0
  255. package/app/types/domain/index.ts +94 -0
  256. package/app/types/index.ts +33 -0
  257. package/app/types/shims.d.ts +52 -0
  258. package/app/types/tilework-opus.d.ts +48 -0
  259. package/app/utils/Address/Address.type.ts +28 -0
  260. package/app/utils/Address/index.ts +325 -0
  261. package/app/utils/Auth/IsSignedIn.ts +4 -0
  262. package/app/utils/Auth/Token.ts +9 -0
  263. package/app/utils/Base64/Base64.ts +16 -0
  264. package/app/utils/Base64/index.ts +12 -0
  265. package/app/utils/Browser/Browser.ts +29 -0
  266. package/app/utils/Browser/index.ts +12 -0
  267. package/app/utils/BrowserDatabase/BrowserDatabase.ts +70 -0
  268. package/app/utils/BrowserDatabase/index.ts +12 -0
  269. package/app/utils/CSS/CSS.ts +65 -0
  270. package/app/utils/CSS/index.ts +12 -0
  271. package/app/utils/Cache/Cache.ts +99 -0
  272. package/app/utils/Cart/Cart.ts +300 -0
  273. package/app/utils/Cart/Cart.type.ts +76 -0
  274. package/app/utils/Cart/Token.ts +59 -0
  275. package/app/utils/Cart/index.ts +13 -0
  276. package/app/utils/Category/Filters.ts +39 -0
  277. package/app/utils/Category/index.ts +12 -0
  278. package/app/utils/Common/index.ts +32 -0
  279. package/app/utils/Compare/Compare.ts +89 -0
  280. package/app/utils/Compare/index.ts +12 -0
  281. package/app/utils/Currency/Currency.ts +84 -0
  282. package/app/utils/Currency/index.ts +12 -0
  283. package/app/utils/DynamicReducer/DynamicReducer.type.ts +14 -0
  284. package/app/utils/DynamicReducer/Helper.ts +30 -0
  285. package/app/utils/DynamicReducer/index.tsx +35 -0
  286. package/app/utils/ElementTransition/ElementTransition.ts +100 -0
  287. package/app/utils/Form/Extract.ts +316 -0
  288. package/app/utils/Form/Form.ts +46 -0
  289. package/app/utils/Form/Form.type.ts +60 -0
  290. package/app/utils/Form/Transform.ts +33 -0
  291. package/app/utils/FormPortalCollector/index.ts +45 -0
  292. package/app/utils/History/History.type.ts +31 -0
  293. package/app/utils/History/index.ts +17 -0
  294. package/app/utils/Manipulations/Array.ts +18 -0
  295. package/app/utils/Manipulations/Date.ts +36 -0
  296. package/app/utils/Manipulations/index.ts +14 -0
  297. package/app/utils/Media/Media.ts +27 -0
  298. package/app/utils/Media/index.ts +13 -0
  299. package/app/utils/Menu/Menu.ts +116 -0
  300. package/app/utils/Menu/Menu.type.ts +37 -0
  301. package/app/utils/Menu/index.ts +12 -0
  302. package/app/utils/Mobile/index.ts +13 -0
  303. package/app/utils/Mobile/isMobile.ts +34 -0
  304. package/app/utils/Orders/Orders.ts +71 -0
  305. package/app/utils/Orders/Orders.type.ts +19 -0
  306. package/app/utils/Orders/index.ts +13 -0
  307. package/app/utils/Polyfill/index.ts +336 -0
  308. package/app/utils/Preload/CategoryPreload.ts +74 -0
  309. package/app/utils/Preload/ProductPreload.ts +28 -0
  310. package/app/utils/Preload/index.ts +75 -0
  311. package/app/utils/Price/Price.config.ts +189 -0
  312. package/app/utils/Price/Price.ts +63 -0
  313. package/app/utils/Price/index.ts +12 -0
  314. package/app/utils/Product/Extract.ts +652 -0
  315. package/app/utils/Product/Product.ts +575 -0
  316. package/app/utils/Product/Product.type.ts +260 -0
  317. package/app/utils/Product/Transform.ts +382 -0
  318. package/app/utils/Product/index.ts +12 -0
  319. package/app/utils/Promise/MakeCancelable.ts +44 -0
  320. package/app/utils/Promise/Promise.type.ts +15 -0
  321. package/app/utils/Promise/index.ts +13 -0
  322. package/app/utils/Query/Field.ts +71 -0
  323. package/app/utils/Query/Fragment.ts +22 -0
  324. package/app/utils/Query/PrepareDocument.ts +119 -0
  325. package/app/utils/Query/Query.type.ts +26 -0
  326. package/app/utils/Query/index.ts +15 -0
  327. package/app/utils/Request/Config.ts +21 -0
  328. package/app/utils/Request/DataContainer.ts +102 -0
  329. package/app/utils/Request/Debounce.ts +48 -0
  330. package/app/utils/Request/Error.ts +31 -0
  331. package/app/utils/Request/Hash.ts +88 -0
  332. package/app/utils/Request/LowPriorityLoad.ts +32 -0
  333. package/app/utils/Request/LowPriorityRender.ts +55 -0
  334. package/app/utils/Request/Mutation.ts +25 -0
  335. package/app/utils/Request/Query.ts +25 -0
  336. package/app/utils/Request/QueryDispatcher.ts +135 -0
  337. package/app/utils/Request/Request.ts +310 -0
  338. package/app/utils/Store/Store.type.ts +26 -0
  339. package/app/utils/Store/index.ts +71 -0
  340. package/app/utils/Url/Url.ts +297 -0
  341. package/app/utils/Url/index.ts +12 -0
  342. package/app/utils/Validator/Config.ts +96 -0
  343. package/app/utils/Validator/Validator.ts +268 -0
  344. package/app/utils/Validator/Validator.type.ts +47 -0
  345. package/app/utils/Validator/index.ts +12 -0
  346. package/app/utils/Wishlist/Wishlist.ts +65 -0
  347. package/app/utils/Wishlist/index.ts +12 -0
  348. package/app/utils/client.ts +280 -0
  349. package/app/utils/index.ts +53 -0
  350. package/app/utils/normalizer.ts +23 -0
  351. package/app/utils/normalizers/magento.ts +29 -0
  352. package/app/utils/normalizers/shopify.ts +29 -0
  353. package/nuxt.config.ts +11 -0
  354. package/package.json +43 -0
  355. package/tsconfig.json +45 -0
@@ -0,0 +1,652 @@
1
+ // TODO remove eslint disable
2
+ /* eslint-disable no-magic-numbers */
3
+ /* eslint-disable @typescript-eslint/no-shadow */
4
+ /**
5
+ * M Framework - Flexible backend agnostic framework.
6
+ *
7
+ * Copyright © Meeovi, LTD. All rights reserved.
8
+ * See LICENSE for license details.
9
+ *
10
+ * @license OSL-3.0 (Open Software License ("OSL") v. 3.0)
11
+ * @package mframework/mframework
12
+ * @link https://github.com/meeovi/mframework
13
+ */
14
+
15
+ import { ProductType } from 'Component/Product/Product.config';
16
+ import { ImageType } from 'Component/ProductGallery/ProductGallery.config';
17
+ import {
18
+ GroupedProductItem,
19
+ Money,
20
+ PriceRange,
21
+ } from '../../normalizers/ProductList.type';
22
+ import { GQLCurrencyEnum, GQLProductStockStatus } from '../../types/Graphql.type';
23
+ import { decodeBase64 } from '../../utils/Base64';
24
+ import { FieldValue } from '../../utils/Form/Form.type';
25
+ import { formatPrice } from '../../utils/Price';
26
+ import { AdjustedPriceMap, ProductOption } from '../../utils/Product/Product.type';
27
+
28
+ import {
29
+ DEFAULT_MAX_PRODUCTS,
30
+ DEFAULT_MIN_PRODUCTS,
31
+ IndexedBundleItem,
32
+ IndexedBundleOption,
33
+ IndexedProduct,
34
+ IndexedVariant,
35
+ ProductExtractImage,
36
+ ProductExtractPrice,
37
+ QtyFields,
38
+ StockCheckProduct,
39
+ } from './Product.type';
40
+
41
+ // TODO unify keyof product and stockitem.
42
+ /** @namespace ../../utils/Product/Extract/getFieldQty */
43
+ export const getFieldQty = (
44
+ product: Partial<IndexedProduct> | Partial<IndexedVariant>,
45
+ field: QtyFields,
46
+ ): number => {
47
+ if (field === QtyFields.MIN_SALE_QTY || field === QtyFields.MAX_SALE_QTY) {
48
+ const { stock_item: { [field]: qty = 0 } = {} } = product;
49
+
50
+ return qty;
51
+ }
52
+
53
+ const { [field]: qty } = product;
54
+
55
+ return qty || 0;
56
+ };
57
+
58
+ /**
59
+ * Returns product quantity for specific field (with fallback value)
60
+ * @param product
61
+ * @param defaultValue
62
+ * @param field
63
+ * @param configIndex
64
+ * @returns {*}
65
+ * @namespace ../../utils/Product/Extract/getQuantity
66
+ */
67
+ export const getQuantity = (
68
+ product: IndexedProduct,
69
+ defaultValue: number,
70
+ field: QtyFields,
71
+ configIndex = -1,
72
+ ): number => {
73
+ if (!product) {
74
+ return defaultValue;
75
+ }
76
+
77
+ const qty = getFieldQty(product, field);
78
+
79
+ if (!qty) {
80
+ return defaultValue;
81
+ }
82
+
83
+ const { variants } = product;
84
+
85
+ if ((!configIndex && !variants) || configIndex === -1 || typeof variants === 'undefined') {
86
+ return qty;
87
+ }
88
+
89
+ const variantQty = getFieldQty(variants[configIndex], field);
90
+
91
+ return variantQty || qty;
92
+ };
93
+
94
+ /**
95
+ * Returns minimum purchasable item quantity
96
+ * @param product
97
+ * @param configIndex
98
+ * @returns {*}
99
+ * @namespace ../../utils/Product/Extract/getMinQuantity
100
+ */
101
+ export const getMinQuantity = (product: IndexedProduct, configIndex = -1): number => (
102
+ getQuantity(product, DEFAULT_MIN_PRODUCTS, QtyFields.MIN_SALE_QTY, configIndex)
103
+ );
104
+
105
+ /**
106
+ * Returns maximum purchasable item quantity.
107
+ * @param product
108
+ * @param configIndex
109
+ * @returns {*}
110
+ * @namespace ../../utils/Product/Extract/getMaxQuantity
111
+ */
112
+ export const getMaxQuantity = (product: IndexedProduct, configIndex = -1): number => {
113
+ const maxQuantity: number = getQuantity(
114
+ product,
115
+ DEFAULT_MAX_PRODUCTS,
116
+ QtyFields.MAX_SALE_QTY,
117
+ configIndex,
118
+ );
119
+ const salableQuantity: number = getQuantity(
120
+ product,
121
+ DEFAULT_MAX_PRODUCTS,
122
+ QtyFields.SALABLE_QTY,
123
+ configIndex,
124
+ );
125
+
126
+ return Math.min(maxQuantity, salableQuantity);
127
+ };
128
+
129
+ /**
130
+ * Returns active products name
131
+ * @param product
132
+ * @param configIndex
133
+ * @returns {*}
134
+ * @namespace ../../utils/Product/Extract/getName
135
+ */
136
+ export const getName = (product: IndexedProduct, configIndex = -1): string => {
137
+ const { variants = [] } = product;
138
+
139
+ const {
140
+ name = '',
141
+ } = variants[configIndex] || product;
142
+
143
+ return name;
144
+ };
145
+
146
+ /** @namespace ../../utils/Product/Extract/getProductOptionInStock */
147
+ export const getProductOptionInStock = (product: IndexedProduct): boolean => {
148
+ const { stock_status: stockStatus } = product;
149
+
150
+ return stockStatus !== GQLProductStockStatus.OUT_OF_STOCK && stockStatus === GQLProductStockStatus.IN_STOCK;
151
+ };
152
+
153
+ /**
154
+ * Returns whether or not product is in stock (true if in stock | false if out of stock)
155
+ * @param product
156
+ * @param parentProduct
157
+ * @returns {boolean}
158
+ * @namespace ../../utils/Product/Extract/getProductInStock
159
+ */
160
+ export const getProductInStock = (
161
+ product: Partial<StockCheckProduct>,
162
+ parentProduct?: Partial<StockCheckProduct>,
163
+ ): boolean => {
164
+ if (!product) {
165
+ return false;
166
+ }
167
+
168
+ const {
169
+ type_id: type,
170
+ stock_item: {
171
+ in_stock: inStock = true,
172
+ } = {},
173
+ } = product;
174
+
175
+ if (type === ProductType.BUNDLE) {
176
+ const { items = [] } = product;
177
+ const requiredItems = (items as IndexedBundleItem[]).filter(({ required }) => required);
178
+ const requiredItemsInStock = requiredItems.filter(
179
+ ({ options }) => options?.some(({ product: optionProduct }) => getProductOptionInStock(optionProduct)),
180
+ );
181
+
182
+ return inStock && requiredItemsInStock.length === requiredItems.length;
183
+ }
184
+
185
+ if (type === ProductType.CONFIGURABLE && parentProduct === product) {
186
+ const { variants = [] } = product;
187
+
188
+ return inStock && !!variants.some((variant) => getProductInStock(
189
+ variant,
190
+ product,
191
+ ));
192
+ }
193
+
194
+ const { type_id: parentTypeId = false } = parentProduct || {};
195
+
196
+ if (parentTypeId === ProductType.CONFIGURABLE && parentProduct !== product) {
197
+ const {
198
+ stock_item: {
199
+ in_stock: parentInStock = true,
200
+ } = {},
201
+ stock_status: parentStockStatus,
202
+ } = parentProduct || {};
203
+
204
+ return parentInStock && parentStockStatus !== GQLProductStockStatus.OUT_OF_STOCK && getProductInStock(product);
205
+ }
206
+
207
+ if (type === ProductType.GROUPED) {
208
+ const { items = [] } = product;
209
+
210
+ return inStock && !!(items as GroupedProductItem[]).some(
211
+ ({ product: groupedProduct }) => getProductInStock(groupedProduct as StockCheckProduct),
212
+ );
213
+ }
214
+
215
+ const { stock_status: stockStatus } = product;
216
+
217
+ return stockStatus !== GQLProductStockStatus.OUT_OF_STOCK
218
+ && (inStock || stockStatus === GQLProductStockStatus.IN_STOCK);
219
+ };
220
+
221
+ /**
222
+ * Checks if items in Grouped Product are in stock
223
+ * @param product: productGroup
224
+ * @param products: products in stock
225
+ * @namespace ../../utils/Product/Extract/getGroupedProductsInStockQuantity */
226
+
227
+ export const getGroupedProductsInStockQuantity = (
228
+ { items = [] }: Partial<IndexedProduct>,
229
+ ): Record<number, number> => (items as GroupedProductItem[]).reduce((acc: Record<number, number>, {
230
+ product, product: { id }, qty = 1,
231
+ }) => (getProductInStock(product as StockCheckProduct) ? { ...acc, [id]: qty } : acc), {});
232
+
233
+ /**
234
+ * Checks if bundle option exist in options (ignoring quantity)
235
+ * @param uid
236
+ * @param options
237
+ * @namespace ../../utils/Product/Extract/getBundleOption
238
+ */
239
+ export const getBundleOption = (uid: string, options: Partial<IndexedBundleOption>[] = []): Partial<IndexedBundleOption> | undefined => {
240
+ const uidParts = decodeBase64(uid).split('/');
241
+
242
+ return options.find(({ uid: linkedUid = '' }) => {
243
+ const linkedUidParts = decodeBase64(linkedUid).split('/');
244
+
245
+ if (uidParts.length !== linkedUidParts.length) {
246
+ return false;
247
+ }
248
+
249
+ // eslint-disable-next-line fp/no-loops,fp/no-let
250
+ for (let i = 0; i < uidParts.length - 1; i++) {
251
+ if (uidParts[i] !== linkedUidParts[i]) {
252
+ return false;
253
+ }
254
+ }
255
+
256
+ return true;
257
+ });
258
+ };
259
+
260
+ /**
261
+ * Returns price object for product.
262
+ * @param priceRange
263
+ * @param dynamicPrice
264
+ * @param adjustedPrice
265
+ * @param type
266
+ * @param options
267
+ * @returns {{originalPrice: {maxFinalPriceExclTax: {valueFormatted: string}, minFinalPrice: {valueFormatted: string}, minFinalPriceExclTax: {valueFormatted: string}, maxFinalPrice: {valueFormatted: string}}, price: {originalPriceExclTax: {currency: string, value: (number|number)}, originalPrice: {currency: string, value: (number|number)}, finalPriceExclTax: {currency: string, value: (number|number)}, finalPrice: {currency: string, value: (number|number)}, discount: {percentOff: number}}}}
268
+ * @namespace ../../utils/Product/Extract/getPrice
269
+ */
270
+ export const getPrice = (
271
+ priceRange: Partial<PriceRange>,
272
+ dynamicPrice = false,
273
+ adjustedPrice: Partial<AdjustedPriceMap> = {},
274
+ type: any = (ProductType as any).SIMPLE,
275
+ options = [],
276
+ ): ProductExtractPrice => {
277
+ const priceAcc = type === (ProductType as any).BUNDLE
278
+ ? 'default_final_price'
279
+ : 'regular_price';
280
+ const priceExcTaxAcc = type === (ProductType as any).BUNDLE || type === (ProductType as any).CONFIGURABLE
281
+ ? 'default_final_price_excl_tax'
282
+ : 'regular_price_excl_tax';
283
+ const accessRange = type === (ProductType as any).VIRTUAL || type === (ProductType as any).DOWNLOADABLE
284
+ ? 'maximum_price'
285
+ : 'minimum_price';
286
+
287
+ const {
288
+ [accessRange]: {
289
+ [priceAcc]: { currency = GQLCurrencyEnum.USD, value: basePrice = 0 } = {},
290
+ [priceExcTaxAcc]: { value: basePriceExclTax = 0 } = {},
291
+ discount: {
292
+ percent_off: percentOffRef = 0,
293
+ amount_off: amountOff = 0,
294
+ } = {},
295
+ } = {},
296
+ minimum_price: {
297
+ regular_price: minRegularPrice = {} as Money,
298
+ final_price: minFinalPrice = {} as Money,
299
+ final_price_excl_tax: minFinalPriceExclTax = {} as Money,
300
+ } = {},
301
+ maximum_price: {
302
+ regular_price: maxRegularPrice = {} as Money,
303
+ final_price: maxFinalPrice = {} as Money,
304
+ final_price_excl_tax: maxFinalPriceExclTax = {} as Money,
305
+ } = {},
306
+ } = priceRange || {};
307
+
308
+ // Fixes decimal misplacement for discount
309
+ // eslint-disable-next-line no-magic-numbers
310
+ const percentOffCalc = (amountOff / basePrice) * 100;
311
+ // eslint-disable-next-line no-magic-numbers
312
+ const percentOff = Math.round(percentOffCalc * 100) / 100 === percentOffRef
313
+ ? percentOffCalc
314
+ : percentOffRef;
315
+
316
+ // eslint-disable-next-line no-magic-numbers
317
+ const discountValue = (1 - percentOff / 100);
318
+ // eslint-disable-next-line no-magic-numbers
319
+ const discountValueRevert = discountValue === 0 ? 1 : discountValue;
320
+
321
+ const basePriceExclDiscount = priceAcc === 'default_final_price'
322
+ ? basePrice / discountValueRevert
323
+ : basePrice;
324
+ const basePriceExclDiscountExclTax = priceAcc === 'default_final_price'
325
+ ? basePriceExclTax / discountValueRevert
326
+ : basePriceExclTax;
327
+
328
+ const priceValue = {
329
+ value: dynamicPrice ? 0 : basePriceExclDiscount * discountValue,
330
+ currency,
331
+ valueFormatted: '0',
332
+ };
333
+ const priceValueExclTax = {
334
+ value: dynamicPrice ? 0 : basePriceExclDiscountExclTax * discountValue,
335
+ currency,
336
+ valueFormatted: '0',
337
+ };
338
+ const priceValueExclDiscount = {
339
+ value: dynamicPrice ? 0 : basePriceExclDiscount,
340
+ currency,
341
+ valueFormatted: '0',
342
+ };
343
+ const priceValueExclDiscountExclTax = {
344
+ value: dynamicPrice ? 0 : basePriceExclDiscountExclTax,
345
+ currency,
346
+ valueFormatted: '0',
347
+ };
348
+
349
+ // Adds adjusted price
350
+ Object.keys(adjustedPrice || {}).forEach((key) => {
351
+ const { [key as keyof AdjustedPriceMap]: group } = adjustedPrice;
352
+ const {
353
+ inclTax = 0,
354
+ exclTax = 0,
355
+ requiresDiscountCalculations = true,
356
+ hasDiscountCalculated = false,
357
+ } = group || {};
358
+
359
+ if (requiresDiscountCalculations) {
360
+ if (hasDiscountCalculated) {
361
+ priceValue.value += inclTax;
362
+ priceValueExclTax.value += exclTax;
363
+ priceValueExclDiscount.value += inclTax / discountValueRevert;
364
+ priceValueExclDiscountExclTax.value += exclTax / discountValueRevert;
365
+ } else {
366
+ priceValue.value += inclTax * discountValue;
367
+ priceValueExclTax.value += exclTax * discountValue;
368
+ priceValueExclDiscount.value += inclTax;
369
+ priceValueExclDiscountExclTax.value += exclTax;
370
+ }
371
+ } else {
372
+ priceValue.value += inclTax;
373
+ priceValueExclTax.value += exclTax;
374
+ priceValueExclDiscount.value += inclTax;
375
+ priceValueExclDiscountExclTax.value += exclTax;
376
+ }
377
+ });
378
+
379
+ // Adds formatted price option
380
+ priceValue.valueFormatted = formatPrice(priceValue.value, currency);
381
+ priceValueExclTax.valueFormatted = formatPrice(priceValueExclTax.value, currency);
382
+ priceValueExclDiscount.valueFormatted = formatPrice(priceValueExclDiscount.value, currency);
383
+ priceValueExclDiscountExclTax.valueFormatted = formatPrice(priceValueExclDiscountExclTax.value, currency);
384
+
385
+ const configuration = {
386
+ containsOptions: options && !!options.length,
387
+ containsOptionsWithPrice: false,
388
+ containsRequiredOptions: false,
389
+ containsRequiredOptionsWithPrice: false,
390
+ };
391
+
392
+ if (options) {
393
+ configuration.containsOptionsWithPrice = !!options.find(
394
+ ({ value = [] }) => Array.isArray(value) && value.find(({ price }) => price),
395
+ );
396
+ const requiredOptions = options.filter(({ required }) => required);
397
+
398
+ configuration.containsRequiredOptions = !!requiredOptions.length;
399
+
400
+ if (requiredOptions.length) {
401
+ configuration.containsRequiredOptionsWithPrice = !!requiredOptions.find(
402
+ ({ value = [] }) => Array.isArray(value) && value.find(({ price }) => price),
403
+ );
404
+ }
405
+ }
406
+
407
+ return {
408
+ price: {
409
+ finalPrice: priceValue,
410
+ finalPriceExclTax: priceValueExclTax,
411
+ originalPrice: priceValueExclDiscount,
412
+ originalPriceExclTax: priceValueExclDiscountExclTax,
413
+ discount: {
414
+ percentOff,
415
+ },
416
+ },
417
+ originalPrice: {
418
+ minRegularPrice: {
419
+ ...minRegularPrice,
420
+ valueFormatted: formatPrice(minRegularPrice.value || 0, currency),
421
+ },
422
+ minFinalPrice: {
423
+ ...minFinalPrice,
424
+ valueFormatted: formatPrice(minFinalPrice.value || 0, currency),
425
+ },
426
+ minFinalPriceExclTax: {
427
+ ...minFinalPriceExclTax,
428
+ valueFormatted: formatPrice(minFinalPriceExclTax.value || 0, currency),
429
+ },
430
+ maxRegularPrice: {
431
+ ...maxRegularPrice,
432
+ valueFormatted: formatPrice(maxRegularPrice.value || 0, currency),
433
+ },
434
+ maxFinalPrice: {
435
+ ...maxFinalPrice,
436
+ valueFormatted: formatPrice(maxFinalPrice.value || 0, currency),
437
+ },
438
+ maxFinalPriceExclTax: {
439
+ ...maxFinalPriceExclTax,
440
+ valueFormatted: formatPrice(maxFinalPriceExclTax.value || 0, currency),
441
+ },
442
+ },
443
+ configuration,
444
+ };
445
+ };
446
+
447
+ /**
448
+ * Generates adjusted price from entered product options
449
+ *
450
+ * @param product
451
+ * @param downloadableLinks
452
+ * @param enteredOptions
453
+ * @param selectedOptions
454
+ * @namespace ../../utils/Product/Extract/getAdjustedPrice
455
+ */
456
+ export const getAdjustedPrice = (
457
+ product: IndexedProduct,
458
+ downloadableLinks: string[],
459
+ enteredOptions: ProductOption[],
460
+ selectedOptions: FieldValue<string, false>[],
461
+ ): AdjustedPriceMap => {
462
+ const {
463
+ options = [],
464
+ type_id: typeId,
465
+ } = product;
466
+
467
+ const adjustedPrice = {
468
+ downloadable: {
469
+ exclTax: 0,
470
+ inclTax: 0,
471
+ requiresDiscountCalculations: true,
472
+ hasDiscountCalculated: false,
473
+ },
474
+ bundle: {
475
+ exclTax: 0,
476
+ inclTax: 0,
477
+ requiresDiscountCalculations: true,
478
+ hasDiscountCalculated: true,
479
+ },
480
+ config: {
481
+ exclTax: 0,
482
+ inclTax: 0,
483
+ requiresDiscountCalculations: false,
484
+ hasDiscountCalculated: false,
485
+ },
486
+ };
487
+
488
+ // #region DOWNLOADABLE
489
+ if (typeId === ProductType.DOWNLOADABLE) {
490
+ const { downloadable_product_links = [] } = product;
491
+
492
+ downloadableLinks.forEach((uid) => {
493
+ const link = downloadable_product_links.find(({ uid: linkUid }: { uid?: any }) => linkUid === uid);
494
+
495
+ if (link) {
496
+ const { price } = link;
497
+
498
+ adjustedPrice.downloadable.exclTax += price;
499
+ adjustedPrice.downloadable.inclTax += price;
500
+ }
501
+ });
502
+ }
503
+ // #endregion
504
+
505
+ // #region BUNDLE
506
+ if (typeId === ProductType.BUNDLE) {
507
+ const { items = [], dynamic_price: dynamicPrice = false } = product;
508
+
509
+ selectedOptions.forEach((uid) => {
510
+ (items as IndexedBundleItem[]).forEach(({ options: sldOptions = [] }) => {
511
+ const uidParts = decodeBase64(uid).split('/');
512
+ const option = Array.isArray(options) && getBundleOption(uid, sldOptions);
513
+ const quantity = +uidParts[uidParts.length - 1];
514
+
515
+ if (option) {
516
+ const {
517
+ finalOptionPrice = 0,
518
+ finalOptionPriceExclTax = 0,
519
+ product: {
520
+ price_range: optionProductPriceRange = {},
521
+ type_id: optionProductType,
522
+ dynamic_price: optionProductDynamic,
523
+ } = {},
524
+ can_change_quantity: canChangeQuantity = false,
525
+ } = option;
526
+
527
+ if (!dynamicPrice) {
528
+ const multiplier = canChangeQuantity ? quantity : quantity;
529
+
530
+ adjustedPrice.bundle.exclTax += finalOptionPriceExclTax * multiplier;
531
+ adjustedPrice.bundle.inclTax += finalOptionPrice * multiplier;
532
+ } else {
533
+ const {
534
+ price: {
535
+ finalPrice: { value: priceInclTax = 0 } = {},
536
+ finalPriceExclTax: { value: priceExclTax = 0 } = {},
537
+ },
538
+ } = getPrice(optionProductPriceRange, optionProductDynamic, {}, optionProductType) || {};
539
+
540
+ adjustedPrice.bundle.inclTax += priceInclTax * quantity;
541
+ adjustedPrice.bundle.exclTax += priceExclTax * quantity;
542
+ }
543
+ }
544
+ });
545
+ });
546
+ }
547
+ // #endregion
548
+
549
+ // #region CONFIGURABLE
550
+ enteredOptions.forEach(({ uid }) => {
551
+ const option = options.find(({ uid: linkUid }) => linkUid === uid);
552
+
553
+ if (option) {
554
+ const { value } = option;
555
+
556
+ if ('priceInclTax' in value && 'priceExclTax' in value) {
557
+ const { priceExclTax = 0, priceInclTax = 0 } = value;
558
+
559
+ adjustedPrice.config.inclTax += priceInclTax as number;
560
+ adjustedPrice.config.exclTax += priceExclTax as number;
561
+ }
562
+ }
563
+ });
564
+
565
+ selectedOptions.forEach((uid) => {
566
+ options.forEach(({ value = [] }) => {
567
+ const option = Array.isArray(value) && value.find((option) => {
568
+ if ('uid' in option) {
569
+ const { uid: linkedUid } = option;
570
+
571
+ return linkedUid === uid;
572
+ }
573
+
574
+ return false;
575
+ });
576
+
577
+ if (option) {
578
+ const { priceExclTax = 0, priceInclTax = 0 } = option;
579
+
580
+ adjustedPrice.config.inclTax += priceInclTax;
581
+ adjustedPrice.config.exclTax += priceExclTax;
582
+ }
583
+ });
584
+ });
585
+ // #endregion
586
+
587
+ return adjustedPrice;
588
+ };
589
+
590
+ // #region SubLabel
591
+ /**
592
+ * Returns ProductCustomizable Text/TextArea Option Sublabel based on Maximum characters setup in BE
593
+ * @param maxCharacters
594
+ * @param value
595
+ * @namespace ../../utils/Product/Extract/getSubLabelFromMaxCharacters
596
+ */
597
+ export const getSubLabelFromMaxCharacters = (maxCharacters: number, value = ''): string | null => {
598
+ const valueLength = value.length;
599
+ const remainingCharacters = maxCharacters - valueLength;
600
+
601
+ if (maxCharacters > 0) {
602
+ if (valueLength > 0 && valueLength <= maxCharacters) {
603
+ return __('Maximum %s characters (%s remaining)', maxCharacters, remainingCharacters);
604
+ }
605
+
606
+ if (valueLength >= maxCharacters) {
607
+ return null;
608
+ }
609
+
610
+ return __('Maximum %s characters', maxCharacters);
611
+ }
612
+
613
+ return null;
614
+ };
615
+ // #endregion
616
+
617
+ // #region IMAGE
618
+ /**
619
+ * Returns product image based on variable field, on fail placeholder
620
+ * @param product
621
+ * @param field
622
+ * @namespace ../../utils/Product/Extract/getImage
623
+ */
624
+ export const getImage = (product: Partial<ProductExtractImage>, field: ImageType): string => {
625
+ const { [field]: { url = 'no_selection' } = {} } = product;
626
+
627
+ return url && url !== 'no_selection' ? url : '';
628
+ };
629
+
630
+ /**
631
+ * Returns products thumbnail image
632
+ * @param product
633
+ * @namespace ../../utils/Product/Extract/getThumbnailImage
634
+ */
635
+ export const getThumbnailImage = (
636
+ product: Partial<ProductExtractImage>,
637
+ ): string => getImage(product, ImageType.THUMBNAIL);
638
+
639
+ /**
640
+ * Returns products small image
641
+ * @param product
642
+ * @namespace ../../utils/Product/Extract/getSmallImage
643
+ */
644
+ export const getSmallImage = (product: Partial<ProductExtractImage>): string => getImage(product, ImageType.SMALL);
645
+
646
+ /**
647
+ * Returns products base image
648
+ * @param product
649
+ * @namespace ../../utils/Product/Extract/getBaseImage
650
+ */
651
+ export const getBaseImage = (product: Partial<ProductExtractImage>): string => getImage(product, ImageType.IMAGE);
652
+ // #endregion