From 63e13073cf59a247e19c2368ad0047aa0ef764f1 Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Mon, 14 Mar 2022 15:37:05 +0100 Subject: [PATCH 01/11] refactor(composable): refactor useReview squash this --- .../src/composables/useReview/index.ts | 4 + .../composables/useReview/commands/index.ts | 54 +++++++++++ packages/theme/composables/useReview/index.ts | 89 +++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 packages/theme/composables/useReview/commands/index.ts create mode 100644 packages/theme/composables/useReview/index.ts diff --git a/packages/composables/src/composables/useReview/index.ts b/packages/composables/src/composables/useReview/index.ts index 2ee3abe5d..f020125b0 100644 --- a/packages/composables/src/composables/useReview/index.ts +++ b/packages/composables/src/composables/useReview/index.ts @@ -1,4 +1,8 @@ /* istanbul ignore file */ + +/** + * @deprecated since version 1.0.0 + */ import { ComposableFunctionArgs, Context, diff --git a/packages/theme/composables/useReview/commands/index.ts b/packages/theme/composables/useReview/commands/index.ts new file mode 100644 index 000000000..4181dbd2c --- /dev/null +++ b/packages/theme/composables/useReview/commands/index.ts @@ -0,0 +1,54 @@ +import { Context, Logger } from '@vue-storefront/core'; +import { GetProductSearchParams } from '~/composables/useProduct/useProduct'; + +export const searchReviews = { + execute: async (context: Context, params?) => { + Logger.debug('[Magento] search review params input:', JSON.stringify(params, null, 2)); + const { + customQuery, + ...input + } = params; + const { data } = await context.$magento.api.productReview(input as GetProductSearchParams); + Logger.debug('[Result]:', { data }); + return data?.products?.items ?? []; + }, +}; +export const addReview = { + execute: async (context: Context, params) => { + Logger.debug('[Magento] add review params input:', JSON.stringify(params, null, 2)); + const { + customQuery, + ...input + } = params; + + const { data } = await context.$magento.api.createProductReview(input); + + Logger.debug('[Result]:', { data }); + + return data?.createProductReview?.review ?? {}; + }, +}; + +export const loadReviewMetadata = { + execute: + async (context: Context) => { + Logger.debug('[Magento] load review metadata'); + + const { data } = await context.$magento.api.productReviewRatingsMetadata(); + + Logger.debug('[Result]:', { data }); + + return data?.productReviewRatingsMetadata?.items ?? []; + }, +}; + +export const loadCustomerReviews = { + execute: async (context: Context, params?) => { + Logger.debug('[Magento] load customer review based on:', { params }); + const { data } = await context.$magento.api.customerProductReview(params); + + Logger.debug('[Result]:', { data }); + + return data?.customer ?? {}; + }, +}; diff --git a/packages/theme/composables/useReview/index.ts b/packages/theme/composables/useReview/index.ts new file mode 100644 index 000000000..7a3584660 --- /dev/null +++ b/packages/theme/composables/useReview/index.ts @@ -0,0 +1,89 @@ +import { ref, useContext } from '@nuxtjs/composition-api'; +import { Context, Logger } from '@vue-storefront/core'; +import { ReviewMetadata } from '@vue-storefront/magento'; +import * as commands from './commands'; + +export const useReview = (id: string) => { + const reviews = ref([]); + const metadata = ref([]); + const loading = ref(false); + const error = ref({ + search: null, + addReview: null, + loadReviewMetadata: null, + loadCustomerReviews: null, + }); + + const { app } = useContext(); + const context = app.$vsf as Context; + + const search = async (searchParams?): Promise => { + Logger.debug(`useReview/${id}/search`, searchParams); + + try { + loading.value = true; + reviews.value = await commands.searchReviews.execute(context, searchParams); + error.value.search = null; + } catch (err) { + error.value.search = err; + Logger.error(`useReview/${id}/search`, err); + } finally { + loading.value = false; + } + }; + + const loadCustomerReviews = async (): Promise => { + Logger.debug(`useReview/${id}/loadCustomerReviews`); + + try { + loading.value = true; + reviews.value = await commands.loadCustomerReviews.execute(context); + error.value.loadCustomerReviews = null; + } catch (err) { + error.value.loadCustomerReviews = err; + Logger.error(`useReview/${id}/loadCustomerReviews`, err); + } finally { + loading.value = false; + } + }; + + const loadReviewMetadata = async (params): Promise => { + Logger.debug(`useReview/${id}/loadReviewMetadata`); + + try { + loading.value = true; + metadata.value = await commands.loadReviewMetadata.execute(context); + error.value.loadReviewMetadata = null; + } catch (err) { + error.value.loadReviewMetadata = err; + Logger.error(`useReview/${id}/loadReviewMetadata`, err); + } finally { + loading.value = false; + } + }; + + const addReview = async (params): Promise => { + Logger.debug(`useReview/${id}/addReview`, params); + try { + loading.value = true; + reviews.value = await commands.addReview.execute(context, params); + error.value.addReview = null; + } catch (err) { + error.value.addReview = err; + Logger.error(`useReview/${id}/addReview`, err); + } finally { + loading.value = false; + } + }; + + return { + search, + addReview, + loadReviewMetadata, + loadCustomerReviews, + metadata, + reviews, + loading, + error, + }; +}; From 2b72a52dd0fdc6643121a2e612521014c831442e Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Tue, 15 Mar 2022 09:37:06 +0100 Subject: [PATCH 02/11] refactor(theme): change to new refactored usereview composable --- packages/theme/components/ProductAddReviewForm.vue | 2 +- .../__tests__/ProductAddReviewForm.spec.js | 12 ++++++++++-- packages/theme/pages/MyAccount/MyReviews.vue | 2 +- packages/theme/pages/Product.vue | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/theme/components/ProductAddReviewForm.vue b/packages/theme/components/ProductAddReviewForm.vue index 393ac2ba1..65edac9aa 100644 --- a/packages/theme/components/ProductAddReviewForm.vue +++ b/packages/theme/components/ProductAddReviewForm.vue @@ -116,7 +116,6 @@ import { useRoute, useContext, } from '@nuxtjs/composition-api'; -import { useReview } from '@vue-storefront/magento'; import { extend, ValidationObserver, ValidationProvider } from 'vee-validate'; import { min, oneOf, required } from 'vee-validate/dist/rules'; import { @@ -124,6 +123,7 @@ import { } from '@storefront-ui/vue'; import { reviewGetters, userGetters } from '~/getters'; import { useUser } from '~/composables'; +import { useReview } from '~/composables/useReview'; extend('required', { ...required, diff --git a/packages/theme/components/__tests__/ProductAddReviewForm.spec.js b/packages/theme/components/__tests__/ProductAddReviewForm.spec.js index 9269b2ea2..64adb73d1 100644 --- a/packages/theme/components/__tests__/ProductAddReviewForm.spec.js +++ b/packages/theme/components/__tests__/ProductAddReviewForm.spec.js @@ -2,13 +2,14 @@ import { waitFor } from '@testing-library/vue'; import userEvent from '@testing-library/user-event'; import { useRoute } from '@nuxtjs/composition-api'; -import { useUser, useReview } from '@vue-storefront/magento'; +import { useUser } from '@vue-storefront/magento'; import { render, useUserMock, useReviewMock, } from '~/test-utils'; +import { useReview } from '~/composables/useReview'; import ProductAddReviewForm from '../ProductAddReviewForm'; jest.mock('@vue-storefront/magento', () => { @@ -16,7 +17,6 @@ jest.mock('@vue-storefront/magento', () => { return { ...originalModule, useUser: jest.fn(), - useReview: jest.fn(), }; }); @@ -30,6 +30,14 @@ jest.mock('@nuxtjs/composition-api', () => { }; }); +jest.mock('~/composables/useReview', () => { + const originalModule = jest.requireActual('~/composables/useReview'); + return { + ...originalModule, + useReview: jest.fn(), + }; +}); + describe.skip('', () => { it('Form fields are rendered and validated', async () => { useUser.mockReturnValue(useUserMock()); diff --git a/packages/theme/pages/MyAccount/MyReviews.vue b/packages/theme/pages/MyAccount/MyReviews.vue index 09810e736..6602b62b3 100644 --- a/packages/theme/pages/MyAccount/MyReviews.vue +++ b/packages/theme/pages/MyAccount/MyReviews.vue @@ -55,9 +55,9 @@ import { SfTabs, SfLoader, SfReview, SfRating, } from '@storefront-ui/vue'; -import { useReview } from '@vue-storefront/magento'; import { reviewGetters } from '~/getters'; import { computed, defineComponent, onMounted } from '@nuxtjs/composition-api'; +import { useReview } from '~/composables/useReview'; export default defineComponent({ name: 'MyReviews', diff --git a/packages/theme/pages/Product.vue b/packages/theme/pages/Product.vue index 6ced7da86..7fe4a7c8f 100644 --- a/packages/theme/pages/Product.vue +++ b/packages/theme/pages/Product.vue @@ -270,7 +270,6 @@ import { SfSelect, SfTabs, } from '@storefront-ui/vue'; -import { useReview } from '@vue-storefront/magento'; import { ref, computed, @@ -290,6 +289,7 @@ import InstagramFeed from '~/components/InstagramFeed.vue'; import MobileStoreBanner from '~/components/MobileStoreBanner.vue'; import ProductAddReviewForm from '~/components/ProductAddReviewForm.vue'; import SvgImage from '~/components/General/SvgImage.vue'; +import { useReview } from '~/composables/useReview'; import BundleProductSelector from '~/components/Products/BundleProductSelector'; import GroupedProductSelector from '~/components/Products/GroupedProductSelector'; import UpsellProducts from '~/components/UpsellProducts'; From 1559d92dc779e79433f6702c06d49449470adfae Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Tue, 15 Mar 2022 15:53:54 +0100 Subject: [PATCH 03/11] refactor(composable): deprecate useReview factory aswell --- packages/composables/src/factories/useReviewFactory.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/composables/src/factories/useReviewFactory.ts b/packages/composables/src/factories/useReviewFactory.ts index 09d6310eb..bf4896af5 100644 --- a/packages/composables/src/factories/useReviewFactory.ts +++ b/packages/composables/src/factories/useReviewFactory.ts @@ -1,3 +1,6 @@ +/** + * @deprecated since version 1.0.0 + */ import { Ref, computed } from '@vue/composition-api'; import { ComposableFunctionArgs, From c309904f85a43f15b80a8ace07e800913aa0bfc9 Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Tue, 15 Mar 2022 16:04:15 +0100 Subject: [PATCH 04/11] refactor(theme): move commands into separate files and change naming convention --- .../useReview/commands/addReviewCommand.ts | 17 ++++++ .../composables/useReview/commands/index.ts | 54 ------------------- .../commands/loadCustomerReviewsCommand.ts | 12 +++++ .../commands/loadReviewMetadataCommand.ts | 13 +++++ .../commands/searchReviewsCommand.ts | 15 ++++++ packages/theme/composables/useReview/index.ts | 16 +++--- 6 files changed, 67 insertions(+), 60 deletions(-) create mode 100644 packages/theme/composables/useReview/commands/addReviewCommand.ts delete mode 100644 packages/theme/composables/useReview/commands/index.ts create mode 100644 packages/theme/composables/useReview/commands/loadCustomerReviewsCommand.ts create mode 100644 packages/theme/composables/useReview/commands/loadReviewMetadataCommand.ts create mode 100644 packages/theme/composables/useReview/commands/searchReviewsCommand.ts diff --git a/packages/theme/composables/useReview/commands/addReviewCommand.ts b/packages/theme/composables/useReview/commands/addReviewCommand.ts new file mode 100644 index 000000000..fe10b6c3d --- /dev/null +++ b/packages/theme/composables/useReview/commands/addReviewCommand.ts @@ -0,0 +1,17 @@ +import { Context, Logger } from '@vue-storefront/core'; + +export const addReviewCommand = { + execute: async (context: Context, params) => { + Logger.debug('[Magento] add review params input:', JSON.stringify(params, null, 2)); + const { + customQuery, + ...input + } = params; + + const { data } = await context.$magento.api.createProductReview(input); + + Logger.debug('[Result]:', { data }); + + return data?.createProductReview?.review ?? {}; + }, +}; diff --git a/packages/theme/composables/useReview/commands/index.ts b/packages/theme/composables/useReview/commands/index.ts deleted file mode 100644 index 4181dbd2c..000000000 --- a/packages/theme/composables/useReview/commands/index.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Context, Logger } from '@vue-storefront/core'; -import { GetProductSearchParams } from '~/composables/useProduct/useProduct'; - -export const searchReviews = { - execute: async (context: Context, params?) => { - Logger.debug('[Magento] search review params input:', JSON.stringify(params, null, 2)); - const { - customQuery, - ...input - } = params; - const { data } = await context.$magento.api.productReview(input as GetProductSearchParams); - Logger.debug('[Result]:', { data }); - return data?.products?.items ?? []; - }, -}; -export const addReview = { - execute: async (context: Context, params) => { - Logger.debug('[Magento] add review params input:', JSON.stringify(params, null, 2)); - const { - customQuery, - ...input - } = params; - - const { data } = await context.$magento.api.createProductReview(input); - - Logger.debug('[Result]:', { data }); - - return data?.createProductReview?.review ?? {}; - }, -}; - -export const loadReviewMetadata = { - execute: - async (context: Context) => { - Logger.debug('[Magento] load review metadata'); - - const { data } = await context.$magento.api.productReviewRatingsMetadata(); - - Logger.debug('[Result]:', { data }); - - return data?.productReviewRatingsMetadata?.items ?? []; - }, -}; - -export const loadCustomerReviews = { - execute: async (context: Context, params?) => { - Logger.debug('[Magento] load customer review based on:', { params }); - const { data } = await context.$magento.api.customerProductReview(params); - - Logger.debug('[Result]:', { data }); - - return data?.customer ?? {}; - }, -}; diff --git a/packages/theme/composables/useReview/commands/loadCustomerReviewsCommand.ts b/packages/theme/composables/useReview/commands/loadCustomerReviewsCommand.ts new file mode 100644 index 000000000..eb5d093b2 --- /dev/null +++ b/packages/theme/composables/useReview/commands/loadCustomerReviewsCommand.ts @@ -0,0 +1,12 @@ +import { Context, Logger } from '@vue-storefront/core'; + +export const loadCustomerReviewsCommand = { + execute: async (context: Context, params?) => { + Logger.debug('[Magento] load customer review based on:', { params }); + const { data } = await context.$magento.api.customerProductReview(params); + + Logger.debug('[Result]:', { data }); + + return data?.customer ?? {}; + }, +}; diff --git a/packages/theme/composables/useReview/commands/loadReviewMetadataCommand.ts b/packages/theme/composables/useReview/commands/loadReviewMetadataCommand.ts new file mode 100644 index 000000000..63d77ac35 --- /dev/null +++ b/packages/theme/composables/useReview/commands/loadReviewMetadataCommand.ts @@ -0,0 +1,13 @@ +import { Context, Logger } from '@vue-storefront/core'; + +export const loadReviewMetadataCommand = { + execute: async (context: Context) => { + Logger.debug('[Magento] load review metadata'); + + const { data } = await context.$magento.api.productReviewRatingsMetadata(); + + Logger.debug('[Result]:', { data }); + + return data?.productReviewRatingsMetadata?.items ?? []; + }, +}; diff --git a/packages/theme/composables/useReview/commands/searchReviewsCommand.ts b/packages/theme/composables/useReview/commands/searchReviewsCommand.ts new file mode 100644 index 000000000..cff5fe0fd --- /dev/null +++ b/packages/theme/composables/useReview/commands/searchReviewsCommand.ts @@ -0,0 +1,15 @@ +import { Context, Logger } from '@vue-storefront/core'; +import { GetProductSearchParams } from '~/composables/useProduct/useProduct'; + +export const searchReviewsCommand = { + execute: async (context: Context, params?) => { + Logger.debug('[Magento] search review params input:', JSON.stringify(params, null, 2)); + const { + customQuery, + ...input + } = params; + const { data } = await context.$magento.api.productReview(input as GetProductSearchParams); + Logger.debug('[Result]:', { data }); + return data?.products?.items ?? []; + }, +}; diff --git a/packages/theme/composables/useReview/index.ts b/packages/theme/composables/useReview/index.ts index 7a3584660..60bbe9def 100644 --- a/packages/theme/composables/useReview/index.ts +++ b/packages/theme/composables/useReview/index.ts @@ -1,7 +1,11 @@ import { ref, useContext } from '@nuxtjs/composition-api'; import { Context, Logger } from '@vue-storefront/core'; import { ReviewMetadata } from '@vue-storefront/magento'; -import * as commands from './commands'; + +import { addReviewCommand } from './commands/addReviewCommand'; +import { loadCustomerReviewsCommand } from './commands/loadCustomerReviewsCommand'; +import { loadReviewMetadataCommand } from './commands/loadReviewMetadataCommand'; +import { searchReviewsCommand } from './commands/searchReviewsCommand'; export const useReview = (id: string) => { const reviews = ref([]); @@ -22,7 +26,7 @@ export const useReview = (id: string) => { try { loading.value = true; - reviews.value = await commands.searchReviews.execute(context, searchParams); + reviews.value = await searchReviewsCommand.execute(context, searchParams); error.value.search = null; } catch (err) { error.value.search = err; @@ -37,7 +41,7 @@ export const useReview = (id: string) => { try { loading.value = true; - reviews.value = await commands.loadCustomerReviews.execute(context); + reviews.value = await loadCustomerReviewsCommand.execute(context); error.value.loadCustomerReviews = null; } catch (err) { error.value.loadCustomerReviews = err; @@ -47,12 +51,12 @@ export const useReview = (id: string) => { } }; - const loadReviewMetadata = async (params): Promise => { + const loadReviewMetadata = async (_params): Promise => { Logger.debug(`useReview/${id}/loadReviewMetadata`); try { loading.value = true; - metadata.value = await commands.loadReviewMetadata.execute(context); + metadata.value = await loadReviewMetadataCommand.execute(context); error.value.loadReviewMetadata = null; } catch (err) { error.value.loadReviewMetadata = err; @@ -66,7 +70,7 @@ export const useReview = (id: string) => { Logger.debug(`useReview/${id}/addReview`, params); try { loading.value = true; - reviews.value = await commands.addReview.execute(context, params); + reviews.value = await addReviewCommand.execute(context, params); error.value.addReview = null; } catch (err) { error.value.addReview = err; From 3d770c6294b35b965aaa08405f6574ffe53c2b35 Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Tue, 15 Mar 2022 16:06:57 +0100 Subject: [PATCH 05/11] refactor(theme): add spaces for readability --- .../theme/composables/useReview/commands/addReviewCommand.ts | 1 + .../useReview/commands/loadCustomerReviewsCommand.ts | 1 + .../composables/useReview/commands/searchReviewsCommand.ts | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/packages/theme/composables/useReview/commands/addReviewCommand.ts b/packages/theme/composables/useReview/commands/addReviewCommand.ts index fe10b6c3d..8ee2ddcc4 100644 --- a/packages/theme/composables/useReview/commands/addReviewCommand.ts +++ b/packages/theme/composables/useReview/commands/addReviewCommand.ts @@ -3,6 +3,7 @@ import { Context, Logger } from '@vue-storefront/core'; export const addReviewCommand = { execute: async (context: Context, params) => { Logger.debug('[Magento] add review params input:', JSON.stringify(params, null, 2)); + const { customQuery, ...input diff --git a/packages/theme/composables/useReview/commands/loadCustomerReviewsCommand.ts b/packages/theme/composables/useReview/commands/loadCustomerReviewsCommand.ts index eb5d093b2..0da482eaa 100644 --- a/packages/theme/composables/useReview/commands/loadCustomerReviewsCommand.ts +++ b/packages/theme/composables/useReview/commands/loadCustomerReviewsCommand.ts @@ -3,6 +3,7 @@ import { Context, Logger } from '@vue-storefront/core'; export const loadCustomerReviewsCommand = { execute: async (context: Context, params?) => { Logger.debug('[Magento] load customer review based on:', { params }); + const { data } = await context.$magento.api.customerProductReview(params); Logger.debug('[Result]:', { data }); diff --git a/packages/theme/composables/useReview/commands/searchReviewsCommand.ts b/packages/theme/composables/useReview/commands/searchReviewsCommand.ts index cff5fe0fd..4b894ea2e 100644 --- a/packages/theme/composables/useReview/commands/searchReviewsCommand.ts +++ b/packages/theme/composables/useReview/commands/searchReviewsCommand.ts @@ -4,12 +4,16 @@ import { GetProductSearchParams } from '~/composables/useProduct/useProduct'; export const searchReviewsCommand = { execute: async (context: Context, params?) => { Logger.debug('[Magento] search review params input:', JSON.stringify(params, null, 2)); + const { customQuery, ...input } = params; + const { data } = await context.$magento.api.productReview(input as GetProductSearchParams); + Logger.debug('[Result]:', { data }); + return data?.products?.items ?? []; }, }; From df274e276d7a99d5860a409082439af476d79d23 Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Wed, 16 Mar 2022 08:07:07 +0100 Subject: [PATCH 06/11] refactor(theme): add typings for commands --- packages/theme/composables/context.d.ts | 8 +++ packages/theme/composables/useReview/index.ts | 49 ++++++++++--------- .../composables/useReview/useReview.d.ts | 6 +++ 3 files changed, 39 insertions(+), 24 deletions(-) create mode 100644 packages/theme/composables/context.d.ts create mode 100644 packages/theme/composables/useReview/useReview.d.ts diff --git a/packages/theme/composables/context.d.ts b/packages/theme/composables/context.d.ts new file mode 100644 index 000000000..fa267d60a --- /dev/null +++ b/packages/theme/composables/context.d.ts @@ -0,0 +1,8 @@ +import { ApiClientMethods, IntegrationContext } from '@vue-storefront/core'; +import { ClientInstance, Config, MagentoApiMethods } from '@vue-storefront/magento-api'; + +declare module '@vue-storefront/core' { + export interface Context { + $magento: IntegrationContext>; + } +} diff --git a/packages/theme/composables/useReview/index.ts b/packages/theme/composables/useReview/index.ts index 60bbe9def..ba6718efb 100644 --- a/packages/theme/composables/useReview/index.ts +++ b/packages/theme/composables/useReview/index.ts @@ -1,17 +1,18 @@ +/* eslint-disable consistent-return */ import { ref, useContext } from '@nuxtjs/composition-api'; -import { Context, Logger } from '@vue-storefront/core'; -import { ReviewMetadata } from '@vue-storefront/magento'; +import { ComposableFunctionArgs, Context, Logger } from '@vue-storefront/core'; +import { CreateProductReviewInput, CustomerProductReviewParams } from '~/../api-client/lib'; +import { UseReviewErrors } from './useReview'; import { addReviewCommand } from './commands/addReviewCommand'; import { loadCustomerReviewsCommand } from './commands/loadCustomerReviewsCommand'; import { loadReviewMetadataCommand } from './commands/loadReviewMetadataCommand'; import { searchReviewsCommand } from './commands/searchReviewsCommand'; +import { GetProductSearchParams } from '../useProduct/useProduct'; -export const useReview = (id: string) => { - const reviews = ref([]); - const metadata = ref([]); +export const useReview = () => { const loading = ref(false); - const error = ref({ + const error = ref({ search: null, addReview: null, loadReviewMetadata: null, @@ -21,60 +22,60 @@ export const useReview = (id: string) => { const { app } = useContext(); const context = app.$vsf as Context; - const search = async (searchParams?): Promise => { - Logger.debug(`useReview/${id}/search`, searchParams); + const search = async (searchParams: ComposableFunctionArgs) => { + Logger.debug('useReview/search', searchParams); try { loading.value = true; - reviews.value = await searchReviewsCommand.execute(context, searchParams); error.value.search = null; + return await searchReviewsCommand.execute(context, searchParams); } catch (err) { error.value.search = err; - Logger.error(`useReview/${id}/search`, err); + Logger.error('useReview/search', err); } finally { loading.value = false; } }; - const loadCustomerReviews = async (): Promise => { - Logger.debug(`useReview/${id}/loadCustomerReviews`); + const loadCustomerReviews = async (_params?: ComposableFunctionArgs) => { + Logger.debug('useReview/loadCustomerReviews'); try { loading.value = true; - reviews.value = await loadCustomerReviewsCommand.execute(context); error.value.loadCustomerReviews = null; + return await loadCustomerReviewsCommand.execute(context); } catch (err) { error.value.loadCustomerReviews = err; - Logger.error(`useReview/${id}/loadCustomerReviews`, err); + Logger.error('useReview/loadCustomerReviews', err); } finally { loading.value = false; } }; - const loadReviewMetadata = async (_params): Promise => { - Logger.debug(`useReview/${id}/loadReviewMetadata`); + const loadReviewMetadata = async (_params?: ComposableFunctionArgs<{}>) => { + Logger.debug('useReview/loadReviewMetadata'); try { loading.value = true; - metadata.value = await loadReviewMetadataCommand.execute(context); error.value.loadReviewMetadata = null; + return await loadReviewMetadataCommand.execute(context); } catch (err) { error.value.loadReviewMetadata = err; - Logger.error(`useReview/${id}/loadReviewMetadata`, err); + Logger.error('useReview/loadReviewMetadata', err); } finally { loading.value = false; } }; - const addReview = async (params): Promise => { - Logger.debug(`useReview/${id}/addReview`, params); + const addReview = async (params: ComposableFunctionArgs) => { + Logger.debug('useReview/addReview', params); try { loading.value = true; - reviews.value = await addReviewCommand.execute(context, params); error.value.addReview = null; + return await addReviewCommand.execute(context, params); } catch (err) { error.value.addReview = err; - Logger.error(`useReview/${id}/addReview`, err); + Logger.error('useReview/addReview', err); } finally { loading.value = false; } @@ -85,9 +86,9 @@ export const useReview = (id: string) => { addReview, loadReviewMetadata, loadCustomerReviews, - metadata, - reviews, loading, error, }; }; + +export default useReview; diff --git a/packages/theme/composables/useReview/useReview.d.ts b/packages/theme/composables/useReview/useReview.d.ts new file mode 100644 index 000000000..57f19c248 --- /dev/null +++ b/packages/theme/composables/useReview/useReview.d.ts @@ -0,0 +1,6 @@ +export interface UseReviewErrors { + search: Error; + addReview: Error; + loadReviewMetadata: Error; + loadCustomerReviews: Error; +} From 0a42bc3ebd3a74bdcc4f265f03510b1d8df731d7 Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Wed, 16 Mar 2022 08:20:05 +0100 Subject: [PATCH 07/11] refactor(theme): fix useReview imports --- packages/theme/components/ProductAddReviewForm.vue | 3 +-- .../theme/components/__tests__/ProductAddReviewForm.spec.js | 3 +-- packages/theme/composables/index.ts | 1 + packages/theme/pages/MyAccount/MyReviews.vue | 2 +- packages/theme/pages/Product.vue | 3 +-- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/theme/components/ProductAddReviewForm.vue b/packages/theme/components/ProductAddReviewForm.vue index 65edac9aa..d40160b0a 100644 --- a/packages/theme/components/ProductAddReviewForm.vue +++ b/packages/theme/components/ProductAddReviewForm.vue @@ -122,8 +122,7 @@ import { SfInput, SfButton, SfSelect, SfTextarea, } from '@storefront-ui/vue'; import { reviewGetters, userGetters } from '~/getters'; -import { useUser } from '~/composables'; -import { useReview } from '~/composables/useReview'; +import { useUser, useReview } from '~/composables'; extend('required', { ...required, diff --git a/packages/theme/components/__tests__/ProductAddReviewForm.spec.js b/packages/theme/components/__tests__/ProductAddReviewForm.spec.js index 64adb73d1..ed057e20b 100644 --- a/packages/theme/components/__tests__/ProductAddReviewForm.spec.js +++ b/packages/theme/components/__tests__/ProductAddReviewForm.spec.js @@ -2,14 +2,13 @@ import { waitFor } from '@testing-library/vue'; import userEvent from '@testing-library/user-event'; import { useRoute } from '@nuxtjs/composition-api'; -import { useUser } from '@vue-storefront/magento'; import { render, useUserMock, useReviewMock, } from '~/test-utils'; -import { useReview } from '~/composables/useReview'; +import { useReview, useUser } from '~/composables'; import ProductAddReviewForm from '../ProductAddReviewForm'; jest.mock('@vue-storefront/magento', () => { diff --git a/packages/theme/composables/index.ts b/packages/theme/composables/index.ts index 90bb0f03a..57859973e 100644 --- a/packages/theme/composables/index.ts +++ b/packages/theme/composables/index.ts @@ -16,6 +16,7 @@ export { default as useCart } from './useCart'; export { default as useContent } from './useContent'; export { default as useCategorySearch } from './useCategorySearch'; export { default as useProduct } from './useProduct'; +export { default as useReview } from './useReview'; export { default as useShipping } from './useShipping'; export { default as useShippingProvider } from './useShippingProvider'; export { default as useRelatedProducts } from './useRelatedProducts'; diff --git a/packages/theme/pages/MyAccount/MyReviews.vue b/packages/theme/pages/MyAccount/MyReviews.vue index 6602b62b3..a8829ec4b 100644 --- a/packages/theme/pages/MyAccount/MyReviews.vue +++ b/packages/theme/pages/MyAccount/MyReviews.vue @@ -57,7 +57,7 @@ import { } from '@storefront-ui/vue'; import { reviewGetters } from '~/getters'; import { computed, defineComponent, onMounted } from '@nuxtjs/composition-api'; -import { useReview } from '~/composables/useReview'; +import { useReview } from '~/composables'; export default defineComponent({ name: 'MyReviews', diff --git a/packages/theme/pages/Product.vue b/packages/theme/pages/Product.vue index 7fe4a7c8f..b41f49325 100644 --- a/packages/theme/pages/Product.vue +++ b/packages/theme/pages/Product.vue @@ -281,7 +281,7 @@ import { import { useCache, CacheTagPrefix } from '@vue-storefront/cache'; import { productGetters, reviewGetters } from '~/getters'; import { - useProduct, useCart, useWishlist, useUser, + useProduct, useCart, useWishlist, useUser, useReview, } from '~/composables'; import { productData } from '~/helpers/product/productData'; import cacheControl from '~/helpers/cacheControl'; @@ -289,7 +289,6 @@ import InstagramFeed from '~/components/InstagramFeed.vue'; import MobileStoreBanner from '~/components/MobileStoreBanner.vue'; import ProductAddReviewForm from '~/components/ProductAddReviewForm.vue'; import SvgImage from '~/components/General/SvgImage.vue'; -import { useReview } from '~/composables/useReview'; import BundleProductSelector from '~/components/Products/BundleProductSelector'; import GroupedProductSelector from '~/components/Products/GroupedProductSelector'; import UpsellProducts from '~/components/UpsellProducts'; From df004d6801d0d5da65f5e8e95442414833c93004 Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Wed, 16 Mar 2022 11:50:45 +0100 Subject: [PATCH 08/11] fix(theme): fix TypeScript errors after adding context.d.ts $magento types --- packages/theme/composables/useCart/useCart.d.ts | 2 +- .../useProduct/commands/getProductDetailsCommand.ts | 2 +- .../composables/useProduct/commands/getProductListCommand.ts | 2 +- packages/theme/composables/useProduct/index.ts | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/theme/composables/useCart/useCart.d.ts b/packages/theme/composables/useCart/useCart.d.ts index 920cae894..d0e45d708 100644 --- a/packages/theme/composables/useCart/useCart.d.ts +++ b/packages/theme/composables/useCart/useCart.d.ts @@ -17,7 +17,7 @@ export interface UseCartInterface { clear: (params: ComposableFunctionArgs<{ realCart?: boolean; }>) => Promise; applyCoupon: (params: ComposableFunctionArgs<{ couponCode: string; }>) => Promise; removeCoupon: (params: ComposableFunctionArgs<{}>) => Promise; - isInCart: (context: Context, params: { currentCart: CART; product: PRODUCT }) => boolean; + isInCart: (params: { currentCart: CART; product: PRODUCT }) => boolean; setCart: (newCart: CART) => void; cart: ComputedRef; loading: Ref; diff --git a/packages/theme/composables/useProduct/commands/getProductDetailsCommand.ts b/packages/theme/composables/useProduct/commands/getProductDetailsCommand.ts index b46fcaf1b..e5a35ffd1 100644 --- a/packages/theme/composables/useProduct/commands/getProductDetailsCommand.ts +++ b/packages/theme/composables/useProduct/commands/getProductDetailsCommand.ts @@ -10,6 +10,6 @@ export const getProductDetailsCommand = { ...searchParams, } as GetProductSearchParams, customQuery); - return result.data?.products ?? []; + return result.data?.products; }, }; diff --git a/packages/theme/composables/useProduct/commands/getProductListCommand.ts b/packages/theme/composables/useProduct/commands/getProductListCommand.ts index 9873677b9..287c6b2d6 100644 --- a/packages/theme/composables/useProduct/commands/getProductListCommand.ts +++ b/packages/theme/composables/useProduct/commands/getProductListCommand.ts @@ -8,6 +8,6 @@ export const getProductListCommand = { .api .products(searchParams as GetProductSearchParams, customQuery); - return result.data?.products ?? []; + return result.data?.products; }, }; diff --git a/packages/theme/composables/useProduct/index.ts b/packages/theme/composables/useProduct/index.ts index 3e990d3a9..5cc4883be 100644 --- a/packages/theme/composables/useProduct/index.ts +++ b/packages/theme/composables/useProduct/index.ts @@ -5,6 +5,7 @@ import { import { ref, useContext } from '@nuxtjs/composition-api'; import { getProductListCommand } from '~/composables/useProduct/commands/getProductListCommand'; import { getProductDetailsCommand } from '~/composables/useProduct/commands/getProductDetailsCommand'; +import { ProductsListQuery } from '~/modules/GraphQL/types'; export const useProduct = (id: string) => { const loading = ref(false); @@ -17,7 +18,7 @@ export const useProduct = (id: string) => { const getProductList = async (searchParams) => { Logger.debug(`useProduct/${id}/getProductList`, searchParams); - let products = []; + let products : ProductsListQuery['products'] = null; try { loading.value = true; @@ -35,7 +36,7 @@ export const useProduct = (id: string) => { const getProductDetails = async (searchParams) => { Logger.debug(`useProduct/${id}/getProductDetails`, searchParams); - let products = []; + let products : ProductsListQuery['products'] = null; try { loading.value = true; From 11bee3f6140989a840be99de733d2567fc655792 Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Wed, 16 Mar 2022 12:11:27 +0100 Subject: [PATCH 09/11] refactor(theme): adjust to lack of state refs in composable --- packages/theme/components/ProductAddReviewForm.vue | 10 +++++----- packages/theme/pages/MyAccount/MyReviews.vue | 11 ++++++----- packages/theme/pages/Product.vue | 6 +++--- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/theme/components/ProductAddReviewForm.vue b/packages/theme/components/ProductAddReviewForm.vue index d40160b0a..4d8156747 100644 --- a/packages/theme/components/ProductAddReviewForm.vue +++ b/packages/theme/components/ProductAddReviewForm.vue @@ -167,16 +167,16 @@ export default defineComponent({ typeof $recaptcha !== 'undefined' && $config.isRecaptcha, ); const { - loading, loadReviewMetadata, metadata, error, - } = useReview( - `productReviews-${id}`, - ); + loading, loadReviewMetadata, error, + } = useReview(); const { isAuthenticated, user } = useUser(); const reviewSent = ref(false); const form = ref(BASE_FORM(id)); + const metadata = ref([]); + const ratingMetadata = computed(() => reviewGetters.getReviewMetadata([...metadata.value])); const formSubmitValue = computed(() => { @@ -233,7 +233,7 @@ export default defineComponent({ }; onBeforeMount(async () => { - await loadReviewMetadata(); + metadata.value = await loadReviewMetadata(); }); return { diff --git a/packages/theme/pages/MyAccount/MyReviews.vue b/packages/theme/pages/MyAccount/MyReviews.vue index a8829ec4b..5c8b0b6e5 100644 --- a/packages/theme/pages/MyAccount/MyReviews.vue +++ b/packages/theme/pages/MyAccount/MyReviews.vue @@ -56,7 +56,9 @@ import { SfTabs, SfLoader, SfReview, SfRating, } from '@storefront-ui/vue'; import { reviewGetters } from '~/getters'; -import { computed, defineComponent, onMounted } from '@nuxtjs/composition-api'; +import { + computed, defineComponent, onMounted, ref, +} from '@nuxtjs/composition-api'; import { useReview } from '~/composables'; export default defineComponent({ @@ -68,14 +70,13 @@ export default defineComponent({ SfRating, }, setup() { - const { reviews, loading, loadCustomerReviews } = useReview( - 'productReviews-my-reviews', - ); + const { loading, loadCustomerReviews } = useReview(); + const reviews = ref([]); const userReviews = computed(() => reviewGetters.getItems(reviews.value)); onMounted(async () => { - await loadCustomerReviews(); + reviews.value = await loadCustomerReviews(); }); return { diff --git a/packages/theme/pages/Product.vue b/packages/theme/pages/Product.vue index b41f49325..bde1ca7d8 100644 --- a/packages/theme/pages/Product.vue +++ b/packages/theme/pages/Product.vue @@ -340,11 +340,11 @@ export default defineComponent({ const { getProductDetails, loading: productLoading } = useProduct(); const { addItem, loading } = useCart(); const { - reviews: productReviews, search: searchReviews, loading: reviewsLoading, addReview, - } = useReview(`productReviews-${id}`); + } = useReview(); + const productReviews = ref([]); const { isAuthenticated } = useUser(); const { addItem: addItemToWishlist, isInWishlist } = useWishlist(); const { error: nuxtError, app } = useContext(); @@ -481,7 +481,7 @@ export default defineComponent({ if (product?.value?.length === 0) nuxtError({ statusCode: 404 }); - await searchReviews(baseSearchQuery); + productReviews.value = await searchReviews(baseSearchQuery); const tags = [ { From 7c26ec79e7d23ff46e341ea21bac20a13926aded Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Thu, 17 Mar 2022 09:03:51 +0100 Subject: [PATCH 10/11] refactor(composable): remove unused params also use local types, not magento-api ones --- packages/theme/composables/useReview/index.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/theme/composables/useReview/index.ts b/packages/theme/composables/useReview/index.ts index ba6718efb..d0135f761 100644 --- a/packages/theme/composables/useReview/index.ts +++ b/packages/theme/composables/useReview/index.ts @@ -1,8 +1,7 @@ /* eslint-disable consistent-return */ import { ref, useContext } from '@nuxtjs/composition-api'; import { ComposableFunctionArgs, Context, Logger } from '@vue-storefront/core'; - -import { CreateProductReviewInput, CustomerProductReviewParams } from '~/../api-client/lib'; +import { CreateProductReviewInput } from '~/modules/GraphQL/types'; import { UseReviewErrors } from './useReview'; import { addReviewCommand } from './commands/addReviewCommand'; import { loadCustomerReviewsCommand } from './commands/loadCustomerReviewsCommand'; @@ -37,7 +36,7 @@ export const useReview = () => { } }; - const loadCustomerReviews = async (_params?: ComposableFunctionArgs) => { + const loadCustomerReviews = async () => { Logger.debug('useReview/loadCustomerReviews'); try { @@ -52,7 +51,7 @@ export const useReview = () => { } }; - const loadReviewMetadata = async (_params?: ComposableFunctionArgs<{}>) => { + const loadReviewMetadata = async () => { Logger.debug('useReview/loadReviewMetadata'); try { From b311a236bafa1246ab5e02d6326ec21b2a0b286a Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Thu, 17 Mar 2022 09:15:51 +0100 Subject: [PATCH 11/11] refactor(composables): add composable command types --- .../theme/composables/useReview/commands/addReviewCommand.ts | 4 +++- .../useReview/commands/loadCustomerReviewsCommand.ts | 5 +++-- .../composables/useReview/commands/searchReviewsCommand.ts | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/theme/composables/useReview/commands/addReviewCommand.ts b/packages/theme/composables/useReview/commands/addReviewCommand.ts index 8ee2ddcc4..0d3912a98 100644 --- a/packages/theme/composables/useReview/commands/addReviewCommand.ts +++ b/packages/theme/composables/useReview/commands/addReviewCommand.ts @@ -1,7 +1,9 @@ import { Context, Logger } from '@vue-storefront/core'; +import {CreateProductReviewInput } from '~/modules/GraphQL/types'; +import { ComposableFunctionArgs } from '~/composables/types'; export const addReviewCommand = { - execute: async (context: Context, params) => { + execute: async (context: Context, params: ComposableFunctionArgs) => { Logger.debug('[Magento] add review params input:', JSON.stringify(params, null, 2)); const { diff --git a/packages/theme/composables/useReview/commands/loadCustomerReviewsCommand.ts b/packages/theme/composables/useReview/commands/loadCustomerReviewsCommand.ts index 0da482eaa..d8ea60761 100644 --- a/packages/theme/composables/useReview/commands/loadCustomerReviewsCommand.ts +++ b/packages/theme/composables/useReview/commands/loadCustomerReviewsCommand.ts @@ -1,7 +1,8 @@ -import { Context, Logger } from '@vue-storefront/core'; +import { ComposableFunctionArgs, Context, Logger } from '@vue-storefront/core'; +import { CustomerProductReviewParams } from '@vue-storefront/magento-api'; export const loadCustomerReviewsCommand = { - execute: async (context: Context, params?) => { + execute: async (context: Context, params?: ComposableFunctionArgs) => { Logger.debug('[Magento] load customer review based on:', { params }); const { data } = await context.$magento.api.customerProductReview(params); diff --git a/packages/theme/composables/useReview/commands/searchReviewsCommand.ts b/packages/theme/composables/useReview/commands/searchReviewsCommand.ts index 4b894ea2e..e6a20bf71 100644 --- a/packages/theme/composables/useReview/commands/searchReviewsCommand.ts +++ b/packages/theme/composables/useReview/commands/searchReviewsCommand.ts @@ -1,8 +1,9 @@ import { Context, Logger } from '@vue-storefront/core'; +import { ComposableFunctionArgs } from '~/composables/types'; import { GetProductSearchParams } from '~/composables/useProduct/useProduct'; export const searchReviewsCommand = { - execute: async (context: Context, params?) => { + execute: async (context: Context, params?: ComposableFunctionArgs) => { Logger.debug('[Magento] search review params input:', JSON.stringify(params, null, 2)); const {