mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-31 10:13:32 -04:00 
			
		
		
		
	feat: add the fuzzy search on Categories, Tags, and Tools pages (#1867)
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							b7ab16a7df
						
					
				
				
					commit
					05dfe38f19
				
			| @@ -12,6 +12,22 @@ | ||||
|     > | ||||
|       <v-card-text> {{ $t("general.confirm-delete-generic-with-name", { name: deleteTarget.name }) }} </v-card-text> | ||||
|     </BaseDialog> | ||||
|  | ||||
|     <v-row dense> | ||||
|         <v-col> | ||||
|           <v-text-field | ||||
|             v-model="searchString" | ||||
|             outlined | ||||
|             autofocus | ||||
|             color="primary accent-3" | ||||
|             :placeholder="$t('search.search-placeholder')" | ||||
|             :prepend-inner-icon="$globals.icons.search" | ||||
|             clearable | ||||
|           > | ||||
|           </v-text-field> | ||||
|         </v-col> | ||||
|       </v-row> | ||||
|  | ||||
|     <v-app-bar color="transparent" flat class="mt-n1 rounded align-center"> | ||||
|       <v-icon large left> | ||||
|         {{ icon }} | ||||
| @@ -24,8 +40,8 @@ | ||||
|       <v-spacer></v-spacer> | ||||
|       <BaseButton create @click="dialog = true" /> | ||||
|     </v-app-bar> | ||||
|     <section v-for="(itms, key, idx) in itemsSorted" :key="'header' + idx" :class="idx === 1 ? null : 'my-4'"> | ||||
|       <BaseCardSectionTitle :title="key"> </BaseCardSectionTitle> | ||||
|     <section v-for="(itms, key, idx) in showItems" :key="'header' + idx" :class="idx === 1 ? null : 'my-4'"> | ||||
|       <BaseCardSectionTitle v-if="key.length === 1" :title="key"> </BaseCardSectionTitle> | ||||
|       <v-row> | ||||
|         <v-col v-for="(item, index) in itms" :key="'cat' + index" cols="12" :sm="12" :md="6" :lg="4" :xl="3"> | ||||
|           <v-card class="left-border" hover :to="`/recipes/${itemType}/${item.slug}`"> | ||||
| @@ -47,10 +63,12 @@ | ||||
| </template> | ||||
|  | ||||
| <script lang="ts"> | ||||
| import { defineComponent, computed, ref } from "@nuxtjs/composition-api"; | ||||
| import Fuse from "fuse.js"; | ||||
| import { defineComponent, computed, ref, reactive } from "@nuxtjs/composition-api"; | ||||
| import { useContextPresets } from "~/composables/use-context-presents"; | ||||
| import RecipeOrganizerDialog from "~/components/Domain/Recipe/RecipeOrganizerDialog.vue"; | ||||
| import { RecipeOrganizer } from "~/lib/api/types/non-generated"; | ||||
| import { useRouteQuery } from "~/composables/use-router"; | ||||
|  | ||||
| interface GenericItem { | ||||
|   id?: string; | ||||
| @@ -77,6 +95,20 @@ export default defineComponent({ | ||||
|     }, | ||||
|   }, | ||||
|   setup(props, { emit }) { | ||||
|     const state = reactive({ | ||||
|       // Search Options | ||||
|       options: { | ||||
|         ignoreLocation: true, | ||||
|         shouldSort: true, | ||||
|         threshold: 0.6, | ||||
|         location: 0, | ||||
|         distance: 100, | ||||
|         findAllMatches: true, | ||||
|         maxPatternLength: 32, | ||||
|         minMatchCharLength: 1, | ||||
|         keys: ["name"], | ||||
|       }, | ||||
|     }); | ||||
|     // ================================================================= | ||||
|     // Sorted Items | ||||
|     const itemsSorted = computed(() => { | ||||
| @@ -119,6 +151,31 @@ export default defineComponent({ | ||||
|  | ||||
|     const dialog = ref(false); | ||||
|  | ||||
|     // ================================================================ | ||||
|     // Search Functions | ||||
|  | ||||
|     const searchString = useRouteQuery("q", ""); | ||||
|  | ||||
|     const fuse = computed(() => { | ||||
|       return new Fuse(props.items, state.options); | ||||
|     }); | ||||
|  | ||||
|     const fuzzyItems = computed(() => { | ||||
|       if (searchString.value.trim() === "") { | ||||
|         return props.items; | ||||
|       } | ||||
|       const result = fuse.value.search(searchString.value.trim() as string); | ||||
|       return result.map((x) => x.item); | ||||
|     }); | ||||
|  | ||||
|     const showItems = computed(() => { | ||||
|       if (searchString.value.trim() === "") { | ||||
|         return itemsSorted.value; | ||||
|       } else { | ||||
|         return fuzzyItems; | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     return { | ||||
|       dialog, | ||||
|       confirmDelete, | ||||
| @@ -127,6 +184,8 @@ export default defineComponent({ | ||||
|       deleteTarget, | ||||
|       presets, | ||||
|       itemsSorted, | ||||
|       searchString, | ||||
|       showItems, | ||||
|     }; | ||||
|   }, | ||||
|   // Needed for useMeta | ||||
|   | ||||
		Reference in New Issue
	
	Block a user