1
0
Fork 0
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:
Hayden 2021-11-06 11:28:47 -08:00 committed by GitHub
parent 095d3bda3f
commit 788e176b16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
68 changed files with 330 additions and 245 deletions

View file

@ -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);

View file

@ -1 +1,2 @@
export { useStaticRoutes } from "./static-routes";
export { useAdminApi, useUserApi } from "./api-client";

View 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";

View file

@ -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);

View 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>&frasl;<sub>${fraction[2]}</sub>`;
}
} else {
returnQty = (quantity * scale).toString();
}
return `${returnQty} ${unit?.name || " "} ${food?.name || " "} ${note}`.replace(/ {2,}/g, " ");
}

View file

@ -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);

View 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,
};
};

View file

@ -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 } = (() => {

View file

@ -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),

View file

@ -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("");

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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() {

View file

@ -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();

View file

@ -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 };
};

View file

@ -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) {

View file

@ -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)
);
}

View file

@ -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)
);
}