diff --git a/docs/docs/overrides/api.html b/docs/docs/overrides/api.html
index 0dc543851..526c3d3dc 100644
--- a/docs/docs/overrides/api.html
+++ b/docs/docs/overrides/api.html
@@ -14,7 +14,7 @@
diff --git a/frontend/components/Layout/DefaultLayout.vue b/frontend/components/Layout/DefaultLayout.vue
index 86e74c2a1..7dce34bf0 100644
--- a/frontend/components/Layout/DefaultLayout.vue
+++ b/frontend/components/Layout/DefaultLayout.vue
@@ -100,9 +100,7 @@ import type { SideBarLink } from "~/types/application-types";
import { useAppInfo } from "~/composables/api";
import { useCookbookPreferences } from "~/composables/use-users/preferences";
import { useCookbookStore, usePublicCookbookStore } from "~/composables/store/use-cookbook-store";
-import { useHouseholdStore, usePublicHouseholdStore } from "~/composables/store/use-household-store";
import type { ReadCookBook } from "~/lib/api/types/cookbook";
-import type { HouseholdSummary } from "~/lib/api/types/household";
export default defineNuxtComponent({
setup() {
@@ -116,12 +114,8 @@ export default defineNuxtComponent({
const groupSlug = computed(() => route.params.groupSlug as string || $auth.user.value?.groupSlug || "");
const cookbookPreferences = useCookbookPreferences();
-
const ownCookbookStore = useCookbookStore(i18n);
- const ownHouseholdStore = useHouseholdStore(i18n);
-
const publicCookbookStoreCache = ref>>({});
- const publicHouseholdStoreCache = ref>>({});
function getPublicCookbookStore(slug: string) {
if (!publicCookbookStoreCache.value[slug]) {
@@ -130,13 +124,6 @@ export default defineNuxtComponent({
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;
@@ -148,24 +135,6 @@ export default defineNuxtComponent({
return [];
});
- 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(() => {
- return households.value.reduce((acc, household) => {
- acc[household.id] = household;
- return acc;
- }, {} as { [key: string]: HouseholdSummary });
- });
-
const appInfo = useAppInfo();
const showImageImport = computed(() => appInfo.value?.enableOpenaiImageServices);
@@ -197,11 +166,8 @@ export default defineNuxtComponent({
const ownLinks: SideBarLink[] = [];
const links: SideBarLink[] = [];
const cookbooksByHousehold = sortedCookbooks.reduce((acc, cookbook) => {
- const householdName = householdsById.value[cookbook.householdId]?.name || "";
- if (!acc[householdName]) {
- acc[householdName] = [];
- }
- acc[householdName].push(cookbook);
+ const householdName = cookbook.household?.name || "";
+ (acc[householdName] ||= []).push(cookbook);
return acc;
}, {} as Record);
diff --git a/frontend/lib/api/types/cookbook.ts b/frontend/lib/api/types/cookbook.ts
index 753b11c6a..7104b774c 100644
--- a/frontend/lib/api/types/cookbook.ts
+++ b/frontend/lib/api/types/cookbook.ts
@@ -9,6 +9,10 @@ export type LogicalOperator = "AND" | "OR";
export type RelationalKeyword = "IS" | "IS NOT" | "IN" | "NOT IN" | "CONTAINS ALL" | "LIKE" | "NOT LIKE";
export type RelationalOperator = "=" | "<>" | ">" | "<" | ">=" | "<=";
+export interface CookbookHousehold {
+ id: string;
+ name: string;
+}
export interface CreateCookBook {
name: string;
description?: string;
@@ -28,6 +32,7 @@ export interface ReadCookBook {
householdId: string;
id: string;
queryFilter?: QueryFilterJSON;
+ household?: CookbookHousehold | null;
}
export interface QueryFilterJSON {
parts?: QueryFilterJSONPart[];
diff --git a/frontend/lib/api/types/openai.ts b/frontend/lib/api/types/openai.ts
index be28b87be..10b506402 100644
--- a/frontend/lib/api/types/openai.ts
+++ b/frontend/lib/api/types/openai.ts
@@ -6,8 +6,6 @@
*/
export interface OpenAIIngredient {
- input: string;
- confidence?: number | null;
quantity?: number | null;
unit?: string | null;
food?: string | null;
diff --git a/frontend/types/components.d.ts b/frontend/types/components.d.ts
index 25d97d654..bcee9b06c 100644
--- a/frontend/types/components.d.ts
+++ b/frontend/types/components.d.ts
@@ -3,6 +3,7 @@ import type AdvancedOnly from "@/components/global/AdvancedOnly.vue";
import type AppButtonCopy from "@/components/global/AppButtonCopy.vue";
import type AppButtonUpload from "@/components/global/AppButtonUpload.vue";
import type AppLoader from "@/components/global/AppLoader.vue";
+import type AppLogo from "@/components/global/AppLogo.vue";
import type AppToolbar from "@/components/global/AppToolbar.vue";
import type AutoForm from "@/components/global/AutoForm.vue";
import type BannerExperimental from "@/components/global/BannerExperimental.vue";
@@ -43,6 +44,7 @@ declare module "vue" {
AppButtonCopy: typeof AppButtonCopy;
AppButtonUpload: typeof AppButtonUpload;
AppLoader: typeof AppLoader;
+ AppLogo: typeof AppLogo;
AppToolbar: typeof AppToolbar;
AutoForm: typeof AutoForm;
BannerExperimental: typeof BannerExperimental;
@@ -79,4 +81,4 @@ declare module "vue" {
}
}
-export { };
+export {};
diff --git a/mealie/schema/cookbook/__init__.py b/mealie/schema/cookbook/__init__.py
index 8a358571a..65df16532 100644
--- a/mealie/schema/cookbook/__init__.py
+++ b/mealie/schema/cookbook/__init__.py
@@ -1,8 +1,9 @@
# This file is auto-generated by gen_schema_exports.py
-from .cookbook import CookBookPagination, CreateCookBook, ReadCookBook, SaveCookBook, UpdateCookBook
+from .cookbook import CookbookHousehold, CookBookPagination, CreateCookBook, ReadCookBook, SaveCookBook, UpdateCookBook
__all__ = [
"CookBookPagination",
+ "CookbookHousehold",
"CreateCookBook",
"ReadCookBook",
"SaveCookBook",
diff --git a/mealie/schema/cookbook/cookbook.py b/mealie/schema/cookbook/cookbook.py
index 66ba3b668..8d7761e3c 100644
--- a/mealie/schema/cookbook/cookbook.py
+++ b/mealie/schema/cookbook/cookbook.py
@@ -3,8 +3,11 @@ from typing import Annotated
import sqlalchemy as sa
from pydantic import UUID4, ConfigDict, Field, ValidationInfo, field_validator
from slugify import slugify
+from sqlalchemy.orm import joinedload
+from sqlalchemy.orm.interfaces import LoaderOption
from mealie.core.root_logger import get_logger
+from mealie.db.models.household.cookbook import CookBook
from mealie.db.models.recipe import RecipeModel
from mealie.schema._mealie import MealieModel
from mealie.schema.response.pagination import PaginationBase
@@ -13,6 +16,12 @@ from mealie.schema.response.query_filter import QueryFilterBuilder, QueryFilterJ
logger = get_logger()
+class CookbookHousehold(MealieModel):
+ id: UUID4
+ name: str
+ model_config = ConfigDict(from_attributes=True)
+
+
class CreateCookBook(MealieModel):
name: str
description: str = ""
@@ -62,6 +71,7 @@ class UpdateCookBook(SaveCookBook):
class ReadCookBook(UpdateCookBook):
query_filter: Annotated[QueryFilterJSON, Field(validate_default=True)] = None # type: ignore
+ household: CookbookHousehold | None = None
model_config = ConfigDict(from_attributes=True)
@@ -80,6 +90,10 @@ class ReadCookBook(UpdateCookBook):
logger.exception(f"Invalid query filter string: {query_filter_string}")
return QueryFilterJSON()
+ @classmethod
+ def loader_options(cls) -> list[LoaderOption]:
+ return [joinedload(CookBook.household)]
+
class CookBookPagination(PaginationBase):
items: list[ReadCookBook]
diff --git a/tests/integration_tests/public_explorer_tests/test_public_cookbooks.py b/tests/integration_tests/public_explorer_tests/test_public_cookbooks.py
index c3902a6d4..7fba33316 100644
--- a/tests/integration_tests/public_explorer_tests/test_public_cookbooks.py
+++ b/tests/integration_tests/public_explorer_tests/test_public_cookbooks.py
@@ -139,6 +139,7 @@ def test_get_one_cookbook(
assert response.status_code == 200
cookbook_data = response.json()
assert cookbook_data["id"] == str(cookbook.id)
+ assert cookbook_data["household"]["name"] == household.name
def test_get_cookbooks_with_recipes(api_client: TestClient, unique_user: TestUser, h2_user: TestUser):
diff --git a/tests/integration_tests/user_household_tests/test_group_cookbooks.py b/tests/integration_tests/user_household_tests/test_group_cookbooks.py
index 90dbc2fa8..5807d0b1e 100644
--- a/tests/integration_tests/user_household_tests/test_group_cookbooks.py
+++ b/tests/integration_tests/user_household_tests/test_group_cookbooks.py
@@ -89,6 +89,9 @@ def test_read_cookbook(
use_other_household: bool,
):
sample = random.choice(cookbooks)
+ household = unique_user.repos.households.get_one(sample.data["household_id"])
+ assert household
+
if use_other_household:
headers = h2_user.token
else:
@@ -104,6 +107,8 @@ def test_read_cookbook(
assert page_data["slug"] == sample.slug
assert page_data["name"] == sample.name
assert page_data["groupId"] == str(unique_user.group_id)
+ assert page_data["householdId"] == str(unique_user.household_id)
+ assert page_data["household"]["name"] == household.name
def test_update_cookbook(api_client: TestClient, unique_user: TestUser, cookbooks: list[TestCookbook]):