[Vue3] Fixed pricelist
This commit is contained in:
		
							parent
							
								
									62aa627f0c
								
							
						
					
					
						commit
						5153f074b5
					
				|  | @ -13,10 +13,10 @@ declare namespace FG { | |||
|     firstname: string; | ||||
|     lastname: string; | ||||
|     mail: string; | ||||
|     birthday?: Date; | ||||
|     birthday?: any; | ||||
|     roles: Array<string>; | ||||
|     permissions?: Array<string>; | ||||
|     avatar_url?: string; | ||||
|     permissions?: any; | ||||
|     avatar_url?: any; | ||||
|   } | ||||
|   type Permission = string; | ||||
|   interface Role { | ||||
|  | @ -29,58 +29,41 @@ declare namespace FG { | |||
|     time: Date; | ||||
|     amount: number; | ||||
|     reversal_id: number; | ||||
|     sender_id?: string; | ||||
|     receiver_id?: string; | ||||
|     author_id?: string; | ||||
|     original_id?: number; | ||||
|     sender_id?: any; | ||||
|     receiver_id?: any; | ||||
|     author_id?: any; | ||||
|     original_id?: any; | ||||
|   } | ||||
|   interface Drink { | ||||
|     id: number; | ||||
|     article_id?: string; | ||||
|     package_size?: number; | ||||
|     name: string; | ||||
|     volume?: number; | ||||
|     cost_price_pro_volume?: number; | ||||
|     cost_price_package_netto?: number; | ||||
|     tags?: Array<Tag>; | ||||
|     type?: DrinkType; | ||||
|     volumes: Array<DrinkPriceVolume>; | ||||
|   } | ||||
|   interface DrinkIngredient { | ||||
|     id: number; | ||||
|     volume: number; | ||||
|     drink_ingredient_id: number; | ||||
|     cost_price: number; | ||||
|     discount: number; | ||||
|     extra_charge?: any; | ||||
|     prices: Array<DrinkPrice>; | ||||
|     ingredients: Array<Ingredient>; | ||||
|     tags: Array<any>; | ||||
|   } | ||||
|   interface DrinkPrice { | ||||
|     id: number; | ||||
|     price: number; | ||||
|     public: boolean; | ||||
|     description?: string; | ||||
|   } | ||||
|   interface DrinkPriceVolume { | ||||
|     id: number; | ||||
|     volume: number; | ||||
|     min_prices: Array<MinPrices>; | ||||
|     prices: Array<DrinkPrice>; | ||||
|     ingredients: Array<Ingredient>; | ||||
|     price: number; | ||||
|     no_auto: boolean; | ||||
|     public: boolean; | ||||
|     description?: any; | ||||
|     round_step: number; | ||||
|   } | ||||
|   interface DrinkType { | ||||
|     id: number; | ||||
|     name: string; | ||||
|   } | ||||
|   interface ExtraIngredient { | ||||
|     id: number; | ||||
|     name: string; | ||||
|     price: number; | ||||
|   } | ||||
|   interface Ingredient { | ||||
|     id: number; | ||||
|     drink_ingredient?: DrinkIngredient; | ||||
|     extra_ingredient?: ExtraIngredient; | ||||
|   } | ||||
|   interface MinPrices { | ||||
|     percentage: number; | ||||
|     price: number; | ||||
|     volume: number; | ||||
|     drink_parent_id: number; | ||||
|     drink_ingredient_id: number; | ||||
|     drink_ingredient?: any; | ||||
|   } | ||||
|   interface Tag { | ||||
|     id: number; | ||||
|  | @ -90,7 +73,7 @@ declare namespace FG { | |||
|     id: number; | ||||
|     start: Date; | ||||
|     end: Date; | ||||
|     description?: string; | ||||
|     description?: any; | ||||
|     type: EventType; | ||||
|     jobs: Array<Job>; | ||||
|   } | ||||
|  | @ -101,7 +84,7 @@ declare namespace FG { | |||
|   interface Job { | ||||
|     id: number; | ||||
|     start: Date; | ||||
|     end?: Date; | ||||
|     end?: any; | ||||
|     comment: string; | ||||
|     type: JobType; | ||||
|     services: Array<Service>; | ||||
|  |  | |||
|  | @ -0,0 +1,162 @@ | |||
| <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 | ||||
|               v-model="drink.name" | ||||
|               class="col-12 col-sm-6 q-px-sm q-py-md" | ||||
|               filled | ||||
|               label="Name" | ||||
|             /> | ||||
|             <q-input | ||||
|               v-model="drink.volume" | ||||
|               class="col-12 col-sm-6 q-px-sm q-py-md" | ||||
|               filled | ||||
|               label="Inhalt in Liter" | ||||
|               type="number" | ||||
|               step="0.01" | ||||
|             /> | ||||
|             <q-input | ||||
|               v-model="drink.cost_price" | ||||
|               class="col-12 col-sm-6 q-px-sm q-py-md" | ||||
|               filled | ||||
|               label="Einkaufspreis" | ||||
|               type="number" | ||||
|               step="0.01" | ||||
|             /> | ||||
|             <q-input | ||||
|               v-model="drink.discount" | ||||
|               class="col-12 col-sm-6 q-px-sm q-py-md" | ||||
|               filled | ||||
|               label="Aufschlag in Prozent" | ||||
|               type="number" | ||||
|               hint="Wenn nicht gesetzt wird default-wert genommen." | ||||
|               step="0.01" | ||||
|             /> | ||||
|             <q-input | ||||
|               v-model="drink.extra_charge" | ||||
|               class="col-12 col-sm-6 q-px-sm q-py-md" | ||||
|               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" color="primary" @click="addPrice" /> | ||||
|           </div> | ||||
|           <q-card v-for="(price, index) in drink.prices" :key="index" class="q-ma-sm"> | ||||
|             <div class="row"> | ||||
|               <q-input | ||||
|                 v-model="price.volume" | ||||
|                 class="col-12 col-sm-6 q-px-sm q-py-md" | ||||
|                 label="Inhalt in Liter" | ||||
|                 filled | ||||
|                 type="number" | ||||
|                 step="0.01" | ||||
|               /> | ||||
|               <q-input | ||||
|                 v-model="price.price" | ||||
|                 class="col-12 col-sm-6 q-px-sm q-py-md" | ||||
|                 label="Preis in €" | ||||
|                 filled | ||||
|                 :disable="price.no_auto" | ||||
|                 type="number" | ||||
|                 step="0.1" | ||||
|               /> | ||||
|               <q-toggle | ||||
|                 v-model="price.no_auto" | ||||
|                 class="col-12 col-sm-6 q-px-sm q-py-md" | ||||
|                 label="Automatische Preiskalkulation" | ||||
|                 color="primary" | ||||
|               /> | ||||
|               <q-input | ||||
|                 v-model="price.round_step" | ||||
|                 class="col-12 col-sm-6 q-px-sm q-py-md" | ||||
|                 label="Rundungsschritt" | ||||
|                 type="number" | ||||
|                 filled | ||||
|                 step="0.1" | ||||
|               /> | ||||
|               <q-toggle | ||||
|                 v-model="price.public" | ||||
|                 class="col-12 col-sm-6 q-px-sm q-py-md" | ||||
|                 label="Öffentlich" | ||||
|                 color="primary" | ||||
|               /> | ||||
|               <q-input | ||||
|                 v-model="price.description" | ||||
|                 class="col-12 col-sm-6 q-px-sm q-py-md" | ||||
|                 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 } from 'vue'; | ||||
| import { useStore } from 'vuex'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   name: 'Drink', | ||||
|   setup() { | ||||
|     const store = useStore(); | ||||
|     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> | ||||
|  | @ -6,7 +6,7 @@ | |||
|           <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-input v-model="newDrinkTypeName" dense label="name" filled /> | ||||
|         </q-card-section> | ||||
|         <q-card-actions> | ||||
|           <q-btn flat color="danger" label="Abbrechen" @click="discardChanges()" /> | ||||
|  | @ -17,11 +17,11 @@ | |||
| 
 | ||||
|     <q-page padding> | ||||
|       <q-table title="Getränkearten" :data="rows" :row-key="(row) => row.id" :columns="columns"> | ||||
|         <template v-slot:top-right> | ||||
|         <template #top-right> | ||||
|           <q-input | ||||
|             v-model="newDrinkType" | ||||
|             class="q-px-sm" | ||||
|             dense | ||||
|             v-model="newDrinkType" | ||||
|             placeholder="Neue Getränkeart" | ||||
|             filled | ||||
|           /> | ||||
|  | @ -29,7 +29,7 @@ | |||
|           <div></div> | ||||
|           <q-btn color="primary" icon="mdi-plus" label="Hinzufügen" @click="addType" /> | ||||
|         </template> | ||||
|         <template v-slot:body-cell-actions="props"> | ||||
|         <template #body-cell-actions="props"> | ||||
|           <q-td :props="props" align="right" :auto-width="true"> | ||||
|             <q-btn | ||||
|               round | ||||
|  | @ -46,15 +46,14 @@ | |||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent, onBeforeMount, ref } from '@vue/composition-api'; | ||||
| import { Store } from 'vuex'; | ||||
| import { StateInterface } from 'src/store'; | ||||
| import { computed, defineComponent, onBeforeMount, ref } from 'vue'; | ||||
| import { useStore } from 'vuex'; | ||||
| import { DrinkInterface } from 'src/plugins/pricelist/store/drinks'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   name: 'DrinkTypes', | ||||
|   setup(_, { root }) { | ||||
|     const store = <Store<StateInterface>>root.$store; | ||||
|   setup() { | ||||
|     const store = useStore(); | ||||
|     const state = <DrinkInterface>store.state.drink; | ||||
|     const newDrinkType = ref(''); | ||||
|     const newDrinkTypeName = ref(''); | ||||
|  |  | |||
|  | @ -1,14 +1,14 @@ | |||
| <template> | ||||
|   <div> | ||||
|     <q-table title="Getränke" :columns="columns" :data="drinks" row-key="name"> | ||||
|       <template v-slot:body-cell-prices="{ row: { prices } }"> | ||||
|       <template #body-cell-prices="{ row: { prices } }"> | ||||
|         <q-td> | ||||
|           <div v-for="price in prices" :key="price.id" class="row"> | ||||
|             <div class="col"> | ||||
|               {{ price.volume | setVolume }} | ||||
|               {{ setVolume(price.volume) }} | ||||
|             </div> | ||||
|             <div class="col"> | ||||
|               {{ price.price | setCurrency }} | ||||
|               {{ setCurrency(price.price) }} | ||||
|             </div> | ||||
|             <div class="col"> | ||||
|               {{ price.description }} | ||||
|  | @ -20,10 +20,11 @@ | |||
|   </div> | ||||
| </template> | ||||
| <script lang="ts"> | ||||
| import { defineComponent, onBeforeMount, ref } from '@vue/composition-api'; | ||||
| import { defineComponent, onBeforeMount, ref } from 'vue'; | ||||
| import { StateInterface } from 'src/store'; | ||||
| import { DrinkInterface } from '../store/drinks'; | ||||
| import { Store } from 'vuex'; | ||||
| import { useStore } from 'vuex'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   name: 'Pricelist', | ||||
|   filters: { | ||||
|  | @ -37,8 +38,8 @@ export default defineComponent({ | |||
|       return `${price.toFixed(2)}€`; | ||||
|     }, | ||||
|   }, | ||||
|   setup(_, { root }) { | ||||
|     const store = <Store<StateInterface>>root.$store; | ||||
|   setup() { | ||||
|     const store = useStore(); | ||||
|     const state = <DrinkInterface>store.state.drink; | ||||
|     const drinks = ref(state.drinks); | ||||
|     onBeforeMount(() => { | ||||
|  |  | |||
|  | @ -1,44 +0,0 @@ | |||
| <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, onBeforeMount } from '@vue/composition-api'; | ||||
| import EssentialLink from 'src/components/navigation/EssentialLink.vue'; | ||||
| import mainRoutes from '../routes'; | ||||
| import store from '../store/altStore'; | ||||
| export default defineComponent({ | ||||
|   // name: 'PageName' | ||||
|   components: { EssentialLink }, | ||||
|   setup(_, { root }) { | ||||
|     const checkMain = computed(() => { | ||||
|       return root.$route.matched.length == 2; | ||||
|     }); | ||||
|     onBeforeMount(() => { | ||||
|       store.actions.getDrinks(); | ||||
|       store.actions.getExtraIngredients(); | ||||
|       store.actions.getDrinkTypes(); | ||||
|     }); | ||||
| 
 | ||||
|     return { checkMain, mainRoutes }; | ||||
|   }, | ||||
| }); | ||||
| </script> | ||||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
|   <div> | ||||
|     <q-tabs v-model="tab" v-if="$q.screen.gt.sm"> | ||||
|     <q-tabs v-if="$q.screen.gt.sm" v-model="tab"> | ||||
|       <q-tab | ||||
|         v-for="(tabindex, index) in tabs" | ||||
|         :key="'tab' + index" | ||||
|  | @ -8,10 +8,10 @@ | |||
|         :label="tabindex.label" | ||||
|       /> | ||||
|     </q-tabs> | ||||
|     <div class="fit row justify-end" v-else> | ||||
|     <div v-else class="fit row justify-end"> | ||||
|       <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-drawer v-model="showDrawer" side="right" behavior="mobile" @click="showDrawer = !showDrawer"> | ||||
|       <q-list v-model="tab"> | ||||
|         <q-item | ||||
|           v-for="(tabindex, index) in tabs" | ||||
|  | @ -46,7 +46,7 @@ | |||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent, ref } from '@vue/composition-api'; | ||||
| import { computed, defineComponent, ref } from 'vue'; | ||||
| import { Screen } from 'quasar'; | ||||
| import DrinkTypes from 'src/plugins/pricelist/components/DrinkTypes.vue'; | ||||
| import CalculationTable from 'src/plugins/pricelist/components/CalculationTable.vue'; | ||||
|  |  | |||
|  | @ -3,28 +3,34 @@ 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'] }, | ||||
|     route: { | ||||
|       path: 'drinks', | ||||
|       name: 'drinks', | ||||
|       redirect: { name: 'drinks-pricelist' }, | ||||
|     }, | ||||
|     permissions: ['user'], | ||||
|     children: [ | ||||
|       { | ||||
|         title: 'Preisliste', | ||||
|         icon: 'mdi-cash-100', | ||||
|         path: 'pricelist', | ||||
|         name: 'drinks-pricelist', | ||||
|         shortcut: true, | ||||
|         meta: { permissions: ['user'] }, | ||||
|         component: () => import('../pages/Pricelist.vue'), | ||||
|         permissions: ['user'], | ||||
|         route: { | ||||
|           path: 'pricelist', | ||||
|           name: 'drinks-pricelist', | ||||
|           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'), | ||||
|         permissions: ['pricelist_settings'], | ||||
|         route: { | ||||
|           path: 'settings', | ||||
|           name: 'drinks-settings', | ||||
|           component: () => import('../pages/Settings.vue'), | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
|   }, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue