Improved Transaction design and function
This commit is contained in:
		
							parent
							
								
									e366a25838
								
							
						
					
					
						commit
						a787abdbc0
					
				|  | @ -24,5 +24,6 @@ | |||
|       "sortAttributes": false | ||||
|     } | ||||
|   }, | ||||
|   "vetur.format.defaultFormatter.ts": "prettier-tslint" | ||||
|   "vetur.format.defaultFormatter.ts": "prettier-tslint", | ||||
|   "typescript.format.enable": false | ||||
| } | ||||
|  |  | |||
|  | @ -1,24 +1,33 @@ | |||
| <template> | ||||
|   <q-card> | ||||
|     <q-card-actions align="right"> | ||||
|       <q-btn | ||||
|         :color="color()" | ||||
|         icon="mdi-trash-can" | ||||
|         aria-label="Löschen" | ||||
|         :disable="disabled()" | ||||
|         @click="reverse(transaction)" | ||||
|       /> | ||||
|     </q-card-actions> | ||||
|     <q-card-section> | ||||
|       <span>{{ timeStr }}: {{ transaction.amount }}</span> | ||||
|   <q-card v-bind:class="{ 'bg-grey': isReversed }"> | ||||
|     <q-card-section class="row items-start justify-between"> | ||||
|       <div class="col text-center"> | ||||
|         <div | ||||
|           v-bind:class="{ 'text-negative': isNegative() }" | ||||
|           class="text-weight-bold" | ||||
|           style="font-size: 2em" | ||||
|         > | ||||
|           <span v-if="isNegative()">-</span>{{ transaction.amount.toFixed(2) }} € | ||||
|         </div> | ||||
|         <div>{{ text }}</div> | ||||
|         <div>{{ timeStr }}</div> | ||||
|       </div> | ||||
|       <div class="col" style="text-align: right"> | ||||
|         <q-btn | ||||
|           color="negative" | ||||
|           aria-label="Reverse transaction" | ||||
|           icon="mdi-trash-can" | ||||
|           square | ||||
|           :disable="!canReverse" | ||||
|           @click="reverse" | ||||
|         /> | ||||
|       </div> | ||||
|     </q-card-section> | ||||
|   </q-card> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| // TODO: Better styling | ||||
| 
 | ||||
| import { ref, computed, defineComponent, onUnmounted } from '@vue/composition-api'; | ||||
| import { ref, computed, defineComponent, onUnmounted, onMounted } from '@vue/composition-api'; | ||||
| import { hasPermission } from 'src/utils/permission'; | ||||
| import { formatDateTime } from 'src/utils/datetime'; | ||||
| import { StateInterfaceBalance } from 'src/plugins/balance/store/balance'; | ||||
|  | @ -30,36 +39,60 @@ interface Props { | |||
| 
 | ||||
| export default defineComponent({ | ||||
|   name: 'Transaction', | ||||
|   props: ['transaction'], | ||||
|   props: { | ||||
|     transaction: { | ||||
|       type: Object, | ||||
|       required: true | ||||
|     } | ||||
|   }, | ||||
|   watch: { transaction: 'refreshText' }, | ||||
|   setup(props: Props, { root, emit }) { | ||||
|     const now = ref(Date.now()); | ||||
|     const ival = setInterval(() => (now.value = Date.now()), 1000); | ||||
|     const store: Store<StateInterfaceBalance> = <Store<StateInterfaceBalance>>root.$store; | ||||
|     const text = ref(''); | ||||
| 
 | ||||
|     onUnmounted(() => clearInterval(ival)); | ||||
|     onMounted(() => refreshText()); | ||||
| 
 | ||||
|     function canReverse(transaction: FG.Transaction) { | ||||
|       return ( | ||||
|         hasPermission('balance_reversal', store) || | ||||
|         (transaction.sender_id === store.state.user.currentUser?.userid && | ||||
|           Date.now() - transaction.time.getTime() < 10000) | ||||
|       ); | ||||
|     } | ||||
|     const isNegative = () => props.transaction.sender_id === store.state.user.currentUser?.userid; | ||||
| 
 | ||||
|     function color() { | ||||
|       return canReverse(props.transaction) ? 'negative' : 'grey'; | ||||
|     } | ||||
|     const refreshText = async () => { | ||||
|       if (isNegative()) { | ||||
|         text.value = 'Anschreiben'; | ||||
|         if (props.transaction.receiver_id !== null) { | ||||
|           const user = <FG.User>await store.dispatch('user/getUser', { | ||||
|             userid: props.transaction.receiver_id | ||||
|           }); | ||||
|           text.value = `Gesendet an ${user.display_name}`; | ||||
|         } | ||||
|       } else { | ||||
|         text.value = 'Gutschrift'; | ||||
|         if (props.transaction.sender_id !== null) { | ||||
|           const user = <FG.User>await store.dispatch('user/getUser', { | ||||
|             userid: props.transaction.sender_id | ||||
|           }); | ||||
|           text.value = `Bekommen von ${user.display_name}`; | ||||
|         } | ||||
|       } | ||||
|     }; | ||||
| 
 | ||||
|     function disabled() { | ||||
|       return !canReverse(props.transaction); | ||||
|     } | ||||
|     const isReversed = computed(() => props.transaction.reversal != undefined); | ||||
| 
 | ||||
|     function reverse(transaction: FG.Transaction) { | ||||
|       if (canReverse(transaction)) | ||||
|     const canReverse = computed( | ||||
|       () => | ||||
|         !isReversed.value && | ||||
|         (hasPermission('balance_reversal', store) || | ||||
|           (props.transaction.sender_id === store.state.user.currentUser?.userid && | ||||
|             now.value - props.transaction.time.getTime() < 10000)) | ||||
|     ); | ||||
| 
 | ||||
|     function reverse() { | ||||
|       if (canReverse.value) | ||||
|         store | ||||
|           .dispatch('balance/revert', transaction) | ||||
|           .dispatch('balance/revert', props.transaction) | ||||
|           .then(() => { | ||||
|             emit('reversed', transaction.id); | ||||
|             emit('update:transaction', props.transaction); | ||||
|           }) | ||||
|           .catch(error => console.log(error)); | ||||
|     } | ||||
|  | @ -70,7 +103,7 @@ export default defineComponent({ | |||
|       return formatDateTime(props.transaction.time, elapsed > 12 * 60 * 60, true, true) + ' Uhr'; | ||||
|     }); | ||||
| 
 | ||||
|     return { timeStr, disabled, color, reverse }; | ||||
|     return { timeStr, reverse, isNegative, text, refreshText, canReverse, isReversed }; | ||||
|   } | ||||
| }); | ||||
| </script> | ||||
|  |  | |||
|  | @ -56,8 +56,9 @@ | |||
|         </q-card-section> | ||||
|       </q-card> | ||||
|     </div> | ||||
|     <div v-for="(transaction, index) in transactions" v-bind:key="index" class="col-sm-4 col-xs-6"> | ||||
|       <Transaction :transaction="transaction" @reversed="reversed" /> | ||||
|     <div v-for="(transaction, index) in transactions" v-bind:key="index" class="col-md-4 col-sm-6"> | ||||
|       <!-- TODO: In Vue3 use v-model:transaction="..." --> | ||||
|       <Transaction :transaction.sync="transactions[index]" /> | ||||
|     </div> | ||||
|   </q-page> | ||||
| </template> | ||||
|  | @ -80,7 +81,7 @@ export default defineComponent({ | |||
| 
 | ||||
|     const amount = ref<number>(0); | ||||
|     const showAddShortcut = ref(false); | ||||
|     const transactions = ref<FG.Transaction[]>([]); | ||||
|     const transactions = computed(() => store.state.balance.transactions.slice().reverse()); | ||||
|     const user = ref(store.state.user.currentUser); | ||||
|     const shortCuts = ref(store.state.balance.shortcuts); | ||||
| 
 | ||||
|  | @ -89,7 +90,7 @@ export default defineComponent({ | |||
|     ); | ||||
| 
 | ||||
|     function addShortcut() { | ||||
|       void store.dispatch('balance/addShortcut', amount.value * -1); | ||||
|       if (amount.value != 0) void store.dispatch('balance/addShortcut', amount.value * -1); | ||||
|     } | ||||
|     function removeShortcut(shortcut: number) { | ||||
|       void store.dispatch('balance/removeShortcut', shortcut); | ||||
|  | @ -100,19 +101,9 @@ export default defineComponent({ | |||
|     function changeBalance(amount: number) { | ||||
|       store | ||||
|         .dispatch('balance/changeBalance', { amount: amount, user: user.value?.userid }) | ||||
|         .then((transaction: FG.Transaction) => { | ||||
|           if (transactions.value.length > 5) transactions.value.pop(); | ||||
|           transaction.time = new Date(transaction.time); | ||||
|           transactions.value.unshift(transaction); | ||||
|           console.log(transactions.value); | ||||
|         }) | ||||
|         .catch(err => console.log(err)); | ||||
|     } | ||||
| 
 | ||||
|     function reversed(id: number) { | ||||
|       transactions.value = transactions.value.filter(t => t.id != id); | ||||
|     } | ||||
| 
 | ||||
|     return { | ||||
|       user, | ||||
|       addShortcut, | ||||
|  | @ -123,7 +114,6 @@ export default defineComponent({ | |||
|       amount, | ||||
|       showSelector, | ||||
|       shortCuts, | ||||
|       reversed, | ||||
|       userUpdated | ||||
|     }; | ||||
|   } | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ | |||
|       </q-card> | ||||
|     </div> | ||||
|     <div v-for="(transaction, index) in transactions" v-bind:key="index" class="col-sm-4 col-xs-6"> | ||||
|       <Transaction :transaction="transaction" @reversed="reversed" /> | ||||
|       <Transaction :transaction.sync="transactions[index]" /> | ||||
|     </div> | ||||
|   </q-page> | ||||
| </template> | ||||
|  | @ -56,7 +56,7 @@ export default defineComponent({ | |||
|     const sender = ref(store.state.user.currentUser); | ||||
|     const receiver = ref<FG.User | undefined>(undefined); | ||||
|     const amount = ref<number>(0); | ||||
|     const transactions = ref<FG.Transaction[]>([]); | ||||
|     const transactions = computed(() => store.state.balance.transactions.slice().reverse()); | ||||
| 
 | ||||
|     const sendDisabled = computed(() => { | ||||
|       return !( | ||||
|  | @ -75,10 +75,6 @@ export default defineComponent({ | |||
|       receiver.value = selectedUser; | ||||
|     } | ||||
| 
 | ||||
|     function reversed(id: number) { | ||||
|       transactions.value = transactions.value.filter(value => value.id != id); | ||||
|     } | ||||
| 
 | ||||
|     function sendAmount() { | ||||
|       store | ||||
|         .dispatch('balance/changeBalance', { | ||||
|  | @ -86,11 +82,6 @@ export default defineComponent({ | |||
|           sender: sender.value?.userid, | ||||
|           user: receiver.value?.userid | ||||
|         }) | ||||
|         .then((transaction: FG.Transaction) => { | ||||
|           if (transactions.value.length > 5) transactions.value.pop(); | ||||
|           transaction.time = new Date(transaction.time); | ||||
|           transactions.value.unshift(transaction); | ||||
|         }) | ||||
|         .catch(err => console.log(err)); | ||||
|     } | ||||
| 
 | ||||
|  | @ -103,8 +94,7 @@ export default defineComponent({ | |||
|       showSelector, | ||||
|       senderUpdated, | ||||
|       receiverUpdated, | ||||
|       sendDisabled, | ||||
|       reversed | ||||
|       sendDisabled | ||||
|     }; | ||||
|   } | ||||
| }); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue