mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-02 20:15:24 +02:00
Refactor/composables-folder (#787)
* move api clients and rename * organize recipes composables * rewrite useRecipeContext * refactor(frontend): ♻️ abstract common ingredient functionality. * feat(frontend): ✨ add scale, and back to recipe button + hide ingredients if none * update regex to mach 11. instead of just 1. * minor UX improvements Co-authored-by: Hayden K <hay-kot@pm.me>
This commit is contained in:
parent
095d3bda3f
commit
788e176b16
68 changed files with 330 additions and 245 deletions
|
@ -59,7 +59,7 @@ export const useAdminApi = function (): AdminAPI {
|
|||
return new AdminAPI(requests);
|
||||
};
|
||||
|
||||
export const useApiSingleton = function (): Api {
|
||||
export const useUserApi = function (): Api {
|
||||
const { $axios } = useContext();
|
||||
const requests = getRequests($axios);
|
||||
|
|
@ -1 +1,2 @@
|
|||
export { useStaticRoutes } from "./static-routes";
|
||||
export { useAdminApi, useUserApi } from "./api-client";
|
||||
|
|
7
frontend/composables/recipes/index.ts
Normal file
7
frontend/composables/recipes/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
export { useFraction } from "./use-fraction";
|
||||
export { useRecipe } from "./use-recipe";
|
||||
export { useFoods } from "./use-recipe-foods";
|
||||
export { useUnits } from "./use-recipe-units";
|
||||
export { useRecipes, recentRecipes, allRecipes, useLazyRecipes, useSorter } from "./use-recipes";
|
||||
export { useTags, useCategories, allCategories, allTags } from "./use-tags-categories";
|
||||
export { parseIngredientText } from "./use-recipe-ingredients";
|
|
@ -1,12 +1,12 @@
|
|||
import { useAsync, ref, reactive, Ref } from "@nuxtjs/composition-api";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useApiSingleton } from "~/composables/use-api";
|
||||
import { useAsyncKey } from "../use-utils";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { Food } from "~/api/class-interfaces/recipe-foods";
|
||||
|
||||
let foodStore: Ref<Food[] | null> | null = null;
|
||||
|
||||
export const useFoods = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
const loading = ref(false);
|
||||
const deleteTargetId = ref(0);
|
||||
const validForm = ref(true);
|
28
frontend/composables/recipes/use-recipe-ingredients.ts
Normal file
28
frontend/composables/recipes/use-recipe-ingredients.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { useFraction } from "./use-fraction";
|
||||
import { RecipeIngredient } from "~/types/api-types/recipe";
|
||||
|
||||
const { frac } = useFraction();
|
||||
|
||||
export function parseIngredientText(ingredient: RecipeIngredient, disableAmount: boolean, scale: number = 1): string {
|
||||
if (disableAmount) {
|
||||
return ingredient.note;
|
||||
}
|
||||
|
||||
const { quantity, food, unit, note } = ingredient;
|
||||
|
||||
let returnQty = "";
|
||||
if (unit?.fraction) {
|
||||
const fraction = frac(quantity * scale, 10, true);
|
||||
if (fraction[0] !== undefined && fraction[0] > 0) {
|
||||
returnQty += fraction[0];
|
||||
}
|
||||
|
||||
if (fraction[1] > 0) {
|
||||
returnQty += ` <sup>${fraction[1]}</sup>⁄<sub>${fraction[2]}</sub>`;
|
||||
}
|
||||
} else {
|
||||
returnQty = (quantity * scale).toString();
|
||||
}
|
||||
|
||||
return `${returnQty} ${unit?.name || " "} ${food?.name || " "} ${note}`.replace(/ {2,}/g, " ");
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
import { useAsync, ref, reactive, Ref } from "@nuxtjs/composition-api";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useApiSingleton } from "~/composables/use-api";
|
||||
import { useAsyncKey } from "../use-utils";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { Unit } from "~/api/class-interfaces/recipe-units";
|
||||
|
||||
let unitStore: Ref<Unit[] | null> | null = null;
|
||||
|
||||
export const useUnits = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
const loading = ref(false);
|
||||
const deleteTargetId = ref(0);
|
||||
const validForm = ref(true);
|
47
frontend/composables/recipes/use-recipe.ts
Normal file
47
frontend/composables/recipes/use-recipe.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
import { ref, onMounted } from "@nuxtjs/composition-api";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { Recipe } from "~/types/api-types/recipe";
|
||||
|
||||
export const useRecipe = function (slug: string, eager: boolean = true) {
|
||||
const api = useUserApi();
|
||||
const loading = ref(false);
|
||||
|
||||
const recipe = ref<Recipe | null>(null);
|
||||
|
||||
async function fetchRecipe() {
|
||||
loading.value = true;
|
||||
const { data } = await api.recipes.getOne(slug);
|
||||
loading.value = false;
|
||||
if (data) {
|
||||
recipe.value = data;
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteRecipe() {
|
||||
loading.value = true;
|
||||
const { data } = await api.recipes.deleteOne(slug);
|
||||
loading.value = false;
|
||||
return data;
|
||||
}
|
||||
|
||||
async function updateRecipe(recipe: Recipe) {
|
||||
loading.value = true;
|
||||
const { data } = await api.recipes.updateOne(slug, recipe);
|
||||
loading.value = false;
|
||||
return data;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (eager) {
|
||||
fetchRecipe();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
recipe,
|
||||
loading,
|
||||
fetchRecipe,
|
||||
deleteRecipe,
|
||||
updateRecipe,
|
||||
};
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
import { useAsync, ref } from "@nuxtjs/composition-api";
|
||||
import { set } from "@vueuse/core";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useApiSingleton } from "~/composables/use-api";
|
||||
import { useAsyncKey } from "../use-utils";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { Recipe } from "~/types/api-types/recipe";
|
||||
|
||||
export const allRecipes = ref<Recipe[] | null>([]);
|
||||
|
@ -58,7 +58,7 @@ export const useSorter = () => {
|
|||
};
|
||||
|
||||
export const useLazyRecipes = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
|
||||
const recipes = ref<Recipe[] | null>([]);
|
||||
|
||||
|
@ -78,7 +78,7 @@ export const useLazyRecipes = function () {
|
|||
};
|
||||
|
||||
export const useRecipes = (all = false, fetchRecipes = true) => {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
|
||||
// recipes is non-reactive!!
|
||||
const { recipes, start, end } = (() => {
|
|
@ -1,6 +1,6 @@
|
|||
import { Ref, ref, useAsync } from "@nuxtjs/composition-api";
|
||||
import { useApiSingleton } from "./use-api";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useUserApi } from "../api";
|
||||
import { useAsyncKey } from "../use-utils";
|
||||
import { CategoriesAPI, Category } from "~/api/class-interfaces/categories";
|
||||
import { Tag, TagsAPI } from "~/api/class-interfaces/tags";
|
||||
|
||||
|
@ -45,14 +45,14 @@ function baseTagsCategories(reference: Ref<Category[] | null> | Ref<Tag[] | null
|
|||
}
|
||||
|
||||
export const useTags = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
return {
|
||||
allTags,
|
||||
...baseTagsCategories(allTags, api.tags),
|
||||
};
|
||||
};
|
||||
export const useCategories = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
return {
|
||||
allCategories,
|
||||
...baseTagsCategories(allCategories, api.categories),
|
|
@ -2,7 +2,7 @@ import { useAsync, ref, reactive } from "@nuxtjs/composition-api";
|
|||
import { set } from "@vueuse/core";
|
||||
import { toastLoading, loader } from "./use-toast";
|
||||
import { AllBackups, ImportBackup } from "~/api/class-interfaces/backups";
|
||||
import { useApiSingleton } from "~/composables/use-api";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
|
||||
const backups = ref<AllBackups>({
|
||||
imports: [],
|
||||
|
@ -32,7 +32,7 @@ function optionsFactory() {
|
|||
}
|
||||
|
||||
export const useBackups = function (fetch = true) {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
|
||||
const backupOptions = reactive(optionsFactory());
|
||||
const deleteTarget = ref("");
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { useAsync, ref, reactive, Ref } from "@nuxtjs/composition-api";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useApiSingleton } from "~/composables/use-api";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { CookBook } from "~/api/class-interfaces/group-cookbooks";
|
||||
|
||||
let cookbookStore: Ref<CookBook[] | null> | null = null;
|
||||
|
||||
export const useCookbook = function () {
|
||||
function getOne(id: string | number) {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
|
||||
const units = useAsync(async () => {
|
||||
const { data } = await api.cookbooks.getOne(id);
|
||||
|
@ -22,7 +22,7 @@ export const useCookbook = function () {
|
|||
};
|
||||
|
||||
export const useCookbooks = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
const loading = ref(false);
|
||||
const deleteTargetId = ref(0);
|
||||
const validForm = ref(true);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { useAsync, ref } from "@nuxtjs/composition-api";
|
||||
import { addDays, subDays, format } from "date-fns";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useApiSingleton } from "~/composables/use-api";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { CreateMealPlan, UpdateMealPlan } from "~/api/class-interfaces/group-mealplan";
|
||||
|
||||
export const useMealplans = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
const loading = ref(false);
|
||||
const validForm = ref(true);
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { useAsync, ref } from "@nuxtjs/composition-api";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useApiSingleton } from "~/composables/use-api";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { GroupWebhook } from "~/api/class-interfaces/group-webhooks";
|
||||
|
||||
export const useGroupWebhooks = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
const loading = ref(false);
|
||||
const validForm = ref(true);
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { useAsync, ref } from "@nuxtjs/composition-api";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useApiSingleton } from "~/composables/use-api";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { CreateGroup } from "~/api/class-interfaces/groups";
|
||||
|
||||
export const useGroupSelf = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
|
||||
const actions = {
|
||||
get() {
|
||||
|
@ -35,7 +35,7 @@ export const useGroupSelf = function () {
|
|||
};
|
||||
|
||||
export const useGroupCategories = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
|
||||
const actions = {
|
||||
getAll() {
|
||||
|
@ -61,7 +61,7 @@ export const useGroupCategories = function () {
|
|||
};
|
||||
|
||||
export const useGroups = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
const loading = ref(false);
|
||||
|
||||
function getAllGroups() {
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import { useAsync, ref } from "@nuxtjs/composition-api";
|
||||
import { CreateEventNotification } from "@/api/class-interfaces/event-notifications";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useApiSingleton } from "~/composables/use-api";
|
||||
import { CreateEventNotification } from "@/api/class-interfaces/event-notifications";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
|
||||
const notificationTypes = ["General", "Discord", "Gotify", "Pushover", "Home Assistant"];
|
||||
|
||||
|
||||
export const useNotifications = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
const loading = ref(false);
|
||||
|
||||
const createNotificationData = ref<CreateEventNotification>({
|
||||
|
@ -23,7 +22,7 @@ export const useNotifications = function () {
|
|||
notificationUrl: "",
|
||||
});
|
||||
|
||||
const deleteTarget = ref(0)
|
||||
const deleteTarget = ref(0);
|
||||
|
||||
function getNotifications() {
|
||||
loading.value = true;
|
||||
|
@ -63,13 +62,13 @@ export const useNotifications = function () {
|
|||
}
|
||||
|
||||
async function testById(id: number) {
|
||||
const {data} = await api.notifications.testNotification(id, null)
|
||||
console.log(data)
|
||||
const { data } = await api.notifications.testNotification(id, null);
|
||||
console.log(data);
|
||||
}
|
||||
|
||||
async function testByUrl(testUrl: string) {
|
||||
const {data} = await api.notifications.testNotification(null, testUrl)
|
||||
console.log(data)
|
||||
const { data } = await api.notifications.testNotification(null, testUrl);
|
||||
console.log(data);
|
||||
}
|
||||
|
||||
const notifications = getNotifications();
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
import { useAsync, ref } from "@nuxtjs/composition-api";
|
||||
import { useApiSingleton } from "~/composables/use-api";
|
||||
import { Recipe } from "~/types/api-types/recipe";
|
||||
|
||||
export const useRecipeContext = function () {
|
||||
const api = useApiSingleton();
|
||||
const loading = ref(false);
|
||||
|
||||
function getBySlug(slug: string) {
|
||||
loading.value = true;
|
||||
const recipe = useAsync(async () => {
|
||||
const { data } = await api.recipes.getOne(slug);
|
||||
return data;
|
||||
}, slug);
|
||||
|
||||
loading.value = false;
|
||||
|
||||
return recipe;
|
||||
}
|
||||
|
||||
async function fetchRecipe(slug: string) {
|
||||
loading.value = true;
|
||||
const { data } = await api.recipes.getOne(slug);
|
||||
loading.value = false;
|
||||
return data;
|
||||
}
|
||||
|
||||
async function deleteRecipe(slug: string) {
|
||||
loading.value = true;
|
||||
const { data } = await api.recipes.deleteOne(slug);
|
||||
loading.value = false;
|
||||
return data;
|
||||
}
|
||||
|
||||
async function updateRecipe(slug: string, recipe: Recipe) {
|
||||
loading.value = true;
|
||||
const { data } = await api.recipes.updateOne(slug, recipe);
|
||||
loading.value = false;
|
||||
return data;
|
||||
}
|
||||
|
||||
return { loading, getBySlug, deleteRecipe, updateRecipe, fetchRecipe };
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
import { useAsync, ref } from "@nuxtjs/composition-api";
|
||||
import { useApiSingleton } from "~/composables/use-api";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { UserIn, UserOut } from "~/types/api-types/user";
|
||||
|
||||
/*
|
||||
|
@ -9,7 +9,7 @@ to control whether the object is substantiated... but some of the others rely on
|
|||
*/
|
||||
|
||||
export const useAllUsers = function () {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
const loading = ref(false);
|
||||
|
||||
function getAllUsers() {
|
||||
|
@ -37,7 +37,7 @@ export const useAllUsers = function () {
|
|||
};
|
||||
|
||||
export const useUser = function (refreshFunc: CallableFunction | null = null) {
|
||||
const api = useApiSingleton();
|
||||
const api = useUserApi();
|
||||
const loading = ref(false);
|
||||
|
||||
function getUser(id: string) {
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
export const useAsyncKey = function () {
|
||||
return String(Date.now());
|
||||
};
|
||||
|
||||
export function uuid4() {
|
||||
// @ts-ignore
|
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
|
||||
(c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
const max = 1000000;
|
||||
|
||||
export function uniqueId() {
|
||||
return Date.now() + Math.random() * max;
|
||||
}
|
||||
|
||||
export function uuid4() {
|
||||
// @ts-ignore
|
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
|
||||
(c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue