| @@ -0,0 +1,28 @@ | |||
| <bkp-divider-shadow-bottom></bkp-divider-shadow-bottom> | |||
| <div class="container"> | |||
| <div class="row justify-content-center"> | |||
| <div class="col-sm-4"> | |||
| <div *ngIf="validBrokerSelected()" class="row justify-content-center"> | |||
| <div #brokerPhoto class="broker-photo" [ngStyle]="{'background-image' : avatarUrl }" ></div> | |||
| </div> | |||
| <kendo-combobox #selectBroker | |||
| [data]="filteredBroker" [allowCustom]="false" | |||
| [filterable]="true" | |||
| [textField]="'Display'" | |||
| [valueField]="'Id'" | |||
| [placeholder]="'Select a broker'" | |||
| [(ngModel)]="brokerSelected" | |||
| [ngModelOptions]="{standalone: true}" | |||
| (filterChange)="onFilterBroker($event)" | |||
| (valueChange)="onBrokerSelected($event)" | |||
| > | |||
| <ng-template kendoDropDownListItemTemplate let-dataItem> | |||
| <img class="contact-image" [src]="getContactImageUrl(dataItem.Id)" /> | |||
| <span>{{ dataItem.First +' ' + dataItem.Last}}</span> | |||
| </ng-template> | |||
| </kendo-combobox> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <app-broker-reward #brokerReward></app-broker-reward> | |||
| @@ -0,0 +1,27 @@ | |||
| .broker-photo { | |||
| display: inline-block; | |||
| width: 256px; | |||
| height: 256px; | |||
| border-radius: 50%; | |||
| background-size: 256px 256px; | |||
| background-position: center center; | |||
| vertical-align: middle; | |||
| line-height: 132px; | |||
| margin-left: 5px; | |||
| margin-bottom: 10px; | |||
| background-repeat: no-repeat; | |||
| box-shadow: 1px 1px 10px black; | |||
| } | |||
| kendo-combobox { | |||
| width:100%; | |||
| } | |||
| .contact-image { | |||
| width: 32px; | |||
| height: 32px; | |||
| margin-right: 8px; | |||
| border-radius: 50%; | |||
| } | |||
| @@ -0,0 +1,25 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { AdminRewardByBrokerComponent } from './admin-reward-by-broker.component'; | |||
| describe('AdminRewardByBrokerComponent', () => { | |||
| let component: AdminRewardByBrokerComponent; | |||
| let fixture: ComponentFixture<AdminRewardByBrokerComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [ AdminRewardByBrokerComponent ] | |||
| }) | |||
| .compileComponents(); | |||
| }); | |||
| beforeEach(() => { | |||
| fixture = TestBed.createComponent(AdminRewardByBrokerComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,64 @@ | |||
| import {Component, OnInit, ViewChild} from '@angular/core'; | |||
| import {BrokerModel} from '../models/broker.model'; | |||
| import {PeopleService} from '../service/people.service'; | |||
| import {AuthService} from '../service/auth.service'; | |||
| import {ClonerService} from '../service/clone.service'; | |||
| import {BrokerRewardComponent} from '../broker-reward/broker-reward.component'; | |||
| import {ComboBoxComponent} from '@progress/kendo-angular-dropdowns'; | |||
| @Component({ | |||
| selector: 'app-admin-reward-by-broker', | |||
| templateUrl: './admin-reward-by-broker.component.html', | |||
| styleUrls: ['./admin-reward-by-broker.component.scss'] | |||
| }) | |||
| export class AdminRewardByBrokerComponent implements OnInit { | |||
| public AllBrokers: BrokerModel[] = []; | |||
| public filteredBroker: BrokerModel[] = []; | |||
| public brokerSelected: BrokerModel = BrokerModel.EmptyNew(); | |||
| public avatarUrl = ''; | |||
| @ViewChild('selectBroker', {static: true}) sb: ComboBoxComponent; | |||
| @ViewChild('brokerReward', {static: true}) br: BrokerRewardComponent; | |||
| constructor(private ps: PeopleService, private auth: AuthService, private dcs: ClonerService) { } | |||
| ngOnInit(): void { | |||
| this.ps.getBrokerList('').subscribe( | |||
| resp => { | |||
| this.AllBrokers = resp.List; | |||
| this.onFilterBroker(''); | |||
| this.sb.toggle(true); | |||
| } | |||
| ); | |||
| } | |||
| public getContactImageUrl(contactId: string): string { | |||
| return this.auth.getUrl('avatar/' + contactId); | |||
| } | |||
| public onFilterBroker(hint: string): void { | |||
| if ( hint === undefined || hint.length === 0 ) { | |||
| this.filteredBroker = this.AllBrokers.slice(0); | |||
| }else { | |||
| this.filteredBroker = this.AllBrokers.filter( | |||
| v => v.Display.toLowerCase().includes(hint.toLowerCase()) | |||
| ); | |||
| } | |||
| } | |||
| public onBrokerSelected(broker: BrokerModel): void { | |||
| if ( broker === undefined) { | |||
| this.avatarUrl = ''; | |||
| this.br.ShowBroker('some-broker-that-not-exist'); | |||
| this.sb.toggle(true); | |||
| }else { | |||
| this.avatarUrl = 'url(' + this.auth.getUrl('avatar/' + broker.Id) + ')'; | |||
| this.br.ShowBroker(broker.Id); | |||
| } | |||
| } | |||
| public validBrokerSelected(): boolean{ | |||
| return this.brokerSelected !== undefined && this.brokerSelected.Id !== ''; | |||
| } | |||
| } | |||
| @@ -15,6 +15,10 @@ import {ClientLoanListComponent} from './client-loan-list/client-loan-list.compo | |||
| import {ClientProfileComponent} from './client-profile/client-profile.component'; | |||
| import {E403Component} from './e403/e403.component'; | |||
| import {ListAllRewardsComponent} from './list-all-rewards/list-all-rewards.component'; | |||
| import {AdminRewardByBrokerComponent} from './admin-reward-by-broker/admin-reward-by-broker.component'; | |||
| import {RewardOverviewComponent} from './reward-overview/reward-overview.component'; | |||
| import {RewardPaidComponent} from './reward-paid/reward-paid.component'; | |||
| import {RewardUnpaidComponent} from './reward-unpaid/reward-unpaid.component'; | |||
| const routes: Routes = [ | |||
| @@ -34,6 +38,10 @@ const routes: Routes = [ | |||
| {path : 'client-loan-list', component: ClientLoanListComponent, canActivate: [AuthGuard] }, | |||
| {path : 'client-profile', component: ClientProfileComponent, canActivate: [AuthGuard] }, | |||
| {path : 'list-all-rewards', component: ListAllRewardsComponent, canActivate: [AuthGuard] }, | |||
| {path : 'list-reward-by-broker', component: AdminRewardByBrokerComponent , canActivate: [AuthGuard] }, | |||
| {path : 'reward-overview', component: RewardOverviewComponent, canActivate: [AuthGuard] }, | |||
| {path : 'reward-paid', component: RewardPaidComponent, canActivate: [AuthGuard] }, | |||
| {path : 'reward-unpaid', component: RewardUnpaidComponent, canActivate: [AuthGuard] }, | |||
| {path : 'e403', component: E403Component, }, | |||
| ]; | |||
| @@ -72,6 +72,10 @@ import { ClientProfileComponent } from './client-profile/client-profile.componen | |||
| import { E403Component } from './e403/e403.component'; | |||
| import {FileSelectModule, UploadModule} from '@progress/kendo-angular-upload'; | |||
| import { ListAllRewardsComponent } from './list-all-rewards/list-all-rewards.component'; | |||
| import { AdminRewardByBrokerComponent } from './admin-reward-by-broker/admin-reward-by-broker.component'; | |||
| import { RewardOverviewComponent } from './reward-overview/reward-overview.component'; | |||
| import { RewardUnpaidComponent } from './reward-unpaid/reward-unpaid.component'; | |||
| import { RewardPaidComponent } from './reward-paid/reward-paid.component'; | |||
| @@ -114,7 +118,11 @@ import { ListAllRewardsComponent } from './list-all-rewards/list-all-rewards.com | |||
| ClientLoanListComponent, | |||
| ClientProfileComponent, | |||
| E403Component, | |||
| ListAllRewardsComponent | |||
| ListAllRewardsComponent, | |||
| AdminRewardByBrokerComponent, | |||
| RewardOverviewComponent, | |||
| RewardUnpaidComponent, | |||
| RewardPaidComponent | |||
| ], | |||
| imports: [ | |||
| BrowserModule, | |||
| @@ -1,6 +1,7 @@ | |||
| <kendo-grid | |||
| [groupable]="true" | |||
| [data]="gridView" | |||
| [loading]="loading" | |||
| (groupChange)="groupChange($event)" | |||
| > | |||
| <kendo-grid-column field="Id" [groupable]="false"></kendo-grid-column> | |||
| @@ -1,4 +1,4 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| import {Component, Input, OnInit} from '@angular/core'; | |||
| import {HttpClient} from '@angular/common/http'; | |||
| import {AuthService} from '../service/auth.service'; | |||
| import {RewardByUserModel} from '../models/reward-by-user.model'; | |||
| @@ -11,7 +11,9 @@ import {DataResult, GroupDescriptor, process} from '@progress/kendo-data-query'; | |||
| }) | |||
| export class BrokerRewardComponent implements OnInit { | |||
| @Input() selectedBrokerId = ''; | |||
| public gridData: RewardByUserModel[] = [] ; | |||
| public loading = false; | |||
| public groups: GroupDescriptor[] = [{ field: 'Description' }, { field: 'Item' } ]; | |||
| public gridView: DataResult; | |||
| @@ -19,13 +21,27 @@ export class BrokerRewardComponent implements OnInit { | |||
| constructor(private http: HttpClient, private auth: AuthService ) { } | |||
| ngOnInit(): void { | |||
| this.loading = true; | |||
| this.loadBrokerReward(); | |||
| } | |||
| private loadBrokerReward(): void { | |||
| this.gridData = []; | |||
| this.http.get<RewardByUserModel[]>(this.auth.getUrl('user-reward/')).subscribe( | |||
| // avoid loading everything when used with admin user | |||
| if ( this.auth.loggedIn.role === 'admin' && this.selectedBrokerId === '' ) { | |||
| this.loading = false; | |||
| return ; | |||
| } | |||
| // load a single user | |||
| this.http.get<RewardByUserModel[]>(this.auth.getUrl('user-reward/' + this.selectedBrokerId )).subscribe( | |||
| rsp => { | |||
| rsp.forEach(v => { | |||
| this.gridData.push(new RewardByUserModel(v)); | |||
| }); | |||
| this.loadRewards(); | |||
| this.loading = false; | |||
| } | |||
| ); | |||
| } | |||
| @@ -36,7 +52,20 @@ export class BrokerRewardComponent implements OnInit { | |||
| } | |||
| private loadRewards(): void { | |||
| this.loading = true; | |||
| this.gridView = process(this.gridData, { group: this.groups }); | |||
| this.loading = false; | |||
| } | |||
| public ShowBroker(id: string): void { | |||
| if (id === 'some-broker-that-not-exist' ) { | |||
| this.gridView.data = []; | |||
| this.gridView.total = 0; | |||
| return; | |||
| } | |||
| this.loading = true; | |||
| this.selectedBrokerId = id; | |||
| this.loadBrokerReward(); | |||
| } | |||
| } | |||
| @@ -1,19 +1,112 @@ | |||
| <kendo-chart [legend]="seriesLabels" > | |||
| <kendo-chart-axis-defaults> | |||
| <kendo-chart-axis-defaults-labels format="c0"> | |||
| </kendo-chart-axis-defaults-labels> | |||
| </kendo-chart-axis-defaults> | |||
| <kendo-chart-title text="Reward vs Income (AUD) "></kendo-chart-title> | |||
| <kendo-chart-category-axis> | |||
| <kendo-chart-category-axis-item [categories]="rvi.Categories"> | |||
| </kendo-chart-category-axis-item> | |||
| </kendo-chart-category-axis> | |||
| <kendo-chart-series > | |||
| <kendo-chart-series-item *ngFor="let d of rvi.Data; let idx=index" | |||
| type="bar" | |||
| [gap]="1" [spacing]="0.05" [data]="rvi.Data[idx]" | |||
| [labels]="seriesLabels" | |||
| > | |||
| </kendo-chart-series-item> | |||
| </kendo-chart-series> | |||
| </kendo-chart> | |||
| <div class="box"> | |||
| <kendo-grid | |||
| [data]="gridView" | |||
| [loading]="loading" | |||
| [sortable]="true" | |||
| [pageable]="true" | |||
| [filterable]="true" | |||
| [pageSize]="state.take" | |||
| [skip]="state.skip" | |||
| [sort]="state.sort" | |||
| [filter]="state.filter" | |||
| (dataStateChange)="dataStateChange($event)" | |||
| > | |||
| <kendo-grid-column field="Id" width="100"> | |||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||
| <kendo-grid-string-filter-cell | |||
| [showOperators]="false" | |||
| [operator]="'eq'" | |||
| [column]="column" | |||
| [filter]="filter"> | |||
| </kendo-grid-string-filter-cell> | |||
| </ng-template> | |||
| </kendo-grid-column> | |||
| <kendo-grid-column field="Amount" > | |||
| <ng-template kendoGridCellTemplate let-dataItem> | |||
| <span >{{ dataItem.Amount | currency }}</span> | |||
| </ng-template> | |||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||
| <kendo-grid-numeric-filter-cell | |||
| [showOperators]="false" | |||
| [operator]="'gte'" | |||
| [column]="column" | |||
| [filter]="filter"> | |||
| </kendo-grid-numeric-filter-cell> | |||
| </ng-template> | |||
| </kendo-grid-column> | |||
| <kendo-grid-column field="ToDisplay" title="Beneficiary" width="250"> | |||
| <ng-template kendoGridCellTemplate let-dataItem> | |||
| <div class="customer-photo" [ngStyle]="{'background-image' : photoURL(dataItem.To)}"></div> | |||
| <div class="customer-name"> {{ dataItem.ToDisplay }}</div> | |||
| </ng-template> | |||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||
| <kendo-grid-string-filter-cell | |||
| [showOperators]="false" | |||
| [column]="column" | |||
| [filter]="filter"> | |||
| </kendo-grid-string-filter-cell> | |||
| </ng-template> | |||
| </kendo-grid-column> | |||
| <kendo-grid-column field="Description" title=" Description" > | |||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||
| <kendo-grid-string-filter-cell | |||
| [showOperators]="false" | |||
| [column]="column" | |||
| [filter]="filter"> | |||
| </kendo-grid-string-filter-cell> | |||
| </ng-template> | |||
| </kendo-grid-column> | |||
| <kendo-grid-column field="Item" title=" From Loan"> | |||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||
| <kendo-grid-string-filter-cell | |||
| [showOperators]="false" | |||
| [column]="column" | |||
| [filter]="filter"> | |||
| </kendo-grid-string-filter-cell> | |||
| </ng-template> | |||
| </kendo-grid-column> | |||
| <kendo-grid-column field="Status" title="Loan Status"> | |||
| <ng-template kendoGridCellTemplate let-dataItem> | |||
| <span *ngIf="dataItem.Status != 'none'" class="badge badge-success">{{dataItem.Status}}</span> | |||
| </ng-template> | |||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||
| <kendo-grid-string-filter-cell | |||
| [showOperators]="false" | |||
| [column]="column" | |||
| [filter]="filter"> | |||
| </kendo-grid-string-filter-cell> | |||
| </ng-template> | |||
| </kendo-grid-column> | |||
| <kendo-grid-column field="Ts" title="Date Rewarded" filter="date"> | |||
| <ng-template kendoGridCellTemplate let-dataItem > | |||
| <div *ngIf="dataItem.Ts != null" > | |||
| {{ dataItem.Ts | date: 'yyyy-MM-dd' }} | |||
| </div> | |||
| </ng-template> | |||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||
| <kendo-grid-date-filter-cell | |||
| [showOperators]="false" | |||
| [column]="column" | |||
| [filter]="filter"> | |||
| </kendo-grid-date-filter-cell> | |||
| </ng-template> | |||
| </kendo-grid-column> | |||
| <kendo-grid-column field="Paid" title="Paid"> | |||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||
| <kendo-grid-boolean-filter-cell | |||
| [column]="column" | |||
| [filter]="filter"> | |||
| </kendo-grid-boolean-filter-cell> | |||
| </ng-template> | |||
| </kendo-grid-column> | |||
| </kendo-grid> | |||
| </div> | |||
| @@ -1,3 +1,32 @@ | |||
| kendo-chart { | |||
| height: 600px; | |||
| .box { | |||
| display: flex; | |||
| flex-flow: column; | |||
| height: calc(100vh - 48px); | |||
| } | |||
| kendo-grid{ | |||
| flex: 0 1 auto; | |||
| } | |||
| .customer-photo{ | |||
| display: inline-block; | |||
| width: 32px; | |||
| height: 32px; | |||
| border-radius: 50%; | |||
| background-size: 32px 35px; | |||
| background-position: center center; | |||
| vertical-align: middle; | |||
| line-height: 32px; | |||
| box-shadow: inset 0 0 1px #999, inset 0 0 10px rgba(0,0,0,.2); | |||
| margin-left: 5px; | |||
| margin-bottom: 10px; | |||
| } | |||
| .customer-name { | |||
| display: inline-block; | |||
| vertical-align: middle; | |||
| line-height: 32px; | |||
| padding-left: 10px; | |||
| } | |||
| @@ -1,8 +1,9 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| import {AuthService} from '../service/auth.service'; | |||
| import {HttpClient} from '@angular/common/http'; | |||
| import {RewardVsIncomeModel} from '../models/reward-vs-incom.model'; | |||
| import {SeriesLabels} from '@progress/kendo-angular-charts'; | |||
| import {RewardByUserModel} from '../models/reward-by-user.model'; | |||
| import {DataStateChangeEvent, GridDataResult,} from '@progress/kendo-angular-grid'; | |||
| import {State, process} from '@progress/kendo-data-query'; | |||
| @Component({ | |||
| selector: 'app-list-all-rewards', | |||
| @@ -11,20 +12,47 @@ import {SeriesLabels} from '@progress/kendo-angular-charts'; | |||
| }) | |||
| export class ListAllRewardsComponent implements OnInit { | |||
| public rvi: RewardVsIncomeModel = new RewardVsIncomeModel(); | |||
| public seriesLabels: SeriesLabels = { | |||
| visible: true, // Note that visible defaults to false | |||
| padding: 3, | |||
| font: 'bold 9px Arial, sans-serif', | |||
| format: 'c0' | |||
| public gridData: RewardByUserModel[] = [] ; | |||
| public gridView: GridDataResult; | |||
| public state: State = { | |||
| skip: 0, | |||
| take: 10 | |||
| }; | |||
| public loading = true; | |||
| constructor(private auth: AuthService, private http: HttpClient) { } | |||
| ngOnInit(): void { | |||
| this.http.get<RewardVsIncomeModel>(this.auth.getUrl('chart/reward-vs-income-monthly')).subscribe( | |||
| resp => { console.log(resp); this.rvi = resp; } | |||
| this.loadInitRewardGrid(); | |||
| } | |||
| public loadInitRewardGrid(): void { | |||
| this.loading = true; | |||
| this.gridData = []; | |||
| this.http.get<RewardByUserModel[]>(this.auth.getUrl('user-reward/')).subscribe( | |||
| rsp => { | |||
| this.loading = false; | |||
| rsp.forEach(v => { | |||
| this.gridData.push(new RewardByUserModel(v)); | |||
| }); | |||
| this.loadRewards(); | |||
| } | |||
| ); | |||
| } | |||
| private loadRewards(): void { | |||
| this.gridView = process(this.gridData, this.state); | |||
| } | |||
| public dataStateChange(state: DataStateChangeEvent): void { | |||
| this.state = state; | |||
| this.loadRewards(); | |||
| } | |||
| private photoURL(peopleId: any): string { | |||
| const url = this.auth.getUrl('avatar/') + peopleId; | |||
| return 'url("' + url + '")'; | |||
| } | |||
| } | |||
| @@ -15,44 +15,38 @@ export const mainMenuItems: any[] = [ | |||
| icon: 'dollar', | |||
| items: [ | |||
| { text: 'Start New Loan', icon: 'plus', url: './#edit-loan/' }, | |||
| { text: 'List All New', icon: 'table' , url: './#list-all-loans' }, | |||
| { text: 'List All', icon: 'table' , url: './#list-all-loans' }, | |||
| { text: '--', separator: 'true' }, | |||
| { text: 'Income', icon: 'dollar', url: './#income' }, | |||
| { text: '--', separator: 'true' }, | |||
| { text: 'Uploads', icon: 'dollar', url: './#loan-uploads' }, | |||
| ] | |||
| }, | |||
| { | |||
| text: 'Reward', | |||
| icon: 'percent', | |||
| items: [ | |||
| { text: 'Overview', icon: 'table', url: './#list-all-rewards#' }, | |||
| { text: 'Overview', icon: 'table', url: './#reward-overview' }, | |||
| { text: 'List All', icon: 'table', url: './#list-all-rewards' }, | |||
| { text: '--', separator: 'true' }, | |||
| { text: 'By Broker', icon: 'table', url: './#list-reward-by-broker' }, | |||
| { text: '--', separator: 'true' }, | |||
| { text: 'Lender Monthly Uploads', icon: 'attachment' , url: './#uploads'} | |||
| { text: 'Not Paid', icon: 'attachment' , url: './#reward-unpaid'}, | |||
| { text: 'Paid', icon: 'attachment' , url: './#reward-paid'}, | |||
| ] | |||
| }, | |||
| { | |||
| text: 'Clients', | |||
| text: 'People', | |||
| icon: 'user', | |||
| items: [ | |||
| { text: 'Add ', icon: 'plus', url: './#add-client' }, | |||
| { text: 'Add ', icon: 'plus', url: './#add-people' }, | |||
| { text: 'List All', fa: faIdCard , url: './#list-all-client'}, | |||
| { text: '--', separator: 'true' }, | |||
| { text: 'Broadcast', icon: 'email', url: './#send-to-all-client'}, | |||
| { text: '--', separator: 'true' }, | |||
| { text: 'Broadcast', icon: 'email', url: './#send-to-all-client'}, | |||
| ] | |||
| }, | |||
| { | |||
| text: 'Brokers', | |||
| fa: faUserCircle, | |||
| items: [ | |||
| { text: 'Add ', icon: 'plus', url: '#' }, | |||
| { text: 'List All', fa: faIdCardAlt}, | |||
| { text: '--', separator: 'true' }, | |||
| { text: 'Search' , icon: 'search'}, | |||
| { text: '--', separator: 'true' }, | |||
| { text: 'Broadcast' , icon : 'email'}, | |||
| { text: '--', separator: 'true' }, | |||
| { text: 'UnPaid', fa : faMoneyCheck }, | |||
| ] | |||
| } | |||
| ]; | |||
| @@ -2,5 +2,11 @@ | |||
| export class RewardVsIncomeModel { | |||
| Categories: string[]; | |||
| Data: number[][2]; | |||
| Data: number[][]; | |||
| constructor() { | |||
| this.Data = new Array<number[]>(3); | |||
| for (let i = 0; i <= 2 ; i++){ | |||
| this.Data[i] = []; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,36 @@ | |||
| <kendo-chart [legend]="seriesLabels" > | |||
| <kendo-chart-legend position="bottom" orientation="horizontal"> | |||
| </kendo-chart-legend> | |||
| <kendo-chart-axis-defaults> | |||
| <kendo-chart-axis-defaults-labels format="c0"> | |||
| </kendo-chart-axis-defaults-labels> | |||
| </kendo-chart-axis-defaults> | |||
| <kendo-chart-title text="Reward vs Income (AUD) "></kendo-chart-title> | |||
| <kendo-chart-category-axis> | |||
| <kendo-chart-category-axis-item [categories]="rvi.Categories"> | |||
| </kendo-chart-category-axis-item> | |||
| </kendo-chart-category-axis> | |||
| <kendo-chart-series > | |||
| <kendo-chart-series-item name="reward (SFM Paid)" | |||
| type="bar" | |||
| color="lightgrey" | |||
| [gap]="4" [spacing]="0.25" [data]="rvi.Data[0]" | |||
| [labels]="seriesLabels" | |||
| > | |||
| </kendo-chart-series-item> | |||
| <kendo-chart-series-item name="Income (SFM received) " | |||
| color="orange" | |||
| type="bar" | |||
| [gap]="1" [spacing]="0.25" [data]="rvi.Data[1]" | |||
| [labels]="seriesLabels" | |||
| > | |||
| </kendo-chart-series-item> | |||
| <kendo-chart-series-item name="Profit SFM earned" | |||
| type="bar" | |||
| color="lightgreen" | |||
| [gap]="1" [spacing]="0.25" [data]="rvi.Data[2]" | |||
| [labels]="seriesLabels" | |||
| > | |||
| </kendo-chart-series-item> | |||
| </kendo-chart-series> | |||
| </kendo-chart> | |||
| @@ -0,0 +1,4 @@ | |||
| kendo-chart { | |||
| height: calc(100vh - 48px); | |||
| flex: 0 1 auto; | |||
| } | |||
| @@ -0,0 +1,25 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { RewardOverviewComponent } from './reward-overview.component'; | |||
| describe('RewardOverviewComponent', () => { | |||
| let component: RewardOverviewComponent; | |||
| let fixture: ComponentFixture<RewardOverviewComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [ RewardOverviewComponent ] | |||
| }) | |||
| .compileComponents(); | |||
| }); | |||
| beforeEach(() => { | |||
| fixture = TestBed.createComponent(RewardOverviewComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,42 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| import {RewardVsIncomeModel} from '../models/reward-vs-incom.model'; | |||
| import {SeriesLabels} from '@progress/kendo-angular-charts'; | |||
| import {AuthService} from '../service/auth.service'; | |||
| import {HttpClient} from '@angular/common/http'; | |||
| @Component({ | |||
| selector: 'app-reward-overview', | |||
| templateUrl: './reward-overview.component.html', | |||
| styleUrls: ['./reward-overview.component.scss'] | |||
| }) | |||
| export class RewardOverviewComponent implements OnInit { | |||
| public rvi: RewardVsIncomeModel = new RewardVsIncomeModel(); | |||
| public seriesLabels: SeriesLabels = { | |||
| visible: true, // Note that visible defaults to false | |||
| padding: 3, | |||
| font: 'bold 9px Arial, sans-serif', | |||
| format: 'c0' | |||
| }; | |||
| constructor(private auth: AuthService, private http: HttpClient) { } | |||
| ngOnInit(): void { | |||
| this.loadInitialRewardOverviewChart(); | |||
| } | |||
| public loadInitialRewardOverviewChart(): void{ | |||
| this.http.get<RewardVsIncomeModel>(this.auth.getUrl('chart/reward-vs-income-monthly')).subscribe( | |||
| resp => { | |||
| this.rvi.Categories = resp.Categories; | |||
| this.rvi.Data[2] = []; | |||
| for (let i = 0; i < 12; i++){ | |||
| this.rvi.Data[0] = resp.Data[0]; | |||
| this.rvi.Data[1] = resp.Data[1]; | |||
| this.rvi.Data[2][i] = this.rvi.Data[1][i] - this.rvi.Data[0][i]; | |||
| } | |||
| } | |||
| ); | |||
| } | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| <p>reward-paid works!</p> | |||
| @@ -0,0 +1,25 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { RewardPaidComponent } from './reward-paid.component'; | |||
| describe('RewardPaidComponent', () => { | |||
| let component: RewardPaidComponent; | |||
| let fixture: ComponentFixture<RewardPaidComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [ RewardPaidComponent ] | |||
| }) | |||
| .compileComponents(); | |||
| }); | |||
| beforeEach(() => { | |||
| fixture = TestBed.createComponent(RewardPaidComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,15 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| @Component({ | |||
| selector: 'app-reward-paid', | |||
| templateUrl: './reward-paid.component.html', | |||
| styleUrls: ['./reward-paid.component.scss'] | |||
| }) | |||
| export class RewardPaidComponent implements OnInit { | |||
| constructor() { } | |||
| ngOnInit(): void { | |||
| } | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| <p>reward-unpaid works!</p> | |||
| @@ -0,0 +1,25 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { RewardUnpaidComponent } from './reward-unpaid.component'; | |||
| describe('RewardUnpaidComponent', () => { | |||
| let component: RewardUnpaidComponent; | |||
| let fixture: ComponentFixture<RewardUnpaidComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [ RewardUnpaidComponent ] | |||
| }) | |||
| .compileComponents(); | |||
| }); | |||
| beforeEach(() => { | |||
| fixture = TestBed.createComponent(RewardUnpaidComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,15 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| @Component({ | |||
| selector: 'app-reward-unpaid', | |||
| templateUrl: './reward-unpaid.component.html', | |||
| styleUrls: ['./reward-unpaid.component.scss'] | |||
| }) | |||
| export class RewardUnpaidComponent implements OnInit { | |||
| constructor() { } | |||
| ngOnInit(): void { | |||
| } | |||
| } | |||