Improve display of zero values

also unify number class construction by using a helper

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2024-01-27 13:43:40 +01:00
parent 9f2c456c78
commit b4dd06463d
Signed by: luzifer
SSH key fingerprint: SHA256:/xtE5lCgiRDQr8SLxHMS92ZBlACmATUmF1crK16Ks4E
4 changed files with 45 additions and 13 deletions

View file

@ -25,7 +25,9 @@
<div class="col d-flex align-items-center"> <div class="col d-flex align-items-center">
<div class="d-flex align-items-start"> <div class="d-flex align-items-start">
<div class="d-inline-flex text-center flex-column me-4"> <div class="d-inline-flex text-center flex-column me-4">
{{ formatNumber(account.balance - balanceUncleared) }} <span :class="classFromNumber(account.balance - balanceUncleared)">
{{ formatNumber(account.balance - balanceUncleared) }}
</span>
<span class="form-text mt-0"> <span class="form-text mt-0">
<i class="fas fa-fw fa-copyright mr-1 text-success" /> <i class="fas fa-fw fa-copyright mr-1 text-success" />
Cleared Balance Cleared Balance
@ -33,7 +35,9 @@
</div> </div>
+ +
<div class="d-inline-flex text-center flex-column mx-4"> <div class="d-inline-flex text-center flex-column mx-4">
{{ formatNumber(balanceUncleared) }} <span :class="classFromNumber(balanceUncleared)">
{{ formatNumber(balanceUncleared) }}
</span>
<span class="form-text mt-0"> <span class="form-text mt-0">
<i class="fas fa-fw fa-copyright mr-1" /> <i class="fas fa-fw fa-copyright mr-1" />
Uncleared Balance Uncleared Balance
@ -41,7 +45,9 @@
</div> </div>
= =
<div class="d-inline-flex text-center flex-column ms-4"> <div class="d-inline-flex text-center flex-column ms-4">
{{ formatNumber(account.balance) }} <span :class="classFromNumber(account.balance)">
{{ formatNumber(account.balance) }}
</span>
<span class="form-text mt-0">Working Balance</span> <span class="form-text mt-0">Working Balance</span>
</div> </div>
</div> </div>
@ -168,7 +174,7 @@
{{ accountIdToName[tx.category] }} {{ accountIdToName[tx.category] }}
</td> </td>
<td>{{ tx.description }}</td> <td>{{ tx.description }}</td>
<td :class="{'minimized-amount text-end': true, 'text-danger': tx.amount < 0}"> <td :class="classFromNumber(tx.amount, ['minimized-amount', 'text-end'])">
{{ formatNumber(tx.amount) }} {{ formatNumber(tx.amount) }}
</td> </td>
<td> <td>
@ -329,7 +335,7 @@
import { Modal } from 'bootstrap' import { Modal } from 'bootstrap'
import accountEditor from './accountEditor.vue' import accountEditor from './accountEditor.vue'
import { formatNumber } from '../helpers' import { classFromNumber, formatNumber } from '../helpers'
import rangeSelector from './rangeSelector.vue' import rangeSelector from './rangeSelector.vue'
import txEditor from './txEditor.vue' import txEditor from './txEditor.vue'
@ -437,6 +443,8 @@ export default {
emits: ['update-accounts'], emits: ['update-accounts'],
methods: { methods: {
classFromNumber,
deleteSelected() { deleteSelected() {
const actions = [] const actions = []
for (const id of this.selectedTx) { for (const id of this.selectedTx) {

View file

@ -2,7 +2,7 @@
<li class="mb-1 fw-semibold"> <li class="mb-1 fw-semibold">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<i class="fas fa-fw fa-credit-card me-1" /> {{ header }} <i class="fas fa-fw fa-credit-card me-1" /> {{ header }}
<span :class="{'ms-auto': true, 'text-danger': sum < 0}"> <span :class="classFromNumber(sum, ['ms-auto'])">
{{ formatNumber(sum) }} {{ formatNumber(sum) }}
</span> </span>
</div> </div>
@ -15,7 +15,7 @@
:to="{ name: 'account-transactions', params: { accountId: acc.id }}" :to="{ name: 'account-transactions', params: { accountId: acc.id }}"
> >
{{ acc.name }} {{ acc.name }}
<span :class="{'ms-auto': true, 'text-danger': acc.balance < 0}"> <span :class="classFromNumber(acc.balance, ['ms-auto'])">
{{ formatNumber(acc.balance) }} {{ formatNumber(acc.balance) }}
</span> </span>
</router-link> </router-link>
@ -25,7 +25,7 @@
</template> </template>
<script> <script>
import { formatNumber } from '../helpers' import { classFromNumber, formatNumber } from '../helpers'
export default { export default {
computed: { computed: {
@ -35,6 +35,7 @@ export default {
}, },
methods: { methods: {
classFromNumber,
formatNumber, formatNumber,
}, },

View file

@ -10,7 +10,7 @@
</div> </div>
<div class="col d-flex align-items-center justify-content-center"> <div class="col d-flex align-items-center justify-content-center">
<div :class="unallocatedMoneyClass"> <div :class="unallocatedMoneyClass">
<span class="fs-4">{{ formatNumber(unallocatedMoney) }} </span> <span :class="classFromNumber(unallocatedMoney, ['fs-4'])">{{ formatNumber(unallocatedMoney) }} </span>
<span class="small">Unallocated</span> <span class="small">Unallocated</span>
</div> </div>
</div> </div>
@ -59,15 +59,15 @@
{{ cat.name }} {{ cat.name }}
</a> </a>
</td> </td>
<td :class="{'text-end': true, 'text-danger': (allocatedByCategory[cat.id] || 0) < 0}"> <td :class="classFromNumber(allocatedByCategory[cat.id] || 0, ['text-end'])">
{{ formatNumber(allocatedByCategory[cat.id] || 0) }} {{ formatNumber(allocatedByCategory[cat.id] || 0) }}
</td> </td>
<td :class="{'text-end': true, 'text-danger': (activityByCategory[cat.id] || 0) < 0}"> <td :class="classFromNumber(activityByCategory[cat.id] || 0, ['text-end'])">
{{ formatNumber(activityByCategory[cat.id] || 0) }} {{ formatNumber(activityByCategory[cat.id] || 0) }}
</td> </td>
<td class="text-end"> <td class="text-end">
<a <a
:class="{'text-decoration-none': true, 'text-danger': cat.balance < 0, 'text-white': cat.balance >= 0}" :class="classFromNumber(cat.balance, ['text-decoration-none'], 'text-white')"
href="#" href="#"
title="Transfer Money using this Category" title="Transfer Money using this Category"
@click.prevent="initTransfer(cat.id)" @click.prevent="initTransfer(cat.id)"
@ -193,7 +193,7 @@
import { Modal } from 'bootstrap' import { Modal } from 'bootstrap'
import accountEditor from './accountEditor.vue' import accountEditor from './accountEditor.vue'
import { formatNumber } from '../helpers' import { classFromNumber, formatNumber } from '../helpers'
import rangeSelector from './rangeSelector.vue' import rangeSelector from './rangeSelector.vue'
import { unallocatedMoneyAcc } from '../constants' import { unallocatedMoneyAcc } from '../constants'
@ -295,6 +295,8 @@ export default {
emits: ['update-accounts'], emits: ['update-accounts'],
methods: { methods: {
classFromNumber,
fetchTransactions() { fetchTransactions() {
const since = this.timeRange.start.toISOString() const since = this.timeRange.start.toISOString()
const until = this.timeRange.end.toISOString() const until = this.timeRange.end.toISOString()

View file

@ -28,6 +28,27 @@ export function formatNumber(number, thousandSep = ' ', decimalSep = '.', places
return result + decimalSep + number.toFixed(places).split('.')[1] return result + decimalSep + number.toFixed(places).split('.')[1]
} }
/**
* Common code to derive a class from a numeric value
*
* @param {Number} num The value to choose the class from
* @param {Array} extraClasses Extra classes to add to the output string
* @param {String | null} positiveClass Class to use on positive numbers
* @returns {String} Space separated combined class list
*/
export function classFromNumber(num, extraClasses = [], positiveClass = null) {
const classes = extraClasses || []
if (num < 0) {
classes.push('text-danger')
} else if (num === 0) {
classes.push('text-muted')
} else if (positiveClass) {
classes.push(positiveClass)
}
return classes.join(' ')
}
/** /**
* Parses the response to JSON and throws an exception in case the * Parses the response to JSON and throws an exception in case the
* request was non-2xx * request was non-2xx