Skip to content

Commit

Permalink
Create exchage rates page (#12)
Browse files Browse the repository at this point in the history
- Created new page to show exchange rates
- Dashboard accounts only show active asset accounts
- Dashboard accounts also show totals by currency
  • Loading branch information
cioraneanu authored May 7, 2024
1 parent 4f96d24 commit c330b8d
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 30 deletions.
6 changes: 3 additions & 3 deletions back/.env.example
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
APP_NAME="Firefly X"
FIREFLY_URL=

APP_NAME="Firefly Pico"
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost

FIREFLY_URL=

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


<van-grid :column-num="2">
<van-grid-item v-for="account in dataStore.assetAccounts"
<van-grid-item v-for="account in dataStore.dashboardAccounts"
:key="account.id"
@click="onGoToTransactions(account)"
icon="photo-o">
Expand All @@ -36,10 +36,25 @@
</van-grid-item>
</van-grid>

<div class="flex-center text-size-13 m-10">
<icon-cash class="text-muted" :size="24" :stroke="1.5"/>
<span class="font-400 text-muted">Total: </span>
<span class="font-700 ms-1 me-2">~{{ accountTotal }} {{ dataStore.accountTotalCurrency }}</span>


<div class="flex-center text-size-13 m-10 flex-wrap">
<div class="flex-center text-size-13 me-1">
<icon-cash class="text-muted" :size="24" :stroke="1.5"/>
<span class="font-400 text-muted">Total: </span>
</div>

<span
v-for="(totalValue, totalCurrency ) in dataStore.dashboardAccountsTotalByCurrency"
class="font-700 ms-1 mx-1 app-select-option-tag">
{{ getFormattedValue(totalValue) }} {{ totalCurrency }}
</span>
</div>

<div
v-if="hasMultipleCurrencies"
class="flex-center text-size-13 mb-3 gap-1">
<span class="font-700">~{{ accountTotal }} {{ dataStore.accountTotalCurrency }}</span>
<van-button
@click="onToggleTotalCurrency"
size="small"
Expand All @@ -56,14 +71,14 @@
import TablerIconConstants from '~/constants/TablerIconConstants.js'
import Account from '~/models/Account.js'
import RouteConstants from '~/constants/RouteConstants.js'
import {IconCash, IconSum, IconSwitchVertical, IconSwitch2} from "@tabler/icons-vue";
import {getFormattedValue} from "~/utils/MathUtils.js";
import { IconCash, IconSwitch2 } from '@tabler/icons-vue'
import { getFormattedValue } from '~/utils/MathUtils.js'
const appStore = useAppStore()
const dataStore = useDataStore()
const accountTotal = computed(() => {
return getFormattedValue(dataStore.accountTotal)
return getFormattedValue(dataStore.dashboardAccountsEstimatedTotal)
})
const onToggleShowDashboardAccountValues = () => {
Expand All @@ -74,13 +89,15 @@ const getAccountAmount = (account) => {
return `${getFormattedValue(Account.getBalance(account))} ${Account.getCurrency(account)}`
}
const hasMultipleCurrencies = computed(() => dataStore.dashboardAccountsCurrencyList.length > 1)
const onToggleTotalCurrency = () => {
if (dataStore.accountTotalCurrencyList.length === 0) {
if (dataStore.dashboardAccountsCurrencyList.length === 0) {
return
}
let index = dataStore.accountTotalCurrencyList.indexOf(dataStore.accountTotalCurrency)
let newIndex = (index + 1) % dataStore.accountTotalCurrencyList.length
dataStore.accountTotalCurrency = dataStore.accountTotalCurrencyList[newIndex]
let index = dataStore.dashboardAccountsCurrencyList.indexOf(dataStore.accountTotalCurrency)
let newIndex = (index + 1) % dataStore.dashboardAccountsCurrencyList.length
dataStore.accountTotalCurrency = dataStore.dashboardAccountsCurrencyList[newIndex]
}
const onGoToTransactions = async (account) => {
Expand Down
1 change: 1 addition & 0 deletions front/constants/RouteConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default {
ROUTE_SETTINGS_USER_PREFERENCES_TRANSACTION_FIELDS_ORDER: '/settings/user-preferences-transaction-fields-order',
ROUTE_SETTINGS_NEW_TRANSACTION_DEFAULTS: '/settings/user-preferences-new-transaction-defaults',
ROUTE_SETTINGS_ABOUT: '/settings/about',
ROUTE_EXCHANGE_RATES: '/exchange-rates',


ROUTE_TRANSACTION_TEMPLATE_LIST: '/transaction-templates/list',
Expand Down
1 change: 1 addition & 0 deletions front/constants/TablerIconConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const icons = {
settingsUserPreferencesDate: 'IconCalendarEvent',
settingsNewTransactionDefaults: 'IconCarambola',
settingsAbout: 'IconInfoSquare',
exchangeRates: 'IconReplace',

dashboardTotalExpenses: 'IconSquareRoundedMinus',
dashboardTotalIncomes: 'IconSquareRoundedPlus',
Expand Down
4 changes: 3 additions & 1 deletion front/models/Account.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ class Account extends BaseModel {
return `${this.getBalance(account)} ${this.getCurrency(account)}`
}


static getIsActive (account) {
return _.get(account, 'attributes.active', false)
}

static getType (account) {
return get(account, 'attributes.type')
Expand Down
74 changes: 74 additions & 0 deletions front/pages/exchange-rates/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<template>

<div class="app-form">
<app-top-toolbar/>

<van-pull-refresh
v-model="isRefreshing"
@refresh="onRefresh">

<van-cell-group inset>
<div class="van-cell-group-title">Date: {{ exchangeDate }}</div>

<van-grid :column-num="3">
<van-grid-item

v-for="(currencyValue, currencyCode ) in exchangeRates">
<template #text>
<div>
<div class="flex-center text-size-14 font-weight-600">{{ currencyCode }}</div>
<div class="flex-center text-size-10 text-muted">{{ currencyValue }}</div>
</div>
</template>
</van-grid-item>
</van-grid>


</van-cell-group>

</van-pull-refresh>


</div>


</template>


<script setup>
import { get } from 'lodash'
import { useAppStore } from '~/stores/appStore'
import { useDataStore } from '~/stores/dataStore'
import { useToolbar } from '~/composables/useToolbar'
import RouteConstants from '~/constants/RouteConstants'
import UIUtils from '~/utils/UIUtils.js'
const appStore = useAppStore()
const dataStore = useDataStore()
const isRefreshing = ref(false)
const onRefresh = async () => {
isRefreshing.value = true
await dataStore.fetchExchangeRate()
isRefreshing.value = false
}
const exchangeDate = computed(() => get(dataStore.exchangeRates, 'date'))
const exchangeRates = computed(() => get(dataStore.exchangeRates, 'rates'))
const getCurrencyValue = (currency) => {
console.log('xxxx', exchangeRates.value, currency)
return get(exchangeRates.value, currency)
}
UIUtils.showLoadingWhen(isRefreshing)
const toolbar = useToolbar()
toolbar.init({
title: 'Exchange rates',
backRoute: RouteConstants.ROUTE_SETTINGS,
})
</script>
6 changes: 6 additions & 0 deletions front/pages/extras.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
@click="onGoToTransactionTemplatesList"
/>

<app-field-link
label="Exchange rates"
:icon="TablerIconConstants.exchangeRates"
@click="navigateTo(RouteConstants.ROUTE_EXCHANGE_RATES)"
/>

<!-- <app-field-link-->
<!-- label="Currencies"-->
<!-- :icon="IconifyConstants.currency"-->
Expand Down
2 changes: 2 additions & 0 deletions front/plugins/register-tablr.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ import {
IconTemplate,
IconTool,
IconTransfer,
IconReplace
} from '@tabler/icons-vue'

export default defineNuxtPlugin(nuxtApp => {

nuxtApp.vueApp.component('IconReplace', IconReplace)
nuxtApp.vueApp.component('IconCarambola', IconCarambola)
nuxtApp.vueApp.component('IconDelta', IconDelta)
nuxtApp.vueApp.component('IconHash', IconHash)
Expand Down
31 changes: 17 additions & 14 deletions front/stores/dataStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,28 +66,31 @@ export const useDataStore = defineStore('data', {

getters: {

assetAccounts(state) {
return state.accountList.filter(account => isEqual(Account.getType(account) , Account.types.asset))
dashboardAccounts(state) {
return state.accountList.filter(account => isEqual(Account.getType(account) , Account.types.asset) && Account.getIsActive(account))
},

accountTotalCurrencyList (state) {
return uniq(state.accountList.map(account => get(account, 'attributes.currency_code')))
dashboardAccountsCurrencyList (state) {
return uniq(this.dashboardAccounts.map(account => get(account, 'attributes.currency_code')))
},

accountTotal (state) {
if (!state.accountTotalCurrency) {
return ' - '
}
let dictionaryByCurrency = state.accountList.reduce((result, account) => {
dashboardAccountsTotalByCurrency(state) {
return this.dashboardAccounts.reduce((result, account) => {
let accountCurrency = get(account, 'attributes.currency_code')
const accountBalance = parseInt(get(account, 'attributes.current_balance') ?? 0)
let oldValue = get(result, accountCurrency, 0)
set(result, accountCurrency, oldValue + accountBalance)
return result
}, {})
},

dashboardAccountsEstimatedTotal (state) {
if (!state.accountTotalCurrency) {
return ' - '
}

return Object.keys(dictionaryByCurrency).reduce((result, currencyCode) => {
let currencyAmount = dictionaryByCurrency[currencyCode]
return Object.keys(this.dashboardAccountsTotalByCurrency).reduce((result, currencyCode) => {
let currencyAmount = this.dashboardAccountsTotalByCurrency[currencyCode]
let exchangeSource = get(state.exchangeRates, `rates.${currencyCode}`)
let exchangeDestination = get(state.exchangeRates, `rates.${state.accountTotalCurrency}`)
let convertedCurrencyAmount = 1.0 * currencyAmount * exchangeDestination / exchangeSource
Expand Down Expand Up @@ -205,9 +208,9 @@ export const useDataStore = defineStore('data', {
async fetchExchangeRate () {
let exchangeDate = get(this.exchangeRates, 'date')
exchangeDate = DateUtils.stringToDate(exchangeDate)
if (isToday(exchangeDate)) {
return
}
// if (isToday(exchangeDate)) {
// return
// }

this.isLoadingExchangeRates = true
this.exchangeRates = await new CurrencyRepository().getCurrencyExchange()
Expand Down

0 comments on commit c330b8d

Please sign in to comment.