property view unit conversion/edit

This commit is contained in:
vabene1111
2025-03-21 21:22:32 +01:00
parent fbab90e954
commit de5ac9181f
34 changed files with 111 additions and 38 deletions

View File

@@ -44,13 +44,17 @@ class FoodPropertyHelper:
if i.food is not None:
conversions = uch.get_conversions(i)
for pt in property_types:
# if a property could be calculated with an actual value
found_property = False
# if food has a value for the given property type (no matter if conversion is possible)
has_property_value = False
if i.food.properties_food_amount == 0 or i.food.properties_food_unit is None: # if food is configured incorrectly
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': i.food.name, 'value': None}
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': {'id': i.food.id, 'name': i.food.name}, 'value': None}
computed_properties[pt.id]['missing_value'] = True
else:
for p in i.food.properties.all():
if p.property_type == pt and p.property_amount is not None:
has_property_value = True
for c in conversions:
if c.unit == i.food.properties_food_unit:
found_property = True
@@ -60,10 +64,12 @@ class FoodPropertyHelper:
if not found_property:
if i.amount == 0: # don't count ingredients without an amount as missing
computed_properties[pt.id]['missing_value'] = computed_properties[pt.id]['missing_value'] or False # don't override if another food was already missing
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': i.food.name, 'value': 0}
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': {'id': i.food.id, 'name': i.food.name}, 'value': 0}
else:
computed_properties[pt.id]['missing_value'] = True
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': i.food.name, 'value': None}
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': {'id': i.food.id, 'name': i.food.name}, 'value': None}
if has_property_value and i.unit is not None:
computed_properties[pt.id]['food_values'][i.food.id]['missing_conversion'] = {'base_unit': {'id': i.unit.id, 'name': i.unit.name}, 'converted_unit': {'id': i.food.properties_food_unit.id, 'name': i.food.properties_food_unit.name}}
return computed_properties
@@ -74,5 +80,5 @@ class FoodPropertyHelper:
if key in d and d[key]['value']:
d[key]['value'] += value
else:
d[key] = {'id': food.id, 'food': food.name, 'value': value}
d[key] = {'id': food.id, 'food': {'id': food.id, 'name': food.name}, 'value': value}
return d

View File

@@ -25,7 +25,8 @@
<td>{{ $n(p.propertyAmountPerServing) }} {{ p.unit }}</td>
<td>{{ $n(p.propertyAmountTotal) }} {{ p.unit }}</td>
<td v-if="sourceSelectedToShow == 'food'">
<v-btn @click="dialogProperty = p; dialog = true" variant="plain" color="warning" icon="fa-solid fa-triangle-exclamation" size="small" v-if="p.missingValue"></v-btn>
<v-btn @click="dialogProperty = p; dialog = true" variant="plain" color="warning" icon="fa-solid fa-triangle-exclamation" size="small"
v-if="p.missingValue"></v-btn>
<v-btn @click="dialogProperty = p; dialog = true" variant="plain" icon="fa-solid fa-circle-info" size="small" v-if="!p.missingValue"></v-btn>
</td>
</tr>
@@ -36,19 +37,33 @@
<v-dialog max-width="900px" v-model="dialog">
<v-card v-if="dialogProperty">
<v-closable-card-title :title="`${dialogProperty.propertyAmountTotal} ${dialogProperty.unit} ${dialogProperty.name}`" :sub-title="$t('total')" icon="$properties" v-model="dialog"></v-closable-card-title>
<v-closable-card-title :title="`${dialogProperty.propertyAmountTotal} ${dialogProperty.unit} ${dialogProperty.name}`" :sub-title="$t('total')" icon="$properties"
v-model="dialog"></v-closable-card-title>
<v-card-text>
<v-list>
<v-list-item border v-for="fv in dialogProperty.foodValues">
<v-list-item border v-for="fv in dialogProperty.foodValues" :key="`${dialogProperty.id}_${fv.id}`">
<template #prepend>
<v-progress-circular size="55" width="5" :model-value="(fv.value/dialogProperty.propertyAmountTotal)*100" :color="colorScale((fv.value/dialogProperty.propertyAmountTotal)*100)" v-if="fv.value != null">{{Math.round((fv.value/dialogProperty.propertyAmountTotal)*100)}}%</v-progress-circular>
<v-progress-circular size="55" width="5" :model-value="(fv.value/dialogProperty.propertyAmountTotal)*100"
:color="colorScale((fv.value/dialogProperty.propertyAmountTotal)*100)" v-if="fv.value != null">
{{ Math.round((fv.value / dialogProperty.propertyAmountTotal) * 100) }}%
</v-progress-circular>
<v-progress-circular size="55" width="5" v-if="fv.value == null">?</v-progress-circular>
</template>
<span class="ms-2">
{{ fv.food }}
{{ fv.food.name }}
</span>
<template #append>
<v-chip v-if="fv.value">{{$n(fv.value)}} {{dialogProperty.unit}}</v-chip>
<v-chip v-if="fv.value != undefined">{{ $n(fv.value) }} {{ dialogProperty.unit }}</v-chip>
<v-chip color="create" v-else-if="fv.missing_conversion" class="cursor-pointer" prepend-icon="$create">
{{ $t('Conversion') }}: {{ fv.missing_conversion.base_unit.name }} <i class="fa-solid fa-arrow-right me-1 ms-1"></i>
{{ fv.missing_conversion.converted_unit.name }}
<model-edit-dialog model="UnitConversion" @create="refreshRecipe()"
:item-defaults="{baseAmount: 1, baseUnit: fv.missing_conversion.base_unit, convertedUnit: fv.missing_conversion.converted_unit, food: fv.food}"></model-edit-dialog>
</v-chip>
<v-chip color="error" prepend-icon="$edit" class="cursor-pointer" v-else>
{{ $t('Edit') }}
<model-edit-dialog model="Food" :item-id="fv.food.id" @update:model-value="refreshRecipe()"></model-edit-dialog>
</v-chip>
</template>
</v-list-item>
</v-list>
@@ -63,9 +78,11 @@
<script setup lang="ts">
import {computed, onMounted, PropType, ref} from "vue";
import {PropertyType, Recipe} from "@/openapi";
import {computed, nextTick, onMounted, ref} from "vue";
import {ApiApi, PropertyType, Recipe} from "@/openapi";
import VClosableCardTitle from "@/components/dialogs/VClosableCardTitle.vue";
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
type PropertyWrapper = {
id: number,
@@ -80,15 +97,16 @@ type PropertyWrapper = {
}
const props = defineProps({
recipe: {type: {} as PropType<Recipe>, required: true},
servings: {type: Number, required: true,},
})
const recipe = defineModel<Recipe>({required: true})
/**
* determines if the recipe has properties on the recipe directly
*/
const hasRecipeProperties = computed(() => {
return props.recipe.properties != undefined && props.recipe.properties.length > 0
return recipe.value.properties != undefined && recipe.value.properties.length > 0
})
/**
@@ -96,7 +114,7 @@ const hasRecipeProperties = computed(() => {
*/
const hasFoodProperties = computed(() => {
let propertiesFound = false
for (const [key, fp] of Object.entries(props.recipe.foodProperties)) {
for (const [key, fp] of Object.entries(recipe.value.foodProperties)) {
if (fp.total_value !== 0) {
propertiesFound = true
}
@@ -111,7 +129,8 @@ const propertyList = computed(() => {
let ptList = [] as PropertyWrapper[]
if (sourceSelectedToShow.value == 'recipe') {
if (hasRecipeProperties.value) {
props.recipe.properties.forEach(rp => {
recipe.value.properties.forEach(rp => {
ptList.push(
{
id: rp.propertyType.id!,
@@ -119,7 +138,7 @@ const propertyList = computed(() => {
description: rp.propertyType.description,
foodValues: [],
propertyAmountPerServing: rp.propertyAmount,
propertyAmountTotal: rp.propertyAmount * props.recipe.servings * (props.servings / props.recipe.servings),
propertyAmountTotal: rp.propertyAmount * recipe.value.servings * (props.servings / recipe.value.servings),
missingValue: false,
unit: rp.propertyType.unit,
type: rp.propertyType,
@@ -128,7 +147,7 @@ const propertyList = computed(() => {
})
}
} else {
for (const [key, fp] of Object.entries(props.recipe.foodProperties)) {
for (const [key, fp] of Object.entries(recipe.value.foodProperties)) {
ptList.push(
{
id: fp.id,
@@ -136,8 +155,8 @@ const propertyList = computed(() => {
description: fp.description,
icon: fp.icon,
foodValues: fp.food_values,
propertyAmountPerServing: fp.total_value / props.recipe.servings,
propertyAmountTotal: fp.total_value * (props.servings / props.recipe.servings),
propertyAmountPerServing: fp.total_value / recipe.value.servings,
propertyAmountTotal: fp.total_value * (props.servings / recipe.value.servings),
missingValue: fp.missing_value,
unit: fp.unit,
type: fp,
@@ -169,6 +188,29 @@ onMounted(() => {
}
})
/**
* refresh recipe data to pull updated conversions/properties
*/
function refreshRecipe() {
let api = new ApiApi()
api.apiRecipeRetrieve({id: recipe.value.id!}).then(r => {
recipe.value = r
nextTick(() => {
if(dialogProperty.value != undefined && dialog.value){
propertyList.value.forEach(pLE => {
if (dialogProperty.value.id == pLE.id) {
dialogProperty.value = pLE
}
})
}
})
}).catch(err => {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
})
}
/**
* return a color based on the given number
* used to color the percentage of each food contributing to the total value of a property

View File

@@ -72,15 +72,9 @@
</v-card>
</template>
<property-view :recipe="recipe" :servings="servings"></property-view>
<property-view v-model="recipe" :servings="servings"></property-view>
<v-expansion-panels class="mt-2">
<v-expansion-panel>
<v-expansion-panel-title><v-icon icon="$properties" class="me-2"></v-icon> {{ $t('Properties') }}</v-expansion-panel-title>
<v-expansion-panel-text>
<property-view :recipe="recipe" :ingredient-factor="ingredientFactor"></property-view>
</v-expansion-panel-text>
</v-expansion-panel>
<v-expansion-panel>
<v-expansion-panel-title><v-icon icon="fa-solid fa-circle-info" class="me-2"></v-icon> {{ $t('Information') }}</v-expansion-panel-title>

View File

@@ -199,6 +199,7 @@
"Message": "",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "",
"More": "",

View File

@@ -193,6 +193,7 @@
"Merge_Keyword": "Обединяване на ключова дума",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Месец",
"More": "",

View File

@@ -249,6 +249,7 @@
"Message": "",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "",
"More": "",

View File

@@ -248,6 +248,7 @@
"Message": "Zpráva",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Měsíc",
"More": "",

View File

@@ -235,6 +235,7 @@
"Message": "Besked",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Måned",
"More": "",

View File

@@ -252,6 +252,7 @@
"Message": "Nachricht",
"Messages": "Nachrichten",
"Miscellaneous": "Sonstige",
"MissingConversion": "Fehlende Umrechnung",
"Monday": "Montag",
"Month": "Monat",
"More": "Mehr",

View File

@@ -230,6 +230,7 @@
"Message": "Μήνυμα",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Μήνας",
"More": "",

View File

@@ -250,6 +250,7 @@
"Message": "Message",
"Messages": "Messages",
"Miscellaneous": "Miscellaneous",
"MissingConversion": "Missing Conversion",
"Monday": "Monday",
"Month": "Month",
"More": "More",

View File

@@ -250,6 +250,7 @@
"Message": "Mensaje",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Mes",
"More": "",

View File

@@ -148,6 +148,7 @@
"Merge_Keyword": "Yhdistä Avainsana",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Kuukausi",
"More": "",

View File

@@ -249,6 +249,7 @@
"Message": "Message",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Mois",
"More": "",

View File

@@ -250,6 +250,7 @@
"Message": "הודעה",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "חודש",
"More": "",

View File

@@ -231,6 +231,7 @@
"Message": "Üzenet",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Hónap",
"More": "",

View File

@@ -113,6 +113,7 @@
"Merge_Keyword": "Միացնել բանալի բառը",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"More": "",
"Move": "Տեղափոխել",

View File

@@ -216,6 +216,7 @@
"Message": "",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "",
"More": "",

View File

@@ -249,6 +249,7 @@
"Message": "",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "",
"More": "",

View File

@@ -221,6 +221,7 @@
"Message": "Messaggio",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Mese",
"More": "",

View File

@@ -233,6 +233,7 @@
"Message": "",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "",
"More": "",

View File

@@ -228,6 +228,7 @@
"Message": "Melding",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Måned",
"More": "",

View File

@@ -232,6 +232,7 @@
"Message": "Bericht",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Maand",
"More": "",

View File

@@ -251,6 +251,7 @@
"Message": "Wiadomość",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Miesiąc",
"More": "",

View File

@@ -190,6 +190,7 @@
"Merge_Keyword": "Unir palavra-chave",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Mês",
"More": "",

View File

@@ -243,6 +243,7 @@
"Message": "Mensagem",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Mês",
"More": "",

View File

@@ -225,6 +225,7 @@
"Message": "Mesaj",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Lună",
"More": "",

View File

@@ -179,6 +179,7 @@
"Merge_Keyword": "Объеденить ключевые слова",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Месяц",
"More": "",

View File

@@ -175,6 +175,7 @@
"Merge_Keyword": "Združi ključno besedo",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Mesec",
"More": "",

View File

@@ -251,6 +251,7 @@
"Message": "Meddelande",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Månad",
"More": "",

View File

@@ -250,6 +250,7 @@
"Message": "Mesaj",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Ay",
"More": "",

View File

@@ -204,6 +204,7 @@
"Merge_Keyword": "Об'єднати Ключове слово",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "Місяць",
"More": "",

View File

@@ -246,6 +246,7 @@
"Message": "信息",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"Month": "月份",
"More": "",

View File

@@ -96,6 +96,7 @@
"MergeAutomateHelp": "",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"Monday": "",
"More": "",
"New": "",