feat: refactor recipe scaling (#4298)

This commit is contained in:
Kuchenpirat 2024-10-01 16:31:04 +02:00 committed by GitHub
parent 1bd3d38dfc
commit 14dbd79c7f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 45 additions and 29 deletions

View File

@ -33,8 +33,6 @@ Do the following for each recipe you want to intelligently handle ingredients.
Scaling up this recipe or adding it to a Shopping List will now smartly take care of ingredient amounts and duplicate combinations.
Note: Each recipe must have a servings count set for recipe scaling to work.
## Is it safe to upgrade Mealie?
Yes. If you are using the v1 branches (including beta), you can upgrade to the latest version of Mealie without performing a site Export/Restore. This process was required in previous versions of Mealie, however we've automated the database migration process to make it easier to upgrade. Note that if you were using the v0.5.x version, you CANNOT upgrade to the latest version automatically. You must follow the migration instructions in the documentation.

View File

@ -1,13 +1,13 @@
<template>
<div class="d-flex justify-space-between align-center pt-2 pb-3">
<v-tooltip v-if="!isEditMode && recipe.recipeYield" small top color="secondary darken-1">
<v-tooltip v-if="!isEditMode" small top color="secondary darken-1">
<template #activator="{ on, attrs }">
<RecipeScaleEditButton
v-model.number="scaleValue"
v-bind="attrs"
:recipe-yield="recipe.recipeYield"
:basic-yield="basicYield"
:scaled-yield="scaledYield"
:basic-yield-num="basicYieldNum"
:edit-scale="!recipe.settings.disableAmount && !isEditMode"
v-on="on"
/>
@ -27,13 +27,13 @@
</template>
<script lang="ts">
import { computed, defineComponent } from "@nuxtjs/composition-api";
import { computed, defineComponent, ref } from "@nuxtjs/composition-api";
import RecipeScaleEditButton from "~/components/Domain/Recipe/RecipeScaleEditButton.vue";
import RecipeRating from "~/components/Domain/Recipe/RecipeRating.vue";
import { NoUndefinedField } from "~/lib/api/types/non-generated";
import { Recipe } from "~/lib/api/types/recipe";
import { usePageState } from "~/composables/recipe-page/shared-state";
import { useExtractRecipeYield } from "~/composables/recipe-page/use-extract-recipe-yield";
import { useExtractRecipeYield, findMatch } from "~/composables/recipe-page/use-extract-recipe-yield";
export default defineComponent({
components: {
@ -70,14 +70,13 @@ export default defineComponent({
return useExtractRecipeYield(props.recipe.recipeYield, scaleValue.value);
});
const basicYield = computed(() => {
return useExtractRecipeYield(props.recipe.recipeYield, 1);
});
const match = findMatch(props.recipe.recipeYield);
const basicYieldNum = ref<number |null>(match ? match[1] : null);
return {
scaleValue,
basicYield,
scaledYield,
basicYieldNum,
isEditMode,
};
},

View File

@ -5,17 +5,22 @@
<v-menu v-model="menu" :disabled="!editScale" offset-y top nudge-top="6" :close-on-content-click="false">
<template #activator="{ on, attrs }">
<v-card class="pa-1 px-2" dark color="secondary darken-1" small v-bind="attrs" v-on="on">
<span v-if="recipeYield"> {{ scaledYield }} </span>
<span v-if="!recipeYield"> x {{ scale }} </span>
<div v-else-if="!numberParsed && recipeYield">
<span v-if="numerator === 1"> {{ recipeYield }} </span>
<span v-else> {{ numerator }}x {{ scaledYield }} </span>
</div>
<span v-else> {{ scaledYield }} </span>
</v-card>
</template>
<v-card min-width="300px">
<v-card-title class="mb-0">
{{ $t("recipe.edit-scale") }}
{{ $t("recipe.servings") }}
</v-card-title>
<v-card-text class="mt-n5">
<div class="mt-4 d-flex align-center">
<v-text-field v-model.number="scale" type="number" :min="0" :label="$t('recipe.edit-scale')" />
<v-text-field v-model="numerator" type="number" :min="0" hide-spin-buttons />
<v-tooltip right color="secondary darken-1">
<template #activator="{ on, attrs }">
<v-btn v-bind="attrs" icon class="mx-1" small v-on="on" @click="scale = 1">
@ -24,7 +29,7 @@
</v-icon>
</v-btn>
</template>
<span> {{ $t("recipe.reset-scale") }} </span>
<span> {{ $t("recipe.reset-servings-count") }} </span>
</v-tooltip>
</div>
</v-card-text>
@ -38,24 +43,25 @@
:buttons="[
{
icon: $globals.icons.minus,
text: $t('recipe.decrease-scale-label'),
text: $tc('recipe.decrease-scale-label'),
event: 'decrement',
disabled: disableDecrement,
},
{
icon: $globals.icons.createAlt,
text: $t('recipe.increase-scale-label'),
text: $tc('recipe.increase-scale-label'),
event: 'increment',
},
]"
@decrement="scale > 1 ? scale-- : null"
@increment="scale++"
@decrement="numerator--"
@increment="numerator++"
/>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs, computed } from "@nuxtjs/composition-api";
import { defineComponent, ref, computed, watch } from "@nuxtjs/composition-api";
export default defineComponent({
props: {
@ -63,12 +69,12 @@ export default defineComponent({
type: String,
default: null,
},
basicYield: {
scaledYield: {
type: String,
default: null,
},
scaledYield: {
type: String,
basicYieldNum: {
type: Number,
default: null,
},
editScale: {
@ -81,10 +87,7 @@ export default defineComponent({
},
},
setup(props, { emit }) {
const state = reactive({
tempScale: 1,
menu: false,
});
const menu = ref<boolean>(false);
const scale = computed({
get: () => props.value,
@ -94,9 +97,24 @@ export default defineComponent({
},
});
const numerator = ref<number>(parseFloat(props.basicYieldNum.toFixed(3)) ?? 1);
const denominator = parseFloat(props.basicYieldNum.toFixed(32)) ?? 1;
const numberParsed = !!props.basicYieldNum;
watch(() => numerator.value, () => {
scale.value = parseFloat((numerator.value / denominator).toFixed(3));
});
const disableDecrement = computed(() => {
return numerator.value <= 1;
});
return {
menu,
scale,
...toRefs(state),
numerator,
disableDecrement,
numberParsed,
};
},
});

View File

@ -39,7 +39,7 @@ function extractServingsFromFraction(fractionString: string): number | undefined
function findMatch(yieldString: string): [matchString: string, servings: number, isFraction: boolean] | null {
export function findMatch(yieldString: string): [matchString: string, servings: number, isFraction: boolean] | null {
if (!yieldString) {
return null;
}

View File

@ -652,7 +652,8 @@
"missing-unit": "Create missing unit: {unit}",
"missing-food": "Create missing food: {food}",
"no-food": "No Food"
}
},
"reset-servings-count": "Reset Servings Count"
},
"search": {
"advanced-search": "Advanced Search",