From c6fbf8bce858368f912b70004e1bc0b0c64540bf Mon Sep 17 00:00:00 2001 From: Michael Genson <71845777+michael-genson@users.noreply.github.com> Date: Fri, 26 Jan 2024 09:27:36 -0600 Subject: [PATCH] feat: Improvements To Adding A Recipe To A Shopping List (#3036) * tweaked dialogs to make grammatical sense * refactor ingredient rendering on recipe shopping list dialog --- .../Recipe/RecipeDialogAddToShoppingList.vue | 132 ++++++++++++------ frontend/lang/messages/en-US.json | 2 + 2 files changed, 94 insertions(+), 40 deletions(-) diff --git a/frontend/components/Domain/Recipe/RecipeDialogAddToShoppingList.vue b/frontend/components/Domain/Recipe/RecipeDialogAddToShoppingList.vue index a3621043685c..1992ca3797ee 100644 --- a/frontend/components/Domain/Recipe/RecipeDialogAddToShoppingList.vue +++ b/frontend/components/Domain/Recipe/RecipeDialogAddToShoppingList.vue @@ -26,54 +26,69 @@ >
- + - {{ section.recipeName }} + {{ recipeSection.recipeName }} - + - ({{ $tc("recipe.quantity") }}: {{ section.recipeScale }}) + ({{ $tc("recipe.quantity") }}: {{ recipeSection.recipeScale }}) -
- +
- - - - - + + {{ ingredientSection.sectionName }} + +
+ + + + + + +
+
@@ -112,17 +127,22 @@ export interface RecipeWithScale extends Recipe { scale: number; } -export interface ShoppingListRecipeIngredient { +export interface ShoppingListIngredient { checked: boolean; ingredient: RecipeIngredient; disableAmount: boolean; } +export interface ShoppingListIngredientSection { + sectionName: string; + ingredients: ShoppingListIngredient[]; +} + export interface ShoppingListRecipeIngredientSection { recipeId: string; recipeName: string; recipeScale: number; - ingredients: ShoppingListRecipeIngredient[]; + ingredientSections: ShoppingListIngredientSection[]; } export default defineComponent({ @@ -191,7 +211,7 @@ export default defineComponent({ continue; } - const shoppingListIngredients: ShoppingListRecipeIngredient[] = recipe.recipeIngredient.map((ing) => { + const shoppingListIngredients: ShoppingListIngredient[] = recipe.recipeIngredient.map((ing) => { return { checked: true, ingredient: ing, @@ -199,11 +219,35 @@ export default defineComponent({ } }); + const shoppingListIngredientSections = shoppingListIngredients.reduce((sections, ing) => { + // if title append new section to the end of the array + if (ing.ingredient.title) { + sections.push({ + sectionName: ing.ingredient.title, + ingredients: [ing], + }); + return sections; + } + + // append new section if first + if (sections.length === 0) { + sections.push({ + sectionName: "", + ingredients: [ing], + }); + return sections; + } + + // otherwise add ingredient to last section in the array + sections[sections.length - 1].ingredients.push(ing); + return sections; + }, [] as ShoppingListIngredientSection[]); + recipeSectionMap.set(recipe.slug, { recipeId: recipe.id, recipeName: recipe.name, recipeScale: recipe.scale, - ingredients: shoppingListIngredients, + ingredientSections: shoppingListIngredientSections, }) } @@ -231,9 +275,11 @@ export default defineComponent({ } function bulkCheckIngredients(value = true) { - recipeIngredientSections.value.forEach((section) => { - section.ingredients.forEach((ing) => { - ing.checked = value; + recipeIngredientSections.value.forEach((recipeSection) => { + recipeSection.ingredientSections.forEach((ingSection) => { + ingSection.ingredients.forEach((ing) => { + ing.checked = value; + }); }); }); } @@ -246,10 +292,12 @@ export default defineComponent({ } const ingredients: RecipeIngredient[] = []; - section.ingredients.forEach((ing) => { - if (ing.checked) { - ingredients.push(ing.ingredient); - } + section.ingredientSections.forEach((ingSection) => { + ingSection.ingredients.forEach((ing) => { + if (ing.checked) { + ingredients.push(ing.ingredient); + } + }); }); if (!ingredients.length) { @@ -272,7 +320,11 @@ export default defineComponent({ } }) - success ? alert.success(i18n.t("recipe.recipes-added-to-list") as string) + const successMessage = promises.length === 1 + ? i18n.t("recipe.successfully-added-to-list") as string + : i18n.t("recipe.failed-to-add-to-list") as string; + + success ? alert.success(successMessage) : alert.error(i18n.t("failed-to-add-recipes-to-list") as string) state.shoppingListDialog = false; diff --git a/frontend/lang/messages/en-US.json b/frontend/lang/messages/en-US.json index 525263ee79ab..1f1e370c4a75 100644 --- a/frontend/lang/messages/en-US.json +++ b/frontend/lang/messages/en-US.json @@ -473,9 +473,11 @@ "add-to-timeline": "Add to Timeline", "recipe-added-to-list": "Recipe added to list", "recipes-added-to-list": "Recipes added to list", + "successfully-added-to-list": "Successfully added to list", "recipe-added-to-mealplan": "Recipe added to mealplan", "failed-to-add-recipes-to-list": "Failed to add recipe to list", "failed-to-add-recipe-to-mealplan": "Failed to add recipe to mealplan", + "failed-to-add-to-list": "Failed to add to list", "yield": "Yield", "quantity": "Quantity", "choose-unit": "Choose Unit",