#43 Displaying The Securities On The Home Screen
Saturday, March 28, 2020
In this video we are going to start by implementing a fix for the problem of editing the percentage of a portfolio category and having that change be persisted in our store even if it is cancelled. This fix could then be extended to cover similar problems with other objects being saved in our store. Once that is done we will proceed to modifying our home screen to display a select input for our different plans as well as all of the securities contained in each of our accounts.
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
portfolio-category-model.ts (1:46)
...
export class PortfolioCategoryModel {
...
public get category() {
if (this._category === null) {
throw new Error("The category has not been defined.");
}
return this._category;
}
...
public get plan() {
if (this._plan === null) {
throw new Error("The plan has not been defined.");
}
return this._plan;
}
...
public clone() {
const model = new PortfolioCategoryModel({
categoryId: this.categoryId,
id: this.id,
percent: this.percent,
planId: this.planId,
});
if (this._category !== null) {
model.setCategory(this.category);
}
if (this._plan !== null) {
model.setPlan(this.plan);
}
return model;
}
...
}
portfolio-module.ts (3:50)
...
export const portfolioGetters: StoreGetterTree = {
...
[GETTER_PORTFOLIO_CATEGORY]: (storeState, getters: IStoreGetters) => {
return (id: number) => {
...
return portfolioCategory.clone();
};
},
...
};
...
export const portfolioMutations: StoreMutationTree = {
...
[MUTATION_UPDATE_PORTFOLIO_PLAN](storeState, payload: PayloadUpdatePortfolioPlan) {
...
portfolioCategories.forEach((x) => {
...
x.percent = category.percent;
});
},
};
...
portfolio-initial-state.ts (5:57)
...
if (process.env.NODE_ENV === "development") {
...
const value = new PortfolioPlanModel({ categories, id: 2, name: "Value" });
...
plans.push(value);
...
const growthCatDelc = new PortfolioCategoryModel({ categoryId: delc.id, id: 1, percent: 38, planId: growth.id });
const growthCatDemc = new PortfolioCategoryModel({ categoryId: demc.id, id: 2, percent: 12, planId: growth.id });
const growthCatDesc = new PortfolioCategoryModel({ categoryId: desc.id, id: 3, percent: 6, planId: growth.id });
const growthCatIedm = new PortfolioCategoryModel({ categoryId: iedm.id, id: 4, percent: 18, planId: growth.id });
const growthCatIeem = new PortfolioCategoryModel({ categoryId: ieem.id, id: 5, percent: 7, planId: growth.id });
const growthCatDfdm = new PortfolioCategoryModel({ categoryId: dfdm.id, id: 6, percent: 13, planId: growth.id });
const growthCatIfdm = new PortfolioCategoryModel({ categoryId: ifdm.id, id: 7, percent: 3, planId: growth.id });
const growthCatDsdm = new PortfolioCategoryModel({ categoryId: dsdm.id, id: 8, percent: 3, planId: growth.id });
const valueCatDelc = new PortfolioCategoryModel({ categoryId: delc.id, id: 9, percent: 30, planId: value.id });
const valueCatDemc = new PortfolioCategoryModel({ categoryId: demc.id, id: 10, percent: 8, planId: value.id });
const valueCatDesc = new PortfolioCategoryModel({ categoryId: desc.id, id: 11, percent: 2, planId: value.id });
const valueCatIedm = new PortfolioCategoryModel({ categoryId: iedm.id, id: 12, percent: 10, planId: value.id });
const valueCatIeem = new PortfolioCategoryModel({ categoryId: ieem.id, id: 13, percent: 3, planId: value.id });
const valueCatDfdm = new PortfolioCategoryModel({ categoryId: dfdm.id, id: 14, percent: 33, planId: value.id });
const valueCatIfdm = new PortfolioCategoryModel({ categoryId: ifdm.id, id: 15, percent: 11, planId: value.id });
const valueCatDsdm = new PortfolioCategoryModel({ categoryId: dsdm.id, id: 16, percent: 3, planId: value.id });
categories.push(growthCatDelc);
categories.push(growthCatDemc);
categories.push(growthCatDesc);
categories.push(growthCatIedm);
categories.push(growthCatIeem);
categories.push(growthCatDfdm);
categories.push(growthCatIfdm);
categories.push(growthCatDsdm);
categories.push(valueCatDelc);
categories.push(valueCatDemc);
categories.push(valueCatDesc);
categories.push(valueCatIedm);
categories.push(valueCatIeem);
categories.push(valueCatDfdm);
categories.push(valueCatIfdm);
categories.push(valueCatDsdm);
}
export const categoryState: IPortfolioCategoryModelState = {
index: categories.length + 1,
items: categories,
};
export const planState: IPortfolioPlanModelState = {
index: plans.length + 1,
items: plans,
};
Advertisement
Home.vue (7:16)
<template lang="pug">
div Hello World
</template>
Home.vue (7:28)
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
@Component
export default class Home extends Vue {}
</script>
Home.vue (7:48)
<script lang="ts">
...
import { currencyFormatter } from "@/functions";
import {
AccountModel,
AccountSecurityModel,
GETTER_ACCOUNTS,
GETTER_PORTFOLIO_PLANS,
Getter,
PortfolioPlanModel,
} from "@/store";
...
export default class Home extends Vue {
@Getter(GETTER_ACCOUNTS) private readonly accounts!: AccountModel[];
@Getter(GETTER_PORTFOLIO_PLANS) private readonly plans!: PortfolioPlanModel[];
private readonly currency = currencyFormatter();
private accountSecurities: Array<[string, AccountSecurityModel[]]> = [];
private selectedPlan: PortfolioPlanModel | null = null;
private mounted() {
if (this.plans.length > 0) {
this.selectedPlan = this.plans[0];
}
if (this.selectedPlan === null) {
return;
}
const groups: { [key: string]: AccountSecurityModel[] } = {};
this.selectedPlan.categories.forEach((x) => {
this.accounts.forEach((y) => {
const filteredSecurities = y.securities
.filter((z) => z.security.categoryId === x.categoryId)
.map((z) => {
const accountSecurity = new AccountSecurityModel({
accountId: z.accountId,
id: z.id,
security: z.security,
securityId: z.securityId,
shares: z.shares,
});
accountSecurity.account = y;
return accountSecurity;
});
if (groups[x.category.abbreviation]) {
groups[x.category.abbreviation].push(...filteredSecurities);
} else {
groups[x.category!.abbreviation] = filteredSecurities;
}
});
});
Object.keys(groups).forEach((x) => this.accountSecurities.push([x, groups[x]]));
}
}
</script>
Home.vue (18:28)
<template lang="pug">
div.home
select(v-model="selectedPlan")
option(
v-for="plan in plans"
v-bind:key="plan.id"
v-bind:value="plan") {{plan.name}}
ul.account-securities
li.row
label Symbol
label Account
label Shares
label Last
li(
v-for="acctSecurityArray in accountSecurities"
v-bind:key="acctSecurityArray[0]")
ul
li(
v-for="acctSecurity in acctSecurityArray[1]"
v-bind:key="acctSecurity.id")
div.row
div {{acctSecurity.security.symbol}}
div {{acctSecurity.account.name}}
div {{acctSecurity.shares}}
div {{currency.format(acctSecurity.security.last)}}
</template>
Home.vue (22:38)
<style lang="sass" scoped>
@import "../bourbon/bourbon"
@import "../bitters/functions"
@import "../bitters/variables"
.home
@include padding(0.25rem)
.row
display: flex
align-items: center
& > *
flex: 1
</style>
Exciton Interactive LLC