flaschengeist-frontend/src/components/pricelist/PriceList.vue

489 lines
15 KiB
Vue

<template>
<div>
<v-data-table :headers="headers" :items="priceList" :search="search" :loading="priceListLoading || typesLoading">
<template v-slot:top>
<v-toolbar flat color="white">
<v-toolbar-title>Preisliste</v-toolbar-title>
<v-spacer></v-spacer>
<v-text-field
v-model="search"
label="Suche Getränk"
single-line
hide-details
>
<template v-slot:append>
<v-icon>{{ searchIcon }}</v-icon>
</template>
</v-text-field>
<v-dialog v-model="dialog" v-if="isGastro">
<template v-slot:activator="{ on }">
<v-btn
fab
x-small
color="primary"
class="mb-2"
v-on="on"
style="margin: 5px"
>
<v-icon>{{ plus }}</v-icon>
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="headline">{{ formTitle }}</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.name"
label="Name"
outlined
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-autocomplete
return-object
v-model="editedItem.type"
label="Kategorie"
item-text="name"
item-value="id"
:items="types"
outlined
:search-input.sync="searchType"
no-data-text="Kategorie nicht vorhanden."
>
<template v-slot:append-item>
<v-list-item v-if="!inType(searchType)">
<v-list-item-title>
{{ searchType }}
</v-list-item-title>
<v-btn
dark
x-small
color="blue darken-1"
@click="addType()"
:disabled="inType(searchType)"
fab
>
<v-icon>
{{ plus }}
</v-icon>
</v-btn>
</v-list-item>
</template>
</v-autocomplete>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.price"
label="Preis in €"
outlined
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.price_big"
label="Preis groß in €"
outlined
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.price_club"
label="Preis Club in €"
outlined
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.price_club_big"
label="Preis Club groß in €"
outlined
></v-text-field>
</v-col>
<v-col col="12" sm="6" md="4">
<v-text-field
v-model="editedItem.premium"
label="Aufpreis in €"
outlined
/>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.premium_club"
label="Aufpreis Club in €"
outlined
/>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.price_extern_club"
label="Preis extern Club in €"
outlined
/>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="close"
>Abbrechen</v-btn
>
<v-btn color="blue darken-1" text @click="save"
>Speichern</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-toolbar>
</template>
<template v-slot:item.type="{ item }">
{{ computeType(item.type) }}
</template>
<template v-slot:item.price="{ item }">
{{ item.price ? (item.price / 100).toFixed(2) : '' }}
</template>
<template v-slot:item.price_big="{ item }">
{{ item.price_big ? (item.price_big / 100).toFixed(2) : '' }}
</template>
<template v-slot:item.price_club="{ item }">
{{
item.name.toLowerCase() == 'long island ice tea'.toLowerCase()
? 'Ein Klubmitglied bestellt keinen Long Island Icetea'
: item.price_club
? (item.price_club / 100).toFixed(2)
: ''
}}
</template>
<template v-slot:item.price_club_big="{ item }">
{{ item.price_club_big ? (item.price_club_big / 100).toFixed(2) : '' }}
</template>
<template v-slot:item.premium="{ item }">
{{ item.premium ? (item.premium / 100).toFixed(2) : '' }}
</template>
<template v-slot:item.premium_club="{ item }">
{{ item.premium_club ? (item.premium_club / 100).toFixed(2) : '' }}
</template>
<template v-slot:item.price_extern_club="{ item }">
{{
item.price_extern_club
? (item.price_extern_club / 100).toFixed(2)
: ''
}}
</template>
<template v-slot:item.action="{ item }">
<v-icon small class="mr-2" @click="editItem(item)">
{{ editIcon }}
</v-icon>
<v-icon small @click="deleteItem(item)">
{{ deleteIcon }}
</v-icon>
</template>
</v-data-table>
<v-card tile v-if="isGastro" :loading="typesLoading">
<v-card-title>
Kategorien
<v-spacer />
<v-btn fab x-small @click="dialogType = true" color="primary">
<v-icon>{{ plus }}</v-icon>
</v-btn>
</v-card-title>
<v-card-text>
<div tile v-for="type in types" :key="type.id">
<v-card tile>
<v-card-text class="black--text">
<v-row class="ml-3 mr-3">
{{ type.name }}
<v-spacer />
<v-btn icon @click="editType(type)">
<v-icon>
{{ editIcon }}
</v-icon>
</v-btn>
<v-btn icon @click="deleteType(type)">
<v-icon>
{{ deleteIcon }}
</v-icon>
</v-btn>
</v-row>
</v-card-text>
</v-card>
</div>
</v-card-text>
<v-dialog v-model="dialogType">
<v-card>
<v-card-title>
{{ dialogTypeTitle }}
</v-card-title>
<v-card-text>
<v-container>
<v-text-field
v-model="editedType.name"
outlined
label="Name der Kategorie"
/>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn text color="blue darken-1" @click="closeType()">
Abbrechen
</v-btn>
<v-btn
text
color="blue darken-1"
@click="saveType()"
:disabled="inType(editedType.name)"
>
Speichern
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-card>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
import { mdiMagnify, mdiPlus, mdiPencil, mdiDelete } from '@mdi/js'
export default {
name: 'PriceList',
data() {
return {
editIcon: mdiPencil,
deleteIcon: mdiDelete,
searchIcon: mdiMagnify,
plus: mdiPlus,
searchType: null,
search: null,
dialog: null,
dialogType: null,
editedIndex: -1,
headers: [
{
text: 'Name',
value: 'name'
},
{
text: 'Kategorie',
value: 'type'
},
{
text: 'Preis in €',
value: 'price'
},
{
text: 'Preis groß in €',
value: 'price_big'
},
{
text: 'Preis Club in €',
value: 'price_club'
},
{
text: 'Preis groß Club in €',
value: 'price_club_big'
},
{
text: 'Aufpreis in €',
value: 'premium'
},
{
text: 'Aufpreis Club in €',
value: 'premium_club'
},
{
text: 'Preis Club extern in €',
value: 'price_extern_club'
}
],
editedItem: {
name: null,
type: { id: -1, name: null },
price: null,
price_big: null,
price_club: null,
price_club_big: null,
premium: null,
premium_club: null,
price_extern_club: null
},
defaultItem: {
name: null,
type: { id: -1, name: null },
price: null,
price_big: null,
price_club: null,
price_club_big: null,
premium: null,
premium_club: null,
price_extern_club: null
},
editedType: {
id: -1,
name: null
},
defaultType: {
id: -1,
name: null
}
}
},
methods: {
...mapActions({
getPriceList: 'priceList/getPriceList',
getTypes: 'priceList/getTypes',
setDrink: 'priceList/setDrink',
updateDrink: 'priceList/updateDrink',
deleteDrink: 'priceList/deleteDrink',
setDrinkType: 'priceList/setDrinkType',
updateDrinkType: 'priceList/updateDrinkType',
deleteDrinkType: 'priceList/deleteDrinkType'
}),
editType(item) {
this.editedType = Object.assign({}, item)
this.dialogType = true
},
closeType() {
this.dialogType = false
setTimeout(() => {
this.editedType = Object.assign({}, this.defaultType)
}, 300)
},
saveType() {
this.editedType.id === -1
? this.setDrinkType(this.editedType)
: this.updateDrinkType(this.editedType)
this.closeType()
},
deleteType(item) {
confirm('Bist du sicher, dass die diese Kategorie entfernen wills?') &&
this.deleteDrinkType({ id: item.id })
},
addType() {
this.setDrinkType({ name: this.searchType })
},
close() {
this.dialog = false
setTimeout(() => {
this.editedItem = Object.assign({}, this.defaultItem)
this.editedIndex = -1
}, 300)
},
editItem(item) {
this.editedIndex = item.id
this.editedItem = Object.assign({}, item)
for (let i in this.editedItem) {
this.editedItem[i] = isNaN(this.editedItem[i])
? this.editedItem[i]
: this.editedItem[i] == null || this.editedItem[i] == 0
? null
: (this.editedItem[i] / 100).toFixed(2)
}
this.editedItem.type = Object.assign(
{},
this.types.find(a => a.id == item.type)
)
this.dialog = true
},
deleteItem(item) {
confirm('Bist du sicher, dass die dieses Getränk entfernen wills?') &&
this.deleteDrink({ id: item.id })
},
save() {
var drink = {
id: this.editedIndex,
name: this.editedItem.name,
type: this.editedItem.type.id,
price: !isNaN(this.editedItem.price)
? this.editedItem.price * 100
: null,
price_big: !isNaN(this.editedItem.price_big)
? this.editedItem.price_big * 100
: null,
price_club: !isNaN(this.editedItem.price_club)
? this.editedItem.price_club * 100
: null,
price_club_big: !isNaN(this.editedItem.price_club_big)
? this.editedItem.price_club_big * 100
: null,
premium: !isNaN(this.editedItem.premium)
? this.editedItem.premium * 100
: null,
premium_club: !isNaN(this.editedItem.premium_club)
? this.editedItem.premium_club * 100
: null,
price_extern_club: !isNaN(this.editedItem.price_extern_club)
? this.editedItem.price_extern_club * 100
: null
}
drink.id === -1 ? this.setDrink(drink) : this.updateDrink(drink)
this.editedItem = Object.assign({}, this.defaultItem)
this.close()
}
},
computed: {
...mapGetters({
priceList: 'priceList/priceList',
types: 'priceList/types',
priceListLoading: 'priceList/priceListLoading',
typesLoading: 'priceList/typesLoading',
isGastro: 'isGastro'
}),
formTitle() {
return this.editedIndex === -1 ? 'Neues Getränk' : 'Bearbeite Getränk'
},
inType() {
return text => {
return !!this.types.find(a => {
if (a.name === null || text === null) {
return true
} else {
return a.name.toLowerCase() === text.toLowerCase()
}
})
}
},
dialogTypeTitle() {
return this.editedType.id === -1
? 'Neue Kategorie'
: 'Bearbeite Kategorie'
},
computeType() {
return id => {
const type = this.types.find(a => {
return a.id === id
})
return type ? type.name : null
}
}
},
created() {
this.getPriceList()
this.getTypes()
if (this.isGastro) {
this.headers.push({
text: 'Aktion',
value: 'action',
sortable: false,
filterable: false
})
}
},
watch: {
dialog(val) {
val || this.close()
}
}
}
</script>
<style scoped></style>