| <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> |
| .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%; | |||||
| } | |||||
| 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(); | |||||
| }); | |||||
| }); |
| 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 !== ''; | |||||
| } | |||||
| } | |||||
| import {ClientProfileComponent} from './client-profile/client-profile.component'; | import {ClientProfileComponent} from './client-profile/client-profile.component'; | ||||
| import {E403Component} from './e403/e403.component'; | import {E403Component} from './e403/e403.component'; | ||||
| import {ListAllRewardsComponent} from './list-all-rewards/list-all-rewards.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 = [ | const routes: Routes = [ | ||||
| {path : 'client-loan-list', component: ClientLoanListComponent, canActivate: [AuthGuard] }, | {path : 'client-loan-list', component: ClientLoanListComponent, canActivate: [AuthGuard] }, | ||||
| {path : 'client-profile', component: ClientProfileComponent, canActivate: [AuthGuard] }, | {path : 'client-profile', component: ClientProfileComponent, canActivate: [AuthGuard] }, | ||||
| {path : 'list-all-rewards', component: ListAllRewardsComponent, 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, }, | {path : 'e403', component: E403Component, }, | ||||
| ]; | ]; | ||||
| import { E403Component } from './e403/e403.component'; | import { E403Component } from './e403/e403.component'; | ||||
| import {FileSelectModule, UploadModule} from '@progress/kendo-angular-upload'; | import {FileSelectModule, UploadModule} from '@progress/kendo-angular-upload'; | ||||
| import { ListAllRewardsComponent } from './list-all-rewards/list-all-rewards.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 { RewardUnpaidComponent } from './reward-unpaid/reward-unpaid.component'; | |||||
| import { RewardPaidComponent } from './reward-paid/reward-paid.component'; | |||||
| ClientLoanListComponent, | ClientLoanListComponent, | ||||
| ClientProfileComponent, | ClientProfileComponent, | ||||
| E403Component, | E403Component, | ||||
| ListAllRewardsComponent | |||||
| ListAllRewardsComponent, | |||||
| AdminRewardByBrokerComponent, | |||||
| RewardOverviewComponent, | |||||
| RewardUnpaidComponent, | |||||
| RewardPaidComponent | |||||
| ], | ], | ||||
| imports: [ | imports: [ | ||||
| BrowserModule, | BrowserModule, |
| <kendo-grid | <kendo-grid | ||||
| [groupable]="true" | [groupable]="true" | ||||
| [data]="gridView" | [data]="gridView" | ||||
| [loading]="loading" | |||||
| (groupChange)="groupChange($event)" | (groupChange)="groupChange($event)" | ||||
| > | > | ||||
| <kendo-grid-column field="Id" [groupable]="false"></kendo-grid-column> | <kendo-grid-column field="Id" [groupable]="false"></kendo-grid-column> |
| import { Component, OnInit } from '@angular/core'; | |||||
| import {Component, Input, OnInit} from '@angular/core'; | |||||
| import {HttpClient} from '@angular/common/http'; | import {HttpClient} from '@angular/common/http'; | ||||
| import {AuthService} from '../service/auth.service'; | import {AuthService} from '../service/auth.service'; | ||||
| import {RewardByUserModel} from '../models/reward-by-user.model'; | import {RewardByUserModel} from '../models/reward-by-user.model'; | ||||
| }) | }) | ||||
| export class BrokerRewardComponent implements OnInit { | export class BrokerRewardComponent implements OnInit { | ||||
| @Input() selectedBrokerId = ''; | |||||
| public gridData: RewardByUserModel[] = [] ; | public gridData: RewardByUserModel[] = [] ; | ||||
| public loading = false; | |||||
| public groups: GroupDescriptor[] = [{ field: 'Description' }, { field: 'Item' } ]; | public groups: GroupDescriptor[] = [{ field: 'Description' }, { field: 'Item' } ]; | ||||
| public gridView: DataResult; | public gridView: DataResult; | ||||
| constructor(private http: HttpClient, private auth: AuthService ) { } | constructor(private http: HttpClient, private auth: AuthService ) { } | ||||
| ngOnInit(): void { | ngOnInit(): void { | ||||
| this.loading = true; | |||||
| this.loadBrokerReward(); | |||||
| } | |||||
| private loadBrokerReward(): void { | |||||
| this.gridData = []; | 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 => { | ||||
| rsp.forEach(v => { | rsp.forEach(v => { | ||||
| this.gridData.push(new RewardByUserModel(v)); | this.gridData.push(new RewardByUserModel(v)); | ||||
| }); | }); | ||||
| this.loadRewards(); | this.loadRewards(); | ||||
| this.loading = false; | |||||
| } | } | ||||
| ); | ); | ||||
| } | } | ||||
| } | } | ||||
| private loadRewards(): void { | private loadRewards(): void { | ||||
| this.loading = true; | |||||
| this.gridView = process(this.gridData, { group: this.groups }); | 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(); | |||||
| } | |||||
| } | } |
| <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> |
| 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; | |||||
| } | } |
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit } from '@angular/core'; | ||||
| import {AuthService} from '../service/auth.service'; | import {AuthService} from '../service/auth.service'; | ||||
| import {HttpClient} from '@angular/common/http'; | 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({ | @Component({ | ||||
| selector: 'app-list-all-rewards', | selector: 'app-list-all-rewards', | ||||
| }) | }) | ||||
| export class ListAllRewardsComponent implements OnInit { | 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) { } | constructor(private auth: AuthService, private http: HttpClient) { } | ||||
| ngOnInit(): void { | 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 + '")'; | |||||
| } | |||||
| } | } |
| icon: 'dollar', | icon: 'dollar', | ||||
| items: [ | items: [ | ||||
| { text: 'Start New Loan', icon: 'plus', url: './#edit-loan/' }, | { 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', | text: 'Reward', | ||||
| icon: 'percent', | icon: 'percent', | ||||
| items: [ | 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: 'By Broker', icon: 'table', url: './#list-reward-by-broker' }, | ||||
| { text: '--', separator: 'true' }, | { 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', | icon: 'user', | ||||
| items: [ | 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: 'List All', fa: faIdCard , url: './#list-all-client'}, | ||||
| { text: '--', separator: 'true' }, | { text: '--', separator: 'true' }, | ||||
| { text: 'Broadcast', icon: 'email', url: './#send-to-all-client'}, | { 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 }, | |||||
| ] | |||||
| } | |||||
| ]; | ]; | ||||
| export class RewardVsIncomeModel { | export class RewardVsIncomeModel { | ||||
| Categories: string[]; | Categories: string[]; | ||||
| Data: number[][2]; | |||||
| Data: number[][]; | |||||
| constructor() { | |||||
| this.Data = new Array<number[]>(3); | |||||
| for (let i = 0; i <= 2 ; i++){ | |||||
| this.Data[i] = []; | |||||
| } | |||||
| } | |||||
| } | } |
| <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> |
| kendo-chart { | |||||
| height: calc(100vh - 48px); | |||||
| flex: 0 1 auto; | |||||
| } |
| 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(); | |||||
| }); | |||||
| }); |
| 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]; | |||||
| } | |||||
| } | |||||
| ); | |||||
| } | |||||
| } |
| <p>reward-paid works!</p> |
| 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(); | |||||
| }); | |||||
| }); |
| 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 { | |||||
| } | |||||
| } |
| <p>reward-unpaid works!</p> |
| 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(); | |||||
| }); | |||||
| }); |
| 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 { | |||||
| } | |||||
| } |