release v2.0.0 #4
|
@ -12,7 +12,7 @@ const config = {
|
||||||
// Do not change required Modules !!
|
// Do not change required Modules !!
|
||||||
requiredModules: ['User'],
|
requiredModules: ['User'],
|
||||||
// here you can import plugins.
|
// here you can import plugins.
|
||||||
loadModules: ['Balance', 'Schedule']
|
loadModules: ['Balance', 'Schedule', 'Pricelist']
|
||||||
};
|
};
|
||||||
|
|
||||||
// do not change anything here !!
|
// do not change anything here !!
|
||||||
|
|
|
@ -13,10 +13,10 @@ declare namespace FG {
|
||||||
firstname: string;
|
firstname: string;
|
||||||
lastname: string;
|
lastname: string;
|
||||||
mail: string;
|
mail: string;
|
||||||
birthday?: Date;
|
birthday?: any;
|
||||||
roles: Array<string>;
|
roles: Array<string>;
|
||||||
permissions?: Array<string>;
|
permissions?: any;
|
||||||
avatar_url?: string;
|
avatar_url?: any;
|
||||||
}
|
}
|
||||||
type Permission = string;
|
type Permission = string;
|
||||||
interface Role {
|
interface Role {
|
||||||
|
@ -29,16 +29,51 @@ declare namespace FG {
|
||||||
time: Date;
|
time: Date;
|
||||||
amount: number;
|
amount: number;
|
||||||
reversal_id: number;
|
reversal_id: number;
|
||||||
sender_id?: string;
|
sender_id?: any;
|
||||||
receiver_id?: string;
|
receiver_id?: any;
|
||||||
author_id?: string;
|
author_id?: any;
|
||||||
original_id?: number;
|
original_id?: any;
|
||||||
|
}
|
||||||
|
interface Drink {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
volume: number;
|
||||||
|
cost_price: number;
|
||||||
|
discount: number;
|
||||||
|
extra_charge?: any;
|
||||||
|
prices: Array<DrinkPrice>;
|
||||||
|
ingredients: Array<Ingredient>;
|
||||||
|
tags: Array<any>;
|
||||||
|
}
|
||||||
|
interface DrinkPrice {
|
||||||
|
id: number;
|
||||||
|
volume: number;
|
||||||
|
price: number;
|
||||||
|
no_auto: boolean;
|
||||||
|
public: boolean;
|
||||||
|
description?: any;
|
||||||
|
round_step: number;
|
||||||
|
}
|
||||||
|
interface DrinkType {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
interface Ingredient {
|
||||||
|
id: number;
|
||||||
|
volume: number;
|
||||||
|
drink_parent_id: number;
|
||||||
|
drink_ingredient_id: number;
|
||||||
|
drink_ingredient?: any;
|
||||||
|
}
|
||||||
|
interface Tag {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
}
|
}
|
||||||
interface Event {
|
interface Event {
|
||||||
id: number;
|
id: number;
|
||||||
start: Date;
|
start: Date;
|
||||||
end: Date;
|
end: Date;
|
||||||
description?: string;
|
description?: any;
|
||||||
type: EventType;
|
type: EventType;
|
||||||
jobs: Array<Job>;
|
jobs: Array<Job>;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +84,7 @@ declare namespace FG {
|
||||||
interface Job {
|
interface Job {
|
||||||
id: number;
|
id: number;
|
||||||
start: Date;
|
start: Date;
|
||||||
end?: Date;
|
end?: any;
|
||||||
comment: string;
|
comment: string;
|
||||||
type: JobType;
|
type: JobType;
|
||||||
services: Array<Service>;
|
services: Array<Service>;
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<q-card>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-h4">Neues Getränk</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-form @submit="save">
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-h5">Getränkinformationen</div>
|
||||||
|
<div class="row">
|
||||||
|
<q-input class="col-12 col-sm-6 q-px-sm q-py-md" v-model="drink.name" filled label="Name" />
|
||||||
|
<q-input
|
||||||
|
class="col-12 col-sm-6 q-px-sm q-py-md"
|
||||||
|
v-model="drink.volume"
|
||||||
|
filled
|
||||||
|
label="Inhalt in Liter"
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
/>
|
||||||
|
<q-input
|
||||||
|
class="col-12 col-sm-6 q-px-sm q-py-md"
|
||||||
|
v-model="drink.cost_price"
|
||||||
|
filled
|
||||||
|
label="Einkaufspreis"
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
/>
|
||||||
|
<q-input
|
||||||
|
class="col-12 col-sm-6 q-px-sm q-py-md"
|
||||||
|
v-model="drink.discount"
|
||||||
|
filled
|
||||||
|
label="Aufschlag in Prozent"
|
||||||
|
type="number"
|
||||||
|
hint="Wenn nicht gesetzt wird default-wert genommen."
|
||||||
|
step="0.01"
|
||||||
|
/>
|
||||||
|
<q-input
|
||||||
|
class="col-12 col-sm-6 q-px-sm q-py-md"
|
||||||
|
v-model="drink.extra_charge"
|
||||||
|
filled
|
||||||
|
label="Extra Aufschlag in Euro"
|
||||||
|
type="number"
|
||||||
|
step="0.1"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-input class="col-12 col-sm-6 q-px-sm q-py-md" filled label="Tags" />
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="row justify-between">
|
||||||
|
<div class="text-h5">
|
||||||
|
Preise
|
||||||
|
</div>
|
||||||
|
<q-btn round icon="mdi-plus" @click="addPrice" color="primary" />
|
||||||
|
</div>
|
||||||
|
<q-card class="q-ma-sm" v-for="(price,index) in drink.prices" :key="index">
|
||||||
|
<div class="row">
|
||||||
|
<q-input class="col-12 col-sm-6 q-px-sm q-py-md" v-model="price.volume" label="Inhalt in Liter" filled type="number" step="0.01" />
|
||||||
|
<q-input class="col-12 col-sm-6 q-px-sm q-py-md" v-model="price.price" label="Preis in €" filled :disable="price.no_auto" type="number" step="0.1"/>
|
||||||
|
<q-toggle class="col-12 col-sm-6 q-px-sm q-py-md" v-model="price.no_auto" label="Automatische Preiskalkulation" color="primary" />
|
||||||
|
<q-input class="col-12 col-sm-6 q-px-sm q-py-md" v-model="price.round_step" label="Rundungsschritt" type="number" filled step="0.1"/>
|
||||||
|
<q-toggle class="col-12 col-sm-6 q-px-sm q-py-md" v-model="price.public" label="Öffentlich" color="primary" />
|
||||||
|
<q-input class="col-12 col-sm-6 q-px-sm q-py-md" v-model="price.description" label="Beschreibung" filled />
|
||||||
|
</div>
|
||||||
|
</q-card>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="row justify-between">
|
||||||
|
<div class="text-h5">
|
||||||
|
Zutaten
|
||||||
|
</div>
|
||||||
|
<q-btn round icon="mdi-plus" color="primary" />
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-actions align="right">
|
||||||
|
<q-btn type="submit" label="Speichern" color="primary" />
|
||||||
|
</q-card-actions>
|
||||||
|
</q-form>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, computed } from '@vue/composition-api';
|
||||||
|
import { StateInterface } from 'src/store';
|
||||||
|
import { Store } from 'vuex';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Drink',
|
||||||
|
setup(_, {root}) {
|
||||||
|
const store = <Store<StateInterface>>root.$store;
|
||||||
|
const drink = ref({
|
||||||
|
name: '',
|
||||||
|
volume: '',
|
||||||
|
cost_price: '',
|
||||||
|
discount: '',
|
||||||
|
extra_charge: '',
|
||||||
|
prices: [],
|
||||||
|
ingredients: []
|
||||||
|
})
|
||||||
|
const emptyPrice = {
|
||||||
|
volume: '',
|
||||||
|
price: '',
|
||||||
|
description: '',
|
||||||
|
no_auto: false,
|
||||||
|
round_step: '',
|
||||||
|
public: true
|
||||||
|
}
|
||||||
|
|
||||||
|
function addPrice() {
|
||||||
|
drink.value.prices.unshift({...emptyPrice})
|
||||||
|
}
|
||||||
|
function save() {
|
||||||
|
console.log(drink)
|
||||||
|
drink.value.prices.forEach((price: FG.DrinkPrice) => {
|
||||||
|
price.no_auto = !price.no_auto
|
||||||
|
})
|
||||||
|
void store.dispatch('drink/createDrink', drink.value)
|
||||||
|
}
|
||||||
|
return {drink, addPrice, save};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,133 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<q-dialog v-model="edittype">
|
||||||
|
<q-card>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-h6">Editere Getränkeart {{ actualDrinkType.name }}</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<q-input dense label="name" filled v-model="newDrinkTypeName" />
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-actions>
|
||||||
|
<q-btn flat color="danger" label="Abbrechen" @click="discardChanges()" />
|
||||||
|
<q-btn flat color="primary" label="Speichern" @click="saveChanges()" />
|
||||||
|
</q-card-actions>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
|
|
||||||
|
<q-page padding>
|
||||||
|
<q-table title="Getränkearten" :data="rows" :row-key="row => row.id" :columns="columns">
|
||||||
|
<template v-slot:top-right>
|
||||||
|
<q-input
|
||||||
|
class="q-px-sm"
|
||||||
|
dense
|
||||||
|
v-model="newDrinkType"
|
||||||
|
placeholder="Neue Getränkeart"
|
||||||
|
filled
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div></div>
|
||||||
|
<q-btn color="primary" icon="mdi-plus" label="Hinzufügen" @click="addType" />
|
||||||
|
</template>
|
||||||
|
<template v-slot:body-cell-actions="props">
|
||||||
|
<q-td :props="props" align="right" :auto-width="true">
|
||||||
|
<q-btn
|
||||||
|
round
|
||||||
|
flat
|
||||||
|
icon="mdi-pencil"
|
||||||
|
@click="editType({ id: props.row.id, name: props.row.name })"
|
||||||
|
/>
|
||||||
|
<q-btn round flat icon="mdi-delete" @click="deleteType(props.row.id)" />
|
||||||
|
</q-td>
|
||||||
|
</template>
|
||||||
|
</q-table>
|
||||||
|
</q-page>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { computed, defineComponent, onBeforeMount, ref } from '@vue/composition-api';
|
||||||
|
import { Store } from 'vuex';
|
||||||
|
import { StateInterface } from 'src/store';
|
||||||
|
import { DrinkInterface } from 'src/plugins/pricelist/store/drinks';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'DrinkTypes',
|
||||||
|
setup(_, { root }) {
|
||||||
|
const store = <Store<StateInterface>>root.$store;
|
||||||
|
const state = <DrinkInterface>store.state.drink;
|
||||||
|
const newDrinkType = ref('');
|
||||||
|
const newDrinkTypeName = ref('');
|
||||||
|
const edittype = ref(false);
|
||||||
|
const emptyDrinkType: FG.DrinkType = { id: -1, name: '' };
|
||||||
|
const actualDrinkType = ref(emptyDrinkType);
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
console.log(store);
|
||||||
|
void store.dispatch('drink/getDrinkTypes');
|
||||||
|
});
|
||||||
|
|
||||||
|
const rows = computed(() => state.drinkTypes);
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
name: 'drinkTypeName',
|
||||||
|
label: 'Getränkeart',
|
||||||
|
field: 'name',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'actions',
|
||||||
|
label: 'Aktionen',
|
||||||
|
field: 'actions',
|
||||||
|
align: 'right'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function addType() {
|
||||||
|
void store.dispatch('drink/addDrinkType', { name: newDrinkType.value });
|
||||||
|
newDrinkType.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function editType(drinkType: FG.DrinkType) {
|
||||||
|
edittype.value = true;
|
||||||
|
actualDrinkType.value = drinkType;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveChanges() {
|
||||||
|
void store
|
||||||
|
.dispatch('drink/changeDrinkTypeName', {
|
||||||
|
id: actualDrinkType.value.id,
|
||||||
|
name: newDrinkTypeName.value
|
||||||
|
})
|
||||||
|
.finally(() => discardChanges());
|
||||||
|
}
|
||||||
|
|
||||||
|
function discardChanges() {
|
||||||
|
actualDrinkType.value = emptyDrinkType;
|
||||||
|
newDrinkTypeName.value = '';
|
||||||
|
edittype.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteType(id: number) {
|
||||||
|
void store.dispatch('drink/removeDrinkType', id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
columns,
|
||||||
|
rows,
|
||||||
|
addType,
|
||||||
|
newDrinkType,
|
||||||
|
deleteType,
|
||||||
|
edittype,
|
||||||
|
editType,
|
||||||
|
actualDrinkType,
|
||||||
|
newDrinkTypeName,
|
||||||
|
discardChanges,
|
||||||
|
saveChanges
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,67 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<q-table
|
||||||
|
title="Getränke"
|
||||||
|
:columns="columns"
|
||||||
|
:data="drinks"
|
||||||
|
row-key="name"
|
||||||
|
>
|
||||||
|
<template v-slot:body-cell-prices="{row: {prices}}">
|
||||||
|
<q-td>
|
||||||
|
<div v-for="price in prices" :key="price.id" class="row">
|
||||||
|
<div class="col">
|
||||||
|
{{price.volume | setVolume}}
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
{{price.price | setCurrency}}
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
{{price.description}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-td>
|
||||||
|
</template>
|
||||||
|
</q-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, onBeforeMount, ref} from '@vue/composition-api';
|
||||||
|
import {StateInterface} from 'src/store';
|
||||||
|
import {DrinkInterface} from '../store/drinks';
|
||||||
|
import {Store} from 'vuex';
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Pricelist',
|
||||||
|
filters: {
|
||||||
|
setVolume(volume: number) {
|
||||||
|
if (volume*10 > 1) {
|
||||||
|
return `${volume}l`
|
||||||
|
}
|
||||||
|
return `${volume*100}cl`
|
||||||
|
},
|
||||||
|
setCurrency(price: number) {
|
||||||
|
return `${price.toFixed(2)}€`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup(_, {root}) {
|
||||||
|
const store = <Store<StateInterface>>root.$store;
|
||||||
|
const state = <DrinkInterface>store.state.drink;
|
||||||
|
const drinks = ref(state.drinks)
|
||||||
|
onBeforeMount(() => {
|
||||||
|
void store.dispatch('drink/getDrinks');
|
||||||
|
})
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
label: 'Getränk',
|
||||||
|
field: 'name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'prices',
|
||||||
|
label: 'Preise',
|
||||||
|
field: 'prices'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
return {columns, drinks}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -0,0 +1,37 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<q-page padding v-if="checkMain">
|
||||||
|
<q-card>
|
||||||
|
<q-card-section>
|
||||||
|
<q-list v-for="(mainRoute, index) in mainRoutes" :key="'mainRoute' + index">
|
||||||
|
<essential-link
|
||||||
|
v-for="(route, index2) in mainRoute.children"
|
||||||
|
:key="'route' + index2"
|
||||||
|
:title="route.title"
|
||||||
|
:icon="route.icon"
|
||||||
|
:link="route.name"
|
||||||
|
:permissions="route.meta.permissions"
|
||||||
|
/>
|
||||||
|
</q-list>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</q-page>
|
||||||
|
<router-view />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { computed, defineComponent } from '@vue/composition-api';
|
||||||
|
import EssentialLink from 'src/components/navigation/EssentialLink.vue';
|
||||||
|
import mainRoutes from '../routes';
|
||||||
|
export default defineComponent({
|
||||||
|
// name: 'PageName'
|
||||||
|
components: { EssentialLink },
|
||||||
|
setup(_, { root }) {
|
||||||
|
const checkMain = computed(() => {
|
||||||
|
return root.$route.matched.length == 2;
|
||||||
|
});
|
||||||
|
return { checkMain, mainRoutes };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<template>
|
||||||
|
<Pricelist />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Pricelist from '../components/Pricelist.vue'
|
||||||
|
export default {
|
||||||
|
name: 'PricelistPage',
|
||||||
|
components: {Pricelist}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,86 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<q-tabs v-model="tab" v-if="$q.screen.gt.sm">
|
||||||
|
<q-tab
|
||||||
|
v-for="(tabindex, index) in tabs"
|
||||||
|
:key="'tab' + index"
|
||||||
|
:name="tabindex.name"
|
||||||
|
:label="tabindex.label"
|
||||||
|
/>
|
||||||
|
</q-tabs>
|
||||||
|
<div class="fit row justify-end" v-else>
|
||||||
|
<q-btn flat round icon="mdi-menu" @click="showDrawer = !showDrawer"></q-btn>
|
||||||
|
</div>
|
||||||
|
<q-drawer side="right" v-model="showDrawer" @click="showDrawer = !showDrawer" behavior="mobile">
|
||||||
|
<q-list v-model="tab">
|
||||||
|
<q-item
|
||||||
|
v-for="(tabindex, index) in tabs"
|
||||||
|
:key="'tab' + index"
|
||||||
|
:active="tab == tabindex.name"
|
||||||
|
clickable
|
||||||
|
@click="tab = tabindex.name"
|
||||||
|
>
|
||||||
|
<q-item-label>{{ tabindex.label }}</q-item-label>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-drawer>
|
||||||
|
<q-page paddding class="fit row justify-center content-start items-start q-gutter-sm">
|
||||||
|
<q-tab-panels
|
||||||
|
v-model="tab"
|
||||||
|
style="background-color: transparent;"
|
||||||
|
animated
|
||||||
|
class="q-ma-none q-pa-none fit row justify-center content-start items-start"
|
||||||
|
>
|
||||||
|
<q-tab-panel name="pricelist">
|
||||||
|
<h1>preisliste</h1>
|
||||||
|
</q-tab-panel>
|
||||||
|
<q-tab-panel name="new_drink">
|
||||||
|
<Drink />
|
||||||
|
</q-tab-panel>
|
||||||
|
<q-tab-panel name="drink_types">
|
||||||
|
<DrinkTypes />
|
||||||
|
</q-tab-panel>
|
||||||
|
</q-tab-panels>
|
||||||
|
</q-page>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { computed, defineComponent, ref } from '@vue/composition-api';
|
||||||
|
import { Screen } from 'quasar';
|
||||||
|
import DrinkTypes from 'src/plugins/pricelist/components/DrinkTypes.vue';
|
||||||
|
import Drink from 'src/plugins/pricelist/components/Drink.vue';
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Settings',
|
||||||
|
components: { DrinkTypes, Drink },
|
||||||
|
setup(_) {
|
||||||
|
interface Tab {
|
||||||
|
name: string;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const drawer = ref<boolean>(false);
|
||||||
|
|
||||||
|
const showDrawer = computed({
|
||||||
|
get: () => {
|
||||||
|
return !Screen.gt.sm && drawer.value;
|
||||||
|
},
|
||||||
|
set: (val: boolean) => {
|
||||||
|
drawer.value = val;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const tabs: Tab[] = [
|
||||||
|
{ name: 'pricelist', label: 'Getränke' },
|
||||||
|
{ name: 'new_drink', label: 'Neues Getränk' },
|
||||||
|
{ name: 'drink_types', label: 'Getränketypen' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const tab = ref<string>('pricelist');
|
||||||
|
|
||||||
|
return { tabs, tab, showDrawer };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Module } from 'vuex';
|
||||||
|
import routes from './routes';
|
||||||
|
import { StateInterface } from 'src/store';
|
||||||
|
import drink, { DrinkInterface } from 'src/plugins/pricelist/store/drinks';
|
||||||
|
import { FG_Plugin } from 'src/plugins';
|
||||||
|
|
||||||
|
const plugin: FG_Plugin.Plugin = {
|
||||||
|
name: 'Pricelist',
|
||||||
|
mainRoutes: routes,
|
||||||
|
requiredModules: [],
|
||||||
|
requiredBackendModules: ['pricelist'],
|
||||||
|
version: '0.0.1',
|
||||||
|
store: new Map<string, Module<DrinkInterface, StateInterface>>([['drink', drink]]),
|
||||||
|
widgets: []
|
||||||
|
// widgets: [
|
||||||
|
// {
|
||||||
|
// priority: 1,
|
||||||
|
// name: 'greeting',
|
||||||
|
// permissions: []
|
||||||
|
// widget: () => import('./components/Widget.vue')
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
};
|
||||||
|
|
||||||
|
export default plugin;
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { FG_Plugin } from 'src/plugins';
|
||||||
|
const mainRoutes: FG_Plugin.PluginRouteConfig[] = [
|
||||||
|
{
|
||||||
|
title: 'Getränke',
|
||||||
|
icon: 'mdi-glass-mug-variant',
|
||||||
|
path: 'drinks',
|
||||||
|
name: 'drinks',
|
||||||
|
component: () => import('../pages/MainPage.vue'),
|
||||||
|
meta: { permissions: ['user'] },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'Preisliste',
|
||||||
|
icon: 'mdi-cash-100',
|
||||||
|
path: 'pricelist',
|
||||||
|
name: 'drinks-pricelist',
|
||||||
|
shortcut: true,
|
||||||
|
meta: { permissions: ['user'] },
|
||||||
|
component: () => import('../pages/Pricelist.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Einstellungen',
|
||||||
|
icon: 'mdi-coffee-to-go',
|
||||||
|
path: 'settings',
|
||||||
|
name: 'drinks-settings',
|
||||||
|
shortcut: false,
|
||||||
|
meta: { permissions: ['users_edit_other'] },
|
||||||
|
component: () => import('../pages/Settings.vue')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export default mainRoutes;
|
|
@ -0,0 +1,106 @@
|
||||||
|
import { Module, MutationTree, ActionTree, GetterTree } from 'vuex';
|
||||||
|
import { StateInterface } from 'src/store';
|
||||||
|
import { axios } from 'src/boot/axios';
|
||||||
|
import { AxiosResponse } from 'axios';
|
||||||
|
|
||||||
|
export interface DrinkInterface {
|
||||||
|
drinkTypes: FG.DrinkType[];
|
||||||
|
drinks: FG.Drink[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const state: DrinkInterface = {
|
||||||
|
drinkTypes: [],
|
||||||
|
drinks: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const mutations: MutationTree<DrinkInterface> = {
|
||||||
|
setDrinkTypes(state, drinkTypes: FG.DrinkType[]) {
|
||||||
|
state.drinkTypes = drinkTypes;
|
||||||
|
},
|
||||||
|
setDrinkType(state, drinkType: FG.DrinkType) {
|
||||||
|
const item = state.drinkTypes.find(item => item.id == drinkType.id);
|
||||||
|
if (item) {
|
||||||
|
item.name = drinkType.name;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addDrinkType(state, drinkType: FG.DrinkType) {
|
||||||
|
state.drinkTypes.unshift(drinkType);
|
||||||
|
},
|
||||||
|
removeDrinkType(state, id: number) {
|
||||||
|
const index = state.drinkTypes.findIndex(item => item.id == id);
|
||||||
|
state.drinkTypes.splice(index, 1);
|
||||||
|
},
|
||||||
|
setDrinks(state, drinks: FG.Drink[]) {
|
||||||
|
state.drinks = drinks
|
||||||
|
},
|
||||||
|
setDrink(state, drink: FG.Drink) {
|
||||||
|
const index = state.drinks.findIndex(item => item.id = drink.id)
|
||||||
|
if (index) {
|
||||||
|
state.drinks[index] = drink
|
||||||
|
} else {
|
||||||
|
state.drinks.push(drink)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const actions: ActionTree<DrinkInterface, StateInterface> = {
|
||||||
|
getDrinkTypes({ commit }) {
|
||||||
|
axios
|
||||||
|
.get('/pricelist/drink-types')
|
||||||
|
.then((response: AxiosResponse<FG.DrinkType[]>) => {
|
||||||
|
commit('setDrinkTypes', response.data);
|
||||||
|
})
|
||||||
|
.catch(err => console.warn(err));
|
||||||
|
},
|
||||||
|
addDrinkType({ commit }, data) {
|
||||||
|
axios
|
||||||
|
.post('/pricelist/drink-types', data)
|
||||||
|
.then((response: AxiosResponse<FG.DrinkType>) => {
|
||||||
|
commit('addDrinkType', response.data);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.warn(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
removeDrinkType({ commit }, data: number) {
|
||||||
|
axios
|
||||||
|
.delete(`/pricelist/drink-types/${data}`)
|
||||||
|
.then(() => {
|
||||||
|
commit('removeDrinkType', data);
|
||||||
|
})
|
||||||
|
.catch(err => console.warn(err));
|
||||||
|
},
|
||||||
|
changeDrinkTypeName({ commit }, drinkType: FG.DrinkType) {
|
||||||
|
axios
|
||||||
|
.put(`/pricelist/drink-types/${drinkType.id}`, drinkType)
|
||||||
|
.then(() => {
|
||||||
|
commit('setDrinkType', drinkType);
|
||||||
|
})
|
||||||
|
.catch(err => console.warn(err));
|
||||||
|
},
|
||||||
|
getDrinks({commit}) {
|
||||||
|
axios.get('/pricelist/drinks')
|
||||||
|
.then((response: AxiosResponse<FG.Drink[]>) => {
|
||||||
|
commit('setDrinks', response.data)
|
||||||
|
})
|
||||||
|
.catch(err => console.warn(err))
|
||||||
|
},
|
||||||
|
createDrink({commit}, data) {
|
||||||
|
axios.post('/pricelist/drinks', data)
|
||||||
|
.then((response: AxiosResponse<FG.Drink>) => {
|
||||||
|
commit('setDrink', response.data)
|
||||||
|
})
|
||||||
|
.catch(err => console.warn(err))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getters: GetterTree<DrinkInterface, StateInterface> = {};
|
||||||
|
|
||||||
|
const schedule: Module<DrinkInterface, StateInterface> = {
|
||||||
|
namespaced: true,
|
||||||
|
state,
|
||||||
|
mutations,
|
||||||
|
actions,
|
||||||
|
getters
|
||||||
|
};
|
||||||
|
|
||||||
|
export default schedule;
|
Loading…
Reference in New Issue