mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-31 10:13:32 -04:00 
			
		
		
		
	fix: QueryFilter Hydration & script setup (#5839)
This commit is contained in:
		| @@ -3,7 +3,7 @@ | ||||
|     v-model="selected" | ||||
|     v-bind="inputAttrs" | ||||
|     v-model:search="searchInput" | ||||
|     :items="storeItem" | ||||
|     :items="items" | ||||
|     :label="label" | ||||
|     chips | ||||
|     closable-chips | ||||
| @@ -46,180 +46,138 @@ | ||||
|   </v-autocomplete> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts"> | ||||
| <script setup lang="ts"> | ||||
| import type { IngredientFood, RecipeCategory, RecipeTag } from "~/lib/api/types/recipe"; | ||||
| import type { RecipeTool } from "~/lib/api/types/admin"; | ||||
| import { Organizer, type RecipeOrganizer } from "~/lib/api/types/non-generated"; | ||||
| import type { HouseholdSummary } from "~/lib/api/types/household"; | ||||
| import { useCategoryStore, useFoodStore, useHouseholdStore, useTagStore, useToolStore } from "~/composables/store"; | ||||
|  | ||||
| export default defineNuxtComponent({ | ||||
|   props: { | ||||
|     modelValue: { | ||||
|       type: Array as () => ( | ||||
|         | HouseholdSummary | ||||
|         | RecipeTag | ||||
|         | RecipeCategory | ||||
|         | RecipeTool | ||||
|         | IngredientFood | ||||
|         | string | ||||
|       )[] | undefined, | ||||
|       required: true, | ||||
|     }, | ||||
|     /** | ||||
|      * The type of organizer to use. | ||||
|      */ | ||||
|     selectorType: { | ||||
|       type: String as () => RecipeOrganizer, | ||||
|       required: true, | ||||
|     }, | ||||
|     inputAttrs: { | ||||
|       type: Object as () => Record<string, any>, | ||||
|       default: () => ({}), | ||||
|     }, | ||||
|     returnObject: { | ||||
|       type: Boolean, | ||||
|       default: true, | ||||
|     }, | ||||
|     showAdd: { | ||||
|       type: Boolean, | ||||
|       default: true, | ||||
|     }, | ||||
|     showLabel: { | ||||
|       type: Boolean, | ||||
|       default: true, | ||||
|     }, | ||||
|     showIcon: { | ||||
|       type: Boolean, | ||||
|       default: true, | ||||
|     }, | ||||
|     variant: { | ||||
|       type: String as () => "filled" | "underlined" | "outlined" | "plain" | "solo" | "solo-inverted" | "solo-filled", | ||||
|       default: "outlined", | ||||
|     }, | ||||
|   }, | ||||
|   emits: ["update:modelValue"], | ||||
| interface Props { | ||||
|   selectorType: RecipeOrganizer; | ||||
|   inputAttrs?: Record<string, any>; | ||||
|   returnObject?: boolean; | ||||
|   showAdd?: boolean; | ||||
|   showLabel?: boolean; | ||||
|   showIcon?: boolean; | ||||
|   variant?: "filled" | "underlined" | "outlined" | "plain" | "solo" | "solo-inverted" | "solo-filled"; | ||||
| } | ||||
|  | ||||
|   setup(props, context) { | ||||
|     const selected = computed({ | ||||
|       get: () => props.modelValue, | ||||
|       set: (val) => { | ||||
|         context.emit("update:modelValue", val); | ||||
|       }, | ||||
|     }); | ||||
|  | ||||
|     onMounted(() => { | ||||
|       if (selected.value === undefined) { | ||||
|         selected.value = []; | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     const i18n = useI18n(); | ||||
|     const { $globals } = useNuxtApp(); | ||||
|  | ||||
|     const label = computed(() => { | ||||
|       if (!props.showLabel) { | ||||
|         return ""; | ||||
|       } | ||||
|  | ||||
|       switch (props.selectorType) { | ||||
|         case Organizer.Tag: | ||||
|           return i18n.t("tag.tags"); | ||||
|         case Organizer.Category: | ||||
|           return i18n.t("category.categories"); | ||||
|         case Organizer.Tool: | ||||
|           return i18n.t("tool.tools"); | ||||
|         case Organizer.Food: | ||||
|           return i18n.t("general.foods"); | ||||
|         case Organizer.Household: | ||||
|           return i18n.t("household.households"); | ||||
|         default: | ||||
|           return i18n.t("general.organizer"); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     const icon = computed(() => { | ||||
|       if (!props.showIcon) { | ||||
|         return ""; | ||||
|       } | ||||
|  | ||||
|       switch (props.selectorType) { | ||||
|         case Organizer.Tag: | ||||
|           return $globals.icons.tags; | ||||
|         case Organizer.Category: | ||||
|           return $globals.icons.categories; | ||||
|         case Organizer.Tool: | ||||
|           return $globals.icons.tools; | ||||
|         case Organizer.Food: | ||||
|           return $globals.icons.foods; | ||||
|         case Organizer.Household: | ||||
|           return $globals.icons.household; | ||||
|         default: | ||||
|           return $globals.icons.tags; | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     // =========================================================================== | ||||
|     // Store & Items Setup | ||||
|  | ||||
|     const storeMap = { | ||||
|       [Organizer.Category]: useCategoryStore(), | ||||
|       [Organizer.Tag]: useTagStore(), | ||||
|       [Organizer.Tool]: useToolStore(), | ||||
|       [Organizer.Food]: useFoodStore(), | ||||
|       [Organizer.Household]: useHouseholdStore(), | ||||
|     }; | ||||
|  | ||||
|     const store = computed(() => { | ||||
|       const { store } = storeMap[props.selectorType]; | ||||
|       return store.value; | ||||
|     }); | ||||
|  | ||||
|     const items = computed(() => { | ||||
|       if (!props.returnObject) { | ||||
|         return store.value.map(item => item.name); | ||||
|       } | ||||
|       return store.value; | ||||
|     }); | ||||
|  | ||||
|     function removeByIndex(index: number) { | ||||
|       if (selected.value === undefined) { | ||||
|         return; | ||||
|       } | ||||
|       const newSelected = selected.value.filter((_, i) => i !== index); | ||||
|       selected.value = [...newSelected]; | ||||
|     } | ||||
|  | ||||
|     function appendCreated(item: any) { | ||||
|       if (selected.value === undefined) { | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       selected.value = [...selected.value, item]; | ||||
|     } | ||||
|  | ||||
|     const dialog = ref(false); | ||||
|  | ||||
|     const searchInput = ref(""); | ||||
|  | ||||
|     function resetSearchInput() { | ||||
|       searchInput.value = ""; | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|       Organizer, | ||||
|       appendCreated, | ||||
|       dialog, | ||||
|       storeItem: items, | ||||
|       label, | ||||
|       icon, | ||||
|       selected, | ||||
|       removeByIndex, | ||||
|       searchInput, | ||||
|       resetSearchInput, | ||||
|     }; | ||||
|   }, | ||||
| const props = withDefaults(defineProps<Props>(), { | ||||
|   inputAttrs: () => ({}), | ||||
|   returnObject: true, | ||||
|   showAdd: true, | ||||
|   showLabel: true, | ||||
|   showIcon: true, | ||||
|   variant: "outlined", | ||||
| }); | ||||
|  | ||||
| const selected = defineModel<( | ||||
|   | HouseholdSummary | ||||
|   | RecipeTag | ||||
|   | RecipeCategory | ||||
|   | RecipeTool | ||||
|   | IngredientFood | ||||
|   | string | ||||
| )[] | undefined>({ required: true }); | ||||
|  | ||||
| onMounted(() => { | ||||
|   if (selected.value === undefined) { | ||||
|     selected.value = []; | ||||
|   } | ||||
| }); | ||||
|  | ||||
| const i18n = useI18n(); | ||||
| const { $globals } = useNuxtApp(); | ||||
|  | ||||
| const label = computed(() => { | ||||
|   if (!props.showLabel) { | ||||
|     return ""; | ||||
|   } | ||||
|  | ||||
|   switch (props.selectorType) { | ||||
|     case Organizer.Tag: | ||||
|       return i18n.t("tag.tags"); | ||||
|     case Organizer.Category: | ||||
|       return i18n.t("category.categories"); | ||||
|     case Organizer.Tool: | ||||
|       return i18n.t("tool.tools"); | ||||
|     case Organizer.Food: | ||||
|       return i18n.t("general.foods"); | ||||
|     case Organizer.Household: | ||||
|       return i18n.t("household.households"); | ||||
|     default: | ||||
|       return i18n.t("general.organizer"); | ||||
|   } | ||||
| }); | ||||
|  | ||||
| const icon = computed(() => { | ||||
|   if (!props.showIcon) { | ||||
|     return ""; | ||||
|   } | ||||
|  | ||||
|   switch (props.selectorType) { | ||||
|     case Organizer.Tag: | ||||
|       return $globals.icons.tags; | ||||
|     case Organizer.Category: | ||||
|       return $globals.icons.categories; | ||||
|     case Organizer.Tool: | ||||
|       return $globals.icons.tools; | ||||
|     case Organizer.Food: | ||||
|       return $globals.icons.foods; | ||||
|     case Organizer.Household: | ||||
|       return $globals.icons.household; | ||||
|     default: | ||||
|       return $globals.icons.tags; | ||||
|   } | ||||
| }); | ||||
|  | ||||
| // =========================================================================== | ||||
| // Store & Items Setup | ||||
|  | ||||
| const storeMap = { | ||||
|   [Organizer.Category]: useCategoryStore(), | ||||
|   [Organizer.Tag]: useTagStore(), | ||||
|   [Organizer.Tool]: useToolStore(), | ||||
|   [Organizer.Food]: useFoodStore(), | ||||
|   [Organizer.Household]: useHouseholdStore(), | ||||
| }; | ||||
|  | ||||
| const store = computed(() => { | ||||
|   const { store } = storeMap[props.selectorType]; | ||||
|   return store.value; | ||||
| }); | ||||
|  | ||||
| const items = computed(() => { | ||||
|   if (!props.returnObject) { | ||||
|     return store.value.map(item => item.name); | ||||
|   } | ||||
|   return store.value; | ||||
| }); | ||||
|  | ||||
| function removeByIndex(index: number) { | ||||
|   if (selected.value === undefined) { | ||||
|     return; | ||||
|   } | ||||
|   const newSelected = selected.value.filter((_, i) => i !== index); | ||||
|   selected.value = [...newSelected]; | ||||
| } | ||||
|  | ||||
| function appendCreated(item: any) { | ||||
|   if (selected.value === undefined) { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   selected.value = [...selected.value, item]; | ||||
| } | ||||
|  | ||||
| const dialog = ref(false); | ||||
|  | ||||
| const searchInput = ref(""); | ||||
|  | ||||
| function resetSearchInput() { | ||||
|   searchInput.value = ""; | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user