mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-12-24 19:25:13 -05:00
feat: Replace number inputs with new v-number-input compontent (#6767)
This commit is contained in:
@@ -144,11 +144,13 @@
|
||||
variant="underlined"
|
||||
@update:model-value="setFieldValue(field, index, $event)"
|
||||
/>
|
||||
<v-text-field
|
||||
<v-number-input
|
||||
v-else-if="field.type === 'number'"
|
||||
:model-value="field.value"
|
||||
type="number"
|
||||
variant="underlined"
|
||||
control-variant="stacked"
|
||||
inset
|
||||
:precision="null"
|
||||
@update:model-value="setFieldValue(field, index, $event)"
|
||||
/>
|
||||
<v-checkbox
|
||||
|
||||
@@ -22,12 +22,15 @@
|
||||
cols="12"
|
||||
class="flex-grow-0 flex-shrink-0"
|
||||
>
|
||||
<v-text-field
|
||||
<v-number-input
|
||||
v-model="model.quantity"
|
||||
variant="solo"
|
||||
:precision="null"
|
||||
:min="0"
|
||||
hide-details
|
||||
control-variant="stacked"
|
||||
inset
|
||||
density="compact"
|
||||
type="number"
|
||||
:placeholder="$t('recipe.quantity')"
|
||||
@keypress="quantityFilter"
|
||||
>
|
||||
@@ -38,7 +41,7 @@
|
||||
{{ $globals.icons.arrowUpDown }}
|
||||
</v-icon>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</v-number-input>
|
||||
</v-col>
|
||||
<v-col
|
||||
v-if="!state.isRecipe"
|
||||
|
||||
@@ -10,14 +10,17 @@
|
||||
v-for="(item, key, index) in modelValue"
|
||||
:key="index"
|
||||
>
|
||||
<v-text-field
|
||||
density="compact"
|
||||
<v-number-input
|
||||
:model-value="modelValue[key]"
|
||||
:label="labels[key].label"
|
||||
:suffix="labels[key].suffix"
|
||||
type="number"
|
||||
density="compact"
|
||||
autocomplete="off"
|
||||
variant="underlined"
|
||||
control-variant="stacked"
|
||||
inset
|
||||
:precision="null"
|
||||
:min="0"
|
||||
@update:model-value="updateValue(key, $event)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -11,27 +11,27 @@
|
||||
<v-container class="ma-0 pa-0">
|
||||
<v-row>
|
||||
<v-col cols="3">
|
||||
<v-text-field
|
||||
:model-value="recipeServings"
|
||||
type="number"
|
||||
<v-number-input
|
||||
:model-value="recipe.recipeServings"
|
||||
:min="0"
|
||||
hide-spin-buttons
|
||||
:precision="null"
|
||||
density="compact"
|
||||
:label="$t('recipe.servings')"
|
||||
variant="underlined"
|
||||
@update:model-value="validateInput($event, 'recipeServings')"
|
||||
control-variant="hidden"
|
||||
@update:model-value="recipe.recipeServings = $event"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="3">
|
||||
<v-text-field
|
||||
:model-value="recipeYieldQuantity"
|
||||
type="number"
|
||||
<v-number-input
|
||||
:model-value="recipe.recipeYieldQuantity"
|
||||
:min="0"
|
||||
hide-spin-buttons
|
||||
:precision="null"
|
||||
density="compact"
|
||||
:label="$t('recipe.yield')"
|
||||
variant="underlined"
|
||||
@update:model-value="validateInput($event, 'recipeYieldQuantity')"
|
||||
control-variant="hidden"
|
||||
@update:model-value="recipe.recipeYieldQuantity = $event"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
@@ -85,37 +85,4 @@ import type { NoUndefinedField } from "~/lib/api/types/non-generated";
|
||||
import type { Recipe } from "~/lib/api/types/recipe";
|
||||
|
||||
const recipe = defineModel<NoUndefinedField<Recipe>>({ required: true });
|
||||
|
||||
const recipeServings = computed<number>({
|
||||
get() {
|
||||
return recipe.value.recipeServings;
|
||||
},
|
||||
set(val) {
|
||||
validateInput(val.toString(), "recipeServings");
|
||||
},
|
||||
});
|
||||
|
||||
const recipeYieldQuantity = computed<number>({
|
||||
get() {
|
||||
return recipe.value.recipeYieldQuantity;
|
||||
},
|
||||
set(val) {
|
||||
validateInput(val.toString(), "recipeYieldQuantity");
|
||||
},
|
||||
});
|
||||
|
||||
function validateInput(value: string | null, property: "recipeServings" | "recipeYieldQuantity") {
|
||||
if (!value) {
|
||||
recipe.value[property] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const number = parseFloat(value.replace(/[^0-9.]/g, ""));
|
||||
if (isNaN(number) || number <= 0) {
|
||||
recipe.value[property] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
recipe.value[property] = number;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -65,13 +65,13 @@
|
||||
</v-card-title>
|
||||
<v-card-text class="mt-n5">
|
||||
<div class="mt-4 d-flex align-center">
|
||||
<v-text-field
|
||||
<v-number-input
|
||||
:model-value="yieldQuantity"
|
||||
type="number"
|
||||
:precision="null"
|
||||
:min="0"
|
||||
variant="underlined"
|
||||
hide-spin-buttons
|
||||
@update:model-value="recalculateScale(parseFloat($event) || 0)"
|
||||
control-variant="hidden"
|
||||
@update:model-value="recalculateScale($event || 0)"
|
||||
/>
|
||||
<v-tooltip
|
||||
location="end"
|
||||
|
||||
@@ -4,7 +4,19 @@
|
||||
<v-card-text class="pb-3 pt-1">
|
||||
<div class="d-md-flex align-center mb-2" style="gap: 20px">
|
||||
<div>
|
||||
<InputQuantity v-model="listItem.quantity" />
|
||||
<v-number-input
|
||||
v-model="listItem.quantity"
|
||||
hide-details
|
||||
:label="$t('form.quantity-label-abbreviated')"
|
||||
:min="0"
|
||||
:precision="null"
|
||||
variant="plain"
|
||||
control-variant="stacked"
|
||||
inset
|
||||
density="compact"
|
||||
class="centered-number-input"
|
||||
style="width: 100px;"
|
||||
/>
|
||||
</div>
|
||||
<InputLabelType
|
||||
v-model="listItem.unit"
|
||||
@@ -158,6 +170,15 @@ export default defineNuxtComponent({
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.modelValue.quantity,
|
||||
() => {
|
||||
if (!props.modelValue.quantity) {
|
||||
listItem.value.quantity = 0;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.modelValue.food,
|
||||
(newFood) => {
|
||||
@@ -221,3 +242,10 @@ export default defineNuxtComponent({
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.centered-number-input :deep(.v-field) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
class="d-flex align-center"
|
||||
style="max-width: 60px"
|
||||
>
|
||||
<v-text-field
|
||||
v-model.number="quantity"
|
||||
hide-details
|
||||
:label="$t('form.quantity-label-abbreviated')"
|
||||
:min="min"
|
||||
:max="max"
|
||||
type="number"
|
||||
variant="plain"
|
||||
density="compact"
|
||||
style="width: 60px;"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineNuxtComponent({
|
||||
name: "VInputNumber",
|
||||
props: {
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 9999,
|
||||
},
|
||||
rules: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
modelValue: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
setup(props, context) {
|
||||
const quantity = computed({
|
||||
get: () => {
|
||||
return Number(props.modelValue);
|
||||
},
|
||||
set: (val) => {
|
||||
context.emit("update:modelValue", val);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
quantity,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user