release v2.0.0 #4
|
@ -47,314 +47,6 @@
|
|||
/>
|
||||
</div>
|
||||
</template>
|
||||
<!--<template #body="drinks_props">
|
||||
<q-tr :props="drinks_props">
|
||||
<q-td auto-width>
|
||||
<q-btn
|
||||
v-if="drinks_props.row.volumes.length === 0"
|
||||
size="xs"
|
||||
color="negative"
|
||||
round
|
||||
dense
|
||||
icon="mdi-delete"
|
||||
class="q-mx-sm"
|
||||
@click="deleteDrink(drinks_props.row)"
|
||||
/>
|
||||
</q-td>
|
||||
<q-td key="picture" :props="drinks_props" style="min-width: 256px">
|
||||
<q-img
|
||||
loading="lazy"
|
||||
:src="
|
||||
drinks_props.row.uuid
|
||||
? `/api/pricelist/picture/${drinks_props.row.uuid}?size=256`
|
||||
: 'no-image.svg'
|
||||
"
|
||||
placeholder-src="no-image.svg"
|
||||
>
|
||||
<template #error>
|
||||
<div class="absolute-full flex flex-center bg-negative text-white">
|
||||
Cannot load image
|
||||
</div>
|
||||
</template>
|
||||
</q-img>
|
||||
<q-popup-edit v-model="drinkPic" @update:modelValue="savePicture(drinks_props.row)">
|
||||
<template #default="scope">
|
||||
<div class="full-width row">
|
||||
<q-file v-model="scope.value" filled>
|
||||
<template #prepend>
|
||||
<q-icon name="attach_file" />
|
||||
</template>
|
||||
</q-file>
|
||||
<div class="full-width row justify-between">
|
||||
<q-btn label="Abbrechen" flat color="primary" @click="scope.cancel" />
|
||||
<q-btn
|
||||
label="Löschen"
|
||||
flat
|
||||
color="primary"
|
||||
@click="
|
||||
scope.cancel();
|
||||
deletePicture(drinks_props.row);
|
||||
"
|
||||
/>
|
||||
<q-btn label="Speichern" flat color="primary" @click="scope.set" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</q-popup-edit>
|
||||
</q-td>
|
||||
<q-td key="name" :props="drinks_props">
|
||||
{{ drinks_props.row.name }}
|
||||
<q-popup-edit
|
||||
v-slot="scope"
|
||||
v-model="drinks_props.row.name"
|
||||
buttons
|
||||
label-cancel="Abbrechen"
|
||||
label-set="Speichern"
|
||||
@update:modelValue="updateDrink(drinks_props.row)"
|
||||
>
|
||||
<q-input
|
||||
v-model="scope.value"
|
||||
filled
|
||||
dense
|
||||
autofocus
|
||||
clearable
|
||||
@keyup.enter="scope.set"
|
||||
/>
|
||||
</q-popup-edit>
|
||||
</q-td>
|
||||
<q-td key="drink_type" :props="drinks_props">
|
||||
{{ drinks_props.row.type.name }}
|
||||
<q-popup-edit
|
||||
v-slot="scope"
|
||||
v-model="drinks_props.row.type"
|
||||
buttons
|
||||
label-cancel="Abbrechen"
|
||||
label-set="Speichern"
|
||||
@update:modelValue="updateDrink(drinks_props.row)"
|
||||
>
|
||||
<q-select
|
||||
v-model="scope.value"
|
||||
:options="drinkTypes"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
filled
|
||||
dense
|
||||
autofocus
|
||||
@keyup.enter="scope.set"
|
||||
/>
|
||||
</q-popup-edit>
|
||||
</q-td>
|
||||
<q-td key="tags" :props="drinks_props">
|
||||
<q-badge
|
||||
v-for="tag in drinks_props.row.tags"
|
||||
:key="`${drinks_props.row.id}-${tag.id}`"
|
||||
class="q-ma-xs"
|
||||
rounded
|
||||
:style="`background-color: ${tag.color}`"
|
||||
>
|
||||
{{ tag.name }}
|
||||
</q-badge>
|
||||
<q-popup-edit
|
||||
v-model="drinks_props.row.tags"
|
||||
buttons
|
||||
label-cancel="Abbrechen"
|
||||
label-set="Speichern"
|
||||
@update:modelValue="updateDrink(drinks_props.row)"
|
||||
>
|
||||
<template #default="scope">
|
||||
<q-select
|
||||
v-model="scope.value"
|
||||
multiple
|
||||
:options="tags"
|
||||
label="Tags"
|
||||
option-label="name"
|
||||
filled
|
||||
>
|
||||
<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>
|
||||
</template>
|
||||
</q-popup-edit>
|
||||
</q-td>
|
||||
<q-td key="article_id" :props="drinks_props">
|
||||
{{ drinks_props.row.article_id || 'o.A.' }}
|
||||
<q-popup-edit
|
||||
v-slot="scope"
|
||||
v-model="drinks_props.row.article_id"
|
||||
buttons
|
||||
label-cancel="Abbrechen"
|
||||
label-set="Speichern"
|
||||
@update:modelValue="updateDrink(drinks_props.row)"
|
||||
>
|
||||
<q-input
|
||||
v-model="scope.value"
|
||||
filled
|
||||
dense
|
||||
autofocus
|
||||
clearable
|
||||
@keyup.enter="scope.set"
|
||||
/>
|
||||
</q-popup-edit>
|
||||
</q-td>
|
||||
<q-td key="volume_package" :props="drinks_props">
|
||||
{{ drinks_props.row.volume ? `${drinks_props.row.volume} L` : 'o.A.' }}
|
||||
<q-popup-edit
|
||||
v-if="
|
||||
!drinks_props.row.volumes.some((volume) =>
|
||||
volume.ingredients.some((ingredient) => ingredient.drink_ingredient)
|
||||
)
|
||||
"
|
||||
v-slot="scope"
|
||||
v-model.number="drinks_props.row.volume"
|
||||
buttons
|
||||
label-cancel="Abbrechen"
|
||||
label-set="Speichern"
|
||||
@update:modelValue="updateDrink(drinks_props.row)"
|
||||
>
|
||||
<q-input
|
||||
v-model.number="scope.value"
|
||||
filled
|
||||
dense
|
||||
autofocus
|
||||
type="number"
|
||||
clearable
|
||||
step="0.01"
|
||||
min="0"
|
||||
suffix="L"
|
||||
@keyup.enter="scope.set"
|
||||
/>
|
||||
</q-popup-edit>
|
||||
</q-td>
|
||||
<q-td key="package_size" :props="drinks_props">
|
||||
{{ drinks_props.row.package_size || 'o.A.' }}
|
||||
<q-popup-edit
|
||||
v-if="
|
||||
!drinks_props.row.volumes.some((volume) =>
|
||||
volume.ingredients.some((ingredient) => ingredient.drink_ingredient)
|
||||
)
|
||||
"
|
||||
v-slot="scope"
|
||||
v-model="drinks_props.row.package_size"
|
||||
buttons
|
||||
label-cancel="Abbrechen"
|
||||
label-set="Speichern"
|
||||
@update:modelValue="updateDrink(drinks_props.row)"
|
||||
>
|
||||
<q-input
|
||||
v-model.number="scope.value"
|
||||
filled
|
||||
dense
|
||||
autofocus
|
||||
type="number"
|
||||
min="0"
|
||||
@keyup.enter="scope.set"
|
||||
/>
|
||||
</q-popup-edit>
|
||||
</q-td>
|
||||
<q-td key="cost_per_package" :props="drinks_props">
|
||||
{{
|
||||
drinks_props.row.cost_per_package
|
||||
? `${drinks_props.row.cost_per_package.toFixed(2)}€`
|
||||
: 'o.A.'
|
||||
}}
|
||||
<q-popup-edit
|
||||
v-if="
|
||||
!drinks_props.row.volumes.some((volume) =>
|
||||
volume.ingredients.some((ingredient) => ingredient.drink_ingredient)
|
||||
)
|
||||
"
|
||||
v-slot="scope"
|
||||
v-model="drinks_props.row.cost_per_package"
|
||||
buttons
|
||||
label-cancel="Abbrechen"
|
||||
label-set="Speichern"
|
||||
@update:modelValue="updateDrink(drinks_props.row)"
|
||||
>
|
||||
<q-input
|
||||
v-model.number="scope.value"
|
||||
filled
|
||||
dense
|
||||
autofocus
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
suffix="€"
|
||||
@keyup.enter="scope.set"
|
||||
/>
|
||||
</q-popup-edit>
|
||||
</q-td>
|
||||
<q-td key="cost_per_volume" :props="drinks_props">
|
||||
{{
|
||||
drinks_props.row.cost_per_volume
|
||||
? `${drinks_props.row.cost_per_volume.toFixed(3)}€`
|
||||
: 'o.A.'
|
||||
}}
|
||||
<q-popup-edit
|
||||
v-if="
|
||||
!(
|
||||
!!drinks_props.row.cost_per_package &&
|
||||
!!drinks_props.row.volume &&
|
||||
!!drinks_props.row.package_size
|
||||
) &&
|
||||
!drinks_props.row.volumes.some((volume) =>
|
||||
volume.ingredients.some((ingredient) => ingredient.drink_ingredient)
|
||||
)
|
||||
"
|
||||
v-slot="scope"
|
||||
v-model="drinks_props.row.cost_per_volume"
|
||||
buttons
|
||||
label-cancel="Abbrechen"
|
||||
label-set="Speichern"
|
||||
@update:modelValue="updateDrink(drinks_props.row)"
|
||||
>
|
||||
<q-input
|
||||
v-model.number="scope.value"
|
||||
filled
|
||||
dense
|
||||
autofocus
|
||||
type="number"
|
||||
min="0"
|
||||
step="0.1"
|
||||
suffix="€"
|
||||
@keyup.enter="scope.set"
|
||||
/>
|
||||
</q-popup-edit>
|
||||
</q-td>
|
||||
<q-td key="volumes" :props="drinks_props">
|
||||
<drink-price-volumes-table
|
||||
:rows="drinks_props.row.volumes"
|
||||
:visible-columns="visibleColumn"
|
||||
:columns="column_calc"
|
||||
:drink="drinks_props.row"
|
||||
@updateDrink="updateDrink(drinks_props.row)"
|
||||
/>
|
||||
</q-td>
|
||||
<q-td key="receipt" :props="drinks_props">
|
||||
|
||||
</q-td>
|
||||
</q-tr>
|
||||
</template>-->
|
||||
<template #item="props">
|
||||
<div class="q-pa-xs col-xs-12 col-sm-6 col-md-4">
|
||||
<q-card>
|
||||
|
@ -459,12 +151,10 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onBeforeMount, ComputedRef, computed, ref } from 'vue';
|
||||
import DrinkPriceVolumesTable from 'src/plugins/pricelist/components/CalculationTable/DrinkPriceVolumesTable.vue';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { Drink, usePricelistStore, DrinkPriceVolume } from 'src/plugins/pricelist/store';
|
||||
import MinPriceSetting from 'src/plugins/pricelist/components/MinPriceSetting.vue';
|
||||
import NewDrink from 'src/plugins/pricelist/components/CalculationTable/NewDrink.vue';
|
||||
import BuildManual from 'src/plugins/pricelist/components/CalculationTable/BuildManual.vue';
|
||||
import SearchInput from './SearchInput.vue';
|
||||
import DrinkPriceVolumes from 'src/plugins/pricelist/components/CalculationTable/DrinkPriceVolumes.vue';
|
||||
import DrinkModify from './DrinkModify.vue';
|
||||
|
@ -487,10 +177,6 @@ export default defineComponent({
|
|||
const store = usePricelistStore();
|
||||
|
||||
onBeforeMount(() => {
|
||||
// void store.getDrinkTypes(true);
|
||||
// void store.getTags();
|
||||
//void store.getDrinks();
|
||||
//void store.get_min_prices();
|
||||
void store.getPriceCalcColumn(user);
|
||||
});
|
||||
|
||||
|
@ -683,10 +369,9 @@ export default defineComponent({
|
|||
drinkPic.value = undefined;
|
||||
}
|
||||
|
||||
function savePicture(drink: Drink) {
|
||||
console.log('hier bin ich!!!', drinkPic.value);
|
||||
if (drinkPic.value && drinkPic.value instanceof File) {
|
||||
store.upload_drink_picture(drink, drinkPic.value).catch((response: Response) => {
|
||||
async function savePicture(drinkPic: File) {
|
||||
if (editDrink.value) {
|
||||
await store.upload_drink_picture(editDrink.value, drinkPic).catch((response: Response) => {
|
||||
if (response && response.status == 400) {
|
||||
onPictureRejected();
|
||||
}
|
||||
|
@ -694,8 +379,10 @@ export default defineComponent({
|
|||
}
|
||||
}
|
||||
|
||||
function deletePicture(drink: Drink) {
|
||||
void store.delete_drink_picture(drink);
|
||||
async function deletePicture() {
|
||||
if (editDrink.value) {
|
||||
await store.delete_drink_picture(editDrink.value);
|
||||
}
|
||||
}
|
||||
|
||||
const search = ref<Search>({
|
||||
|
@ -705,7 +392,12 @@ export default defineComponent({
|
|||
});
|
||||
const editDrink = ref();
|
||||
|
||||
async function editing_drink(drink: Drink, toDeleteObjects: DeleteObjects) {
|
||||
async function editing_drink(
|
||||
drink: Drink,
|
||||
toDeleteObjects: DeleteObjects,
|
||||
drinkPic: File | undefined,
|
||||
deletePic: boolean
|
||||
) {
|
||||
notLoading.value = false;
|
||||
for (const ingredient of toDeleteObjects.ingredients) {
|
||||
await store.deleteIngredient(ingredient);
|
||||
|
@ -718,6 +410,22 @@ export default defineComponent({
|
|||
}
|
||||
console.log(drink);
|
||||
await store.updateDrink(drink);
|
||||
if (deletePic || drinkPic) {
|
||||
let loading = imageloading.value.find((a) => a.id === drink.id);
|
||||
if (loading) {
|
||||
loading.loading = true;
|
||||
} else {
|
||||
loading = { id: drink.id, loading: true };
|
||||
imageloading.value.push(loading);
|
||||
}
|
||||
if (deletePic) {
|
||||
await deletePicture();
|
||||
}
|
||||
if (drinkPic instanceof File) {
|
||||
await savePicture(drinkPic);
|
||||
}
|
||||
loading.loading = false;
|
||||
}
|
||||
editDrink.value = undefined;
|
||||
notLoading.value = true;
|
||||
}
|
||||
|
@ -728,6 +436,15 @@ export default defineComponent({
|
|||
|
||||
const notLoading = ref(true);
|
||||
|
||||
const imageloading = ref<Array<{ id: number; loading: boolean }>>([]);
|
||||
function getImageLoading(id: number) {
|
||||
const loading = imageloading.value.find((a) => a.id === id);
|
||||
if (loading) {
|
||||
return loading.loading;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return {
|
||||
drinks: computed(() => store.drinks),
|
||||
pagination,
|
||||
|
@ -751,6 +468,7 @@ export default defineComponent({
|
|||
editing_drink,
|
||||
get_volumes,
|
||||
notLoading,
|
||||
getImageLoading,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -3,6 +3,30 @@
|
|||
<q-card-section>
|
||||
<div class="text-h6">Getränk Bearbeiten</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"
|
||||
|
@ -101,6 +125,7 @@ import { Drink, DrinkPriceVolume, usePricelistStore } from '../store';
|
|||
import DrinkPriceVolumes from './CalculationTable/DrinkPriceVolumes.vue';
|
||||
import { clone, calc_min_prices, DeleteObjects } from '../utils/utils';
|
||||
import BuildManual from 'src/plugins/pricelist/components/CalculationTable/BuildManual.vue';
|
||||
import config from 'src/config';
|
||||
export default defineComponent({
|
||||
name: 'DrinkModify',
|
||||
components: { BuildManual, DrinkPriceVolumes },
|
||||
|
@ -111,7 +136,12 @@ export default defineComponent({
|
|||
},
|
||||
},
|
||||
emits: {
|
||||
save: (drink: Drink, toDeleteObjects: DeleteObjects) => drink && toDeleteObjects,
|
||||
save: (
|
||||
drink: Drink,
|
||||
toDeleteObjects: DeleteObjects,
|
||||
drinkPic: File | undefined,
|
||||
deletePic: boolean
|
||||
) => drink && toDeleteObjects || drinkPic || deletePic,
|
||||
cancel: () => true,
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
|
@ -130,8 +160,9 @@ export default defineComponent({
|
|||
|
||||
const edit_drink = ref<Drink>();
|
||||
function save() {
|
||||
emit('save', <Drink>edit_drink.value, toDeleteObjects.value);
|
||||
emit('save', <Drink>edit_drink.value, toDeleteObjects.value, drinkPic.value, deletePic.value);
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
emit('cancel');
|
||||
}
|
||||
|
@ -147,17 +178,14 @@ export default defineComponent({
|
|||
|
||||
function deletePrice(price: FG.DrinkPrice) {
|
||||
toDeleteObjects.value.prices.push(price);
|
||||
console.log('toDelete', toDeleteObjects.value);
|
||||
}
|
||||
|
||||
function deleteVolume(volume: DrinkPriceVolume) {
|
||||
toDeleteObjects.value.volumes.push(volume);
|
||||
console.log('toDelete', toDeleteObjects.value);
|
||||
}
|
||||
|
||||
function deleteIngredient(ingredient: FG.Ingredient) {
|
||||
toDeleteObjects.value.ingredients.push(ingredient);
|
||||
console.log('toDelete', toDeleteObjects.value);
|
||||
}
|
||||
|
||||
function addStep(event: string) {
|
||||
|
@ -168,6 +196,45 @@ export default defineComponent({
|
|||
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.uuid = '';
|
||||
}
|
||||
}
|
||||
|
||||
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(() => {
|
||||
if (deletePic.value) {
|
||||
return 'no-image.svg';
|
||||
}
|
||||
if (imgsrc.value) {
|
||||
return <string>imgsrc.value;
|
||||
}
|
||||
if (edit_drink.value?.uuid) {
|
||||
return `${config.baseURL}/pricelist/picture/${edit_drink.value.uuid}?size=256`;
|
||||
}
|
||||
return 'no-image.svg';
|
||||
});
|
||||
|
||||
return {
|
||||
edit_drink,
|
||||
save,
|
||||
|
@ -179,6 +246,11 @@ export default defineComponent({
|
|||
addStep,
|
||||
deleteStep,
|
||||
tags: computed(() => store.tags),
|
||||
image,
|
||||
imgsrc,
|
||||
drinkPic,
|
||||
imagePreview,
|
||||
delete_pic,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -204,6 +204,7 @@ export const usePricelistStore = defineStore({
|
|||
this.drinks[index] = _drink;
|
||||
}
|
||||
calc_all_min_prices(this.drinks, this.min_prices);
|
||||
console.log('update drink', drink);
|
||||
},
|
||||
deleteDrink(drink: Drink) {
|
||||
api
|
||||
|
@ -250,7 +251,10 @@ export const usePricelistStore = defineStore({
|
|||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
drink.uuid = data.uuid;
|
||||
const _drink = this.drinks.find((a) => a.id === drink.id);
|
||||
if (_drink) {
|
||||
_drink.uuid = data.uuid;
|
||||
}
|
||||
},
|
||||
async delete_drink_picture(drink: Drink) {
|
||||
await api.delete(`pricelist/drinks/${drink.id}/picture`);
|
||||
|
|
Loading…
Reference in New Issue