diff --git a/CHANGELOG.md b/CHANGELOG.md index a5859ba..35748e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ # Next Release * Changed Story Trail choosing to modals +* Revamped snippets and graph widgets on customer dashboard +* Added local purchase pie chart for customer dashboard +* Added week by week purchase list for customer dashboard +* Added sector purchase amount list for customer dashboard # v0.0.7 diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 07d74ad..0f257e7 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -21,7 +21,10 @@ import { CustomerGuard } from './_guards/customer.guard'; import { ApiService } from './providers/api-service'; import { OrgGraphsService } from './providers/org-graphs.service'; +import { CustGraphsService } from './providers/cust-graphs.service'; import { OrgSnippetsService } from './providers/org-snippets.service'; +import { CustSnippetsService } from './providers/cust-snippets.service'; +import { CustPiesService } from './providers/cust-pies.service'; // Layouts import { FullLayoutComponent } from './layouts/full-layout.component'; @@ -65,6 +68,9 @@ import { DashboardModule } from './dashboard/dashboard.module'; ApiService, OrgGraphsService, OrgSnippetsService, + CustGraphsService, + CustSnippetsService, + CustPiesService, { provide: LocationStrategy, useClass: HashLocationStrategy diff --git a/src/app/dashboard/dashboard-customer.component.html b/src/app/dashboard/dashboard-customer.component.html index 6a7c209..5be3628 100644 --- a/src/app/dashboard/dashboard-customer.component.html +++ b/src/app/dashboard/dashboard-customer.component.html @@ -1,129 +1,200 @@
-
- - -
+
-
-
+
+ + +
+
+
+
+ +
+
+
-
{{ basicStats.today_sum | currency:'GBP':'symbol':'1.2-2' }}
-
Total Today
- +
+
+
    +
  • + This Week + {{ (weekPurchaseList.week_0 || 0 ) }} ({{ (weekPurchaseList.week_0 || 0 ) / maxPurchase | percent:'1.0-0' }}) +
    +
    +
    +
    +
    +
  • +
  • + Last Week + {{ weekPurchaseList.week_1 || 0 }} ({{ (weekPurchaseList.week_1 || 0 ) / maxPurchase | percent:'1.0-0' }}) +
    +
    +
    +
    +
    +
  • +
  • + 2 Weeks Ago + {{ weekPurchaseList.week_2 || 0 }} ({{ (weekPurchaseList.week_2 || 0 ) / maxPurchase | percent:'1.0-0' }}) +
    +
    +
    +
    +
    +
  • +
  • + 3 Weeks Ago + {{ weekPurchaseList.week_3 || 0 }} ({{ (weekPurchaseList.week_3 || 0 ) / maxPurchase | percent:'1.0-0' }}) +
    +
    +
    +
    +
    +
  • +
  • + 4 Weeks Ago + {{ weekPurchaseList.week_4 || 0 }} ({{ (weekPurchaseList.week_4 || 0 ) / maxPurchase | percent:'1.0-0' }}) +
    +
    +
    +
    +
    +
  • +
  • + 5 Weeks Ago + {{ weekPurchaseList.week_5 || 0 }} ({{ (weekPurchaseList.week_5 || 0 ) / maxPurchase | percent:'1.0-0' }}) +
    +
    +
    +
    +
    +
  • +
  • + 6 Weeks Ago + {{ weekPurchaseList.week_6 || 0 }} ({{ (weekPurchaseList.week_6 || 0 ) / maxPurchase | percent:'1.0-0' }}) +
    +
    +
    +
    +
    +
  • +
- Lorem ipsum dolor sit amet enim. -->
-
-
+
+
-
{{ basicStats.today_sum / (basicStats.today_count ? basicStats.today_count : 1) | currency:'GBP':'symbol':'1.2-2' }}
-
Avg. Spend Today
- +
+
+
    +
  • + +
    +
    Sector {{ sectorLetters[0] || 'N/A' }}
    +
    {{ sectorNames [sectorLetters[0]] }}
    +
    +
    +
    Bought from Sector
    + {{ sectorPurchases[0] || 'N/A' }} +
    +
  • +
  • + +
    +
    Sector {{ sectorLetters[1] || 'N/A' }}
    + {{ sectorNames [sectorLetters[1]] || 'N/A' }} +
    +
    +
    Bought from Sector
    + {{ sectorPurchases[1] || 'N/A' }} +
    +
  • +
  • + +
    +
    Sector {{ sectorLetters[2] || 'N/A' }}
    + {{ sectorNames [sectorLetters[2]] || 'N/A' }} +
    +
    +
    Bought from Sector
    + {{ sectorPurchases[2] || 'N/A' }} +
    +
  • +
  • + +
    +
    Sector {{ sectorLetters[3] || 'N/A' }}
    + {{ sectorNames [sectorLetters[3]] || 'N/A' }} +
    +
    +
    Bought from Sector
    + {{ sectorPurchases[3] || 'N/A' }} +
    +
  • +
  • + +
    +
    Sector {{ sectorLetters[4] || 'N/A' }}
    + {{ sectorNames [sectorLetters[4]] || 'N/A' }} +
    +
    +
    Bought from Sector
    + {{ sectorPurchases[4] || 'N/A' }} +
    +
  • +
  • + +
    +
    Sector {{ sectorLetters[5] || 'N/A' }}
    + {{ sectorNames [sectorLetters[5]] || 'N/A' }} +
    +
    +
    Bought from Sector
    + {{ sectorPurchases[5] || 'N/A' }} +
    +
  • +
  • + +
    +
    Sector {{ sectorLetters[6] || 'N/A' }}
    + {{ sectorNames [sectorLetters[6]] || 'N/A' }} +
    +
    +
    Bought from Sector
    + {{ sectorPurchases[6] || 'N/A' }} +
    +
  • +
- Lorem ipsum dolor sit amet enim. --> -
-
-
-
-
-
-
{{ basicStats.week_sum | currency:'GBP':'symbol':'1.2-2' }}
-
Last Week Total
- -
-
-
-
-
-
-
{{ basicStats.week_sum / (basicStats.week_count ? basicStats.week_count : 1) | currency:'GBP':'symbol':'1.2-2' }}
-
Last Week Avg. Spend
- -
-
-
-
-
-
-
{{ basicStats.month_sum | currency:'GBP':'symbol':'1.2-2' }}
-
Last Month Total
- -
-
-
-
-
-
-
{{ basicStats.month_sum / (basicStats.month_count ? basicStats.month_count : 1) | currency:'GBP':'symbol':'1.2-2' }}
-
Last Month Avg. Spend
- -
-
-
-
-
-
-
{{ basicStats.user_sum | currency:'GBP':'symbol':'1.2-2' }}
-
User Total
- -
-
-
-
-
-
-
{{ basicStats.user_sum / (basicStats.user_count ? basicStats.user_count : 1) | currency:'GBP':'symbol':'1.2-2' }}
-
User Avg. Spend
-
diff --git a/src/app/dashboard/dashboard-customer.component.ts b/src/app/dashboard/dashboard-customer.component.ts index 39230e3..e781f78 100644 --- a/src/app/dashboard/dashboard-customer.component.ts +++ b/src/app/dashboard/dashboard-customer.component.ts @@ -2,15 +2,14 @@ import { Directive, Component, OnInit } from '@angular/core'; import { ApiService } from '../providers/api-service'; import { Router } from '@angular/router'; import { GraphWidget } from '../widgets/graph-widget.component'; +import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component'; +import { PiePanel } from '../panels/pie-panel.component'; +import { DataType } from '../shared/data-types.enum'; @Component({ templateUrl: 'dashboard-customer.component.html' }) export class DashboardCustomerComponent implements OnInit { - customersThisMonth: any; - moneySpentThisMonth: any; - pointsTotal: any; - averageTransactionToday: any; /* Setting up dashboard's main variables*/ name: any; @@ -19,27 +18,106 @@ export class DashboardCustomerComponent implements OnInit { trends: any; myRank: any; username: any; + maxPurchase: number = 0; - basicStats = { - today_sum: 0, - today_count: 0, - week_sum: 0, - week_count: 0, - month_sum: 0, - month_count: 0, - user_sum: 0, - user_count: 0, - global_sum: 0, - global_count: 0, - user_position: 0, + weekPurchaseList = { + week_0: 0, + week_1: 0, + week_2: 0, + week_3: 0, + week_4: 0, + week_5: 0, + week_6: 0, }; + sectorNames = { + A: 'Agriculture, Forestry & Fishing', + B: 'Mining & Quarrying', + C: 'Manufacturing', + D: 'Electricity, Gas, Steam & Air Conditioning', + E: 'Water & Waste Management', + F: 'Construction', + G: 'Wholesale & Retail Trade', + H: 'Transportation & Storage', + I: 'Accomodation & Food Services', + J: 'Information & Communication', + K: 'Financial & Insurance Activities', + L: 'Real Estate', + M: 'Professional, Scientfic & Technical', + N: 'Administrative & Support Services', + O: 'Public Administration, Defence & Social Security', + P: 'Education', + Q: 'Human Health & Social Work', + R: 'Arts, Entertainment & Recreation', + S: 'Other Service Activities', + T: 'Household Domestic Business', + } + + sectorIcons = { + A: 'icon-drop', + B: 'icon-diamond', + C: 'icon-settings', + D: 'icon-energy', + E: 'icon-trash', + F: 'icon-wrench', + G: 'icon-tag', + H: 'icon-speedometer', + I: 'icon-cup', + J: 'icon-globe', + K: 'icon-credit-card', + L: 'icon-graph', + M: 'icon-chemistry', + N: 'icon-drawer', + O: 'icon-pie-chart', + P: 'icon-graduation', + Q: 'icon-support', + R: 'icon-film', + S: 'icon-calendar', + T: 'icon-home', + } + + sectorLetters: string[] = []; + sectorPurchases: number[] = []; + + sectorList: any; + + // Graph widgets + public widgetList = [ + { + type: 'graph', + name: 'total_last_week', + icon: 'icon-diamond', + title: 'Last Week Total', + dataType: DataType.currency, + }, + { + type: 'graph', + name: 'avg_spend_last_week', + icon: 'icon-diamond', + title: 'Last Week Avg. Spend', + dataType: DataType.currency, + }, + { + type: 'graph', + name: 'total_last_month', + title: 'Last Month Total', + dataType: DataType.currency, + }, + { + type: 'graph', + name: 'avg_spend_last_month', + title: 'Last Month Avg. Spend', + dataType: DataType.currency, + }, + ]; + constructor( private api: ApiService, ) { this.api.basicStats().subscribe( result => { - this.basicStats = result; + this.setWeekPurchaseList(result.weeks); + this.setSectorList(result.sectors); }, error => { console.log('Retrieval Error'); @@ -48,6 +126,28 @@ export class DashboardCustomerComponent implements OnInit { ); } + public setWeekPurchaseList (data: any) { + this.weekPurchaseList = { + week_0: data.purchases[0], + week_1: data.purchases[1], + week_2: data.purchases[2], + week_3: data.purchases[3], + week_4: data.purchases[4], + week_5: data.purchases[5], + week_6: data.purchases[6], + }; + this.maxPurchase = Object.keys(this.weekPurchaseList).map(key => this.weekPurchaseList[key]).reduce((a,b) => { + if (! a) { a = 0 } + if (! b) { b = 0 } + return Math.max(a,b); + }); + } + + public setSectorList (data: any) { + this.sectorLetters = Object.keys(data.sectors).map(key => data.sectors[key]); + this.sectorPurchases = Object.keys(data.purchases).map(key => data.purchases[key]); + } + ngOnInit(): void { } } diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html index 4ee858b..ff6f092 100644 --- a/src/app/dashboard/dashboard.component.html +++ b/src/app/dashboard/dashboard.component.html @@ -6,7 +6,8 @@ [graphName]="widget.name" [graphTitle]="widget.title" [graphIcon]="widget.icon" - [dataType]="widget.dataType"> + [dataType]="widget.dataType"> +
diff --git a/src/app/dashboard/dashboard.module.ts b/src/app/dashboard/dashboard.module.ts index 0e5302b..d6fcfca 100644 --- a/src/app/dashboard/dashboard.module.ts +++ b/src/app/dashboard/dashboard.module.ts @@ -23,7 +23,9 @@ import { TrailMapComponent } from './trail-map.component'; import { GraphWidget } from '../widgets/graph-widget.component'; import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component'; +import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component'; import { GraphPanel } from '../panels/graph-panel.component'; +import { PiePanel } from '../panels/pie-panel.component'; import { DashboardRoutingModule } from './dashboard.routing'; import { OrgResultComponent } from '../shared/org-result.component'; @@ -69,7 +71,9 @@ import { environment } from '../../environments/environment'; FeedbackComponent, GraphWidget, OrgBarSnippetComponent, + CustBarSnippetComponent, GraphPanel, + PiePanel, ], providers: [ CurrencyPipe, diff --git a/src/app/panels/pie-panel.component.html b/src/app/panels/pie-panel.component.html new file mode 100644 index 0000000..eb0c194 --- /dev/null +++ b/src/app/panels/pie-panel.component.html @@ -0,0 +1,27 @@ +
+
+
+
+

Local Purchases

+
+
+ +
+
+
+ +
+
+
diff --git a/src/app/panels/pie-panel.component.ts b/src/app/panels/pie-panel.component.ts new file mode 100644 index 0000000..bae839f --- /dev/null +++ b/src/app/panels/pie-panel.component.ts @@ -0,0 +1,57 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { CustPiesService } from '../providers/cust-pies.service'; +import { DataType } from '../shared/data-types.enum'; +import { ChartData } from '../_interfaces/chart-data'; + +@Component({ + selector: 'panel-pie', + templateUrl: 'pie-panel.component.html', +}) +export class PiePanel implements OnInit { + + public chartType = 'doughnut'; + public chartLegend = true; + public doughnutChartLabels: string[] = []; + public doughnutChartData: number[] = []; + + + //Old + + // public mainChartElements = 7; + + constructor( + private pieService: CustPiesService, + ) { } + + public ngOnInit(): void { + this.pieService.getPie() + .subscribe( result => this.setData(result.pie) ); + } + + private setData(data: any) { + this.doughnutChartData = Object.keys(data).map(key => data[key]); + // setTimeout is currently a workaround for ng2-charts labels + setTimeout(() => this.doughnutChartLabels = Object.keys(data), 0); + } + + // convert Hex to RGBA + public convertHex(hex: string, opacity: number) { + hex = hex.replace('#', ''); + const r = parseInt(hex.substring(0, 2), 16); + const g = parseInt(hex.substring(2, 4), 16); + const b = parseInt(hex.substring(4, 6), 16); + + const rgba = 'rgba(' + r + ', ' + g + ', ' + b + ', ' + opacity / 100 + ')'; + return rgba; + } + + // events + public chartClicked(e: any): void { + console.log(e); + } + + public chartHovered(e: any): void { + console.log(e); + } + +} diff --git a/src/app/providers/cust-graphs.service.ts b/src/app/providers/cust-graphs.service.ts new file mode 100644 index 0000000..e03da37 --- /dev/null +++ b/src/app/providers/cust-graphs.service.ts @@ -0,0 +1,14 @@ +import { Injectable } from '@angular/core'; +import { ApiService } from './api-service'; + +@Injectable() +export class CustGraphsService { + private custGraphUrl = '/v1/customer/graphs'; + + constructor(private api: ApiService) { } + + public getGraph(name: string, data: any = {}) { + data.graph = name; + return this.api.post(this.custGraphUrl, data); + } +} diff --git a/src/app/providers/cust-pies.service.ts b/src/app/providers/cust-pies.service.ts new file mode 100644 index 0000000..4608369 --- /dev/null +++ b/src/app/providers/cust-pies.service.ts @@ -0,0 +1,14 @@ +import { Injectable } from '@angular/core'; +import { ApiService } from './api-service'; +import { Observable } from 'rxjs/Rx'; + +@Injectable() +export class CustPiesService { + private custPieUrl = '/v1/customer/pies'; + + constructor(private api: ApiService) { } + + public getPie(): Observable { + return this.api.post(this.custPieUrl); + } +} diff --git a/src/app/providers/cust-snippets.service.ts b/src/app/providers/cust-snippets.service.ts new file mode 100644 index 0000000..9c75c5e --- /dev/null +++ b/src/app/providers/cust-snippets.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { ApiService } from './api-service'; +import { Observable } from 'rxjs/Rx'; + +@Injectable() +export class CustSnippetsService { + private custSnippetsUrl = '/v1/customer/snippets'; + + constructor(private api: ApiService) { } + + // This endpoint should mimic basicStats + public getData(): Observable { + return this.api.post(this.custSnippetsUrl); + } +} diff --git a/src/app/providers/org-graphs.service.ts b/src/app/providers/org-graphs.service.ts index 859361c..d19a53b 100644 --- a/src/app/providers/org-graphs.service.ts +++ b/src/app/providers/org-graphs.service.ts @@ -3,7 +3,7 @@ import { ApiService } from './api-service'; @Injectable() export class OrgGraphsService { - private orgGraphUrl = '/v1/organisation/graphs'; + private orgGraphUrl = '/v1/customer/graphs'; constructor(private api: ApiService) { } diff --git a/src/app/snippets/cust-snippet-bar.component.html b/src/app/snippets/cust-snippet-bar.component.html new file mode 100644 index 0000000..80a44ef --- /dev/null +++ b/src/app/snippets/cust-snippet-bar.component.html @@ -0,0 +1,27 @@ +
+ +
diff --git a/src/app/snippets/cust-snippet-bar.component.ts b/src/app/snippets/cust-snippet-bar.component.ts new file mode 100644 index 0000000..93ac86d --- /dev/null +++ b/src/app/snippets/cust-snippet-bar.component.ts @@ -0,0 +1,26 @@ +import { Component, OnInit } from '@angular/core'; +import { CustSnippetsService } from '../providers/cust-snippets.service'; + +@Component({ + selector: 'snippet-bar-cust', + templateUrl: 'cust-snippet-bar.component.html', +}) +export class CustBarSnippetComponent implements OnInit { + + public userSum = 0; + public userPosition = 0; + + constructor( + private snippetsService: CustSnippetsService, + ) { } + + public ngOnInit(): void { + this.snippetsService.getData() + .subscribe( + result => { + this.userSum = result.snippets.user_sum; + this.userPosition = result.snippets.user_position; + } + ); + } +} diff --git a/src/app/widgets/graph-widget.component.ts b/src/app/widgets/graph-widget.component.ts index 3d99096..8c5b55d 100644 --- a/src/app/widgets/graph-widget.component.ts +++ b/src/app/widgets/graph-widget.component.ts @@ -35,12 +35,21 @@ export class GraphWidget implements OnInit { maintainAspectRatio: false, scales: { xAxes: [{ + type: 'time', + time: { + unit: 'day', + displayFormats: { + day: 'MMM D', + }, + tooltipFormat: 'MMM D', + }, gridLines: { color: 'transparent', zeroLineColor: 'transparent' }, ticks: { fontSize: 2, + source: 'data', fontColor: 'transparent', } @@ -106,6 +115,12 @@ export class GraphWidget implements OnInit { private setData(data: any) { this.setChartData(data.data); this.setChartLabels(data.labels); + this.setChartBounds(data.bounds); + } + + private setChartBounds(data) { + this.lineChartOptions.scales.xAxes[0].time.max = data.max; + this.lineChartOptions.scales.xAxes[0].time.min = data.min; } private setChartData(data: Array) {