#28 Refactoring The Accounts Module
Saturday, December 14, 2019
In this article we return to the first module that we created which was our accounts module. Our focus is to refactor the code that we have written previously to use the additional functionality and conventions that we created when working on our securities module.
Parts
- Part 45: Adjusting Shares
- Part 44: Plan Percentages
- Part 43: Home Securities
- Part 42: Updating Plans
- Part 41: Plan Details View
- Part 40: Portfolio Getters
- Part 39: Portfolio Plan
- Part 38: Portfolio Category
- Part 37: Account Securities
- Part 36: Account Transfer
- Part 35: View Account Security
- Part 34: Updating Deposit
- Part 33: View Account Deposit
- Part 32: Display Account Details
- Part 31: Account Getters
- Part 30: Deposits And Securities
- Part 29: Add Accounts Details
- Part 28: Refactoring Accounts
- Part 27: Add Security Models
- Part 26: Edit Security Details
- Part 25: View Security Details
- Part 24: Navigating To Details
- Part 23: Getters Validation
- Part 22: Query Parameters
- Part 21: Tab Entries
- Part 20: Tab Header
- Part 19: List View
- Part 18: Vuex Getters
- Part 17: End Domain Model
- Part 16: Start Domain Model
- Part 15: Pop Routes
- Part 14: Push Routes
- Part 13: Removing Accounts
- Part 12: Vuex (Decorators)
- Part 11: Vuex (Accounts)
- Part 10: The App Bar (Settings)
- Part 9: Remove Consumer Rxjs
- Part 8: The App Bar (Back)
- Part 7: Structuring Our App
- Part 6: Animation Between Views
- Part 5: Navigation Fade
- Part 4: Navigation Requests
- Part 3: Fade Animations (cont.)
- Part 2: Fade Animations
- Part 1: Splash Screen
Code Snippets
store-constants.ts (1:13)
...
export const GETTER_ACCOUNT = "GETTER_ACCOUNT";
export const GETTER_ACCOUNTS = "GETTER_ACCOUNTS";
...
store-types.ts (1:54)
...
export interface IStoreState extends IAccountState, ISecurityState {
[STATE_ROUTES]: IRouteState;
}
account-types.ts (2:29)
import { GETTER_ACCOUNT, GETTER_ACCOUNTS, STATE_ACCOUNTS } from "@/store/store-constants";
...
export type GetterAccount = (id: number) => AccountModel;
...
export type PayloadAddAccount = AccountModel;
export type PayloadRemoveAccount = number;
export interface IAccountGetters {
[GETTER_ACCOUNT]: GetterAccount;
[GETTER_ACCOUNTS]: AccountModel[];
}
export interface IAccountModelState {
index: number;
items: AccountModel[];
}
export interface IAccountState {
[STATE_ACCOUNTS]: IAccountModelState;
}
functions.ts (4:33)
...
export function remove<T extends IStateItem>(state: IState<T>, id: number) {
state.items = state.items.filter((x) => x.id !== id);
}
...
account-module.ts (5:52)
import { StoreActions, StoreActionValidator } from "@/store/store-action-validator";
...
import {
...
GETTER_ACCOUNT,
GETTER_ACCOUNTS,
...
} from "@/store/store-constants";
import { add, findById, remove, undefinedMessage } from "@/store/functions";
import { ... StoreGetterTree, ... } from "@/store/store-types";
import { IAccountGetters, IAccountState, PayloadAddAccount, PayloadRemoveAccount } from "@/store/account-types";
import { initialState as accountState } from "@/store/account-initial-state";
const storeActionValidator = new StoreActionValidator();
export const accountActions: StoreActionTree = {
[ACTION_ADD_ACCOUNT](this, { commit }, payload: PayloadAddAccount) {
commit(MUTATION_ADD_ACCOUNT, payload);
},
[ACTION_REMOVE_ACCOUNT](this, { commit }, payload: PayloadRemoveAccount) {
commit(MUTATION_REMOVE_ACCOUNT, payload);
},
};
export const accountGetters: StoreGetterTree = {
[GETTER_ACCOUNT]: (state) => {
return (id: number) => {
const account = findById(state[STATE_ACCOUNTS], id)!;
storeActionValidator
.begin()
.while(StoreActions.Getting)
.throwIf(account)
.isUndefined(undefinedMessage("account", id, state[STATE_ACCOUNTS].index));
return account;
};
},
[GETTER_ACCOUNTS]: (state, getters: IAccountGetters) => {
return state[STATE_ACCOUNTS].items.map((x) => getters[GETTER_ACCOUNT](x.id));
},
};
export const accountMutations: StoreMutationTree = {
[MUTATION_ADD_ACCOUNT](storeState, payload: PayloadAddAccount) {
add(storeState[STATE_ACCOUNTS], payload, (x) => x.name);
},
[MUTATION_REMOVE_ACCOUNT](storeState: IStoreState, payload: PayloadRemoveAccount) {
remove(storeState[STATE_ACCOUNTS], payload);
},
};
export const accountsState = {
[STATE_ACCOUNTS]: accountState,
};
Advertisement
account-model.ts (13:18)
export interface IAccountModelConfig {
...
}
export class AccountModel {
...
public set id(id: number) {
this._id = id;
}
...
public set name(name: string) {
this._name = name;
}
constructor(config: IAccountModelConfig) {
...
}
}
account-initial-state.ts (14:06)
import { IAccountModelConfig, ... } from "@/store/account-model";
import { IAccountModelState } from "@/store/account-types";
...
function createAccount(id: number, config: Omit<IAccountModelConfig, "id">) {
accounts.push(new AccountModel({ id, ...config }));
return (id += 1);
}
let index = 1;
if (process.env.NODE_ENV === "development") {
index = createAccount(index, { name: "name-1" });
index = createAccount(index, { name: "name-2" });
}
export const initialState: IAccountModelState = {
index,
items: accounts,
};
store.ts (15:48)
...
import { ..., accountGetters, accountsState } from "@/store/account-module";
...
const getters = {
...accountGetters,
...,
};
...
const state: IStoreState = {
...accountsState,
...,
};
...
Accounts.vue (16:24)
<script lang="tsx">
import { Component, Inject, Vue } from "vue-property-decorator";
import ListView from "@/components/ListView.vue";
import { IRoute, Routes, RoutingService } from "@/components/routing";
import { AccountModel, GETTER_ACCOUNTS, Getter } from "@/store";
@Component({
components: {
ListView,
},
})
export default class Accounts extends Vue {
@Getter(GETTER_ACCOUNTS) private readonly accounts!: AccountModel[];
@Inject() private readonly routingService!: RoutingService;
private onClick(account: AccountModel) {
console.log("click")
}
private onClickCreate() {
console.log("click create")
}
private renderAccount(account: AccountModel) {
return <label>{account.name}</label>;
}
}
</script>
Accounts.vue (19:37)
<template lang="pug">
ListView(
v-bind:items="accounts"
v-bind:onClick="onClick"
v-bind:onClickCreate="onClickCreate"
v-bind:renderFn="renderAccount")
</template>
Accounts.vue
<style lang="sass" scoped>
@import "../bourbon/bourbon"
@import "../bitters/functions"
@import "../bitters/variables"
</style>
Exciton Interactive LLC