mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-15 23:47:33 +08:00
use pinia to replace vuex, code refactor
This commit is contained in:
@@ -41,8 +41,14 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
|
||||
import licenses from '@/lib/licenses.js';
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
...mapStores(useUserStore),
|
||||
version() {
|
||||
return 'v' + this.$version;
|
||||
},
|
||||
@@ -51,13 +57,13 @@ export default {
|
||||
return this.$buildTime;
|
||||
}
|
||||
|
||||
return this.$utilities.formatUnixTime(this.$buildTime, this.$locale.getLongDateTimeFormat());
|
||||
return this.$locale.formatUnixTimeToLongDateTime(this.userStore, this.$buildTime);
|
||||
},
|
||||
licenseLines() {
|
||||
return this.$licenses.license.replaceAll(/\r/g, '').split('\n');
|
||||
return licenses.getLicense().replaceAll(/\r/g, '').split('\n');
|
||||
},
|
||||
thirdPartyLicenses() {
|
||||
return this.$licenses.thirdPartyLicenses;
|
||||
return licenses.getThirdPartyLicenses();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
|
||||
import logger from '@/lib/logger.js';
|
||||
import webauthn from '@/lib/webauthn.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -48,6 +54,9 @@ export default {
|
||||
showInputPinCodeSheetForDisable: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useUserStore)
|
||||
},
|
||||
watch: {
|
||||
isEnableApplicationLockWebAuthn: function (newValue) {
|
||||
const self = this;
|
||||
@@ -55,9 +64,9 @@ export default {
|
||||
if (newValue) {
|
||||
self.$showLoading();
|
||||
|
||||
self.$webauthn.registerCredential(
|
||||
webauthn.registerCredential(
|
||||
self.$user.getUserAppLockState(),
|
||||
self.$store.state.currentUserInfo,
|
||||
self.userStore.currentUserInfo,
|
||||
).then(({ id }) => {
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -65,7 +74,7 @@ export default {
|
||||
self.$settings.setEnableApplicationLockWebAuthn(true);
|
||||
self.$toast('You have enabled WebAuthn successfully');
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to enable WebAuthn', error);
|
||||
logger.error('failed to enable WebAuthn', error);
|
||||
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -91,7 +100,7 @@ export default {
|
||||
},
|
||||
created() {
|
||||
const self = this;
|
||||
self.$webauthn.isCompletelySupported().then(result => {
|
||||
webauthn.isCompletelySupported().then(result => {
|
||||
self.isSupportedWebAuthn = result;
|
||||
});
|
||||
},
|
||||
@@ -112,7 +121,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
const user = this.$store.state.currentUserInfo;
|
||||
const user = this.userStore.currentUserInfo;
|
||||
|
||||
if (!user || !user.username) {
|
||||
this.$alert('An error has occurred');
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
:title="displayBaseAmount"
|
||||
@click="showBaseAmountSheet = true"
|
||||
>
|
||||
<number-pad-sheet :min-value="$constants.transaction.minAmount"
|
||||
:max-value="$constants.transaction.maxAmount"
|
||||
<number-pad-sheet :min-value="allowedMinAmount"
|
||||
:max-value="allowedMaxAmount"
|
||||
v-model:show="showBaseAmountSheet"
|
||||
v-model="baseAmount"
|
||||
></number-pad-sheet>
|
||||
@@ -90,12 +90,20 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
|
||||
|
||||
import transactionConstants from '@/consts/transaction.js';
|
||||
import { isNumber, appendThousandsSeparator } from '@/lib/common.js';
|
||||
import { stringCurrencyToNumeric, getExchangedAmount } from '@/lib/currency.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
const self = this;
|
||||
const userStore = useUserStore();
|
||||
|
||||
return {
|
||||
baseCurrency: self.$store.getters.currentUserDefaultCurrency,
|
||||
baseCurrency: userStore.currentUserDefaultCurrency,
|
||||
baseAmount: 100,
|
||||
updating: false,
|
||||
showMoreActionSheet: false,
|
||||
@@ -103,29 +111,13 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useUserStore, useExchangeRatesStore),
|
||||
exchangeRatesData() {
|
||||
return this.$store.state.latestExchangeRates.data;
|
||||
return this.exchangeRatesStore.latestExchangeRates.data;
|
||||
},
|
||||
exchangeRatesDataUpdateTime() {
|
||||
if (!this.exchangeRatesData) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return this.$utilities.formatUnixTime(this.exchangeRatesData.updateTime, this.$locale.getLongDateFormat());
|
||||
},
|
||||
exchangeRateMap() {
|
||||
const exchangeRateMap = {};
|
||||
|
||||
if (!this.exchangeRatesData.exchangeRates) {
|
||||
return exchangeRateMap;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.exchangeRatesData.exchangeRates.length; i++) {
|
||||
const exchangeRate = this.exchangeRatesData.exchangeRates[i];
|
||||
exchangeRateMap[exchangeRate.currency] = exchangeRate;
|
||||
}
|
||||
|
||||
return exchangeRateMap;
|
||||
const exchangeRatesLastUpdateTime = this.exchangeRatesStore.exchangeRatesLastUpdateTime;
|
||||
return exchangeRatesLastUpdateTime ? this.$locale.formatUnixTimeToLongDate(this.userStore, exchangeRatesLastUpdateTime) : '';
|
||||
},
|
||||
availableExchangeRates() {
|
||||
if (!this.exchangeRatesData || !this.exchangeRatesData.exchangeRates) {
|
||||
@@ -155,6 +147,12 @@ export default {
|
||||
},
|
||||
baseAmountFontSize() {
|
||||
return this.getFontSizeByAmount(this.baseAmount);
|
||||
},
|
||||
allowedMinAmount() {
|
||||
return transactionConstants.minAmount;
|
||||
},
|
||||
allowedMaxAmount() {
|
||||
return transactionConstants.maxAmount;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -189,7 +187,7 @@ export default {
|
||||
self.$showLoading();
|
||||
}
|
||||
|
||||
self.$store.dispatch('getLatestExchangeRates', {
|
||||
self.exchangeRatesStore.getLatestExchangeRates({
|
||||
silent: false,
|
||||
force: true
|
||||
}).then(() => {
|
||||
@@ -215,19 +213,19 @@ export default {
|
||||
});
|
||||
},
|
||||
getConvertedAmount(toExchangeRate) {
|
||||
const fromExchangeRate = this.exchangeRateMap[this.baseCurrency];
|
||||
const fromExchangeRate = this.exchangeRatesStore.latestExchangeRateMap[this.baseCurrency];
|
||||
|
||||
if (!fromExchangeRate) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return this.$utilities.getExchangedAmount(this.baseAmount / 100, fromExchangeRate.rate, toExchangeRate.rate);
|
||||
return getExchangedAmount(this.baseAmount / 100, fromExchangeRate.rate, toExchangeRate.rate);
|
||||
},
|
||||
getDisplayConvertedAmount(toExchangeRate) {
|
||||
const rateStr = this.getConvertedAmount(toExchangeRate).toString();
|
||||
|
||||
if (rateStr.indexOf('.') < 0) {
|
||||
return this.$utilities.appendThousandsSeparator(rateStr);
|
||||
return appendThousandsSeparator(rateStr);
|
||||
} else {
|
||||
let firstNonZeroPos = 0;
|
||||
|
||||
@@ -239,16 +237,16 @@ export default {
|
||||
}
|
||||
|
||||
const trimmedRateStr = rateStr.substring(0, Math.max(6, Math.max(firstNonZeroPos, rateStr.indexOf('.') + 2)));
|
||||
return this.$utilities.appendThousandsSeparator(trimmedRateStr);
|
||||
return appendThousandsSeparator(trimmedRateStr);
|
||||
}
|
||||
},
|
||||
setAsBaseline(currency, amount) {
|
||||
if (!this.$utilities.isNumber(amount)) {
|
||||
if (!isNumber(amount)) {
|
||||
amount = '';
|
||||
}
|
||||
|
||||
this.baseCurrency = currency;
|
||||
this.baseAmount = this.$utilities.stringCurrencyToNumeric(amount.toString());
|
||||
this.baseAmount = stringCurrencyToNumeric(amount.toString());
|
||||
},
|
||||
getFontSizeByAmount(amount) {
|
||||
if (amount >= 100000000 || amount <= -100000000) {
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
</f7-card>
|
||||
|
||||
<f7-list strong inset dividers class="margin-top overview-transaction-list" :class="{ 'skeleton-text': loading }">
|
||||
<f7-list-item :link="'/transaction/list?dateType=' + $constants.datetime.allDateRanges.Today.type" chevron-center>
|
||||
<f7-list-item :link="'/transaction/list?dateType=' + allDateRanges.Today.type" chevron-center>
|
||||
<template #media>
|
||||
<f7-icon f7="calendar_today"></f7-icon>
|
||||
</template>
|
||||
@@ -66,7 +66,7 @@
|
||||
</template>
|
||||
</f7-list-item>
|
||||
|
||||
<f7-list-item :link="'/transaction/list?dateType=' + $constants.datetime.allDateRanges.ThisWeek.type" chevron-center>
|
||||
<f7-list-item :link="'/transaction/list?dateType=' + allDateRanges.ThisWeek.type" chevron-center>
|
||||
<template #media>
|
||||
<f7-icon f7="calendar"></f7-icon>
|
||||
</template>
|
||||
@@ -99,7 +99,7 @@
|
||||
</template>
|
||||
</f7-list-item>
|
||||
|
||||
<f7-list-item :link="'/transaction/list?dateType=' + $constants.datetime.allDateRanges.ThisMonth.type" chevron-center>
|
||||
<f7-list-item :link="'/transaction/list?dateType=' + allDateRanges.ThisMonth.type" chevron-center>
|
||||
<template #media>
|
||||
<f7-icon f7="calendar"></f7-icon>
|
||||
</template>
|
||||
@@ -132,7 +132,7 @@
|
||||
</template>
|
||||
</f7-list-item>
|
||||
|
||||
<f7-list-item :link="'/transaction/list?dateType=' + $constants.datetime.allDateRanges.ThisYear.type" chevron-center>
|
||||
<f7-list-item :link="'/transaction/list?dateType=' + allDateRanges.ThisYear.type" chevron-center>
|
||||
<template #media>
|
||||
<f7-icon f7="square_stack_3d_up"></f7-icon>
|
||||
</template>
|
||||
@@ -188,25 +188,46 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useOverviewStore } from '@/stores/overview.js';
|
||||
|
||||
import datetimeConstants from '@/consts/datetime.js';
|
||||
import {
|
||||
formatUnixTime,
|
||||
getTodayFirstUnixTime,
|
||||
getTodayLastUnixTime,
|
||||
getThisWeekFirstUnixTime,
|
||||
getThisWeekLastUnixTime,
|
||||
getThisMonthFirstUnixTime,
|
||||
getThisMonthLastUnixTime,
|
||||
getThisYearFirstUnixTime,
|
||||
getThisYearLastUnixTime
|
||||
} from '@/lib/datetime.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
const self = this;
|
||||
|
||||
return {
|
||||
loading: true,
|
||||
todayFirstUnixTime: self.$utilities.getTodayFirstUnixTime(),
|
||||
todayLastUnixTime: self.$utilities.getTodayLastUnixTime(),
|
||||
todayFirstUnixTime: getTodayFirstUnixTime(),
|
||||
todayLastUnixTime: getTodayLastUnixTime(),
|
||||
showAmountInHomePage: self.$settings.isShowAmountInHomePage(),
|
||||
isEnableThousandsSeparator: self.$settings.isEnableThousandsSeparator(),
|
||||
currencyDisplayMode: self.$settings.getCurrencyDisplayMode()
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useUserStore, useOverviewStore),
|
||||
defaultCurrency() {
|
||||
return this.$store.getters.currentUserDefaultCurrency;
|
||||
return this.userStore.currentUserDefaultCurrency;
|
||||
},
|
||||
firstDayOfWeek() {
|
||||
return this.$store.getters.currentUserFirstDayOfWeek;
|
||||
return this.userStore.currentUserFirstDayOfWeek;
|
||||
},
|
||||
allDateRanges() {
|
||||
return datetimeConstants.allDateRanges;
|
||||
},
|
||||
dateRange() {
|
||||
const self = this;
|
||||
@@ -217,16 +238,16 @@ export default {
|
||||
endTime: self.todayLastUnixTime
|
||||
},
|
||||
thisWeek: {
|
||||
startTime: self.$utilities.getThisWeekFirstUnixTime(self.firstDayOfWeek),
|
||||
endTime: self.$utilities.getThisWeekLastUnixTime(self.firstDayOfWeek)
|
||||
startTime: getThisWeekFirstUnixTime(self.firstDayOfWeek),
|
||||
endTime: getThisWeekLastUnixTime(self.firstDayOfWeek)
|
||||
},
|
||||
thisMonth: {
|
||||
startTime: self.$utilities.getThisMonthFirstUnixTime(),
|
||||
endTime: self.$utilities.getThisMonthLastUnixTime()
|
||||
startTime: getThisMonthFirstUnixTime(),
|
||||
endTime: getThisMonthLastUnixTime()
|
||||
},
|
||||
thisYear: {
|
||||
startTime: self.$utilities.getThisYearFirstUnixTime(),
|
||||
endTime: self.$utilities.getThisYearLastUnixTime()
|
||||
startTime: getThisYearFirstUnixTime(),
|
||||
endTime: getThisYearLastUnixTime()
|
||||
}
|
||||
};
|
||||
},
|
||||
@@ -235,19 +256,19 @@ export default {
|
||||
|
||||
return {
|
||||
today: {
|
||||
displayTime: self.$utilities.formatUnixTime(self.dateRange.today.startTime, self.$locale.getLongDateFormat()),
|
||||
displayTime: self.$locale.formatUnixTimeToLongDate(self.userStore, self.dateRange.today.startTime),
|
||||
},
|
||||
thisWeek: {
|
||||
startTime: self.$utilities.formatUnixTime(self.dateRange.thisWeek.startTime, self.$locale.getLongMonthDayFormat()),
|
||||
endTime: self.$utilities.formatUnixTime(self.dateRange.thisWeek.endTime, self.$locale.getLongMonthDayFormat())
|
||||
startTime: self.$locale.formatUnixTimeToLongMonthDay(self.userStore, self.dateRange.thisWeek.startTime),
|
||||
endTime: self.$locale.formatUnixTimeToLongMonthDay(self.userStore, self.dateRange.thisWeek.endTime)
|
||||
},
|
||||
thisMonth: {
|
||||
displayTime: self.$utilities.formatUnixTime(self.dateRange.thisMonth.startTime, 'MMMM'),
|
||||
startTime: self.$utilities.formatUnixTime(self.dateRange.thisMonth.startTime, self.$locale.getLongMonthDayFormat()),
|
||||
endTime: self.$utilities.formatUnixTime(self.dateRange.thisMonth.endTime, self.$locale.getLongMonthDayFormat())
|
||||
displayTime: formatUnixTime(self.dateRange.thisMonth.startTime, 'MMMM'),
|
||||
startTime: self.$locale.formatUnixTimeToLongMonthDay(self.userStore, self.dateRange.thisMonth.startTime),
|
||||
endTime: self.$locale.formatUnixTimeToLongMonthDay(self.userStore, self.dateRange.thisMonth.endTime)
|
||||
},
|
||||
thisYear: {
|
||||
displayTime: self.$utilities.formatUnixTime(self.dateRange.thisYear.startTime, self.$locale.getLongYearFormat())
|
||||
displayTime: self.$locale.formatUnixTimeToLongYear(self.userStore, self.dateRange.thisYear.startTime)
|
||||
}
|
||||
};
|
||||
},
|
||||
@@ -256,7 +277,7 @@ export default {
|
||||
const isEnableThousandsSeparator = this.isEnableThousandsSeparator; // eslint-disable-line
|
||||
const currencyDisplayMode = this.currencyDisplayMode; // eslint-disable-line
|
||||
|
||||
if (!this.$store.state.transactionOverview || !this.$store.state.transactionOverview.thisMonth) {
|
||||
if (!this.overviewStore.transactionOverview || !this.overviewStore.transactionOverview.thisMonth) {
|
||||
return {
|
||||
thisMonth: {
|
||||
valid: false,
|
||||
@@ -266,7 +287,7 @@ export default {
|
||||
};
|
||||
}
|
||||
|
||||
const originalOverview = this.$store.state.transactionOverview;
|
||||
const originalOverview = this.overviewStore.transactionOverview;
|
||||
const displayOverview = {};
|
||||
|
||||
[ 'today', 'thisWeek', 'thisMonth', 'thisYear' ].forEach(key => {
|
||||
@@ -292,7 +313,7 @@ export default {
|
||||
if (self.$user.isUserLogined() && self.$user.isUserUnlocked()) {
|
||||
self.loading = true;
|
||||
|
||||
self.$store.dispatch('loadTransactionOverview', {
|
||||
self.overviewStore.loadTransactionOverview({
|
||||
defaultCurrency: self.defaultCurrency,
|
||||
dateRange: self.dateRange,
|
||||
force: false
|
||||
@@ -319,21 +340,21 @@ export default {
|
||||
|
||||
let dateChanged = false;
|
||||
|
||||
if (this.todayFirstUnixTime !== this.$utilities.getTodayFirstUnixTime()) {
|
||||
if (this.todayFirstUnixTime !== getTodayFirstUnixTime()) {
|
||||
dateChanged = true;
|
||||
|
||||
this.todayFirstUnixTime = this.$utilities.getTodayFirstUnixTime();
|
||||
this.todayLastUnixTime = this.$utilities.getTodayLastUnixTime();
|
||||
this.todayFirstUnixTime = getTodayFirstUnixTime();
|
||||
this.todayLastUnixTime = getTodayLastUnixTime();
|
||||
}
|
||||
|
||||
if ((dateChanged || this.$store.state.transactionOverviewStateInvalid) && !this.loading) {
|
||||
if ((dateChanged || this.overviewStore.transactionOverviewStateInvalid) && !this.loading) {
|
||||
this.reload(null);
|
||||
}
|
||||
},
|
||||
reload(done) {
|
||||
const self = this;
|
||||
|
||||
self.$store.dispatch('loadTransactionOverview', {
|
||||
self.overviewStore.loadTransactionOverview({
|
||||
defaultCurrency: self.defaultCurrency,
|
||||
dateRange: self.dateRange,
|
||||
force: true
|
||||
|
||||
@@ -109,6 +109,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useRootStore } from '@/stores/index.js';
|
||||
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
|
||||
|
||||
import { isModalShowing } from '@/lib/ui.mobile.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7router'
|
||||
@@ -127,6 +133,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useRootStore, useExchangeRatesStore),
|
||||
version() {
|
||||
return 'v' + this.$version;
|
||||
},
|
||||
@@ -187,7 +194,7 @@ export default {
|
||||
self.logining = true;
|
||||
self.$showLoading(() => self.logining);
|
||||
|
||||
self.$store.dispatch('authorize', {
|
||||
self.rootStore.authorize({
|
||||
loginName: self.username,
|
||||
password: self.password
|
||||
}).then(authResponse => {
|
||||
@@ -205,7 +212,7 @@ export default {
|
||||
}
|
||||
|
||||
if (self.$settings.isAutoUpdateExchangeRatesData()) {
|
||||
self.$store.dispatch('getLatestExchangeRates', { silent: true, force: false });
|
||||
self.exchangeRatesStore.getLatestExchangeRates({ silent: true, force: false });
|
||||
}
|
||||
|
||||
router.refreshPage();
|
||||
@@ -219,7 +226,7 @@ export default {
|
||||
});
|
||||
},
|
||||
loginByPressEnter() {
|
||||
if (this.$ui.isModalShowing()) {
|
||||
if (isModalShowing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -244,7 +251,7 @@ export default {
|
||||
self.verifying = true;
|
||||
self.$showLoading(() => self.verifying);
|
||||
|
||||
self.$store.dispatch('authorize2FA', {
|
||||
self.rootStore.authorize2FA({
|
||||
token: self.tempToken,
|
||||
passcode: self.twoFAVerifyType === 'passcode' ? self.passcode : null,
|
||||
recoveryCode: self.twoFAVerifyType === 'backupcode' ? self.backupCode : null
|
||||
@@ -257,7 +264,7 @@ export default {
|
||||
}
|
||||
|
||||
if (self.$settings.isAutoUpdateExchangeRatesData()) {
|
||||
self.$store.dispatch('getLatestExchangeRates', { silent: true, force: false });
|
||||
self.exchangeRatesStore.getLatestExchangeRates({ silent: true, force: false });
|
||||
}
|
||||
|
||||
self.show2faSheet = false;
|
||||
|
||||
@@ -61,10 +61,10 @@
|
||||
:title="$t('Currency Display Mode')"
|
||||
smart-select :smart-select-params="{ openIn: 'popup', popupPush: true, closeOnSelect: true, scrollToSelectedItem: true, searchbar: true, searchbarPlaceholder: $t('Currency Display Mode'), searchbarDisableText: $t('Cancel'), appendSearchbarNotFound: $t('No results'), popupCloseLinkText: $t('Done') }">
|
||||
<select v-model="currencyDisplayMode">
|
||||
<option :value="$constants.currency.allCurrencyDisplayModes.None">{{ $t('None') }}</option>
|
||||
<option :value="$constants.currency.allCurrencyDisplayModes.Symbol">{{ $t('Currency Symbol') }}</option>
|
||||
<option :value="$constants.currency.allCurrencyDisplayModes.Code">{{ $t('Currency Code') }}</option>
|
||||
<option :value="$constants.currency.allCurrencyDisplayModes.Name">{{ $t('Currency Name') }}</option>
|
||||
<option :value="allCurrencyDisplayModes.None">{{ $t('None') }}</option>
|
||||
<option :value="allCurrencyDisplayModes.Symbol">{{ $t('Currency Symbol') }}</option>
|
||||
<option :value="allCurrencyDisplayModes.Code">{{ $t('Currency Code') }}</option>
|
||||
<option :value="allCurrencyDisplayModes.Name">{{ $t('Currency Name') }}</option>
|
||||
</select>
|
||||
</f7-list-item>
|
||||
|
||||
@@ -96,6 +96,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useRootStore } from '@/stores/index.js';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
|
||||
|
||||
import currencyConstants from '@/consts/currency.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7router'
|
||||
@@ -110,6 +117,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useRootStore, useUserStore, useExchangeRatesStore),
|
||||
version() {
|
||||
return 'v' + this.$version;
|
||||
},
|
||||
@@ -136,11 +144,14 @@ export default {
|
||||
}
|
||||
},
|
||||
currentNickName() {
|
||||
return this.$store.getters.currentUserNickname || this.$t('User');
|
||||
return this.userStore.currentUserNickname || this.$t('User');
|
||||
},
|
||||
exchangeRatesLastUpdateDate() {
|
||||
const exchangeRatesLastUpdateTime = this.$store.getters.exchangeRatesLastUpdateTime;
|
||||
return exchangeRatesLastUpdateTime ? this.$utilities.formatUnixTime(exchangeRatesLastUpdateTime, this.$locale.getLongDateFormat()) : '';
|
||||
const exchangeRatesLastUpdateTime = this.exchangeRatesStore.exchangeRatesLastUpdateTime;
|
||||
return exchangeRatesLastUpdateTime ? this.$locale.formatUnixTimeToLongDate(this.userStore, exchangeRatesLastUpdateTime) : '';
|
||||
},
|
||||
allCurrencyDisplayModes() {
|
||||
return currencyConstants.allCurrencyDisplayModes;
|
||||
},
|
||||
isAutoUpdateExchangeRatesData: {
|
||||
get: function () {
|
||||
@@ -223,7 +234,7 @@ export default {
|
||||
self.logouting = true;
|
||||
self.$showLoading(() => self.logouting);
|
||||
|
||||
self.$store.dispatch('logout').then(() => {
|
||||
self.rootStore.logout().then(() => {
|
||||
self.logouting = false;
|
||||
self.$hideLoading();
|
||||
|
||||
|
||||
@@ -174,12 +174,23 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useRootStore } from '@/stores/index.js';
|
||||
import { useSettingsStore } from '@/stores/setting.js';
|
||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
|
||||
|
||||
import datetimeConstants from '@/consts/datetime.js';
|
||||
import categoryConstants from '@/consts/category.js';
|
||||
import { getNameByKeyValue, copyArrayTo } from '@/lib/common.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7router'
|
||||
],
|
||||
data() {
|
||||
const self = this;
|
||||
const settingsStore = useSettingsStore();
|
||||
|
||||
return {
|
||||
user: {
|
||||
@@ -189,14 +200,14 @@ export default {
|
||||
email: '',
|
||||
nickname: '',
|
||||
language: self.$i18n.locale,
|
||||
defaultCurrency: self.$store.state.defaultSetting.currency,
|
||||
firstDayOfWeek: self.$constants.datetime.allWeekDays[self.$t('default.firstDayOfWeek')] ? self.$constants.datetime.allWeekDays[self.$t('default.firstDayOfWeek')].type : 0
|
||||
defaultCurrency: settingsStore.defaultSetting.currency,
|
||||
firstDayOfWeek: datetimeConstants.allWeekDays[self.$t('default.firstDayOfWeek')] ? datetimeConstants.allWeekDays[self.$t('default.firstDayOfWeek')].type : 0
|
||||
},
|
||||
submitting: false,
|
||||
presetCategories: {
|
||||
[self.$constants.category.allCategoryTypes.Income]: self.$utilities.copyArrayTo(self.$constants.category.defaultIncomeCategories, []),
|
||||
[self.$constants.category.allCategoryTypes.Expense]: self.$utilities.copyArrayTo(self.$constants.category.defaultExpenseCategories, []),
|
||||
[self.$constants.category.allCategoryTypes.Transfer]: self.$utilities.copyArrayTo(self.$constants.category.defaultTransferCategories, [])
|
||||
[categoryConstants.allCategoryTypes.Income]: copyArrayTo(categoryConstants.defaultIncomeCategories, []),
|
||||
[categoryConstants.allCategoryTypes.Expense]: copyArrayTo(categoryConstants.defaultExpenseCategories, []),
|
||||
[categoryConstants.allCategoryTypes.Transfer]: copyArrayTo(categoryConstants.defaultTransferCategories, [])
|
||||
},
|
||||
usePresetCategories: false,
|
||||
showPresetCategories: false,
|
||||
@@ -205,6 +216,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useRootStore, useSettingsStore, useTransactionCategoriesStore, useExchangeRatesStore),
|
||||
allLanguages() {
|
||||
return this.$locale.getAllLanguageInfos();
|
||||
},
|
||||
@@ -212,25 +224,25 @@ export default {
|
||||
return this.$locale.getAllCurrencies();
|
||||
},
|
||||
allWeekDays() {
|
||||
return this.$constants.datetime.allWeekDays;
|
||||
return datetimeConstants.allWeekDays;
|
||||
},
|
||||
currentLocale: {
|
||||
get: function () {
|
||||
return this.$i18n.locale;
|
||||
},
|
||||
set: function (value) {
|
||||
const isCurrencyDefault = this.user.defaultCurrency === this.$store.state.defaultSetting.currency;
|
||||
const isFirstWeekDayDefault = this.user.firstDayOfWeek === (this.$constants.datetime.allWeekDays[this.$t('default.firstDayOfWeek')] ? this.$constants.datetime.allWeekDays[this.$t('default.firstDayOfWeek')].type : 0);
|
||||
const isCurrencyDefault = this.user.defaultCurrency === this.settingsStore.defaultSetting.currency;
|
||||
const isFirstWeekDayDefault = this.user.firstDayOfWeek === (datetimeConstants.allWeekDays[this.$t('default.firstDayOfWeek')] ? datetimeConstants.allWeekDays[this.$t('default.firstDayOfWeek')].type : 0);
|
||||
|
||||
this.user.language = value;
|
||||
this.$locale.setLanguage(value);
|
||||
|
||||
if (isCurrencyDefault) {
|
||||
this.user.defaultCurrency = this.$store.state.defaultSetting.currency;
|
||||
this.user.defaultCurrency = this.settingsStore.defaultSetting.currency;
|
||||
}
|
||||
|
||||
if (isFirstWeekDayDefault) {
|
||||
this.user.firstDayOfWeek = this.$constants.datetime.allWeekDays[this.$t('default.firstDayOfWeek')] ? this.$constants.datetime.allWeekDays[this.$t('default.firstDayOfWeek')].type : 0;
|
||||
this.user.firstDayOfWeek = datetimeConstants.allWeekDays[this.$t('default.firstDayOfWeek')] ? datetimeConstants.allWeekDays[this.$t('default.firstDayOfWeek')].type : 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -324,7 +336,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
self.$store.dispatch('register', {
|
||||
self.rootStore.register({
|
||||
user: self.user
|
||||
}).then(response => {
|
||||
if (!self.$user.isUserLogined()) {
|
||||
@@ -346,7 +358,7 @@ export default {
|
||||
}
|
||||
|
||||
if (self.$settings.isAutoUpdateExchangeRatesData()) {
|
||||
self.$store.dispatch('getLatestExchangeRates', { silent: true, force: false });
|
||||
self.exchangeRatesStore.getLatestExchangeRates({ silent: true, force: false });
|
||||
}
|
||||
|
||||
if (!self.usePresetCategories) {
|
||||
@@ -358,7 +370,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
self.$store.dispatch('addCategories', {
|
||||
self.transactionCategoriesStore.addCategories({
|
||||
categories: allCategories
|
||||
}).then(() => {
|
||||
self.submitting = false;
|
||||
@@ -383,17 +395,17 @@ export default {
|
||||
});
|
||||
},
|
||||
getDayOfWeekName(dayOfWeek) {
|
||||
const weekName = this.$utilities.getNameByKeyValue(this.$constants.datetime.allWeekDays, dayOfWeek, 'type', 'name');
|
||||
const weekName = getNameByKeyValue(datetimeConstants.allWeekDays, dayOfWeek, 'type', 'name');
|
||||
const i18nWeekNameKey = `datetime.${weekName}.long`;
|
||||
return this.$t(i18nWeekNameKey);
|
||||
},
|
||||
getCategoryTypeName(categoryType) {
|
||||
switch (categoryType) {
|
||||
case this.$constants.category.allCategoryTypes.Income.toString():
|
||||
case categoryConstants.allCategoryTypes.Income.toString():
|
||||
return this.$t('Income Categories');
|
||||
case this.$constants.category.allCategoryTypes.Expense.toString():
|
||||
case categoryConstants.allCategoryTypes.Expense.toString():
|
||||
return this.$t('Expense Categories');
|
||||
case this.$constants.category.allCategoryTypes.Transfer.toString():
|
||||
case categoryConstants.allCategoryTypes.Transfer.toString():
|
||||
return this.$t('Transfer Categories');
|
||||
default:
|
||||
return this.$t('Transaction Categories');
|
||||
|
||||
@@ -57,6 +57,16 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useRootStore } from '@/stores/index.js';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useTokensStore } from '@/stores/token.js';
|
||||
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
|
||||
|
||||
import logger from '@/lib/logger.js';
|
||||
import webauthn from '@/lib/webauthn.js';
|
||||
import { isModalShowing } from '@/lib/ui.mobile.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7router'
|
||||
@@ -67,6 +77,7 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useRootStore, useUserStore, useTokensStore, useExchangeRatesStore),
|
||||
version() {
|
||||
return 'v' + this.$version;
|
||||
},
|
||||
@@ -76,7 +87,7 @@ export default {
|
||||
isWebAuthnAvailable() {
|
||||
return this.$settings.isEnableApplicationLockWebAuthn()
|
||||
&& this.$user.getWebAuthnCredentialId()
|
||||
&& this.$webauthn.isSupported();
|
||||
&& webauthn.isSupported();
|
||||
},
|
||||
currentLanguageName() {
|
||||
const currentLocale = this.$i18n.locale;
|
||||
@@ -99,34 +110,34 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self.$webauthn.isSupported()) {
|
||||
if (!webauthn.isSupported()) {
|
||||
self.$toast('This device does not support WebAuthn');
|
||||
return;
|
||||
}
|
||||
|
||||
self.$showLoading();
|
||||
|
||||
self.$webauthn.verifyCredential(
|
||||
self.$store.state.currentUserInfo,
|
||||
webauthn.verifyCredential(
|
||||
self.userStore.currentUserInfo,
|
||||
self.$user.getWebAuthnCredentialId()
|
||||
).then(({ id, userName, userSecret }) => {
|
||||
self.$hideLoading();
|
||||
|
||||
self.$user.unlockTokenByWebAuthn(id, userName, userSecret);
|
||||
self.$store.dispatch('refreshTokenAndRevokeOldToken').then(response => {
|
||||
self.tokensStore.refreshTokenAndRevokeOldToken().then(response => {
|
||||
if (response.user && response.user.language) {
|
||||
self.$locale.setLanguage(response.user.language);
|
||||
}
|
||||
});
|
||||
|
||||
if (self.$settings.isAutoUpdateExchangeRatesData()) {
|
||||
self.$store.dispatch('getLatestExchangeRates', { silent: true, force: false });
|
||||
self.exchangeRatesStore.getLatestExchangeRates({ silent: true, force: false });
|
||||
}
|
||||
|
||||
router.refreshPage();
|
||||
}).catch(error => {
|
||||
self.$hideLoading();
|
||||
self.$logger.error('failed to use webauthn to verify', error);
|
||||
logger.error('failed to use webauthn to verify', error);
|
||||
|
||||
if (error.notSupported) {
|
||||
self.$toast('This device does not support WebAuthn');
|
||||
@@ -146,12 +157,12 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.$ui.isModalShowing()) {
|
||||
if (isModalShowing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const router = self.f7router;
|
||||
const user = self.$store.state.currentUserInfo;
|
||||
const user = self.userStore.currentUserInfo;
|
||||
|
||||
if (!user || !user.username) {
|
||||
self.$alert('An error has occurred');
|
||||
@@ -160,19 +171,19 @@ export default {
|
||||
|
||||
try {
|
||||
self.$user.unlockTokenByPinCode(user.username, pinCode);
|
||||
self.$store.dispatch('refreshTokenAndRevokeOldToken').then(response => {
|
||||
self.tokensStore.refreshTokenAndRevokeOldToken().then(response => {
|
||||
if (response.user && response.user.language) {
|
||||
self.$locale.setLanguage(response.user.language);
|
||||
}
|
||||
});
|
||||
|
||||
if (self.$settings.isAutoUpdateExchangeRatesData()) {
|
||||
self.$store.dispatch('getLatestExchangeRates', { silent: true, force: false });
|
||||
self.exchangeRatesStore.getLatestExchangeRates({ silent: true, force: false });
|
||||
}
|
||||
|
||||
router.refreshPage();
|
||||
} catch (ex) {
|
||||
self.$logger.error('failed to unlock by pin code', ex);
|
||||
logger.error('failed to unlock by pin code', ex);
|
||||
self.$toast('PIN code is wrong');
|
||||
}
|
||||
},
|
||||
@@ -181,10 +192,7 @@ export default {
|
||||
const router = self.f7router;
|
||||
|
||||
self.$confirm('Are you sure you want to re-login?', () => {
|
||||
self.$user.clearTokenAndUserInfo(true);
|
||||
self.$user.clearWebAuthnConfig();
|
||||
self.$store.dispatch('clearUserInfoState');
|
||||
self.$store.dispatch('resetState');
|
||||
self.rootStore.forceLogout();
|
||||
self.$settings.clearSettings();
|
||||
self.$locale.initLocale();
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<f7-nav-left :back-link="$t('Back')"></f7-nav-left>
|
||||
<f7-nav-title :title="$t(title)"></f7-nav-title>
|
||||
<f7-nav-right>
|
||||
<f7-link icon-f7="ellipsis" v-if="!editAccountId && account.type === $constants.account.allAccountTypes.MultiSubAccounts" @click="showMoreActionSheet = true"></f7-link>
|
||||
<f7-link icon-f7="ellipsis" v-if="!editAccountId && account.type === allAccountTypes.MultiSubAccounts" @click="showMoreActionSheet = true"></f7-link>
|
||||
<f7-link :class="{ 'disabled': isInputEmpty() || submitting }" :text="$t(saveButtonTitle)" @click="save"></f7-link>
|
||||
</f7-nav-right>
|
||||
</f7-navbar>
|
||||
@@ -42,7 +42,7 @@
|
||||
>
|
||||
<list-item-selection-sheet value-type="item"
|
||||
key-field="id" value-field="id" title-field="name"
|
||||
:items="allAccountTypes"
|
||||
:items="allAccountTypesArray"
|
||||
:title-i18n="true"
|
||||
v-model:show="showAccountTypeSheet"
|
||||
v-model="account.type">
|
||||
@@ -96,7 +96,7 @@
|
||||
<f7-list-input label="Description" type="textarea" placeholder="Your account description (optional)"></f7-list-input>
|
||||
</f7-list>
|
||||
|
||||
<f7-list form strong inset dividers class="margin-vertical" v-else-if="!loading && account.type === $constants.account.allAccountTypes.SingleAccount">
|
||||
<f7-list form strong inset dividers class="margin-vertical" v-else-if="!loading && account.type === allAccountTypes.SingleAccount">
|
||||
<f7-list-input
|
||||
type="text"
|
||||
clear-button
|
||||
@@ -180,11 +180,11 @@
|
||||
class="list-item-with-header-and-title"
|
||||
:class="{ 'disabled': editAccountId }"
|
||||
:header="$t('Account Balance')"
|
||||
:title="$locale.getDisplayCurrency(account.balance, account.currency)"
|
||||
:title="getAccountBalance(account)"
|
||||
@click="account.showBalanceSheet = true"
|
||||
>
|
||||
<number-pad-sheet :min-value="$constants.transaction.minAmount"
|
||||
:max-value="$constants.transaction.maxAmount"
|
||||
<number-pad-sheet :min-value="allowedMinAmount"
|
||||
:max-value="allowedMaxAmount"
|
||||
v-model:show="account.showBalanceSheet"
|
||||
v-model="account.balance"
|
||||
></number-pad-sheet>
|
||||
@@ -204,7 +204,7 @@
|
||||
></f7-list-input>
|
||||
</f7-list>
|
||||
|
||||
<f7-list form strong inset dividers class="margin-vertical" v-else-if="!loading && account.type === $constants.account.allAccountTypes.MultiSubAccounts">
|
||||
<f7-list form strong inset dividers class="margin-vertical" v-else-if="!loading && account.type === allAccountTypes.MultiSubAccounts">
|
||||
<f7-list-input
|
||||
type="text"
|
||||
clear-button
|
||||
@@ -277,7 +277,7 @@
|
||||
></f7-list-input>
|
||||
</f7-list>
|
||||
|
||||
<f7-block class="no-padding no-margin" v-if="!loading && account.type === $constants.account.allAccountTypes.MultiSubAccounts">
|
||||
<f7-block class="no-padding no-margin" v-if="!loading && account.type === allAccountTypes.MultiSubAccounts">
|
||||
<f7-list strong inset dividers class="subaccount-edit-list margin-vertical"
|
||||
:key="idx"
|
||||
v-for="(subAccount, idx) in subAccounts">
|
||||
@@ -373,11 +373,11 @@
|
||||
class="list-item-with-header-and-title"
|
||||
:class="{ 'disabled': editAccountId }"
|
||||
:header="$t('Sub Account Balance')"
|
||||
:title="$locale.getDisplayCurrency(subAccount.balance, subAccount.currency)"
|
||||
:title="getAccountBalance(subAccount)"
|
||||
@click="subAccount.showBalanceSheet = true"
|
||||
>
|
||||
<number-pad-sheet :min-value="$constants.transaction.minAmount"
|
||||
:max-value="$constants.transaction.maxAmount"
|
||||
<number-pad-sheet :min-value="allowedMinAmount"
|
||||
:max-value="allowedMaxAmount"
|
||||
v-model:show="subAccount.showBalanceSheet"
|
||||
v-model="subAccount.balance"
|
||||
></number-pad-sheet>
|
||||
@@ -420,13 +420,24 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useAccountsStore } from '@/stores/account.js';
|
||||
|
||||
import accountConstants from '@/consts/account.js';
|
||||
import iconConstants from '@/consts/icon.js';
|
||||
import colorConstants from '@/consts/color.js';
|
||||
import currencyConstants from '@/consts/currency.js';
|
||||
import transactionConstants from '@/consts/transaction.js';
|
||||
import { getNameByKeyValue } from '@/lib/common.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7route',
|
||||
'f7router'
|
||||
],
|
||||
data() {
|
||||
const self = this;
|
||||
const userStore = useUserStore();
|
||||
|
||||
return {
|
||||
editAccountId: null,
|
||||
@@ -434,11 +445,11 @@ export default {
|
||||
loadingError: null,
|
||||
account: {
|
||||
category: 1,
|
||||
type: self.$constants.account.allAccountTypes.SingleAccount,
|
||||
type: accountConstants.allAccountTypes.SingleAccount,
|
||||
name: '',
|
||||
icon: self.$constants.icons.defaultAccountIconId,
|
||||
color: self.$constants.colors.defaultAccountColor,
|
||||
currency: self.$store.getters.currentUserDefaultCurrency,
|
||||
icon: iconConstants.defaultAccountIconId,
|
||||
color: colorConstants.defaultAccountColor,
|
||||
currency: userStore.currentUserDefaultCurrency,
|
||||
balance: 0,
|
||||
comment: '',
|
||||
visible: true,
|
||||
@@ -456,6 +467,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useUserStore, useAccountsStore),
|
||||
title() {
|
||||
if (!this.editAccountId) {
|
||||
return 'Add Account';
|
||||
@@ -470,26 +482,29 @@ export default {
|
||||
return 'Save';
|
||||
}
|
||||
},
|
||||
allAccountCategories() {
|
||||
return this.$constants.account.allCategories;
|
||||
},
|
||||
allAccountTypes() {
|
||||
return [{
|
||||
id: 1,
|
||||
name: 'Single Account'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'Multi Sub Accounts'
|
||||
}];
|
||||
return accountConstants.allAccountTypes;
|
||||
},
|
||||
allAccountCategories() {
|
||||
return accountConstants.allCategories;
|
||||
},
|
||||
allAccountTypesArray() {
|
||||
return accountConstants.allAccountTypesArray;
|
||||
},
|
||||
allAccountIcons() {
|
||||
return this.$constants.icons.allAccountIcons;
|
||||
return iconConstants.allAccountIcons;
|
||||
},
|
||||
allAccountColors() {
|
||||
return this.$constants.colors.allAccountColors;
|
||||
return colorConstants.allAccountColors;
|
||||
},
|
||||
allCurrencies() {
|
||||
return this.$locale.getAllCurrencies();
|
||||
},
|
||||
allowedMinAmount() {
|
||||
return transactionConstants.minAmount;
|
||||
},
|
||||
allowedMaxAmount() {
|
||||
return transactionConstants.maxAmount;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -511,7 +526,7 @@ export default {
|
||||
|
||||
self.editAccountId = query.id;
|
||||
|
||||
self.$store.dispatch('getAccount', {
|
||||
self.accountsStore.getAccount({
|
||||
accountId: self.editAccountId
|
||||
}).then(account => {
|
||||
self.account.id = account.id;
|
||||
@@ -568,7 +583,7 @@ export default {
|
||||
addSubAccount() {
|
||||
const self = this;
|
||||
|
||||
if (self.account.type !== self.$constants.account.allAccountTypes.MultiSubAccounts) {
|
||||
if (self.account.type !== this.allAccountTypes.MultiSubAccounts) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -578,7 +593,7 @@ export default {
|
||||
name: '',
|
||||
icon: self.account.icon,
|
||||
color: self.account.color,
|
||||
currency: self.$store.getters.currentUserDefaultCurrency,
|
||||
currency: self.userStore.currentUserDefaultCurrency,
|
||||
balance: 0,
|
||||
comment: '',
|
||||
visible: true,
|
||||
@@ -614,7 +629,7 @@ export default {
|
||||
|
||||
let problemMessage = self.getInputEmptyProblemMessage(self.account, false);
|
||||
|
||||
if (!problemMessage && self.account.type === self.$constants.account.allAccountTypes.MultiSubAccounts) {
|
||||
if (!problemMessage && self.account.type === self.allAccountTypes.MultiSubAccounts) {
|
||||
for (let i = 0; i < self.subAccounts.length; i++) {
|
||||
problemMessage = self.getInputEmptyProblemMessage(self.subAccounts[i], true);
|
||||
|
||||
@@ -634,12 +649,12 @@ export default {
|
||||
|
||||
const subAccounts = [];
|
||||
|
||||
if (self.account.type === self.$constants.account.allAccountTypes.MultiSubAccounts) {
|
||||
if (self.account.type === self.allAccountTypes.MultiSubAccounts) {
|
||||
for (let i = 0; i < self.subAccounts.length; i++) {
|
||||
const subAccount = self.subAccounts[i];
|
||||
const submitAccount = {
|
||||
category: self.account.category,
|
||||
type: self.$constants.account.allAccountTypes.SingleAccount,
|
||||
type: self.allAccountTypes.SingleAccount,
|
||||
name: subAccount.name,
|
||||
icon: subAccount.icon,
|
||||
color: subAccount.color,
|
||||
@@ -663,10 +678,10 @@ export default {
|
||||
name: self.account.name,
|
||||
icon: self.account.icon,
|
||||
color: self.account.color,
|
||||
currency: self.account.type === self.$constants.account.allAccountTypes.SingleAccount ? self.account.currency : self.$constants.currency.parentAccountCurrencyPlaceholder,
|
||||
balance: self.account.type === self.$constants.account.allAccountTypes.SingleAccount ? self.account.balance : 0,
|
||||
currency: self.account.type === self.allAccountTypes.SingleAccount ? self.account.currency : currencyConstants.parentAccountCurrencyPlaceholder,
|
||||
balance: self.account.type === self.allAccountTypes.SingleAccount ? self.account.balance : 0,
|
||||
comment: self.account.comment,
|
||||
subAccounts: self.account.type === self.$constants.account.allAccountTypes.SingleAccount ? null : subAccounts,
|
||||
subAccounts: self.account.type === self.allAccountTypes.SingleAccount ? null : subAccounts,
|
||||
};
|
||||
|
||||
if (self.editAccountId) {
|
||||
@@ -674,7 +689,7 @@ export default {
|
||||
submitAccount.hidden = !self.account.visible;
|
||||
}
|
||||
|
||||
self.$store.dispatch('saveAccount', {
|
||||
self.accountsStore.saveAccount({
|
||||
account: submitAccount
|
||||
}).then(() => {
|
||||
self.submitting = false;
|
||||
@@ -697,19 +712,20 @@ export default {
|
||||
});
|
||||
},
|
||||
getAccountTypeName(accountType) {
|
||||
const typeName = this.$utilities.getNameByKeyValue(this.allAccountTypes, accountType, 'id', 'name');
|
||||
const typeName = getNameByKeyValue(this.allAccountTypesArray, accountType, 'id', 'name');
|
||||
return this.$t(typeName);
|
||||
},
|
||||
getAccountCategoryName(accountCategory) {
|
||||
const categoryName = this.$utilities.getNameByKeyValue(this.allAccountCategories, accountCategory, 'id', 'name');
|
||||
const categoryName = getNameByKeyValue(this.allAccountCategories, accountCategory, 'id', 'name');
|
||||
return this.$t(categoryName);
|
||||
},
|
||||
getAccountBalance(account) {
|
||||
return this.$locale.getDisplayCurrency(account.balance, account.currency)
|
||||
},
|
||||
chooseSuitableIcon(oldCategory, newCategory) {
|
||||
const allCategories = this.$constants.account.allCategories;
|
||||
|
||||
for (let i = 0; i < allCategories.length; i++) {
|
||||
if (allCategories[i].id === oldCategory) {
|
||||
if (this.account.icon !== allCategories[i].defaultAccountIconId) {
|
||||
for (let i = 0; i < this.allAccountCategories.length; i++) {
|
||||
if (this.allAccountCategories[i].id === oldCategory) {
|
||||
if (this.account.icon !== this.allAccountCategories[i].defaultAccountIconId) {
|
||||
return;
|
||||
} else {
|
||||
break;
|
||||
@@ -717,9 +733,9 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < allCategories.length; i++) {
|
||||
if (allCategories[i].id === newCategory) {
|
||||
this.account.icon = allCategories[i].defaultAccountIconId;
|
||||
for (let i = 0; i < this.allAccountCategories.length; i++) {
|
||||
if (this.allAccountCategories[i].id === newCategory) {
|
||||
this.account.icon = this.allAccountCategories[i].defaultAccountIconId;
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -730,7 +746,7 @@ export default {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.account.type === this.$constants.account.allAccountTypes.MultiSubAccounts) {
|
||||
if (this.account.type === this.allAccountTypes.MultiSubAccounts) {
|
||||
for (let i = 0; i < this.subAccounts.length; i++) {
|
||||
const isSubAccountEmpty = !!this.getInputEmptyProblemMessage(this.subAccounts[i], true);
|
||||
|
||||
@@ -749,7 +765,7 @@ export default {
|
||||
return 'Account type cannot be empty';
|
||||
} else if (!account.name) {
|
||||
return 'Account name cannot be empty';
|
||||
} else if (account.type === this.$constants.account.allAccountTypes.SingleAccount && !account.currency) {
|
||||
} else if (account.type === this.allAccountTypes.SingleAccount && !account.currency) {
|
||||
return 'Account currency cannot be empty';
|
||||
} else {
|
||||
return null;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
</p>
|
||||
<p class="no-margin">
|
||||
<span class="net-assets" v-if="loading">0.00 USD</span>
|
||||
<span class="net-assets" v-else-if="!loading">{{ $locale.getDisplayCurrency(netAssets, defaultCurrency) }}</span>
|
||||
<span class="net-assets" v-else-if="!loading">{{ netAssets }}</span>
|
||||
<f7-link class="margin-left-half" @click="toggleShowAccountBalance()">
|
||||
<f7-icon :f7="showAccountBalance ? 'eye_slash_fill' : 'eye_fill'" size="18px"></f7-icon>
|
||||
</f7-link>
|
||||
@@ -29,10 +29,10 @@
|
||||
</small>
|
||||
<small class="account-overview-info" v-else-if="!loading">
|
||||
<span>{{ $t('Total assets') }}</span>
|
||||
<span>{{ $locale.getDisplayCurrency(totalAssets, defaultCurrency) }}</span>
|
||||
<span>{{ totalAssets }}</span>
|
||||
<span>|</span>
|
||||
<span>{{ $t('Total liabilities') }}</span>
|
||||
<span>{{ $locale.getDisplayCurrency(totalLiabilities, defaultCurrency) }}</span>
|
||||
<span>{{ totalLiabilities }}</span>
|
||||
</small>
|
||||
</p>
|
||||
</f7-card-header>
|
||||
@@ -68,21 +68,21 @@
|
||||
<f7-list-item group-title :sortable="false">
|
||||
<small>
|
||||
<span>{{ $t(accountCategory.name) }}</span>
|
||||
<span style="margin-left: 10px">{{ $locale.getDisplayCurrency(accountCategoryTotalBalance(accountCategory), defaultCurrency) }}</span>
|
||||
<span style="margin-left: 10px">{{ accountCategoryTotalBalance(accountCategory) }}</span>
|
||||
</small>
|
||||
</f7-list-item>
|
||||
<f7-list-item swipeout
|
||||
class="nested-list-item"
|
||||
:id="getAccountDomId(account)"
|
||||
:class="{ 'has-child-list-item': account.type === $constants.account.allAccountTypes.MultiSubAccounts && hasVisibleSubAccount(account), 'actual-first-child': account.id === firstShowingIds.accounts[accountCategory.id], 'actual-last-child': account.id === lastShowingIds.accounts[accountCategory.id] }"
|
||||
:after="$locale.getDisplayCurrency(accountBalance(account), account.currency)"
|
||||
:class="{ 'has-child-list-item': account.type === allAccountTypes.MultiSubAccounts && hasVisibleSubAccount(account), 'actual-first-child': account.id === firstShowingIds.accounts[accountCategory.id], 'actual-last-child': account.id === lastShowingIds.accounts[accountCategory.id] }"
|
||||
:after="accountBalance(account)"
|
||||
:link="!sortable ? '/transaction/list?accountId=' + account.id : null"
|
||||
:key="account.id"
|
||||
v-for="account in categorizedAccounts[accountCategory.id].accounts"
|
||||
v-show="showHidden || !account.hidden"
|
||||
@taphold="setSortable()"
|
||||
>
|
||||
<template #media v-if="account.type !== $constants.account.allAccountTypes.MultiSubAccounts || !hasVisibleSubAccount(account)">
|
||||
<template #media v-if="account.type !== allAccountTypes.MultiSubAccounts || !hasVisibleSubAccount(account)">
|
||||
<ItemIcon icon-type="account" :icon-id="account.icon" :color="account.color">
|
||||
<f7-badge color="gray" class="right-bottom-icon" v-if="account.hidden">
|
||||
<f7-icon f7="eye_slash_fill"></f7-icon>
|
||||
@@ -93,7 +93,7 @@
|
||||
<template #title>
|
||||
<div class="display-flex padding-top-half padding-bottom-half">
|
||||
<ItemIcon icon-type="account" :icon-id="account.icon" :color="account.color"
|
||||
v-if="account.type === $constants.account.allAccountTypes.MultiSubAccounts && hasVisibleSubAccount(account)">
|
||||
v-if="account.type === allAccountTypes.MultiSubAccounts && hasVisibleSubAccount(account)">
|
||||
<f7-badge color="gray" class="right-bottom-icon" v-if="account.hidden">
|
||||
<f7-icon f7="eye_slash_fill"></f7-icon>
|
||||
</f7-badge>
|
||||
@@ -103,12 +103,12 @@
|
||||
<div class="item-footer" v-if="account.comment">{{ account.comment }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<li v-if="account.type === $constants.account.allAccountTypes.MultiSubAccounts">
|
||||
<li v-if="account.type === allAccountTypes.MultiSubAccounts">
|
||||
<ul class="no-padding">
|
||||
<f7-list-item class="no-sortable nested-list-item-child"
|
||||
:class="{ 'actual-first-child': subAccount.id === firstShowingIds.subAccounts[account.id], 'actual-last-child': subAccount.id === lastShowingIds.subAccounts[account.id] }"
|
||||
:id="getAccountDomId(subAccount)"
|
||||
:title="subAccount.name" :footer="subAccount.comment" :after="$locale.getDisplayCurrency(accountBalance(subAccount), subAccount.currency)"
|
||||
:title="subAccount.name" :footer="subAccount.comment" :after="accountBalance(subAccount)"
|
||||
:link="!sortable ? '/transaction/list?accountId=' + subAccount.id : null"
|
||||
:key="subAccount.id"
|
||||
v-for="subAccount in account.subAccounts"
|
||||
@@ -165,6 +165,14 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useAccountsStore } from '@/stores/account.js';
|
||||
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
|
||||
|
||||
import accountConstants from '@/consts/account.js';
|
||||
import { onSwipeoutDeleted } from '@/lib/ui.mobile.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7router'
|
||||
@@ -184,194 +192,46 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useUserStore, useAccountsStore, useExchangeRatesStore),
|
||||
defaultCurrency() {
|
||||
return this.$store.getters.currentUserDefaultCurrency;
|
||||
return this.userStore.currentUserDefaultCurrency;
|
||||
},
|
||||
allAccountTypes() {
|
||||
return accountConstants.allAccountTypes;
|
||||
},
|
||||
allAccountCategories() {
|
||||
return this.$constants.account.allCategories;
|
||||
return accountConstants.allCategories;
|
||||
},
|
||||
categorizedAccounts() {
|
||||
return this.$store.state.allCategorizedAccounts;
|
||||
return this.accountsStore.allCategorizedAccounts;
|
||||
},
|
||||
allAccountCount() {
|
||||
return this.$store.getters.allAvailableAccountsCount;
|
||||
return this.accountsStore.allAvailableAccountsCount;
|
||||
},
|
||||
firstShowingIds() {
|
||||
const ret = {
|
||||
accounts: {},
|
||||
subAccounts: {}
|
||||
};
|
||||
|
||||
for (let category in this.categorizedAccounts) {
|
||||
if (!Object.prototype.hasOwnProperty.call(this.categorizedAccounts, category)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this.categorizedAccounts[category] || !this.categorizedAccounts[category].accounts) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const accounts = this.categorizedAccounts[category].accounts;
|
||||
|
||||
for (let i = 0; i < accounts.length; i++) {
|
||||
const account = accounts[i];
|
||||
|
||||
if (account.type === this.$constants.account.allAccountTypes.MultiSubAccounts && account.subAccounts) {
|
||||
for (let j = 0; j < account.subAccounts.length; j++) {
|
||||
const subAccount = account.subAccounts[j];
|
||||
|
||||
if (this.showHidden || !subAccount.hidden) {
|
||||
ret.subAccounts[account.id] = subAccount.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.showHidden || !account.hidden) {
|
||||
ret.accounts[category] = account.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return this.accountsStore.getFirstShowingIds(this.showHidden);
|
||||
},
|
||||
lastShowingIds() {
|
||||
const ret = {
|
||||
accounts: {},
|
||||
subAccounts: {}
|
||||
};
|
||||
|
||||
for (let category in this.categorizedAccounts) {
|
||||
if (!Object.prototype.hasOwnProperty.call(this.categorizedAccounts, category)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this.categorizedAccounts[category] || !this.categorizedAccounts[category].accounts) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const accounts = this.categorizedAccounts[category].accounts;
|
||||
|
||||
for (let i = accounts.length - 1; i >= 0; i--) {
|
||||
const account = accounts[i];
|
||||
|
||||
if (account.type === this.$constants.account.allAccountTypes.MultiSubAccounts && account.subAccounts) {
|
||||
for (let j = account.subAccounts.length - 1; j >= 0; j--) {
|
||||
const subAccount = account.subAccounts[j];
|
||||
|
||||
if (this.showHidden || !subAccount.hidden) {
|
||||
ret.subAccounts[account.id] = subAccount.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.showHidden || !account.hidden) {
|
||||
ret.accounts[category] = account.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return this.accountsStore.getLastShowingIds(this.showHidden);
|
||||
},
|
||||
noAvailableAccount() {
|
||||
if (this.showHidden) {
|
||||
return this.$store.getters.allAvailableAccountsCount < 1;
|
||||
return this.accountsStore.allAvailableAccountsCount < 1;
|
||||
} else {
|
||||
return this.$store.getters.allVisibleAccountsCount < 1;
|
||||
return this.accountsStore.allVisibleAccountsCount < 1;
|
||||
}
|
||||
},
|
||||
netAssets() {
|
||||
if (!this.showAccountBalance) {
|
||||
return '***';
|
||||
}
|
||||
|
||||
const accountsBalance = this.$utilities.getAllFilteredAccountsBalance(this.categorizedAccounts, () => true);
|
||||
let netAssets = 0;
|
||||
let hasUnCalculatedAmount = false;
|
||||
|
||||
for (let i = 0; i < accountsBalance.length; i++) {
|
||||
if (accountsBalance[i].currency === this.defaultCurrency) {
|
||||
netAssets += accountsBalance[i].balance;
|
||||
} else {
|
||||
const balance = this.$store.getters.getExchangedAmount(accountsBalance[i].balance, accountsBalance[i].currency, this.defaultCurrency);
|
||||
|
||||
if (!this.$utilities.isNumber(balance)) {
|
||||
hasUnCalculatedAmount = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
netAssets += Math.floor(balance);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUnCalculatedAmount) {
|
||||
return netAssets + '+';
|
||||
} else {
|
||||
return netAssets;
|
||||
}
|
||||
const netAssets = this.accountsStore.getNetAssets(this.showAccountBalance);
|
||||
return this.$locale.getDisplayCurrency(netAssets, this.defaultCurrency);
|
||||
},
|
||||
totalAssets() {
|
||||
if (!this.showAccountBalance) {
|
||||
return '***';
|
||||
}
|
||||
|
||||
const accountsBalance = this.$utilities.getAllFilteredAccountsBalance(this.categorizedAccounts, account => account.isAsset);
|
||||
let totalAssets = 0;
|
||||
let hasUnCalculatedAmount = false;
|
||||
|
||||
for (let i = 0; i < accountsBalance.length; i++) {
|
||||
if (accountsBalance[i].currency === this.defaultCurrency) {
|
||||
totalAssets += accountsBalance[i].balance;
|
||||
} else {
|
||||
const balance = this.$store.getters.getExchangedAmount(accountsBalance[i].balance, accountsBalance[i].currency, this.defaultCurrency);
|
||||
|
||||
if (!this.$utilities.isNumber(balance)) {
|
||||
hasUnCalculatedAmount = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
totalAssets += Math.floor(balance);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUnCalculatedAmount) {
|
||||
return totalAssets + '+';
|
||||
} else {
|
||||
return totalAssets;
|
||||
}
|
||||
const totalAssets = this.accountsStore.getTotalAssets(this.showAccountBalance);
|
||||
return this.$locale.getDisplayCurrency(totalAssets, this.defaultCurrency);
|
||||
},
|
||||
totalLiabilities() {
|
||||
if (!this.showAccountBalance) {
|
||||
return '***';
|
||||
}
|
||||
|
||||
const accountsBalance = this.$utilities.getAllFilteredAccountsBalance(this.categorizedAccounts, account => account.isLiability);
|
||||
let totalLiabilities = 0;
|
||||
let hasUnCalculatedAmount = false;
|
||||
|
||||
for (let i = 0; i < accountsBalance.length; i++) {
|
||||
if (accountsBalance[i].currency === this.defaultCurrency) {
|
||||
totalLiabilities -= accountsBalance[i].balance;
|
||||
} else {
|
||||
const balance = this.$store.getters.getExchangedAmount(accountsBalance[i].balance, accountsBalance[i].currency, this.defaultCurrency);
|
||||
|
||||
if (!this.$utilities.isNumber(balance)) {
|
||||
hasUnCalculatedAmount = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
totalLiabilities -= Math.floor(balance);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUnCalculatedAmount) {
|
||||
return totalLiabilities + '+';
|
||||
} else {
|
||||
return totalLiabilities;
|
||||
}
|
||||
const totalLiabilities = this.accountsStore.getTotalLiabilities(this.showAccountBalance);
|
||||
return this.$locale.getDisplayCurrency(totalLiabilities, this.defaultCurrency);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -379,7 +239,7 @@ export default {
|
||||
|
||||
self.loading = true;
|
||||
|
||||
self.$store.dispatch('loadAllAccounts', {
|
||||
self.accountsStore.loadAllAccounts({
|
||||
force: false
|
||||
}).then(() => {
|
||||
self.loading = false;
|
||||
@@ -394,7 +254,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
onPageAfterIn() {
|
||||
if (this.$store.state.accountListStateInvalid && !this.loading) {
|
||||
if (this.accountsStore.accountListStateInvalid && !this.loading) {
|
||||
this.reload(null);
|
||||
}
|
||||
|
||||
@@ -408,7 +268,7 @@ export default {
|
||||
|
||||
const self = this;
|
||||
|
||||
self.$store.dispatch('loadAllAccounts', {
|
||||
self.accountsStore.loadAllAccounts({
|
||||
force: true
|
||||
}).then(() => {
|
||||
if (done) {
|
||||
@@ -425,99 +285,22 @@ export default {
|
||||
});
|
||||
},
|
||||
hasAccount(accountCategory, visibleOnly) {
|
||||
if (!this.categorizedAccounts[accountCategory.id] ||
|
||||
!this.categorizedAccounts[accountCategory.id].accounts ||
|
||||
!this.categorizedAccounts[accountCategory.id].accounts.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let shownCount = 0;
|
||||
|
||||
for (let i = 0; i < this.categorizedAccounts[accountCategory.id].accounts.length; i++) {
|
||||
const account = this.categorizedAccounts[accountCategory.id].accounts[i];
|
||||
|
||||
if (!visibleOnly || !account.hidden) {
|
||||
shownCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return shownCount > 0;
|
||||
return this.accountsStore.hasAccount(accountCategory, visibleOnly);
|
||||
},
|
||||
hasVisibleSubAccount(account) {
|
||||
if (!account || account.type !== this.$constants.account.allAccountTypes.MultiSubAccounts || !account.subAccounts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < account.subAccounts.length; i++) {
|
||||
if (this.showHidden || !account.subAccounts[i].hidden) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return this.accountsStore.hasVisibleSubAccount(this.showHidden, account);
|
||||
},
|
||||
toggleShowAccountBalance() {
|
||||
this.showAccountBalance = !this.showAccountBalance;
|
||||
this.$settings.setShowAccountBalance(this.showAccountBalance);
|
||||
},
|
||||
accountBalance(account) {
|
||||
if (account.type !== this.$constants.account.allAccountTypes.SingleAccount) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.showAccountBalance) {
|
||||
if (account.isAsset) {
|
||||
return account.balance;
|
||||
} else if (account.isLiability) {
|
||||
return -account.balance;
|
||||
} else {
|
||||
return account.balance;
|
||||
}
|
||||
} else {
|
||||
return '***';
|
||||
}
|
||||
const balance = this.accountsStore.getAccountBalance(this.showAccountBalance, account);
|
||||
return this.$locale.getDisplayCurrency(balance, account.currency);
|
||||
},
|
||||
accountCategoryTotalBalance(accountCategory) {
|
||||
if (!this.showAccountBalance) {
|
||||
return '***';
|
||||
}
|
||||
|
||||
const accountsBalance = this.$utilities.getAllFilteredAccountsBalance(this.categorizedAccounts, account => account.category === accountCategory.id);
|
||||
let totalBalance = 0;
|
||||
let hasUnCalculatedAmount = false;
|
||||
|
||||
for (let i = 0; i < accountsBalance.length; i++) {
|
||||
if (accountsBalance[i].currency === this.defaultCurrency) {
|
||||
if (accountsBalance[i].isAsset) {
|
||||
totalBalance += accountsBalance[i].balance;
|
||||
} else if (accountsBalance[i].isLiability) {
|
||||
totalBalance -= accountsBalance[i].balance;
|
||||
} else {
|
||||
totalBalance += accountsBalance[i].balance;
|
||||
}
|
||||
} else {
|
||||
const balance = this.$store.getters.getExchangedAmount(accountsBalance[i].balance, accountsBalance[i].currency, this.defaultCurrency);
|
||||
|
||||
if (!this.$utilities.isNumber(balance)) {
|
||||
hasUnCalculatedAmount = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (accountsBalance[i].isAsset) {
|
||||
totalBalance += Math.floor(balance);
|
||||
} else if (accountsBalance[i].isLiability) {
|
||||
totalBalance -= Math.floor(balance);
|
||||
} else {
|
||||
totalBalance += Math.floor(balance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUnCalculatedAmount) {
|
||||
return totalBalance + '+';
|
||||
} else {
|
||||
return totalBalance;
|
||||
}
|
||||
const totalBalance = this.accountsStore.getAccountCategoryTotalBalance(this.showAccountBalance, accountCategory);
|
||||
return this.$locale.getDisplayCurrency(totalBalance, this.defaultCurrency);
|
||||
},
|
||||
setSortable() {
|
||||
if (this.sortable) {
|
||||
@@ -543,7 +326,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
self.$store.dispatch('changeAccountDisplayOrder', {
|
||||
self.accountsStore.changeAccountDisplayOrder({
|
||||
accountId: id,
|
||||
from: event.from - 1, // first item in the list is title, so the index need minus one
|
||||
to: event.to - 1
|
||||
@@ -565,7 +348,7 @@ export default {
|
||||
self.displayOrderSaving = true;
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('updateAccountDisplayOrders').then(() => {
|
||||
self.accountsStore.updateAccountDisplayOrders().then(() => {
|
||||
self.displayOrderSaving = false;
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -589,7 +372,7 @@ export default {
|
||||
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('hideAccount', {
|
||||
self.accountsStore.hideAccount({
|
||||
account: account,
|
||||
hidden: hidden
|
||||
}).then(() => {
|
||||
@@ -620,10 +403,10 @@ export default {
|
||||
self.accountToDelete = null;
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('deleteAccount', {
|
||||
self.accountsStore.deleteAccount({
|
||||
account: account,
|
||||
beforeResolve: (done) => {
|
||||
self.$ui.onSwipeoutDeleted(self.getAccountDomId(account), done);
|
||||
onSwipeoutDeleted(self.getAccountDomId(account), done);
|
||||
}
|
||||
}).then(() => {
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7router'
|
||||
@@ -28,12 +31,15 @@ export default {
|
||||
loadingError: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useTransactionCategoriesStore)
|
||||
},
|
||||
created() {
|
||||
const self = this;
|
||||
|
||||
self.loading = true;
|
||||
|
||||
self.$store.dispatch('loadAllCategories', {
|
||||
self.transactionCategoriesStore.loadAllCategories({
|
||||
force: false
|
||||
}).then(() => {
|
||||
self.loading = false;
|
||||
@@ -53,7 +59,7 @@ export default {
|
||||
reload(done) {
|
||||
const self = this;
|
||||
|
||||
self.$store.dispatch('loadAllCategories', {
|
||||
self.transactionCategoriesStore.loadAllCategories({
|
||||
force: true
|
||||
}).then(() => {
|
||||
if (done) {
|
||||
|
||||
@@ -128,6 +128,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||
|
||||
import categoryConstants from '@/consts/category.js';
|
||||
import iconConstants from '@/consts/icon.js';
|
||||
import colorConstants from '@/consts/color.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7route',
|
||||
@@ -145,8 +152,8 @@ export default {
|
||||
type: parseInt(query.type),
|
||||
name: '',
|
||||
parentId: query.parentId,
|
||||
icon: self.$constants.icons.defaultCategoryIconId,
|
||||
color: self.$constants.colors.defaultCategoryColor,
|
||||
icon: iconConstants.defaultCategoryIconId,
|
||||
color: colorConstants.defaultCategoryColor,
|
||||
comment: '',
|
||||
visible: true,
|
||||
showIconSelectionSheet: false,
|
||||
@@ -156,6 +163,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useTransactionCategoriesStore),
|
||||
title() {
|
||||
if (!this.editCategoryId) {
|
||||
if (this.category.parentId === '0') {
|
||||
@@ -175,10 +183,10 @@ export default {
|
||||
}
|
||||
},
|
||||
allCategoryIcons() {
|
||||
return this.$constants.icons.allCategoryIcons;
|
||||
return iconConstants.allCategoryIcons;
|
||||
},
|
||||
allCategoryColors() {
|
||||
return this.$constants.colors.allCategoryColors;
|
||||
return colorConstants.allCategoryColors;
|
||||
},
|
||||
inputIsEmpty() {
|
||||
return !!this.inputEmptyProblemMessage;
|
||||
@@ -205,7 +213,7 @@ export default {
|
||||
self.loading = true;
|
||||
|
||||
self.editCategoryId = query.id;
|
||||
self.$store.dispatch('getCategory', {
|
||||
self.transactionCategoriesStore.getCategory({
|
||||
categoryId: self.editCategoryId
|
||||
}).then(category => {
|
||||
self.category.id = category.id;
|
||||
@@ -229,9 +237,9 @@ export default {
|
||||
} else if (query.parentId) {
|
||||
const categoryType = parseInt(query.type);
|
||||
|
||||
if (categoryType !== this.$constants.category.allCategoryTypes.Income &&
|
||||
categoryType !== this.$constants.category.allCategoryTypes.Expense &&
|
||||
categoryType !== this.$constants.category.allCategoryTypes.Transfer) {
|
||||
if (categoryType !== categoryConstants.allCategoryTypes.Income &&
|
||||
categoryType !== categoryConstants.allCategoryTypes.Expense &&
|
||||
categoryType !== categoryConstants.allCategoryTypes.Transfer) {
|
||||
self.$toast('Parameter Invalid');
|
||||
self.loadingError = 'Parameter Invalid';
|
||||
return;
|
||||
@@ -272,7 +280,7 @@ export default {
|
||||
submitCategory.hidden = !self.category.visible;
|
||||
}
|
||||
|
||||
self.$store.dispatch('saveCategory', {
|
||||
self.transactionCategoriesStore.saveCategory({
|
||||
category: submitCategory
|
||||
}).then(() => {
|
||||
self.submitting = false;
|
||||
|
||||
@@ -87,6 +87,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||
|
||||
import categoryConstants from '@/consts/category.js';
|
||||
import { onSwipeoutDeleted } from '@/lib/ui.mobile.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7route',
|
||||
@@ -109,19 +115,20 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useTransactionCategoriesStore),
|
||||
categories() {
|
||||
if (!this.categoryId || this.categoryId === '' || this.categoryId === '0') {
|
||||
if (!this.$store.state.allTransactionCategories || !this.$store.state.allTransactionCategories[this.categoryType]) {
|
||||
if (!this.transactionCategoriesStore.allTransactionCategories || !this.transactionCategoriesStore.allTransactionCategories[this.categoryType]) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.$store.state.allTransactionCategories[this.categoryType];
|
||||
return this.transactionCategoriesStore.allTransactionCategories[this.categoryType];
|
||||
} else if (this.categoryId && this.categoryId !== '' && this.categoryId !== '0') {
|
||||
if (!this.$store.state.allTransactionCategoriesMap || !this.$store.state.allTransactionCategoriesMap[this.categoryId]) {
|
||||
if (!this.transactionCategoriesStore.allTransactionCategoriesMap || !this.transactionCategoriesStore.allTransactionCategoriesMap[this.categoryId]) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.$store.state.allTransactionCategoriesMap[this.categoryId].subCategories;
|
||||
return this.transactionCategoriesStore.allTransactionCategoriesMap[this.categoryId].subCategories;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
@@ -130,13 +137,13 @@ export default {
|
||||
let title = '';
|
||||
|
||||
switch (this.categoryType) {
|
||||
case this.$constants.category.allCategoryTypes.Income:
|
||||
case categoryConstants.allCategoryTypes.Income:
|
||||
title = 'Income';
|
||||
break;
|
||||
case this.$constants.category.allCategoryTypes.Expense:
|
||||
case categoryConstants.allCategoryTypes.Expense:
|
||||
title = 'Expense';
|
||||
break;
|
||||
case this.$constants.category.allCategoryTypes.Transfer:
|
||||
case categoryConstants.allCategoryTypes.Transfer:
|
||||
title = 'Transfer';
|
||||
break;
|
||||
default:
|
||||
@@ -189,9 +196,9 @@ export default {
|
||||
|
||||
self.categoryType = parseInt(query.type);
|
||||
|
||||
if (self.categoryType !== this.$constants.category.allCategoryTypes.Income &&
|
||||
self.categoryType !== this.$constants.category.allCategoryTypes.Expense &&
|
||||
self.categoryType !== this.$constants.category.allCategoryTypes.Transfer) {
|
||||
if (self.categoryType !== categoryConstants.allCategoryTypes.Income &&
|
||||
self.categoryType !== categoryConstants.allCategoryTypes.Expense &&
|
||||
self.categoryType !== categoryConstants.allCategoryTypes.Transfer) {
|
||||
self.$toast('Parameter Invalid');
|
||||
self.loadingError = 'Parameter Invalid';
|
||||
return;
|
||||
@@ -207,7 +214,7 @@ export default {
|
||||
|
||||
self.loading = true;
|
||||
|
||||
self.$store.dispatch('loadAllCategories', {
|
||||
self.transactionCategoriesStore.loadAllCategories({
|
||||
force: false
|
||||
}).then(() => {
|
||||
self.loading = false;
|
||||
@@ -222,7 +229,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
onPageAfterIn() {
|
||||
if (this.$store.state.transactionCategoryListStateInvalid && !this.loading) {
|
||||
if (this.transactionCategoriesStore.transactionCategoryListStateInvalid && !this.loading) {
|
||||
this.reload(null);
|
||||
}
|
||||
|
||||
@@ -236,7 +243,7 @@ export default {
|
||||
|
||||
const self = this;
|
||||
|
||||
self.$store.dispatch('loadAllCategories', {
|
||||
self.transactionCategoriesStore.loadAllCategories({
|
||||
force: true
|
||||
}).then(() => {
|
||||
if (done) {
|
||||
@@ -276,7 +283,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
self.$store.dispatch('changeCategoryDisplayOrder', {
|
||||
self.transactionCategoriesStore.changeCategoryDisplayOrder({
|
||||
categoryId: id,
|
||||
from: event.from,
|
||||
to: event.to
|
||||
@@ -298,7 +305,7 @@ export default {
|
||||
self.displayOrderSaving = true;
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('updateCategoryDisplayOrders', {
|
||||
self.transactionCategoriesStore.updateCategoryDisplayOrders({
|
||||
type: self.categoryType,
|
||||
parentId: self.categoryId,
|
||||
}).then(() => {
|
||||
@@ -325,7 +332,7 @@ export default {
|
||||
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('hideCategory', {
|
||||
self.transactionCategoriesStore.hideCategory({
|
||||
category: category,
|
||||
hidden: hidden
|
||||
}).then(() => {
|
||||
@@ -356,10 +363,10 @@ export default {
|
||||
self.categoryToDelete = null;
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('deleteCategory', {
|
||||
self.transactionCategoriesStore.deleteCategory({
|
||||
category: category,
|
||||
beforeResolve: (done) => {
|
||||
self.$ui.onSwipeoutDeleted(self.getCategoryDomId(category), done);
|
||||
onSwipeoutDeleted(self.getCategoryDomId(category), done);
|
||||
}
|
||||
}).then(() => {
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -55,6 +55,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||
|
||||
import categoryConstants from '@/consts/category.js';
|
||||
import { copyArrayTo } from '@/lib/common.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7route',
|
||||
@@ -74,6 +80,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useTransactionCategoriesStore),
|
||||
allLanguages() {
|
||||
return this.$locale.getAllLanguageInfos();
|
||||
}
|
||||
@@ -85,9 +92,9 @@ export default {
|
||||
self.categoryType = parseInt(query.type);
|
||||
|
||||
if (self.categoryType !== 0 &&
|
||||
self.categoryType !== this.$constants.category.allCategoryTypes.Income &&
|
||||
self.categoryType !== this.$constants.category.allCategoryTypes.Expense &&
|
||||
self.categoryType !== this.$constants.category.allCategoryTypes.Transfer) {
|
||||
self.categoryType !== categoryConstants.allCategoryTypes.Income &&
|
||||
self.categoryType !== categoryConstants.allCategoryTypes.Expense &&
|
||||
self.categoryType !== categoryConstants.allCategoryTypes.Transfer) {
|
||||
self.$toast('Parameter Invalid');
|
||||
self.loadingError = 'Parameter Invalid';
|
||||
return;
|
||||
@@ -97,13 +104,13 @@ export default {
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
self.allCategories.push({
|
||||
type: i,
|
||||
categories: self.$utilities.copyArrayTo(self.getDefaultCategories(i), [])
|
||||
categories: copyArrayTo(self.getDefaultCategories(i), [])
|
||||
});
|
||||
}
|
||||
} else {
|
||||
self.allCategories.push({
|
||||
type: self.categoryType,
|
||||
categories: self.$utilities.copyArrayTo(self.getDefaultCategories(self.categoryType), [])
|
||||
categories: copyArrayTo(self.getDefaultCategories(self.categoryType), [])
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -113,12 +120,12 @@ export default {
|
||||
},
|
||||
getDefaultCategories(categoryType) {
|
||||
switch (categoryType) {
|
||||
case this.$constants.category.allCategoryTypes.Income:
|
||||
return this.$constants.category.defaultIncomeCategories;
|
||||
case this.$constants.category.allCategoryTypes.Expense:
|
||||
return this.$constants.category.defaultExpenseCategories;
|
||||
case this.$constants.category.allCategoryTypes.Transfer:
|
||||
return this.$constants.category.defaultTransferCategories;
|
||||
case categoryConstants.allCategoryTypes.Income:
|
||||
return categoryConstants.defaultIncomeCategories;
|
||||
case categoryConstants.allCategoryTypes.Expense:
|
||||
return categoryConstants.defaultExpenseCategories;
|
||||
case categoryConstants.allCategoryTypes.Transfer:
|
||||
return categoryConstants.defaultTransferCategories;
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
@@ -159,7 +166,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
self.$store.dispatch('addCategories', {
|
||||
self.transactionCategoriesStore.addCategories({
|
||||
categories: categories
|
||||
}).then(() => {
|
||||
self.submitting = false;
|
||||
@@ -178,11 +185,11 @@ export default {
|
||||
},
|
||||
getCategoryTypeName(categoryType) {
|
||||
switch (categoryType) {
|
||||
case this.$constants.category.allCategoryTypes.Income:
|
||||
case categoryConstants.allCategoryTypes.Income:
|
||||
return this.$t('Income Categories');
|
||||
case this.$constants.category.allCategoryTypes.Expense:
|
||||
case categoryConstants.allCategoryTypes.Expense:
|
||||
return this.$t('Expense Categories');
|
||||
case this.$constants.category.allCategoryTypes.Transfer:
|
||||
case categoryConstants.allCategoryTypes.Transfer:
|
||||
return this.$t('Transfer Categories');
|
||||
default:
|
||||
return this.$t('Transaction Categories');
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
<f7-accordion-content :style="{ height: collapseStates[accountCategory.category].opened ? 'auto' : '' }">
|
||||
<f7-list strong inset dividers accordion-list class="combination-list-content">
|
||||
<f7-list-item checkbox
|
||||
:class="{ 'has-child-list-item': account.type === $constants.account.allAccountTypes.MultiSubAccounts && accountCategory.visibleSubAccounts[account.id] }"
|
||||
:class="{ 'has-child-list-item': account.type === allAccountTypes.MultiSubAccounts && accountCategory.visibleSubAccounts[account.id] }"
|
||||
:title="account.name"
|
||||
:value="account.id"
|
||||
:checked="isAccountOrSubAccountsAllChecked(account, filterAccountIds)"
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
<template #root>
|
||||
<ul class="padding-left"
|
||||
v-if="account.type === $constants.account.allAccountTypes.MultiSubAccounts && accountCategory.visibleSubAccounts[account.id]">
|
||||
v-if="account.type === allAccountTypes.MultiSubAccounts && accountCategory.visibleSubAccounts[account.id]">
|
||||
<f7-list-item checkbox
|
||||
:title="subAccount.name"
|
||||
:value="subAccount.id"
|
||||
@@ -114,6 +114,14 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useAccountsStore } from '@/stores/account.js';
|
||||
import { useStatisticsStore } from '@/stores/statistics.js';
|
||||
|
||||
import accountConstants from '@/consts/account.js';
|
||||
import { copyObjectTo } from '@/lib/common.js';
|
||||
import { getVisibleCategorizedAccounts } from '@/lib/account.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7route',
|
||||
@@ -132,6 +140,7 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useAccountsStore, useStatisticsStore),
|
||||
title() {
|
||||
if (this.modifyDefault) {
|
||||
return 'Default Account Filter';
|
||||
@@ -146,11 +155,14 @@ export default {
|
||||
return 'Apply';
|
||||
}
|
||||
},
|
||||
allAccountTypes() {
|
||||
return accountConstants.allAccountTypes;
|
||||
},
|
||||
allVisibleCategorizedAccounts() {
|
||||
return this.$utilities.getVisibleCategorizedAccounts(this.$store.state.allCategorizedAccounts);
|
||||
return getVisibleCategorizedAccounts(this.accountsStore.allCategorizedAccounts);
|
||||
},
|
||||
hasAnyAvailableAccount() {
|
||||
return this.$store.getters.allVisibleAccountsCount > 0;
|
||||
return this.accountsStore.allVisibleAccountsCount > 0;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -159,26 +171,26 @@ export default {
|
||||
|
||||
self.modifyDefault = !!query.modifyDefault;
|
||||
|
||||
self.$store.dispatch('loadAllAccounts', {
|
||||
self.accountsStore.loadAllAccounts({
|
||||
force: false
|
||||
}).then(() => {
|
||||
self.loading = false;
|
||||
|
||||
const allAccountIds = {};
|
||||
|
||||
for (let accountId in self.$store.state.allAccountsMap) {
|
||||
if (!Object.prototype.hasOwnProperty.call(self.$store.state.allAccountsMap, accountId)) {
|
||||
for (let accountId in self.accountsStore.allAccountsMap) {
|
||||
if (!Object.prototype.hasOwnProperty.call(self.accountsStore.allAccountsMap, accountId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const account = self.$store.state.allAccountsMap[accountId];
|
||||
const account = self.accountsStore.allAccountsMap[accountId];
|
||||
allAccountIds[account.id] = false;
|
||||
}
|
||||
|
||||
if (self.modifyDefault) {
|
||||
self.filterAccountIds = self.$utilities.copyObjectTo(self.$settings.getStatisticsDefaultAccountFilter(), allAccountIds);
|
||||
self.filterAccountIds = copyObjectTo(self.$settings.getStatisticsDefaultAccountFilter(), allAccountIds);
|
||||
} else {
|
||||
self.filterAccountIds = self.$utilities.copyObjectTo(self.$store.state.transactionStatisticsFilter.filterAccountIds, allAccountIds);
|
||||
self.filterAccountIds = copyObjectTo(self.statisticsStore.transactionStatisticsFilter.filterAccountIds, allAccountIds);
|
||||
}
|
||||
}).catch(error => {
|
||||
if (error.processed) {
|
||||
@@ -212,7 +224,7 @@ export default {
|
||||
if (self.modifyDefault) {
|
||||
self.$settings.setStatisticsDefaultAccountFilter(filteredAccountIds);
|
||||
} else {
|
||||
self.$store.dispatch('updateTransactionStatisticsFilter', {
|
||||
self.statisticsStore.updateTransactionStatisticsFilter({
|
||||
filterAccountIds: filteredAccountIds
|
||||
});
|
||||
}
|
||||
@@ -221,15 +233,15 @@ export default {
|
||||
},
|
||||
selectAccountOrSubAccounts(e) {
|
||||
const accountId = e.target.value;
|
||||
const account = this.$store.state.allAccountsMap[accountId];
|
||||
const account = this.accountsStore.allAccountsMap[accountId];
|
||||
|
||||
if (!account) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (account.type === this.$constants.account.allAccountTypes.SingleAccount) {
|
||||
if (account.type === this.allAccountTypes.SingleAccount) {
|
||||
this.filterAccountIds[account.id] = !e.target.checked;
|
||||
} else if (account.type === this.$constants.account.allAccountTypes.MultiSubAccounts) {
|
||||
} else if (account.type === this.allAccountTypes.MultiSubAccounts) {
|
||||
if (!account.subAccounts || !account.subAccounts.length) {
|
||||
return;
|
||||
}
|
||||
@@ -242,7 +254,7 @@ export default {
|
||||
},
|
||||
selectAccount(e) {
|
||||
const accountId = e.target.value;
|
||||
const account = this.$store.state.allAccountsMap[accountId];
|
||||
const account = this.accountsStore.allAccountsMap[accountId];
|
||||
|
||||
if (!account) {
|
||||
return;
|
||||
@@ -256,9 +268,9 @@ export default {
|
||||
continue;
|
||||
}
|
||||
|
||||
const account = this.$store.state.allAccountsMap[accountId];
|
||||
const account = this.accountsStore.allAccountsMap[accountId];
|
||||
|
||||
if (account && account.type === this.$constants.account.allAccountTypes.SingleAccount) {
|
||||
if (account && account.type === this.allAccountTypes.SingleAccount) {
|
||||
this.filterAccountIds[account.id] = false;
|
||||
}
|
||||
}
|
||||
@@ -269,9 +281,9 @@ export default {
|
||||
continue;
|
||||
}
|
||||
|
||||
const account = this.$store.state.allAccountsMap[accountId];
|
||||
const account = this.accountsStore.allAccountsMap[accountId];
|
||||
|
||||
if (account && account.type === this.$constants.account.allAccountTypes.SingleAccount) {
|
||||
if (account && account.type === this.allAccountTypes.SingleAccount) {
|
||||
this.filterAccountIds[account.id] = true;
|
||||
}
|
||||
}
|
||||
@@ -282,9 +294,9 @@ export default {
|
||||
continue;
|
||||
}
|
||||
|
||||
const account = this.$store.state.allAccountsMap[accountId];
|
||||
const account = this.accountsStore.allAccountsMap[accountId];
|
||||
|
||||
if (account && account.type === this.$constants.account.allAccountTypes.SingleAccount) {
|
||||
if (account && account.type === this.allAccountTypes.SingleAccount) {
|
||||
this.filterAccountIds[account.id] = !this.filterAccountIds[account.id];
|
||||
}
|
||||
}
|
||||
@@ -325,12 +337,12 @@ export default {
|
||||
getCollapseStates() {
|
||||
const collapseStates = {};
|
||||
|
||||
for (let categoryType in this.$constants.account.allCategories) {
|
||||
if (!Object.prototype.hasOwnProperty.call(this.$constants.account.allCategories, categoryType)) {
|
||||
for (let categoryType in accountConstants.allCategories) {
|
||||
if (!Object.prototype.hasOwnProperty.call(accountConstants.allCategories, categoryType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const accountCategory = this.$constants.account.allCategories[categoryType];
|
||||
const accountCategory = accountConstants.allCategories[categoryType];
|
||||
|
||||
collapseStates[accountCategory.id] = {
|
||||
opened: true
|
||||
|
||||
@@ -123,6 +123,14 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||
import { useStatisticsStore } from '@/stores/statistics.js';
|
||||
|
||||
import categoryConstants from '@/consts/category.js';
|
||||
import { copyObjectTo } from '@/lib/common.js';
|
||||
import { allVisibleTransactionCategories } from '@/lib/category.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7route',
|
||||
@@ -141,6 +149,8 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useTransactionCategoriesStore, useStatisticsStore),
|
||||
|
||||
title() {
|
||||
if (this.modifyDefault) {
|
||||
return 'Default Transaction Category Filter';
|
||||
@@ -156,7 +166,7 @@ export default {
|
||||
}
|
||||
},
|
||||
allVisibleTransactionCategories() {
|
||||
return this.$utilities.allVisibleTransactionCategories(this.$store.state.allTransactionCategories);
|
||||
return allVisibleTransactionCategories(this.transactionCategoriesStore.allTransactionCategories);
|
||||
},
|
||||
hasAnyAvailableCategory() {
|
||||
for (let type in this.allVisibleTransactionCategories) {
|
||||
@@ -194,26 +204,26 @@ export default {
|
||||
|
||||
self.modifyDefault = !!query.modifyDefault;
|
||||
|
||||
self.$store.dispatch('loadAllCategories', {
|
||||
self.transactionCategoriesStore.loadAllCategories({
|
||||
force: false
|
||||
}).then(() => {
|
||||
self.loading = false;
|
||||
|
||||
const allCategoryIds = {};
|
||||
|
||||
for (let categoryId in self.$store.state.allTransactionCategoriesMap) {
|
||||
if (!Object.prototype.hasOwnProperty.call(self.$store.state.allTransactionCategoriesMap, categoryId)) {
|
||||
for (let categoryId in self.transactionCategoriesStore.allTransactionCategoriesMap) {
|
||||
if (!Object.prototype.hasOwnProperty.call(self.transactionCategoriesStore.allTransactionCategoriesMap, categoryId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const category = self.$store.state.allTransactionCategoriesMap[categoryId];
|
||||
const category = self.transactionCategoriesStore.allTransactionCategoriesMap[categoryId];
|
||||
allCategoryIds[category.id] = false;
|
||||
}
|
||||
|
||||
if (self.modifyDefault) {
|
||||
self.filterCategoryIds = self.$utilities.copyObjectTo(self.$settings.getStatisticsDefaultTransactionCategoryFilter(), allCategoryIds);
|
||||
self.filterCategoryIds = copyObjectTo(self.$settings.getStatisticsDefaultTransactionCategoryFilter(), allCategoryIds);
|
||||
} else {
|
||||
self.filterCategoryIds = self.$utilities.copyObjectTo(self.$store.state.transactionStatisticsFilter.filterCategoryIds, allCategoryIds);
|
||||
self.filterCategoryIds = copyObjectTo(self.statisticsStore.transactionStatisticsFilter.filterCategoryIds, allCategoryIds);
|
||||
}
|
||||
}).catch(error => {
|
||||
if (error.processed) {
|
||||
@@ -247,7 +257,7 @@ export default {
|
||||
if (self.modifyDefault) {
|
||||
self.$settings.setStatisticsDefaultTransactionCategoryFilter(filteredCategoryIds);
|
||||
} else {
|
||||
self.$store.dispatch('updateTransactionStatisticsFilter', {
|
||||
self.statisticsStore.updateTransactionStatisticsFilter({
|
||||
filterCategoryIds: filteredCategoryIds
|
||||
});
|
||||
}
|
||||
@@ -256,7 +266,7 @@ export default {
|
||||
},
|
||||
selectCategory(e) {
|
||||
const categoryId = e.target.value;
|
||||
const category = this.$store.state.allTransactionCategoriesMap[categoryId];
|
||||
const category = this.transactionCategoriesStore.allTransactionCategoriesMap[categoryId];
|
||||
|
||||
if (!category) {
|
||||
return;
|
||||
@@ -266,7 +276,7 @@ export default {
|
||||
},
|
||||
selectSubCategories(e) {
|
||||
const categoryId = e.target.value;
|
||||
const category = this.$store.state.allTransactionCategoriesMap[categoryId];
|
||||
const category = this.transactionCategoriesStore.allTransactionCategoriesMap[categoryId];
|
||||
|
||||
if (!category || !category.subCategories || !category.subCategories.length) {
|
||||
return;
|
||||
@@ -283,7 +293,7 @@ export default {
|
||||
continue;
|
||||
}
|
||||
|
||||
const category = this.$store.state.allTransactionCategoriesMap[categoryId];
|
||||
const category = this.transactionCategoriesStore.allTransactionCategoriesMap[categoryId];
|
||||
|
||||
if (category) {
|
||||
this.filterCategoryIds[category.id] = false;
|
||||
@@ -296,7 +306,7 @@ export default {
|
||||
continue;
|
||||
}
|
||||
|
||||
const category = this.$store.state.allTransactionCategoriesMap[categoryId];
|
||||
const category = this.transactionCategoriesStore.allTransactionCategoriesMap[categoryId];
|
||||
|
||||
if (category) {
|
||||
this.filterCategoryIds[category.id] = true;
|
||||
@@ -309,7 +319,7 @@ export default {
|
||||
continue;
|
||||
}
|
||||
|
||||
const category = this.$store.state.allTransactionCategoriesMap[categoryId];
|
||||
const category = this.transactionCategoriesStore.allTransactionCategoriesMap[categoryId];
|
||||
|
||||
if (category) {
|
||||
this.filterCategoryIds[category.id] = !this.filterCategoryIds[category.id];
|
||||
@@ -318,11 +328,11 @@ export default {
|
||||
},
|
||||
getCategoryTypeName(categoryType) {
|
||||
switch (categoryType) {
|
||||
case this.$constants.category.allCategoryTypes.Income.toString():
|
||||
case categoryConstants.allCategoryTypes.Income.toString():
|
||||
return this.$t('Income Categories');
|
||||
case this.$constants.category.allCategoryTypes.Expense.toString():
|
||||
case categoryConstants.allCategoryTypes.Expense.toString():
|
||||
return this.$t('Expense Categories');
|
||||
case this.$constants.category.allCategoryTypes.Transfer.toString():
|
||||
case categoryConstants.allCategoryTypes.Transfer.toString():
|
||||
return this.$t('Transfer Categories');
|
||||
default:
|
||||
return this.$t('Transaction Categories');
|
||||
@@ -356,12 +366,12 @@ export default {
|
||||
getCollapseStates() {
|
||||
const collapseStates = {};
|
||||
|
||||
for (let categoryTypeField in this.$constants.category.allCategoryTypes) {
|
||||
if (!Object.prototype.hasOwnProperty.call(this.$constants.category.allCategoryTypes, categoryTypeField)) {
|
||||
for (let categoryTypeField in categoryConstants.allCategoryTypes) {
|
||||
if (!Object.prototype.hasOwnProperty.call(categoryConstants.allCategoryTypes, categoryTypeField)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const categoryType = this.$constants.category.allCategoryTypes[categoryTypeField];
|
||||
const categoryType = categoryConstants.allCategoryTypes[categoryTypeField];
|
||||
|
||||
collapseStates[categoryType] = {
|
||||
opened: true
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
:title="$t('Default Chart Type')"
|
||||
smart-select :smart-select-params="{ openIn: 'popup', popupPush: true, closeOnSelect: true, scrollToSelectedItem: true, searchbar: true, searchbarPlaceholder: $t('Chart Type'), searchbarDisableText: $t('Cancel'), appendSearchbarNotFound: $t('No results'), popupCloseLinkText: $t('Done') }">
|
||||
<select v-model="defaultChartType">
|
||||
<option :value="$constants.statistics.allChartTypes.Pie">{{ $t('Pie Chart') }}</option>
|
||||
<option :value="$constants.statistics.allChartTypes.Bar">{{ $t('Bar Chart') }}</option>
|
||||
<option :value="allChartTypes.Pie">{{ $t('Pie Chart') }}</option>
|
||||
<option :value="allChartTypes.Bar">{{ $t('Bar Chart') }}</option>
|
||||
</select>
|
||||
</f7-list-item>
|
||||
|
||||
@@ -50,25 +50,31 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import datetimeConstants from '@/consts/datetime.js';
|
||||
import statisticsConstants from '@/consts/statistics.js';
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
allChartTypes() {
|
||||
return statisticsConstants.allChartTypes;
|
||||
},
|
||||
allChartDataTypes() {
|
||||
return this.$constants.statistics.allChartDataTypes;
|
||||
return statisticsConstants.allChartDataTypes;
|
||||
},
|
||||
allSortingTypes() {
|
||||
return this.$constants.statistics.allSortingTypes;
|
||||
return statisticsConstants.allSortingTypes;
|
||||
},
|
||||
allDateRanges() {
|
||||
const allDateRanges = [];
|
||||
|
||||
for (let dateRangeField in this.$constants.datetime.allDateRanges) {
|
||||
if (!Object.prototype.hasOwnProperty.call(this.$constants.datetime.allDateRanges, dateRangeField)) {
|
||||
for (let dateRangeField in datetimeConstants.allDateRanges) {
|
||||
if (!Object.prototype.hasOwnProperty.call(datetimeConstants.allDateRanges, dateRangeField)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const dateRangeType = this.$constants.datetime.allDateRanges[dateRangeField];
|
||||
const dateRangeType = datetimeConstants.allDateRanges[dateRangeField];
|
||||
|
||||
if (dateRangeType.type !== this.$constants.datetime.allDateRanges.Custom.type) {
|
||||
if (dateRangeType.type !== datetimeConstants.allDateRanges.Custom.type) {
|
||||
allDateRanges.push(dateRangeType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</f7-list>
|
||||
</f7-popover>
|
||||
|
||||
<f7-card v-if="query.chartType === $constants.statistics.allChartTypes.Pie">
|
||||
<f7-card v-if="query.chartType === allChartTypes.Pie">
|
||||
<f7-card-header class="no-border display-block">
|
||||
<div class="statistics-chart-header full-line text-align-right">
|
||||
<span style="margin-right: 4px;">{{ $t('Sort By') }}</span>
|
||||
@@ -76,7 +76,7 @@
|
||||
</f7-card-content>
|
||||
</f7-card>
|
||||
|
||||
<f7-card v-else-if="query.chartType === $constants.statistics.allChartTypes.Bar">
|
||||
<f7-card v-else-if="query.chartType === allChartTypes.Bar">
|
||||
<f7-card-header class="no-border display-block">
|
||||
<div class="statistics-chart-header display-flex full-line justify-content-space-between">
|
||||
<div>
|
||||
@@ -150,7 +150,7 @@
|
||||
<template #title>
|
||||
<div class="statistics-list-item-text">
|
||||
<span>{{ item.name }}</span>
|
||||
<small class="statistics-percent" v-if="item.percent >= 0">{{ $utilities.formatPercent(item.percent, 2, '<0.01') }}</small>
|
||||
<small class="statistics-percent" v-if="item.percent >= 0">{{ getDisplayPercent(item.percent, 2, '<0.01') }}</small>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -195,11 +195,11 @@
|
||||
<f7-link :class="{ 'disabled': query.dateType === allDateRanges.All.type || query.chartDataType === allChartDataTypes.AccountTotalAssets.type || query.chartDataType === allChartDataTypes.AccountTotalLiabilities.type }" @click="shiftDateRange(query.startTime, query.endTime, 1)">
|
||||
<f7-icon f7="arrow_right_square"></f7-icon>
|
||||
</f7-link>
|
||||
<f7-link class="tabbar-text-with-ellipsis" @click="setChartType($constants.statistics.allChartTypes.Pie)">
|
||||
<span :class="{ 'tabbar-item-changed': query.chartType === $constants.statistics.allChartTypes.Pie }">{{ $t('Pie Chart') }}</span>
|
||||
<f7-link class="tabbar-text-with-ellipsis" @click="setChartType(allChartTypes.Pie)">
|
||||
<span :class="{ 'tabbar-item-changed': query.chartType === allChartTypes.Pie }">{{ $t('Pie Chart') }}</span>
|
||||
</f7-link>
|
||||
<f7-link class="tabbar-text-with-ellipsis" @click="setChartType($constants.statistics.allChartTypes.Bar)">
|
||||
<span :class="{ 'tabbar-item-changed': query.chartType === $constants.statistics.allChartTypes.Bar }">{{ $t('Bar Chart') }}</span>
|
||||
<f7-link class="tabbar-text-with-ellipsis" @click="setChartType(allChartTypes.Bar)">
|
||||
<span :class="{ 'tabbar-item-changed': query.chartType === allChartTypes.Bar }">{{ $t('Bar Chart') }}</span>
|
||||
</f7-link>
|
||||
</f7-toolbar>
|
||||
|
||||
@@ -217,10 +217,10 @@
|
||||
</template>
|
||||
<template #footer>
|
||||
<div v-if="dateRange.type === allDateRanges.Custom.type && query.dateType === allDateRanges.Custom.type && query.startTime && query.endTime">
|
||||
<span>{{ $utilities.formatUnixTime(query.startTime, $locale.getLongDateTimeFormat()) }}</span>
|
||||
<span>{{ queryStartTime }}</span>
|
||||
<span> - </span>
|
||||
<br/>
|
||||
<span>{{ $utilities.formatUnixTime(query.endTime, $locale.getLongDateTimeFormat()) }}</span>
|
||||
<span>{{ queryEndTime }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</f7-list-item>
|
||||
@@ -250,6 +250,24 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useAccountsStore } from '@/stores/account.js';
|
||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||
import { useStatisticsStore } from '@/stores/statistics.js';
|
||||
|
||||
import datetimeConstants from '@/consts/datetime.js';
|
||||
import statisticsConstants from '@/consts/statistics.js';
|
||||
import { getNameByKeyValue, limitText, formatPercent } from '@/lib/common.js'
|
||||
import {
|
||||
parseDateFromUnixTime,
|
||||
getYear,
|
||||
getShiftedDateRange,
|
||||
getDateRangeByDateType,
|
||||
isDateRangeMatchFullYears,
|
||||
isDateRangeMatchFullMonths
|
||||
} from '@/lib/datetime.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7router'
|
||||
@@ -269,31 +287,41 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useUserStore, useAccountsStore, useTransactionCategoriesStore, useStatisticsStore),
|
||||
defaultCurrency() {
|
||||
return this.$store.getters.currentUserDefaultCurrency;
|
||||
return this.userStore.currentUserDefaultCurrency;
|
||||
},
|
||||
firstDayOfWeek() {
|
||||
return this.$store.getters.currentUserFirstDayOfWeek;
|
||||
return this.userStore.currentUserFirstDayOfWeek;
|
||||
},
|
||||
query() {
|
||||
return this.$store.state.transactionStatisticsFilter;
|
||||
return this.statisticsStore.transactionStatisticsFilter;
|
||||
},
|
||||
queryChartDataTypeName() {
|
||||
const queryChartDataTypeName = this.$utilities.getNameByKeyValue(this.allChartDataTypes, this.query.chartDataType, 'type', 'name', 'Statistics');
|
||||
const queryChartDataTypeName = getNameByKeyValue(this.allChartDataTypes, this.query.chartDataType, 'type', 'name', 'Statistics');
|
||||
return this.$t(queryChartDataTypeName);
|
||||
},
|
||||
querySortingTypeName() {
|
||||
const querySortingTypeName = this.$utilities.getNameByKeyValue(this.allSortingTypes, this.query.sortingType, 'type', 'name', 'System Default');
|
||||
const querySortingTypeName = getNameByKeyValue(this.allSortingTypes, this.query.sortingType, 'type', 'name', 'System Default');
|
||||
return this.$t(querySortingTypeName);
|
||||
},
|
||||
queryStartTime() {
|
||||
return this.$locale.formatUnixTimeToLongDateTime(this.userStore, this.query.startTime);
|
||||
},
|
||||
queryEndTime() {
|
||||
return this.$locale.formatUnixTimeToLongDateTime(this.userStore, this.query.endTime);
|
||||
},
|
||||
allChartTypes() {
|
||||
return statisticsConstants.allChartTypes;
|
||||
},
|
||||
allChartDataTypes() {
|
||||
return this.$constants.statistics.allChartDataTypes;
|
||||
return statisticsConstants.allChartDataTypes;
|
||||
},
|
||||
allSortingTypes() {
|
||||
return this.$constants.statistics.allSortingTypes;
|
||||
return statisticsConstants.allSortingTypes;
|
||||
},
|
||||
allDateRanges() {
|
||||
return this.$constants.datetime.allDateRanges;
|
||||
return datetimeConstants.allDateRanges;
|
||||
},
|
||||
totalAmountName() {
|
||||
if (this.query.chartDataType === this.allChartDataTypes.IncomeByAccount.type
|
||||
@@ -325,10 +353,10 @@ export default {
|
||||
self.query.chartDataType === self.allChartDataTypes.IncomeByAccount.type ||
|
||||
self.query.chartDataType === self.allChartDataTypes.IncomeByPrimaryCategory.type ||
|
||||
self.query.chartDataType === self.allChartDataTypes.IncomeBySecondaryCategory.type) {
|
||||
combinedData = this.$store.getters.statisticsItemsByTransactionStatisticsData;
|
||||
combinedData = this.statisticsStore.statisticsItemsByTransactionStatisticsData;
|
||||
} else if (self.query.chartDataType === self.allChartDataTypes.AccountTotalAssets.type ||
|
||||
self.query.chartDataType === self.allChartDataTypes.AccountTotalLiabilities.type) {
|
||||
combinedData = this.$store.getters.statisticsItemsByAccountsData;
|
||||
combinedData = this.statisticsStore.statisticsItemsByAccountsData;
|
||||
}
|
||||
|
||||
const allStatisticsItems = [];
|
||||
@@ -405,31 +433,31 @@ export default {
|
||||
|
||||
let defaultChartType = self.$settings.getStatisticsDefaultChartType();
|
||||
|
||||
if (defaultChartType !== self.$constants.statistics.allChartTypes.Pie && defaultChartType !== self.$constants.statistics.allChartTypes.Bar) {
|
||||
defaultChartType = self.$constants.statistics.defaultChartType;
|
||||
if (defaultChartType !== self.allChartTypes.Pie && defaultChartType !== self.allChartTypes.Bar) {
|
||||
defaultChartType = statisticsConstants.defaultChartType;
|
||||
}
|
||||
|
||||
let defaultChartDataType = self.$settings.getStatisticsDefaultChartDataType();
|
||||
|
||||
if (defaultChartDataType < self.allChartDataTypes.ExpenseByAccount.type || defaultChartDataType > self.allChartDataTypes.AccountTotalLiabilities.type) {
|
||||
defaultChartDataType = self.$constants.statistics.defaultChartDataType;
|
||||
defaultChartDataType = statisticsConstants.defaultChartDataType;
|
||||
}
|
||||
|
||||
let defaultDateRange = self.$settings.getStatisticsDefaultDateRange();
|
||||
|
||||
if (defaultDateRange < self.allDateRanges.All.type || defaultDateRange >= self.allDateRanges.Custom.type) {
|
||||
defaultDateRange = self.$constants.statistics.defaultDataRangeType;
|
||||
defaultDateRange = statisticsConstants.defaultDataRangeType;
|
||||
}
|
||||
|
||||
let defaultSortType = self.$settings.getStatisticsSortingType();
|
||||
|
||||
if (defaultSortType < self.allSortingTypes.Amount.type || defaultSortType > self.allSortingTypes.Name.type) {
|
||||
defaultSortType = self.$constants.statistics.defaultSortingType;
|
||||
defaultSortType = statisticsConstants.defaultSortingType;
|
||||
}
|
||||
|
||||
const dateRange = self.$utilities.getDateRangeByDateType(defaultDateRange, self.firstDayOfWeek);
|
||||
const dateRange = getDateRangeByDateType(defaultDateRange, self.firstDayOfWeek);
|
||||
|
||||
self.$store.dispatch('initTransactionStatisticsFilter', {
|
||||
self.statisticsStore.initTransactionStatisticsFilter({
|
||||
dateType: dateRange ? dateRange.dateType : undefined,
|
||||
startTime: dateRange ? dateRange.minTime : undefined,
|
||||
endTime: dateRange ? dateRange.maxTime : undefined,
|
||||
@@ -441,10 +469,10 @@ export default {
|
||||
});
|
||||
|
||||
Promise.all([
|
||||
self.$store.dispatch('loadAllAccounts', { force: false }),
|
||||
self.$store.dispatch('loadAllCategories', { force: false })
|
||||
self.accountsStore.loadAllAccounts({ force: false }),
|
||||
self.transactionCategoriesStore.loadAllCategories({ force: false })
|
||||
]).then(() => {
|
||||
return self.$store.dispatch('loadTransactionStatistics', {
|
||||
return self.statisticsStore.loadTransactionStatistics({
|
||||
defaultCurrency: self.defaultCurrency
|
||||
});
|
||||
}).then(() => {
|
||||
@@ -460,7 +488,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
onPageAfterIn() {
|
||||
if (this.$store.state.transactionStatisticsStateInvalid && !this.loading) {
|
||||
if (this.statisticsStore.transactionStatisticsStateInvalid && !this.loading) {
|
||||
this.reload(null);
|
||||
}
|
||||
|
||||
@@ -476,12 +504,12 @@ export default {
|
||||
self.query.chartDataType === self.allChartDataTypes.IncomeByAccount.type ||
|
||||
self.query.chartDataType === self.allChartDataTypes.IncomeByPrimaryCategory.type ||
|
||||
self.query.chartDataType === self.allChartDataTypes.IncomeBySecondaryCategory.type) {
|
||||
dispatchPromise = self.$store.dispatch('loadTransactionStatistics', {
|
||||
dispatchPromise = self.statisticsStore.loadTransactionStatistics({
|
||||
defaultCurrency: self.defaultCurrency
|
||||
});
|
||||
} else if (self.query.chartDataType === self.allChartDataTypes.AccountTotalAssets.type ||
|
||||
self.query.chartDataType === self.allChartDataTypes.AccountTotalLiabilities.type) {
|
||||
dispatchPromise = self.$store.dispatch('loadAllAccounts', {
|
||||
dispatchPromise = self.accountsStore.loadAllAccounts({
|
||||
force: true
|
||||
});
|
||||
}
|
||||
@@ -503,12 +531,12 @@ export default {
|
||||
}
|
||||
},
|
||||
setChartType(chartType) {
|
||||
this.$store.dispatch('updateTransactionStatisticsFilter', {
|
||||
this.statisticsStore.updateTransactionStatisticsFilter({
|
||||
chartType: chartType
|
||||
});
|
||||
},
|
||||
setChartDataType(chartDataType) {
|
||||
this.$store.dispatch('updateTransactionStatisticsFilter', {
|
||||
this.statisticsStore.updateTransactionStatisticsFilter({
|
||||
chartDataType: chartDataType
|
||||
});
|
||||
this.showChartDataTypePopover = false;
|
||||
@@ -519,7 +547,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$store.dispatch('updateTransactionStatisticsFilter', {
|
||||
this.statisticsStore.updateTransactionStatisticsFilter({
|
||||
sortingType: sortingType
|
||||
});
|
||||
|
||||
@@ -535,13 +563,13 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
const dateRange = this.$utilities.getDateRangeByDateType(dateType, this.firstDayOfWeek);
|
||||
const dateRange = getDateRangeByDateType(dateType, this.firstDayOfWeek);
|
||||
|
||||
if (!dateRange) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$store.dispatch('updateTransactionStatisticsFilter', {
|
||||
this.statisticsStore.updateTransactionStatisticsFilter({
|
||||
dateType: dateRange.dateType,
|
||||
startTime: dateRange.minTime,
|
||||
endTime: dateRange.maxTime
|
||||
@@ -555,7 +583,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$store.dispatch('updateTransactionStatisticsFilter', {
|
||||
this.statisticsStore.updateTransactionStatisticsFilter({
|
||||
dateType: this.allDateRanges.Custom.type,
|
||||
startTime: startTime,
|
||||
endTime: endTime
|
||||
@@ -570,7 +598,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
const newDateRange = this.$utilities.getShiftedDateRange(startTime, endTime, scale);
|
||||
const newDateRange = getShiftedDateRange(startTime, endTime, scale);
|
||||
let newDateType = this.allDateRanges.Custom.type;
|
||||
|
||||
for (let dateRangeField in this.allDateRanges) {
|
||||
@@ -579,7 +607,7 @@ export default {
|
||||
}
|
||||
|
||||
const dateRangeType = this.allDateRanges[dateRangeField];
|
||||
const dateRange = this.$utilities.getDateRangeByDateType(dateRangeType.type, this.firstDayOfWeek);
|
||||
const dateRange = getDateRangeByDateType(dateRangeType.type, this.firstDayOfWeek);
|
||||
|
||||
if (dateRange && dateRange.minTime === newDateRange.minTime && dateRange.maxTime === newDateRange.maxTime) {
|
||||
newDateType = dateRangeType.type;
|
||||
@@ -587,7 +615,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
this.$store.dispatch('updateTransactionStatisticsFilter', {
|
||||
this.statisticsStore.updateTransactionStatisticsFilter({
|
||||
dateType: newDateType,
|
||||
startTime: newDateRange.minTime,
|
||||
endTime: newDateRange.maxTime
|
||||
@@ -617,30 +645,30 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.$utilities.isDateRangeMatchFullYears(query.startTime, query.endTime)) {
|
||||
const displayStartTime = this.$utilities.formatUnixTime(query.startTime, this.$locale.getShortYearFormat());
|
||||
const displayEndTime = this.$utilities.formatUnixTime(query.endTime, this.$locale.getShortYearFormat());
|
||||
if (isDateRangeMatchFullYears(query.startTime, query.endTime)) {
|
||||
const displayStartTime = this.$locale.formatUnixTimeToShortYear(this.userStore, query.startTime);
|
||||
const displayEndTime = this.$locale.formatUnixTimeToShortYear(this.userStore, query.endTime);
|
||||
|
||||
return displayStartTime !== displayEndTime ? `${displayStartTime} ~ ${displayEndTime}` : displayStartTime;
|
||||
}
|
||||
|
||||
if (this.$utilities.isDateRangeMatchFullMonths(query.startTime, query.endTime)) {
|
||||
const displayStartTime = this.$utilities.formatUnixTime(query.startTime, this.$locale.getShortYearMonthFormat());
|
||||
const displayEndTime = this.$utilities.formatUnixTime(query.endTime, this.$locale.getShortYearMonthFormat());
|
||||
if (isDateRangeMatchFullMonths(query.startTime, query.endTime)) {
|
||||
const displayStartTime = this.$locale.formatUnixTimeToShortYearMonth(this.userStore, query.startTime);
|
||||
const displayEndTime = this.$locale.formatUnixTimeToShortYearMonth(this.userStore, query.endTime);
|
||||
|
||||
return displayStartTime !== displayEndTime ? `${displayStartTime} ~ ${displayEndTime}` : displayStartTime;
|
||||
}
|
||||
|
||||
const startTimeYear = this.$utilities.getYear(this.$utilities.parseDateFromUnixTime(query.startTime));
|
||||
const endTimeYear = this.$utilities.getYear(this.$utilities.parseDateFromUnixTime(query.endTime));
|
||||
const startTimeYear = getYear(parseDateFromUnixTime(query.startTime));
|
||||
const endTimeYear = getYear(parseDateFromUnixTime(query.endTime));
|
||||
|
||||
const displayStartTime = this.$utilities.formatUnixTime(query.startTime, this.$locale.getShortDateFormat());
|
||||
const displayEndTime = this.$utilities.formatUnixTime(query.endTime, this.$locale.getShortDateFormat());
|
||||
const displayStartTime = this.$locale.formatUnixTimeToShortDate(this.userStore, query.startTime);
|
||||
const displayEndTime = this.$locale.formatUnixTimeToShortDate(this.userStore, query.endTime);
|
||||
|
||||
if (displayStartTime === displayEndTime) {
|
||||
return displayStartTime;
|
||||
} else if (startTimeYear === endTimeYear) {
|
||||
const displayShortEndTime = this.$utilities.formatUnixTime(query.endTime, this.$locale.getShortMonthDayFormat());
|
||||
const displayShortEndTime = this.$locale.formatUnixTimeToShortMonthDay(this.userStore, query.endTime);
|
||||
return `${displayStartTime} ~ ${displayShortEndTime}`;
|
||||
}
|
||||
|
||||
@@ -690,11 +718,14 @@ export default {
|
||||
}
|
||||
|
||||
if (textLimit) {
|
||||
this.$utilities.limitText(amount, textLimit);
|
||||
return limitText(amount, textLimit);
|
||||
}
|
||||
|
||||
return amount;
|
||||
},
|
||||
getDisplayPercent(value, precision, lowPrecisionValue) {
|
||||
return formatPercent(value, precision, lowPrecisionValue);
|
||||
},
|
||||
getItemLinkUrl(item) {
|
||||
const querys = [];
|
||||
|
||||
|
||||
@@ -144,6 +144,11 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
||||
|
||||
import { onSwipeoutDeleted } from '@/lib/ui.mobile.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7router'
|
||||
@@ -168,8 +173,10 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useTransactionTagsStore),
|
||||
|
||||
tags() {
|
||||
return this.$store.state.allTransactionTags;
|
||||
return this.transactionTagsStore.allTransactionTags;
|
||||
},
|
||||
firstShowingId() {
|
||||
for (let i = 0; i < this.tags.length; i++) {
|
||||
@@ -207,7 +214,7 @@ export default {
|
||||
|
||||
self.loading = true;
|
||||
|
||||
self.$store.dispatch('loadAllTags', {
|
||||
self.transactionTagsStore.loadAllTags({
|
||||
force: false
|
||||
}).then(() => {
|
||||
self.loading = false;
|
||||
@@ -232,7 +239,7 @@ export default {
|
||||
|
||||
const self = this;
|
||||
|
||||
self.$store.dispatch('loadAllTags', {
|
||||
self.transactionTagsStore.loadAllTags({
|
||||
force: true
|
||||
}).then(() => {
|
||||
if (done) {
|
||||
@@ -272,7 +279,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
self.$store.dispatch('changeTagDisplayOrder', {
|
||||
self.transactionTagsStore.changeTagDisplayOrder({
|
||||
tagId: id,
|
||||
from: event.from,
|
||||
to: event.to
|
||||
@@ -294,7 +301,7 @@ export default {
|
||||
self.displayOrderSaving = true;
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('updateTagDisplayOrders').then(() => {
|
||||
self.transactionTagsStore.updateTagDisplayOrders().then(() => {
|
||||
self.displayOrderSaving = false;
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -324,7 +331,7 @@ export default {
|
||||
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('saveTag', {
|
||||
self.transactionTagsStore.saveTag({
|
||||
tag: tag
|
||||
}).then(() => {
|
||||
self.$hideLoading();
|
||||
@@ -363,7 +370,7 @@ export default {
|
||||
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('hideTag', {
|
||||
self.transactionTagsStore.hideTag({
|
||||
tag: tag,
|
||||
hidden: hidden
|
||||
}).then(() => {
|
||||
@@ -394,10 +401,10 @@ export default {
|
||||
self.tagToDelete = null;
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('deleteTag', {
|
||||
self.transactionTagsStore.deleteTag({
|
||||
tag: tag,
|
||||
beforeResolve: (done) => {
|
||||
self.$ui.onSwipeoutDeleted(self.getTagDomId(tag), done);
|
||||
onSwipeoutDeleted(self.getTagDomId(tag), done);
|
||||
}
|
||||
}).then(() => {
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
|
||||
<f7-subnavbar>
|
||||
<f7-segmented strong :class="{ 'readonly': mode !== 'add' }">
|
||||
<f7-button :text="$t('Expense')" :active="transaction.type === $constants.transaction.allTransactionTypes.Expense" @click="transaction.type = $constants.transaction.allTransactionTypes.Expense"></f7-button>
|
||||
<f7-button :text="$t('Income')" :active="transaction.type === $constants.transaction.allTransactionTypes.Income" @click="transaction.type = $constants.transaction.allTransactionTypes.Income"></f7-button>
|
||||
<f7-button :text="$t('Transfer')" :active="transaction.type === $constants.transaction.allTransactionTypes.Transfer" @click="transaction.type = $constants.transaction.allTransactionTypes.Transfer"></f7-button>
|
||||
<f7-button :text="$t('Expense')" :active="transaction.type === allTransactionTypes.Expense" @click="transaction.type = allTransactionTypes.Expense"></f7-button>
|
||||
<f7-button :text="$t('Income')" :active="transaction.type === allTransactionTypes.Income" @click="transaction.type = allTransactionTypes.Income"></f7-button>
|
||||
<f7-button :text="$t('Transfer')" :active="transaction.type === allTransactionTypes.Transfer" @click="transaction.type = allTransactionTypes.Transfer"></f7-button>
|
||||
</f7-segmented>
|
||||
</f7-subnavbar>
|
||||
</f7-navbar>
|
||||
@@ -43,14 +43,14 @@
|
||||
<f7-list-item
|
||||
class="transaction-edit-amount"
|
||||
link="#" no-chevron
|
||||
:class="{ 'readonly': mode === 'view', 'color-teal': transaction.type === $constants.transaction.allTransactionTypes.Expense, 'color-red': transaction.type === $constants.transaction.allTransactionTypes.Income }"
|
||||
:class="{ 'readonly': mode === 'view', 'color-teal': transaction.type === allTransactionTypes.Expense, 'color-red': transaction.type === allTransactionTypes.Income }"
|
||||
:style="{ fontSize: sourceAmountFontSize + 'px' }"
|
||||
:header="$t(sourceAmountName)"
|
||||
:title="getDisplayAmount(transaction.sourceAmount, transaction.hideAmount)"
|
||||
@click="showSourceAmountSheet = true"
|
||||
>
|
||||
<number-pad-sheet :min-value="$constants.transaction.minAmount"
|
||||
:max-value="$constants.transaction.maxAmount"
|
||||
<number-pad-sheet :min-value="allowedMinAmount"
|
||||
:max-value="allowedMaxAmount"
|
||||
v-model:show="showSourceAmountSheet"
|
||||
v-model="transaction.sourceAmount"
|
||||
></number-pad-sheet>
|
||||
@@ -64,10 +64,10 @@
|
||||
:header="$t('Transfer In Amount')"
|
||||
:title="getDisplayAmount(transaction.destinationAmount, transaction.hideAmount)"
|
||||
@click="showDestinationAmountSheet = true"
|
||||
v-if="transaction.type === $constants.transaction.allTransactionTypes.Transfer"
|
||||
v-if="transaction.type === allTransactionTypes.Transfer"
|
||||
>
|
||||
<number-pad-sheet :min-value="$constants.transaction.minAmount"
|
||||
:max-value="$constants.transaction.maxAmount"
|
||||
<number-pad-sheet :min-value="allowedMinAmount"
|
||||
:max-value="allowedMaxAmount"
|
||||
v-model:show="showDestinationAmountSheet"
|
||||
v-model="transaction.destinationAmount"
|
||||
></number-pad-sheet>
|
||||
@@ -80,13 +80,13 @@
|
||||
:class="{ 'disabled': !hasAvailableExpenseCategories, 'readonly': mode === 'view' }"
|
||||
:header="$t('Category')"
|
||||
@click="showCategorySheet = true"
|
||||
v-if="transaction.type === $constants.transaction.allTransactionTypes.Expense"
|
||||
v-if="transaction.type === allTransactionTypes.Expense"
|
||||
>
|
||||
<template #title>
|
||||
<div class="list-item-custom-title" v-if="hasAvailableExpenseCategories">
|
||||
<span>{{ getPrimaryCategoryName(transaction.expenseCategory, allCategories[$constants.category.allCategoryTypes.Expense]) }}</span>
|
||||
<span>{{ getPrimaryCategoryName(transaction.expenseCategory, allCategories[allCategoryTypes.Expense]) }}</span>
|
||||
<f7-icon class="category-separate-icon" f7="chevron_right"></f7-icon>
|
||||
<span>{{ getSecondaryCategoryName(transaction.expenseCategory, allCategories[$constants.category.allCategoryTypes.Expense]) }}</span>
|
||||
<span>{{ getSecondaryCategoryName(transaction.expenseCategory, allCategories[allCategoryTypes.Expense]) }}</span>
|
||||
</div>
|
||||
<div class="list-item-custom-title" v-else-if="!hasAvailableExpenseCategories">
|
||||
<span>{{ $t('None') }}</span>
|
||||
@@ -97,7 +97,7 @@
|
||||
primary-sub-items-field="subCategories"
|
||||
secondary-key-field="id" secondary-value-field="id" secondary-title-field="name"
|
||||
secondary-icon-field="icon" secondary-icon-type="category" secondary-color-field="color"
|
||||
:items="allCategories[$constants.category.allCategoryTypes.Expense]"
|
||||
:items="allCategories[allCategoryTypes.Expense]"
|
||||
v-model:show="showCategorySheet"
|
||||
v-model="transaction.expenseCategory">
|
||||
</tree-view-selection-sheet>
|
||||
@@ -110,13 +110,13 @@
|
||||
:class="{ 'disabled': !hasAvailableIncomeCategories, 'readonly': mode === 'view' }"
|
||||
:header="$t('Category')"
|
||||
@click="showCategorySheet = true"
|
||||
v-if="transaction.type === $constants.transaction.allTransactionTypes.Income"
|
||||
v-if="transaction.type === allTransactionTypes.Income"
|
||||
>
|
||||
<template #title>
|
||||
<div class="list-item-custom-title" v-if="hasAvailableIncomeCategories">
|
||||
<span>{{ getPrimaryCategoryName(transaction.incomeCategory, allCategories[$constants.category.allCategoryTypes.Income]) }}</span>
|
||||
<span>{{ getPrimaryCategoryName(transaction.incomeCategory, allCategories[allCategoryTypes.Income]) }}</span>
|
||||
<f7-icon class="category-separate-icon" f7="chevron_right"></f7-icon>
|
||||
<span>{{ getSecondaryCategoryName(transaction.incomeCategory, allCategories[$constants.category.allCategoryTypes.Income]) }}</span>
|
||||
<span>{{ getSecondaryCategoryName(transaction.incomeCategory, allCategories[allCategoryTypes.Income]) }}</span>
|
||||
</div>
|
||||
<div class="list-item-custom-title" v-else-if="!hasAvailableIncomeCategories">
|
||||
<span>{{ $t('None') }}</span>
|
||||
@@ -127,7 +127,7 @@
|
||||
primary-sub-items-field="subCategories"
|
||||
secondary-key-field="id" secondary-value-field="id" secondary-title-field="name"
|
||||
secondary-icon-field="icon" secondary-icon-type="category" secondary-color-field="color"
|
||||
:items="allCategories[$constants.category.allCategoryTypes.Income]"
|
||||
:items="allCategories[allCategoryTypes.Income]"
|
||||
v-model:show="showCategorySheet"
|
||||
v-model="transaction.incomeCategory">
|
||||
</tree-view-selection-sheet>
|
||||
@@ -140,13 +140,13 @@
|
||||
:class="{ 'disabled': !hasAvailableTransferCategories, 'readonly': mode === 'view' }"
|
||||
:header="$t('Category')"
|
||||
@click="showCategorySheet = true"
|
||||
v-if="transaction.type === $constants.transaction.allTransactionTypes.Transfer"
|
||||
v-if="transaction.type === allTransactionTypes.Transfer"
|
||||
>
|
||||
<template #title>
|
||||
<div class="list-item-custom-title" v-if="hasAvailableTransferCategories">
|
||||
<span>{{ getPrimaryCategoryName(transaction.transferCategory, allCategories[$constants.category.allCategoryTypes.Transfer]) }}</span>
|
||||
<span>{{ getPrimaryCategoryName(transaction.transferCategory, allCategories[allCategoryTypes.Transfer]) }}</span>
|
||||
<f7-icon class="category-separate-icon" f7="chevron_right"></f7-icon>
|
||||
<span>{{ getSecondaryCategoryName(transaction.transferCategory, allCategories[$constants.category.allCategoryTypes.Transfer]) }}</span>
|
||||
<span>{{ getSecondaryCategoryName(transaction.transferCategory, allCategories[allCategoryTypes.Transfer]) }}</span>
|
||||
</div>
|
||||
<div class="list-item-custom-title" v-else-if="!hasAvailableTransferCategories">
|
||||
<span>{{ $t('None') }}</span>
|
||||
@@ -157,7 +157,7 @@
|
||||
primary-sub-items-field="subCategories"
|
||||
secondary-key-field="id" secondary-value-field="id" secondary-title-field="name"
|
||||
secondary-icon-field="icon" secondary-icon-type="category" secondary-color-field="color"
|
||||
:items="allCategories[$constants.category.allCategoryTypes.Transfer]"
|
||||
:items="allCategories[allCategoryTypes.Transfer]"
|
||||
v-model:show="showCategorySheet"
|
||||
v-model="transaction.transferCategory">
|
||||
</tree-view-selection-sheet>
|
||||
@@ -167,8 +167,8 @@
|
||||
class="list-item-with-header-and-title"
|
||||
link="#" no-chevron
|
||||
:class="{ 'disabled': !allVisibleAccounts.length, 'readonly': mode === 'view' }"
|
||||
:header="$t(sourceAccountName)"
|
||||
:title="transaction.sourceAccountId ? $utilities.getNameByKeyValue(allAccounts, transaction.sourceAccountId, 'id', 'name') : $t('None')"
|
||||
:header="$t(sourceAccountTitle)"
|
||||
:title="sourceAccountName"
|
||||
@click="showSourceAccountSheet = true"
|
||||
>
|
||||
<two-column-list-item-selection-sheet primary-key-field="id" primary-value-field="category"
|
||||
@@ -190,8 +190,8 @@
|
||||
link="#" no-chevron
|
||||
:class="{ 'disabled': !allVisibleAccounts.length, 'readonly': mode === 'view' }"
|
||||
:header="$t('Destination Account')"
|
||||
:title="transaction.destinationAccountId ? $utilities.getNameByKeyValue(allAccounts, transaction.destinationAccountId, 'id', 'name') : $t('None')"
|
||||
v-if="transaction.type === $constants.transaction.allTransactionTypes.Transfer"
|
||||
:title="destinationAccountName"
|
||||
v-if="transaction.type === allTransactionTypes.Transfer"
|
||||
@click="showDestinationAccountSheet = true"
|
||||
>
|
||||
<two-column-list-item-selection-sheet primary-key-field="id" primary-value-field="category"
|
||||
@@ -213,7 +213,7 @@
|
||||
link="#" no-chevron
|
||||
:class="{ 'readonly': mode === 'view' }"
|
||||
:header="$t('Transaction Time')"
|
||||
:title="$utilities.formatUnixTime($utilities.getActualUnixTimeForStore(transaction.time, $utilities.getTimezoneOffsetMinutes(), $utilities.getBrowserTimezoneOffsetMinutes()), $locale.getLongDateTimeFormat())"
|
||||
:title="transactionDisplayTime"
|
||||
@click="showTransactionDateTimeSheet = true"
|
||||
>
|
||||
<date-time-selection-sheet v-model:show="showTransactionDateTimeSheet"
|
||||
@@ -234,8 +234,8 @@
|
||||
</select>
|
||||
<template #title>
|
||||
<f7-block class="list-item-custom-title no-padding no-margin">
|
||||
<span>{{ `(UTC${$utilities.getUtcOffsetByUtcOffsetMinutes(transaction.utcOffset)})` }}</span>
|
||||
<span class="transaction-edit-timezone-name" v-if="transaction.timeZone || transaction.timeZone === ''">{{ $utilities.getNameByKeyValue(allTimezones, transaction.timeZone, 'name', 'displayName') }}</span>
|
||||
<span>{{ `(${transactionDisplayTimezone})` }}</span>
|
||||
<span class="transaction-edit-timezone-name" v-if="transaction.timeZone || transaction.timeZone === ''">{{ transactionDisplayTimezoneName }}</span>
|
||||
</f7-block>
|
||||
</template>
|
||||
</f7-list-item>
|
||||
@@ -273,7 +273,7 @@
|
||||
<template #footer>
|
||||
<f7-block class="margin-top-half no-padding no-margin" v-if="transaction.tagIds && transaction.tagIds.length">
|
||||
<f7-chip media-bg-color="black" class="transaction-edit-tag"
|
||||
:text="$utilities.getNameByKeyValue(allTags, tagId, 'id', 'name')"
|
||||
:text="getTagName(tagId)"
|
||||
:key="tagId"
|
||||
v-for="tagId in transaction.tagIds">
|
||||
<template #media>
|
||||
@@ -332,6 +332,43 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useAccountsStore } from '@/stores/account.js';
|
||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
||||
import { useTransactionsStore } from '@/stores/transaction.js';
|
||||
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
|
||||
|
||||
import categoryConstants from '@/consts/category.js';
|
||||
import transactionConstants from '@/consts/transaction.js';
|
||||
import logger from '@/lib/logger.js';
|
||||
import {
|
||||
isNumber,
|
||||
copyObjectTo,
|
||||
getNameByKeyValue
|
||||
} from '@/lib/common.js';
|
||||
import {
|
||||
getCurrentUnixTime,
|
||||
getTimezoneOffsetMinutes,
|
||||
getBrowserTimezoneOffsetMinutes,
|
||||
getUtcOffsetByUtcOffsetMinutes,
|
||||
getDummyUnixTimeForLocalUsage,
|
||||
getActualUnixTimeForStore
|
||||
} from '@/lib/datetime.js';
|
||||
import {
|
||||
stringCurrencyToNumeric
|
||||
} from '@/lib/currency.js';
|
||||
import {
|
||||
getCategorizedAccounts,
|
||||
getAllFilteredAccountsBalance
|
||||
} from '@/lib/account.js';
|
||||
import {
|
||||
categoryTypeToTransactionType,
|
||||
getTransactionPrimaryCategoryName,
|
||||
getTransactionSecondaryCategoryName
|
||||
} from '@/lib/category.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7route',
|
||||
@@ -340,15 +377,15 @@ export default {
|
||||
data() {
|
||||
const self = this;
|
||||
const query = self.f7route.query;
|
||||
const now = self.$utilities.getCurrentUnixTime();
|
||||
const now = getCurrentUnixTime();
|
||||
const currentTimezone = self.$locale.getTimezone();
|
||||
|
||||
let defaultType = self.$constants.transaction.allTransactionTypes.Expense;
|
||||
let defaultType = transactionConstants.allTransactionTypes.Expense;
|
||||
|
||||
if (query.type === self.$constants.transaction.allTransactionTypes.Income.toString()) {
|
||||
defaultType = self.$constants.transaction.allTransactionTypes.Income;
|
||||
} else if (query.type === self.$constants.transaction.allTransactionTypes.Transfer.toString()) {
|
||||
defaultType = self.$constants.transaction.allTransactionTypes.Transfer;
|
||||
if (query.type === transactionConstants.allTransactionTypes.Income.toString()) {
|
||||
defaultType = transactionConstants.allTransactionTypes.Income;
|
||||
} else if (query.type === transactionConstants.allTransactionTypes.Transfer.toString()) {
|
||||
defaultType = transactionConstants.allTransactionTypes.Transfer;
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -358,7 +395,7 @@ export default {
|
||||
type: defaultType,
|
||||
time: now,
|
||||
timeZone: currentTimezone,
|
||||
utcOffset: self.$utilities.getTimezoneOffsetMinutes(currentTimezone),
|
||||
utcOffset: getTimezoneOffsetMinutes(currentTimezone),
|
||||
expenseCategory: '',
|
||||
incomeCategory: '',
|
||||
transferCategory: '',
|
||||
@@ -390,6 +427,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useUserStore, useAccountsStore, useTransactionCategoriesStore, useTransactionTagsStore, useTransactionsStore, useExchangeRatesStore),
|
||||
title() {
|
||||
if (this.mode === 'add') {
|
||||
return 'Add Transaction';
|
||||
@@ -407,48 +445,51 @@ export default {
|
||||
}
|
||||
},
|
||||
sourceAmountName() {
|
||||
if (this.transaction.type === this.$constants.transaction.allTransactionTypes.Expense) {
|
||||
if (this.transaction.type === this.allTransactionTypes.Expense) {
|
||||
return 'Expense Amount';
|
||||
} else if (this.transaction.type === this.$constants.transaction.allTransactionTypes.Income) {
|
||||
} else if (this.transaction.type === this.allTransactionTypes.Income) {
|
||||
return 'Income Amount';
|
||||
} else if (this.transaction.type === this.$constants.transaction.allTransactionTypes.Transfer) {
|
||||
} else if (this.transaction.type === this.allTransactionTypes.Transfer) {
|
||||
return 'Transfer Out Amount';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
sourceAccountName() {
|
||||
if (this.transaction.type === this.$constants.transaction.allTransactionTypes.Expense || this.transaction.type === this.$constants.transaction.allTransactionTypes.Income) {
|
||||
sourceAccountTitle() {
|
||||
if (this.transaction.type === this.allTransactionTypes.Expense || this.transaction.type === this.allTransactionTypes.Income) {
|
||||
return 'Account';
|
||||
} else if (this.transaction.type === this.$constants.transaction.allTransactionTypes.Transfer) {
|
||||
} else if (this.transaction.type === this.allTransactionTypes.Transfer) {
|
||||
return 'Source Account';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
defaultCurrency() {
|
||||
return this.$store.getters.currentUserDefaultCurrency;
|
||||
return this.userStore.currentUserDefaultCurrency;
|
||||
},
|
||||
defaultAccountId() {
|
||||
return this.$store.getters.currentUserDefaultAccountId;
|
||||
return this.userStore.currentUserDefaultAccountId;
|
||||
},
|
||||
defaultFirstDayOfWeek() {
|
||||
return this.$store.getters.currentUserFirstDayOfWeek;
|
||||
allTransactionTypes() {
|
||||
return transactionConstants.allTransactionTypes;
|
||||
},
|
||||
allCategoryTypes() {
|
||||
return categoryConstants.allCategoryTypes;
|
||||
},
|
||||
allTimezones() {
|
||||
return this.$locale.getAllTimezones(true);
|
||||
},
|
||||
allAccounts() {
|
||||
return this.$store.getters.allPlainAccounts;
|
||||
return this.accountsStore.allPlainAccounts;
|
||||
},
|
||||
allVisibleAccounts() {
|
||||
return this.$store.getters.allVisiblePlainAccounts;
|
||||
return this.accountsStore.allVisiblePlainAccounts;
|
||||
},
|
||||
allAccountsMap() {
|
||||
return this.$store.state.allAccountsMap;
|
||||
return this.accountsStore.allAccountsMap;
|
||||
},
|
||||
categorizedAccounts() {
|
||||
const categorizedAccounts = this.$utilities.copyObjectTo(this.$utilities.getCategorizedAccounts(this.allVisibleAccounts), {});
|
||||
const categorizedAccounts = copyObjectTo(getCategorizedAccounts(this.allVisibleAccounts), {});
|
||||
|
||||
for (let category in categorizedAccounts) {
|
||||
if (!Object.prototype.hasOwnProperty.call(categorizedAccounts, category)) {
|
||||
@@ -472,7 +513,7 @@ export default {
|
||||
}
|
||||
|
||||
if (this.showAccountBalance) {
|
||||
const accountsBalance = this.$utilities.getAllFilteredAccountsBalance(categorizedAccounts, account => account.category === accountCategory.category);
|
||||
const accountsBalance = getAllFilteredAccountsBalance(categorizedAccounts, account => account.category === accountCategory.category);
|
||||
let totalBalance = 0;
|
||||
let hasUnCalculatedAmount = false;
|
||||
|
||||
@@ -484,9 +525,9 @@ export default {
|
||||
totalBalance -= accountsBalance[i].balance;
|
||||
}
|
||||
} else {
|
||||
const balance = this.$store.getters.getExchangedAmount(accountsBalance[i].balance, accountsBalance[i].currency, this.defaultCurrency);
|
||||
const balance = this.exchangeRatesStore.getExchangedAmount(accountsBalance[i].balance, accountsBalance[i].currency, this.defaultCurrency);
|
||||
|
||||
if (!this.$utilities.isNumber(balance)) {
|
||||
if (!isNumber(balance)) {
|
||||
hasUnCalculatedAmount = true;
|
||||
continue;
|
||||
}
|
||||
@@ -512,38 +553,61 @@ export default {
|
||||
return categorizedAccounts;
|
||||
},
|
||||
allCategories() {
|
||||
return this.$store.state.allTransactionCategories;
|
||||
return this.transactionCategoriesStore.allTransactionCategories;
|
||||
},
|
||||
allCategoriesMap() {
|
||||
return this.$store.state.allTransactionCategoriesMap;
|
||||
return this.transactionCategoriesStore.allTransactionCategoriesMap;
|
||||
},
|
||||
allTags() {
|
||||
return this.$store.state.allTransactionTags;
|
||||
return this.transactionTagsStore.allTransactionTags;
|
||||
},
|
||||
hasAvailableExpenseCategories() {
|
||||
if (!this.allCategories || !this.allCategories[this.$constants.category.allCategoryTypes.Expense] || !this.allCategories[this.$constants.category.allCategoryTypes.Expense].length) {
|
||||
if (!this.allCategories || !this.allCategories[this.allCategoryTypes.Expense] || !this.allCategories[this.allCategoryTypes.Expense].length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const firstAvailableCategoryId = this.getFirstAvailableCategoryId(this.allCategories[this.$constants.category.allCategoryTypes.Expense]);
|
||||
const firstAvailableCategoryId = this.getFirstAvailableCategoryId(this.allCategories[this.allCategoryTypes.Expense]);
|
||||
return firstAvailableCategoryId !== '';
|
||||
},
|
||||
hasAvailableIncomeCategories() {
|
||||
if (!this.allCategories || !this.allCategories[this.$constants.category.allCategoryTypes.Income] || !this.allCategories[this.$constants.category.allCategoryTypes.Income].length) {
|
||||
if (!this.allCategories || !this.allCategories[this.allCategoryTypes.Income] || !this.allCategories[this.allCategoryTypes.Income].length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const firstAvailableCategoryId = this.getFirstAvailableCategoryId(this.allCategories[this.$constants.category.allCategoryTypes.Income]);
|
||||
const firstAvailableCategoryId = this.getFirstAvailableCategoryId(this.allCategories[this.allCategoryTypes.Income]);
|
||||
return firstAvailableCategoryId !== '';
|
||||
},
|
||||
hasAvailableTransferCategories() {
|
||||
if (!this.allCategories || !this.allCategories[this.$constants.category.allCategoryTypes.Transfer] || !this.allCategories[this.$constants.category.allCategoryTypes.Transfer].length) {
|
||||
if (!this.allCategories || !this.allCategories[this.allCategoryTypes.Transfer] || !this.allCategories[this.allCategoryTypes.Transfer].length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const firstAvailableCategoryId = this.getFirstAvailableCategoryId(this.allCategories[this.$constants.category.allCategoryTypes.Transfer]);
|
||||
const firstAvailableCategoryId = this.getFirstAvailableCategoryId(this.allCategories[this.allCategoryTypes.Transfer]);
|
||||
return firstAvailableCategoryId !== '';
|
||||
},
|
||||
sourceAccountName() {
|
||||
if (this.transaction.sourceAccountId) {
|
||||
return getNameByKeyValue(this.allAccounts, this.transaction.sourceAccountId, 'id', 'name');
|
||||
} else {
|
||||
return this.$t('None');
|
||||
}
|
||||
},
|
||||
destinationAccountName() {
|
||||
if (this.transaction.destinationAccountId) {
|
||||
return getNameByKeyValue(this.allAccounts, this.transaction.destinationAccountId, 'id', 'name');
|
||||
} else {
|
||||
return this.$t('None');
|
||||
}
|
||||
},
|
||||
transactionDisplayTime() {
|
||||
return this.$locale.formatUnixTimeToLongDateTime(this.userStore, getActualUnixTimeForStore(this.transaction.time, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()))
|
||||
},
|
||||
transactionDisplayTimezone() {
|
||||
return `UTC${getUtcOffsetByUtcOffsetMinutes(this.transaction.utcOffset)}`;
|
||||
},
|
||||
transactionDisplayTimezoneName() {
|
||||
return getNameByKeyValue(this.allTimezones, this.transaction.timeZone, 'name', 'displayName');
|
||||
},
|
||||
sourceAmountFontSize() {
|
||||
return this.getFontSizeByAmount(this.transaction.sourceAmount);
|
||||
},
|
||||
@@ -559,6 +623,12 @@ export default {
|
||||
return this.$t('No Location');
|
||||
}
|
||||
},
|
||||
allowedMinAmount() {
|
||||
return transactionConstants.minAmount;
|
||||
},
|
||||
allowedMaxAmount() {
|
||||
return transactionConstants.maxAmount;
|
||||
},
|
||||
inputIsEmpty() {
|
||||
return !!this.inputEmptyProblemMessage;
|
||||
},
|
||||
@@ -572,28 +642,28 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.transaction.type === this.$constants.transaction.allTransactionTypes.Expense || this.transaction.type === this.$constants.transaction.allTransactionTypes.Income) {
|
||||
if (this.transaction.type === this.allTransactionTypes.Expense || this.transaction.type === this.allTransactionTypes.Income) {
|
||||
this.transaction.destinationAmount = newValue;
|
||||
} else if (this.transaction.type === this.$constants.transaction.allTransactionTypes.Transfer) {
|
||||
} else if (this.transaction.type === this.allTransactionTypes.Transfer) {
|
||||
const sourceAccount = this.allAccountsMap[this.transaction.sourceAccountId]
|
||||
const destinationAccount = this.allAccountsMap[this.transaction.destinationAccountId]
|
||||
|
||||
if (sourceAccount && destinationAccount && sourceAccount.currency !== destinationAccount.currency) {
|
||||
const exchangedOldValue = this.$store.getters.getExchangedAmount(oldValue, sourceAccount.currency, destinationAccount.currency);
|
||||
const exchangedNewValue = this.$store.getters.getExchangedAmount(newValue, sourceAccount.currency, destinationAccount.currency);
|
||||
const exchangedOldValue = this.exchangeRatesStore.getExchangedAmount(oldValue, sourceAccount.currency, destinationAccount.currency);
|
||||
const exchangedNewValue = this.exchangeRatesStore.getExchangedAmount(newValue, sourceAccount.currency, destinationAccount.currency);
|
||||
|
||||
if (this.$utilities.isNumber(exchangedOldValue)) {
|
||||
if (isNumber(exchangedOldValue)) {
|
||||
oldValue = Math.floor(exchangedOldValue);
|
||||
}
|
||||
|
||||
if (this.$utilities.isNumber(exchangedNewValue)) {
|
||||
if (isNumber(exchangedNewValue)) {
|
||||
newValue = Math.floor(exchangedNewValue);
|
||||
}
|
||||
}
|
||||
|
||||
if ((!sourceAccount || !destinationAccount || this.transaction.destinationAmount === oldValue) &&
|
||||
(this.$utilities.stringCurrencyToNumeric(this.$constants.transaction.minAmount) <= newValue &&
|
||||
newValue <= this.$utilities.stringCurrencyToNumeric(this.$constants.transaction.maxAmount))) {
|
||||
(stringCurrencyToNumeric(this.allowedMinAmount) <= newValue &&
|
||||
newValue <= stringCurrencyToNumeric(this.allowedMaxAmount))) {
|
||||
this.transaction.destinationAmount = newValue;
|
||||
}
|
||||
}
|
||||
@@ -603,7 +673,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.transaction.type === this.$constants.transaction.allTransactionTypes.Expense || this.transaction.type === this.$constants.transaction.allTransactionTypes.Income) {
|
||||
if (this.transaction.type === this.allTransactionTypes.Expense || this.transaction.type === this.allTransactionTypes.Income) {
|
||||
this.transaction.sourceAmount = newValue;
|
||||
}
|
||||
},
|
||||
@@ -629,9 +699,9 @@ export default {
|
||||
self.loading = true;
|
||||
|
||||
const promises = [
|
||||
self.$store.dispatch('loadAllAccounts', { force: false }),
|
||||
self.$store.dispatch('loadAllCategories', { force: false }),
|
||||
self.$store.dispatch('loadAllTags', { force: false })
|
||||
self.accountsStore.loadAllAccounts({ force: false }),
|
||||
self.transactionCategoriesStore.loadAllCategories({ force: false }),
|
||||
self.transactionTagsStore.loadAllTags({ force: false })
|
||||
];
|
||||
|
||||
if (query.id) {
|
||||
@@ -639,12 +709,12 @@ export default {
|
||||
self.editTransactionId = query.id;
|
||||
}
|
||||
|
||||
promises.push(self.$store.dispatch('getTransaction', { transactionId: query.id }));
|
||||
promises.push(self.transactionsStore.getTransaction({ transactionId: query.id }));
|
||||
}
|
||||
|
||||
if (query.type && query.type !== '0' &&
|
||||
query.type >= self.$constants.transaction.allTransactionTypes.Income &&
|
||||
query.type <= self.$constants.transaction.allTransactionTypes.Transfer) {
|
||||
query.type >= self.allTransactionTypes.Income &&
|
||||
query.type <= self.allTransactionTypes.Transfer) {
|
||||
self.transaction.type = parseInt(query.type);
|
||||
}
|
||||
|
||||
@@ -657,43 +727,43 @@ export default {
|
||||
|
||||
if ((!query.type || query.type === '0') && query.categoryId && query.categoryId !== '0' && self.allCategoriesMap[query.categoryId]) {
|
||||
const category = self.allCategoriesMap[query.categoryId];
|
||||
const type = self.$utilities.categoryTypeToTransactionType(category.type);
|
||||
const type = categoryTypeToTransactionType(category.type);
|
||||
|
||||
if (self.$utilities.isNumber(type)) {
|
||||
if (isNumber(type)) {
|
||||
self.transaction.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
if (self.allCategories[self.$constants.category.allCategoryTypes.Expense] &&
|
||||
self.allCategories[self.$constants.category.allCategoryTypes.Expense].length) {
|
||||
if (query.categoryId && query.categoryId !== '0' && self.isCategoryIdAvailable(self.allCategories[self.$constants.category.allCategoryTypes.Expense], query.categoryId)) {
|
||||
if (self.allCategories[self.allCategoryTypes.Expense] &&
|
||||
self.allCategories[self.allCategoryTypes.Expense].length) {
|
||||
if (query.categoryId && query.categoryId !== '0' && self.isCategoryIdAvailable(self.allCategories[self.allCategoryTypes.Expense], query.categoryId)) {
|
||||
self.transaction.expenseCategory = query.categoryId;
|
||||
}
|
||||
|
||||
if (!self.transaction.expenseCategory) {
|
||||
self.transaction.expenseCategory = self.getFirstAvailableCategoryId(self.allCategories[self.$constants.category.allCategoryTypes.Expense]);
|
||||
self.transaction.expenseCategory = self.getFirstAvailableCategoryId(self.allCategories[self.allCategoryTypes.Expense]);
|
||||
}
|
||||
}
|
||||
|
||||
if (self.allCategories[self.$constants.category.allCategoryTypes.Income] &&
|
||||
self.allCategories[self.$constants.category.allCategoryTypes.Income].length) {
|
||||
if (query.categoryId && query.categoryId !== '0' && self.isCategoryIdAvailable(self.allCategories[self.$constants.category.allCategoryTypes.Income], query.categoryId)) {
|
||||
if (self.allCategories[self.allCategoryTypes.Income] &&
|
||||
self.allCategories[self.allCategoryTypes.Income].length) {
|
||||
if (query.categoryId && query.categoryId !== '0' && self.isCategoryIdAvailable(self.allCategories[self.allCategoryTypes.Income], query.categoryId)) {
|
||||
self.transaction.incomeCategory = query.categoryId;
|
||||
}
|
||||
|
||||
if (!self.transaction.incomeCategory) {
|
||||
self.transaction.incomeCategory = self.getFirstAvailableCategoryId(self.allCategories[self.$constants.category.allCategoryTypes.Income]);
|
||||
self.transaction.incomeCategory = self.getFirstAvailableCategoryId(self.allCategories[self.allCategoryTypes.Income]);
|
||||
}
|
||||
}
|
||||
|
||||
if (self.allCategories[self.$constants.category.allCategoryTypes.Transfer] &&
|
||||
self.allCategories[self.$constants.category.allCategoryTypes.Transfer].length) {
|
||||
if (query.categoryId && query.categoryId !== '0' && self.isCategoryIdAvailable(self.allCategories[self.$constants.category.allCategoryTypes.Transfer], query.categoryId)) {
|
||||
if (self.allCategories[self.allCategoryTypes.Transfer] &&
|
||||
self.allCategories[self.allCategoryTypes.Transfer].length) {
|
||||
if (query.categoryId && query.categoryId !== '0' && self.isCategoryIdAvailable(self.allCategories[self.allCategoryTypes.Transfer], query.categoryId)) {
|
||||
self.transaction.transferCategory = query.categoryId;
|
||||
}
|
||||
|
||||
if (!self.transaction.transferCategory) {
|
||||
self.transaction.transferCategory = self.getFirstAvailableCategoryId(self.allCategories[self.$constants.category.allCategoryTypes.Transfer]);
|
||||
self.transaction.transferCategory = self.getFirstAvailableCategoryId(self.allCategories[self.allCategoryTypes.Transfer]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -734,18 +804,18 @@ export default {
|
||||
|
||||
self.transaction.type = transaction.type;
|
||||
|
||||
if (self.transaction.type === self.$constants.transaction.allTransactionTypes.Expense) {
|
||||
if (self.transaction.type === self.allTransactionTypes.Expense) {
|
||||
self.transaction.expenseCategory = transaction.categoryId;
|
||||
} else if (self.transaction.type === self.$constants.transaction.allTransactionTypes.Income) {
|
||||
} else if (self.transaction.type === self.allTransactionTypes.Income) {
|
||||
self.transaction.incomeCategory = transaction.categoryId;
|
||||
} else if (self.transaction.type === self.$constants.transaction.allTransactionTypes.Transfer) {
|
||||
} else if (self.transaction.type === self.allTransactionTypes.Transfer) {
|
||||
self.transaction.transferCategory = transaction.categoryId;
|
||||
}
|
||||
|
||||
if (self.mode === 'edit' || self.mode === 'view') {
|
||||
self.transaction.utcOffset = transaction.utcOffset;
|
||||
self.transaction.timeZone = null;
|
||||
self.transaction.time = self.$utilities.getDummyUnixTimeForLocalUsage(transaction.time, self.transaction.utcOffset, self.$utilities.getBrowserTimezoneOffsetMinutes());
|
||||
self.transaction.time = getDummyUnixTimeForLocalUsage(transaction.time, self.transaction.utcOffset, getBrowserTimezoneOffsetMinutes());
|
||||
}
|
||||
|
||||
self.transaction.sourceAccountId = transaction.sourceAccountId;
|
||||
@@ -771,7 +841,7 @@ export default {
|
||||
|
||||
self.loading = false;
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to load essential data for editing transaction', error);
|
||||
logger.error('failed to load essential data for editing transaction', error);
|
||||
|
||||
if (error.processed) {
|
||||
self.loading = false;
|
||||
@@ -800,7 +870,7 @@ export default {
|
||||
|
||||
const submitTransaction = {
|
||||
type: self.transaction.type,
|
||||
time: self.$utilities.getActualUnixTimeForStore(self.transaction.time, self.transaction.utcOffset, self.$utilities.getBrowserTimezoneOffsetMinutes()),
|
||||
time: getActualUnixTimeForStore(self.transaction.time, self.transaction.utcOffset, getBrowserTimezoneOffsetMinutes()),
|
||||
sourceAccountId: self.transaction.sourceAccountId,
|
||||
sourceAmount: self.transaction.sourceAmount,
|
||||
destinationAccountId: '0',
|
||||
@@ -812,11 +882,11 @@ export default {
|
||||
utcOffset: self.transaction.utcOffset
|
||||
};
|
||||
|
||||
if (self.transaction.type === self.$constants.transaction.allTransactionTypes.Expense) {
|
||||
if (self.transaction.type === self.allTransactionTypes.Expense) {
|
||||
submitTransaction.categoryId = self.transaction.expenseCategory;
|
||||
} else if (self.transaction.type === self.$constants.transaction.allTransactionTypes.Income) {
|
||||
} else if (self.transaction.type === self.allTransactionTypes.Income) {
|
||||
submitTransaction.categoryId = self.transaction.incomeCategory;
|
||||
} else if (self.transaction.type === self.$constants.transaction.allTransactionTypes.Transfer) {
|
||||
} else if (self.transaction.type === self.allTransactionTypes.Transfer) {
|
||||
submitTransaction.categoryId = self.transaction.transferCategory;
|
||||
submitTransaction.destinationAccountId = self.transaction.destinationAccountId;
|
||||
submitTransaction.destinationAmount = self.transaction.destinationAmount;
|
||||
@@ -833,7 +903,7 @@ export default {
|
||||
self.submitting = true;
|
||||
self.$showLoading(() => self.submitting);
|
||||
|
||||
self.$store.dispatch('saveTransaction', {
|
||||
self.transactionsStore.saveTransaction({
|
||||
transaction: submitTransaction,
|
||||
defaultCurrency: self.defaultCurrency
|
||||
}).then(() => {
|
||||
@@ -869,7 +939,7 @@ export default {
|
||||
const self = this;
|
||||
|
||||
if (!self.isSupportGeoLocation) {
|
||||
self.$logger.warn('this browser does not support geo location');
|
||||
logger.warn('this browser does not support geo location');
|
||||
|
||||
if (forceUpdate) {
|
||||
self.$toast('Unable to get current position');
|
||||
@@ -879,7 +949,7 @@ export default {
|
||||
|
||||
navigator.geolocation.getCurrentPosition(function (position) {
|
||||
if (!position || !position.coords) {
|
||||
self.$logger.error('current position is null');
|
||||
logger.error('current position is null');
|
||||
self.geoLocationStatus = 'error';
|
||||
|
||||
if (forceUpdate) {
|
||||
@@ -896,7 +966,7 @@ export default {
|
||||
longitude: position.coords.longitude
|
||||
};
|
||||
}, function (err) {
|
||||
self.$logger.error('cannot get current position', err);
|
||||
logger.error('cannot get current position', err);
|
||||
self.geoLocationStatus = 'error';
|
||||
|
||||
if (forceUpdate) {
|
||||
@@ -953,10 +1023,13 @@ export default {
|
||||
return this.$locale.getDisplayCurrency(amount);
|
||||
},
|
||||
getPrimaryCategoryName(categoryId, allCategories) {
|
||||
return this.$utilities.getTransactionPrimaryCategoryName(categoryId, allCategories);
|
||||
return getTransactionPrimaryCategoryName(categoryId, allCategories);
|
||||
},
|
||||
getSecondaryCategoryName(categoryId, allCategories) {
|
||||
return this.$utilities.getTransactionSecondaryCategoryName(categoryId, allCategories);
|
||||
return getTransactionSecondaryCategoryName(categoryId, allCategories);
|
||||
},
|
||||
getTagName(tagId) {
|
||||
return getNameByKeyValue(this.allTags, tagId, 'id', 'name');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
<f7-list-item>
|
||||
<template #title>
|
||||
<small>
|
||||
<span>{{ $utilities.formatTime(transactionMonthList.yearMonth, $locale.getLongYearMonthFormat()) }}</span>
|
||||
<span>{{ getDisplayYearMonth(transactionMonthList) }}</span>
|
||||
</small>
|
||||
<small class="transaction-amount-statistics" v-if="showTotalAmountInTransactionListPage && transactionMonthList.totalAmount">
|
||||
<span class="text-color-red">
|
||||
@@ -144,7 +144,7 @@
|
||||
<f7-list-item swipeout chevron-center
|
||||
class="transaction-info"
|
||||
:id="getTransactionDomId(transaction)"
|
||||
:link="transaction.type !== $constants.transaction.allTransactionTypes.ModifyBalance ? `/transaction/detail?id=${transaction.id}&type=${transaction.type}` : null"
|
||||
:link="transaction.type !== allTransactionTypes.ModifyBalance ? `/transaction/detail?id=${transaction.id}&type=${transaction.type}` : null"
|
||||
:key="transaction.id"
|
||||
v-for="(transaction, idx) in transactionMonthList.items"
|
||||
>
|
||||
@@ -175,20 +175,20 @@
|
||||
<div class="item-title-row">
|
||||
<div class="item-title">
|
||||
<div class="transaction-category-name no-padding">
|
||||
<span v-if="transaction.type === $constants.transaction.allTransactionTypes.ModifyBalance">
|
||||
<span v-if="transaction.type === allTransactionTypes.ModifyBalance">
|
||||
{{ $t('Modify Balance') }}
|
||||
</span>
|
||||
<span v-else-if="transaction.type !== $constants.transaction.allTransactionTypes.ModifyBalance && transaction.category">
|
||||
<span v-else-if="transaction.type !== allTransactionTypes.ModifyBalance && transaction.category">
|
||||
{{ transaction.category.name }}
|
||||
</span>
|
||||
<span v-else-if="transaction.type !== $constants.transaction.allTransactionTypes.ModifyBalance && !transaction.category">
|
||||
<span v-else-if="transaction.type !== allTransactionTypes.ModifyBalance && !transaction.category">
|
||||
{{ getTransactionTypeName(transaction.type, 'Transaction') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-after">
|
||||
<div class="transaction-amount" v-if="transaction.sourceAccount"
|
||||
:class="{ 'text-color-teal': transaction.type === $constants.transaction.allTransactionTypes.Expense, 'text-color-red': transaction.type === $constants.transaction.allTransactionTypes.Income }">
|
||||
:class="{ 'text-color-teal': transaction.type === allTransactionTypes.Expense, 'text-color-red': transaction.type === allTransactionTypes.Income }">
|
||||
<span v-if="!query.accountId || query.accountId === '0' || (transaction.sourceAccount && (transaction.sourceAccount.id === query.accountId || transaction.sourceAccount.parentId === query.accountId))">{{ getDisplayAmount(transaction.sourceAmount, transaction.sourceAccount.currency, transaction.hideAmount) }}</span>
|
||||
<span v-else-if="query.accountId && query.accountId !== '0' && transaction.destinationAccount && (transaction.destinationAccount.id === query.accountId || transaction.destinationAccount.parentId === query.accountId)">{{ getDisplayAmount(transaction.destinationAmount, transaction.destinationAccount.currency, transaction.hideAmount) }}</span>
|
||||
<span v-else></span>
|
||||
@@ -202,12 +202,12 @@
|
||||
</div>
|
||||
<div class="item-footer">
|
||||
<div class="transaction-footer">
|
||||
<span>{{ $utilities.formatUnixTime(transaction.time, $locale.getShortTimeFormat(), transaction.utcOffset, currentTimezoneOffsetMinutes) }}</span>
|
||||
<span v-if="transaction.utcOffset !== currentTimezoneOffsetMinutes">{{ `(UTC${$utilities.getUtcOffsetByUtcOffsetMinutes(transaction.utcOffset)})` }}</span>
|
||||
<span>{{ getDisplayTime(transaction) }}</span>
|
||||
<span v-if="transaction.utcOffset !== currentTimezoneOffsetMinutes">{{ `(${getDisplayTimezone(transaction)})` }}</span>
|
||||
<span v-if="transaction.sourceAccount">·</span>
|
||||
<span v-if="transaction.sourceAccount">{{ transaction.sourceAccount.name }}</span>
|
||||
<span v-if="transaction.sourceAccount && transaction.type === $constants.transaction.allTransactionTypes.Transfer && transaction.destinationAccount && transaction.sourceAccount.id !== transaction.destinationAccount.id">→</span>
|
||||
<span v-if="transaction.sourceAccount && transaction.type === $constants.transaction.allTransactionTypes.Transfer && transaction.destinationAccount && transaction.sourceAccount.id !== transaction.destinationAccount.id">{{ transaction.destinationAccount.name }}</span>
|
||||
<span v-if="transaction.sourceAccount && transaction.type === allTransactionTypes.Transfer && transaction.destinationAccount && transaction.sourceAccount.id !== transaction.destinationAccount.id">→</span>
|
||||
<span v-if="transaction.sourceAccount && transaction.type === allTransactionTypes.Transfer && transaction.destinationAccount && transaction.sourceAccount.id !== transaction.destinationAccount.id">{{ transaction.destinationAccount.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -216,11 +216,11 @@
|
||||
<f7-swipeout-actions right>
|
||||
<f7-swipeout-button color="primary" close
|
||||
:text="$t('Duplicate')"
|
||||
v-if="transaction.type !== $constants.transaction.allTransactionTypes.ModifyBalance"
|
||||
v-if="transaction.type !== allTransactionTypes.ModifyBalance"
|
||||
@click="duplicate(transaction)"></f7-swipeout-button>
|
||||
<f7-swipeout-button color="orange" close
|
||||
:text="$t('Edit')"
|
||||
v-if="transaction.editable && transaction.type !== $constants.transaction.allTransactionTypes.ModifyBalance"
|
||||
v-if="transaction.editable && transaction.type !== allTransactionTypes.ModifyBalance"
|
||||
@click="edit(transaction)"></f7-swipeout-button>
|
||||
<f7-swipeout-button color="red" class="padding-left padding-right"
|
||||
v-if="transaction.editable"
|
||||
@@ -251,11 +251,11 @@
|
||||
<f7-icon class="list-item-checked-icon" f7="checkmark_alt" v-if="query.dateType === dateRange.type"></f7-icon>
|
||||
</template>
|
||||
<template #footer>
|
||||
<div v-if="dateRange.type === $constants.datetime.allDateRanges.Custom.type && query.dateType === $constants.datetime.allDateRanges.Custom.type && query.minTime && query.maxTime">
|
||||
<span>{{ $utilities.formatUnixTime(query.minTime, $locale.getLongDateTimeFormat()) }}</span>
|
||||
<div v-if="dateRange.type === allDateRanges.Custom.type && query.dateType === allDateRanges.Custom.type && query.minTime && query.maxTime">
|
||||
<span>{{ queryMinTime }}</span>
|
||||
<span> - </span>
|
||||
<br/>
|
||||
<span>{{ $utilities.formatUnixTime(query.maxTime, $locale.getLongDateTimeFormat()) }}</span>
|
||||
<span>{{ queryMaxTime }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</f7-list-item>
|
||||
@@ -318,9 +318,9 @@
|
||||
class="no-margin-vertical"
|
||||
:key="categoryType"
|
||||
v-for="(categories, categoryType) in allPrimaryCategories"
|
||||
v-show="!query.type || $utilities.categoryTypeToTransactionType(parseInt(categoryType)) === query.type"
|
||||
v-show="!query.type || getTransactionTypeFromCategoryType(categoryType) === query.type"
|
||||
>
|
||||
<f7-list-item divider :title="getTransactionTypeName($utilities.categoryTypeToTransactionType(parseInt(categoryType)), 'Type')"></f7-list-item>
|
||||
<f7-list-item divider :title="getTransactionTypeName(getTransactionTypeFromCategoryType(categoryType), 'Type')"></f7-list-item>
|
||||
<f7-list-item accordion-item
|
||||
:title="category.name"
|
||||
:class="getCategoryListItemCheckedClass(category, query.categoryId)"
|
||||
@@ -407,6 +407,25 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useAccountsStore } from '@/stores/account.js';
|
||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||
import { useTransactionsStore } from '@/stores/transaction.js';
|
||||
|
||||
import datetimeConstants from '@/consts/datetime.js';
|
||||
import currencyConstants from '@/consts/currency.js';
|
||||
import accountConstants from '@/consts/account.js';
|
||||
import transactionConstants from '@/consts/transaction.js';
|
||||
import { getNameByKeyValue } from '@/lib/common.js';
|
||||
import {
|
||||
getUtcOffsetByUtcOffsetMinutes,
|
||||
getTimezoneOffsetMinutes,
|
||||
getDateRangeByDateType
|
||||
} from '@/lib/datetime.js';
|
||||
import { categoryTypeToTransactionType, transactionTypeToCategoryType } from '@/lib/category.js';
|
||||
import { onSwipeoutDeleted } from '@/lib/ui.mobile.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7route',
|
||||
@@ -430,22 +449,23 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useUserStore, useAccountsStore, useTransactionCategoriesStore, useTransactionsStore),
|
||||
defaultCurrency() {
|
||||
if (this.query.accountId && this.query.accountId !== '0') {
|
||||
const account = this.allAccounts[this.query.accountId];
|
||||
|
||||
if (account && account.currency && account.currency !== this.$constants.currency.parentAccountCurrencyPlaceholder) {
|
||||
if (account && account.currency && account.currency !== currencyConstants.parentAccountCurrencyPlaceholder) {
|
||||
return account.currency;
|
||||
}
|
||||
}
|
||||
|
||||
return this.$store.getters.currentUserDefaultCurrency;
|
||||
return this.userStore.currentUserDefaultCurrency;
|
||||
},
|
||||
canAddTransaction() {
|
||||
if (this.query.accountId && this.query.accountId !== '0') {
|
||||
const account = this.allAccounts[this.query.accountId];
|
||||
|
||||
if (account && account.type === this.$constants.account.allAccountTypes.MultiSubAccounts) {
|
||||
if (account && account.type === accountConstants.allAccountTypes.MultiSubAccounts) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -453,38 +473,13 @@ export default {
|
||||
return true;
|
||||
},
|
||||
currentTimezoneOffsetMinutes() {
|
||||
return this.$utilities.getTimezoneOffsetMinutes();
|
||||
return getTimezoneOffsetMinutes();
|
||||
},
|
||||
firstDayOfWeek() {
|
||||
return this.$store.getters.currentUserFirstDayOfWeek;
|
||||
return this.userStore.currentUserFirstDayOfWeek;
|
||||
},
|
||||
query() {
|
||||
return this.$store.state.transactionsFilter;
|
||||
},
|
||||
transactions() {
|
||||
if (this.loading) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.$store.state.transactions;
|
||||
},
|
||||
noTransaction() {
|
||||
return this.$store.getters.noTransaction;
|
||||
},
|
||||
hasMoreTransaction() {
|
||||
return this.$store.getters.hasMoreTransaction;
|
||||
},
|
||||
allAccounts() {
|
||||
return this.$store.state.allAccountsMap;
|
||||
},
|
||||
allCategories() {
|
||||
return this.$store.state.allTransactionCategoriesMap;
|
||||
},
|
||||
allPrimaryCategories() {
|
||||
return this.$store.state.allTransactionCategories;
|
||||
},
|
||||
allDateRanges() {
|
||||
return this.$constants.datetime.allDateRanges;
|
||||
return this.transactionsStore.transactionsFilter;
|
||||
},
|
||||
queryDateRangeName() {
|
||||
if (this.query.dateType === this.allDateRanges.All.type) {
|
||||
@@ -505,24 +500,58 @@ export default {
|
||||
|
||||
return this.$t('Date');
|
||||
},
|
||||
queryMinTime() {
|
||||
return this.$locale.formatUnixTimeToLongDateTime(this.userStore, this.query.minTime);
|
||||
},
|
||||
queryMaxTime() {
|
||||
return this.$locale.formatUnixTimeToLongDateTime(this.userStore, this.query.maxTime);
|
||||
},
|
||||
queryTransactionTypeName() {
|
||||
return this.getTransactionTypeName(this.query.type, 'Type');
|
||||
},
|
||||
queryCategoryName() {
|
||||
return this.$utilities.getNameByKeyValue(this.allCategories, this.query.categoryId, null, 'name', this.$t('Category'));
|
||||
return getNameByKeyValue(this.allCategories, this.query.categoryId, null, 'name', this.$t('Category'));
|
||||
},
|
||||
queryAccountName() {
|
||||
return this.$utilities.getNameByKeyValue(this.allAccounts, this.query.accountId, null, 'name', this.$t('Account'));
|
||||
return getNameByKeyValue(this.allAccounts, this.query.accountId, null, 'name', this.$t('Account'));
|
||||
},
|
||||
transactions() {
|
||||
if (this.loading) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.transactionsStore.transactions;
|
||||
},
|
||||
noTransaction() {
|
||||
return this.transactionsStore.noTransaction;
|
||||
},
|
||||
hasMoreTransaction() {
|
||||
return this.transactionsStore.hasMoreTransaction;
|
||||
},
|
||||
allTransactionTypes() {
|
||||
return transactionConstants.allTransactionTypes;
|
||||
},
|
||||
allAccounts() {
|
||||
return this.accountsStore.allAccountsMap;
|
||||
},
|
||||
allCategories() {
|
||||
return this.transactionCategoriesStore.allTransactionCategoriesMap;
|
||||
},
|
||||
allPrimaryCategories() {
|
||||
return this.transactionCategoriesStore.allTransactionCategories;
|
||||
},
|
||||
allDateRanges() {
|
||||
return datetimeConstants.allDateRanges;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const self = this;
|
||||
const query = self.f7route.query;
|
||||
|
||||
let dateRange = self.$utilities.getDateRangeByDateType(query.dateType ? parseInt(query.dateType) : undefined, self.firstDayOfWeek);
|
||||
let dateRange = getDateRangeByDateType(query.dateType ? parseInt(query.dateType) : undefined, self.firstDayOfWeek);
|
||||
|
||||
if (!dateRange &&
|
||||
query.dateType === self.$constants.datetime.allDateRanges.Custom.type.toString() &&
|
||||
query.dateType === self.allDateRanges.Custom.type.toString() &&
|
||||
parseInt(query.maxTime) > 0 && parseInt(query.minTime) > 0) {
|
||||
dateRange = {
|
||||
dateType: parseInt(query.dateType),
|
||||
@@ -531,7 +560,7 @@ export default {
|
||||
};
|
||||
}
|
||||
|
||||
this.$store.dispatch('initTransactionListFilter', {
|
||||
this.transactionsStore.initTransactionListFilter({
|
||||
dateType: dateRange ? dateRange.dateType : undefined,
|
||||
maxTime: dateRange ? dateRange.maxTime : undefined,
|
||||
minTime: dateRange ? dateRange.minTime : undefined,
|
||||
@@ -544,7 +573,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
onPageAfterIn() {
|
||||
if (this.$store.state.transactionListStateInvalid && !this.loading) {
|
||||
if (this.transactionsStore.transactionListStateInvalid && !this.loading) {
|
||||
this.reload(null);
|
||||
}
|
||||
|
||||
@@ -558,10 +587,10 @@ export default {
|
||||
}
|
||||
|
||||
Promise.all([
|
||||
self.$store.dispatch('loadAllAccounts', { force: false }),
|
||||
self.$store.dispatch('loadAllCategories', { force: false })
|
||||
self.accountsStore.loadAllAccounts({ force: false }),
|
||||
self.transactionCategoriesStore.loadAllCategories({ force: false })
|
||||
]).then(() => {
|
||||
return self.$store.dispatch('loadTransactions', {
|
||||
return self.transactionsStore.loadTransactions({
|
||||
reload: true,
|
||||
autoExpand: true,
|
||||
defaultCurrency: self.defaultCurrency
|
||||
@@ -603,7 +632,7 @@ export default {
|
||||
|
||||
self.loadingMore = true;
|
||||
|
||||
self.$store.dispatch('loadTransactions', {
|
||||
self.transactionsStore.loadTransactions({
|
||||
reload: false,
|
||||
autoExpand: autoExpand,
|
||||
defaultCurrency: self.defaultCurrency
|
||||
@@ -618,13 +647,13 @@ export default {
|
||||
});
|
||||
},
|
||||
collapseTransactionMonthList(month, collapse) {
|
||||
this.$store.dispatch('collapseMonthInTransactionList', {
|
||||
this.transactionsStore.collapseMonthInTransactionList({
|
||||
month: month,
|
||||
collapse: collapse
|
||||
});
|
||||
},
|
||||
changeDateFilter(dateType) {
|
||||
if (dateType === this.$constants.datetime.allDateRanges.Custom.type) { // Custom
|
||||
if (dateType === this.allDateRanges.Custom.type) { // Custom
|
||||
this.showCustomDateRangeSheet = true;
|
||||
this.showDatePopover = false;
|
||||
return;
|
||||
@@ -632,13 +661,13 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
const dateRange = this.$utilities.getDateRangeByDateType(dateType, this.firstDayOfWeek);
|
||||
const dateRange = getDateRangeByDateType(dateType, this.firstDayOfWeek);
|
||||
|
||||
if (!dateRange) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$store.dispatch('updateTransactionListFilter', {
|
||||
this.transactionsStore.updateTransactionListFilter({
|
||||
dateType: dateRange.dateType,
|
||||
maxTime: dateRange.maxTime,
|
||||
minTime: dateRange.minTime
|
||||
@@ -652,8 +681,8 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$store.dispatch('updateTransactionListFilter', {
|
||||
dateType: this.$constants.datetime.allDateRanges.Custom.type,
|
||||
this.transactionsStore.updateTransactionListFilter({
|
||||
dateType: this.allDateRanges.Custom.type,
|
||||
maxTime: maxTime,
|
||||
minTime: minTime
|
||||
});
|
||||
@@ -672,12 +701,12 @@ export default {
|
||||
if (type && this.query.categoryId) {
|
||||
const category = this.allCategories[this.query.categoryId];
|
||||
|
||||
if (category && category.type !== this.$utilities.transactionTypeToCategoryType(type)) {
|
||||
if (category && category.type !== transactionTypeToCategoryType(type)) {
|
||||
removeCategoryFilter = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.$store.dispatch('updateTransactionListFilter', {
|
||||
this.transactionsStore.updateTransactionListFilter({
|
||||
type: type,
|
||||
categoryId: removeCategoryFilter ? '0' : undefined
|
||||
});
|
||||
@@ -690,7 +719,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$store.dispatch('updateTransactionListFilter', {
|
||||
this.transactionsStore.updateTransactionListFilter({
|
||||
categoryId: categoryId
|
||||
});
|
||||
|
||||
@@ -702,7 +731,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$store.dispatch('updateTransactionListFilter', {
|
||||
this.transactionsStore.updateTransactionListFilter({
|
||||
accountId: accountId
|
||||
});
|
||||
|
||||
@@ -714,7 +743,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$store.dispatch('updateTransactionListFilter', {
|
||||
this.transactionsStore.updateTransactionListFilter({
|
||||
keyword: keyword
|
||||
});
|
||||
|
||||
@@ -744,11 +773,11 @@ export default {
|
||||
self.transactionToDelete = null;
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('deleteTransaction', {
|
||||
self.transactionsStore.deleteTransaction({
|
||||
transaction: transaction,
|
||||
defaultCurrency: self.defaultCurrency,
|
||||
beforeResolve: (done) => {
|
||||
self.$ui.onSwipeoutDeleted(self.getTransactionDomId(transaction), done);
|
||||
onSwipeoutDeleted(self.getTransactionDomId(transaction), done);
|
||||
}
|
||||
}).then(() => {
|
||||
self.$hideLoading();
|
||||
@@ -781,6 +810,15 @@ export default {
|
||||
|
||||
container.scrollTop(targetPos);
|
||||
},
|
||||
getDisplayYearMonth(transactionMonthList) {
|
||||
return this.$locale.formatTimeToLongYearMonth(this.userStore, transactionMonthList.yearMonth);
|
||||
},
|
||||
getDisplayTime(transaction) {
|
||||
return this.$locale.formatUnixTimeToShortTime(this.userStore, transaction.time, transaction.utcOffset, this.currentTimezoneOffsetMinutes);
|
||||
},
|
||||
getDisplayTimezone(transaction) {
|
||||
return `UTC${getUtcOffsetByUtcOffsetMinutes(transaction.utcOffset)}`;
|
||||
},
|
||||
getDisplayAmount(amount, currency, hideAmount) {
|
||||
if (hideAmount) {
|
||||
return this.$locale.getDisplayCurrency('***', currency);
|
||||
@@ -794,18 +832,21 @@ export default {
|
||||
},
|
||||
getTransactionTypeName(type, defaultName) {
|
||||
switch (type){
|
||||
case this.$constants.transaction.allTransactionTypes.ModifyBalance:
|
||||
case this.allTransactionTypes.ModifyBalance:
|
||||
return this.$t('Modify Balance');
|
||||
case this.$constants.transaction.allTransactionTypes.Income:
|
||||
case this.allTransactionTypes.Income:
|
||||
return this.$t('Income');
|
||||
case this.$constants.transaction.allTransactionTypes.Expense:
|
||||
case this.allTransactionTypes.Expense:
|
||||
return this.$t('Expense');
|
||||
case this.$constants.transaction.allTransactionTypes.Transfer:
|
||||
case this.allTransactionTypes.Transfer:
|
||||
return this.$t('Transfer');
|
||||
default:
|
||||
return this.$t(defaultName);
|
||||
}
|
||||
},
|
||||
getTransactionTypeFromCategoryType(categoryType) {
|
||||
return categoryTypeToTransactionType(parseInt(categoryType));
|
||||
},
|
||||
getTransactionDomId(transaction) {
|
||||
return 'transaction_' + transaction.id;
|
||||
},
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
</f7-list>
|
||||
|
||||
<f7-list strong inset dividers class="margin-vertical" v-else-if="!loading">
|
||||
<f7-list-item :title="$t('Accounts')" :after="$utilities.appendThousandsSeparator(dataStatistics.totalAccountCount)"></f7-list-item>
|
||||
<f7-list-item :title="$t('Transaction Categories')" :after="$utilities.appendThousandsSeparator(dataStatistics.totalTransactionCategoryCount)"></f7-list-item>
|
||||
<f7-list-item :title="$t('Transaction Tags')" :after="$utilities.appendThousandsSeparator(dataStatistics.totalTransactionTagCount)"></f7-list-item>
|
||||
<f7-list-item :title="$t('Transactions')" :after="$utilities.appendThousandsSeparator(dataStatistics.totalTransactionCount)"></f7-list-item>
|
||||
<f7-list-item :title="$t('Accounts')" :after="displayDataStatistics.totalAccountCount"></f7-list-item>
|
||||
<f7-list-item :title="$t('Transaction Categories')" :after="displayDataStatistics.totalTransactionCategoryCount"></f7-list-item>
|
||||
<f7-list-item :title="$t('Transaction Tags')" :after="displayDataStatistics.totalTransactionTagCount"></f7-list-item>
|
||||
<f7-list-item :title="$t('Transactions')" :after="displayDataStatistics.totalTransactionCount"></f7-list-item>
|
||||
</f7-list>
|
||||
|
||||
<f7-list strong inset dividers class="margin-vertical" :class="{ 'disabled': loading }">
|
||||
@@ -56,6 +56,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useRootStore } from '@/stores/index.js';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
|
||||
import { appendThousandsSeparator } from '@/lib/common.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7router'
|
||||
@@ -74,11 +80,26 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useRootStore, useUserStore),
|
||||
displayDataStatistics() {
|
||||
const self = this;
|
||||
|
||||
if (!self.dataStatistics) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
totalAccountCount: appendThousandsSeparator(self.dataStatistics.totalAccountCount),
|
||||
totalTransactionCategoryCount: appendThousandsSeparator(self.dataStatistics.totalTransactionCategoryCount),
|
||||
totalTransactionTagCount: appendThousandsSeparator(self.dataStatistics.totalTransactionTagCount),
|
||||
totalTransactionCount: appendThousandsSeparator(self.dataStatistics.totalTransactionCount)
|
||||
};
|
||||
},
|
||||
isDataExportingEnabled() {
|
||||
return this.$settings.isDataExportingEnabled();
|
||||
},
|
||||
exportFileName() {
|
||||
const nickname = this.$store.getters.currentUserNickname;
|
||||
const nickname = this.userStore.currentUserNickname;
|
||||
|
||||
if (nickname) {
|
||||
return this.$t('dataExport.exportFilename', {
|
||||
@@ -94,7 +115,7 @@ export default {
|
||||
|
||||
self.loading = true;
|
||||
|
||||
self.$store.dispatch('getUserDataStatistics').then(dataStatistics => {
|
||||
self.userStore.getUserDataStatistics().then(dataStatistics => {
|
||||
self.dataStatistics = dataStatistics;
|
||||
self.loading = false;
|
||||
}).catch(error => {
|
||||
@@ -116,7 +137,7 @@ export default {
|
||||
self.$showLoading();
|
||||
self.exportingData = true;
|
||||
|
||||
self.$store.dispatch('getExportedUserData').then(data => {
|
||||
self.userStore.getExportedUserData().then(data => {
|
||||
self.exportedData = URL.createObjectURL(data);
|
||||
self.exportingData = false;
|
||||
self.$hideLoading();
|
||||
@@ -142,7 +163,7 @@ export default {
|
||||
self.clearingData = true;
|
||||
self.$showLoading(() => self.clearingData);
|
||||
|
||||
self.$store.dispatch('clearUserData', {
|
||||
self.rootStore.clearUserData({
|
||||
password: password
|
||||
}).then(() => {
|
||||
self.clearingData = false;
|
||||
@@ -153,7 +174,7 @@ export default {
|
||||
|
||||
self.loading = true;
|
||||
|
||||
self.$store.dispatch('getUserDataStatistics').then(dataStatistics => {
|
||||
self.userStore.getUserDataStatistics().then(dataStatistics => {
|
||||
self.dataStatistics = dataStatistics;
|
||||
self.loading = false;
|
||||
}).catch(error => {
|
||||
|
||||
@@ -43,6 +43,15 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useTokensStore } from '@/stores/token.js';
|
||||
|
||||
import iconConstants from '@/consts/icon.js';
|
||||
import { parseDeviceInfo, parseUserAgent } from '@/lib/misc.js';
|
||||
|
||||
import { onSwipeoutDeleted } from '@/lib/ui.mobile.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7router'
|
||||
@@ -55,6 +64,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useUserStore, useTokensStore),
|
||||
sessions() {
|
||||
if (!this.tokens) {
|
||||
return this.tokens;
|
||||
@@ -70,9 +80,9 @@ export default {
|
||||
domId: this.getTokenDomId(token.tokenId),
|
||||
isCurrent: token.isCurrent,
|
||||
deviceType: this.$t(token.isCurrent ? 'Current' : 'Other Device'),
|
||||
deviceInfo: this.$utilities.parseDeviceInfo(token.userAgent),
|
||||
deviceInfo: parseDeviceInfo(token.userAgent),
|
||||
icon: this.getTokenIcon(token),
|
||||
createdAt: this.$utilities.formatUnixTime(token.createdAt, this.$locale.getLongDateTimeFormat())
|
||||
createdAt: this.$locale.formatUnixTimeToLongDateTime(this.userStore, token.createdAt)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -84,7 +94,7 @@ export default {
|
||||
|
||||
self.loading = true;
|
||||
|
||||
self.$store.dispatch('getAllTokens').then(tokens => {
|
||||
self.tokensStore.getAllTokens().then(tokens => {
|
||||
self.tokens = tokens;
|
||||
self.loading = false;
|
||||
}).catch(error => {
|
||||
@@ -103,7 +113,7 @@ export default {
|
||||
reload(done) {
|
||||
const self = this;
|
||||
|
||||
self.$store.dispatch('getAllTokens').then(tokens => {
|
||||
self.tokensStore.getAllTokens().then(tokens => {
|
||||
if (done) {
|
||||
done();
|
||||
}
|
||||
@@ -125,12 +135,12 @@ export default {
|
||||
self.$confirm('Are you sure you want to logout from this session?', () => {
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('revokeToken', {
|
||||
self.tokensStore.revokeToken({
|
||||
tokenId: session.tokenId
|
||||
}).then(() => {
|
||||
self.$hideLoading();
|
||||
|
||||
self.$ui.onSwipeoutDeleted(self.getTokenDomId(session.tokenId), () => {
|
||||
onSwipeoutDeleted(self.getTokenDomId(session.tokenId), () => {
|
||||
for (let i = 0; i < self.tokens.length; i++) {
|
||||
if (self.tokens[i].tokenId === session.tokenId) {
|
||||
self.tokens.splice(i, 1);
|
||||
@@ -156,7 +166,7 @@ export default {
|
||||
self.$confirm('Are you sure you want to logout all other sessions?', () => {
|
||||
self.$showLoading();
|
||||
|
||||
self.$store.dispatch('revokeAllTokens').then(() => {
|
||||
self.tokensStore.revokeAllTokens().then(() => {
|
||||
self.$hideLoading();
|
||||
|
||||
for (let i = self.tokens.length - 1; i >= 0; i--) {
|
||||
@@ -176,22 +186,22 @@ export default {
|
||||
});
|
||||
},
|
||||
getTokenIcon(token) {
|
||||
const ua = this.$utilities.parseUserAgent(token.userAgent);
|
||||
const ua = parseUserAgent(token.userAgent);
|
||||
|
||||
if (!ua || !ua.device) {
|
||||
return this.$constants.icons.deviceIcons.desktop.f7Icon;
|
||||
return iconConstants.deviceIcons.desktop.f7Icon;
|
||||
}
|
||||
|
||||
if (ua.device.type === 'mobile') {
|
||||
return this.$constants.icons.deviceIcons.mobile.f7Icon;
|
||||
return iconConstants.deviceIcons.mobile.f7Icon;
|
||||
} else if (ua.device.type === 'wearable') {
|
||||
return this.$constants.icons.deviceIcons.wearable.f7Icon;
|
||||
return iconConstants.deviceIcons.wearable.f7Icon;
|
||||
} else if (ua.device.type === 'tablet') {
|
||||
return this.$constants.icons.deviceIcons.tablet.f7Icon;
|
||||
return iconConstants.deviceIcons.tablet.f7Icon;
|
||||
} else if (ua.device.type === 'smarttv') {
|
||||
return this.$constants.icons.deviceIcons.tv.f7Icon;
|
||||
return iconConstants.deviceIcons.tv.f7Icon;
|
||||
} else {
|
||||
return this.$constants.icons.deviceIcons.desktop.f7Icon;
|
||||
return iconConstants.deviceIcons.desktop.f7Icon;
|
||||
}
|
||||
},
|
||||
getTokenDomId(tokenId) {
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useTwoFactorAuthStore } from '@/stores/twoFactorAuth.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7router'
|
||||
@@ -82,12 +85,15 @@ export default {
|
||||
showBackupCodeSheet: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useTwoFactorAuthStore),
|
||||
},
|
||||
created() {
|
||||
const self = this;
|
||||
|
||||
self.loading = true;
|
||||
|
||||
self.$store.dispatch('get2FAStatus').then(response => {
|
||||
self.twoFactorAuthStore.get2FAStatus().then(response => {
|
||||
self.status = response.enable;
|
||||
self.loading = false;
|
||||
}).catch(error => {
|
||||
@@ -112,7 +118,7 @@ export default {
|
||||
self.enabling = true;
|
||||
self.$showLoading(() => self.enabling);
|
||||
|
||||
self.$store.dispatch('enable2FA').then(response => {
|
||||
self.twoFactorAuthStore.enable2FA().then(response => {
|
||||
self.enabling = false;
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -135,7 +141,7 @@ export default {
|
||||
self.enableConfirming = true;
|
||||
self.$showLoading(() => self.enableConfirming);
|
||||
|
||||
self.$store.dispatch('confirmEnable2FA', {
|
||||
self.twoFactorAuthStore.confirmEnable2FA({
|
||||
secret: self.new2FASecret,
|
||||
passcode: self.currentPasscodeForEnable
|
||||
}).then(response => {
|
||||
@@ -173,7 +179,7 @@ export default {
|
||||
self.disabling = true;
|
||||
self.$showLoading(() => self.disabling);
|
||||
|
||||
self.$store.dispatch('disable2FA', {
|
||||
self.twoFactorAuthStore.disable2FA({
|
||||
password: password
|
||||
}).then(() => {
|
||||
self.disabling = false;
|
||||
@@ -203,7 +209,7 @@ export default {
|
||||
self.regenerating = true;
|
||||
self.$showLoading(() => self.regenerating);
|
||||
|
||||
self.$store.dispatch('regenerate2FARecoveryCode', {
|
||||
self.twoFactorAuthStore.regenerate2FARecoveryCode({
|
||||
password: password
|
||||
}).then(response => {
|
||||
self.regenerating = false;
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
link="#" no-chevron
|
||||
:class="{ 'disabled': !allVisibleAccounts.length }"
|
||||
:header="$t('Default Account')"
|
||||
:title="$utilities.getNameByKeyValue(allAccounts, newProfile.defaultAccountId, 'id', 'name', $t('Not Specified'))"
|
||||
:title="getNameByKeyValue(allAccounts, newProfile.defaultAccountId, 'id', 'name', $t('Not Specified'))"
|
||||
@click="showAccountSheet = true"
|
||||
>
|
||||
<two-column-list-item-selection-sheet primary-key-field="id" primary-value-field="category"
|
||||
@@ -96,7 +96,7 @@
|
||||
<f7-list-item
|
||||
class="list-item-with-header-and-title list-item-no-item-after"
|
||||
:header="$t('Editable Transaction Scope')"
|
||||
:title="$t($utilities.getNameByKeyValue(allTransactionEditScopeTypes, newProfile.transactionEditScope, 'value', 'name'))"
|
||||
:title="$t(getNameByKeyValue(allTransactionEditScopeTypes, newProfile.transactionEditScope, 'value', 'name'))"
|
||||
smart-select :smart-select-params="{ openIn: 'popup', popupPush: true, closeOnSelect: true, scrollToSelectedItem: true, searchbar: true, searchbarPlaceholder: $t('Date Range'), searchbarDisableText: $t('Cancel'), appendSearchbarNotFound: $t('No results'), pageTitle: $t('Editable Transaction Scope'), popupCloseLinkText: $t('Done') }"
|
||||
>
|
||||
<select v-model="newProfile.transactionEditScope">
|
||||
@@ -156,7 +156,7 @@
|
||||
<f7-list-item
|
||||
class="list-item-with-header-and-title list-item-no-item-after"
|
||||
:header="$t('Long Date Format')"
|
||||
:title="$utilities.getNameByKeyValue(allLongDateFormats, newProfile.longDateFormat, 'type', 'displayName')"
|
||||
:title="getNameByKeyValue(allLongDateFormats, newProfile.longDateFormat, 'type', 'displayName')"
|
||||
smart-select :smart-select-params="{ openIn: 'popup', popupPush: true, closeOnSelect: true, scrollToSelectedItem: true, searchbar: true, searchbarPlaceholder: $t('Long Date Format'), searchbarDisableText: $t('Cancel'), appendSearchbarNotFound: $t('No results'), pageTitle: $t('Long Date Format'), popupCloseLinkText: $t('Done') }"
|
||||
>
|
||||
<select v-model="newProfile.longDateFormat">
|
||||
@@ -169,7 +169,7 @@
|
||||
<f7-list-item
|
||||
class="list-item-with-header-and-title list-item-no-item-after"
|
||||
:header="$t('Short Date Format')"
|
||||
:title="$utilities.getNameByKeyValue(allShortDateFormats, newProfile.shortDateFormat, 'type', 'displayName')"
|
||||
:title="getNameByKeyValue(allShortDateFormats, newProfile.shortDateFormat, 'type', 'displayName')"
|
||||
smart-select :smart-select-params="{ openIn: 'popup', popupPush: true, closeOnSelect: true, scrollToSelectedItem: true, searchbar: true, searchbarPlaceholder: $t('Short Date Format'), searchbarDisableText: $t('Cancel'), appendSearchbarNotFound: $t('No results'), pageTitle: $t('Short Date Format'), popupCloseLinkText: $t('Done') }"
|
||||
>
|
||||
<select v-model="newProfile.shortDateFormat">
|
||||
@@ -182,7 +182,7 @@
|
||||
<f7-list-item
|
||||
class="list-item-with-header-and-title list-item-no-item-after"
|
||||
:header="$t('Long Time Format')"
|
||||
:title="$utilities.getNameByKeyValue(allLongTimeFormats, newProfile.longTimeFormat, 'type', 'displayName')"
|
||||
:title="getNameByKeyValue(allLongTimeFormats, newProfile.longTimeFormat, 'type', 'displayName')"
|
||||
smart-select :smart-select-params="{ openIn: 'popup', popupPush: true, closeOnSelect: true, scrollToSelectedItem: true, searchbar: true, searchbarPlaceholder: $t('Long Time Format'), searchbarDisableText: $t('Cancel'), appendSearchbarNotFound: $t('No results'), pageTitle: $t('Long Time Format'), popupCloseLinkText: $t('Done') }"
|
||||
>
|
||||
<select v-model="newProfile.longTimeFormat">
|
||||
@@ -195,7 +195,7 @@
|
||||
<f7-list-item
|
||||
class="list-item-with-header-and-title list-item-no-item-after"
|
||||
:header="$t('Short Time Format')"
|
||||
:title="$utilities.getNameByKeyValue(allShortTimeFormats, newProfile.shortTimeFormat, 'type', 'displayName')"
|
||||
:title="getNameByKeyValue(allShortTimeFormats, newProfile.shortTimeFormat, 'type', 'displayName')"
|
||||
smart-select :smart-select-params="{ openIn: 'popup', popupPush: true, closeOnSelect: true, scrollToSelectedItem: true, searchbar: true, searchbarPlaceholder: $t('Long Time Format'), searchbarDisableText: $t('Cancel'), appendSearchbarNotFound: $t('No results'), pageTitle: $t('Short Time Format'), popupCloseLinkText: $t('Done') }"
|
||||
>
|
||||
<select v-model="newProfile.shortTimeFormat">
|
||||
@@ -220,6 +220,15 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useRootStore } from '@/stores/index.js';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useAccountsStore } from '@/stores/account.js';
|
||||
|
||||
import datetimeConstants from '@/consts/datetime.js';
|
||||
import { getNameByKeyValue } from '@/lib/common.js';
|
||||
import { getCategorizedAccounts } from '@/lib/account.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'f7router'
|
||||
@@ -263,6 +272,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useRootStore, useUserStore, useAccountsStore),
|
||||
allLanguages() {
|
||||
const ret = [];
|
||||
const allLanguageInfo = this.$locale.getAllLanguageInfos();
|
||||
@@ -291,16 +301,16 @@ export default {
|
||||
return this.$locale.getAllCurrencies();
|
||||
},
|
||||
allAccounts() {
|
||||
return this.$store.getters.allPlainAccounts;
|
||||
return this.accountsStore.allPlainAccounts;
|
||||
},
|
||||
allVisibleAccounts() {
|
||||
return this.$store.getters.allVisiblePlainAccounts;
|
||||
return this.accountsStore.allVisiblePlainAccounts;
|
||||
},
|
||||
allCategorizedAccounts() {
|
||||
return this.$utilities.getCategorizedAccounts(this.allVisibleAccounts);
|
||||
return getCategorizedAccounts(this.allVisibleAccounts);
|
||||
},
|
||||
allWeekDays() {
|
||||
return this.$constants.datetime.allWeekDays;
|
||||
return datetimeConstants.allWeekDays;
|
||||
},
|
||||
allLongDateFormats() {
|
||||
return this.$locale.getAllLongDateFormats();
|
||||
@@ -348,7 +358,7 @@ export default {
|
||||
return this.$t('Unknown');
|
||||
},
|
||||
currentDayOfWeekName() {
|
||||
const weekName = this.$utilities.getNameByKeyValue(this.$constants.datetime.allWeekDays, this.newProfile.firstDayOfWeek, 'type', 'name');
|
||||
const weekName = getNameByKeyValue(datetimeConstants.allWeekDays, this.newProfile.firstDayOfWeek, 'type', 'name');
|
||||
const i18nWeekNameKey = `datetime.${weekName}.long`;
|
||||
return this.$t(i18nWeekNameKey);
|
||||
},
|
||||
@@ -418,8 +428,8 @@ export default {
|
||||
self.loading = true;
|
||||
|
||||
const promises = [
|
||||
self.$store.dispatch('loadAllAccounts', { force: false }),
|
||||
self.$store.dispatch('getCurrentUserProfile')
|
||||
self.accountsStore.loadAllAccounts({ force: false }),
|
||||
self.userStore.getCurrentUserProfile()
|
||||
];
|
||||
|
||||
Promise.all(promises).then(responses => {
|
||||
@@ -460,7 +470,7 @@ export default {
|
||||
self.saving = true;
|
||||
self.$showLoading(() => self.saving);
|
||||
|
||||
self.$store.dispatch('updateUserProfile', {
|
||||
self.rootStore.updateUserProfile({
|
||||
profile: self.newProfile,
|
||||
currentPassword: self.currentPassword
|
||||
}).then(response => {
|
||||
@@ -485,6 +495,9 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
getNameByKeyValue(src, value, keyField, nameField, defaultName) {
|
||||
return getNameByKeyValue(src, value, keyField, nameField, defaultName);
|
||||
},
|
||||
setCurrentUserProfile(profile) {
|
||||
this.oldProfile.email = profile.email;
|
||||
this.oldProfile.nickname = profile.nickname;
|
||||
|
||||
Reference in New Issue
Block a user