diff --git a/projects/project-3/frontend/src/app/app.module.ts b/projects/project-3/frontend/src/app/app.module.ts
index cf93dc8..43484df 100644
--- a/projects/project-3/frontend/src/app/app.module.ts
+++ b/projects/project-3/frontend/src/app/app.module.ts
@@ -29,6 +29,9 @@ import {MatSlideToggleModule} from '@angular/material/slide-toggle';
import {MatCheckboxModule} from '@angular/material/checkbox';
import {MatTooltipModule} from '@angular/material/tooltip';
import {MatProgressSpinnerModule} from "@angular/material/progress-spinner";
+import { TableComponent } from './dashboard/table/table.component';
+import { RentDurationChartComponent } from './dashboard/rent-duration-chart/rent-duration-chart.component';
+import { RentTimeChartComponent } from './dashboard/rent-time-chart/rent-time-chart.component';
@NgModule({
declarations: [
@@ -36,7 +39,10 @@ import {MatProgressSpinnerModule} from "@angular/material/progress-spinner";
MapComponent,
DashboardComponent,
PopUpComponent,
- AutoRefreshComponent
+ AutoRefreshComponent,
+ TableComponent,
+ RentDurationChartComponent,
+ RentTimeChartComponent
],
imports: [
BrowserModule,
diff --git a/projects/project-3/frontend/src/app/dashboard/table/table.component.html b/projects/project-3/frontend/src/app/dashboard/table/table.component.html
new file mode 100644
index 0000000..18d02db
--- /dev/null
+++ b/projects/project-3/frontend/src/app/dashboard/table/table.component.html
@@ -0,0 +1,76 @@
+
+
+
+ |
+
+
+
+ |
+
+
+ station of rental destination |
+ {{element.stationName}} |
+
+
+
+ number of drives |
+ {{element.number}} |
+
+
+
+ average rental duration |
+ {{humanizeAvgDuration(element.avgDuration)}} |
+
+
+
+ icon on map |
+ |
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+ |
+
+
+ station of rental origin |
+ {{element.stationName}} |
+
+
+
+ number of drives |
+ {{element.number}} |
+
+
+
+ average rental duration |
+ {{humanizeAvgDuration(element.avgDuration)}} |
+
+
+
+ icon on map |
+ |
+
+
+
+
+
+
diff --git a/projects/project-3/frontend/src/app/dashboard/table/table.component.scss b/projects/project-3/frontend/src/app/dashboard/table/table.component.scss
new file mode 100644
index 0000000..e01303d
--- /dev/null
+++ b/projects/project-3/frontend/src/app/dashboard/table/table.component.scss
@@ -0,0 +1,15 @@
+img {
+ width: 60px;
+}
+
+a {
+ color: black;
+}
+
+.dashboard-table-to {
+ margin-right: 1em;
+}
+
+.dashboard-table-from {
+ margin-left: 1em;
+}
diff --git a/projects/project-3/frontend/src/app/dashboard/table/table.component.spec.ts b/projects/project-3/frontend/src/app/dashboard/table/table.component.spec.ts
new file mode 100644
index 0000000..e2f8acc
--- /dev/null
+++ b/projects/project-3/frontend/src/app/dashboard/table/table.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { TableComponent } from './table.component';
+
+describe('TableComponent', () => {
+ let component: TableComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ TableComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(TableComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/project-3/frontend/src/app/dashboard/table/table.component.ts b/projects/project-3/frontend/src/app/dashboard/table/table.component.ts
new file mode 100644
index 0000000..0e6f0ea
--- /dev/null
+++ b/projects/project-3/frontend/src/app/dashboard/table/table.component.ts
@@ -0,0 +1,140 @@
+import {Component, Input, OnInit} from '@angular/core';
+import {MatTableDataSource} from '@angular/material/table';
+import {IDashboardCommonBikePoint} from '../../service/domain/dashboard-common-bike-point';
+import {SelectionModel} from '@angular/cdk/collections';
+import {MatCheckboxChange} from '@angular/material/checkbox';
+import stht from 'seconds-to-human-time';
+import {MapService} from '../../service/map.service';
+import {DashboardService} from '../../service/dashboard.service';
+import {ActivatedRoute} from '@angular/router';
+
+@Component({
+ selector: 'app-table',
+ templateUrl: './table.component.html',
+ styleUrls: ['./table.component.scss']
+})
+export class TableComponent implements OnInit {
+ displayedColumnsTo: string[] = ['select', 'endStationName', 'number', 'avgDuration', 'marker'];
+ displayedColumnsFrom: string[] = ['select', 'startStationName', 'number', 'avgDuration', 'marker'];
+ stationToSource = new MatTableDataSource();
+
+ iterableToSource: any[];
+ stationFromSource = new MatTableDataSource();
+ iterableFromSource: any[];
+ selectionModel = new SelectionModel(true, []);
+ colors = ['black', 'gray', 'green', 'orange', 'purple', 'red'];
+ bikePoint: IDashboardCommonBikePoint;
+ maxStartDate: Date;
+ maxEndDate: Date;
+
+ constructor(
+ private route: ActivatedRoute,
+ private map: MapService,
+ private service: DashboardService
+ ) {
+ }
+
+ ngOnInit(): void {
+ this.route.params.subscribe(params => {
+ this.selectionModel.clear();
+ this.colors = ['black', 'gray', 'green', 'orange', 'purple', 'red'];
+ this.service.fetchDashboardInit(params.id).then(data => {
+ this.bikePoint = data;
+ this.maxStartDate = new Date(data.maxStartDate);
+ this.maxEndDate = new Date(data.maxEndDate);
+ this.initTable();
+ });
+ });
+ }
+
+ async initTable(): Promise {
+ const initDate = this.maxEndDate.toISOString().substring(0, 10);
+ await this.service.fetchDashboardStationTo(this.bikePoint.id, initDate, initDate).then(source => {
+ this.stationToSource = this.setBikePointColorToSource(source);
+ this.iterableToSource = source;
+ });
+ await this.service.fetchDashboardStationFrom(this.bikePoint.id, initDate, initDate).then(source => {
+ this.stationFromSource = this.setBikePointColorFromSource(source);
+ this.iterableFromSource = source;
+ });
+ }
+
+ async onSubmit(actualStartDate: string, actualEndDate: string): Promise {
+ await this.service.fetchDashboardStationTo(this.bikePoint.id, actualStartDate, actualEndDate).then((source) => {
+ this.colors = ['black', 'gray', 'green', 'orange', 'purple', 'red'];
+ this.stationToSource = this.setBikePointColorToSource(source);
+ this.iterableToSource = source;
+ });
+ await this.service.fetchDashboardStationFrom(this.bikePoint.id, actualStartDate, actualEndDate).then((source) => {
+ this.stationFromSource = this.setBikePointColorFromSource(source);
+ this.iterableFromSource = source;
+ });
+ }
+
+ public drawIconInTable(bikePoint: any): string {
+ return `../../assets/bike-point-${bikePoint.color}.png`;
+ }
+
+ humanizeAvgDuration(avgDuration: number): string {
+ return stht(avgDuration);
+ }
+
+ selectRow(selection: MatCheckboxChange, row): void {
+ const markerToDisplay = [];
+ this.iterableToSource.forEach(point => {
+ if (point.stationId === row.stationId) {
+ this.selectionModel.toggle(point);
+ }
+ });
+ this.iterableFromSource.forEach(point => {
+ if (point.stationId === row.stationId) {
+ this.selectionModel.toggle(point);
+ }
+ });
+ this.selectionModel.selected.forEach(point => {
+ markerToDisplay.push(point);
+ });
+ this.map.drawTableStationMarker(markerToDisplay);
+ }
+
+ setBikePointColorToSource(source): any {
+ for (const station of source) {
+ if (station.stationId === this.bikePoint.id) {
+ station.color = 'blue';
+ continue;
+ }
+ station.color = this.getRandomColor();
+ }
+ return source;
+ }
+
+ setBikePointColorFromSource(source): any {
+ for (const station of source) {
+ if (station.stationId === this.bikePoint.id) {
+ station.color = 'blue';
+ continue;
+ }
+ for (const to of this.iterableToSource) {
+ if (station.stationId === to.stationId) {
+ station.color = to.color;
+ break;
+ }
+ }
+ if (!station.color) {
+ station.color = this.getRandomColor();
+ }
+ }
+ return source;
+ }
+
+ getRandomColor(): string {
+ const color = this.colors[Math.floor(Math.random() * this.colors.length)];
+ this.colors = this.colors.filter(c => c !== color);
+ return color;
+ }
+
+ isCheckBoxDisable(row): boolean {
+ return row.stationId === this.bikePoint.id;
+ }
+
+}