#42 Adding And Updating Portfolio Plans In The Vuex Store
Saturday, March 21, 2020
In this article we will go through the process of updating our vuex store so that we will have the ability to add and update portfolio plans. The will give us the ability to add new plans as well as modify the name and category percentages of existing plans.
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-types.ts (1:40)
...
import { IPortfolioGetters, IPortfolioState } from "@/store/portfolio-types";
...
export interface IStoreGetters extends IAccountGetters, IPortfolioGetters, ISecurityGetters {}
...
portfolio-module.ts (2:30)
import {
...
GETTER_SECURITY_CATEGORIES,
...
} from "@/store/store-constants";
...
export const portfolioGetters: StoreGetterTree = {
[GETTER_PORTFOLIO_CATEGORIES]: (storeState, getters: IPortfolioGetters) => {
return (planId: number) => {
if (planId <= 0) {
return getters[GETTER_SECURITY_CATEGORIES].map((x) => {
const portfolioCategory = new PortfolioCategoryModel({
categoryId: x.id,
id: x.id,
percent: 0,
planId: 0,
});
portfolioCategory.setCategory(x);
return portfolioCategory;
});
}
...
};
},
...
};
...
PlannerDetails.vue (6:00)
<script lang="ts">
...
import {
...
GETTER_PORTFOLIO_CATEGORIES,
...
GetterPortfolioCategories,
...
PortfolioPlanModel,
} from "@/store";
...
export default class PlannerDetails extends Vue {
...
@Getter(GETTER_PORTFOLIO_CATEGORIES) private readonly getterPortfolioCategories!: GetterPortfolioCategories;
...
private mounted() {
...
if (this.id <= 0) {
this.portfolioCategories = this.getterPortfolioCategories(0);
return;
}
...
}
private save() {
const plan = new PortfolioPlanModel({
categories: this.portfolioCategories,
id: this.id,
name: this.name,
});
console.log(plan);
}
}
</script>
store-constants.ts (8:16)
...
export const ACTION_ADD_PORTFOLIO_PLAN = "ACTION_ADD_PORTFOLIO_PLAN";
...
export const ACTION_UPDATE_PORTFOLIO_PLAN = "ACTION_UPDATE_PORTFOLIO_PLAN";
...
export const MUTATION_ADD_PORTFOLIO_PLAN = "MUTATION_ADD_PORTFOLIO_PLAN";
...
export const MUTATION_UPDATE_PORTFOLIO_PLAN = "MUTATION_UPDATE_PORTFOLIO_PLAN";
...
portfolio-types.ts (9:09)
...
export type PayloadAddPortfolioPlan = PortfolioPlanModel;
export type PayloadUpdatePortfolioPlan = PortfolioPlanModel;
...
Advertisement
functions.ts (9:36)
...
export function add<T extends IStateItem>(...) {
...
return item;
}
...
portfolio-module.ts (10:12)
import {
ACTION_ADD_PORTFOLIO_PLAN,
ACTION_UPDATE_PORTFOLIO_PLAN,
...
MUTATION_ADD_PORTFOLIO_PLAN,
MUTATION_UPDATE_PORTFOLIO_PLAN,
...
} from "@/store/store-constants";
import { add, ... } from "@/store/functions";
...
import { PortfolioPlanModel } from "@/store/portfolio-plan-model";
import {
...
PayloadAddPortfolioPlan,
PayloadUpdatePortfolioPlan,
} from "@/store/portfolio-types";
...
import { ..., StoreActionTree, ..., StoreMutationTree } from "@/store/store-types";
...
function totalPercent(plan: PortfolioPlanModel) {
const total = plan.categories.reduce((pre, cur) => pre + cur.percent, 0);
if (total !== 100) {
console.log(`The total percent of the plan must be 100% but the current percent is '${total}%'`);
return true;
}
return false;
}
...
export const portfolioActions: StoreActionTree = {
[ACTION_ADD_PORTFOLIO_PLAN](this, { commit }, payload: PayloadAddPortfolioPlan) {
if (totalPercent(payload)) {
return;
}
commit(MUTATION_ADD_PORTFOLIO_PLAN, payload);
},
[ACTION_UPDATE_PORTFOLIO_PLAN](this, { commit }, payload: PayloadUpdatePortfolioPlan) {
if (totalPercent(payload)) {
return;
}
commit(MUTATION_UPDATE_PORTFOLIO_PLAN, payload);
},
};
...
export const portfolioMutations: StoreMutationTree = {
[MUTATION_ADD_PORTFOLIO_PLAN](storeState, payload: PayloadAddPortfolioPlan) {
const plan = add(storeState[STATE_PORTFOLIO_PLANS], payload, (x) => x.name);
payload.categories.forEach((x) => {
x.planId = plan.id;
add(storeState[STATE_PORTFOLIO_CATEGORIES], x);
});
},
[MUTATION_UPDATE_PORTFOLIO_PLAN](storeState, payload: PayloadUpdatePortfolioPlan) {
const portfolioCategories = storeState[STATE_PORTFOLIO_CATEGORIES].items.filter((x) => x.planId === payload.id);
const portfolioPlanState = storeState[STATE_PORTFOLIO_PLANS];
const plan = findById(portfolioPlanState, payload.id)!;
storeActionValidator
.begin()
.while(StoreActions.Updating)
.throwIf(plan)
.isUndefined(undefinedMessage("portfolio plan", payload.id, portfolioPlanState.index));
plan.name = payload.name;
portfolioCategories.forEach((x) => {
const category = plan.categories.find((y) => y.id === x.id)!;
category.percent = x.percent;
});
},
};
store.ts (19:11)
...
import { portfolioActions, ..., portfolioMutations, ... } from "@/store/portfolio-module";
...
const actions = {
...accountActions,
...portfolioActions,
...routeActions,
...securitiesActions,
};
...
const mutations = {
...accountMutations,
...portfolioMutations,
...routeMutations,
...securitiesMutations,
};
...
PlannerDetails.vue (19:42)
<script lang="ts">
...
import {
ACTION_ADD_PORTFOLIO_PLAN,
ACTION_UPDATE_PORTFOLIO_PLAN,
...
PayloadAddPortfolioPlan,
PayloadUpdatePortfolioPlan,
...
} from "@/store";
...
export default class PlannerDetails extends Vue {
@Action(ACTION_ADD_PORTFOLIO_PLAN) private readonly addPlan!: ActionFn<PayloadAddPortfolioPlan>;
...
@Action(ACTION_UPDATE_PORTFOLIO_PLAN) private readonly updatePlan!: ActionFn<PayloadUpdatePortfolioPlan>;
...
private save() {
...
switch (this.id) {
case 0:
this.addPlan(plan);
break;
default:
this.updatePlan(plan);
break;
}
}
}
</script>
Exciton Interactive LLC