Advertisement

#44 Adding Portfolio Plan Percentages And A Little Bit Of Color

In this article we will start by displaying the components of the selected portfolio plan by showing the percentages that the plan calls for based on category as well as calculating the difference in percentages between the plan percentage and the actual percentages. We will also start to address some usability issues by making it a little bit easier to determing what category a give security belonged to using a dynamically set background color.

Code Snippets

index.ts (1:30)

...
export * from "@/store/functions";
...
src ⟩ store ⟩ index.ts

Home.vue (1:55)

<script lang="ts">
...
import {
    ...
    sort,
} from "@/store";
...
export default class Home extends Vue {
    ...
    private mounted() {
        ...
        this.selectedPlan.categories.forEach((x) => {
            ...
            groups[x.category.abbreviation] = sort(groups[x.category.abbreviation], (x) => x.security.symbol);
        });
        ...
    }
}
</script>
src ⟩ views ⟩ Home.vue

Home.vue (3:16)

<script lang="ts">
...
import {
    ...
    PortfolioCategoryModel,
    ...
} from "@/store";
...
export default class Home extends Vue {
    ...
    private get totalValue() {
        return this.accountSecurities.reduce(
            (pre, cur) => pre + cur[1].reduce((pre1, cur1) => pre1 + cur1.value, 0),
            0,
        );
    }
    ...
    private categoryPercent(portfolioCategory: PortfolioCategoryModel) {
        return (this.categoryValue(portfolioCategory.category.abbreviation) / this.valueTotal) * 100;
    }

    private categoryValue(category: string) {
        return this.accountSecurities
            .filter((x) => x[0] === category)
            .map((x) => x[1])
            .reduce((pre, cur) => pre + cur.reduce((pre1, cur1) => pre1 + cur1.value, 0), 0);
    }
}
</script>
src ⟩ views ⟩ Home.vue

Home.vue (8:07)

<template lang="pug">
div.home
    div
        select(v-model="selectedPlan")
            option(
                v-for="plan in plans"
                v-bind:key="plan.id"
                v-bind:value="plan") {{plan.name}}
        div(v-if="selectedPlan")
            ul
                li.row
                    label Category
                    label Plan
                    label Actual
                    label Difference
                li.row(v-for="portfolioCategory in selectedPlan.categories")
                    div {{portfolioCategory.category.abbreviation}}
                    div {{portfolioCategory.percent.toFixed(1)}}
                    div {{categoryPercent(portfolioCategory).toFixed(1)}}
                    div {{(categoryPercent(portfolioCategory) - portfolioCategory.percent).toFixed(1)}}
    ...
</template>
src ⟩ views ⟩ Home.vue

TheRouterOutlet.vue (11:39)

<style lang="sass" scoped>
...
.router-view-animatable
    ...
    overflow: auto
</style>
src ⟩ components ⟩ routing ⟩ TheRouterOutlet.vue

Home.vue (12:18)

<style lang="sass" scoped>
...
.home
    display: grid
    @include padding(0.25rem)
    height: 100%
    grid-template-rows: auto 1fr

.account-securities
    overflow: auto
...
</style>
src ⟩ views ⟩ Home.vue

Advertisement

security-category-model.ts (13:58)

...
export interface ISecurityCategoryModelConfig {
    color: string;
    ...
}

export class SecurityCategoryModel {
    private _color: string;
    ...
    public get color() {
        return this._color;
    }
    public set color(color: string) {
        this._color = color;
    }
    ...
    constructor(config: ISecurityCategoryModelConfig) {
        this._color = config.color;
        ...
    }
    ...
    public toPersistObj = (): ISecurityCategoryModelConfig => {
        return {
            color: this._color,
            ...
        };
    };
}
src ⟩ store ⟩ security-category-model.ts

security-category-initial-state.ts (14:48)

...
index = createCategory({
    color: "#fc8279",
    id: index,
    segmentId: largeCap.id,
    territoryId: domestic.id,
    typeId: equity.id,
});
index = createCategory({
    color: "#fcb479",
    id: index,
    segmentId: midCap.id,
    territoryId: domestic.id,
    typeId: equity.id,
});
index = createCategory({
    color: "#fcf579",
    id: index,
    segmentId: smallCap.id,
    territoryId: domestic.id,
    typeId: equity.id,
});
index = createCategory({
    color: "#c5fc79",
    id: index,
    segmentId: developed.id,
    territoryId: international.id,
    typeId: equity.id,
});
index = createCategory({
    color: "#79fcd7",
    id: index,
    segmentId: emerging.id,
    territoryId: international.id,
    typeId: equity.id,
});
index = createCategory({
    color: "#79dbfc",
    id: index,
    segmentId: developed.id,
    territoryId: domestic.id,
    typeId: fixedIncome.id,
});
index = createCategory({
    color: "#b679fc",
    id: index,
    segmentId: developed.id,
    territoryId: international.id,
    typeId: fixedIncome.id,
});
index = createCategory({
    color: "#fc79dd",
    id: index,
    segmentId: developed.id,
    territoryId: domestic.id,
    typeId: specialty.id,
});
...
src ⟩ store ⟩ security-category-initial-state.ts

Home.vue (15:21)

<template lang="pug">
div.home
    div
        ...
        div(v-if="selectedPlan")
            ul
                li.row
                    label.color
                    ...
                li.row(v-for="portfolioCategory in selectedPlan.categories")
                    div.color(v-bind:style="{ 'background-color': portfolioCategory.category.color }")
                    ...
    ...
</template>
src ⟩ views ⟩ Home.vue

Home.vue (16:32)

<style lang="sass" scoped>
...
.color
    height: 1.5rem
    max-width: 0.75rem
    margin-right: 0.25rem
...
</style>
src ⟩ views ⟩ Home.vue

Home.vue (17:14)

<template lang="pug">
div.home
    ...
    ul.account-securities
        ...
        li(
            v-for="acctSecurityArray in accountSecurities"
            v-bind:key="acctSecurityArray[0]")
            ul
                li(
                    v-for="acctSecurity in acctSecurityArray[1]"
                    v-bind:key="acctSecurity.id"
                    v-bind:style="{ 'background-color': acctSecurity.security.category.color }")
                    ...
</template>
src ⟩ views ⟩ Home.vue

Exciton Interactive LLC
Advertisement