From b2b8dcb09808727ceaa710ae95f4001577cb2d81 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Mon, 9 Nov 2020 01:10:41 +0800 Subject: [PATCH] add account list page and account add page --- cmd/database.go | 1 + cmd/webserver.go | 4 + pkg/api/accounts.go | 151 ++++++++++++++++++++++ pkg/errs/account.go | 11 ++ pkg/models/account.go | 97 ++++++++++++++ pkg/services/accounts.go | 123 ++++++++++++++++++ src/consts/account.js | 34 +++++ src/filters/currency.js | 5 +- src/lib/services.js | 14 ++ src/locales/en.js | 30 +++++ src/locales/zh_Hans.js | 30 +++++ src/mobile-main.js | 4 + src/router/mobile.js | 6 + src/views/mobile/accounts/AccountAdd.vue | 151 ++++++++++++++++++++++ src/views/mobile/accounts/AccountList.vue | 98 +++++++++++++- 15 files changed, 753 insertions(+), 6 deletions(-) create mode 100644 pkg/api/accounts.go create mode 100644 pkg/errs/account.go create mode 100644 pkg/models/account.go create mode 100644 pkg/services/accounts.go create mode 100644 src/consts/account.js create mode 100644 src/views/mobile/accounts/AccountAdd.vue diff --git a/cmd/database.go b/cmd/database.go index a18128ef..5fd9c230 100644 --- a/cmd/database.go +++ b/cmd/database.go @@ -31,6 +31,7 @@ func updateDatabaseStructure(c *cli.Context) error { _ = datastore.Container.UserStore.SyncStructs(new(models.User), new(models.TwoFactor), new(models.TwoFactorRecoveryCode)) _ = datastore.Container.TokenStore.SyncStructs(new(models.TokenRecord)) + _ = datastore.Container.UserDataStore.SyncStructs(new(models.Account)) log.BootInfof("[database.updateDatabaseStructure] maintained successfully") diff --git a/cmd/webserver.go b/cmd/webserver.go index 38635e1d..92070dd3 100644 --- a/cmd/webserver.go +++ b/cmd/webserver.go @@ -157,6 +157,10 @@ func startWebServer(c *cli.Context) error { apiV1Route.POST("/users/2fa/disable.json", bindApi(api.TwoFactorAuthorizations.TwoFactorDisableHandler)) apiV1Route.POST("/users/2fa/recovery/regenerate.json", bindApi(api.TwoFactorAuthorizations.TwoFactorRecoveryCodeRegenerateHandler)) } + + // Accounts + apiV1Route.GET("/accounts/list.json", bindApi(api.Accounts.AccountListHandler)) + apiV1Route.POST("/accounts/add.json", bindApi(api.Accounts.AccountCreateHandler)) } } diff --git a/pkg/api/accounts.go b/pkg/api/accounts.go new file mode 100644 index 00000000..d1210258 --- /dev/null +++ b/pkg/api/accounts.go @@ -0,0 +1,151 @@ +package api + +import ( + "sort" + + "github.com/mayswind/lab/pkg/core" + "github.com/mayswind/lab/pkg/errs" + "github.com/mayswind/lab/pkg/log" + "github.com/mayswind/lab/pkg/models" + "github.com/mayswind/lab/pkg/services" +) + +type AccountsApi struct { + accounts *services.AccountService +} + +var ( + Accounts = &AccountsApi{ + accounts: services.Accounts, + } +) + +func (a *AccountsApi) AccountListHandler(c *core.Context) (interface{}, *errs.Error) { + uid := c.GetCurrentUid() + accounts, err := a.accounts.GetAllAccountsByUid(uid) + + if err != nil { + log.ErrorfWithRequestId(c, "[accounts.AccountListHandler] failed to get all accounts for user \"uid:%d\", because %s", uid, err.Error()) + return nil, errs.ErrOperationFailed + } + + userAllAccountResps := make([]*models.AccountInfoResponse, len(accounts)) + userAllAccountRespMap := make(map[int64]*models.AccountInfoResponse) + + for i := 0; i < len(accounts); i++ { + userAllAccountResps[i] = accounts[i].ToAccountInfoResponse() + userAllAccountRespMap[userAllAccountResps[i].Id] = userAllAccountResps[i] + } + + for i := 0; i < len(userAllAccountResps); i++ { + userAccountResp := userAllAccountResps[i] + + if userAccountResp.ParentId <= models.ACCOUNT_PARENT_ID_LEVEL_ONE { + continue + } + + parentAccount, parentExists := userAllAccountRespMap[userAccountResp.ParentId] + + if !parentExists || parentAccount == nil { + continue + } + + parentAccount.SubAccounts = append(parentAccount.SubAccounts, userAccountResp) + } + + userFinalAccountResps := make(models.AccountInfoResponseSlice, 0) + + for i := 0; i < len(userAllAccountResps); i++ { + if userAllAccountResps[i].ParentId == models.ACCOUNT_PARENT_ID_LEVEL_ONE { + sort.Sort(userAllAccountResps[i].SubAccounts) + userFinalAccountResps = append(userFinalAccountResps, userAllAccountResps[i]) + } + } + + sort.Sort(userFinalAccountResps) + + return userFinalAccountResps, nil +} + +func (a *AccountsApi) AccountCreateHandler(c *core.Context) (interface{}, *errs.Error) { + var accountCreateReq models.AccountCreateRequest + err := c.ShouldBindJSON(&accountCreateReq) + + if err != nil { + log.WarnfWithRequestId(c, "[accounts.AccountCreateHandler] parse request failed, because %s", err.Error()) + return nil, errs.NewIncompleteOrIncorrectSubmissionError(err) + } + + if accountCreateReq.Type == models.ACCOUNT_TYPE_SINGLE_ACCOUNT { + if len(accountCreateReq.SubAccounts) > 0 { + log.WarnfWithRequestId(c, "[accounts.AccountCreateHandler] account cannot have any sub accounts") + return nil, errs.ErrAccountCannotHaveSubAccounts + } + } else if accountCreateReq.Type == models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS { + if len(accountCreateReq.SubAccounts) < 1 { + log.WarnfWithRequestId(c, "[accounts.AccountCreateHandler] account does not have any sub accounts") + return nil, errs.ErrAccountHaveNoSubAccount + } + } else { + log.WarnfWithRequestId(c, "[accounts.AccountCreateHandler] account type invalid, type is %d", accountCreateReq.Type) + return nil, errs.ErrAccountTypeInvalid + } + + uid := c.GetCurrentUid() + maxOrderId, err := a.accounts.GetMaxDisplayOrder(uid) + + if err != nil { + log.ErrorfWithRequestId(c, "[accounts.AccountCreateHandler] failed to get max display order for user \"uid:%d\", because %s", uid, err.Error()) + return nil, errs.ErrOperationFailed + } + + mainAccount := a.createNewAccount(uid, &accountCreateReq, maxOrderId+1) + childrenAccounts := a.createSubAccounts(uid, &accountCreateReq) + + err = a.accounts.CreateAccounts(mainAccount, childrenAccounts) + + if err != nil { + log.ErrorfWithRequestId(c, "[accounts.AccountCreateHandler] failed to create account \"id:%d\" for user \"uid:%d\", because %s", mainAccount.AccountId, uid, err.Error()) + return nil, errs.Or(err, errs.ErrOperationFailed) + } + + log.InfofWithRequestId(c, "[accounts.AccountCreateHandler] user \"uid:%d\" has created a new account \"id:%d\" successfully", uid, mainAccount.AccountId) + + accountInfoResp := mainAccount.ToAccountInfoResponse() + + if len(childrenAccounts) > 0 { + accountInfoResp.SubAccounts = make([]*models.AccountInfoResponse, len(childrenAccounts)) + + for i := 0; i < len(childrenAccounts); i++ { + accountInfoResp.SubAccounts[i] = childrenAccounts[i].ToAccountInfoResponse() + } + } + + return accountInfoResp, nil +} + +func (a *AccountsApi) createNewAccount(uid int64, accountCreateReq *models.AccountCreateRequest, order int) *models.Account { + return &models.Account{ + Uid: uid, + Name: accountCreateReq.Name, + DisplayOrder: order, + Category: accountCreateReq.Category, + Icon: accountCreateReq.Icon, + Currency: accountCreateReq.Currency, + Comment: accountCreateReq.Comment, + } +} + +func (a *AccountsApi) createSubAccounts(uid int64, accountCreateReq *models.AccountCreateRequest) []*models.Account { + if len(accountCreateReq.SubAccounts) <= 0 { + return nil + } + + childrenAccounts := make([]*models.Account, len(accountCreateReq.SubAccounts)) + + for i := 0; i < len(accountCreateReq.SubAccounts); i++ { + childrenAccounts[i] = a.createNewAccount(uid, accountCreateReq.SubAccounts[i], i+1) + } + + return childrenAccounts +} diff --git a/pkg/errs/account.go b/pkg/errs/account.go new file mode 100644 index 00000000..3b606a50 --- /dev/null +++ b/pkg/errs/account.go @@ -0,0 +1,11 @@ +package errs + +import "net/http" + +var ( + ErrAccountIdInvalid = NewNormalError(NORMAL_SUBCATEGORY_ACCOUNT, 0, http.StatusBadRequest, "account id is invalid") + ErrAccountNotFound = NewNormalError(NORMAL_SUBCATEGORY_ACCOUNT, 1, http.StatusBadRequest, "account not found") + ErrAccountTypeInvalid = NewNormalError(NORMAL_SUBCATEGORY_ACCOUNT, 2, http.StatusBadRequest, "account type is invalid") + ErrAccountHaveNoSubAccount = NewNormalError(NORMAL_SUBCATEGORY_ACCOUNT, 3, http.StatusBadRequest, "account must have at least one sub account") + ErrAccountCannotHaveSubAccounts = NewNormalError(NORMAL_SUBCATEGORY_ACCOUNT, 4, http.StatusBadRequest, "account cannot have sub accounts") +) diff --git a/pkg/models/account.go b/pkg/models/account.go new file mode 100644 index 00000000..e24f48f9 --- /dev/null +++ b/pkg/models/account.go @@ -0,0 +1,97 @@ +package models + +// Level-One Account +const ACCOUNT_PARENT_ID_LEVEL_ONE = 0 + +type AccountCategory byte + +const ( + ACCOUNT_CATEGORY_CASH AccountCategory = 1 + ACCOUNT_CATEGORY_DEBIT_CARD AccountCategory = 2 + ACCOUNT_CATEGORY_CREDIT_CARD AccountCategory = 3 + ACCOUNT_CATEGORY_VIRTUAL AccountCategory = 4 + ACCOUNT_CATEGORY_DEBT AccountCategory = 5 + ACCOUNT_CATEGORY_RECEIVABLES AccountCategory = 6 + ACCOUNT_CATEGORY_INVESTMENT AccountCategory = 7 +) + +type AccountType byte + +const ( + ACCOUNT_TYPE_SINGLE_ACCOUNT AccountType = 1 + ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS AccountType = 2 +) + +type Account struct { + AccountId int64 `xorm:"PK"` + Uid int64 `xorm:"INDEX(IDX_account_uid_deleted_parent_account_id_order) NOT NULL"` + Deleted bool `xorm:"INDEX(IDX_account_uid_deleted_parent_account_id_order) NOT NULL"` + Category AccountCategory `xorm:"NOT NULL"` + Type AccountType `xorm:"NOT NULL"` + ParentAccountId int64 `xorm:"INDEX(IDX_account_uid_deleted_parent_account_id_order) NOT NULL"` + Name string `xorm:"VARCHAR(32) NOT NULL"` + DisplayOrder int `xorm:"INDEX(IDX_account_uid_deleted_parent_account_id_order) NOT NULL"` + Icon int64 `xorm:"NOT NULL"` + Currency string `xorm:"VARCHAR(3) NOT NULL"` + Balance int64 `xorm:"NOT NULL"` + Comment string `xorm:"VARCHAR(255) NOT NULL"` + Hidden bool `xorm:"NOT NULL"` + CreatedUnixTime int64 + UpdatedUnixTime int64 + DeletedUnixTime int64 +} + +type AccountCreateRequest struct { + Name string `json:"name" binding:"required,notBlank,max=32"` + Category AccountCategory `json:"category" binding:"required"` + Type AccountType `json:"type" binding:"required"` + Icon int64 `json:"icon,string" binding:"required,min=1"` + Currency string `json:"currency" binding:"required,len=3,validCurrency"` + Comment string `json:"comment" binding:"max=255"` + SubAccounts []*AccountCreateRequest `json:"subAccounts" binding:"omitempty"` +} + +type AccountInfoResponse struct { + Id int64 `json:"id,string"` + Name string `json:"name"` + ParentId int64 `json:"parentId,string"` + Category AccountCategory `json:"category"` + Type AccountType `json:"type"` + Icon int64 `json:"icon,string"` + Currency string `json:"currency"` + Balance int64 `json:"balance"` + Comment string `json:"comment"` + DisplayOrder int `json:"displayOrder"` + Hidden bool `json:"hidden"` + SubAccounts AccountInfoResponseSlice `json:"subAccounts,omitempty"` +} + +func (a *Account) ToAccountInfoResponse() *AccountInfoResponse { + return &AccountInfoResponse{ + Id: a.AccountId, + Name: a.Name, + ParentId: a.ParentAccountId, + Category: a.Category, + Type: a.Type, + Icon: a.Icon, + Currency: a.Currency, + Balance: a.Balance, + Comment: a.Comment, + DisplayOrder: a.DisplayOrder, + Hidden: a.Hidden, + } +} + +type AccountInfoResponseSlice []*AccountInfoResponse + +func (a AccountInfoResponseSlice) Len() int { + return len(a) +} + +func (a AccountInfoResponseSlice) Swap(i, j int) { + a[i], a[j] = a[j], a[i] +} + +func (a AccountInfoResponseSlice) Less(i, j int) bool { + return a[i].DisplayOrder < a[j].DisplayOrder +} diff --git a/pkg/services/accounts.go b/pkg/services/accounts.go new file mode 100644 index 00000000..44fc0b7e --- /dev/null +++ b/pkg/services/accounts.go @@ -0,0 +1,123 @@ +package services + +import ( + "time" + + "xorm.io/xorm" + + "github.com/mayswind/lab/pkg/datastore" + "github.com/mayswind/lab/pkg/errs" + "github.com/mayswind/lab/pkg/models" + "github.com/mayswind/lab/pkg/uuid" +) + +type AccountService struct { + ServiceUsingDB + ServiceUsingUuid +} + +var ( + Accounts = &AccountService{ + ServiceUsingDB: ServiceUsingDB{ + container: datastore.Container, + }, + ServiceUsingUuid: ServiceUsingUuid{ + container: uuid.Container, + }, + } +) + +func (s *AccountService) GetAllAccountsByUid(uid int64) ([]*models.Account, error) { + if uid <= 0 { + return nil, errs.ErrUserIdInvalid + } + + var accounts []*models.Account + err := s.UserDataDB(uid).Where("uid=? AND deleted=?", uid, false).OrderBy("parent_account_id asc, display_order asc").Find(&accounts) + + return accounts, err +} + +func (s *AccountService) GetMaxDisplayOrder(uid int64) (int, error) { + if uid <= 0 { + return 0, errs.ErrUserIdInvalid + } + + account := &models.Account{} + has, err := s.UserDataDB(uid).Cols("uid", "deleted", "parent_account_id", "display_order").Where("uid=? AND deleted=? AND parent_account_id=?", uid, false, models.ACCOUNT_PARENT_ID_LEVEL_ONE).OrderBy("display_order desc").Limit(1).Get(account) + + if err != nil { + return 0, err + } + + if has { + return account.DisplayOrder, nil + } else { + return 0, nil + } +} + +func (s *AccountService) GetMaxSubAccountDisplayOrder(uid int64, parentAccountId int64) (int, error) { + if uid <= 0 { + return 0, errs.ErrUserIdInvalid + } + + if parentAccountId <= 0 { + return 0, errs.ErrAccountIdInvalid + } + + account := &models.Account{} + has, err := s.UserDataDB(uid).Cols("uid", "deleted", "parent_account_id", "display_order").Where("uid=? AND deleted=? AND parent_account_id=?", uid, false, parentAccountId).OrderBy("display_order desc").Limit(1).Get(account) + + if err != nil { + return 0, err + } + + if has { + return account.DisplayOrder, nil + } else { + return 0, nil + } +} + +func (s *AccountService) CreateAccounts(mainAccount *models.Account, childrenAccounts []*models.Account) error { + if mainAccount.Uid <= 0 { + return errs.ErrUserIdInvalid + } + + allAccounts := make([]*models.Account, len(childrenAccounts)+1) + + mainAccount.AccountId = s.GenerateUuid(uuid.UUID_TYPE_ACCOUNT) + allAccounts[0] = mainAccount + + if mainAccount.Type == models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS { + for i := 0; i < len(childrenAccounts); i++ { + childAccount := childrenAccounts[i] + childAccount.AccountId = s.GenerateUuid(uuid.UUID_TYPE_ACCOUNT) + childAccount.ParentAccountId = mainAccount.AccountId + childAccount.Uid = mainAccount.Uid + childAccount.Type = models.ACCOUNT_TYPE_SINGLE_ACCOUNT + + allAccounts[i+1] = childrenAccounts[i] + } + } + + for i := 0; i < len(allAccounts); i++ { + allAccounts[i].Deleted = false + allAccounts[i].CreatedUnixTime = time.Now().Unix() + allAccounts[i].UpdatedUnixTime = time.Now().Unix() + } + + return s.UserDataDB(mainAccount.Uid).DoTransaction(func(sess *xorm.Session) error { + for i := 0; i < len(allAccounts); i++ { + account := allAccounts[i] + _, err := sess.Insert(account) + + if err != nil { + return err + } + } + + return nil + }) +} diff --git a/src/consts/account.js b/src/consts/account.js new file mode 100644 index 00000000..26bb7bd0 --- /dev/null +++ b/src/consts/account.js @@ -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 +}; diff --git a/src/filters/currency.js b/src/filters/currency.js index 46c58f80..0d8cc5ee 100644 --- a/src/filters/currency.js +++ b/src/filters/currency.js @@ -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(); diff --git a/src/lib/services.js b/src/lib/services.js index 96d77fb3..0834e2e0 100644 --- a/src/lib/services.js +++ b/src/lib/services.js @@ -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 + }); + }, }; diff --git a/src/locales/en.js b/src/locales/en.js index 0f060cd7..a1df2aeb 100644 --- a/src/locales/en.js +++ b/src/locales/en.js @@ -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', diff --git a/src/locales/zh_Hans.js b/src/locales/zh_Hans.js index db1a137f..d2d8f976 100644 --- a/src/locales/zh_Hans.js +++ b/src/locales/zh_Hans.js @@ -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': '货币显示模式', diff --git a/src/mobile-main.js b/src/mobile-main.js index a5c27c2d..951fa136 100644 --- a/src/mobile-main.js +++ b/src/mobile-main.js @@ -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; diff --git a/src/router/mobile.js b/src/router/mobile.js index 5163562a..5030e9d2 100644 --- a/src/router/mobile.js +++ b/src/router/mobile.js @@ -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, diff --git a/src/views/mobile/accounts/AccountAdd.vue b/src/views/mobile/accounts/AccountAdd.vue new file mode 100644 index 00000000..b61d092e --- /dev/null +++ b/src/views/mobile/accounts/AccountAdd.vue @@ -0,0 +1,151 @@ + + + diff --git a/src/views/mobile/accounts/AccountList.vue b/src/views/mobile/accounts/AccountList.vue index f72a5da3..46099873 100644 --- a/src/views/mobile/accounts/AccountList.vue +++ b/src/views/mobile/accounts/AccountList.vue @@ -1,9 +1,99 @@ + +