mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-07 23:28:16 -05:00
working add to shopping dialog
This commit is contained in:
@@ -1,29 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-dialog activator="parent" max-width="600px" v-model="dialog">
|
<v-dialog activator="parent" max-width="600px" v-model="dialog">
|
||||||
<v-card :loading="loading">
|
<v-card :loading="loading">
|
||||||
<v-closable-card-title :title="$t('Add_Servings_to_Shopping', servings)" v-model="dialog"></v-closable-card-title>
|
<v-closable-card-title :title="$t('Add_Servings_to_Shopping', {servings: servings})" v-model="dialog"></v-closable-card-title>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-expansion-panels variant="accordion">
|
<v-expansion-panels variant="accordion">
|
||||||
<v-expansion-panel>
|
<v-expansion-panel v-for="r in dialogRecipes">
|
||||||
<v-expansion-panel-title>{{ recipe.name }}</v-expansion-panel-title>
|
<v-expansion-panel-title>{{ r.recipe.name }}</v-expansion-panel-title>
|
||||||
<v-expansion-panel-text>
|
<v-expansion-panel-text>
|
||||||
<v-list>
|
<v-list>
|
||||||
<template v-for="s in recipe.steps">
|
<v-list-item v-for="e in r.entries">
|
||||||
<v-list-item v-for="i in s.ingredients">
|
<v-checkbox v-model="e.checked" size="small" density="compact" hide-details>
|
||||||
{{ i }}
|
<template #label>
|
||||||
|
{{ $n(e.amount * (servings / r.recipe.servings)) }}
|
||||||
|
<span class="ms-1" v-if="e.unit">{{ e.unit.name }}</span>
|
||||||
|
<span class="ms-1" v-if="e.food">{{e.food.name }}</span>
|
||||||
|
</template>
|
||||||
|
</v-checkbox>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</template>
|
|
||||||
</v-list>
|
|
||||||
</v-expansion-panel-text>
|
|
||||||
</v-expansion-panel>
|
|
||||||
|
|
||||||
<v-expansion-panel v-for="r in relatedRecipes">
|
|
||||||
<v-expansion-panel-title>{{ r.name }}</v-expansion-panel-title>
|
|
||||||
<v-expansion-panel-text>
|
|
||||||
<v-list>
|
|
||||||
<template v-for="s in r.steps">
|
|
||||||
<v-list-item v-for="i in s.ingredients">{{ i }}</v-list-item>
|
|
||||||
</template>
|
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-expansion-panel-text>
|
</v-expansion-panel-text>
|
||||||
</v-expansion-panel>
|
</v-expansion-panel>
|
||||||
@@ -31,7 +24,7 @@
|
|||||||
<v-number-input v-model="servings" class="mt-3" control-variant="split" :label="$t('Servings')"></v-number-input>
|
<v-number-input v-model="servings" class="mt-3" control-variant="split" :label="$t('Servings')"></v-number-input>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-btn class="float-right" prepend-icon="$create" color="create" @click="createShoppingListRecipe()">{{$t('Add_to_Shopping')}}</v-btn>
|
<v-btn class="float-right" prepend-icon="$create" color="create" @click="createShoppingListRecipe()">{{ $t('Add_to_Shopping') }}</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
@@ -39,11 +32,12 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import {computed, onMounted, PropType, ref} from "vue";
|
import {onMounted, PropType, ref} from "vue";
|
||||||
import VClosableCardTitle from "@/components/dialogs/VClosableCardTitle.vue";
|
import VClosableCardTitle from "@/components/dialogs/VClosableCardTitle.vue";
|
||||||
import {ApiApi, Recipe, RecipeFlat, RecipeOverview, type RecipeShoppingUpdate, type ShoppingListEntryBulkCreate, ShoppingListRecipe} from "@/openapi";
|
import {ApiApi, Recipe, RecipeFlat, RecipeOverview, type ShoppingListEntryBulkCreate, ShoppingListRecipe} from "@/openapi";
|
||||||
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
|
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
|
||||||
import {VNumberInput} from 'vuetify/labs/VNumberInput'
|
import {VNumberInput} from 'vuetify/labs/VNumberInput'
|
||||||
|
import {ShoppingDialogRecipe, ShoppingDialogRecipeEntry} from "@/types/Shopping";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
recipe: {type: Object as PropType<Recipe | RecipeFlat | RecipeOverview>, required: true},
|
recipe: {type: Object as PropType<Recipe | RecipeFlat | RecipeOverview>, required: true},
|
||||||
@@ -56,6 +50,8 @@ const servings = ref(1)
|
|||||||
const recipe = ref({} as Recipe)
|
const recipe = ref({} as Recipe)
|
||||||
const relatedRecipes = ref([] as Recipe[])
|
const relatedRecipes = ref([] as Recipe[])
|
||||||
|
|
||||||
|
const dialogRecipes = ref([] as ShoppingDialogRecipe[])
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadRecipeData()
|
loadRecipeData()
|
||||||
})
|
})
|
||||||
@@ -88,6 +84,28 @@ function loadRecipeData() {
|
|||||||
Promise.allSettled(promises).then(() => {
|
Promise.allSettled(promises).then(() => {
|
||||||
console.log('ALL LOADED')
|
console.log('ALL LOADED')
|
||||||
loading.value = false
|
loading.value = false
|
||||||
|
|
||||||
|
let allRecipes = [recipe.value].concat(relatedRecipes.value)
|
||||||
|
|
||||||
|
allRecipes.forEach(recipe => {
|
||||||
|
let dialogRecipe = {
|
||||||
|
recipe: recipe,
|
||||||
|
entries: [] as ShoppingDialogRecipeEntry[]
|
||||||
|
} as ShoppingDialogRecipe
|
||||||
|
|
||||||
|
recipe.steps.forEach(step => {
|
||||||
|
step.ingredients.forEach(ingredient => {
|
||||||
|
dialogRecipe.entries.push({
|
||||||
|
amount: ingredient.amount,
|
||||||
|
food: ingredient.food,
|
||||||
|
unit: ingredient.unit,
|
||||||
|
checked: (ingredient.food ? !(ingredient.food.ignoreShopping || ingredient.food.foodOnhand) : true),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
dialogRecipes.value.push(dialogRecipe)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -97,6 +115,8 @@ function loadRecipeData() {
|
|||||||
*/
|
*/
|
||||||
function createShoppingListRecipe() {
|
function createShoppingListRecipe() {
|
||||||
let api = new ApiApi()
|
let api = new ApiApi()
|
||||||
|
loading.value = true
|
||||||
|
|
||||||
let shoppingListRecipe = {
|
let shoppingListRecipe = {
|
||||||
recipe: props.recipe.id,
|
recipe: props.recipe.id,
|
||||||
servings: servings.value,
|
servings: servings.value,
|
||||||
@@ -106,22 +126,26 @@ function createShoppingListRecipe() {
|
|||||||
entries: []
|
entries: []
|
||||||
} as ShoppingListEntryBulkCreate
|
} as ShoppingListEntryBulkCreate
|
||||||
|
|
||||||
recipe.value.steps.forEach(step => {
|
dialogRecipes.value.forEach(dialogRecipe => {
|
||||||
step.ingredients.forEach(ingredient => {
|
dialogRecipe.entries.forEach(entry => {
|
||||||
|
if (entry.checked) {
|
||||||
shoppingListEntries.entries.push({
|
shoppingListEntries.entries.push({
|
||||||
amount: ingredient.amount * (servings.value / (recipe.value.servings ? recipe.value.servings : 1)),
|
amount: entry.amount * (servings.value / (recipe.value.servings ? recipe.value.servings : 1)),
|
||||||
foodId: ingredient.food ? ingredient.food.id! : null,
|
foodId: entry.food ? entry.food.id! : null,
|
||||||
unitId: ingredient.unit ? ingredient.unit.id! : null
|
unitId: entry.unit ? entry.unit.id! : null
|
||||||
})
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
api.apiShoppingListRecipeCreate({shoppingListRecipe: shoppingListRecipe}).then(slr => {
|
api.apiShoppingListRecipeCreate({shoppingListRecipe: shoppingListRecipe}).then(slr => {
|
||||||
|
|
||||||
api.apiShoppingListRecipeBulkCreateEntriesCreate({id: slr.id!, shoppingListEntryBulkCreate: shoppingListEntries}).then(r => {
|
api.apiShoppingListRecipeBulkCreateEntriesCreate({id: slr.id!, shoppingListEntryBulkCreate: shoppingListEntries}).then(r => {
|
||||||
|
useMessageStore().addPreparedMessage(PreparedMessage.CREATE_SUCCESS)
|
||||||
|
dialog.value = false
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
|
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
|
||||||
|
}).finally(() => {
|
||||||
|
loading.value = false
|
||||||
})
|
})
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
|
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {Food, ShoppingListEntry, Unit} from "@/openapi";
|
import {Food, Recipe, ShoppingListEntry, Unit} from "@/openapi";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum of different options a shopping list can be grouped by
|
* enum of different options a shopping list can be grouped by
|
||||||
@@ -88,3 +88,15 @@ export type ShoppingOperationHistoryEntry = {
|
|||||||
type: ShoppingOperationHistoryType,
|
type: ShoppingOperationHistoryType,
|
||||||
entries: ShoppingListEntry[]
|
entries: ShoppingListEntry[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ShoppingDialogRecipe = {
|
||||||
|
recipe: Recipe
|
||||||
|
entries: ShoppingDialogRecipeEntry[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ShoppingDialogRecipeEntry = {
|
||||||
|
amount: number,
|
||||||
|
unit: Unit|null,
|
||||||
|
food: Food|null,
|
||||||
|
checked: boolean,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user