number scaler component and changing entry amount

This commit is contained in:
vabene1111 2024-01-10 06:51:34 +08:00
parent 69b24db442
commit 6d4f094455
4 changed files with 92 additions and 47 deletions

View File

@ -108,29 +108,11 @@
<span><small class="text-muted">{{ r.recipe_name }}</small></span> <span><small class="text-muted">{{ r.recipe_name }}</small></span>
<!-- TODO show meal plan date/type --> <!-- TODO show meal plan date/type -->
</b-button> </b-button>
<!-- <b-form-input min="1" type="number" :debounce="300" v-model="r.servings" @update="updateServings(r.shopping_list_recipe_id, r.servings)"></b-form-input>-->
<b-button variant="danger" @click="deleteRecipe(r.shopping_list_recipe_id)"><i <b-button variant="danger" @click="deleteRecipe(r.shopping_list_recipe_id)"><i
class="fas fa-trash fa-fw"></i></b-button> class="fas fa-trash fa-fw"></i></b-button>
</b-button-group> </b-button-group>
<b-button-group class="w-100 mt-1"> <number-scaler-component :number="r.servings" @change="updateServings(r, $event)" :disable="useShoppingListStore().currently_updating"></number-scaler-component>
<b-button @click="r.servings = updateServings(r, 'half')"
:disabled="shopping_list_store.currently_updating"><i class="fas fa-divide"></i> 2
</b-button>
<b-button variant="info" @click="r.servings = updateServings(r, 'sub')"
:disabled="shopping_list_store.currently_updating"><i class="fas fa-minus"></i>
</b-button>
<b-button variant="info" @click="r.servings = updateServings(r, 'prompt')">{{
r.servings
}}
</b-button>
<b-button variant="info" @click="r.servings = updateServings(r, 'add')"
:disabled="shopping_list_store.currently_updating"><i class="fas fa-plus"></i>
</b-button>
<b-button @click="r.servings = updateServings(r, 'multiply')"
:disabled="shopping_list_store.currently_updating"><i class="fas fa-times"></i> 2
</b-button>
</b-button-group>
</b-col> </b-col>
</b-row> </b-row>
@ -488,11 +470,13 @@ import {Workbox} from 'workbox-window';
import BottomNavigationBar from "@/components/BottomNavigationBar.vue"; import BottomNavigationBar from "@/components/BottomNavigationBar.vue";
import {useShoppingListStore} from "@/stores/ShoppingListStore"; import {useShoppingListStore} from "@/stores/ShoppingListStore";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore"; import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
import NumberScalerComponent from "@/components/NumberScalerComponent.vue";
export default { export default {
name: "ShoppingListView", name: "ShoppingListView",
mixins: [ApiMixin, ResolveUrlMixin], mixins: [ApiMixin, ResolveUrlMixin],
components: { components: {
NumberScalerComponent,
ShoppingLineItem, ShoppingLineItem,
GenericMultiselect, GenericMultiselect,
@ -741,39 +725,22 @@ export default {
* change number of servings of a shopping list recipe * change number of servings of a shopping list recipe
* backend handles scaling of associated entries * backend handles scaling of associated entries
* @param recipe recipe to update * @param recipe recipe to update
* @param mode mode to change servings * @param servings number of servings to set recipe to
*/ */
updateServings(recipe, mode) { updateServings(recipe, servings) {
if (mode === 'half') { if (servings > 0 && servings !== "") {
recipe.servings = recipe.servings / 2
}
if (mode === 'multiply') {
recipe.servings = recipe.servings * 2
}
if (mode === 'add') {
recipe.servings++
}
if (mode === 'sub') {
recipe.servings--
}
if (mode === 'prompt') {
let servings = prompt(this.$t('Servings'), recipe.servings);
if (servings !== null && servings !== "" && !isNaN(servings) && !isNaN(parseFloat(servings))) {
recipe.servings = parseFloat(servings)
} else {
console.log('Invalid input in servings prompt', servings)
}
}
if (recipe.servings > 0 && recipe.servings !== "") {
let api = new ApiApiFactory() let api = new ApiApiFactory()
useShoppingListStore().currently_updating = true
api.partialUpdateShoppingListRecipe(recipe.shopping_list_recipe_id, { api.partialUpdateShoppingListRecipe(recipe.shopping_list_recipe_id, {
id: recipe.shopping_list_recipe_id, id: recipe.shopping_list_recipe_id,
servings: recipe.servings servings: servings
}).then(() => { }).then(() => {
useShoppingListStore().currently_updating = false
useShoppingListStore().refreshFromAPI() useShoppingListStore().refreshFromAPI()
}).catch((err) => {
useShoppingListStore().currently_updating = false
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
}) })
return recipe.servings
} }
}, },

View File

@ -0,0 +1,74 @@
<template>
<div>
<b-button-group class="w-100 mt-1">
<b-button @click="updateNumber( 'half')"
:disabled="disable"><i class="fas fa-divide"></i> 2
</b-button>
<b-button variant="info" @click="updateNumber( 'sub')"
:disabled="disable"><i class="fas fa-minus"></i>
</b-button>
<b-button variant="info" @click="updateNumber('prompt')"
:disabled="disable">
{{ number }}
</b-button>
<b-button variant="info" @click="updateNumber( 'add')"
:disabled="disable"><i class="fas fa-plus"></i>
</b-button>
<b-button @click="updateNumber('multiply')"
:disabled="disable"><i class="fas fa-times"></i> 2
</b-button>
</b-button-group>
</div>
</template>
<script>
import Vue from "vue"
import {BootstrapVue} from "bootstrap-vue"
import "bootstrap-vue/dist/bootstrap-vue.css"
Vue.use(BootstrapVue)
export default {
name: "NumberScalerComponent",
props: {
number: {type: Number, default:0},
disable: {type: Boolean, default: false}
},
data() {
return {}
},
methods: {
/**
* perform given operation on linked number
* @param operation update mode
*/
updateNumber: function(operation) {
if (operation === 'half') {
this.$emit('change', this.number / 2)
}
if (operation === 'multiply') {
this.$emit('change', this.number * 2)
}
if (operation === 'add') {
this.$emit('change', this.number + 1)
}
if (operation === 'sub') {
this.$emit('change', this.number - 1)
}
if (operation === 'prompt') {
let input_number = prompt(this.$t('Input'), this.number);
if (input_number !== null && input_number !== "" && !isNaN(input_number) && !isNaN(parseFloat(input_number))) {
this.$emit('change', parseFloat(input_number))
} else {
console.log('Invalid number input in prompt', input_number)
}
}
},
},
}
</script>
<style scoped>
</style>

View File

@ -57,7 +57,7 @@
<b-col cold="12"> <b-col cold="12">
<b-button-group class="mt-1 w-100"> <b-button-group class="mt-1 w-100">
<b-button variant="dark" block class="btn btn-block text-left"> <b-button variant="dark" block class="btn btn-block text-left">
<span>{{ food.name }}</span> <span><span v-if="e.amount > 0">{{e.amount}}</span> {{e.unit?.name}} {{ food.name }}</span>
<span><br/><small class="text-muted"> <span><br/><small class="text-muted">
<span v-if="e.recipe_mealplan && e.recipe_mealplan.recipe_name !== ''"> <span v-if="e.recipe_mealplan && e.recipe_mealplan.recipe_name !== ''">
<a :href="resolveDjangoUrl('view_recipe', e.recipe_mealplan.recipe)"> {{ e.recipe_mealplan.recipe_name }} </a>({{ <a :href="resolveDjangoUrl('view_recipe', e.recipe_mealplan.recipe)"> {{ e.recipe_mealplan.recipe_name }} </a>({{
@ -76,6 +76,8 @@
<b-button variant="warning" @click="detail_modal_visible = false; useShoppingListStore().deleteObject(e)"><i class="fas fa-trash"></i></b-button> <!-- TODO implement --> <b-button variant="warning" @click="detail_modal_visible = false; useShoppingListStore().deleteObject(e)"><i class="fas fa-trash"></i></b-button> <!-- TODO implement -->
</b-button-group> </b-button-group>
<number-scaler-component :number="e.amount" @change="e.amount = $event; useShoppingListStore().updateObject(e)"></number-scaler-component>
</b-col> </b-col>
</b-row> </b-row>
</template> </template>
@ -97,6 +99,7 @@ import {useMealPlanStore} from "@/stores/MealPlanStore";
import {useShoppingListStore} from "@/stores/ShoppingListStore"; import {useShoppingListStore} from "@/stores/ShoppingListStore";
import {ApiApiFactory} from "@/utils/openapi/api"; import {ApiApiFactory} from "@/utils/openapi/api";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore"; import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
import NumberScalerComponent from "@/components/NumberScalerComponent.vue";
Vue.use(BootstrapVue) Vue.use(BootstrapVue)
@ -104,7 +107,7 @@ Vue.use(BootstrapVue)
export default { export default {
name: "ShoppingLineItem", name: "ShoppingLineItem",
mixins: [ApiMixin], mixins: [ApiMixin],
components: {}, components: {NumberScalerComponent},
props: { props: {
entries: {type: Object,}, entries: {type: Object,},
}, },

View File

@ -96,6 +96,7 @@
"base_unit": "Base Unit", "base_unit": "Base Unit",
"base_amount": "Base Amount", "base_amount": "Base Amount",
"Datatype": "Datatype", "Datatype": "Datatype",
"Input": "Input",
"Number of Objects": "Number of Objects", "Number of Objects": "Number of Objects",
"Add_Step": "Add Step", "Add_Step": "Add Step",
"Keywords": "Keywords", "Keywords": "Keywords",