mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-04 21:15:22 +02:00
feat: Add Households to Mealie (#3970)
This commit is contained in:
parent
0c29cef17d
commit
eb170cc7e5
315 changed files with 6975 additions and 3577 deletions
|
@ -4,7 +4,7 @@ import { BaseCRUDAPI, BaseCRUDAPIReadOnly } from "~/lib/api/base/base-clients";
|
|||
import { QueryValue } from "~/lib/api/base/route";
|
||||
|
||||
type BoundT = {
|
||||
id?: string | number;
|
||||
id?: string | number | null;
|
||||
};
|
||||
|
||||
interface PublicStoreActions<T extends BoundT> {
|
||||
|
|
|
@ -160,6 +160,9 @@ export function usePageUser(): { user: UserOut } {
|
|||
group: "",
|
||||
groupId: "",
|
||||
groupSlug: "",
|
||||
household: "",
|
||||
householdId: "",
|
||||
householdSlug: "",
|
||||
cacheKey: "",
|
||||
email: "",
|
||||
},
|
||||
|
|
|
@ -46,7 +46,7 @@ export function useParsedIngredientText(ingredient: RecipeIngredient, disableAmo
|
|||
}
|
||||
|
||||
const { quantity, food, unit, note } = ingredient;
|
||||
const usePluralUnit = quantity !== undefined && (quantity * scale > 1 || quantity * scale === 0);
|
||||
const usePluralUnit = quantity !== undefined && ((quantity || 0) * scale > 1 || (quantity || 0) * scale === 0);
|
||||
const usePluralFood = (!quantity) || quantity * scale > 1
|
||||
|
||||
let returnQty = "";
|
||||
|
@ -69,8 +69,8 @@ export function useParsedIngredientText(ingredient: RecipeIngredient, disableAmo
|
|||
}
|
||||
}
|
||||
|
||||
const unitName = useUnitName(unit, usePluralUnit);
|
||||
const foodName = useFoodName(food, usePluralFood);
|
||||
const unitName = useUnitName(unit || undefined, usePluralUnit);
|
||||
const foodName = useFoodName(food || undefined, usePluralFood);
|
||||
|
||||
return {
|
||||
quantity: returnQty ? sanitizeIngredientHTML(returnQty) : undefined,
|
||||
|
|
|
@ -2,7 +2,7 @@ import { reactive, ref, Ref } from "@nuxtjs/composition-api";
|
|||
import { usePublicStoreActions, useStoreActions } from "../partials/use-actions-factory";
|
||||
import { usePublicExploreApi } from "../api/api-client";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { RecipeTag } from "~/lib/api/types/admin";
|
||||
import { RecipeTag } from "~/lib/api/types/recipe";
|
||||
|
||||
const items: Ref<RecipeTag[]> = ref([]);
|
||||
const publicStoreLoading = ref(false);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useAsync, ref, Ref, useContext } from "@nuxtjs/composition-api";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { usePublicExploreApi } from "./api/api-client";
|
||||
import { useHouseholdSelf } from "./use-households";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { ReadCookBook, UpdateCookBook } from "~/lib/api/types/cookbook";
|
||||
|
||||
|
@ -67,6 +68,7 @@ export const usePublicCookbooks = function (groupSlug: string) {
|
|||
|
||||
export const useCookbooks = function () {
|
||||
const api = useUserApi();
|
||||
const { household } = useHouseholdSelf();
|
||||
const loading = ref(false);
|
||||
|
||||
const { i18n } = useContext();
|
||||
|
@ -100,7 +102,7 @@ export const useCookbooks = function () {
|
|||
async createOne() {
|
||||
loading.value = true;
|
||||
const { data } = await api.cookbooks.createOne({
|
||||
name: i18n.t("cookbook.cookbook-with-name", [String((cookbookStore?.value?.length ?? 0) + 1)]) as string,
|
||||
name: i18n.t("cookbook.household-cookbook-name", [household.value?.name || "", String((cookbookStore?.value?.length ?? 0) + 1)]) as string,
|
||||
});
|
||||
if (data && cookbookStore?.value) {
|
||||
cookbookStore.value.push(data);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { computed, reactive, ref } from "@nuxtjs/composition-api";
|
||||
import { useStoreActions } from "./partials/use-actions-factory";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { GroupRecipeActionOut, RecipeActionType } from "~/lib/api/types/group";
|
||||
import { GroupRecipeActionOut, GroupRecipeActionType } from "~/lib/api/types/household";
|
||||
import { Recipe } from "~/lib/api/types/recipe";
|
||||
|
||||
const groupRecipeActions = ref<GroupRecipeActionOut[] | null>(null);
|
||||
|
@ -10,7 +10,7 @@ const loading = ref(false);
|
|||
export function useGroupRecipeActionData() {
|
||||
const data = reactive({
|
||||
id: "",
|
||||
actionType: "link" as RecipeActionType,
|
||||
actionType: "link" as GroupRecipeActionType,
|
||||
title: "",
|
||||
url: "",
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { useAsync, ref } from "@nuxtjs/composition-api";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { ReadWebhook } from "~/lib/api/types/group";
|
||||
import { ReadWebhook } from "~/lib/api/types/household";
|
||||
|
||||
export const useGroupWebhooks = function () {
|
||||
const api = useUserApi();
|
||||
|
|
|
@ -51,7 +51,7 @@ export const useGroups = function () {
|
|||
loading.value = true;
|
||||
const asyncKey = String(Date.now());
|
||||
const groups = useAsync(async () => {
|
||||
const { data } = await api.groups.getAll();
|
||||
const { data } = await api.groups.getAll(1, -1, {orderBy: "name", orderDirection: "asc"});;
|
||||
|
||||
if (data) {
|
||||
return data.items;
|
||||
|
@ -66,7 +66,7 @@ export const useGroups = function () {
|
|||
|
||||
async function refreshAllGroups() {
|
||||
loading.value = true;
|
||||
const { data } = await api.groups.getAll();
|
||||
const { data } = await api.groups.getAll(1, -1, {orderBy: "name", orderDirection: "asc"});;
|
||||
|
||||
if (data) {
|
||||
groups.value = data.items;
|
||||
|
|
117
frontend/composables/use-households.ts
Normal file
117
frontend/composables/use-households.ts
Normal file
|
@ -0,0 +1,117 @@
|
|||
import { computed, ref, Ref, useAsync } from "@nuxtjs/composition-api";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { HouseholdCreate, HouseholdInDB } from "~/lib/api/types/household";
|
||||
|
||||
const householdSelfRef = ref<HouseholdInDB | null>(null);
|
||||
const loading = ref(false);
|
||||
|
||||
export const useHouseholdSelf = function () {
|
||||
const api = useUserApi();
|
||||
|
||||
async function refreshHouseholdSelf() {
|
||||
loading.value = true;
|
||||
const { data } = await api.households.getCurrentUserHousehold();
|
||||
householdSelfRef.value = data;
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
const actions = {
|
||||
get() {
|
||||
if (!(householdSelfRef.value || loading.value)) {
|
||||
refreshHouseholdSelf();
|
||||
}
|
||||
|
||||
return householdSelfRef;
|
||||
},
|
||||
async updatePreferences() {
|
||||
if (!householdSelfRef.value) {
|
||||
await refreshHouseholdSelf();
|
||||
}
|
||||
if (!householdSelfRef.value?.preferences) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { data } = await api.households.setPreferences(householdSelfRef.value.preferences);
|
||||
|
||||
if (data) {
|
||||
householdSelfRef.value.preferences = data;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const household = actions.get();
|
||||
|
||||
return { actions, household };
|
||||
};
|
||||
|
||||
export const useHouseholds = function () {
|
||||
const api = useUserApi();
|
||||
const loading = ref(false);
|
||||
|
||||
function getAllHouseholds() {
|
||||
loading.value = true;
|
||||
const asyncKey = String(Date.now());
|
||||
const households = useAsync(async () => {
|
||||
const { data } = await api.households.getAll(1, -1, {orderBy: "name, group.name", orderDirection: "asc"});
|
||||
|
||||
if (data) {
|
||||
return data.items;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}, asyncKey);
|
||||
|
||||
loading.value = false;
|
||||
return households;
|
||||
}
|
||||
|
||||
async function refreshAllHouseholds() {
|
||||
loading.value = true;
|
||||
const { data } = await api.households.getAll(1, -1, {orderBy: "name, group.name", orderDirection: "asc"});;
|
||||
|
||||
if (data) {
|
||||
households.value = data.items;
|
||||
} else {
|
||||
households.value = null;
|
||||
}
|
||||
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
async function deleteHousehold(id: string | number) {
|
||||
loading.value = true;
|
||||
const { data } = await api.households.deleteOne(id);
|
||||
loading.value = false;
|
||||
refreshAllHouseholds();
|
||||
return data;
|
||||
}
|
||||
|
||||
async function createHousehold(payload: HouseholdCreate) {
|
||||
loading.value = true;
|
||||
const { data } = await api.households.createOne(payload);
|
||||
|
||||
if (data && households.value) {
|
||||
households.value.push(data);
|
||||
}
|
||||
}
|
||||
|
||||
const households = getAllHouseholds();
|
||||
function useHouseholdsInGroup(groupIdRef: Ref<string>) {
|
||||
return computed(
|
||||
() => {
|
||||
return (households.value && groupIdRef.value)
|
||||
? households.value.filter((h) => h.groupId === groupIdRef.value)
|
||||
: [];
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
households,
|
||||
useHouseholdsInGroup,
|
||||
getAllHouseholds,
|
||||
refreshAllHouseholds,
|
||||
deleteHousehold,
|
||||
createHousehold,
|
||||
};
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
import { computed, reactive, watch } from "@nuxtjs/composition-api";
|
||||
import { useLocalStorage } from "@vueuse/core";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { ShoppingListItemOut, ShoppingListOut } from "~/lib/api/types/group";
|
||||
import { ShoppingListItemOut, ShoppingListOut } from "~/lib/api/types/household";
|
||||
import { RequestResponse } from "~/lib/api/types/non-generated";
|
||||
|
||||
const localStorageKey = "shopping-list-queue";
|
||||
|
@ -144,7 +144,7 @@ export function useShoppingListItemActions(shoppingListId: string) {
|
|||
|
||||
function checkUpdateState(list: ShoppingListOut) {
|
||||
const cutoffDate = new Date(queue.lastUpdate + queueTimeout).toISOString();
|
||||
if (list.updateAt && list.updateAt > cutoffDate) {
|
||||
if (list.updatedAt && list.updatedAt > cutoffDate) {
|
||||
// If the queue is too far behind the shopping list to reliably do updates, we clear the queue
|
||||
console.log("Out of sync with server; clearing queue");
|
||||
clearQueueItems("all");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue