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",