@meeovi/layer-commerce 1.0.10 → 1.0.13

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 (324) hide show
  1. package/app/components/catalog/product/ProductAccordion/ProductAccordion.vue +39 -0
  2. package/app/components/catalog/product/ProductAccordion/__tests__/ProductAccordion.spec.ts +15 -0
  3. package/app/components/catalog/product/ProductAccordion/types.ts +5 -0
  4. package/app/components/catalog/product/ProductProperties/ProductProperties.vue +50 -0
  5. package/app/components/catalog/product/ProductProperties/__tests__/ProductProperties.spec.ts +15 -0
  6. package/app/components/catalog/product/ProductProperties/types.ts +5 -0
  7. package/app/components/catalog/product/ProductSlider/ProductSlider.vue +28 -0
  8. package/app/components/catalog/product/ProductSlider/__tests__/ProductSlider.spec.ts +14 -0
  9. package/app/components/catalog/product/ProductSlider/types.ts +7 -0
  10. package/app/components/catalog/product/RecommendedProducts/RecommendedProducts.vue +12 -0
  11. package/app/components/catalog/product/RecommendedProducts/types.ts +5 -0
  12. package/app/components/catalog/product/RenderContentProductSlider/RenderContentProductSlider.vue +11 -0
  13. package/app/components/catalog/product/add-attribute.vue +54 -0
  14. package/app/components/catalog/product/add-product-type.vue +54 -0
  15. package/app/components/catalog/product/add-product.vue +53 -0
  16. package/app/components/catalog/product/add-showcase.vue +52 -0
  17. package/app/components/catalog/product/add-station.vue +54 -0
  18. package/app/components/catalog/product/bestsellers.vue +57 -0
  19. package/app/components/catalog/product/bidding.vue +93 -0
  20. package/app/components/catalog/product/colorOptions.vue +58 -0
  21. package/app/components/catalog/product/deals.vue +46 -0
  22. package/app/components/catalog/product/exclusives.vue +56 -0
  23. package/app/components/catalog/product/featuredproducts.vue +57 -0
  24. package/app/components/catalog/product/giftCard.vue +63 -0
  25. package/app/components/catalog/product/latestproducts.vue +46 -0
  26. package/app/components/catalog/product/productCard.vue +105 -0
  27. package/app/components/catalog/product/productCompare.vue +60 -0
  28. package/app/components/catalog/product/productCompareTable.vue +441 -0
  29. package/app/components/catalog/product/productDetails.vue +126 -0
  30. package/app/components/catalog/product/productFaqs.vue +17 -0
  31. package/app/components/catalog/product/productGallery.vue +16 -0
  32. package/app/components/catalog/product/productQty.vue +54 -0
  33. package/app/components/catalog/product/productReviews.vue +56 -0
  34. package/app/components/catalog/product/productSpecs.vue +116 -0
  35. package/app/components/catalog/product/radiostation.vue +36 -0
  36. package/app/components/catalog/product/recentlyviewed.vue +43 -0
  37. package/app/components/catalog/product/relatedbrands.vue +54 -0
  38. package/app/components/catalog/product/relatedproducts.vue +43 -0
  39. package/app/components/catalog/product/relatedstations.vue +40 -0
  40. package/app/components/catalog/product/shippingOptions.vue +41 -0
  41. package/app/components/catalog/product/sizeOptions.vue +42 -0
  42. package/app/components/catalog/product/update-attribute-set.vue +209 -0
  43. package/app/components/catalog/product/update-attribute.vue +118 -0
  44. package/app/components/catalog/product/update-product.vue +372 -0
  45. package/app/components/catalog/product/update-showcase.vue +153 -0
  46. package/app/components/catalog/shops/relatedstores.vue +37 -0
  47. package/app/components/catalog/shops/restaurant.vue +66 -0
  48. package/app/components/catalog/shops/stores.vue +44 -0
  49. package/app/components/catalog/vendor/README.md +3 -0
  50. package/app/components/catalog/vendor/blocks/biggestcustomers.vue +33 -0
  51. package/app/components/catalog/vendor/blocks/lowestselling.vue +33 -0
  52. package/app/components/catalog/vendor/blocks/topcategories.vue +33 -0
  53. package/app/components/catalog/vendor/blocks/topproducts.vue +27 -0
  54. package/app/components/catalog/vendor/pages/attributes.vue +43 -0
  55. package/app/components/catalog/vendor/pages/commissions.vue +43 -0
  56. package/app/components/catalog/vendor/pages/crm.vue +67 -0
  57. package/app/components/catalog/vendor/pages/dashboard.vue +46 -0
  58. package/app/components/catalog/vendor/pages/emails.vue +43 -0
  59. package/app/components/catalog/vendor/pages/enquiries.vue +43 -0
  60. package/app/components/catalog/vendor/pages/invoices.vue +43 -0
  61. package/app/components/catalog/vendor/pages/orders.vue +68 -0
  62. package/app/components/catalog/vendor/pages/products.vue +55 -0
  63. package/app/components/catalog/vendor/pages/reviews.vue +48 -0
  64. package/app/components/catalog/vendor/pages/shipments.vue +43 -0
  65. package/app/components/catalog/vendor/pages/stores.vue +43 -0
  66. package/app/components/categories/chart/[id].vue +200 -0
  67. package/app/components/categories/chart/add-chart.vue +142 -0
  68. package/app/components/categories/chart/chart.vue +82 -0
  69. package/app/components/categories/chart/monthlyChart.vue +46 -0
  70. package/app/components/categories/chart/weeklyChart.vue +46 -0
  71. package/app/components/categories/chart/yearlyChart.vue +46 -0
  72. package/app/components/categories/charts.vue +118 -0
  73. package/app/components/categories/deals.vue +101 -0
  74. package/app/components/categories/eats.vue +49 -0
  75. package/app/components/categories/restaurants.vue +26 -0
  76. package/app/components/categories/station/[id].vue +72 -0
  77. package/app/components/categories/stations.vue +124 -0
  78. package/app/components/categories/time/time.vue +63 -0
  79. package/app/components/categories/travel.vue +75 -0
  80. package/app/components/categories/weather/weather.vue +44 -0
  81. package/app/components/content/blocks/breadcrumbs.vue +0 -0
  82. package/app/components/content/blocks/currencySwitcher.vue +0 -0
  83. package/app/components/content/blocks/languageSwitcher.vue +0 -0
  84. package/app/components/content/blocks/videoproduct.vue +9 -0
  85. package/app/components/content/pages/checkout.vue +118 -0
  86. package/app/components/content/pages/meeoviGlobal.vue +68 -0
  87. package/app/components/content/pages/pickup-locations.vue +238 -0
  88. package/app/components/content/pages/showcases.vue +90 -0
  89. package/app/components/content/pages/success.vue +60 -0
  90. package/app/components/marketing/add-brand.vue +54 -0
  91. package/app/components/marketing/add-incentive.vue +54 -0
  92. package/app/components/marketing/promotions/giftcards.vue +102 -0
  93. package/app/components/marketing/promotions/subscriptions.vue +121 -0
  94. package/app/components/marketing/update-incentive.vue +326 -0
  95. package/app/components/menus/lowernav.vue +78 -0
  96. package/app/components/partials/LocaleSelector.vue +24 -0
  97. package/app/components/partials/ShoppingCart.vue +128 -0
  98. package/app/components/partials/StripePayment.vue +149 -0
  99. package/app/components/partials/addToCartBtn.vue +40 -0
  100. package/app/components/partials/cartItem.vue +124 -0
  101. package/app/components/partials/checkoutButton.vue +44 -0
  102. package/app/components/partials/compareBtn.vue +68 -0
  103. package/app/components/partials/ratings.vue +13 -0
  104. package/app/components/partials/store/CurrencySelector.vue +133 -0
  105. package/app/components/partials/store/StoreSwitcher.vue +13 -0
  106. package/app/components/placeholders/Comments.vue +15 -0
  107. package/app/components/placeholders/CreateListBtn.vue +7 -0
  108. package/app/components/placeholders/Event.vue +9 -0
  109. package/app/components/placeholders/ListShowcases.vue +9 -0
  110. package/app/components/placeholders/Short.vue +9 -0
  111. package/app/components/placeholders/Space.vue +9 -0
  112. package/app/components/placeholders/Tag.vue +7 -0
  113. package/app/components/related/brandCard.vue +41 -0
  114. package/app/components/related/incentiveCard.vue +44 -0
  115. package/app/components/related/invoiceCard.vue +43 -0
  116. package/app/components/related/orderCard.vue +43 -0
  117. package/app/components/related/relatedproducts.vue +17 -0
  118. package/app/components/sales/CartPageContent/CartPageContent.vue +37 -0
  119. package/app/components/sales/CheckoutAddress/CheckoutAddress.vue +50 -0
  120. package/app/components/sales/CheckoutAddress/__tests__/CheckoutAddress.spec.ts +16 -0
  121. package/app/components/sales/CheckoutAddress/types.ts +16 -0
  122. package/app/components/sales/CheckoutPayment/CheckoutPayment.vue +68 -0
  123. package/app/components/sales/CheckoutPayment/__tests__/CheckoutPayment.spec.ts +14 -0
  124. package/app/components/sales/CheckoutPayment/types.ts +12 -0
  125. package/app/components/sales/OrderSummary/OrderSummary.vue +57 -0
  126. package/app/components/sales/OrderSummary/__tests__/ContactInformation.spec.ts +52 -0
  127. package/app/components/sales/OrderSummary/types.ts +5 -0
  128. package/app/components/sales/incentives.vue +223 -0
  129. package/app/components/sales/invoices.vue +107 -0
  130. package/app/components/sales/orders.vue +378 -0
  131. package/app/components/sales/shipments.vue +65 -0
  132. package/app/components/sales/transactions.vue +109 -0
  133. package/app/components/shop/add-shop.vue +54 -0
  134. package/app/components/shop/cart/cartItem.vue +182 -0
  135. package/app/components/shop/cart/checkout.vue +415 -0
  136. package/app/components/shop/checkout/StripeCardElement.vue +206 -0
  137. package/app/components/shop/checkout/StripeCheckout.vue +49 -0
  138. package/app/components/shop/checkout/addressBilling.vue +263 -0
  139. package/app/components/shop/checkout/addressShipping.vue +175 -0
  140. package/app/components/shop/checkout/cart/ProductItem.vue +56 -0
  141. package/app/components/shop/checkout/cart/PromotionItem.vue +53 -0
  142. package/app/composables/_types.ts +18 -0
  143. package/app/composables/adapters/abstract/cartAdapter.ts +0 -0
  144. package/app/composables/adapters/abstract/categoryAdapter.ts +0 -0
  145. package/app/composables/adapters/abstract/customerAdapter.ts +0 -0
  146. package/app/composables/adapters/abstract/inventoryAdapter.ts +0 -0
  147. package/app/composables/adapters/abstract/orderAdapter.ts +0 -0
  148. package/app/composables/adapters/abstract/productAdapter.ts +7 -0
  149. package/app/composables/cart/registry.ts +20 -0
  150. package/app/composables/cart/types.ts +18 -0
  151. package/app/composables/cart/useCart.ts +15 -0
  152. package/app/composables/config.ts +19 -0
  153. package/app/composables/defs/apiDefinitions.ts +55 -0
  154. package/app/composables/defs/extension.feature +40 -0
  155. package/app/composables/defs/extension.mocks.ts +39 -0
  156. package/app/composables/defs/extension.test.ts +280 -0
  157. package/app/composables/defs/extension.ts +236 -0
  158. package/app/composables/defs/index.ts +3 -0
  159. package/app/composables/defs/types.ts +136 -0
  160. package/app/composables/domain/cart.ts +0 -0
  161. package/app/composables/domain/category.ts +0 -0
  162. package/app/composables/domain/order.ts +0 -0
  163. package/app/composables/domain/price.ts +0 -0
  164. package/app/composables/domain/product.ts +8 -0
  165. package/app/composables/domain/reward.ts +0 -0
  166. package/app/composables/domain/transactions.ts +0 -0
  167. package/app/composables/helpers/contextualizedNormalizers.feature +14 -0
  168. package/app/composables/helpers/contextualizedNormalizers.test.ts +85 -0
  169. package/app/composables/helpers/contextualizedNormalizers.ts +20 -0
  170. package/app/composables/helpers/index.ts +1 -0
  171. package/app/composables/index.ts +6 -0
  172. package/app/composables/methods/auth.ts +83 -0
  173. package/app/composables/methods/cart.ts +119 -0
  174. package/app/composables/methods/category.ts +27 -0
  175. package/app/composables/methods/checkout.ts +54 -0
  176. package/app/composables/methods/customer.ts +52 -0
  177. package/app/composables/methods/helpers.ts +5 -0
  178. package/app/composables/methods/index.ts +75 -0
  179. package/app/composables/methods/order.ts +39 -0
  180. package/app/composables/methods/product.ts +95 -0
  181. package/app/composables/methods/settings.ts +16 -0
  182. package/app/composables/models/cart.ts +95 -0
  183. package/app/composables/models/category.ts +13 -0
  184. package/app/composables/models/checkout.ts +17 -0
  185. package/app/composables/models/customer.ts +16 -0
  186. package/app/composables/models/facets.ts +25 -0
  187. package/app/composables/models/index.ts +94 -0
  188. package/app/composables/models/order.ts +43 -0
  189. package/app/composables/models/product.ts +73 -0
  190. package/app/composables/models/shared.ts +75 -0
  191. package/app/composables/products/registry.ts +20 -0
  192. package/app/composables/products/types.ts +13 -0
  193. package/app/composables/products/useEvents.ts +0 -0
  194. package/app/composables/products/useGiftCards.ts +0 -0
  195. package/app/composables/products/useProducts.ts +12 -0
  196. package/app/composables/products/useSubscriptions.ts +0 -0
  197. package/app/composables/registry.ts +21 -0
  198. package/app/composables/stores/cart.ts +218 -0
  199. package/app/composables/stores/cartStore.ts +300 -0
  200. package/app/composables/stores/checkout.ts +19 -0
  201. package/app/composables/stores/compare.ts +65 -0
  202. package/app/composables/stores/currency.js +29 -0
  203. package/app/composables/stores/digital-products.js +11 -0
  204. package/app/composables/stores/index.js +0 -0
  205. package/app/composables/stores/orders.ts +161 -0
  206. package/app/composables/stores/product.ts +26 -0
  207. package/app/composables/stores/productList.ts +0 -0
  208. package/app/composables/stores/productListInfo.ts +0 -0
  209. package/app/composables/stores/products.ts +112 -0
  210. package/app/composables/stores/recentlyViewedProducts.ts +0 -0
  211. package/app/composables/stores/review.ts +25 -0
  212. package/app/composables/stores/storeInPickUp.ts +22 -0
  213. package/app/composables/stores/user.ts +20 -0
  214. package/app/composables/stores/wishlist.ts +19 -0
  215. package/app/composables/types/Order.type.ts +181 -0
  216. package/app/composables/types/index.ts +285 -0
  217. package/app/composables/types/product.ts +14 -0
  218. package/app/composables/useBreakpoints/index.ts +1 -0
  219. package/app/composables/useBreakpoints/useBreakpoints.ts +28 -0
  220. package/app/composables/useCart/__tests__/useCart.spec.ts +11 -0
  221. package/app/composables/useCart/index.ts +1 -0
  222. package/app/composables/useCart/types.ts +17 -0
  223. package/app/composables/useCart/useCart.ts +46 -0
  224. package/app/composables/useCartShippingMethods/__tests__/useCartShippingMethods.spec.ts +11 -0
  225. package/app/composables/useCartShippingMethods/index.ts +1 -0
  226. package/app/composables/useCartShippingMethods/types.ts +17 -0
  227. package/app/composables/useCartShippingMethods/useCartShippingMethods.ts +47 -0
  228. package/app/composables/useCatalog.ts +64 -0
  229. package/app/composables/useContent/index.ts +1 -0
  230. package/app/composables/useContent/types.ts +44 -0
  231. package/app/composables/useContent/useContent.ts +45 -0
  232. package/app/composables/useContent.ts +57 -0
  233. package/app/composables/useCustomer/__tests__/useCustomer.spec.ts +25 -0
  234. package/app/composables/useCustomer/index.ts +2 -0
  235. package/app/composables/useCustomer/types.ts +17 -0
  236. package/app/composables/useCustomer/useCustomer.ts +40 -0
  237. package/app/composables/useCustomerAddress/__tests__/useCustomerAddress.spec.ts +11 -0
  238. package/app/composables/useCustomerAddress/index.ts +2 -0
  239. package/app/composables/useCustomerAddress/types.ts +17 -0
  240. package/app/composables/useCustomerAddress/useCustomerAddress.ts +55 -0
  241. package/app/composables/useCustomerOrder/__tests__/useCustomerOrder.spec.ts +11 -0
  242. package/app/composables/useCustomerOrder/adress.ts +10 -0
  243. package/app/composables/useCustomerOrder/index.ts +2 -0
  244. package/app/composables/useCustomerOrder/product.ts +37 -0
  245. package/app/composables/useCustomerOrder/types.ts +40 -0
  246. package/app/composables/useCustomerOrder/useCustomerOrder.ts +63 -0
  247. package/app/composables/useCustomerOrders/__tests__/useCustomerOrders.spec.ts +11 -0
  248. package/app/composables/useCustomerOrders/index.ts +2 -0
  249. package/app/composables/useCustomerOrders/types.ts +20 -0
  250. package/app/composables/useCustomerOrders/useCustomerOrders.ts +56 -0
  251. package/app/composables/useCustomerReturns/__tests__/useCustomerReturns.spec.ts +11 -0
  252. package/app/composables/useCustomerReturns/index.ts +2 -0
  253. package/app/composables/useCustomerReturns/types.ts +17 -0
  254. package/app/composables/useCustomerReturns/useCustomerReturns.ts +41 -0
  255. package/app/composables/useHandleError/index.ts +1 -0
  256. package/app/composables/useHandleError/types.ts +11 -0
  257. package/app/composables/useHandleError/useHandleError.ts +27 -0
  258. package/app/composables/usePageTitle.ts +16 -0
  259. package/app/composables/useProduct/index.ts +2 -0
  260. package/app/composables/useProduct/types.ts +17 -0
  261. package/app/composables/useProduct/useProduct.ts +42 -0
  262. package/app/composables/useProductAttribute/__tests__/useProduct.mock.ts +31 -0
  263. package/app/composables/useProductAttribute/__tests__/useProductAttribute.spec.ts +14 -0
  264. package/app/composables/useProductAttribute/index.ts +1 -0
  265. package/app/composables/useProductAttribute/useProductAttribute.ts +37 -0
  266. package/app/composables/useProductRecommended/__tests__/useProductRecommended.spec.ts +12 -0
  267. package/app/composables/useProductRecommended/index.ts +1 -0
  268. package/app/composables/useProductRecommended/types.ts +17 -0
  269. package/app/composables/useProductRecommended/useProductRecommended.ts +43 -0
  270. package/app/composables/useProductReviews/__tests__/productReviews.mock.ts +20 -0
  271. package/app/composables/useProductReviews/__tests__/useProductReviews.spec.ts +22 -0
  272. package/app/composables/useProductReviews/index.ts +2 -0
  273. package/app/composables/useProductReviews/types.ts +17 -0
  274. package/app/composables/useProductReviews/useProductReviews.ts +46 -0
  275. package/app/composables/useProducts/__tests__/useProducts.spec.ts +11 -0
  276. package/app/composables/useProducts/types.ts +22 -0
  277. package/app/composables/useProducts/useProducts.ts +41 -0
  278. package/app/composables/utils/countryList.ts +14 -0
  279. package/app/composables/utils/currency.js +56 -0
  280. package/app/composables/utils/glossary.ts +0 -0
  281. package/app/composables/utils/importExport.ts +0 -0
  282. package/app/composables/utils/index.js +0 -0
  283. package/app/composables/utils/print.ts +0 -0
  284. package/app/composables/utils/shopThemes.ts +0 -0
  285. package/app/composables/utils/statistics.ts +0 -0
  286. package/app/composables/utils/stock.ts +0 -0
  287. package/app/composables/utils/stripe.ts +16 -0
  288. package/app/composables/utils/taxation.ts +0 -0
  289. package/app/composables/utils/tellFriends.ts +0 -0
  290. package/app/composables/validationRules/index.ts +1 -0
  291. package/app/composables/validationRules/password.feature +67 -0
  292. package/app/composables/validationRules/password.test.ts +89 -0
  293. package/app/composables/validationRules/password.ts +25 -0
  294. package/app/composables/vendors/index.ts +0 -0
  295. package/app/composables/vendors/registry.ts +0 -0
  296. package/app/composables/vendors/useAffiliates.ts +0 -0
  297. package/app/composables/vendors/useCommission.ts +0 -0
  298. package/app/modules/vue-head/composables/useHead.ts +3 -0
  299. package/app/pages/brand/[...slug].vue +92 -0
  300. package/app/pages/brands.vue +90 -0
  301. package/app/pages/cart.vue +142 -0
  302. package/app/pages/compare.vue +166 -0
  303. package/app/pages/departments/[...slug].vue +385 -0
  304. package/app/pages/departments/category/[...slug].vue +135 -0
  305. package/app/pages/incentive/[...id].vue +66 -0
  306. package/app/pages/invoice/[id].vue +309 -0
  307. package/app/pages/order/[id].vue +327 -0
  308. package/app/pages/product/[...id].vue +309 -0
  309. package/app/pages/product/showcases/index.vue +86 -0
  310. package/app/pages/shipment/[...id].vue +176 -0
  311. package/app/pages/shop/[...slug].vue +158 -0
  312. package/app/pages/shops.vue +76 -0
  313. package/app/pages/subscription/[...id].vue +147 -0
  314. package/app/pages/transaction/[...id].vue +74 -0
  315. package/app/types/shims-imports.d.ts +13 -0
  316. package/app/utils/client.ts +26 -0
  317. package/app/utils/index.ts +53 -0
  318. package/app/utils/normalizer.ts +23 -0
  319. package/app/utils/normalizers/magento.ts +29 -0
  320. package/app/utils/normalizers/shopify.ts +29 -0
  321. package/global.d.ts +149 -0
  322. package/index.js +3 -0
  323. package/package.json +3 -9
  324. package/tsconfig.json +31 -0
@@ -0,0 +1,56 @@
1
+ <script setup lang="ts">
2
+ import { ref, computed, watch } from 'vue';
3
+ import { useVendureMutation } from '../../../composables/useVendureMutation';
4
+ import adjustOrderLineMutation from '#graphql/app/commerce/mutations/adjustOrderLine.gql';
5
+ import removeOrderLineMutation from '#graphql/app/commerce/mutations/removeOrderLine.gql';
6
+
7
+ const props = defineProps({
8
+ cartItem: { type: Object, required: true },
9
+ maxQty: { type: Number, default: 100 },
10
+ });
11
+
12
+ const { mutate: adjustOrderLine } = useVendureMutation(adjustOrderLineMutation);
13
+ const { mutate: removeOrderLine } = useVendureMutation(removeOrderLineMutation);
14
+
15
+ const quantity = ref(props.cartItem.quantity);
16
+ const isRemovable = computed(() => true);
17
+ const itemTotalPrice = computed(() => props.cartItem.linePriceWithTax);
18
+
19
+ const updateQuantity = async (qty: number) => {
20
+ if (qty !== props.cartItem.quantity) {
21
+ await adjustOrderLine({ orderLineId: props.cartItem.id, quantity: qty });
22
+ }
23
+ };
24
+
25
+ const removeCartItem = async () => {
26
+ await removeOrderLine({ orderLineId: props.cartItem.id });
27
+ };
28
+
29
+ watch(quantity, (val) => {
30
+ updateQuantity(val);
31
+ });
32
+ </script>
33
+
34
+ <template>
35
+ <div v-if="cartItem.productVariant" class="mr-4 h-24 w-24 shrink-0 overflow-hidden rounded-md border border-secondary-200">
36
+ <img :src="cartItem.productVariant.featuredAsset?.preview" :alt="cartItem.productVariant.name" class="h-full w-full object-cover object-center" />
37
+ </div>
38
+ <div class="flex flex-1 flex-col text-left">
39
+ <div>
40
+ <div class="flex flex-col lg:flex-row justify-between text-base font-medium text-secondary-900">
41
+ <h3 class="text-base cursor-pointer pr-2">
42
+ {{ cartItem.productVariant.name }}
43
+ </h3>
44
+ <span v-if="itemTotalPrice">{{ itemTotalPrice }}</span>
45
+ </div>
46
+ </div>
47
+ <div v-if="cartItem.productVariant.stockOnHand" class="flex flex-1 items-end justify-between text-sm">
48
+ <input v-model="quantity" type="number" :min="1" :max="maxQty" name="quantity" aria-label="Cart item quantity" class="w-18 mt-1 inline-block py-2 px-3 border border-secondary-300 bg-white rounded-md shadow-sm" />
49
+ <div class="flex">
50
+ <button v-if="isRemovable" type="button" class="font-medium text-dark bg-transparent" @click="removeCartItem">
51
+ Remove
52
+ </button>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </template>
@@ -0,0 +1,53 @@
1
+ <script setup lang="ts">
2
+ import { ref, computed } from 'vue';
3
+ import { useVendureMutation } from '../../../composables/useVendureMutation';
4
+ import adjustOrderLineMutation from '#graphql/app/commerce/mutations/adjustOrderLine.gql';
5
+ import removeOrderLineMutation from '#graphql/app/commerce/mutations/removeOrderLine.gql';
6
+
7
+ const props = defineProps({
8
+ cartItem: { type: Object, required: true },
9
+ maxQty: { type: Number, default: 100 },
10
+ });
11
+
12
+ const { mutate: adjustOrderLine } = useVendureMutation(adjustOrderLineMutation);
13
+ const { mutate: removeOrderLine } = useVendureMutation(removeOrderLineMutation);
14
+
15
+ const quantity = ref(props.cartItem.quantity);
16
+ const isRemovable = computed(() => true); // Vendure: all lines can be removed
17
+ const itemTotalPrice = computed(() => props.cartItem.linePriceWithTax);
18
+
19
+ const updateQuantity = async (qty: number) => {
20
+ if (qty !== props.cartItem.quantity) {
21
+ await adjustOrderLine({ orderLineId: props.cartItem.id, quantity: qty });
22
+ }
23
+ };
24
+
25
+ const removeItem = async () => {
26
+ await removeOrderLine({ orderLineId: props.cartItem.id });
27
+ };
28
+ </script>
29
+ <template>
30
+ <div class="mr-4 w-24 shrink-0 overflow-hidden">
31
+ <div class="w-26 i-carbon-tag text-3xl"></div>
32
+ </div>
33
+ <div class="flex flex-1 flex-col">
34
+ <div>
35
+ <div class="flex flex-col lg:flex-row justify-between text-base font-medium text-secondary-900">
36
+ <h3 class="text-base" data-testid="cart-promotion-name">
37
+ {{ cartItem.productVariant.name }}
38
+ <span class="bg-green-100 text-green-800 text-xs font-medium mr-2 px-2.5 py-0.5 rounded-full dark:bg-green-900 dark:text-green-300">
39
+ Promotion
40
+ </span>
41
+ </h3>
42
+ <span v-if="itemTotalPrice">{{ itemTotalPrice }}</span>
43
+ </div>
44
+ </div>
45
+ <div class="flex flex-1 items-end justify-end text-sm">
46
+ <div class="flex">
47
+ <button v-if="isRemovable" type="button" class="font-medium text-dark bg-transparent" @click="removeItem">
48
+ Remove
49
+ </button>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ </template>
@@ -0,0 +1,18 @@
1
+ export type Maybe<T> = T | null | undefined;
2
+
3
+ // Re-export or alias common legacy names expected by the composables
4
+ // Fallback permissive types for isolated builds
5
+ export type SfProduct = any;
6
+ export type Product = any;
7
+ export type SfCart = any;
8
+ export type Cart = any;
9
+
10
+ // No direct equivalents in @meeovi/commerce yet — use permissive any types
11
+ export type SfCustomer = any;
12
+ export type SfAddress = any;
13
+ export type SfProductReview = any;
14
+ export type SfShippingMethods = any;
15
+ export type SfAttribute = any;
16
+
17
+ // Export additional useful types from the commerce package if needed
18
+ export type Category = any;
@@ -0,0 +1,7 @@
1
+ import { Product } from "../../domain/product"
2
+
3
+ export interface ProductAdapter {
4
+ list(): Promise<Product[]>
5
+ get(id: string): Promise<Product | null>
6
+ search(query: string): Promise<Product[]>
7
+ }
@@ -0,0 +1,20 @@
1
+ import { CartProvider } from "./types"
2
+
3
+ const providers: Record<string, CartProvider> = {}
4
+
5
+ export function registerCartProvider(name: string, provider: CartProvider) {
6
+ providers[name] = provider
7
+ }
8
+
9
+ export function getCartProvider(name: string) {
10
+ const provider = providers[name]
11
+ if (!provider) throw new Error(`Cart provider "${name}" not found`)
12
+ return provider
13
+ }
14
+
15
+ // Runtime helper for adapter packages to register themselves when the
16
+ // app boots. Adapter packages can import this and call it from their
17
+ // plugin entry to wire into the commerce cart provider registry.
18
+ export function registerCartProviderRuntime(name: string, provider: CartProvider) {
19
+ registerCartProvider(name, provider)
20
+ }
@@ -0,0 +1,18 @@
1
+ export interface CartItem {
2
+ id: string
3
+ quantity: number
4
+ product: any
5
+ }
6
+
7
+ export interface Cart {
8
+ id: string
9
+ items: CartItem[]
10
+ total: number
11
+ }
12
+
13
+ export interface CartProvider {
14
+ getCart(): Promise<Cart>
15
+ addItem(productId: string, quantity?: number): Promise<Cart>
16
+ removeItem(productId: string): Promise<Cart>
17
+ clearCart(): Promise<Cart>
18
+ }
@@ -0,0 +1,15 @@
1
+ import { getCartProvider } from './registry'
2
+ import { useRuntimeConfig } from '#imports'
3
+
4
+ export function useCart() {
5
+ const config = useRuntimeConfig()
6
+ const providerName = config.public.cartProvider || 'directus'
7
+ const provider = getCartProvider(providerName)
8
+
9
+ return {
10
+ getCart: provider.getCart,
11
+ addItem: provider.addItem,
12
+ removeItem: provider.removeItem,
13
+ clearCart: provider.clearCart
14
+ }
15
+ }
@@ -0,0 +1,19 @@
1
+ export interface CommerceConfig {
2
+ productProvider: string
3
+ cartProvider: string
4
+ categoryProvider: string
5
+ }
6
+
7
+ let config: CommerceConfig = {
8
+ productProvider: 'directus',
9
+ cartProvider: 'directus',
10
+ categoryProvider: 'directus'
11
+ }
12
+
13
+ export function setCommerceConfig(newConfig: Partial<CommerceConfig>) {
14
+ config = { ...config, ...newConfig }
15
+ }
16
+
17
+ export function getCommerceConfig() {
18
+ return config
19
+ }
@@ -0,0 +1,55 @@
1
+ import type { DefineAddCustomFields, NormalizersConstraint } from "./types";
2
+ import type { UnifiedMethods } from "../methods";
3
+
4
+ export type DefineApi<TContext = Record<string, unknown>> = {
5
+ [TKey in keyof UnifiedMethods]: (
6
+ fn: (
7
+ context: TContext,
8
+ ...args: Parameters<UnifiedMethods[TKey]>
9
+ ) => ReturnType<UnifiedMethods[TKey]>,
10
+ ) => (
11
+ context: TContext,
12
+ ...args: Parameters<UnifiedMethods[TKey]>
13
+ ) => ReturnType<UnifiedMethods[TKey]>;
14
+ };
15
+
16
+ export function getApiDefinitions<TContext = Record<string, unknown>>(): DefineApi<TContext> {
17
+ return {
18
+ getCategories: (fn) => fn,
19
+ getCategory: (fn) => fn,
20
+ getCart: (fn) => fn,
21
+ addCartLineItem: (fn) => fn,
22
+ updateCartLineItem: (fn) => fn,
23
+ removeCartLineItem: (fn) => fn,
24
+ applyCouponToCart: (fn) => fn,
25
+ removeCouponFromCart: (fn) => fn,
26
+ setCustomerEmail: (fn) => fn,
27
+ setCartAddress: (fn) => fn,
28
+ getAvailableShippingMethods: (fn) => fn,
29
+ setShippingMethod: (fn) => fn,
30
+ registerCustomer: (fn) => fn,
31
+ loginCustomer: (fn) => fn,
32
+ getCustomer: (fn) => fn,
33
+ logoutCustomer: (fn) => fn,
34
+ updateCustomer: (fn) => fn,
35
+ changeCustomerPassword: (fn) => fn,
36
+ searchProducts: (fn) => fn,
37
+ getProducts: (fn) => fn,
38
+ getProductDetails: (fn) => fn,
39
+ getProductReviews: (fn) => fn,
40
+ createCustomerAddress: (fn) => fn,
41
+ getCustomerAddresses: (fn) => fn,
42
+ updateCustomerAddress: (fn) => fn,
43
+ deleteCustomerAddress: (fn) => fn,
44
+ getCurrencies: (fn) => fn,
45
+ getOrders: (fn) => fn,
46
+ getOrderDetails: (fn) => fn,
47
+ placeOrder: (fn) => fn,
48
+ };
49
+ }
50
+
51
+ export function defineAddCustomFieldsFactory<TNormalizers extends NormalizersConstraint>() {
52
+ return <TInput extends DefineAddCustomFields<TNormalizers>>(input: TInput) => {
53
+ return input;
54
+ };
55
+ }
@@ -0,0 +1,40 @@
1
+ Feature: Unified Extension
2
+
3
+ Scenario: Overriding normalizer
4
+ Given one of the normalizers is overridden
5
+ When extension is created
6
+ And the normalizer is called
7
+ Then the overridden normalizer should be called
8
+ And remaining normalizers should be unchanged
9
+
10
+ Scenario: Add custom fields array with a single element
11
+ Given a custom field is added to one of the normalizers
12
+ When extension is created
13
+ And the normalizer is called
14
+ Then the custom field should be present in the $custom object
15
+ And remaining normalizers should be unchanged
16
+
17
+ Scenario: Add custom fields array with multiple elements
18
+ Given multiple elements of the addCustomFields array override the same normalizer
19
+ When extension is created
20
+ And the normalizer is called
21
+ Then all custom fields should be present in the $custom object
22
+
23
+ Scenario: Nested custom fields
24
+ Given multiple elements of the addCustomFields array override the same normalizer
25
+ And custom fields are objects
26
+ When extension is created
27
+ And the normalizer is called
28
+ Then objects should be merged into the $custom object
29
+
30
+ Scenario: Adding the same custom fields more than once
31
+ Given multiple elements of the addCustomFields array add the same custom field
32
+ When extension is created
33
+ And the normalizer is called
34
+ Then the custom field should have value based on the last element of the addCustomFields array
35
+
36
+ Scenario: Overriding api method
37
+ Given one of the api methods is overridden
38
+ When extension is created
39
+ And the api method is called
40
+ Then the overridden api method should be called
@@ -0,0 +1,39 @@
1
+ interface RawMoney {
2
+ amount: number;
3
+ formattedAmount: string;
4
+ decimalPlaces: number;
5
+ }
6
+
7
+ interface RawProduct {
8
+ id: string;
9
+ name: string;
10
+ }
11
+
12
+ type NormalizerContext = any;
13
+
14
+ export const normalizers = {
15
+ normalizeMoney: (rawMoney: RawMoney, ctx: NormalizerContext) => ({
16
+ amount: rawMoney.amount,
17
+ currency: ctx.currency,
18
+ }),
19
+ normalizeProductCatalogItem: (rawProduct: RawProduct) => ({
20
+ id: rawProduct.id,
21
+ name: rawProduct.name,
22
+ }),
23
+ };
24
+
25
+ export const rawMoneyMock: RawMoney = {
26
+ amount: 10,
27
+ formattedAmount: "10.00",
28
+ decimalPlaces: 2,
29
+ };
30
+
31
+ export const methods = {
32
+ getSuccess() {
33
+ return Promise.resolve({ ok: true });
34
+ },
35
+ };
36
+
37
+ export const getAdditionalNormalizerContext = () => ({
38
+ sku: "123",
39
+ });
@@ -0,0 +1,280 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import type { DefineStepFunction } from "jest-cucumber";
3
+ import { defineFeature, loadFeature } from "jest-cucumber";
4
+ import { beforeEach, expect } from "vitest";
5
+ import { unifiedExtensionFactory } from "./extension";
6
+ import {
7
+ getAdditionalNormalizerContext,
8
+ methods,
9
+ normalizers,
10
+ rawMoneyMock,
11
+ } from "./extension.mocks";
12
+ import type { DefineAddCustomFields } from "./types";
13
+
14
+ const feature = loadFeature("./extension.feature", {
15
+ loadRelativePath: true,
16
+ });
17
+
18
+ defineFeature(feature, (test) => {
19
+ let overrideNormalizers: Partial<typeof normalizers>;
20
+ let addCustomFields: [
21
+ DefineAddCustomFields<typeof normalizers>,
22
+ ...DefineAddCustomFields<typeof normalizers>[],
23
+ ];
24
+ let overrideApiMethods: Partial<typeof methods>;
25
+ const createUnifiedExtension = unifiedExtensionFactory<typeof methods, typeof normalizers, any>({
26
+ normalizers,
27
+ extendApiMethods: methods,
28
+ getAdditionalNormalizerContext,
29
+ });
30
+ let extension: ReturnType<typeof createUnifiedExtension>;
31
+
32
+ beforeEach(() => {
33
+ overrideNormalizers = {};
34
+ addCustomFields = [{}];
35
+ overrideApiMethods = {};
36
+ });
37
+
38
+ function whenTheExtensionIsCreated(when: DefineStepFunction) {
39
+ when("extension is created", () => {
40
+ extension = createUnifiedExtension({
41
+ normalizers: {
42
+ override: overrideNormalizers,
43
+ addCustomFields,
44
+ },
45
+ methods: {
46
+ override: overrideApiMethods,
47
+ },
48
+ config: {},
49
+ });
50
+ });
51
+ }
52
+
53
+ test("Overriding normalizer", ({ given, when, and, then }) => {
54
+ let result: any;
55
+
56
+ given("one of the normalizers is overridden", () => {
57
+ overrideNormalizers = {
58
+ normalizeMoney(rawMoney) {
59
+ return {
60
+ amount: rawMoney.amount,
61
+ currency: "USD",
62
+ };
63
+ },
64
+ };
65
+ });
66
+
67
+ whenTheExtensionIsCreated(when);
68
+
69
+ and("the normalizer is called", () => {
70
+ result = extension.normalizers.normalizeMoney(rawMoneyMock, { currency: "PLN" });
71
+ });
72
+
73
+ then("the overridden normalizer should be called", () => {
74
+ expect(result).toMatchInlineSnapshot(`
75
+ {
76
+ "amount": 10,
77
+ "currency": "USD",
78
+ }
79
+ `);
80
+ });
81
+
82
+ and("remaining normalizers should be unchanged", () => {
83
+ expect(extension.normalizers.normalizeProductCatalogItem).toBeDefined();
84
+ });
85
+ });
86
+ test("Add custom fields array with a single element", ({ given, when, and, then }) => {
87
+ let result: any;
88
+
89
+ given("a custom field is added to one of the normalizers", () => {
90
+ addCustomFields = [
91
+ {
92
+ normalizeMoney: ({ formattedAmount }) => ({
93
+ formattedAmount,
94
+ }),
95
+ },
96
+ ];
97
+ });
98
+
99
+ whenTheExtensionIsCreated(when);
100
+
101
+ and("the normalizer is called", () => {
102
+ result = extension.normalizers.normalizeMoney(rawMoneyMock, { currency: "PLN" });
103
+ });
104
+
105
+ then("the custom field should be present in the $custom object", () => {
106
+ expect(result).toMatchInlineSnapshot(`
107
+ {
108
+ "$custom": {
109
+ "formattedAmount": "10.00",
110
+ },
111
+ "amount": 10,
112
+ "currency": "PLN",
113
+ }
114
+ `);
115
+ });
116
+
117
+ and("remaining normalizers should be unchanged", () => {
118
+ expect(extension.normalizers.normalizeProductCatalogItem).toBeDefined();
119
+ });
120
+ });
121
+ test("Add custom fields array with multiple elements", ({ given, when, and, then }) => {
122
+ given("multiple elements of the addCustomFields array override the same normalizer", () => {
123
+ addCustomFields = [
124
+ {
125
+ normalizeMoney: ({ formattedAmount }) => ({
126
+ formattedAmount,
127
+ }),
128
+ },
129
+ {
130
+ normalizeMoney: ({ decimalPlaces }) => ({
131
+ decimalPlaces,
132
+ }),
133
+ },
134
+ ];
135
+ });
136
+
137
+ whenTheExtensionIsCreated(when);
138
+
139
+ and("the normalizer is called", () => {
140
+ extension.normalizers.normalizeMoney(rawMoneyMock, { currency: "PLN" });
141
+ });
142
+
143
+ then("all custom fields should be present in the $custom object", () => {
144
+ expect(extension.normalizers.normalizeMoney(rawMoneyMock, { currency: "PLN" }))
145
+ .toMatchInlineSnapshot(`
146
+ {
147
+ "$custom": {
148
+ "decimalPlaces": 2,
149
+ "formattedAmount": "10.00",
150
+ },
151
+ "amount": 10,
152
+ "currency": "PLN",
153
+ }
154
+ `);
155
+ });
156
+ });
157
+ test("Nested custom fields", ({ given, and, when, then }) => {
158
+ let result: any;
159
+
160
+ given("multiple elements of the addCustomFields array override the same normalizer", () => {
161
+ addCustomFields = [
162
+ {
163
+ normalizeMoney: () => ({
164
+ nested: {
165
+ nested_field1: "value1",
166
+ nestedLvl2: {
167
+ nestedLvl2_field1: "value1",
168
+ },
169
+ },
170
+ }),
171
+ },
172
+ {
173
+ normalizeMoney: () => ({
174
+ nested: {
175
+ nested_field2: "value2",
176
+ },
177
+ nested2: {
178
+ nested2_field1: "value3",
179
+ },
180
+ }),
181
+ },
182
+ ];
183
+ });
184
+
185
+ and("custom fields are objects", () => {});
186
+
187
+ whenTheExtensionIsCreated(when);
188
+
189
+ and("the normalizer is called", () => {
190
+ result = extension.normalizers.normalizeMoney(rawMoneyMock, { currency: "PLN" });
191
+ });
192
+
193
+ then("objects should be merged into the $custom object", () => {
194
+ expect(result).toMatchInlineSnapshot(`
195
+ {
196
+ "$custom": {
197
+ "nested": {
198
+ "nestedLvl2": {
199
+ "nestedLvl2_field1": "value1",
200
+ },
201
+ "nested_field1": "value1",
202
+ "nested_field2": "value2",
203
+ },
204
+ "nested2": {
205
+ "nested2_field1": "value3",
206
+ },
207
+ },
208
+ "amount": 10,
209
+ "currency": "PLN",
210
+ }
211
+ `);
212
+ });
213
+ });
214
+
215
+ test("Adding the same custom fields more than once", ({ given, when, and, then }) => {
216
+ let result: any;
217
+
218
+ given("multiple elements of the addCustomFields array add the same custom field", () => {
219
+ addCustomFields = [
220
+ {
221
+ normalizeMoney: ({ formattedAmount, decimalPlaces }) => ({
222
+ formattedAmount,
223
+ decimalPlaces,
224
+ }),
225
+ },
226
+ {
227
+ normalizeMoney: () => ({
228
+ formattedAmount: "overridden",
229
+ }),
230
+ },
231
+ ];
232
+ });
233
+
234
+ whenTheExtensionIsCreated(when);
235
+
236
+ and("the normalizer is called", () => {
237
+ result = extension.normalizers.normalizeMoney(rawMoneyMock, { currency: "PLN" });
238
+ });
239
+
240
+ then(
241
+ "the custom field should have value based on the last element of the addCustomFields array",
242
+ () => {
243
+ expect(result).toMatchInlineSnapshot(`
244
+ {
245
+ "$custom": {
246
+ "decimalPlaces": 2,
247
+ "formattedAmount": "overridden",
248
+ },
249
+ "amount": 10,
250
+ "currency": "PLN",
251
+ }
252
+ `);
253
+ },
254
+ );
255
+ });
256
+
257
+ test("Overriding api method", ({ given, when, and, then }) => {
258
+ let result: any;
259
+
260
+ given("one of the api methods is overridden", () => {
261
+ overrideApiMethods = {
262
+ getSuccess: () => Promise.resolve({ ok: false }),
263
+ };
264
+ });
265
+
266
+ whenTheExtensionIsCreated(when);
267
+
268
+ and("the api method is called", async () => {
269
+ result = await extension.extendApiMethods.getSuccess();
270
+ });
271
+
272
+ then("the overridden api method should be called", () => {
273
+ expect(result).toMatchInlineSnapshot(`
274
+ {
275
+ "ok": false,
276
+ }
277
+ `);
278
+ });
279
+ });
280
+ });