Skip to content

Commit

Permalink
[BUS-874] - Search adjustments (#55)
Browse files Browse the repository at this point in the history
* add missing delivery snippet

* improve search ux by using a store for the display of search term, adjusting the handling of search bar on search result page

* add pagination, partial forwards/backwards cache management, fix edge case undefined display in input

* linting

* load german localization in formkit config, not applied yet

* add missing check for promotion in orderitem display

* linting
  • Loading branch information
m-borgmann authored Sep 30, 2024
1 parent 52138eb commit ebf4f9c
Show file tree
Hide file tree
Showing 28 changed files with 162 additions and 47 deletions.
2 changes: 1 addition & 1 deletion components/Checkout/CheckoutTotalDeliveryTime.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ const latestDeliveryDate = computed(() => {

<template>
<div v-if="earliestDeliveryDate && latestDeliveryDate">
Order delivery period: {{ earliestDeliveryDate }} - {{ latestDeliveryDate }}
{{ $t('order.deliveryPeriod') }} {{ earliestDeliveryDate }} - {{ latestDeliveryDate }}
</div>
</template>
2 changes: 1 addition & 1 deletion components/Cms/Block/CmsBlockCategoryNavigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ const content: Schemas['CmsSlot'] = getSlotContent('content');

<template>
<CmsLoader :content="content" />
</template>
</template>
2 changes: 1 addition & 1 deletion components/Cms/Element/CmsElementBuyBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const { product } = useProduct(props.element.data.product);
:label="true"
/>
<div class="rounded-md border border-gray-medium bg-white">
<ProductAddToWishlist :productId="product.id" />
<ProductAddToWishlist :product-id="product.id" />
</div>
</div>
</div>
Expand Down
1 change: 0 additions & 1 deletion components/Cms/Element/CmsElementCategoryNavigation.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script setup lang="ts">
import type { CmsElementCategoryNavigation } from '@shopware-pwa/composables-next';
import { getCategoryRoute, getTranslatedProperty } from '@shopware-pwa/helpers-next';
import type { Schemas } from '@shopware/api-client/api-types';
defineProps<{
element: CmsElementCategoryNavigation;
Expand Down
2 changes: 1 addition & 1 deletion components/Cookie/CookieBannerActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ const { isAcceptAllEnabled } = storeToRefs(cookieBannerStore);
{{ $t('cookie.banner.allowAllButton') }}
</button>
</div>
</template>
</template>
5 changes: 4 additions & 1 deletion components/Cookie/CookieBannerMessage.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<template>
<div>
<span>{{ $t('cookie.banner.message') }}</span>
<LazySharedModal :with-close-button="true" size="sm">
<LazySharedModal
:with-close-button="true"
size="sm"
>
<template #trigger>
<button class="ml-2 text-status-info">
{{ $t('cookie.banner.additionalInformationTriggerButton') }}
Expand Down
1 change: 0 additions & 1 deletion components/Cookie/CookieBannerModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const onDenyAll = () => {
cookieBannerStore.denyAll();
modalController.close();
};
</script>

<template>
Expand Down
2 changes: 1 addition & 1 deletion components/Error/ErrorMaintenance.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<p class="pb-8 text-center">
{{ $t('error.maintenance.detail') }}
<br>
<br />
{{ $t('error.maintenance.tryAgain') }}
</p>

Expand Down
4 changes: 1 addition & 3 deletions components/Error/ErrorServer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ defineProps<{
class="block h-20 w-20 text-gray-dark"
/>

<h1 class="pb-4 pt-6">
{{ $t('error.server.heading') }} - {{ error.statusCode }}
</h1>
<h1 class="pb-4 pt-6">{{ $t('error.server.heading') }} - {{ error.statusCode }}</h1>

<p class="pb-8 text-center">
{{ $t('error.server.detail') }}
Expand Down
4 changes: 1 addition & 3 deletions components/Error/ErrorUnknown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ defineProps<{
class="block h-20 w-20 text-gray-dark"
/>

<h1 class="pb-4 pt-6">
{{ $t('error.unknown.heading') }} - {{ error.statusCode }}
</h1>
<h1 class="pb-4 pt-6">{{ $t('error.unknown.heading') }} - {{ error.statusCode }}</h1>

<p class="pb-8 text-center">
{{ $t('error.unknown.detail') }}
Expand Down
6 changes: 6 additions & 0 deletions components/Layout/Header/Search/LayoutHeaderSearch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ onClickOutside(searchComponent, event => {
searchVisible.value = false;
}
});
// If the user is on the result page automatically open the search bar
const route = useRoute();
if (route.path === '/search') {
searchVisible.value = true;
}
</script>

<template>
Expand Down
60 changes: 45 additions & 15 deletions components/Layout/Header/Search/LayoutHeaderSearchBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,42 +15,71 @@ const props = withDefaults(
defineEmits(['closeSearch']);
const { searchTerm, search, getProducts, getTotal, loading } = useProductSearchSuggest();
const { push } = useRouter();
const router = useRouter();
// String the user has typed in the search field
const typingQuery = ref('');
// Reference to the searchInput to focus it onMount
const searchInput = ref(null);
// Perform search if input is greater or equal to the minimum characters prop
watch(typingQuery, (value: string) => {
// If the user is on the result page, hide suggestions since the listing is automatically updated
const isResultPage = ref(false);
const route = useRoute();
if (route.path === '/search') {
isResultPage.value = true;
}
// Use searchStore to share searchTerm with search result page
const searchStore = useSearchStore();
// Defer the search request to prevent the search from instantly being triggered, 500ms fixes holding backspace triggering twice
const performDebouncedSearch = useDebounceFn((value: string) => {
// Only perform search and update valid searchTerm if searchTerm is longer than minCharacters
if (value.length >= props.minCharacters) {
performSuggestSearch(value);
searchTerm.value = value;
searchStore.updateLastValidSearchTerm(value);
search();
// Update URL with new valid search term
if (isResultPage.value) {
router.push({
query: {
...route.query,
search: value,
},
});
}
}
});
}, 500);
// Defer the search request to prevent the search from instantly being triggered after every character typed
const performSuggestSearch = useDebounceFn((value: string) => {
searchTerm.value = value;
search();
}, 300);
watch(typingQuery, (value: string) => {
// Update searchTerm in searchStore
searchStore.updateSearchTerm(value);
performDebouncedSearch(value);
});
// Suggest results will only be shown, when the user has typed more than the minimum characters prop in the search field
const showSuggest = computed(() => {
return typingQuery.value.length >= props.minCharacters;
return typingQuery.value.length >= props.minCharacters && !isResultPage.value;
});
// Redirect to search page when pressing enter
// Redirect to search result page when pressing enter
const handleEnter = () => {
if (typingQuery.value.length >= 1) {
push('/search?search=' + typingQuery.value);
navigateTo('/search?search=' + typingQuery.value);
}
};
onMounted(() => {
// Get the input from the ref (need querySelector since the ref returns the FormKit wrapper and not the input itself)
searchInput.value.$el.querySelector('input').focus();
// If on result page, set the search input to the last valid search term when opening it
if (isResultPage.value) {
searchInput.value.$el.querySelector('input').value =
searchStore.lastValidSearchTerm !== '' ? searchStore.lastValidSearchTerm : route.query.search ?? '';
}
});
</script>

Expand All @@ -72,7 +101,7 @@ onMounted(() => {
@keyup.enter="
() => {
handleEnter();
$emit('closeSearch');
isResultPage = true;
}
"
/>
Expand Down Expand Up @@ -106,11 +135,12 @@ onMounted(() => {
v-if="getTotal > 0"
:to="'/search?search=' + typingQuery"
class="block w-full py-3"
@click="$emit('closeSearch')"
@click="isResultPage = true"
>
<template v-if="getTotal > 1">
<span>{{ $t('search.searchBar.resultsLinkLabel', { number: getTotal }) }}</span>
</template>

<template v-else>
<span>{{ $t('search.searchBar.oneResultLinkLabel') }}</span>
</template>
Expand Down
2 changes: 1 addition & 1 deletion components/Navigation/NavigationMainItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const debounced = refDebounced(isOutsideNavItem, 300);
<template>
<div
ref="navigationItem"
class="min-w-max px-2 py-4"
class="min-w-max px-2 py-4 first:pl-0 last:pr-0"
>
<NavigationLink
:navigation-element="navigationElement"
Expand Down
16 changes: 15 additions & 1 deletion components/Order/OrderLineItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ const props = defineProps<{
}>();
const { lineItem } = toRefs(props);
const { isPromotion } = useCartItem(lineItem);
const lineItemCover = getProductCover(lineItem.value.cover, 'xs');
</script>

<template>
<div class="mr-4 h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-medium bg-gray-light">
<NuxtLink :to="getProductRoute(lineItem)">
<NuxtLink
v-if="!isPromotion"
:to="getProductRoute(lineItem)"
>
<template v-if="lineItemCover.placeholder">
<SharedImagePlaceholder :size="'sm'" />
</template>
Expand All @@ -28,6 +32,16 @@ const lineItemCover = getProductCover(lineItem.value.cover, 'xs');
/>
</template>
</NuxtLink>

<div
v-else-if="isPromotion"
class="flex h-full w-full items-center justify-center"
>
<FormKitIcon
icon="percent"
class="block h-16 w-16 text-gray"
/>
</div>
</div>

<div class="flex flex-1 flex-col">
Expand Down
4 changes: 3 additions & 1 deletion components/Product/ProductAvailability.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const restockTime = props.product.restockTime ?? props.product.deliveryInformati
{{ $t('product.availability.deliveryTime', { deliveryTime: deliveryTime?.name }) }}
</span>

<span v-else-if="availableStock < minPurchase">{{ $t('product.availability.notAvailable') }}</span>
<span v-else-if="availableStock < minPurchase">
{{ $t('product.availability.notAvailable') }}
</span>
</div>
</template>
2 changes: 1 addition & 1 deletion components/Product/ProductCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const cover = getProductCover(props.product.cover);
<template>
<div class="relative rounded-md p-4 shadow-md">
<div class="absolute right-0 top-0 z-[2] p-4">
<ProductAddToWishlist :productId="props.product.id" />
<ProductAddToWishlist :product-id="props.product.id" />
</div>
<NuxtLink
:to="getProductRoute(product)"
Expand Down
2 changes: 1 addition & 1 deletion components/Product/ProductGoToDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ defineProps<{
>
{{ $t('product.goToDetail.label') }}
</NuxtLink>
</template>
</template>
2 changes: 1 addition & 1 deletion components/Shared/SharedModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const onUpdatedOpen = (value: boolean) => {
leave-to-class="-translate-y-10 scale-50"
>
<DialogContent
class="fixed left-1/2 top-8 z-[100] -translate-x-1/2 rounded-lg bg-white shadow-lg focus:outline-none max-h-[calc(100vh-4rem)] overflow-auto"
class="fixed left-1/2 top-8 z-[100] max-h-[calc(100vh-4rem)] -translate-x-1/2 overflow-auto rounded-lg bg-white shadow-lg focus:outline-none"
:class="{
'w-80': size === 'sm',
'w-128': size === 'md',
Expand Down
2 changes: 1 addition & 1 deletion composables/useActivePath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ export const useActivePath = () => {
};

return { isActive };
};
};
2 changes: 1 addition & 1 deletion composables/useCookieGroupsHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,4 @@ export function useCookieGroupsHelper() {
defaultCookieGroup,
filterCookieGroups,
};
};
}
2 changes: 1 addition & 1 deletion error.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const pageNotFound = computed(() => {
});
const isMaintenanceMode = computed(() => {
return props.error.statusCode === 503 && props.error.statusMessage === "MAINTENANCE_MODE";
return props.error.statusCode === 503 && props.error.statusMessage === 'MAINTENANCE_MODE';
});
const genericServerError = computed(() => {
Expand Down
2 changes: 2 additions & 0 deletions formkit.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { rootClasses } from './formkit.theme';
import { de } from '@formkit/i18n';
import { createAutoAnimatePlugin, createFloatingLabelsPlugin } from '@formkit/addons';
import '@formkit/addons/css/floatingLabels';

Expand Down Expand Up @@ -58,6 +59,7 @@ export default {
return undefined;
});
},
locales: { de },
config: {
rootClasses,
},
Expand Down
2 changes: 1 addition & 1 deletion i18n/de-DE/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"layout": {
"breadcrumb": {
"ariaLabel": "Breadcrumb",
"homeLinkLabel": "Home"
"homeLinkLabel": "Startseite"
}
}
}
3 changes: 2 additions & 1 deletion i18n/de-DE/order.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"taxLabel": "MwSt.",
"shippingCostLabel": "Versand",
"totalLabel": "Gesamt"
}
},
"deliveryPeriod": "Lieferzeitraum:"
}
}
3 changes: 2 additions & 1 deletion i18n/en-GB/order.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"taxLabel": "Tax",
"shippingCostLabel": "Shipping",
"totalLabel": "Total"
}
},
"deliveryPeriod": "Order delivery period:"
}
}
Loading

0 comments on commit ebf4f9c

Please sign in to comment.