Skip to content

Commit

Permalink
refactor: replace useFacet with useProduct for searching
Browse files Browse the repository at this point in the history
useFacet is meant to be used with url sorting params in the product category
page, not with simple product searches. useFacet implicitly has some category
search logic while the search bar doesn't care about products
  • Loading branch information
sethidden committed Jun 2, 2022
1 parent 6d29de6 commit c1637ea
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 66 deletions.
22 changes: 12 additions & 10 deletions packages/theme/components/AppHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,16 @@
</template>
<template #search>
<SearchBar
@SearchBar:toggle="isSearchOpen = $event"
@SearchBar:result="result = $event"
:is-search-open="isSearchOpen"
@set-is-open="isSearchOpen = $event"
@set-search-results="productSearchResults = $event"
/>
</template>
</SfHeader>
<SearchResults
v-if="isSearchOpen"
:visible="isSearchOpen"
:result="result"
:search-results="productSearchResults"
/>
<SfOverlay :visible="isSearchOpen" />
</div>
Expand All @@ -115,16 +116,16 @@ import {
useFetch,
} from '@nuxtjs/composition-api';
import HeaderNavigation from '~/components/Header/Navigation/HeaderNavigation.vue';
import useCategory from '~/modules/catalog/category/composables/useCategory';
import { useCategory } from '~/modules/catalog/category/composables/useCategory';
import {
useUiHelpers,
useUiState,
} from '~/composables';
import useCart from '~/modules/checkout/composables/useCart';
import useWishlist from '~/modules/wishlist/composables/useWishlist';
import { useCart } from '~/modules/checkout/composables/useCart';
import { useWishlist } from '~/modules/wishlist/composables/useWishlist';
import { useUser } from '~/modules/customer/composables/useUser';
import { useWishlistStore } from '~/modules/wishlist/store/wishlistStore';
import type { CategoryTree } from '~/modules/GraphQL/types';
import type { CategoryTree, ProductInterface } from '~/modules/GraphQL/types';
import CurrencySelector from '~/components/CurrencySelector.vue';
import HeaderLogo from '~/components/HeaderLogo.vue';
import SvgImage from '~/components/General/SvgImage.vue';
Expand Down Expand Up @@ -156,9 +157,10 @@ export default defineComponent({
const { loadItemsCount: loadWishlistItemsCount } = useWishlist();
const { categories: categoryList, load: categoriesListLoad } = useCategory();
const wishlistStore = useWishlistStore();
const isSearchOpen = ref(false);
const result = ref(null);
const productSearchResults = ref<ProductInterface[] | null>(null);
const wishlistStore = useWishlistStore();
const wishlistItemsQty = computed(() => wishlistStore.wishlist?.items_count ?? 0);
const wishlistHasProducts = computed(() => wishlistItemsQty.value > 0);
Expand Down Expand Up @@ -196,7 +198,7 @@ export default defineComponent({
handleAccountClick,
isAuthenticated,
isSearchOpen,
result,
productSearchResults,
setTermForUrl,
toggleCartSidebar,
toggleWishlistSidebar,
Expand Down
58 changes: 26 additions & 32 deletions packages/theme/components/Header/SearchBar/SearchBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ import {
import debounce from 'lodash.debounce';
import { clickOutside } from '~/utilities/directives/click-outside/click-outside-directive';
import SvgImage from '~/components/General/SvgImage.vue';
import { useFacet } from '~/modules/catalog/category/composables/useFacet';
import { useProduct } from '~/modules/catalog/product/composables/useProduct';
import { Products } from '~/modules/GraphQL/types';
export default defineComponent({
name: 'SearchBar',
Expand All @@ -67,6 +68,10 @@ export default defineComponent({
},
directives: { clickOutside },
props: {
isSearchOpen: {
type: Boolean,
default: false,
},
itemsPerPage: {
type: Number,
default: 12,
Expand All @@ -76,41 +81,34 @@ export default defineComponent({
default: 3,
},
},
setup({ itemsPerPage, minTermLen }, { emit }) {
emits: ['set-is-open', 'set-search-results'],
setup(props, { emit }) {
const term = ref('');
const isSearchOpen = ref(false);
const result = ref(null);
const route = useRoute();
const {
result: searchResult,
search: productsSearch,
} = useFacet();
const { getProductList } = useProduct();
const showSearch = () => {
if (!isSearchOpen.value) {
isSearchOpen.value = true;
emit('SearchBar:toggle', true);
if (!props.isSearchOpen) {
emit('set-is-open', true);
if (document) {
document.body.classList.add('no-scroll');
}
}
};
const hideSearch = () => {
if (isSearchOpen.value) {
isSearchOpen.value = false;
emit('SearchBar:toggle', false);
emit('SearchBar:result', {});
if (props.isSearchOpen) {
emit('set-is-open', false);
emit('set-search-results', null);
if (document) {
document.body.classList.remove('no-scroll');
}
}
};
const toggleSearch = () => {
if (isSearchOpen.value) {
if (props.isSearchOpen) {
hideSearch();
} else {
showSearch();
Expand All @@ -119,10 +117,10 @@ export default defineComponent({
const closeSearch = (event: MouseEvent) => {
if (document) {
const searchResultsEl = document.querySelectorAll('.search');
const searchResultsEl = document.querySelector('.search');
const closeTriggerElement = event.target as HTMLElement;
if (!searchResultsEl[0]?.contains(closeTriggerElement)) {
if (!searchResultsEl?.contains(closeTriggerElement)) {
hideSearch();
term.value = '';
}
Expand All @@ -132,20 +130,17 @@ export default defineComponent({
}
};
const handleSearch = debounce(async (paramValue) => {
term.value = !paramValue.target ? paramValue : paramValue.target.value;
if (term.value.length < minTermLen) return;
await productsSearch({
itemsPerPage,
term: term.value,
});
const handleSearch = debounce(async (searchTerm: string) => {
term.value = searchTerm;
if (term.value.length < props.minTermLen) return;
result.value = {
products: searchResult.value?.data?.items,
};
// M2-579
const productList : Products = await getProductList({
pageSize: props.itemsPerPage,
search: term.value,
}) as unknown as Products;
emit('SearchBar:result', result.value);
emit('set-search-results', productList!.items);
}, 1000);
watch(route, () => {
Expand All @@ -159,7 +154,6 @@ export default defineComponent({
hideSearch,
toggleSearch,
handleSearch,
isSearchOpen,
term,
};
},
Expand Down
44 changes: 20 additions & 24 deletions packages/theme/components/Header/SearchBar/SearchResults.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div>
<SfMegaMenu
:visible="isSearchOpen"
:visible="visible"
:title="$t('Search results')"
class="search"
>
Expand All @@ -10,7 +10,7 @@
mode="out-in"
>
<div
v-if="products && products.length > 0"
v-if="searchResults && searchResults.length > 0"
key="results"
class="search__wrapper-results"
>
Expand All @@ -35,7 +35,7 @@
>
<div class="results-listing">
<SfProductCard
v-for="(product, index) in products"
v-for="(product, index) in searchResultsWithWishlistInfo"
:key="index"
class="result-card"
image-tag="nuxt-img"
Expand Down Expand Up @@ -68,13 +68,13 @@
:wishlist-icon="isAuthenticated ? 'heart' : ''"
:is-in-wishlist-icon="isAuthenticated ? 'heart_fill' : ''"
:is-in-wishlist="product.isInWishlist"
@click:wishlist="addItemToWishlist(product)"
@click:wishlist="addOrRemoveWishlistItem(product)"
/>
</div>
</SfScrollable>
<div class="results--mobile smartphone-only">
<SfProductCard
v-for="(product, index) in products"
v-for="(product, index) in searchResultsWithWishlistInfo"
:key="index"
class="result-card"
image-tag="nuxt-img"
Expand Down Expand Up @@ -104,7 +104,7 @@
:wishlist-icon="isAuthenticated ? 'heart' : ''"
:is-in-wishlist-icon="isAuthenticated ? 'heart_fill' : ''"
:is-in-wishlist="product.isInWishlist"
@click:wishlist="addItemToWishlist(product)"
@click:wishlist="addOrRemoveWishlistItem(product)"
/>
</div>
</SfMegaMenuColumn>
Expand Down Expand Up @@ -154,12 +154,11 @@ import {
SfMenuItem,
SfButton,
} from '@storefront-ui/vue';
import { ref, computed, defineComponent } from '@nuxtjs/composition-api';
import { defineComponent, computed } from '@nuxtjs/composition-api';
import type { PropType } from '@nuxtjs/composition-api';
import productGetters from '~/modules/catalog/product/getters/productGetters';
import {
useUiHelpers, useImage,
} from '~/composables';
import useWishlist from '~/modules/wishlist/composables/useWishlist';
import { useUiHelpers, useImage } from '~/composables';
import { useWishlist } from '~/modules/wishlist/composables/useWishlist';
import { useUser } from '~/modules/customer/composables/useUser';
import SvgImage from '~/components/General/SvgImage.vue';
import type { Product } from '~/modules/catalog/product/types';
Expand All @@ -179,35 +178,32 @@ export default defineComponent({
type: Boolean,
default: false,
},
result: {
type: Object,
default: () => ({}),
searchResults: {
type: Array as PropType<Product[] | null>,
default: () => [],
},
},
setup(props) {
const { isAuthenticated } = useUser();
const { isInWishlist, addOrRemoveItem } = useWishlist();
const { isInWishlist, addOrRemoveItem: addOrRemoveWishlistItem } = useWishlist();
const th = useUiHelpers();
const isSearchOpen = ref(props.visible);
const products = computed(() => props.result?.products);
const addItemToWishlist = async (product: Product) => {
await addOrRemoveItem({ product });
};
const searchResultsWithWishlistInfo = computed(() => props.searchResults?.map((product) => ({
...product,
isInWishlist: isInWishlist({ product }),
})));
const { getMagentoImage, imageSizes } = useImage();
return {
th,
isSearchOpen,
productGetters,
products,
addItemToWishlist,
addOrRemoveWishlistItem,
isInWishlist,
isAuthenticated,
getMagentoImage,
imageSizes,
searchResultsWithWishlistInfo,
};
},
});
Expand Down

0 comments on commit c1637ea

Please sign in to comment.