refactor rent-time to component

This commit is contained in:
tim-herbst 2021-01-02 15:33:11 +01:00
parent 6d7c40ada6
commit cdea238830
8 changed files with 257 additions and 171 deletions

View File

@ -86,31 +86,7 @@
</div>
<div class="container-borrow-time" fxLayout="row" fxLayoutAlign="center">
<mat-card fxFlex fxLayout="column">
<mat-card-header class="chart-header">
<mat-card-title>Rental Time</mat-card-title>
<mat-card-subtitle>
This chart shows the workload of the currently selected station in relation
of the time of the day. It is visualized at which time of the day a journey begins or ends (blue).
In addition, the average rental duration of the trips is displayed at the given time (green).
</mat-card-subtitle>
</mat-card-header>
<mat-card-content fxFlex fxLayout="row" fxLayoutAlign="center">
<div class="station-dashboard-borrow-time" fxFlex>
<apx-chart
[chart]="timeChartOptions.chart"
[colors]="timeChartOptions.colors"
[dataLabels]="timeChartOptions.dataLabels"
[fill]="timeChartOptions.fill"
[series]="timeChartOptions.series"
[stroke]="timeChartOptions.stroke"
[tooltip]="timeChartOptions.tooltip"
[xaxis]="timeChartOptions.xaxis"
[yaxis]="timeChartOptions.yaxis"></apx-chart>
</div>
</mat-card-content>
</mat-card>
<app-rent-time-chart fxFlex></app-rent-time-chart>
</div>
</mat-sidenav-content>
</mat-sidenav-container>

View File

@ -61,7 +61,7 @@ mat-sidenav-content {
}
.container-borrow-time {
height: 41em;
height: 44em;
margin: 1em 2em;
}

View File

@ -25,6 +25,7 @@ import {DateAdapter, MAT_DATE_FORMATS, NativeDateAdapter} from '@angular/materia
import {formatDate} from '@angular/common';
import {TableComponent} from './table/table.component';
import {RentDurationChartComponent} from "./rent-duration-chart/rent-duration-chart.component";
import {RentTimeChartComponent} from "./rent-time-chart/rent-time-chart.component";
export type ChartOptions = {
title: ApexTitleSubtitle;
@ -79,8 +80,8 @@ const chartHeight = 460;
export class DashboardComponent implements OnInit {
@ViewChild(TableComponent) table: TableComponent;
@ViewChild(RentDurationChartComponent) durationChart: RentDurationChartComponent;
@ViewChild(RentTimeChartComponent) timeChart: RentTimeChartComponent;
public durationChartOptions: Partial<ChartOptions>;
public timeChartOptions: Partial<ChartOptions>;
public bikePointChartOptions: Partial<ChartOptions>;
@ -101,15 +102,6 @@ export class DashboardComponent implements OnInit {
private changeDetectorRefs: ChangeDetectorRef,
private fb: FormBuilder
) {
this.durationChartOptions = {
series: [],
chart: {
type: 'bar'
},
noData: {
text: 'Loading...'
}
};
this.timeChartOptions = {
series: [],
chart: {
@ -241,139 +233,6 @@ export class DashboardComponent implements OnInit {
const initDate = this.maxEndDate.toISOString().substring(0, 10);
this.form.get('daterange').get('start').setValue(initDate);
this.form.get('daterange').get('end').setValue(initDate);
this.service.fetchDashboardStationCharts(this.station.id, initDate, initDate, 'duration').then((source) => {
const numbers = [];
const minutesGroup = [];
source.forEach(value => {
numbers.push(value.number);
minutesGroup.push(value.minutesGroup);
});
this.durationChartOptions = {
series: [
{
name: 'amount of drives',
data: numbers
}
],
chart: {
type: 'bar',
height: chartHeight
},
colors: ['#017bfe'],
plotOptions: {
bar: {
horizontal: false,
columnWidth: '55%',
endingShape: 'flat'
}
},
dataLabels: {
enabled: false
},
stroke: {
show: true,
width: 4,
colors: ['transparent']
},
xaxis: {
title: {
text: 'average rental duration'
},
categories: minutesGroup,
labels: {
formatter: value => {
return value + ' min';
}
}
},
yaxis: {
title: {
text: 'amount of drives'
}
},
fill: {
opacity: 1
}
};
});
this.service.fetchDashboardStationCharts(this.station.id, initDate, initDate, 'time').then((source) => {
const timeFrame = [];
const numbers = [];
const avgDuration = [];
source.forEach(value => {
timeFrame.push(value.timeFrame);
numbers.push(value.number);
avgDuration.push(Math.round(value.avgDuration / 60));
});
this.timeChartOptions = {
series: [
{
name: 'amount of drives',
type: 'bar',
data: numbers
},
{
name: 'average rental duration',
type: 'line',
data: avgDuration
}
],
tooltip: {
enabled: true,
shared: true,
x: {
show: true
}
},
chart: {
toolbar: {
show: false
},
type: 'line',
height: chartHeight,
zoom: {
enabled: true,
}
},
colors: ['#017bfe', '#51ca49'],
dataLabels: {
enabled: false
},
stroke: {
curve: 'straight'
},
xaxis: {
title: {
text: 'time of the day'
},
categories: timeFrame,
tickAmount: 24,
tickPlacement: 'between',
type: 'category'
},
yaxis: [{
title: {
text: 'amount of drives',
},
}, {
opposite: true,
title: {
text: 'average rental duration'
},
labels: {
formatter: (val: number): string => {
return val + ' min';
}
}
}],
legend: {
horizontalAlign: 'left'
},
fill: {
opacity: 1
}
};
});
this.map.initDashboardMap(this.station.lat, this.station.lon, 17);
this.map.drawDashboardStationMarker(this.station);
}
@ -389,6 +248,10 @@ export class DashboardComponent implements OnInit {
this.actualStartDate.toISOString().substring(0, 10),
this.actualEndDate.toISOString().substring(0, 10)
);
this.timeChart.onSubmit(
this.actualStartDate.toISOString().substring(0, 10),
this.actualEndDate.toISOString().substring(0, 10)
);
}

View File

@ -43,6 +43,7 @@ const chartType = 'duration';
styleUrls: ['./rent-duration-chart.component.scss']
})
export class RentDurationChartComponent implements OnInit {
@ViewChild(ChartComponent) chart: ChartComponent;
chartOptions: Partial<ChartOptions>;
@ -71,7 +72,7 @@ export class RentDurationChartComponent implements OnInit {
this.bikePoint = data;
this.maxStartDate = new Date(data.maxStartDate);
this.maxEndDate = new Date(data.maxEndDate);
this.initChart();
this.initChart().catch(error => console.log(error));
});
});
}
@ -88,7 +89,10 @@ export class RentDurationChartComponent implements OnInit {
],
chart: {
type: 'bar',
height: '460'
height: '460',
toolbar: {
show: false
}
},
colors: ['#017bfe'],
plotOptions: {

View File

@ -0,0 +1,26 @@
<mat-card fxFlex fxLayout="column">
<mat-card-header class="chart-header">
<mat-card-title>Rental Time</mat-card-title>
<mat-card-subtitle>
This chart shows the workload of the currently selected station in relation
of the time of the day. It is visualized at which time of the day a journey begins or ends (blue).
In addition, the average rental duration of the trips is displayed at the given time (green).
</mat-card-subtitle>
</mat-card-header>
<mat-card-content fxFlex fxLayout="row" fxLayoutAlign="center">
<div class="station-dashboard-borrow-time" fxFlex>
<apx-chart
[chart]="chartOptions.chart"
[colors]="chartOptions.colors"
[dataLabels]="chartOptions.dataLabels"
[fill]="chartOptions.fill"
[legend]="chartOptions.legend"
[series]="chartOptions.series"
[stroke]="chartOptions.stroke"
[tooltip]="chartOptions.tooltip"
[xaxis]="chartOptions.xaxis"
[yaxis]="chartOptions.yaxis"></apx-chart>
</div>
</mat-card-content>
</mat-card>

View File

@ -0,0 +1,17 @@
.station-dashboard-borrow-duration {
margin: 1em;
}
.mat-card {
padding: 1px 1px 1px;
margin: 10px;
}
.mat-card-title {
margin-top: 1em;
margin-left: 2em;
}
.mat-card-subtitle {
margin-left: 39px;
}

View File

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RentTimeChartComponent } from './rent-time-chart.component';
describe('RentTimeChartComponent', () => {
let component: RentTimeChartComponent;
let fixture: ComponentFixture<RentTimeChartComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RentTimeChartComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(RentTimeChartComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,175 @@
import {Component, OnInit, ViewChild} from '@angular/core';
import {
ApexAxisChartSeries,
ApexChart,
ApexDataLabels,
ApexFill,
ApexLegend,
ApexNoData,
ApexPlotOptions,
ApexStroke,
ApexTitleSubtitle,
ApexTooltip,
ApexXAxis,
ApexYAxis,
ChartComponent
} from 'ng-apexcharts';
import {DashboardService} from '../../service/dashboard.service';
import {ActivatedRoute} from '@angular/router';
import {IDashboardCommonBikePoint} from '../../service/domain/dashboard-common-bike-point';
export type ChartOptions = {
title: ApexTitleSubtitle;
subtitle: ApexTitleSubtitle;
series: ApexAxisChartSeries;
chart: ApexChart;
colors: string[];
dataLabels: ApexDataLabels;
plotOptions: ApexPlotOptions;
yaxis: ApexYAxis | ApexYAxis[];
xaxis: ApexXAxis;
fill: ApexFill;
tooltip: ApexTooltip;
stroke: ApexStroke;
legend: ApexLegend;
noData: ApexNoData;
};
const chartType = 'time';
@Component({
selector: 'app-rent-time-chart',
templateUrl: './rent-time-chart.component.html',
styleUrls: ['./rent-time-chart.component.scss']
})
export class RentTimeChartComponent implements OnInit {
@ViewChild(ChartComponent) chart: ChartComponent;
chartOptions: Partial<ChartOptions>;
bikePoint: IDashboardCommonBikePoint;
maxStartDate: Date;
maxEndDate: Date;
constructor(
private route: ActivatedRoute,
private service: DashboardService
) {
this.chartOptions = {
series: [],
chart: {
type: 'line'
},
noData: {
text: 'Loading...'
}
};
}
ngOnInit(): void {
this.route.params.subscribe(params => {
this.service.fetchDashboardInit(params.id).then(data => {
this.bikePoint = data;
this.maxStartDate = new Date(data.maxStartDate);
this.maxEndDate = new Date(data.maxEndDate);
this.initChart().catch(error => console.log(error));
});
});
}
async initChart(): Promise<void> {
const initDate = this.maxEndDate.toISOString().substring(0, 10);
await this.service.fetchDashboardStationCharts(this.bikePoint.id, initDate, initDate, chartType).then(source => {
this.chartOptions = {
series: [
{
name: 'amount of drives',
type: 'bar',
data: source.map(value => value.number)
},
{
name: 'average rental duration',
type: 'line',
data: source.map(value => Math.round(value.avgDuration / 60))
}
],
tooltip: {
enabled: true,
shared: true,
x: {
show: true
}
},
chart: {
toolbar: {
show: true
},
type: 'line',
height: '495',
zoom: {
enabled: true,
}
},
colors: ['#017bfe', '#51ca49'],
dataLabels: {
enabled: false,
},
stroke: {
curve: 'straight'
},
legend: {
show: true,
offsetY: 8,
itemMargin: {
horizontal: 5
}
},
xaxis: {
title: {
text: 'time of the day',
offsetY: 17
},
categories: source.map(value => value.timeFrame),
tickAmount: 24,
tickPlacement: 'between',
type: 'category'
},
yaxis: [{
title: {
text: 'amount of drives',
},
}, {
opposite: true,
title: {
text: 'average rental duration'
},
labels: {
formatter: (val: number): string => {
return val + ' min';
}
}
}],
fill: {
opacity: 1
}
};
});
await this.chart.updateOptions(this.chartOptions);
}
async onSubmit(actualStartDate: string, actualEndDate: string): Promise<void> {
await this.service.fetchDashboardStationCharts(
this.bikePoint.id,
actualStartDate,
actualEndDate,
chartType
).then(source => {
this.chart.updateSeries([{
data: source.map(value => value.number)
}, {
data: source.map(value => Math.round(value.avgDuration / 60))
}]);
});
}
}