diff --git a/frontend/components/Domain/Recipe/RecipeIngredientEditor.vue b/frontend/components/Domain/Recipe/RecipeIngredientEditor.vue index 6e659c156f09..2b7a15191b49 100644 --- a/frontend/components/Domain/Recipe/RecipeIngredientEditor.vue +++ b/frontend/components/Domain/Recipe/RecipeIngredientEditor.vue @@ -59,9 +59,6 @@ - - '{{ value.food && value.food !== "" ? value.food.name : null }}' does not exists. Would you like to create it? - @@ -95,7 +92,6 @@ import RecipeIngredientFoodDialog from "./RecipeIngredientFoodDialog.vue"; import { useFoods } from "~/composables/use-recipe-foods"; import { useUnits } from "~/composables/use-recipe-units"; import { validators } from "~/composables/use-validators"; -import { RecipeIngredientFood } from "~/types/api-types/recipe"; export default defineComponent({ components: { RecipeIngredientUnitDialog, RecipeIngredientFoodDialog }, @@ -119,20 +115,6 @@ export default defineComponent({ showTitle: false, }); - function checkForUnit(unit: RecipeIngredientFood) { - if (units.value && unit?.name) { - return units.value.some((u) => u.name === unit.name); - } - return false; - } - - function checkForFood(food: RecipeIngredientFood) { - if (foods.value && food?.name) { - return foods.value.some((f) => f.name === food.name); - } - return false; - } - function toggleTitle() { if (value.title) { state.showTitle = false; @@ -151,8 +133,6 @@ export default defineComponent({ units, ...toRefs(state), toggleTitle, - checkForUnit, - checkForFood, }; }, }); diff --git a/frontend/components/Domain/Recipe/RecipeIngredientParserMenu.vue b/frontend/components/Domain/Recipe/RecipeIngredientParserMenu.vue index 9dc903e7968b..e8f9b7367cb1 100644 --- a/frontend/components/Domain/Recipe/RecipeIngredientParserMenu.vue +++ b/frontend/components/Domain/Recipe/RecipeIngredientParserMenu.vue @@ -10,7 +10,10 @@ - Warning Experimental + + {{ $globals.icons.alert }} Experimental + + Mealie can use natural language processing to attempt to parse and create units, and foods for your Recipe ingredients. This is experimental and may not work as expected. If you choose to not use the parsed results @@ -29,10 +32,32 @@ - - {{ ingredients[index].note }} - - + + + + + + + {{ $globals.icons.close }} + + + {{ $globals.icons.check }} + + + {{ ingredients[index].note }} + + + + + + + + {{ errors[index].foodErrorMessage }} + + + + + @@ -42,7 +67,18 @@ import { defineComponent, ref } from "@nuxtjs/composition-api"; import RecipeIngredientEditor from "./RecipeIngredientEditor.vue"; import { useApiSingleton } from "~/composables/use-api"; -import { RecipeIngredient } from "~/types/api-types/recipe"; +import { RecipeIngredient, RecipeIngredientUnit } from "~/types/api-types/recipe"; +import { useFoods } from "~/composables/use-recipe-foods"; +import { useUnits } from "~/composables/use-recipe-units"; +import { Food } from "~/api/class-interfaces/recipe-foods"; + +interface Error { + ingredientIndex: number; + unitError: Boolean; + unitErrorMessage: string; + foodError: Boolean; + foodErrorMessage: string; +} export default defineComponent({ components: { @@ -60,8 +96,36 @@ export default defineComponent({ const parsedData = ref([]); + const { foods, workingFoodData, actions } = useFoods(); + const { units } = useUnits(); + const domParsedDataDialog = ref(null); + const panels = ref([]); + const errors = ref([]); + + function checkForUnit(unit: RecipeIngredientUnit) { + if (units.value && unit?.name) { + return units.value.some((u) => u.name === unit.name); + } + return false; + } + + function checkForFood(food: Food) { + if (foods.value && food?.name) { + return foods.value.some((f) => f.name === food.name); + } + return false; + } + + async function createFood(food: Food, index: number) { + workingFoodData.name = food.name; + + parsedData.value[index] = await actions.createOne(); + + errors.value[index].foodError = false; + } + async function parseIngredients() { // @ts-ignore -> No idea what it's talking about const ingredientNotes = ingredients.map((ing: RecipeIngredient) => ing.note); @@ -73,12 +137,38 @@ export default defineComponent({ domParsedDataDialog.value.open(); console.log(data); parsedData.value = data; - } - console.log("ingredientNotes", ingredientNotes); + // @ts-ignore + errors.value = data.ingredient.map((ing, index: number) => { + const unitError = !checkForUnit(ing.unit); + const foodError = !checkForFood(ing.food); + + let unitErrorMessage = ""; + let foodErrorMessage = ""; + + if (unitError || foodError) { + if (unitError) { + unitErrorMessage = `Create missing unit '${ing.unit.name || "No unit"}'`; + } + + if (foodError) { + panels.value.push(index); + foodErrorMessage = `Create missing food '${ing.food.name || "No food"}'?`; + } + } + + return { + ingredientIndex: index, + unitError, + unitErrorMessage, + foodError, + foodErrorMessage, + }; + }); + } } - return { api, parseIngredients, parsedData, domParsedDataDialog }; + return { api, parseIngredients, parsedData, domParsedDataDialog, panels, errors, createFood }; }, }); diff --git a/frontend/composables/use-recipe-foods.ts b/frontend/composables/use-recipe-foods.ts index dde81c11d3db..1d0c7ce136dc 100644 --- a/frontend/composables/use-recipe-foods.ts +++ b/frontend/composables/use-recipe-foods.ts @@ -48,6 +48,7 @@ export const useFoods = function () { const { data } = await api.foods.createOne(workingFoodData); if (data && foodStore?.value) { foodStore.value.push(data); + return data; } else { this.refreshAll(); } diff --git a/frontend/nuxt.config.js b/frontend/nuxt.config.js index 2143fae2775d..4c6bcdee8521 100644 --- a/frontend/nuxt.config.js +++ b/frontend/nuxt.config.js @@ -250,7 +250,7 @@ export default { secondary: "#973542", success: "#43A047", info: "#1976d2", - warning: "#FF4081", + warning: "#FF6D00", error: "#EF5350", }, light: { @@ -259,7 +259,7 @@ export default { secondary: "#973542", success: "#43A047", info: "#1976d2", - warning: "#FF4081", + warning: "#FF6D00", error: "#EF5350", }, },