mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-31 10:13:32 -04:00 
			
		
		
		
	fix: Refactor Stores and Fix Missing Public Cookbooks (#5611)
Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
This commit is contained in:
		| @@ -138,14 +138,48 @@ export default defineNuxtComponent({ | |||||||
|     const groupSlug = computed(() => route.params.groupSlug as string || $auth.user.value?.groupSlug || ""); |     const groupSlug = computed(() => route.params.groupSlug as string || $auth.user.value?.groupSlug || ""); | ||||||
|  |  | ||||||
|     const cookbookPreferences = useCookbookPreferences(); |     const cookbookPreferences = useCookbookPreferences(); | ||||||
|     const { store: cookbooks, actions: cookbooksActions } = isOwnGroup.value ? useCookbookStore() : usePublicCookbookStore(groupSlug.value || ""); |  | ||||||
|     onMounted(() => { |     const ownCookbookStore = useCookbookStore(i18n); | ||||||
|       if (!cookbooks.value.length) { |     const ownHouseholdStore = useHouseholdStore(i18n); | ||||||
|         cookbooksActions.refresh(); |  | ||||||
|  |     const publicCookbookStoreCache = ref<Record<string, ReturnType<typeof usePublicCookbookStore>>>({}); | ||||||
|  |     const publicHouseholdStoreCache = ref<Record<string, ReturnType<typeof usePublicHouseholdStore>>>({}); | ||||||
|  |  | ||||||
|  |     function getPublicCookbookStore(slug: string) { | ||||||
|  |       if (!publicCookbookStoreCache.value[slug]) { | ||||||
|  |         publicCookbookStoreCache.value[slug] = usePublicCookbookStore(slug, i18n); | ||||||
|       } |       } | ||||||
|  |       return publicCookbookStoreCache.value[slug]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function getPublicHouseholdStore(slug: string) { | ||||||
|  |       if (!publicHouseholdStoreCache.value[slug]) { | ||||||
|  |         publicHouseholdStoreCache.value[slug] = usePublicHouseholdStore(slug, i18n); | ||||||
|  |       } | ||||||
|  |       return publicHouseholdStoreCache.value[slug]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const cookbooks = computed(() => { | ||||||
|  |       if (isOwnGroup.value) { | ||||||
|  |         return ownCookbookStore.store.value; | ||||||
|  |       } | ||||||
|  |       else if (groupSlug.value) { | ||||||
|  |         const publicStore = getPublicCookbookStore(groupSlug.value); | ||||||
|  |         return unref(publicStore.store); | ||||||
|  |       } | ||||||
|  |       return []; | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     const { store: households } = isOwnGroup.value ? useHouseholdStore() : usePublicHouseholdStore(groupSlug.value || ""); |     const households = computed(() => { | ||||||
|  |       if (isOwnGroup.value) { | ||||||
|  |         return ownHouseholdStore.store.value; | ||||||
|  |       } | ||||||
|  |       else if (groupSlug.value) { | ||||||
|  |         const publicStore = getPublicHouseholdStore(groupSlug.value); | ||||||
|  |         return unref(publicStore.store); | ||||||
|  |       } | ||||||
|  |       return []; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|     const householdsById = computed(() => { |     const householdsById = computed(() => { | ||||||
|       return households.value.reduce((acc, household) => { |       return households.value.reduce((acc, household) => { | ||||||
| @@ -178,6 +212,10 @@ export default defineNuxtComponent({ | |||||||
|  |  | ||||||
|     const currentUserHouseholdId = computed(() => $auth.user.value?.householdId); |     const currentUserHouseholdId = computed(() => $auth.user.value?.householdId); | ||||||
|     const cookbookLinks = computed<SideBarLink[]>(() => { |     const cookbookLinks = computed<SideBarLink[]>(() => { | ||||||
|  |       if (!cookbooks.value?.length) { | ||||||
|  |         return []; | ||||||
|  |       } | ||||||
|  |  | ||||||
|       const sortedCookbooks = [...cookbooks.value].sort((a, b) => (a.position || 0) - (b.position || 0)); |       const sortedCookbooks = [...cookbooks.value].sort((a, b) => (a.position || 0) - (b.position || 0)); | ||||||
|  |  | ||||||
|       const ownLinks: SideBarLink[] = []; |       const ownLinks: SideBarLink[] = []; | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| import type { AxiosInstance, AxiosResponse, AxiosRequestConfig } from "axios"; | import type { AxiosInstance, AxiosResponse, AxiosRequestConfig } from "axios"; | ||||||
|  | import type { Composer } from "vue-i18n"; | ||||||
| import type { ApiRequestInstance, RequestResponse } from "~/lib/api/types/non-generated"; | import type { ApiRequestInstance, RequestResponse } from "~/lib/api/types/non-generated"; | ||||||
| import { AdminAPI, PublicApi, UserApi } from "~/lib/api"; | import { AdminAPI, PublicApi, UserApi } from "~/lib/api"; | ||||||
| import { PublicExploreApi } from "~/lib/api/client-public"; | import { PublicExploreApi } from "~/lib/api/client-public"; | ||||||
| @@ -52,31 +53,34 @@ function getRequests(axiosInstance: AxiosInstance): ApiRequestInstance { | |||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  |  | ||||||
| export const useRequests = function (): ApiRequestInstance { | export const useRequests = function (i18n?: Composer): ApiRequestInstance { | ||||||
|   const i18n = useI18n(); |  | ||||||
|   const { $axios } = useNuxtApp(); |   const { $axios } = useNuxtApp(); | ||||||
|  |   if (!i18n) { | ||||||
|  |     // Only works in a setup block | ||||||
|  |     i18n = useI18n(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   $axios.defaults.headers.common["Accept-Language"] = i18n.locale.value; |   $axios.defaults.headers.common["Accept-Language"] = i18n.locale.value; | ||||||
|  |  | ||||||
|   return getRequests($axios); |   return getRequests($axios); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const useAdminApi = function (): AdminAPI { | export const useAdminApi = function (i18n?: Composer): AdminAPI { | ||||||
|   const requests = useRequests(); |   const requests = useRequests(i18n); | ||||||
|   return new AdminAPI(requests); |   return new AdminAPI(requests); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const useUserApi = function (): UserApi { | export const useUserApi = function (i18n?: Composer): UserApi { | ||||||
|   const requests = useRequests(); |   const requests = useRequests(i18n); | ||||||
|   return new UserApi(requests); |   return new UserApi(requests); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const usePublicApi = function (): PublicApi { | export const usePublicApi = function (i18n?: Composer): PublicApi { | ||||||
|   const requests = useRequests(); |   const requests = useRequests(i18n); | ||||||
|   return new PublicApi(requests); |   return new PublicApi(requests); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const usePublicExploreApi = function (groupSlug: string): PublicExploreApi { | export const usePublicExploreApi = function (groupSlug: string, i18n?: Composer): PublicExploreApi { | ||||||
|   const requests = useRequests(); |   const requests = useRequests(i18n); | ||||||
|   return new PublicExploreApi(requests, groupSlug); |   return new PublicExploreApi(requests, groupSlug); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import type { Composer } from "vue-i18n"; | ||||||
| import { useData, useReadOnlyStore, useStore } from "../partials/use-store-factory"; | import { useData, useReadOnlyStore, useStore } from "../partials/use-store-factory"; | ||||||
| import type { RecipeCategory } from "~/lib/api/types/recipe"; | import type { RecipeCategory } from "~/lib/api/types/recipe"; | ||||||
| import { usePublicExploreApi, useUserApi } from "~/composables/api"; | import { usePublicExploreApi, useUserApi } from "~/composables/api"; | ||||||
| @@ -14,12 +15,12 @@ export const useCategoryData = function () { | |||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const useCategoryStore = function () { | export const useCategoryStore = function (i18n?: Composer) { | ||||||
|   const api = useUserApi(); |   const api = useUserApi(i18n); | ||||||
|   return useStore<RecipeCategory>(store, loading, api.categories); |   return useStore<RecipeCategory>(store, loading, api.categories); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const usePublicCategoryStore = function (groupSlug: string) { | export const usePublicCategoryStore = function (groupSlug: string, i18n?: Composer) { | ||||||
|   const api = usePublicExploreApi(groupSlug).explore; |   const api = usePublicExploreApi(groupSlug, i18n).explore; | ||||||
|   return useReadOnlyStore<RecipeCategory>(store, publicLoading, api.categories); |   return useReadOnlyStore<RecipeCategory>(store, publicLoading, api.categories); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import type { Composer } from "vue-i18n"; | ||||||
| import { useReadOnlyStore, useStore } from "../partials/use-store-factory"; | import { useReadOnlyStore, useStore } from "../partials/use-store-factory"; | ||||||
| import type { RecipeCookBook } from "~/lib/api/types/cookbook"; | import type { RecipeCookBook } from "~/lib/api/types/cookbook"; | ||||||
| import { usePublicExploreApi, useUserApi } from "~/composables/api"; | import { usePublicExploreApi, useUserApi } from "~/composables/api"; | ||||||
| @@ -6,12 +7,12 @@ const store: Ref<RecipeCookBook[]> = ref([]); | |||||||
| const loading = ref(false); | const loading = ref(false); | ||||||
| const publicLoading = ref(false); | const publicLoading = ref(false); | ||||||
|  |  | ||||||
| export const useCookbookStore = function () { | export const useCookbookStore = function (i18n?: Composer) { | ||||||
|   const api = useUserApi(); |   const api = useUserApi(i18n); | ||||||
|   return useStore<RecipeCookBook>(store, loading, api.cookbooks); |   return useStore<RecipeCookBook>(store, loading, api.cookbooks); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const usePublicCookbookStore = function (groupSlug: string) { | export const usePublicCookbookStore = function (groupSlug: string, i18n?: Composer) { | ||||||
|   const api = usePublicExploreApi(groupSlug).explore; |   const api = usePublicExploreApi(groupSlug, i18n).explore; | ||||||
|   return useReadOnlyStore<RecipeCookBook>(store, publicLoading, api.cookbooks); |   return useReadOnlyStore<RecipeCookBook>(store, publicLoading, api.cookbooks); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import type { Composer } from "vue-i18n"; | ||||||
| import { useData, useReadOnlyStore, useStore } from "../partials/use-store-factory"; | import { useData, useReadOnlyStore, useStore } from "../partials/use-store-factory"; | ||||||
| import type { IngredientFood } from "~/lib/api/types/recipe"; | import type { IngredientFood } from "~/lib/api/types/recipe"; | ||||||
| import { usePublicExploreApi, useUserApi } from "~/composables/api"; | import { usePublicExploreApi, useUserApi } from "~/composables/api"; | ||||||
| @@ -15,12 +16,12 @@ export const useFoodData = function () { | |||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const useFoodStore = function () { | export const useFoodStore = function (i18n?: Composer) { | ||||||
|   const api = useUserApi(); |   const api = useUserApi(i18n); | ||||||
|   return useStore<IngredientFood>(store, loading, api.foods); |   return useStore<IngredientFood>(store, loading, api.foods); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const usePublicFoodStore = function (groupSlug: string) { | export const usePublicFoodStore = function (groupSlug: string, i18n?: Composer) { | ||||||
|   const api = usePublicExploreApi(groupSlug).explore; |   const api = usePublicExploreApi(groupSlug, i18n).explore; | ||||||
|   return useReadOnlyStore<IngredientFood>(store, publicLoading, api.foods); |   return useReadOnlyStore<IngredientFood>(store, publicLoading, api.foods); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import type { Composer } from "vue-i18n"; | ||||||
| import { useReadOnlyStore } from "../partials/use-store-factory"; | import { useReadOnlyStore } from "../partials/use-store-factory"; | ||||||
| import type { HouseholdSummary } from "~/lib/api/types/household"; | import type { HouseholdSummary } from "~/lib/api/types/household"; | ||||||
| import { usePublicExploreApi, useUserApi } from "~/composables/api"; | import { usePublicExploreApi, useUserApi } from "~/composables/api"; | ||||||
| @@ -6,12 +7,12 @@ const store: Ref<HouseholdSummary[]> = ref([]); | |||||||
| const loading = ref(false); | const loading = ref(false); | ||||||
| const publicLoading = ref(false); | const publicLoading = ref(false); | ||||||
|  |  | ||||||
| export const useHouseholdStore = function () { | export const useHouseholdStore = function (i18n?: Composer) { | ||||||
|   const api = useUserApi(); |   const api = useUserApi(i18n); | ||||||
|   return useReadOnlyStore<HouseholdSummary>(store, loading, api.households); |   return useReadOnlyStore<HouseholdSummary>(store, loading, api.households); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const usePublicHouseholdStore = function (groupSlug: string) { | export const usePublicHouseholdStore = function (groupSlug: string, i18n?: Composer) { | ||||||
|   const api = usePublicExploreApi(groupSlug).explore; |   const api = usePublicExploreApi(groupSlug, i18n).explore; | ||||||
|   return useReadOnlyStore<HouseholdSummary>(store, publicLoading, api.households); |   return useReadOnlyStore<HouseholdSummary>(store, publicLoading, api.households); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import type { Composer } from "vue-i18n"; | ||||||
| import { useData, useStore } from "../partials/use-store-factory"; | import { useData, useStore } from "../partials/use-store-factory"; | ||||||
| import type { MultiPurposeLabelOut } from "~/lib/api/types/labels"; | import type { MultiPurposeLabelOut } from "~/lib/api/types/labels"; | ||||||
| import { useUserApi } from "~/composables/api"; | import { useUserApi } from "~/composables/api"; | ||||||
| @@ -14,7 +15,7 @@ export const useLabelData = function () { | |||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const useLabelStore = function () { | export const useLabelStore = function (i18n?: Composer) { | ||||||
|   const api = useUserApi(); |   const api = useUserApi(i18n); | ||||||
|   return useStore<MultiPurposeLabelOut>(store, loading, api.multiPurposeLabels); |   return useStore<MultiPurposeLabelOut>(store, loading, api.multiPurposeLabels); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import type { Composer } from "vue-i18n"; | ||||||
| import { useData, useReadOnlyStore, useStore } from "../partials/use-store-factory"; | import { useData, useReadOnlyStore, useStore } from "../partials/use-store-factory"; | ||||||
| import type { RecipeTag } from "~/lib/api/types/recipe"; | import type { RecipeTag } from "~/lib/api/types/recipe"; | ||||||
| import { usePublicExploreApi, useUserApi } from "~/composables/api"; | import { usePublicExploreApi, useUserApi } from "~/composables/api"; | ||||||
| @@ -14,12 +15,12 @@ export const useTagData = function () { | |||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const useTagStore = function () { | export const useTagStore = function (i18n?: Composer) { | ||||||
|   const api = useUserApi(); |   const api = useUserApi(i18n); | ||||||
|   return useStore<RecipeTag>(store, loading, api.tags); |   return useStore<RecipeTag>(store, loading, api.tags); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const usePublicTagStore = function (groupSlug: string) { | export const usePublicTagStore = function (groupSlug: string, i18n?: Composer) { | ||||||
|   const api = usePublicExploreApi(groupSlug).explore; |   const api = usePublicExploreApi(groupSlug, i18n).explore; | ||||||
|   return useReadOnlyStore<RecipeTag>(store, publicLoading, api.tags); |   return useReadOnlyStore<RecipeTag>(store, publicLoading, api.tags); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import type { Composer } from "vue-i18n"; | ||||||
| import { useData, useReadOnlyStore, useStore } from "../partials/use-store-factory"; | import { useData, useReadOnlyStore, useStore } from "../partials/use-store-factory"; | ||||||
| import type { RecipeTool } from "~/lib/api/types/recipe"; | import type { RecipeTool } from "~/lib/api/types/recipe"; | ||||||
| import { usePublicExploreApi, useUserApi } from "~/composables/api"; | import { usePublicExploreApi, useUserApi } from "~/composables/api"; | ||||||
| @@ -20,12 +21,12 @@ export const useToolData = function () { | |||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const useToolStore = function () { | export const useToolStore = function (i18n?: Composer) { | ||||||
|   const api = useUserApi(); |   const api = useUserApi(i18n); | ||||||
|   return useStore<RecipeTool>(store, loading, api.tools); |   return useStore<RecipeTool>(store, loading, api.tools); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const usePublicToolStore = function (groupSlug: string) { | export const usePublicToolStore = function (groupSlug: string, i18n?: Composer) { | ||||||
|   const api = usePublicExploreApi(groupSlug).explore; |   const api = usePublicExploreApi(groupSlug, i18n).explore; | ||||||
|   return useReadOnlyStore<RecipeTool>(store, publicLoading, api.tools); |   return useReadOnlyStore<RecipeTool>(store, publicLoading, api.tools); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import type { Composer } from "vue-i18n"; | ||||||
| import { useData, useStore } from "../partials/use-store-factory"; | import { useData, useStore } from "../partials/use-store-factory"; | ||||||
| import type { IngredientUnit } from "~/lib/api/types/recipe"; | import type { IngredientUnit } from "~/lib/api/types/recipe"; | ||||||
| import { useUserApi } from "~/composables/api"; | import { useUserApi } from "~/composables/api"; | ||||||
| @@ -15,7 +16,7 @@ export const useUnitData = function () { | |||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const useUnitStore = function () { | export const useUnitStore = function (i18n?: Composer) { | ||||||
|   const api = useUserApi(); |   const api = useUserApi(i18n); | ||||||
|   return useStore<IngredientUnit>(store, loading, api.units); |   return useStore<IngredientUnit>(store, loading, api.units); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import type { Composer } from "vue-i18n"; | ||||||
| import { useReadOnlyStore } from "../partials/use-store-factory"; | import { useReadOnlyStore } from "../partials/use-store-factory"; | ||||||
| import { useRequests } from "../api/api-client"; | import { useRequests } from "../api/api-client"; | ||||||
| import type { UserSummary } from "~/lib/api/types/user"; | import type { UserSummary } from "~/lib/api/types/user"; | ||||||
| @@ -11,8 +12,8 @@ class GroupUserAPIReadOnly extends BaseCRUDAPIReadOnly<UserSummary> { | |||||||
|   itemRoute = (idOrUsername: string | number) => `/groups/members/${idOrUsername}`; |   itemRoute = (idOrUsername: string | number) => `/groups/members/${idOrUsername}`; | ||||||
| } | } | ||||||
|  |  | ||||||
| export const useUserStore = function () { | export const useUserStore = function (i18n?: Composer) { | ||||||
|   const requests = useRequests(); |   const requests = useRequests(i18n); | ||||||
|   const api = new GroupUserAPIReadOnly(requests); |   const api = new GroupUserAPIReadOnly(requests); | ||||||
|  |  | ||||||
|   return useReadOnlyStore<UserSummary>(store, loading, api, { orderBy: "full_name" }); |   return useReadOnlyStore<UserSummary>(store, loading, api, { orderBy: "full_name" }); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user