315 lines
9.8 KiB
Vue
315 lines
9.8 KiB
Vue
<template>
|
|
<div class="full-width">
|
|
<div
|
|
v-for="ingredient in edit_ingredients"
|
|
:key="`ingredient:${ingredient.id}`"
|
|
class="full-width row justify-evenly q-py-xs"
|
|
>
|
|
<div class="full-width row justify-evenly">
|
|
<div v-if="ingredient.drink_ingredient" class="col">
|
|
<div class="full-width row justify-evenly q-py-xs">
|
|
<div class="col">
|
|
<!--{{ get_drink_ingredient_name(ingredient.drink_ingredient.ingredient_id) }}-->
|
|
{{ ingredient.drink_ingredient.name }}
|
|
<q-popup-edit
|
|
v-if="editable"
|
|
v-slot="scope"
|
|
v-model="ingredient.drink_ingredient.ingredient_id"
|
|
buttons
|
|
label-cancel="Abbrechen"
|
|
label-set="Speichern"
|
|
@save="updateValue"
|
|
>
|
|
<q-select
|
|
v-model="scope.ingredient_id"
|
|
class="col q-px-sm"
|
|
label="Getränk"
|
|
filled
|
|
dense
|
|
use-input
|
|
@filter="filter_drinks"
|
|
:options="drinks"
|
|
option-label="name"
|
|
option-value="id"
|
|
emit-value
|
|
map-options
|
|
/>
|
|
</q-popup-edit>
|
|
</div>
|
|
<div class="col">
|
|
{{ ingredient.drink_ingredient.volume.toFixed(3) }}L
|
|
<q-popup-edit
|
|
v-if="editable"
|
|
v-slot="scope"
|
|
v-model="ingredient.drink_ingredient.volume"
|
|
buttons
|
|
label-cancel="Abbrechen"
|
|
label-set="Speichern"
|
|
@save="updateValue"
|
|
>
|
|
<q-input
|
|
v-model.number="scope.value"
|
|
class="col q-px-sm"
|
|
label="Volume"
|
|
type="number"
|
|
filled
|
|
dense
|
|
suffix="L"
|
|
step="0.01"
|
|
min="0"
|
|
/>
|
|
</q-popup-edit>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-else-if="ingredient.extra_ingredient" class="col">
|
|
<div class="full-width row justify-evenly q-py-xs">
|
|
<div class="col">
|
|
{{ ingredient.extra_ingredient.name }}
|
|
</div>
|
|
<div class="col">{{ ingredient.extra_ingredient.price.toFixed(3) }}€</div>
|
|
</div>
|
|
<q-popup-edit
|
|
v-if="editable"
|
|
v-model="ingredient.extra_ingredient"
|
|
buttons
|
|
label-cancel="Abbrechen"
|
|
label-set="Speichern"
|
|
@save="updateValue"
|
|
>
|
|
<q-select
|
|
v-model="ingredient.extra_ingredient"
|
|
filled
|
|
dense
|
|
use-input
|
|
@filter="filter_extra_ingredients"
|
|
:options="extra_ingredients"
|
|
option-label="name"
|
|
/>
|
|
</q-popup-edit>
|
|
</div>
|
|
<div v-if="editable" class="col-1 row justify-end q-pa-xs">
|
|
<q-btn
|
|
icon="mdi-delete"
|
|
round
|
|
size="xs"
|
|
color="negative"
|
|
@click="deleteIngredient(ingredient)"
|
|
>
|
|
<q-tooltip> Zutat entfernen </q-tooltip>
|
|
</q-btn>
|
|
</div>
|
|
</div>
|
|
<q-separator />
|
|
</div>
|
|
<div v-if="editable" class="full-width row justify-end q-py-xs">
|
|
<q-btn size="sm" round icon="mdi-plus" color="primary">
|
|
<q-tooltip> Neue Zutat hinzufügen </q-tooltip>
|
|
<q-menu anchor="center middle" self="center middle" persistent>
|
|
<div class="full-width row justify-around q-gutter-sm q-pa-sm">
|
|
<div class="col">
|
|
<q-select
|
|
v-model="newIngredient"
|
|
filled
|
|
dense
|
|
use-input
|
|
label="Zutat"
|
|
:options="[...drinks, ...extra_ingredients]"
|
|
@filter="filter"
|
|
option-label="name"
|
|
/>
|
|
</div>
|
|
<div class="col">
|
|
<q-slide-transition>
|
|
<q-input
|
|
v-if="newIngredient && newIngredient.volume"
|
|
v-model.number="newIngredientVolume"
|
|
filled
|
|
dense
|
|
label="Volume"
|
|
type="number"
|
|
step="0.01"
|
|
min="0"
|
|
suffix="L"
|
|
/>
|
|
</q-slide-transition>
|
|
<q-slide-transition>
|
|
<q-input
|
|
v-if="newIngredient && newIngredient.price"
|
|
v-model="newIngredient.price"
|
|
filled
|
|
dense
|
|
label="Preis"
|
|
disable
|
|
min="0"
|
|
step="0.1"
|
|
fill-mask="0"
|
|
mask="#.##"
|
|
suffix="€"
|
|
/>
|
|
</q-slide-transition>
|
|
</div>
|
|
</div>
|
|
<div class="full-width row justify-around q-gutter-sm q-pa-sm">
|
|
<q-btn v-close-popup flat label="Abbrechen" @click="cancelAddIngredient" />
|
|
<q-btn v-close-popup flat label="Speichern" color="primary" @click="addIngredient" />
|
|
</div>
|
|
</q-menu>
|
|
</q-btn>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { computed, defineComponent, PropType, ref, onBeforeMount, unref } from 'vue';
|
|
import { usePricelistStore, Drink } from '../../store';
|
|
import { clone } from '../../utils/utils';
|
|
|
|
export default defineComponent({
|
|
name: 'Ingredients',
|
|
props: {
|
|
modelValue: {
|
|
type: Object as PropType<Array<FG.Ingredient>>,
|
|
required: true,
|
|
},
|
|
editable: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
},
|
|
emits: {
|
|
'update:modelValue': (val: Array<FG.Ingredient>) => val,
|
|
update: () => true,
|
|
'delete-ingredient': (val: FG.Ingredient) => val,
|
|
},
|
|
setup(props, { emit }) {
|
|
onBeforeMount(() => {
|
|
//edit_ingredients.value = <Array<FG.Ingredient>>JSON.parse(JSON.stringify(props.modelValue))
|
|
//edit_ingredients.value = props.modelValue
|
|
edit_ingredients.value = clone(props.modelValue);
|
|
});
|
|
|
|
const store = usePricelistStore();
|
|
|
|
const edit_ingredients = ref<Array<FG.Ingredient>>([]);
|
|
const newIngredient = ref<FG.Drink | FG.ExtraIngredient>();
|
|
const newIngredientVolume = ref<number>(0);
|
|
function addIngredient() {
|
|
let _ingredient: FG.Ingredient;
|
|
if ((<FG.Drink>newIngredient.value)?.volume && newIngredient.value) {
|
|
_ingredient = {
|
|
id: -1,
|
|
drink_ingredient: {
|
|
id: -1,
|
|
ingredient_id: newIngredient.value.id,
|
|
volume: newIngredientVolume.value,
|
|
cost_per_volume: <number>(<FG.Drink>newIngredient.value).cost_per_volume,
|
|
name: newIngredient.value.name,
|
|
},
|
|
extra_ingredient: undefined,
|
|
};
|
|
} else {
|
|
_ingredient = {
|
|
id: -1,
|
|
drink_ingredient: undefined,
|
|
extra_ingredient: <FG.ExtraIngredient>newIngredient.value,
|
|
};
|
|
}
|
|
edit_ingredients.value.push(_ingredient);
|
|
emit('update:modelValue', unref(edit_ingredients));
|
|
update();
|
|
cancelAddIngredient();
|
|
}
|
|
|
|
function updateValue(value: number, initValue: number) {
|
|
console.log('updateValue', value, initValue);
|
|
emit('update:modelValue', unref(edit_ingredients));
|
|
update();
|
|
}
|
|
|
|
function cancelAddIngredient() {
|
|
setTimeout(() => {
|
|
(newIngredient.value = undefined), (newIngredientVolume.value = 0);
|
|
}, 200);
|
|
}
|
|
function deleteIngredient(ingredient: FG.Ingredient) {
|
|
const index = edit_ingredients.value.findIndex((a) => a.id === ingredient.id);
|
|
if (index > -1) {
|
|
if (edit_ingredients.value[index].id > 0) {
|
|
emit('delete-ingredient', edit_ingredients.value[index]);
|
|
}
|
|
edit_ingredients.value.splice(index, 1);
|
|
}
|
|
emit('update:modelValue', unref(edit_ingredients));
|
|
update();
|
|
}
|
|
const drinks = ref<Array<Drink>>([]);
|
|
const _extra_ingredients = computed(() => store.extraIngredients);
|
|
const extra_ingredients = ref(_extra_ingredients.value);
|
|
|
|
async function filter_drinks(val: string, update: (a: () => void) => void) {
|
|
let result = <Array<Drink>>[];
|
|
if (val === '') {
|
|
result = await store.getDrinks_no_store({ limit: 5, ingredient: true });
|
|
} else {
|
|
result = await store.getDrinks_no_store({
|
|
limit: 5,
|
|
search_name: val,
|
|
search_key: 'name',
|
|
ingredient: true,
|
|
});
|
|
}
|
|
update(() => {
|
|
drinks.value = result;
|
|
});
|
|
}
|
|
function filter_extra_ingredients(val: string, update: (a: () => void) => void) {
|
|
if (val === '') {
|
|
update(() => {
|
|
extra_ingredients.value = _extra_ingredients.value;
|
|
});
|
|
} else {
|
|
update(() => {
|
|
extra_ingredients.value = _extra_ingredients.value.filter((ingredient) => {
|
|
return ingredient.name.toLowerCase().includes(val.toLowerCase());
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
async function filter(val: string, update: () => void) {
|
|
await filter_drinks(val, update);
|
|
filter_extra_ingredients(val, update);
|
|
}
|
|
|
|
function get_drink_ingredient_name(id: number) {
|
|
return store.drinks.find((a) => a.id === id)?.name;
|
|
}
|
|
|
|
function update() {
|
|
setTimeout(() => {
|
|
emit('update');
|
|
}, 50);
|
|
}
|
|
|
|
return {
|
|
addIngredient,
|
|
drinks,
|
|
extra_ingredients,
|
|
newIngredient,
|
|
newIngredientVolume,
|
|
cancelAddIngredient,
|
|
updateValue,
|
|
deleteIngredient,
|
|
get_drink_ingredient_name,
|
|
edit_ingredients,
|
|
filter,
|
|
filter_drinks,
|
|
filter_extra_ingredients,
|
|
};
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style scoped></style>
|