add account list page and account add page

This commit is contained in:
MaysWind
2020-11-09 01:10:41 +08:00
parent 70d4a84349
commit b2b8dcb098
15 changed files with 753 additions and 6 deletions
+34
View File
@@ -0,0 +1,34 @@
const allAccountCategories = [
{
id: 1,
name: 'Cash'
},
{
id: 2,
name: 'Debit Card'
},
{
id: 3,
name: 'Credit Card'
},
{
id: 4,
name: 'Virtual Account'
},
{
id: 5,
name: 'Debt Account'
},
{
id: 6,
name: 'Receivables'
},
{
id: 7,
name: 'Investment Account'
}
];
export default {
allCategories: allAccountCategories
};
+3 -2
View File
@@ -1,10 +1,11 @@
import settings from "../lib/settings.js";
import utils from "../lib/utils.js";
export default function ({ i18n }, value, currencyCode) {
if (!value) {
if (!utils.isNumber(value) && !utils.isString(value)) {
return value;
}
value = value / 100;
const currencyDisplayMode = settings.getCurrencyDisplayMode();
+14
View File
@@ -160,4 +160,18 @@ export default {
password
});
},
getAllAccounts: () => {
return axios.get('v1/accounts/list.json');
},
addAccount: ({ category, type, name, icon, currency, comment, subAccounts }) => {
return axios.post('v1/accounts/add.json', {
category,
type,
name,
icon,
currency,
comment,
subAccounts
});
},
};
+30
View File
@@ -204,6 +204,11 @@ export default {
'two factor is not enabled': 'Two factor is not enabled',
'two factor has already been enabled': 'Two factor has already been enabled',
'two factor backup code does not exist': 'Two factor backup code does not exist',
'account id is invalid': 'Account id is invalid',
'account not found': 'Account is not found',
'account type is invalid': 'Account type is invalid',
'account must have at least one sub account': 'Account must have at least one sub account',
'account cannot have sub accounts': 'Account cannot have sub accounts',
},
'parameter': {
'username': 'Username',
@@ -228,6 +233,7 @@ export default {
'OK': 'OK',
'Cancel': 'Cancel',
'Close': 'Close',
'Submit': 'Submit',
'Update': 'Update',
'None': 'None',
'Done': 'Done',
@@ -286,6 +292,30 @@ export default {
'Expense': 'Expense',
'Income': 'Income',
'Transfer': 'Transfer',
'Cash': 'Cash',
'Debit Card': 'Debit Card',
'Credit Card': 'Credit Card',
'Virtual Account': 'Virtual Account',
'Debt Account': 'Debt Account',
'Receivables': 'Receivables',
'Investment Account': 'Investment Account',
'Unable to get account list': 'Unable to get account list',
'Add Account': 'Add Account',
'Account Category': 'Account Category',
'Single Account': 'Single Account',
'Multi Sub Accounts': 'Multi Sub Accounts',
'Account Type': 'Account Type',
'Account Name': 'Account Name',
'Your account name': 'Your account name',
'Currency': 'Currency',
'Description': 'Description',
'Your account description (optional)': 'Your account description (optional)',
'Account category cannot be empty': 'Account category cannot be empty',
'Account type cannot be empty': 'Account type cannot be empty',
'Account name cannot be empty': 'Account name cannot be empty',
'Account currency cannot be empty': 'Account currency cannot be empty',
'You have added a new account': 'You have added a new account',
'Unable to add account': 'Unable to add account',
'User Profile': 'User Profile',
'Language': 'Language',
'Currency Display Mode': 'Currency Display Mode',
+30
View File
@@ -204,6 +204,11 @@ export default {
'two factor is not enabled': '两步验证没有启用',
'two factor has already been enabled': '两步验证已经启用',
'two factor backup code does not exist': '两步验证备用码不存在',
'account id is invalid': '账户ID无效',
'account not found': '账户不存在',
'account type is invalid': '账户类型无效',
'account must have at least one sub account': '账户必须包含至少一个子账户',
'account cannot have sub accounts': '账户不能包含子账户',
},
'parameter': {
'username': '用户名',
@@ -228,6 +233,7 @@ export default {
'OK': '确定',
'Cancel': '取消',
'Close': '关闭',
'Submit': '提交',
'Update': '更新',
'None': '无',
'Done': '完成',
@@ -286,6 +292,30 @@ export default {
'Expense': '支出',
'Income': '收入',
'Transfer': '转账',
'Cash': '现金',
'Debit Card': '借记卡',
'Credit Card': '信用卡',
'Virtual Account': '虚拟账户',
'Debt Account': '负债账户',
'Receivables': '应收款项',
'Investment Account': '投资账户',
'Unable to get account list': '无法获取账户列表',
'Add Account': '添加账户',
'Account Category': '账户分类',
'Single Account': '单一账户',
'Multi Sub Accounts': '多个子账户',
'Account Type': '账户类型',
'Account Name': '账户名称',
'Your account name': '你的账户名称',
'Currency': '货币',
'Description': '描述',
'Your account description (optional)': '你的账户描述 (可选)',
'Account category cannot be empty': '账户分类不能为空',
'Account type cannot be empty': '账户类型不能为空',
'Account name cannot be empty': '账户名称不能为空',
'Account currency cannot be empty': '账户货币不能为空',
'You have added a new account': '您已经添加新账户',
'Unable to add account': '无法添加账户',
'User Profile': '用户信息',
'Language': '语言',
'Currency Display Mode': '货币显示模式',
+4
View File
@@ -14,6 +14,7 @@ import 'framework7-icons';
import { getAllLanguages, getLanguage, getDefaultLanguage, getI18nOptions, getLocalizedError } from './lib/i18n.js';
import currency from './consts/currency.js';
import account from './consts/account.js';
import version from './lib/version.js';
import settings from './lib/settings.js';
import services from './lib/services.js';
@@ -31,6 +32,9 @@ Framework7.use(Framework7Vue);
const i18n = new VueI18n(getI18nOptions());
Vue.prototype.$version = version.getVersion;
Vue.prototype.$constants = {
account: account
};
Vue.prototype.$utils = utils;
Vue.prototype.$settings = settings;
Vue.prototype.$getDefaultLanguage = getDefaultLanguage;
+6
View File
@@ -8,6 +8,7 @@ import TransactionDetailPage from '../views/mobile/transactions/Detail.vue'
import TransactionNewPage from '../views/mobile/transactions/New.vue'
import AccountListPage from '../views/mobile/accounts/AccountList.vue'
import AccountAddPage from '../views/mobile/accounts/AccountAdd.vue'
import StatisticsOverviewPage from '../views/mobile/statistics/Overview.vue'
@@ -72,6 +73,11 @@ const routes = [
component: AccountListPage,
beforeEnter: checkLogin
},
{
path: '/account/add',
component: AccountAddPage,
beforeEnter: checkLogin
},
{
path: '/statistic/overview',
component: StatisticsOverviewPage,
+151
View File
@@ -0,0 +1,151 @@
<template>
<f7-page>
<f7-navbar :title="$t('Add Account')" :back-link="$t('Back')"></f7-navbar>
<f7-list no-hairlines-md>
<f7-list-input
type="select"
:label="$t('Account Category')"
:value="category"
@input="category = $event.target.value"
>
<option v-for="accountCategory in allAccountCategories"
:key="accountCategory.id"
:value="accountCategory.id">{{ $t(accountCategory.name) }}</option>
</f7-list-input>
<f7-list-input
type="select"
disabled
:label="$t('Account Type')"
:value="type"
@input="type = $event.target.value"
>
<option value="1">{{ $t('Single Account') }}</option>
<option value="2">{{ $t('Multi Sub Accounts') }}</option>
</f7-list-input>
<f7-list-input
type="text"
clear-button
:label="$t('Account Name')"
:placeholder="$t('Your account name')"
:value="name"
@input="name = $event.target.value"
></f7-list-input>
<f7-list-input
type="select"
:label="$t('Currency')"
:value="currency"
@input="currency = $event.target.value"
>
<option v-for="currency in allCurrencies"
:key="currency.code"
:value="currency.code">{{ currency.displayName }}</option>
</f7-list-input>
<f7-list-input
type="textarea"
:label="$t('Description')"
:placeholder="$t('Your account description (optional)')"
:value="comment"
@input="comment = $event.target.value"
></f7-list-input>
<f7-list-item class="lab-list-item-error-info" v-if="inputIsInvalid" :footer="$t(inputInvalidProblemMessage)"></f7-list-item>
</f7-list>
<f7-button large fill :class="{ 'disabled': inputIsEmpty || submitting }" :text="$t('Submit')" @click="submit"></f7-button>
</f7-page>
</template>
<script>
export default {
data() {
const self = this;
return {
category: 1,
type: 1,
name: '',
icon: "1",
currency: self.$user.getUserInfo() ? self.$user.getUserInfo().defaultCurrency : self.$t('default.currency'),
comment: '',
submitting: false,
allAccountCategories: self.$constants.account.allCategories,
allCurrencies: self.$getAllCurrencies()
};
},
computed: {
inputIsEmpty() {
return !!this.inputEmptyProblemMessage;
},
inputIsInvalid() {
return !!this.inputInvalidProblemMessage;
},
inputEmptyProblemMessage() {
if (!this.category) {
return 'Account category cannot be empty';
} else if (!this.type) {
return 'Account type cannot be empty';
} else if (!this.name) {
return 'Account name cannot be empty';
} else if (!this.currency) {
return 'Account currency cannot be empty';
} else {
return null;
}
},
inputInvalidProblemMessage() {
return null;
}
},
methods: {
submit() {
const self = this;
const router = self.$f7router;
let problemMessage = self.inputEmptyProblemMessage || self.inputInvalidProblemMessage;
if (problemMessage) {
self.$alert(problemMessage);
return;
}
self.submitting = true;
self.$showLoading(() => self.signuping);
self.$services.addAccount({
category: parseInt(self.category),
type: parseInt(self.type),
name: self.name,
icon: self.icon,
currency: self.currency,
comment: self.comment
}).then(response => {
self.submitting = false;
self.$hideLoading();
const data = response.data;
if (!data || !data.success || !data.result) {
self.$alert('Unable to add account');
return;
}
self.$toast('You have added a new account');
router.back('/account/list', { force: true });
}).catch(error => {
self.submitting = false;
self.$hideLoading();
if (error.response && error.response.data && error.response.data.errorMessage) {
self.$alert({ error: error.response.data });
} else if (!error.processed) {
self.$alert('Unable to add account');
}
});
}
}
}
</script>
+94 -4
View File
@@ -1,9 +1,99 @@
<template>
<f7-page>
<f7-navbar :title="$t('Account List')" :back-link="$t('Back')"></f7-navbar>
<f7-navbar>
<f7-nav-left :back-link="$t('Back')"></f7-nav-left>
<f7-nav-title :title="$t('Account List')" :back-link="$t('Back')"></f7-nav-title>
<f7-nav-right>
<f7-link href="/account/add" icon-f7="plus"></f7-link>
</f7-nav-right>
</f7-navbar>
<f7-list media-list class="skeleton-text">
<f7-list-item title="Placeholder"></f7-list-item>
</f7-list>
<f7-block class="skeleton-text" v-if="loading">
<f7-block-title>Account Category</f7-block-title>
<f7-list media-list>
<f7-list-item title="Account Name" after="0.00 USD"></f7-list-item>
</f7-list>
</f7-block>
<f7-block v-for="accountCategory in usedAccountCategories" :key="accountCategory.id">
<f7-block-title>{{ $t(accountCategory.name) }}</f7-block-title>
<f7-list media-list>
<f7-list-item v-for="account in accounts[accountCategory.id]" :key="account.id"
:title="account.name" :after="account.balance | currency(account.currency)"></f7-list-item>
</f7-list>
</f7-block>
</f7-page>
</template>
<script>
export default {
data() {
return {
accounts: {},
loading: true
};
},
computed: {
usedAccountCategories() {
const allAccountCategories = this.$constants.account.allCategories;
const usedAccountCategories = [];
for (let i = 0; i < allAccountCategories.length; i++) {
const accountCategory = allAccountCategories[i];
if (this.$utils.isArray(this.accounts[accountCategory.id]) && this.accounts[accountCategory.id].length) {
usedAccountCategories.push(accountCategory);
}
}
return usedAccountCategories;
}
},
created() {
const self = this;
const router = self.$f7router;
self.loading = true;
self.$services.getAllAccounts().then(response => {
self.loading = false;
const data = response.data;
if (!data || !data.success || !data.result) {
self.$alert('Unable to get account list', () => {
router.back();
});
return;
}
self.accounts = {};
for (let i = 0; i < data.result.length; i++) {
const account = data.result[i];
if (!self.accounts[account.category]) {
self.accounts[account.category] = [];
}
const accountList = self.accounts[account.category];
accountList.push(account);
}
}).catch(error => {
self.loading = false;
if (error.response && error.response.data && error.response.data.errorMessage) {
self.$alert({ error: error.response.data }, () => {
router.back();
});
} else if (!error.processed) {
self.$alert('Unable to get account list', () => {
router.back();
});
}
});
},
methods: {
}
};
</script>