From ca26639525d6ea3dfa683041d24f897a2496f974 Mon Sep 17 00:00:00 2001 From: Michael Genson <71845777+michael-genson@users.noreply.github.com> Date: Wed, 22 May 2024 16:58:16 -0500 Subject: [PATCH] feat: Data Management from Shopping List (#3603) Co-authored-by: boc-the-git <3479092+boc-the-git@users.noreply.github.com> --- .../Domain/Recipe/RecipeIngredientEditor.vue | 8 ++ .../ShoppingList/ShoppingListItemEditor.vue | 120 +++++++++++++----- frontend/components/global/BaseButton.vue | 14 +- frontend/components/global/InputLabelType.vue | 30 ++++- frontend/lang/messages/en-US.json | 1 + frontend/lib/icons/icons.ts | 2 + 6 files changed, 140 insertions(+), 35 deletions(-) diff --git a/frontend/components/Domain/Recipe/RecipeIngredientEditor.vue b/frontend/components/Domain/Recipe/RecipeIngredientEditor.vue index 80b5bf7f5cac..b9e2ad52b8b6 100644 --- a/frontend/components/Domain/Recipe/RecipeIngredientEditor.vue +++ b/frontend/components/Domain/Recipe/RecipeIngredientEditor.vue @@ -29,6 +29,7 @@ (); async function createAssignFood() { foodData.data.name = foodSearch.value; props.value.food = await foodStore.actions.createOne(foodData.data) || undefined; foodData.reset(); + foodAutocomplete.value?.blur(); } // ================================================== @@ -212,11 +216,13 @@ export default defineComponent({ const unitStore = useUnitStore(); const unitsData = useUnitData(); const unitSearch = ref(""); + const unitAutocomplete = ref(); async function createAssignUnit() { unitsData.data.name = unitSearch.value; props.value.unit = await unitStore.actions.createOne(unitsData.data) || undefined; unitsData.reset(); + unitAutocomplete.value?.blur(); } const state = reactive({ @@ -269,7 +275,9 @@ export default defineComponent({ contextMenuOptions, handleUnitEnter, handleFoodEnter, + foodAutocomplete, createAssignFood, + unitAutocomplete, createAssignUnit, foods: foodStore.foods, foodSearch, diff --git a/frontend/components/Domain/ShoppingList/ShoppingListItemEditor.vue b/frontend/components/Domain/ShoppingList/ShoppingListItemEditor.vue index 5b0f12611f45..f9291efa09f8 100644 --- a/frontend/components/Domain/ShoppingList/ShoppingListItemEditor.vue +++ b/frontend/components/Domain/ShoppingList/ShoppingListItemEditor.vue @@ -9,6 +9,7 @@ :item-id.sync="listItem.foodId" :label="$t('shopping-list.food')" :icon="$globals.icons.foods" + @create="createAssignFood" />
@@ -28,37 +30,49 @@ @keypress="handleNoteKeyPress" >
-
-
- -
-
- -
+
+
+
+ +
+
+ +
- - - - - {{ $t("shopping-list.linked-item-warning") }} - - - + + + + + {{ $t("shopping-list.linked-item-warning") }} + + + +
+ +
@@ -100,6 +114,7 @@ import { defineComponent, computed, watch } from "@nuxtjs/composition-api"; import { ShoppingListItemCreate, ShoppingListItemOut } from "~/lib/api/types/group"; import { MultiPurposeLabelOut } from "~/lib/api/types/labels"; import { IngredientFood, IngredientUnit } from "~/lib/api/types/recipe"; +import { useFoodStore, useFoodData, useUnitStore, useUnitData } from "~/composables/store"; export default defineComponent({ props: { @@ -121,6 +136,12 @@ export default defineComponent({ }, }, setup(props, context) { + const foodStore = useFoodStore(); + const foodData = useFoodData(); + + const unitStore = useUnitStore(); + const unitData = useUnitData(); + const listItem = computed({ get: () => { return props.value; @@ -139,8 +160,47 @@ export default defineComponent({ } ); + async function createAssignFood(val: string) { + // keep UI reactive + listItem.value.food ? listItem.value.food.name = val : listItem.value.food = { name: val }; + + foodData.data.name = val; + const newFood = await foodStore.actions.createOne(foodData.data); + if (newFood) { + listItem.value.food = newFood; + listItem.value.foodId = newFood.id; + } + foodData.reset(); + } + + async function createAssignUnit(val: string) { + // keep UI reactive + listItem.value.unit ? listItem.value.unit.name = val : listItem.value.unit = { name: val }; + + unitData.data.name = val; + const newUnit = await unitStore.actions.createOne(unitData.data); + if (newUnit) { + listItem.value.unit = newUnit; + listItem.value.unitId = newUnit.id; + } + unitData.reset(); + } + + async function assignLabelToFood() { + if (!(listItem.value.food && listItem.value.foodId && listItem.value.labelId)) { + return; + } + + listItem.value.food.labelId = listItem.value.labelId; + // @ts-ignore the food will have an id, even though TS says it might not + await foodStore.actions.updateOne(listItem.value.food); + } + return { listItem, + createAssignFood, + createAssignUnit, + assignLabelToFood, }; }, methods: { diff --git a/frontend/components/global/BaseButton.vue b/frontend/components/global/BaseButton.vue index 1d404dbebade..7eebc912c56c 100644 --- a/frontend/components/global/BaseButton.vue +++ b/frontend/components/global/BaseButton.vue @@ -14,15 +14,15 @@ > - {{ btnAttrs.icon }} + {{ icon || btnAttrs.icon }} - {{ btnAttrs.text }} + {{ text || btnAttrs.text }} - {{ btnAttrs.icon }} + {{ icon || btnAttrs.icon }} @@ -103,6 +103,14 @@ export default defineComponent({ type: String, default: null, }, + text: { + type: String, + default: null, + }, + icon: { + type: String, + default: null, + }, iconRight: { type: Boolean, default: false, diff --git a/frontend/components/global/InputLabelType.vue b/frontend/components/global/InputLabelType.vue index 9e9cd84fec96..4268d9c93e9d 100644 --- a/frontend/components/global/InputLabelType.vue +++ b/frontend/components/global/InputLabelType.vue @@ -1,14 +1,27 @@