@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.
- package/app/components/catalog/product/ProductAccordion/ProductAccordion.vue +39 -0
- package/app/components/catalog/product/ProductAccordion/__tests__/ProductAccordion.spec.ts +15 -0
- package/app/components/catalog/product/ProductAccordion/types.ts +5 -0
- package/app/components/catalog/product/ProductProperties/ProductProperties.vue +50 -0
- package/app/components/catalog/product/ProductProperties/__tests__/ProductProperties.spec.ts +15 -0
- package/app/components/catalog/product/ProductProperties/types.ts +5 -0
- package/app/components/catalog/product/ProductSlider/ProductSlider.vue +28 -0
- package/app/components/catalog/product/ProductSlider/__tests__/ProductSlider.spec.ts +14 -0
- package/app/components/catalog/product/ProductSlider/types.ts +7 -0
- package/app/components/catalog/product/RecommendedProducts/RecommendedProducts.vue +12 -0
- package/app/components/catalog/product/RecommendedProducts/types.ts +5 -0
- package/app/components/catalog/product/RenderContentProductSlider/RenderContentProductSlider.vue +11 -0
- package/app/components/catalog/product/add-attribute.vue +54 -0
- package/app/components/catalog/product/add-product-type.vue +54 -0
- package/app/components/catalog/product/add-product.vue +53 -0
- package/app/components/catalog/product/add-showcase.vue +52 -0
- package/app/components/catalog/product/add-station.vue +54 -0
- package/app/components/catalog/product/bestsellers.vue +57 -0
- package/app/components/catalog/product/bidding.vue +93 -0
- package/app/components/catalog/product/colorOptions.vue +58 -0
- package/app/components/catalog/product/deals.vue +46 -0
- package/app/components/catalog/product/exclusives.vue +56 -0
- package/app/components/catalog/product/featuredproducts.vue +57 -0
- package/app/components/catalog/product/giftCard.vue +63 -0
- package/app/components/catalog/product/latestproducts.vue +46 -0
- package/app/components/catalog/product/productCard.vue +105 -0
- package/app/components/catalog/product/productCompare.vue +60 -0
- package/app/components/catalog/product/productCompareTable.vue +441 -0
- package/app/components/catalog/product/productDetails.vue +126 -0
- package/app/components/catalog/product/productFaqs.vue +17 -0
- package/app/components/catalog/product/productGallery.vue +16 -0
- package/app/components/catalog/product/productQty.vue +54 -0
- package/app/components/catalog/product/productReviews.vue +56 -0
- package/app/components/catalog/product/productSpecs.vue +116 -0
- package/app/components/catalog/product/radiostation.vue +36 -0
- package/app/components/catalog/product/recentlyviewed.vue +43 -0
- package/app/components/catalog/product/relatedbrands.vue +54 -0
- package/app/components/catalog/product/relatedproducts.vue +43 -0
- package/app/components/catalog/product/relatedstations.vue +40 -0
- package/app/components/catalog/product/shippingOptions.vue +41 -0
- package/app/components/catalog/product/sizeOptions.vue +42 -0
- package/app/components/catalog/product/update-attribute-set.vue +209 -0
- package/app/components/catalog/product/update-attribute.vue +118 -0
- package/app/components/catalog/product/update-product.vue +372 -0
- package/app/components/catalog/product/update-showcase.vue +153 -0
- package/app/components/catalog/shops/relatedstores.vue +37 -0
- package/app/components/catalog/shops/restaurant.vue +66 -0
- package/app/components/catalog/shops/stores.vue +44 -0
- package/app/components/catalog/vendor/README.md +3 -0
- package/app/components/catalog/vendor/blocks/biggestcustomers.vue +33 -0
- package/app/components/catalog/vendor/blocks/lowestselling.vue +33 -0
- package/app/components/catalog/vendor/blocks/topcategories.vue +33 -0
- package/app/components/catalog/vendor/blocks/topproducts.vue +27 -0
- package/app/components/catalog/vendor/pages/attributes.vue +43 -0
- package/app/components/catalog/vendor/pages/commissions.vue +43 -0
- package/app/components/catalog/vendor/pages/crm.vue +67 -0
- package/app/components/catalog/vendor/pages/dashboard.vue +46 -0
- package/app/components/catalog/vendor/pages/emails.vue +43 -0
- package/app/components/catalog/vendor/pages/enquiries.vue +43 -0
- package/app/components/catalog/vendor/pages/invoices.vue +43 -0
- package/app/components/catalog/vendor/pages/orders.vue +68 -0
- package/app/components/catalog/vendor/pages/products.vue +55 -0
- package/app/components/catalog/vendor/pages/reviews.vue +48 -0
- package/app/components/catalog/vendor/pages/shipments.vue +43 -0
- package/app/components/catalog/vendor/pages/stores.vue +43 -0
- package/app/components/categories/chart/[id].vue +200 -0
- package/app/components/categories/chart/add-chart.vue +142 -0
- package/app/components/categories/chart/chart.vue +82 -0
- package/app/components/categories/chart/monthlyChart.vue +46 -0
- package/app/components/categories/chart/weeklyChart.vue +46 -0
- package/app/components/categories/chart/yearlyChart.vue +46 -0
- package/app/components/categories/charts.vue +118 -0
- package/app/components/categories/deals.vue +101 -0
- package/app/components/categories/eats.vue +49 -0
- package/app/components/categories/restaurants.vue +26 -0
- package/app/components/categories/station/[id].vue +72 -0
- package/app/components/categories/stations.vue +124 -0
- package/app/components/categories/time/time.vue +63 -0
- package/app/components/categories/travel.vue +75 -0
- package/app/components/categories/weather/weather.vue +44 -0
- package/app/components/content/blocks/breadcrumbs.vue +0 -0
- package/app/components/content/blocks/currencySwitcher.vue +0 -0
- package/app/components/content/blocks/languageSwitcher.vue +0 -0
- package/app/components/content/blocks/videoproduct.vue +9 -0
- package/app/components/content/pages/checkout.vue +118 -0
- package/app/components/content/pages/meeoviGlobal.vue +68 -0
- package/app/components/content/pages/pickup-locations.vue +238 -0
- package/app/components/content/pages/showcases.vue +90 -0
- package/app/components/content/pages/success.vue +60 -0
- package/app/components/marketing/add-brand.vue +54 -0
- package/app/components/marketing/add-incentive.vue +54 -0
- package/app/components/marketing/promotions/giftcards.vue +102 -0
- package/app/components/marketing/promotions/subscriptions.vue +121 -0
- package/app/components/marketing/update-incentive.vue +326 -0
- package/app/components/menus/lowernav.vue +78 -0
- package/app/components/partials/LocaleSelector.vue +24 -0
- package/app/components/partials/ShoppingCart.vue +128 -0
- package/app/components/partials/StripePayment.vue +149 -0
- package/app/components/partials/addToCartBtn.vue +40 -0
- package/app/components/partials/cartItem.vue +124 -0
- package/app/components/partials/checkoutButton.vue +44 -0
- package/app/components/partials/compareBtn.vue +68 -0
- package/app/components/partials/ratings.vue +13 -0
- package/app/components/partials/store/CurrencySelector.vue +133 -0
- package/app/components/partials/store/StoreSwitcher.vue +13 -0
- package/app/components/placeholders/Comments.vue +15 -0
- package/app/components/placeholders/CreateListBtn.vue +7 -0
- package/app/components/placeholders/Event.vue +9 -0
- package/app/components/placeholders/ListShowcases.vue +9 -0
- package/app/components/placeholders/Short.vue +9 -0
- package/app/components/placeholders/Space.vue +9 -0
- package/app/components/placeholders/Tag.vue +7 -0
- package/app/components/related/brandCard.vue +41 -0
- package/app/components/related/incentiveCard.vue +44 -0
- package/app/components/related/invoiceCard.vue +43 -0
- package/app/components/related/orderCard.vue +43 -0
- package/app/components/related/relatedproducts.vue +17 -0
- package/app/components/sales/CartPageContent/CartPageContent.vue +37 -0
- package/app/components/sales/CheckoutAddress/CheckoutAddress.vue +50 -0
- package/app/components/sales/CheckoutAddress/__tests__/CheckoutAddress.spec.ts +16 -0
- package/app/components/sales/CheckoutAddress/types.ts +16 -0
- package/app/components/sales/CheckoutPayment/CheckoutPayment.vue +68 -0
- package/app/components/sales/CheckoutPayment/__tests__/CheckoutPayment.spec.ts +14 -0
- package/app/components/sales/CheckoutPayment/types.ts +12 -0
- package/app/components/sales/OrderSummary/OrderSummary.vue +57 -0
- package/app/components/sales/OrderSummary/__tests__/ContactInformation.spec.ts +52 -0
- package/app/components/sales/OrderSummary/types.ts +5 -0
- package/app/components/sales/incentives.vue +223 -0
- package/app/components/sales/invoices.vue +107 -0
- package/app/components/sales/orders.vue +378 -0
- package/app/components/sales/shipments.vue +65 -0
- package/app/components/sales/transactions.vue +109 -0
- package/app/components/shop/add-shop.vue +54 -0
- package/app/components/shop/cart/cartItem.vue +182 -0
- package/app/components/shop/cart/checkout.vue +415 -0
- package/app/components/shop/checkout/StripeCardElement.vue +206 -0
- package/app/components/shop/checkout/StripeCheckout.vue +49 -0
- package/app/components/shop/checkout/addressBilling.vue +263 -0
- package/app/components/shop/checkout/addressShipping.vue +175 -0
- package/app/components/shop/checkout/cart/ProductItem.vue +56 -0
- package/app/components/shop/checkout/cart/PromotionItem.vue +53 -0
- package/app/composables/_types.ts +18 -0
- package/app/composables/adapters/abstract/cartAdapter.ts +0 -0
- package/app/composables/adapters/abstract/categoryAdapter.ts +0 -0
- package/app/composables/adapters/abstract/customerAdapter.ts +0 -0
- package/app/composables/adapters/abstract/inventoryAdapter.ts +0 -0
- package/app/composables/adapters/abstract/orderAdapter.ts +0 -0
- package/app/composables/adapters/abstract/productAdapter.ts +7 -0
- package/app/composables/cart/registry.ts +20 -0
- package/app/composables/cart/types.ts +18 -0
- package/app/composables/cart/useCart.ts +15 -0
- package/app/composables/config.ts +19 -0
- package/app/composables/defs/apiDefinitions.ts +55 -0
- package/app/composables/defs/extension.feature +40 -0
- package/app/composables/defs/extension.mocks.ts +39 -0
- package/app/composables/defs/extension.test.ts +280 -0
- package/app/composables/defs/extension.ts +236 -0
- package/app/composables/defs/index.ts +3 -0
- package/app/composables/defs/types.ts +136 -0
- package/app/composables/domain/cart.ts +0 -0
- package/app/composables/domain/category.ts +0 -0
- package/app/composables/domain/order.ts +0 -0
- package/app/composables/domain/price.ts +0 -0
- package/app/composables/domain/product.ts +8 -0
- package/app/composables/domain/reward.ts +0 -0
- package/app/composables/domain/transactions.ts +0 -0
- package/app/composables/helpers/contextualizedNormalizers.feature +14 -0
- package/app/composables/helpers/contextualizedNormalizers.test.ts +85 -0
- package/app/composables/helpers/contextualizedNormalizers.ts +20 -0
- package/app/composables/helpers/index.ts +1 -0
- package/app/composables/index.ts +6 -0
- package/app/composables/methods/auth.ts +83 -0
- package/app/composables/methods/cart.ts +119 -0
- package/app/composables/methods/category.ts +27 -0
- package/app/composables/methods/checkout.ts +54 -0
- package/app/composables/methods/customer.ts +52 -0
- package/app/composables/methods/helpers.ts +5 -0
- package/app/composables/methods/index.ts +75 -0
- package/app/composables/methods/order.ts +39 -0
- package/app/composables/methods/product.ts +95 -0
- package/app/composables/methods/settings.ts +16 -0
- package/app/composables/models/cart.ts +95 -0
- package/app/composables/models/category.ts +13 -0
- package/app/composables/models/checkout.ts +17 -0
- package/app/composables/models/customer.ts +16 -0
- package/app/composables/models/facets.ts +25 -0
- package/app/composables/models/index.ts +94 -0
- package/app/composables/models/order.ts +43 -0
- package/app/composables/models/product.ts +73 -0
- package/app/composables/models/shared.ts +75 -0
- package/app/composables/products/registry.ts +20 -0
- package/app/composables/products/types.ts +13 -0
- package/app/composables/products/useEvents.ts +0 -0
- package/app/composables/products/useGiftCards.ts +0 -0
- package/app/composables/products/useProducts.ts +12 -0
- package/app/composables/products/useSubscriptions.ts +0 -0
- package/app/composables/registry.ts +21 -0
- package/app/composables/stores/cart.ts +218 -0
- package/app/composables/stores/cartStore.ts +300 -0
- package/app/composables/stores/checkout.ts +19 -0
- package/app/composables/stores/compare.ts +65 -0
- package/app/composables/stores/currency.js +29 -0
- package/app/composables/stores/digital-products.js +11 -0
- package/app/composables/stores/index.js +0 -0
- package/app/composables/stores/orders.ts +161 -0
- package/app/composables/stores/product.ts +26 -0
- package/app/composables/stores/productList.ts +0 -0
- package/app/composables/stores/productListInfo.ts +0 -0
- package/app/composables/stores/products.ts +112 -0
- package/app/composables/stores/recentlyViewedProducts.ts +0 -0
- package/app/composables/stores/review.ts +25 -0
- package/app/composables/stores/storeInPickUp.ts +22 -0
- package/app/composables/stores/user.ts +20 -0
- package/app/composables/stores/wishlist.ts +19 -0
- package/app/composables/types/Order.type.ts +181 -0
- package/app/composables/types/index.ts +285 -0
- package/app/composables/types/product.ts +14 -0
- package/app/composables/useBreakpoints/index.ts +1 -0
- package/app/composables/useBreakpoints/useBreakpoints.ts +28 -0
- package/app/composables/useCart/__tests__/useCart.spec.ts +11 -0
- package/app/composables/useCart/index.ts +1 -0
- package/app/composables/useCart/types.ts +17 -0
- package/app/composables/useCart/useCart.ts +46 -0
- package/app/composables/useCartShippingMethods/__tests__/useCartShippingMethods.spec.ts +11 -0
- package/app/composables/useCartShippingMethods/index.ts +1 -0
- package/app/composables/useCartShippingMethods/types.ts +17 -0
- package/app/composables/useCartShippingMethods/useCartShippingMethods.ts +47 -0
- package/app/composables/useCatalog.ts +64 -0
- package/app/composables/useContent/index.ts +1 -0
- package/app/composables/useContent/types.ts +44 -0
- package/app/composables/useContent/useContent.ts +45 -0
- package/app/composables/useContent.ts +57 -0
- package/app/composables/useCustomer/__tests__/useCustomer.spec.ts +25 -0
- package/app/composables/useCustomer/index.ts +2 -0
- package/app/composables/useCustomer/types.ts +17 -0
- package/app/composables/useCustomer/useCustomer.ts +40 -0
- package/app/composables/useCustomerAddress/__tests__/useCustomerAddress.spec.ts +11 -0
- package/app/composables/useCustomerAddress/index.ts +2 -0
- package/app/composables/useCustomerAddress/types.ts +17 -0
- package/app/composables/useCustomerAddress/useCustomerAddress.ts +55 -0
- package/app/composables/useCustomerOrder/__tests__/useCustomerOrder.spec.ts +11 -0
- package/app/composables/useCustomerOrder/adress.ts +10 -0
- package/app/composables/useCustomerOrder/index.ts +2 -0
- package/app/composables/useCustomerOrder/product.ts +37 -0
- package/app/composables/useCustomerOrder/types.ts +40 -0
- package/app/composables/useCustomerOrder/useCustomerOrder.ts +63 -0
- package/app/composables/useCustomerOrders/__tests__/useCustomerOrders.spec.ts +11 -0
- package/app/composables/useCustomerOrders/index.ts +2 -0
- package/app/composables/useCustomerOrders/types.ts +20 -0
- package/app/composables/useCustomerOrders/useCustomerOrders.ts +56 -0
- package/app/composables/useCustomerReturns/__tests__/useCustomerReturns.spec.ts +11 -0
- package/app/composables/useCustomerReturns/index.ts +2 -0
- package/app/composables/useCustomerReturns/types.ts +17 -0
- package/app/composables/useCustomerReturns/useCustomerReturns.ts +41 -0
- package/app/composables/useHandleError/index.ts +1 -0
- package/app/composables/useHandleError/types.ts +11 -0
- package/app/composables/useHandleError/useHandleError.ts +27 -0
- package/app/composables/usePageTitle.ts +16 -0
- package/app/composables/useProduct/index.ts +2 -0
- package/app/composables/useProduct/types.ts +17 -0
- package/app/composables/useProduct/useProduct.ts +42 -0
- package/app/composables/useProductAttribute/__tests__/useProduct.mock.ts +31 -0
- package/app/composables/useProductAttribute/__tests__/useProductAttribute.spec.ts +14 -0
- package/app/composables/useProductAttribute/index.ts +1 -0
- package/app/composables/useProductAttribute/useProductAttribute.ts +37 -0
- package/app/composables/useProductRecommended/__tests__/useProductRecommended.spec.ts +12 -0
- package/app/composables/useProductRecommended/index.ts +1 -0
- package/app/composables/useProductRecommended/types.ts +17 -0
- package/app/composables/useProductRecommended/useProductRecommended.ts +43 -0
- package/app/composables/useProductReviews/__tests__/productReviews.mock.ts +20 -0
- package/app/composables/useProductReviews/__tests__/useProductReviews.spec.ts +22 -0
- package/app/composables/useProductReviews/index.ts +2 -0
- package/app/composables/useProductReviews/types.ts +17 -0
- package/app/composables/useProductReviews/useProductReviews.ts +46 -0
- package/app/composables/useProducts/__tests__/useProducts.spec.ts +11 -0
- package/app/composables/useProducts/types.ts +22 -0
- package/app/composables/useProducts/useProducts.ts +41 -0
- package/app/composables/utils/countryList.ts +14 -0
- package/app/composables/utils/currency.js +56 -0
- package/app/composables/utils/glossary.ts +0 -0
- package/app/composables/utils/importExport.ts +0 -0
- package/app/composables/utils/index.js +0 -0
- package/app/composables/utils/print.ts +0 -0
- package/app/composables/utils/shopThemes.ts +0 -0
- package/app/composables/utils/statistics.ts +0 -0
- package/app/composables/utils/stock.ts +0 -0
- package/app/composables/utils/stripe.ts +16 -0
- package/app/composables/utils/taxation.ts +0 -0
- package/app/composables/utils/tellFriends.ts +0 -0
- package/app/composables/validationRules/index.ts +1 -0
- package/app/composables/validationRules/password.feature +67 -0
- package/app/composables/validationRules/password.test.ts +89 -0
- package/app/composables/validationRules/password.ts +25 -0
- package/app/composables/vendors/index.ts +0 -0
- package/app/composables/vendors/registry.ts +0 -0
- package/app/composables/vendors/useAffiliates.ts +0 -0
- package/app/composables/vendors/useCommission.ts +0 -0
- package/app/modules/vue-head/composables/useHead.ts +3 -0
- package/app/pages/brand/[...slug].vue +92 -0
- package/app/pages/brands.vue +90 -0
- package/app/pages/cart.vue +142 -0
- package/app/pages/compare.vue +166 -0
- package/app/pages/departments/[...slug].vue +385 -0
- package/app/pages/departments/category/[...slug].vue +135 -0
- package/app/pages/incentive/[...id].vue +66 -0
- package/app/pages/invoice/[id].vue +309 -0
- package/app/pages/order/[id].vue +327 -0
- package/app/pages/product/[...id].vue +309 -0
- package/app/pages/product/showcases/index.vue +86 -0
- package/app/pages/shipment/[...id].vue +176 -0
- package/app/pages/shop/[...slug].vue +158 -0
- package/app/pages/shops.vue +76 -0
- package/app/pages/subscription/[...id].vue +147 -0
- package/app/pages/transaction/[...id].vue +74 -0
- package/app/types/shims-imports.d.ts +13 -0
- package/app/utils/client.ts +26 -0
- package/app/utils/index.ts +53 -0
- package/app/utils/normalizer.ts +23 -0
- package/app/utils/normalizers/magento.ts +29 -0
- package/app/utils/normalizers/shopify.ts +29 -0
- package/global.d.ts +149 -0
- package/index.js +3 -0
- package/package.json +3 -9
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { toRefs } from '@vueuse/shared';
|
|
2
|
+
import addressData from './adress';
|
|
3
|
+
import productData from './product';
|
|
4
|
+
import type {
|
|
5
|
+
UseCustomerOrderReturn,
|
|
6
|
+
UseCustomerOrderState,
|
|
7
|
+
FetchCustomerOrder,
|
|
8
|
+
OrderData,
|
|
9
|
+
} from './types';
|
|
10
|
+
import { useAsyncData, useState } from 'nuxt/app';
|
|
11
|
+
import { useHandleError } from '../useHandleError';
|
|
12
|
+
|
|
13
|
+
const order: OrderData = {
|
|
14
|
+
id: '0e4fec5a-61e6-48b8-94cc-d5f77687e2b0',
|
|
15
|
+
date: '2022-08-11',
|
|
16
|
+
paymentAmount: 295.87,
|
|
17
|
+
paymentMethod: 'Credit Card',
|
|
18
|
+
shipping: 'Standard (FREE)',
|
|
19
|
+
summary: {
|
|
20
|
+
subtotal: 7037.99,
|
|
21
|
+
delivery: 0,
|
|
22
|
+
estimatedTax: 457.47,
|
|
23
|
+
total: 295.87,
|
|
24
|
+
},
|
|
25
|
+
billingAddress: addressData,
|
|
26
|
+
shippingAddress: addressData,
|
|
27
|
+
status: 'Completed',
|
|
28
|
+
products: [productData, productData],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars
|
|
32
|
+
const getCustomerOrder = (id: string) => order;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @description Composable managing customer order data
|
|
36
|
+
* @returns {@link UseCustomerOrderReturn}
|
|
37
|
+
* @example
|
|
38
|
+
* const { data, loading, fetchCustomerOrder } = useCustomerOrder();
|
|
39
|
+
*/
|
|
40
|
+
export const useCustomerOrder: UseCustomerOrderReturn = (id) => {
|
|
41
|
+
const state = useState<UseCustomerOrderState>(`useCustomerOrder-${id}`, () => ({
|
|
42
|
+
data: null,
|
|
43
|
+
loading: false,
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
/** Function for fetching customer order data
|
|
47
|
+
* @example
|
|
48
|
+
* fetchCustomerOrder();
|
|
49
|
+
*/
|
|
50
|
+
const fetchCustomerOrder: FetchCustomerOrder = async (id) => {
|
|
51
|
+
state.value.loading = true;
|
|
52
|
+
const { data, error } = await useAsyncData(() => Promise.resolve(getCustomerOrder(id)));
|
|
53
|
+
useHandleError(error.value);
|
|
54
|
+
state.value.data = data.value;
|
|
55
|
+
state.value.loading = false;
|
|
56
|
+
return data as unknown as ReturnType<FetchCustomerOrder>;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
fetchCustomerOrder,
|
|
61
|
+
...toRefs(state.value),
|
|
62
|
+
};
|
|
63
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useCustomerOrders } from '~/composables/useCustomerOrders/useCustomerOrders';
|
|
2
|
+
|
|
3
|
+
describe('useCustomerOrders', () => {
|
|
4
|
+
it('should return customer orders data', async () => {
|
|
5
|
+
const { fetchCustomerOrders, data } = useCustomerOrders();
|
|
6
|
+
|
|
7
|
+
await fetchCustomerOrders();
|
|
8
|
+
|
|
9
|
+
expect(data.value).not.toBeUndefined();
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
import type { Maybe } from '../_types';
|
|
3
|
+
import type { OrderData } from '../useCustomerOrder/types';
|
|
4
|
+
|
|
5
|
+
export type OrdersData = Pick<OrderData, 'id' | 'date' | 'paymentAmount' | 'status'>[];
|
|
6
|
+
|
|
7
|
+
export interface UseCustomerOrdersState {
|
|
8
|
+
data: Maybe<OrdersData>;
|
|
9
|
+
loading: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type FetchCustomerOrders = () => Promise<Ref<Maybe<OrdersData>>>;
|
|
13
|
+
|
|
14
|
+
export interface UseCustomerOrders {
|
|
15
|
+
data: Readonly<Ref<UseCustomerOrdersState['data']>>;
|
|
16
|
+
loading: Readonly<Ref<boolean>>;
|
|
17
|
+
fetchCustomerOrders: FetchCustomerOrders;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type UseCustomerOrdersReturn = () => UseCustomerOrders;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { toRefs } from '@vueuse/shared';
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import type { Ref } from 'vue';
|
|
4
|
+
import type { Maybe } from '../_types';
|
|
5
|
+
import type { OrderData } from '../useCustomerOrder/types';
|
|
6
|
+
import type {
|
|
7
|
+
UseCustomerOrdersReturn,
|
|
8
|
+
UseCustomerOrdersState,
|
|
9
|
+
FetchCustomerOrders,
|
|
10
|
+
OrdersData,
|
|
11
|
+
} from './types';
|
|
12
|
+
import { useAsyncData, useState } from 'nuxt/app';
|
|
13
|
+
import { useHandleError } from '../useHandleError';
|
|
14
|
+
|
|
15
|
+
const order: Pick<OrderData, 'id' | 'date' | 'paymentAmount'> = {
|
|
16
|
+
id: '0e4fec5a-61e6-48b8-94cc-d5f77687e2b0',
|
|
17
|
+
date: '2022-08-11',
|
|
18
|
+
paymentAmount: 295.87,
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* @description Composable managing customer orders data
|
|
22
|
+
* @returns {@link UseCustomerOrdersReturn}
|
|
23
|
+
* @example
|
|
24
|
+
* const { data, loading, fetchCustomerOrders } = useCustomerOrders();
|
|
25
|
+
*/
|
|
26
|
+
export const useCustomerOrders: UseCustomerOrdersReturn = () => {
|
|
27
|
+
const state = useState<UseCustomerOrdersState>('useCustomerOrders', () => ({
|
|
28
|
+
data: null,
|
|
29
|
+
loading: false,
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
/** Function for fetching customer orders data
|
|
33
|
+
* @example
|
|
34
|
+
* fetchCustomerOrders();
|
|
35
|
+
*/
|
|
36
|
+
const fetchCustomerOrders: FetchCustomerOrders = async () => {
|
|
37
|
+
state.value.loading = true;
|
|
38
|
+
const { data, error } = await useAsyncData(() =>
|
|
39
|
+
Promise.resolve([
|
|
40
|
+
{ ...order, status: 'Completed' },
|
|
41
|
+
{ ...order, status: 'Shipped' },
|
|
42
|
+
{ ...order, status: 'Open' },
|
|
43
|
+
{ ...order, status: 'Cancelled' },
|
|
44
|
+
] as OrderData[]),
|
|
45
|
+
);
|
|
46
|
+
useHandleError(error.value);
|
|
47
|
+
state.value.data = data.value;
|
|
48
|
+
state.value.loading = false;
|
|
49
|
+
return computed(() => state.value.data) as unknown as Ref<Maybe<OrdersData>>;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
fetchCustomerOrders,
|
|
54
|
+
...toRefs(state.value),
|
|
55
|
+
};
|
|
56
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useCustomerReturns } from '~/composables/useCustomerReturns/useCustomerReturns';
|
|
2
|
+
|
|
3
|
+
describe('useCustomerReturns', () => {
|
|
4
|
+
it('should return account data', async () => {
|
|
5
|
+
const { fetchCustomerReturns, data } = useCustomerReturns();
|
|
6
|
+
|
|
7
|
+
await fetchCustomerReturns();
|
|
8
|
+
|
|
9
|
+
expect(data.value).not.toBeUndefined();
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
import { Maybe } from '../_types';
|
|
3
|
+
|
|
4
|
+
export interface UseCustomerReturnsState {
|
|
5
|
+
data: Maybe<unknown[]>;
|
|
6
|
+
loading: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type FetchCustomerReturns = () => Promise<Ref<unknown[] | null>>;
|
|
10
|
+
|
|
11
|
+
export interface UseCustomerReturns {
|
|
12
|
+
data: Readonly<Ref<UseCustomerReturnsState['data']>>;
|
|
13
|
+
loading: Readonly<Ref<boolean>>;
|
|
14
|
+
fetchCustomerReturns: FetchCustomerReturns;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type UseCustomerReturnsReturn = () => UseCustomerReturns;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { toRefs } from '@vueuse/shared';
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import type { Ref } from 'vue';
|
|
4
|
+
import type {
|
|
5
|
+
UseCustomerReturnsReturn,
|
|
6
|
+
UseCustomerReturnsState,
|
|
7
|
+
FetchCustomerReturns,
|
|
8
|
+
} from './types';
|
|
9
|
+
import { useAsyncData, useState } from 'nuxt/app';
|
|
10
|
+
import { useHandleError } from '../useHandleError';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @description Composable managing returns data
|
|
14
|
+
* @returns {@link UseCustomerReturnsReturn}
|
|
15
|
+
* @example
|
|
16
|
+
* const { data, loading, fetchCustomerReturns } = useCustomerReturns();
|
|
17
|
+
*/
|
|
18
|
+
export const useCustomerReturns: UseCustomerReturnsReturn = () => {
|
|
19
|
+
const state = useState<UseCustomerReturnsState>(`useCustomerReturns`, () => ({
|
|
20
|
+
data: [],
|
|
21
|
+
loading: false,
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
/** Function for fetching returns data
|
|
25
|
+
* @example
|
|
26
|
+
* fetchCustomerReturns();
|
|
27
|
+
*/
|
|
28
|
+
const fetchCustomerReturns: FetchCustomerReturns = async () => {
|
|
29
|
+
state.value.loading = true;
|
|
30
|
+
const { data, error } = await useAsyncData(() => Promise.resolve([]));
|
|
31
|
+
useHandleError(error.value);
|
|
32
|
+
state.value.data = data.value;
|
|
33
|
+
state.value.loading = false;
|
|
34
|
+
return computed(() => state.value.data) as unknown as Ref<unknown[] | null>;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
fetchCustomerReturns,
|
|
39
|
+
...toRefs(state.value),
|
|
40
|
+
};
|
|
41
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useHandleError';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { UseHandleError, ErrorParams } from './types';
|
|
2
|
+
import { createError } from 'h3';
|
|
3
|
+
|
|
4
|
+
const defaultError: ErrorParams = {
|
|
5
|
+
status: 500,
|
|
6
|
+
message: 'An error occurred',
|
|
7
|
+
statusMessage: 'An error occurred',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @description Composable for handling errors.
|
|
12
|
+
* @param error {@link ErrorParams}
|
|
13
|
+
* @returns Throws an error if there is one.
|
|
14
|
+
* @example
|
|
15
|
+
* const { data, error } = await fetch(data);
|
|
16
|
+
* useHandleError(error.value);
|
|
17
|
+
*/
|
|
18
|
+
export const useHandleError: UseHandleError = (error) => {
|
|
19
|
+
if (error) {
|
|
20
|
+
throw createError({
|
|
21
|
+
statusCode: error.status || defaultError.status,
|
|
22
|
+
message: error.message ?? defaultError.message,
|
|
23
|
+
statusMessage: error.message ?? defaultError.statusMessage,
|
|
24
|
+
fatal: true,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import useHead from "../modules/vue-head/composables/useHead";
|
|
2
|
+
import { useAppConfig } from "nuxt/app";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Composable for setting the page title.
|
|
6
|
+
* Used in layouts. Title can be changed in pages through the `useHead` composable.
|
|
7
|
+
*/
|
|
8
|
+
export const usePageTitle = () => {
|
|
9
|
+
const { titleSuffix } = useAppConfig();
|
|
10
|
+
|
|
11
|
+
useHead({
|
|
12
|
+
titleTemplate: (titleChunk: any) => {
|
|
13
|
+
return titleChunk ? `${titleChunk} | ${titleSuffix}` : titleSuffix;
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
import type { SfProduct, Maybe } from '../_types';
|
|
3
|
+
|
|
4
|
+
export interface UseProductState {
|
|
5
|
+
data: Maybe<SfProduct>;
|
|
6
|
+
loading: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type FetchProduct = (slug: string) => Promise<Ref<Maybe<SfProduct>>>;
|
|
10
|
+
|
|
11
|
+
export interface UseProduct {
|
|
12
|
+
data: Readonly<Ref<UseProductState['data']>>;
|
|
13
|
+
loading: Readonly<Ref<boolean>>;
|
|
14
|
+
fetchProduct: FetchProduct;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type UseProductReturn = (slug: string) => UseProduct;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { toRefs } from '@vueuse/shared';
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import type { Ref } from 'vue';
|
|
4
|
+
import type { Maybe, Product } from '../_types';
|
|
5
|
+
import type { UseProductReturn, UseProductState, FetchProduct } from './types';
|
|
6
|
+
import { getCommerceClient } from '../../utils/client';
|
|
7
|
+
import { useAsyncData, useState } from 'nuxt/app';
|
|
8
|
+
import { useHandleError } from '../useHandleError';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @description Composable managing product data
|
|
12
|
+
* @param {string} slug Product slug
|
|
13
|
+
* @returns {@link UseProductReturn}
|
|
14
|
+
* @example
|
|
15
|
+
* const { data, loading, fetchProduct } = useProduct('product-slug');
|
|
16
|
+
*/
|
|
17
|
+
export const useProduct: UseProductReturn = (slug) => {
|
|
18
|
+
const state = useState<UseProductState>(`useProduct-${slug}`, () => ({
|
|
19
|
+
data: null,
|
|
20
|
+
loading: false,
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
/** Function for fetching product data
|
|
24
|
+
* @param {string} slug Product slug
|
|
25
|
+
* @example
|
|
26
|
+
* fetchProduct('product-slug');
|
|
27
|
+
*/
|
|
28
|
+
const fetchProduct: FetchProduct = async (slug: string) => {
|
|
29
|
+
state.value.loading = true;
|
|
30
|
+
const client = getCommerceClient();
|
|
31
|
+
const { data, error } = await useAsyncData(() => client.getProduct?.(slug) ?? client.fetchProduct?.(slug));
|
|
32
|
+
useHandleError(error.value);
|
|
33
|
+
state.value.data = data.value as unknown as Maybe<Product>;
|
|
34
|
+
state.value.loading = false;
|
|
35
|
+
return computed(() => state.value.data) as unknown as Ref<Maybe<Product>>;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
fetchProduct,
|
|
40
|
+
...toRefs(state.value),
|
|
41
|
+
};
|
|
42
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SfProduct } from '../../_types';
|
|
2
|
+
|
|
3
|
+
export const mockProduct: SfProduct = {
|
|
4
|
+
id: '1',
|
|
5
|
+
sku: 'product-1',
|
|
6
|
+
name: 'Product 1',
|
|
7
|
+
slug: 'product-1',
|
|
8
|
+
description: '',
|
|
9
|
+
rating: {
|
|
10
|
+
average: 4.5,
|
|
11
|
+
count: 133,
|
|
12
|
+
},
|
|
13
|
+
price: {
|
|
14
|
+
isDiscounted: false,
|
|
15
|
+
regularPrice: {
|
|
16
|
+
currency: 'USD',
|
|
17
|
+
amount: 100.0,
|
|
18
|
+
precisionAmount: '2',
|
|
19
|
+
},
|
|
20
|
+
value: {
|
|
21
|
+
currency: 'USD',
|
|
22
|
+
amount: 100.0,
|
|
23
|
+
precisionAmount: '2',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
attributes: [],
|
|
27
|
+
primaryImage: null,
|
|
28
|
+
gallery: [],
|
|
29
|
+
variants: [],
|
|
30
|
+
quantityLimit: 1
|
|
31
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useProductAttribute } from '../useProductAttribute';
|
|
2
|
+
import { mockProduct } from './useProduct.mock';
|
|
3
|
+
|
|
4
|
+
describe('useProductAttribute', () => {
|
|
5
|
+
it('should return product attributes', () => {
|
|
6
|
+
const { getAttributeList, getAttribute } = useProductAttribute(mockProduct, ['attribute']);
|
|
7
|
+
|
|
8
|
+
const attributeList = getAttributeList('attribute');
|
|
9
|
+
const attributeValue = getAttribute('attribute');
|
|
10
|
+
|
|
11
|
+
expect(attributeList).toEqual([]);
|
|
12
|
+
expect(attributeValue).toEqual(null);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useProductAttribute';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ref } from 'vue';
|
|
2
|
+
import { SfAttribute, SfProduct } from '../_types';
|
|
3
|
+
import { groupBy, uniqBy } from 'lodash-es';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* composable for getting product attributes data
|
|
7
|
+
* @param {SfProduct} product Product object
|
|
8
|
+
* @param {TAttribute} attributesNames get specific product attributes
|
|
9
|
+
*/
|
|
10
|
+
export function useProductAttribute<TAttribute extends string>(product: SfProduct, attributesNames: TAttribute[] = []) {
|
|
11
|
+
const attributes = groupBy(
|
|
12
|
+
uniqBy(
|
|
13
|
+
(product?.variants || []).flatMap((variant) => variant?.attributes),
|
|
14
|
+
'value',
|
|
15
|
+
),
|
|
16
|
+
'name',
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const mapAttribute = (attributes: SfAttribute[] = []) => {
|
|
20
|
+
const defaults = attributesNames.map((attribute) => ({ name: attribute, value: null }));
|
|
21
|
+
|
|
22
|
+
return Object.fromEntries([...defaults, ...attributes].map(({ name, value }) => [name, value]));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const selectedAttrs = ref(mapAttribute(product.attributes));
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
getAttributeList: (attributeName: TAttribute) => attributes[attributeName] || [],
|
|
29
|
+
getAttribute: (attributeName: TAttribute) => selectedAttrs.value[attributeName],
|
|
30
|
+
setAttribute: (attributeName: TAttribute, attributeValue: string) => {
|
|
31
|
+
selectedAttrs.value = {
|
|
32
|
+
...selectedAttrs.value,
|
|
33
|
+
[attributeName]: attributeValue,
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useProductRecommended } from '~/composables/useProductRecommended/useProductRecommended';
|
|
2
|
+
|
|
3
|
+
describe('useProductRecommended', () => {
|
|
4
|
+
it('should return product reviews', async () => {
|
|
5
|
+
const slug = 'athletic-mens-walking-sneakers';
|
|
6
|
+
const { data: recommendedProducts, fetchProductRecommended } = useProductRecommended(slug);
|
|
7
|
+
|
|
8
|
+
await fetchProductRecommended(slug);
|
|
9
|
+
|
|
10
|
+
expect(recommendedProducts.value).not.toBeUndefined();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useProductRecommended';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
import type { SfProduct, Maybe } from '../_types';
|
|
3
|
+
|
|
4
|
+
export interface UseProductRecommendedState {
|
|
5
|
+
data: Maybe<SfProduct[]>;
|
|
6
|
+
loading: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type FetchProductRecommended = (slug: string) => Promise<Ref<Maybe<SfProduct[]>>>;
|
|
10
|
+
|
|
11
|
+
export interface UseProductRecommended {
|
|
12
|
+
data: Readonly<Ref<UseProductRecommendedState['data']>>;
|
|
13
|
+
loading: Readonly<Ref<boolean>>;
|
|
14
|
+
fetchProductRecommended: FetchProductRecommended;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type UseProductRecommendedReturn = (slug: string) => UseProductRecommended;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { toRefs } from '@vueuse/shared';
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import type { Ref } from 'vue';
|
|
4
|
+
import type { Maybe, SfProduct } from '../_types';
|
|
5
|
+
import { useAsyncData, useState } from 'nuxt/app';
|
|
6
|
+
import type {
|
|
7
|
+
UseProductRecommendedReturn,
|
|
8
|
+
UseProductRecommendedState,
|
|
9
|
+
FetchProductRecommended,
|
|
10
|
+
} from './types';
|
|
11
|
+
import { getCommerceClient } from '../../utils/client';
|
|
12
|
+
import { useHandleError } from '../useHandleError';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Composable for getting recommended products data
|
|
16
|
+
* @param {string} slug Product slug
|
|
17
|
+
*/
|
|
18
|
+
export const useProductRecommended: UseProductRecommendedReturn = (slug) => {
|
|
19
|
+
const state = useState<UseProductRecommendedState>(`useProductRecommended-${slug}`, () => ({
|
|
20
|
+
data: null,
|
|
21
|
+
loading: false,
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
/** Function for fetching product recommended data
|
|
25
|
+
* @param {string} slug Product slug
|
|
26
|
+
* @example
|
|
27
|
+
* fetchProductRecommended('product-slug');
|
|
28
|
+
*/
|
|
29
|
+
const fetchProductRecommended: FetchProductRecommended = async (slug) => {
|
|
30
|
+
state.value.loading = true;
|
|
31
|
+
const client = getCommerceClient();
|
|
32
|
+
const { data, error } = await useAsyncData(() => client.listProducts?.());
|
|
33
|
+
useHandleError(error.value);
|
|
34
|
+
state.value.data = data.value as unknown as Maybe<SfProduct[]>;
|
|
35
|
+
state.value.loading = false;
|
|
36
|
+
return computed(() => state.value.data) as unknown as Ref<Maybe<SfProduct[]>>;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
fetchProductRecommended,
|
|
41
|
+
...toRefs(state.value),
|
|
42
|
+
};
|
|
43
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { SfProductReview } from '../_types';
|
|
2
|
+
|
|
3
|
+
export const mockProductReviews: SfProductReview[] = [
|
|
4
|
+
{
|
|
5
|
+
id: '1',
|
|
6
|
+
text: "I recently purchased a pair of sneakers and I am thoroughly impressed with their quality and comfort. The design is sleek and modern, and the shoes are available in a variety of colors to suit anyone's style preferences. The upper is made of a breathable and durable material that allows my feet to stay cool and dry during long walks or runs. The sole is also very comfortable and provides great support for my feet, making it easy for me to wear them all day without experiencing any discomfort or fatigue. Overall, I highly recommend these sneakers to anyone in the market for a comfortable and stylish shoe that can handle any activity. They are definitely worth the investment!",
|
|
7
|
+
reviewer: 'John Doe',
|
|
8
|
+
rating: 5,
|
|
9
|
+
title: 'Great product!',
|
|
10
|
+
createdAt: '2022-04-28T12:00:00.000Z',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: '2',
|
|
14
|
+
text: "I recently purchased a pair of sneakers and I am thoroughly impressed with their quality and comfort. The design is sleek and modern, and the shoes are available in a variety of colors to suit anyone's style preferences. The upper is made of a breathable and durable material that allows my feet to stay cool and dry during long walks or runs. The sole is also very comfortable and provides great support for my feet, making it easy for me to wear them all day without experiencing any discomfort or fatigue. Overall, I highly recommend these sneakers to anyone in the market for a comfortable and stylish shoe that can handle any activity. They are definitely worth the investment!",
|
|
15
|
+
reviewer: 'John Doe',
|
|
16
|
+
rating: 5,
|
|
17
|
+
title: 'Great product!',
|
|
18
|
+
createdAt: '2022-03-01T09:30:00.000Z',
|
|
19
|
+
},
|
|
20
|
+
];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
import { useProductReviews } from '~/composables/useProductReviews';
|
|
3
|
+
import { mockProductReviews } from './productReviews.mock';
|
|
4
|
+
|
|
5
|
+
vi.mock('@meeovi/sdk', () => ({
|
|
6
|
+
sdk: {
|
|
7
|
+
commerce: {
|
|
8
|
+
getProductReviews: vi.fn(() => mockProductReviews),
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
describe('useProductReview', () => {
|
|
14
|
+
it('should return product reviews', async () => {
|
|
15
|
+
const slug = 'athletic-mens-walking-sneakers';
|
|
16
|
+
const { data, fetchProductReviews } = useProductReviews(slug);
|
|
17
|
+
|
|
18
|
+
await fetchProductReviews(slug);
|
|
19
|
+
|
|
20
|
+
expect(data.value).toEqual(mockProductReviews);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
import type { SfProductReview, Maybe } from '../_types';
|
|
3
|
+
|
|
4
|
+
export interface UseProductReviewsState {
|
|
5
|
+
data: Maybe<SfProductReview[]>;
|
|
6
|
+
loading: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type FetchProductReviews = (slug: string) => Promise<Ref<Maybe<SfProductReview[]>>>;
|
|
10
|
+
|
|
11
|
+
export interface UseProductReviewsReturn {
|
|
12
|
+
data: Readonly<Ref<UseProductReviewsState['data']>>;
|
|
13
|
+
loading: Readonly<Ref<boolean>>;
|
|
14
|
+
fetchProductReviews: FetchProductReviews;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type UseProductReviews = (slug: string) => UseProductReviewsReturn;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { toRefs } from '@vueuse/shared';
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import type { Ref } from 'vue';
|
|
4
|
+
import type { Maybe, SfProductReview } from '../_types';
|
|
5
|
+
import type {
|
|
6
|
+
UseProductReviews,
|
|
7
|
+
UseProductReviewsState,
|
|
8
|
+
FetchProductReviews,
|
|
9
|
+
} from './types';
|
|
10
|
+
import { getCommerceClient } from '../../utils/client';
|
|
11
|
+
import { useAsyncData, useState } from 'nuxt/app';
|
|
12
|
+
import { useHandleError } from '../useHandleError';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @description Composable managing product reviews data
|
|
16
|
+
* @param {string} slug Product slug
|
|
17
|
+
* @returns {@link UseProductReturn}
|
|
18
|
+
* @example
|
|
19
|
+
* const { data, loading, fetchProductReviews } = useProductReviews('product-slug');
|
|
20
|
+
*/
|
|
21
|
+
export const useProductReviews: UseProductReviews = (slug) => {
|
|
22
|
+
const state = useState<UseProductReviewsState>(`useProductReviews-${slug}`, () => ({
|
|
23
|
+
data: null,
|
|
24
|
+
loading: false,
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
/** Function for fetching product reviews data
|
|
28
|
+
* @param {string} slug Product slug
|
|
29
|
+
* @example
|
|
30
|
+
* fetchProductReviews('product-slug');
|
|
31
|
+
*/
|
|
32
|
+
const fetchProductReviews: FetchProductReviews = async (slug) => {
|
|
33
|
+
state.value.loading = true;
|
|
34
|
+
const client = getCommerceClient();
|
|
35
|
+
const { data, error } = await useAsyncData(() => client.listProductReviews?.(slug) ?? client.listReviews?.(slug));
|
|
36
|
+
useHandleError(error.value);
|
|
37
|
+
state.value.data = data.value as unknown as Maybe<SfProductReview[]>;
|
|
38
|
+
state.value.loading = false;
|
|
39
|
+
return computed(() => state.value.data) as unknown as Ref<Maybe<SfProductReview[]>>;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
fetchProductReviews,
|
|
44
|
+
...toRefs(state.value),
|
|
45
|
+
};
|
|
46
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useProducts } from '../useProducts';
|
|
2
|
+
|
|
3
|
+
describe('useProducts', () => {
|
|
4
|
+
it('should return products', async () => {
|
|
5
|
+
const { fetchProducts, data } = useProducts();
|
|
6
|
+
|
|
7
|
+
await fetchProducts();
|
|
8
|
+
|
|
9
|
+
expect(data.value).not.toBeUndefined();
|
|
10
|
+
});
|
|
11
|
+
});
|