594 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Vue
		
	
	
	
			
		
		
	
	
			594 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Vue
		
	
	
	
| <template>
 | |
|   <div>
 | |
|     <v-dialog v-model="checkValidate" max-width="290">
 | |
|       <v-card>
 | |
|         <v-card-title>
 | |
|           Willst du wirklich??
 | |
|         </v-card-title>
 | |
|         <v-card-text v-if="stornoMessage">
 | |
|           Willst du wirklich den Betrag
 | |
|           {{ (stornoMessage.amount / 100).toFixed(2) }}€ von
 | |
|           {{ stornoMessage.user.firstname }}
 | |
|           {{ stornoMessage.user.lastname }} stornieren?
 | |
|         </v-card-text>
 | |
|         <v-card-actions>
 | |
|           <v-spacer />
 | |
|           <v-btn text @click="cancelStorno">Abbrechen</v-btn>
 | |
|           <v-btn text @click="acceptStorno">Stornieren</v-btn>
 | |
|         </v-card-actions>
 | |
|       </v-card>
 | |
|     </v-dialog>
 | |
|     <v-dialog v-model="dialog" max-width="290">
 | |
|       <v-card>
 | |
|         <v-card-title class="headline"
 | |
|           >Transaktion ist länger als 1 Minute her!</v-card-title
 | |
|         >
 | |
|         <v-card-text>
 | |
|           Da die Transaktion länger als 1 Minuter her ist, kann eine Stornierung
 | |
|           nicht durchgeführt werden. Wende dich bitte an den Finanzer.
 | |
|         </v-card-text>
 | |
|         <v-card-actions>
 | |
|           <v-spacer />
 | |
|           <v-btn text @click="dialog = false">
 | |
|             Verstanden
 | |
|           </v-btn>
 | |
|         </v-card-actions>
 | |
|       </v-card>
 | |
|     </v-dialog>
 | |
|     <v-dialog
 | |
|       v-if="overLimitUser"
 | |
|       v-model="overLimitUser"
 | |
|       max-width="290"
 | |
|       persistent
 | |
|     >
 | |
|       <v-card>
 | |
|         <v-card-title>Warnung</v-card-title>
 | |
|         <v-card-text>
 | |
|           {{ overLimitUser.firstname }} {{ overLimitUser.lastname }} übersteigt
 | |
|           das Anschreibelimit von
 | |
|           {{ (overLimitUser.limit / 100).toFixed(2) }} €. Danach kann dieses
 | |
|           Mitglied nichts mehr anschreiben. Will er das wirklich?
 | |
|         </v-card-text>
 | |
|         <v-card-actions>
 | |
|           <v-spacer />
 | |
|           <v-btn text @click="cancel()">Abbrechen</v-btn>
 | |
|           <v-btn text @click="continueAdd(overLimitUser)">Anschreiben</v-btn>
 | |
|         </v-card-actions>
 | |
|       </v-card>
 | |
|     </v-dialog>
 | |
|     <v-dialog
 | |
|       v-if="overOverLimit"
 | |
|       v-model="overOverLimit"
 | |
|       max-width="290"
 | |
|       persistent
 | |
|     >
 | |
|       <v-card>
 | |
|         <v-card-title>Anschreiben nicht möglich</v-card-title>
 | |
|         <v-card-text>
 | |
|           {{ overOverLimit.firstname }}
 | |
|           {{ overOverLimit.lastname }} überschreitet das Anschreibelimit zuviel.
 | |
|           Das Anschreiben wurde daher gestoppt und zurückgesetzt.
 | |
|         </v-card-text>
 | |
|         <v-card-actions>
 | |
|           <v-btn text @click="overOverLimit = null">Verstanden</v-btn>
 | |
|         </v-card-actions>
 | |
|       </v-card>
 | |
|     </v-dialog>
 | |
|     <v-progress-linear v-if="loading && users.length !== 0" indeterminate />
 | |
|     <v-container>
 | |
|       <AddAmountSkeleton v-if="loading && users.length === 0" />
 | |
|     </v-container>
 | |
|     <v-navigation-drawer v-model="menu" right app clipped>
 | |
|       <v-list-item-group :key="componentRenderer">
 | |
|         <v-list-item inactive>
 | |
|           <v-list-item-title class="headline">
 | |
|             Verlauf
 | |
|           </v-list-item-title>
 | |
|         </v-list-item>
 | |
|         <v-divider />
 | |
|         <div
 | |
|           v-for="message in messages"
 | |
|           three-line
 | |
|           :key="messages.indexOf(message)"
 | |
|         >
 | |
|           <v-list-item three-line inactive @click="storno(message)">
 | |
|             <v-list-item-content>
 | |
|               <v-progress-linear indeterminate v-if="message.loading" />
 | |
|               <v-list-item-title>{{ now(message.date) }}</v-list-item-title>
 | |
|               <v-list-item-subtitle>{{
 | |
|                 createMessage(message)
 | |
|               }}</v-list-item-subtitle>
 | |
|               <v-list-item-subtitle class="red--text" v-if="message.storno">
 | |
|                 STORNIERT!!!
 | |
|               </v-list-item-subtitle>
 | |
|               <v-list-item-subtitle class="red--text" v-else-if="message.error">
 | |
|                 ERROR!
 | |
|               </v-list-item-subtitle>
 | |
|               <v-list-item-action-text v-if="under5minutes(message.date)"
 | |
|                 >Klicken um zu Stornieren
 | |
|               </v-list-item-action-text>
 | |
|             </v-list-item-content>
 | |
|           </v-list-item>
 | |
|         </div>
 | |
|       </v-list-item-group>
 | |
|     </v-navigation-drawer>
 | |
|     <div v-for="user in users" :key="users.indexOf(user)">
 | |
|       <div v-if="isFiltered(user) && calcLastSeen(user)">
 | |
|         <v-container>
 | |
|           <v-card :loading="user.loading">
 | |
|             <v-card-title>
 | |
|               <v-list-item-title class="title"
 | |
|                 >{{ user.firstname }} {{ user.lastname }}</v-list-item-title
 | |
|               >
 | |
|             </v-card-title>
 | |
|             <v-card-subtitle v-if="user.limit + user.amount > 0">
 | |
|               Nur noch {{ ((user.limit + user.amount) / 100).toFixed(2) }} €
 | |
|               übrig!!
 | |
|             </v-card-subtitle>
 | |
|             <v-card-text>
 | |
|               <v-row v-if="!user.locked">
 | |
|                 <v-col cols="10">
 | |
|                   <v-row>
 | |
|                     <v-col cols="6" xs="5" sm="4">
 | |
|                       <v-btn
 | |
|                         class="creditBtn"
 | |
|                         block
 | |
|                         @click="addingAmount(user, 200)"
 | |
|                         :color="color"
 | |
|                         :disabled="user.locked"
 | |
|                         >2 €
 | |
|                       </v-btn>
 | |
|                     </v-col>
 | |
|                     <v-col cols="6" xs="5" sm="4">
 | |
|                       <v-btn
 | |
|                         class="creditBtn"
 | |
|                         block
 | |
|                         @click="addingAmount(user, 100)"
 | |
|                         :color="color"
 | |
|                         :disabled="user.locked"
 | |
|                         >1 €
 | |
|                       </v-btn>
 | |
|                     </v-col>
 | |
|                     <v-col cols="6" xs="5" sm="4">
 | |
|                       <v-btn
 | |
|                         class="creditBtn"
 | |
|                         block
 | |
|                         @click="addingAmount(user, 50)"
 | |
|                         :color="color"
 | |
|                         :disabled="user.locked"
 | |
|                         >0,50 €
 | |
|                       </v-btn>
 | |
|                     </v-col>
 | |
|                     <v-col cols="6" xs="5" sm="4">
 | |
|                       <v-btn
 | |
|                         class="creditBtn"
 | |
|                         block
 | |
|                         @click="addingAmount(user, 40)"
 | |
|                         :color="color"
 | |
|                         :disabled="user.locked"
 | |
|                         >0,40 €
 | |
|                       </v-btn>
 | |
|                     </v-col>
 | |
|                     <v-col cols="6" xs="5" sm="4">
 | |
|                       <v-btn
 | |
|                         class="creditBtn"
 | |
|                         block
 | |
|                         @click="addingAmount(user, 20)"
 | |
|                         :color="color"
 | |
|                         :disabled="user.locked"
 | |
|                         >0,20 €
 | |
|                       </v-btn>
 | |
|                     </v-col>
 | |
|                     <v-col cols="6" xs="5" sm="4">
 | |
|                       <v-btn
 | |
|                         class="creditBtn"
 | |
|                         block
 | |
|                         @click="addingAmount(user, 10)"
 | |
|                         :color="color"
 | |
|                         :disabled="user.locked"
 | |
|                         >0,10 €
 | |
|                       </v-btn>
 | |
|                     </v-col>
 | |
|                     <v-col cols="8">
 | |
|                       <v-text-field
 | |
|                         outlined
 | |
|                         type="number"
 | |
|                         v-model="user.value"
 | |
|                         label="Benutzerdefinierter Betrag"
 | |
|                         :disabled="user.locked"
 | |
|                       ></v-text-field>
 | |
|                     </v-col>
 | |
|                     <v-col cols="4">
 | |
|                       <v-btn
 | |
|                         fab
 | |
|                         :color="color"
 | |
|                         @click="addAmountMore(user)"
 | |
|                         :disabled="user.locked"
 | |
|                       >
 | |
|                         <v-icon>{{ plus }}</v-icon>
 | |
|                       </v-btn>
 | |
|                     </v-col>
 | |
|                   </v-row>
 | |
|                 </v-col>
 | |
|                 <v-col align-self="center">
 | |
|                   <v-row>
 | |
|                     <v-list-item>
 | |
|                       <v-list-item-content class="text-center">
 | |
|                         <v-list-item-action-text :class="getColor(user.type)"
 | |
|                           >{{ (user.amount / 100).toFixed(2) }}
 | |
|                           €
 | |
|                         </v-list-item-action-text>
 | |
|                         <v-list-item-action-text v-if="user.toSetAmount">
 | |
|                           - {{ (user.toSetAmount / 100).toFixed(2) }}
 | |
|                         </v-list-item-action-text>
 | |
|                       </v-list-item-content>
 | |
|                     </v-list-item>
 | |
|                   </v-row>
 | |
|                 </v-col>
 | |
|               </v-row>
 | |
|               <v-row>
 | |
|                 <v-col class="hidden-sm-and-down" cols="80">
 | |
|                   <v-alert v-if="user.locked" type="error"
 | |
|                     >{{ user.firstname }} darf nicht mehr anschreiben.
 | |
|                     {{ user.firstname }} sollte sich lieber mal beim Finanzer
 | |
|                     melden.
 | |
|                   </v-alert>
 | |
|                 </v-col>
 | |
|                 <v-col align-self="center" v-if="user.locked">
 | |
|                   <v-row>
 | |
|                     <v-list-item>
 | |
|                       <v-list-item-content class="text-center">
 | |
|                         <v-list-item-action-text :class="getColor(user.type)"
 | |
|                           >{{ (user.amount / 100).toFixed(2) }}
 | |
|                           €
 | |
|                         </v-list-item-action-text>
 | |
|                       </v-list-item-content>
 | |
|                     </v-list-item>
 | |
|                   </v-row>
 | |
|                 </v-col>
 | |
|               </v-row>
 | |
|             </v-card-text>
 | |
|           </v-card>
 | |
|           <v-snackbar
 | |
|             :color="
 | |
|               messages.length > 0
 | |
|                 ? messages[0].error
 | |
|                   ? 'error'
 | |
|                   : 'success'
 | |
|                 : 'success'
 | |
|             "
 | |
|             bottom
 | |
|             :timeout="0"
 | |
|             :multi-line="true"
 | |
|             :value="messages.length > 0 ? messages[0].visible : test"
 | |
|             vertical
 | |
|           >
 | |
|             <v-list-item
 | |
|               v-for="message in messages"
 | |
|               :key="messages.indexOf(message)"
 | |
|               :style="
 | |
|                 message.error
 | |
|                   ? 'background-color: #FF5252;'
 | |
|                   : 'background-color: #4CAF50;'
 | |
|               "
 | |
|               v-show="message.visible"
 | |
|             >
 | |
|               <v-list-item-content>
 | |
|                 <v-list-item-title style="color: white">
 | |
|                   {{ createMessage(message) }}
 | |
|                 </v-list-item-title>
 | |
|               </v-list-item-content>
 | |
|               <v-list-item-action v-if="message.error">
 | |
|                 <v-btn icon @click="message.visible = false">
 | |
|                   <v-icon color="white">
 | |
|                     mdi-close
 | |
|                   </v-icon>
 | |
|                 </v-btn>
 | |
|               </v-list-item-action>
 | |
|             </v-list-item>
 | |
|           </v-snackbar>
 | |
|         </v-container>
 | |
|       </div>
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import { mapGetters, mapActions } from 'vuex'
 | |
| import { mdiPlus } from '@mdi/js'
 | |
| import AddAmountSkeleton from '../user/Skeleton/AddAmountSkeleton'
 | |
| 
 | |
| export default {
 | |
|   name: 'CreditLists',
 | |
|   components: { AddAmountSkeleton },
 | |
|   props: {},
 | |
|   data() {
 | |
|     return {
 | |
|       plus: mdiPlus,
 | |
|       value: null,
 | |
|       color: 'green accent-4',
 | |
|       menu: true,
 | |
|       dialog: false,
 | |
|       componentRenderer: 0,
 | |
|       timer: '',
 | |
|       stornoMessage: null,
 | |
|       checkValidate: false,
 | |
|       test: null,
 | |
|       overLimitUser: null,
 | |
|       overOverLimit: null
 | |
|     }
 | |
|   },
 | |
|   created() {
 | |
|     this.menu = this.menu_from_store
 | |
|     this.getUsers()
 | |
|     this.timer = setInterval(this.forceRender, 1000)
 | |
|   },
 | |
|   methods: {
 | |
|     ...mapActions({
 | |
|       addAmount: 'barUsers/addAmount',
 | |
|       getUsers: 'barUsers/getUsers',
 | |
|       deactivate: 'barUsers/deactivateMenu',
 | |
|       commitStorno: 'barUsers/storno'
 | |
|     }),
 | |
|     continueAdd(user) {
 | |
|       this.overLimitUser = null
 | |
|       user.checkedOverLimit = true
 | |
|       if (user.value) {
 | |
|         this.addAmount({
 | |
|           username: user.username,
 | |
|           amount: Math.round(Math.abs(user.value * 100)),
 | |
|           user: user
 | |
|         })
 | |
|         setTimeout(() => {
 | |
|           user.value = null
 | |
|           user.toSetAmount = null
 | |
|         }, 300)
 | |
|       } else {
 | |
|         user.timeout = setTimeout(() => {
 | |
|           this.addAmount({
 | |
|             username: user.username,
 | |
|             amount: user.toSetAmount,
 | |
|             user: user
 | |
|           })
 | |
|           setTimeout(() => {
 | |
|             user.toSetAmount = null
 | |
|           }, 300)
 | |
|         }, 2000)
 | |
|       }
 | |
|     },
 | |
|     cancel() {
 | |
|       this.overLimitUser.toSetAmount = null
 | |
|       this.overLimitUser.value = null
 | |
|       this.overLimitUser = null
 | |
|     },
 | |
|     checkOverLimitIsValid(user) {
 | |
|       if (user.toSetAmount) {
 | |
|         if (
 | |
|           Math.abs(user.amount - Number.parseInt(user.toSetAmount)) >
 | |
|           user.limit + 500
 | |
|         ) {
 | |
|           this.overOverLimit = user
 | |
|           user.toSetAmount = null
 | |
|           user.value = null
 | |
|           return false
 | |
|         }
 | |
|       }
 | |
|       return true
 | |
|     },
 | |
|     checkOverLimit(user) {
 | |
|       if (user.toSetAmount) {
 | |
|         if (Math.abs(user.amount - user.toSetAmount) > user.limit) {
 | |
|           return user.checkedOverLimit ? false : true
 | |
|         }
 | |
|       }
 | |
|       return false
 | |
|     },
 | |
|     addingAmount(user, amount) {
 | |
|       clearTimeout(user.timeout)
 | |
|       user.toSetAmount = user.toSetAmount ? user.toSetAmount + amount : amount
 | |
|       if (this.checkOverLimitIsValid(user)) {
 | |
|         if (this.checkOverLimit(user)) {
 | |
|           this.overLimitUser = user
 | |
|         } else {
 | |
|           user.timeout = setTimeout(() => {
 | |
|             this.addAmount({
 | |
|               username: user.username,
 | |
|               amount: user.toSetAmount,
 | |
|               user: user
 | |
|             })
 | |
|             setTimeout(() => {
 | |
|               user.toSetAmount = null
 | |
|             }, 300)
 | |
|           }, 2000)
 | |
|         }
 | |
|       }
 | |
|     },
 | |
|     forceRender() {
 | |
|       this.componentRenderer += 1
 | |
|     },
 | |
|     getColor(type) {
 | |
|       return type === 'credit' ? 'title green--text' : 'title red--text'
 | |
|     },
 | |
|     isFiltered(user) {
 | |
|       try {
 | |
|         var filters = this.filter.split(' ')
 | |
|         if (filters.length === 1) {
 | |
|           if (
 | |
|             user.firstname.toLowerCase().includes(filters[0].toLowerCase()) ||
 | |
|             user.lastname.toLowerCase().includes(filters[0].toLowerCase())
 | |
|           ) {
 | |
|             return true
 | |
|           }
 | |
|         } else if (filters.length > 1) {
 | |
|           if (
 | |
|             user.firstname.toLowerCase().includes(filters[0].toLowerCase()) &&
 | |
|             user.lastname.toLowerCase().includes(filters[1].toLowerCase())
 | |
|           ) {
 | |
|             return true
 | |
|           }
 | |
|         }
 | |
|         return false
 | |
|       } catch (e) {
 | |
|         return true
 | |
|       }
 | |
|     },
 | |
|     addAmountMore(user) {
 | |
|       user.toSetAmount = user.toSetAmount
 | |
|         ? user.toSetAmount + Math.round(Math.abs(user.value * 100))
 | |
|         : Math.round(Math.abs(user.value * 100))
 | |
|       if (this.checkOverLimitIsValid(user)) {
 | |
|         if (this.checkOverLimit(user)) {
 | |
|           this.overLimitUser = user
 | |
|         } else {
 | |
|           this.addAmount({
 | |
|             username: user.username,
 | |
|             amount: Math.round(Math.abs(user.value * 100)),
 | |
|             user: user
 | |
|           })
 | |
|           setTimeout(() => {
 | |
|             user.value = null
 | |
|             user.toSetAmount = null
 | |
|           }, 300)
 | |
|         }
 | |
|       }
 | |
|     },
 | |
|     storno(message) {
 | |
|       if (!message.error) {
 | |
|         if (!this.under5minutes(message.date)) this.dialog = true
 | |
|         else {
 | |
|           this.checkValidate = true
 | |
|           this.stornoMessage = message
 | |
|         }
 | |
|       }
 | |
|     },
 | |
|     acceptStorno() {
 | |
|       this.commitStorno({
 | |
|         username: this.stornoMessage.user.username,
 | |
|         amount: this.stornoMessage.amount,
 | |
|         date: this.stornoMessage.date
 | |
|       })
 | |
|       setTimeout(() => {
 | |
|         this.cancelStorno()
 | |
|       }, 300)
 | |
|     },
 | |
|     cancelStorno() {
 | |
|       this.stornoMessage = null
 | |
|       this.checkValidate = null
 | |
|     },
 | |
|     createMessage(message) {
 | |
|       var text = ''
 | |
|       if (message.error) {
 | |
|         text =
 | |
|           'ERROR: Konnte ' +
 | |
|           (message.amount / 100).toFixed(2) +
 | |
|           '€ nicht zu ' +
 | |
|           message.user.firstname +
 | |
|           ' ' +
 | |
|           message.user.lastname +
 | |
|           ' hinzufügen.'
 | |
|       } else {
 | |
|         text =
 | |
|           '' +
 | |
|           (message.amount / 100).toFixed(2) +
 | |
|           '€ wurde zu ' +
 | |
|           message.user.firstname +
 | |
|           ' ' +
 | |
|           message.user.lastname +
 | |
|           ' hinzugefügt.'
 | |
|       }
 | |
|       return text
 | |
|     },
 | |
|     calcLastSeen(user) {
 | |
|       if (user.last_seen) {
 | |
|         let date = new Date()
 | |
|         if ((date - user.last_seen) / 1000 / 60 / 60 < 72) {
 | |
|           return true
 | |
|         }
 | |
|       }
 | |
|       return false
 | |
|     }
 | |
|   },
 | |
|   computed: {
 | |
|     ...mapGetters({
 | |
|       users: 'barUsers/users',
 | |
|       filter: 'barUsers/filter',
 | |
|       loading: 'barUsers/usersLoading',
 | |
|       messages: 'barUsers/messages',
 | |
|       menu_from_store: 'barUsers/menu'
 | |
|     }),
 | |
|     under5minutes() {
 | |
|       return now => {
 | |
|         var actual = new Date()
 | |
|         return actual - now < 60000
 | |
|       }
 | |
|     },
 | |
|     now() {
 | |
|       return now => {
 | |
|         var actual = new Date()
 | |
|         var zero = new Date(0)
 | |
|         var date = new Date(actual - now)
 | |
|         if (date.getFullYear() === zero.getFullYear()) {
 | |
|           if (date.getMonth() === zero.getMonth()) {
 | |
|             if (date.getDate() === zero.getDate()) {
 | |
|               if (date.getHours() === zero.getDate()) {
 | |
|                 if (date.getMinutes() < 1) {
 | |
|                   return 'vor ' + date.getSeconds() + ' Sekunden'
 | |
|                 } else if (date.getMinutes() < 10) {
 | |
|                   return 'vor ' + date.getMinutes() + ' Minuten'
 | |
|                 } else {
 | |
|                   return (
 | |
|                     (now.getHours() < 10 ? '0' : '') +
 | |
|                     now.getHours() +
 | |
|                     ':' +
 | |
|                     (now.getMinutes() < 10 ? '0' : '') +
 | |
|                     now.getMinutes()
 | |
|                   )
 | |
|                 }
 | |
|               } else {
 | |
|                 return (
 | |
|                   (now.getHours() < 10 ? '0' : '') +
 | |
|                   now.getHours() +
 | |
|                   ':' +
 | |
|                   (now.getMinutes() < 10 ? '0' : '') +
 | |
|                   now.getMinutes()
 | |
|                 )
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         return (
 | |
|           now.getDate() +
 | |
|           '.' +
 | |
|           now.getMonth() +
 | |
|           '.' +
 | |
|           now.getFullYear() +
 | |
|           ' ' +
 | |
|           (now.getHours() < 10 ? '0' : '') +
 | |
|           now.getHours() +
 | |
|           ':' +
 | |
|           (now.getMinutes() < 10 ? '0' : '') +
 | |
|           now.getMinutes()
 | |
|         )
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   watch: {
 | |
|     menu(newValue) {
 | |
|       if (!newValue) this.deactivate()
 | |
|     },
 | |
|     menu_from_store() {
 | |
|       this.menu = this.menu_from_store
 | |
|     }
 | |
|   },
 | |
|   beforeDestroy() {
 | |
|     clearInterval(this.timer)
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style scoped>
 | |
| .creditBtn {
 | |
|   margin: 2px;
 | |
| }
 | |
| </style>
 |