release v2.0.0 #4
|
@ -13,6 +13,7 @@
|
|||
<template #top-right>
|
||||
<div class="row justify-end q-gutter-sm">
|
||||
<search-input v-model="search" :keys="search_keys" />
|
||||
<slot></slot>
|
||||
<q-btn v-if="!public && !nodetails" label="Aufpreise">
|
||||
<q-menu anchor="center middle" self="center middle">
|
||||
<min-price-setting />
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
<template>
|
||||
<q-table
|
||||
title="Preisliste"
|
||||
:columns="columns"
|
||||
:rows="drinks"
|
||||
:visible-columns="visibleColumns"
|
||||
:filter="search"
|
||||
:filter-method="filter"
|
||||
dense
|
||||
>
|
||||
<template #top-right>
|
||||
<div class="row justify-end q-gutter-sm">
|
||||
<search-input v-model="search" :keys="options" />
|
||||
<q-select
|
||||
v-model="visibleColumns"
|
||||
multiple
|
||||
filled
|
||||
dense
|
||||
options-dense
|
||||
display-value="Sichtbarkeit"
|
||||
emit-value
|
||||
map-options
|
||||
:options="options"
|
||||
option-value="name"
|
||||
options-cover
|
||||
/>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<template #body-cell-tags="props">
|
||||
<q-td :props="props">
|
||||
<q-badge
|
||||
v-for="tag in props.row.tags"
|
||||
:key="`${props.row.id}-${tag.id}`"
|
||||
class="text-caption"
|
||||
rounded
|
||||
:style="`background-color: ${tag.color}`"
|
||||
>
|
||||
{{ tag.name }}
|
||||
</q-badge>
|
||||
</q-td>
|
||||
</template>
|
||||
<template #body-cell-public="props">
|
||||
<q-td :props="props">
|
||||
<q-toggle
|
||||
v-model="props.row.public"
|
||||
disable
|
||||
checked-icon="mdi-earth"
|
||||
unchecked-icon="mdi-earth-off"
|
||||
/>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, onBeforeMount, ref } from 'vue';
|
||||
import { usePricelistStore } from '../store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { Search, filter } from 'src/plugins/pricelist/utils/filter';
|
||||
import SearchInput from 'src/plugins/pricelist/components/SearchInput.vue';
|
||||
export default defineComponent({
|
||||
name: 'Pricelist',
|
||||
components: { SearchInput },
|
||||
props: {
|
||||
public: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const store = usePricelistStore();
|
||||
const user = ref('');
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (!props.public) {
|
||||
user.value = useMainStore().currentUser.userid;
|
||||
void store.getPriceCalcColumn(user.value);
|
||||
} else {
|
||||
user.value = '';
|
||||
}
|
||||
});
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
field: 'name',
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
label: 'Kategorie',
|
||||
field: 'type',
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
format: (val: FG.DrinkType) => val.name,
|
||||
},
|
||||
{
|
||||
name: 'tags',
|
||||
label: 'Tags',
|
||||
field: 'tags',
|
||||
filterable: true,
|
||||
|
||||
format: (val: Array<FG.Tag>) => {
|
||||
let retVal = '';
|
||||
val.forEach((tag, index) => {
|
||||
if (index >= val.length - 1 && index > 0) {
|
||||
retVal += ', ';
|
||||
}
|
||||
retVal += tag.name;
|
||||
});
|
||||
return retVal;
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'volume',
|
||||
label: 'Inhalt',
|
||||
field: 'volume',
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
format: (val: number) => `${val.toFixed(3)}L`,
|
||||
},
|
||||
{
|
||||
name: 'price',
|
||||
label: 'Preis',
|
||||
field: 'price',
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
format: (val: number) => `${val.toFixed(2)}€`,
|
||||
},
|
||||
{
|
||||
name: 'public',
|
||||
label: 'Öffentlich',
|
||||
field: 'public',
|
||||
format: (val: boolean) => (val ? 'Öffentlich' : 'nicht Öffentlich'),
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
label: 'Beschreibung',
|
||||
field: 'description',
|
||||
filterable: true,
|
||||
},
|
||||
];
|
||||
|
||||
const _options = computed(() => {
|
||||
const retVal: Array<{ name: string; label: string; field: string }> = [];
|
||||
columns.forEach((col) => {
|
||||
if (props.public) {
|
||||
if (col.name !== 'public') {
|
||||
retVal.push(col);
|
||||
}
|
||||
} else {
|
||||
retVal.push(col);
|
||||
}
|
||||
});
|
||||
return retVal;
|
||||
});
|
||||
|
||||
const _colums = computed<Array<string>>(() => {
|
||||
const retVal: Array<string> = [];
|
||||
columns.forEach((col) => {
|
||||
if (props.public) {
|
||||
if (col.name !== 'public') {
|
||||
retVal.push(col.name);
|
||||
}
|
||||
} else {
|
||||
retVal.push(col.name);
|
||||
}
|
||||
});
|
||||
return retVal;
|
||||
});
|
||||
|
||||
const _visibleColumns = ref(_colums.value);
|
||||
|
||||
const visibleColumns = computed({
|
||||
get: () => (props.public ? _visibleColumns.value : store.pricecalc_columns),
|
||||
set: (val) => {
|
||||
if (!props.public) {
|
||||
void store.updatePriceCalcColumn(user.value, val);
|
||||
} else {
|
||||
_visibleColumns.value = val;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const search = ref<Search>({
|
||||
value: '',
|
||||
key: '',
|
||||
label: '',
|
||||
});
|
||||
|
||||
return {
|
||||
drinks: computed(() => store.pricelist),
|
||||
columns,
|
||||
visibleColumns,
|
||||
options: _options,
|
||||
search,
|
||||
filter,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
|
@ -1,14 +1,32 @@
|
|||
<template>
|
||||
<calculation-table nodetails />
|
||||
<calculation-table v-if="!list" nodetails>
|
||||
<q-btn icon="mdi-view-list" round @click="list = !list">
|
||||
<q-tooltip> Zur Listenansicht wechseln </q-tooltip>
|
||||
</q-btn>
|
||||
</calculation-table>
|
||||
<pricelist v-if="list">
|
||||
<q-btn icon="mdi-cards-variant" round @click="list = !list">
|
||||
<q-tooltip> Zur Kartenansicht wechseln </q-tooltip>
|
||||
</q-btn>
|
||||
</pricelist>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent, onBeforeMount, ref } from 'vue';
|
||||
import CalculationTable from '../components/CalculationTable.vue';
|
||||
import Pricelist from 'src/plugins/pricelist/components/Pricelist.vue';
|
||||
import { usePricelistStore } from 'src/plugins/pricelist/store';
|
||||
export default defineComponent({
|
||||
name: 'InnerPricelist',
|
||||
components: { CalculationTable },
|
||||
components: { Pricelist, CalculationTable },
|
||||
setup() {
|
||||
return {};
|
||||
const store = usePricelistStore();
|
||||
|
||||
onBeforeMount(() => {
|
||||
void store.getDrinks();
|
||||
});
|
||||
|
||||
const list = ref(false);
|
||||
return { list };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,13 +1,36 @@
|
|||
<template>
|
||||
<calculation-table public />
|
||||
<calculation-table v-if="!list" public>
|
||||
<q-btn icon="mdi-view-list" round @click="list = !list">
|
||||
<q-tooltip> Zur Listenansicht wechseln </q-tooltip>
|
||||
</q-btn>
|
||||
</calculation-table>
|
||||
<pricelist v-if="list" public>
|
||||
<q-btn icon="mdi-cards-variant" round @click="list = !list">
|
||||
<q-tooltip> Zur Kartenansicht wechseln </q-tooltip>
|
||||
</q-btn>
|
||||
</pricelist>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
import CalculationTable from '../components/CalculationTable.vue';
|
||||
export default {
|
||||
import Pricelist from '../components/Pricelist.vue';
|
||||
import { usePricelistStore } from '../store';
|
||||
import { onBeforeMount, ref } from 'vue';
|
||||
export default defineComponent({
|
||||
name: 'OuterPricelist',
|
||||
components: { CalculationTable },
|
||||
};
|
||||
components: { Pricelist, CalculationTable },
|
||||
setup() {
|
||||
const store = usePricelistStore();
|
||||
|
||||
onBeforeMount(() => {
|
||||
void store.getDrinks();
|
||||
});
|
||||
|
||||
const list = ref(false);
|
||||
return { list };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
@ -94,7 +94,11 @@ export default defineComponent({
|
|||
|
||||
const _tabs: Tab[] = [
|
||||
{ name: 'pricelist', label: 'Getränke', permissions: ['drink_edit'] },
|
||||
{ name: 'extra_ingredients', label: 'Zutaten', permissions: ['edit_ingredients', 'delete_ingredients'] },
|
||||
{
|
||||
name: 'extra_ingredients',
|
||||
label: 'Zutaten',
|
||||
permissions: ['edit_ingredients', 'delete_ingredients'],
|
||||
},
|
||||
{
|
||||
name: 'drink_types',
|
||||
label: 'Getränketypen',
|
||||
|
|
|
@ -17,6 +17,16 @@ interface Drink extends Omit<Omit<FG.Drink, 'cost_per_volume'>, 'volumes'> {
|
|||
_cost_per_volume?: number;
|
||||
}
|
||||
|
||||
interface Pricelist {
|
||||
name: string;
|
||||
type: FG.DrinkType;
|
||||
tags: Array<FG.Tag>;
|
||||
volume: number;
|
||||
price: number;
|
||||
public: boolean;
|
||||
description: string;
|
||||
}
|
||||
|
||||
class DrinkPriceVolume implements DrinkPriceVolume {
|
||||
constructor({ id, volume, prices, ingredients }: FG.DrinkPriceVolume) {
|
||||
this.id = id;
|
||||
|
@ -67,6 +77,7 @@ export const usePricelistStore = defineStore({
|
|||
extraIngredients: [] as Array<FG.ExtraIngredient>,
|
||||
min_prices: [] as Array<number>,
|
||||
tags: [] as Array<FG.Tag>,
|
||||
pricecalc_columns: [] as Array<string>,
|
||||
}),
|
||||
|
||||
actions: {
|
||||
|
@ -244,6 +255,35 @@ export const usePricelistStore = defineStore({
|
|||
this.tags.splice(index, 1);
|
||||
}
|
||||
},
|
||||
async getPriceCalcColumn(userid: string) {
|
||||
const { data } = await api.get<Array<string>>(`pricelist/users/${userid}/pricecalc_columns`);
|
||||
this.pricecalc_columns = data;
|
||||
},
|
||||
async updatePriceCalcColumn(userid: string, data: Array<string>) {
|
||||
await api.put<Array<string>>(`pricelist/users/${userid}/pricecalc_columns`, data);
|
||||
this.pricecalc_columns = data;
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
pricelist() {
|
||||
const retVal: Array<Pricelist> = [];
|
||||
this.drinks.forEach((drink) => {
|
||||
drink.volumes.forEach((volume) => {
|
||||
volume.prices.forEach((price) => {
|
||||
retVal.push({
|
||||
name: drink.name,
|
||||
type: <FG.DrinkType>drink.type,
|
||||
tags: <Array<FG.Tag>>drink.tags,
|
||||
volume: <number>volume.volume,
|
||||
price: price.price,
|
||||
public: price.public,
|
||||
description: <string>price.description,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return retVal;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue