From e18291710313c04360da8bdf73faf852dc7fa7d1 Mon Sep 17 00:00:00 2001 From: indy koning Date: Thu, 13 Aug 2026 17:01:35 +0200 Subject: [PATCH 1/4] Hide irrelevant filters when they barely return products --- config/rapidez/searchkit.php | 5 +++ resources/js/components/Listing/Listing.vue | 40 +++++++++++++++++++ .../listing/partials/filter/boolean.blade.php | 2 +- .../listing/partials/filter/select.blade.php | 2 +- .../listing/partials/filter/swatch.blade.php | 2 +- 5 files changed, 48 insertions(+), 3 deletions(-) diff --git a/config/rapidez/searchkit.php b/config/rapidez/searchkit.php index 0da079bfa..bb029c73d 100644 --- a/config/rapidez/searchkit.php +++ b/config/rapidez/searchkit.php @@ -59,6 +59,11 @@ ['attribute' => 'visibility', 'field' => 'visibility', 'type' => 'numeric'], ], + // The minimum percentage of products that should be available for a filter to be shown. + // For example, if you have 100 products in the listing and a filter has only 5 products available, + // the filter will not be shown because it is only available for 5% of the products. + 'min_filter_product_percentage' => 10, + // Additional sorting options to be added to the product listings // Given directions can only be an array of 'asc' and/or 'desc' // Order shown here will be the order shown in the dropdown (including the order of the given directions!) diff --git a/resources/js/components/Listing/Listing.vue b/resources/js/components/Listing/Listing.vue index 42166e7b3..205f85c7a 100644 --- a/resources/js/components/Listing/Listing.vue +++ b/resources/js/components/Listing/Listing.vue @@ -8,6 +8,7 @@ import RangeInput from 'vue-instantsearch/vue3/es/src/components/RangeInput.vue. import HierarchicalMenu from 'vue-instantsearch/vue3/es/src/components/HierarchicalMenu.vue.js' import RefinementList from 'vue-instantsearch/vue3/es/src/components/RefinementList.vue.js' import SortBy from 'vue-instantsearch/vue3/es/src/components/SortBy.vue.js' +import { instantsearchMiddlewares } from '../../stores/useInstantsearchMiddlewares' export default { mixins: [InstantSearchMixin], @@ -59,6 +60,7 @@ export default { searchClient: null, destroyed: false, utmFields: [], + instantSearchInstance: null, }), render() { @@ -127,6 +129,19 @@ export default { }, methods: { + getMiddlewares() { + return [ + ({ instantSearchInstance }) => { + this.instantSearchInstance = instantSearchInstance + return { + onStateChange: () => {}, + subscribe: () => {}, + unsubscribe: () => {}, + } + }, + ...instantsearchMiddlewares + ] + }, async getInstantSearchClientConfig() { const config = await InstantSearchMixin.methods.getInstantSearchClientConfig.bind(this).call() @@ -256,6 +271,31 @@ export default { ...item, })) }, + + isRelevantFilter(filterItems, minProductPercentage = null) { + if (!filterItems?.length) { + return false + } + + if (filterItems.some((item) => item.isRefined)) { + return true + } + + if (!this.instantSearchInstance) { + return true + } + const totalHits = this.instantSearchInstance?.helper?.lastResults?.nbHits; + if (!totalHits) { + return true + } + if (isNaN(minProductPercentage) || minProductPercentage === null) { + minProductPercentage = window.config.searchkit.min_filter_product_percentage ?? 10 + } + + const resultCount = filterItems.reduce((sum, item) => item.count + sum, 0) + + return resultCount / totalHits > minProductPercentage / 100 + } }, } diff --git a/resources/views/listing/partials/filter/boolean.blade.php b/resources/views/listing/partials/filter/boolean.blade.php index ed043d4cd..b7aa6b5a8 100644 --- a/resources/views/listing/partials/filter/boolean.blade.php +++ b/resources/views/listing/partials/filter/boolean.blade.php @@ -6,7 +6,7 @@ class="relative -mx-1 -mt-1" >