359 lines
9.9 KiB
Vue
359 lines
9.9 KiB
Vue
<template>
|
|
<q-card>
|
|
<q-card-section>
|
|
<div class="text-h6">Getränk Bearbeiten</div>
|
|
</q-card-section>
|
|
<q-card-section>
|
|
<div class="full-width row">
|
|
<q-input
|
|
v-model="edit_drink.name"
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
|
filled
|
|
label="Name"
|
|
dense
|
|
/>
|
|
<q-select
|
|
v-model="edit_drink.type"
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
|
filled
|
|
label="Kategorie"
|
|
dense
|
|
:options="types"
|
|
option-label="name"
|
|
/>
|
|
</div>
|
|
</q-card-section>
|
|
<q-card-section>
|
|
<q-img :src="image" style="max-height: 256px" fit="contain" />
|
|
<div class="full-width row">
|
|
<div class="col-10 q-pa-sm">
|
|
<q-file
|
|
v-model="drinkPic"
|
|
filled
|
|
clearable
|
|
dense
|
|
@update:model-value="imagePreview"
|
|
@clear="imgsrc = undefined"
|
|
>
|
|
<template #prepend>
|
|
<q-icon name="mdi-image" />
|
|
</template>
|
|
</q-file>
|
|
</div>
|
|
<div class="col-2 q-pa-sm text-right">
|
|
<q-btn round icon="mdi-delete" color="negative" size="sm" @click="delete_pic">
|
|
<q-tooltip> Bild entfernen </q-tooltip>
|
|
</q-btn>
|
|
</div>
|
|
</div>
|
|
</q-card-section>
|
|
<q-card-section>
|
|
<q-select
|
|
v-model="edit_drink.tags"
|
|
multiple
|
|
:options="tags"
|
|
label="Tags"
|
|
option-label="name"
|
|
filled
|
|
dense
|
|
>
|
|
<template #selected-item="item">
|
|
<q-chip
|
|
removable
|
|
:tabindex="item.tabindex"
|
|
:style="`background-color: ${item.opt.color}`"
|
|
@remove="item.removeAtIndex(item.index)"
|
|
>
|
|
{{ item.opt.name }}
|
|
</q-chip>
|
|
</template>
|
|
<template #option="item">
|
|
<q-item v-bind="item.itemProps" v-on="item.itemEvents">
|
|
<q-chip :style="`background-color: ${item.opt.color}`">
|
|
<q-avatar v-if="item.selected" icon="mdi-check" color="positive" text-color="white" />
|
|
{{ item.opt.name }}
|
|
</q-chip>
|
|
</q-item>
|
|
</template>
|
|
</q-select>
|
|
</q-card-section>
|
|
<q-card-section>
|
|
<div class="fit row">
|
|
<q-input
|
|
v-model="edit_drink.article_id"
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
|
filled
|
|
label="Artikelnummer"
|
|
dense
|
|
/>
|
|
<q-input
|
|
v-model="edit_drink.volume"
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
|
filled
|
|
label="Inhalt"
|
|
dense
|
|
suffix="L"
|
|
/>
|
|
<q-input
|
|
v-model="edit_drink.package_size"
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
|
filled
|
|
label="Gebindegröße"
|
|
dense
|
|
/>
|
|
<q-input
|
|
v-model="edit_drink.cost_per_package"
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
|
filled
|
|
label="Preis Gebinde"
|
|
suffix="€"
|
|
dense
|
|
/>
|
|
<q-input
|
|
v-model="cost_per_volume"
|
|
class="col-xs-12 col-sm-6 q-pa-sm q-pb-lg"
|
|
:outlined="auto_cost_per_volume || hasIngredients"
|
|
:filled="!auto_cost_per_volume && !hasIngredients"
|
|
:readonly="auto_cost_per_volume || hasIngredients"
|
|
label="Preis pro L"
|
|
hint="Inkl. 19% Mehrwertsteuer"
|
|
suffix="€"
|
|
dense
|
|
/>
|
|
</div>
|
|
</q-card-section>
|
|
<q-card-section :key="key">
|
|
<drink-price-volumes
|
|
v-model="edit_volumes"
|
|
:cost-per-volume="cost_per_volume"
|
|
:editable="hasPermission(PERMISSIONS.EDIT_VOLUME)"
|
|
@update="updateVolume"
|
|
@delete-volume="deleteVolume"
|
|
@delete-price="deletePrice"
|
|
@delete-ingredient="deleteIngredient"
|
|
/>
|
|
</q-card-section>
|
|
<q-card-section>
|
|
<build-manual :steps="edit_drink.receipt" @deleteStep="deleteStep" @addStep="addStep" />
|
|
</q-card-section>
|
|
<q-card-actions class="justify-around">
|
|
<q-btn label="Abbrechen" @click="cancel" />
|
|
<!--<q-btn v-if="can_delete" label="Löschen" color="negative" @click="delete_drink" />-->
|
|
<q-btn label="Löschen" color="negative" @click="delete_drink" />
|
|
<q-btn label="Speichern" color="primary" @click="save" />
|
|
</q-card-actions>
|
|
</q-card>
|
|
</template>
|
|
<script lang="ts">
|
|
import { clone, calc_min_prices, DeleteObjects, calc_cost_per_volume } from '../utils/utils';
|
|
import { defineComponent, PropType, ref, onBeforeMount, computed } from 'vue';
|
|
import DrinkPriceVolumes from './CalculationTable/DrinkPriceVolumes.vue';
|
|
import BuildManual from '../components/CalculationTable/BuildManual.vue';
|
|
import { Drink, DrinkPriceVolume, usePricelistStore } from '../store';
|
|
import { api, hasPermission } from '@flaschengeist/api';
|
|
import { PERMISSIONS } from '../permissions';
|
|
|
|
export default defineComponent({
|
|
name: 'DrinkModify',
|
|
components: { BuildManual, DrinkPriceVolumes },
|
|
props: {
|
|
drink: {
|
|
type: Object as PropType<Drink>,
|
|
required: true,
|
|
},
|
|
},
|
|
emits: {
|
|
save: (
|
|
drink: Drink,
|
|
toDeleteObjects: DeleteObjects,
|
|
drinkPic: File | undefined,
|
|
deletePic: boolean
|
|
) => (drink && toDeleteObjects) || drinkPic || deletePic,
|
|
delete: () => true,
|
|
cancel: () => true,
|
|
},
|
|
setup(props, { emit }) {
|
|
onBeforeMount(() => {
|
|
//edit_drink.value = <Drink>JSON.parse(JSON.stringify(props.drink));
|
|
edit_volumes.value = clone(props.drink.volumes);
|
|
});
|
|
|
|
const key = ref(0);
|
|
|
|
const store = usePricelistStore();
|
|
|
|
const toDeleteObjects = ref<DeleteObjects>({
|
|
prices: [],
|
|
volumes: [],
|
|
ingredients: [],
|
|
});
|
|
|
|
const edit_drink = ref<Drink>(clone(props.drink));
|
|
const edit_volumes = ref<Array<DrinkPriceVolume>>([]);
|
|
function save() {
|
|
(<Drink>edit_drink.value).volumes = edit_volumes.value;
|
|
edit_drink.value.cost_per_volume = calc_cost_per_volume(edit_drink.value);
|
|
edit_drink.value._cost_per_volume = edit_drink.value.cost_per_volume;
|
|
emit('save', <Drink>edit_drink.value, toDeleteObjects.value, drinkPic.value, deletePic.value);
|
|
}
|
|
|
|
function cancel() {
|
|
emit('cancel');
|
|
}
|
|
function updateVolume(index: number) {
|
|
if (index > -1 && edit_volumes.value) {
|
|
edit_volumes.value[index].min_prices = calc_min_prices(
|
|
edit_volumes.value[index],
|
|
//edit_drink.value.cost_per_volume,
|
|
cost_per_volume.value,
|
|
store.min_prices
|
|
);
|
|
}
|
|
}
|
|
|
|
function updateVolumes() {
|
|
setTimeout(() => {
|
|
edit_volumes.value?.forEach((_, index) => {
|
|
updateVolume(index);
|
|
});
|
|
key.value++;
|
|
}, 50);
|
|
}
|
|
|
|
function deletePrice(price: FG.DrinkPrice) {
|
|
toDeleteObjects.value.prices.push(price);
|
|
}
|
|
|
|
function deleteVolume(volume: DrinkPriceVolume) {
|
|
toDeleteObjects.value.volumes.push(volume);
|
|
}
|
|
|
|
function deleteIngredient(ingredient: FG.Ingredient) {
|
|
toDeleteObjects.value.ingredients.push(ingredient);
|
|
}
|
|
|
|
function addStep(event: string) {
|
|
edit_drink.value?.receipt?.push(event);
|
|
}
|
|
|
|
function deleteStep(event: number) {
|
|
edit_drink.value?.receipt?.splice(event, 1);
|
|
}
|
|
|
|
const drinkPic = ref();
|
|
const imgsrc = ref();
|
|
|
|
const deletePic = ref(false);
|
|
|
|
function delete_pic() {
|
|
deletePic.value = true;
|
|
imgsrc.value = undefined;
|
|
drinkPic.value = undefined;
|
|
if (edit_drink.value) {
|
|
edit_drink.value.has_image = false;
|
|
}
|
|
}
|
|
|
|
function imagePreview() {
|
|
if (drinkPic.value && drinkPic.value instanceof File) {
|
|
let reader = new FileReader();
|
|
|
|
reader.onload = (e) => {
|
|
imgsrc.value = e.target?.result;
|
|
};
|
|
|
|
reader.readAsDataURL(drinkPic.value);
|
|
}
|
|
}
|
|
|
|
const image = computed(() => {
|
|
console.log(imgsrc.value, deletePic.value, edit_drink.value);
|
|
if (deletePic.value) {
|
|
return 'no-image.svg';
|
|
}
|
|
if (imgsrc.value) {
|
|
return <string>imgsrc.value;
|
|
}
|
|
if (edit_drink.value?.has_image) {
|
|
return `${api.defaults.baseURL || ''}/pricelist/drinks/${
|
|
edit_drink.value.id
|
|
}/picture?thumbnail?t=${new Date()}`;
|
|
}
|
|
return 'no-image.svg';
|
|
});
|
|
|
|
const can_delete = computed(() => {
|
|
if (edit_drink.value) {
|
|
if (edit_drink.value.id < 0) {
|
|
return false;
|
|
}
|
|
const _edit_drink = edit_drink.value;
|
|
const test = _edit_drink.volumes ? _edit_drink.volumes.length === 0 : true;
|
|
console.log(test);
|
|
return test;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
function delete_drink() {
|
|
emit('delete');
|
|
}
|
|
|
|
const auto_cost_per_volume = computed(
|
|
() =>
|
|
!!(
|
|
edit_drink.value?.cost_per_package &&
|
|
edit_drink.value?.package_size &&
|
|
edit_drink.value?.volume
|
|
)
|
|
);
|
|
|
|
const cost_per_volume = computed({
|
|
get: () => {
|
|
let retVal: number;
|
|
if (auto_cost_per_volume.value) {
|
|
retVal = <number>calc_cost_per_volume(<Drink>edit_drink.value);
|
|
} else {
|
|
retVal = <number>(<Drink>edit_drink.value).cost_per_volume;
|
|
}
|
|
updateVolumes();
|
|
return retVal;
|
|
},
|
|
set: (val: number) => ((<Drink>edit_drink.value).cost_per_volume = val),
|
|
});
|
|
|
|
const hasIngredients = computed(() =>
|
|
edit_volumes.value?.some((a) => a.ingredients.length > 0)
|
|
);
|
|
|
|
return {
|
|
edit_drink,
|
|
save,
|
|
cancel,
|
|
updateVolume,
|
|
deletePrice,
|
|
deleteIngredient,
|
|
deleteVolume,
|
|
addStep,
|
|
deleteStep,
|
|
tags: computed(() => store.tags),
|
|
image,
|
|
imgsrc,
|
|
drinkPic,
|
|
imagePreview,
|
|
delete_pic,
|
|
types: computed(() => store.drinkTypes),
|
|
can_delete,
|
|
delete_drink,
|
|
auto_cost_per_volume,
|
|
cost_per_volume,
|
|
edit_volumes,
|
|
key,
|
|
hasIngredients,
|
|
hasPermission,
|
|
PERMISSIONS,
|
|
};
|
|
},
|
|
});
|
|
</script>
|