230 lines
6.8 KiB
TypeScript
230 lines
6.8 KiB
TypeScript
import { Component, OnInit, ViewChild } from '@angular/core';
|
|
import { ToastrService } from 'ngx-toastr';
|
|
import { TranslateService } from '@ngx-translate/core';
|
|
import { ApiClientService } from 'src/app/_services/api-client.service';
|
|
import { MapComponent } from 'src/app/_components/map/map.component';
|
|
import { LatLngTuple, Marker } from 'leaflet';
|
|
|
|
@Component({
|
|
selector: 'app-stats',
|
|
templateUrl: './stats-services.component.html',
|
|
styleUrls: ['./stats-services.component.scss']
|
|
})
|
|
export class StatsServicesComponent implements OnInit {
|
|
services: any[] = [];
|
|
serviceNumber = 0;
|
|
servicesFilterStart: Date | undefined;
|
|
servicesFilterEnd: Date | undefined;
|
|
|
|
chartServicesByUserData: any;
|
|
chartServicesByChiefData: any;
|
|
chartServicesByDriverData: any;
|
|
chartServicesByTypeData: any;
|
|
chartServicesByVillageData: any;
|
|
|
|
@ViewChild("servicesMap") servicesMap!: MapComponent;
|
|
|
|
users: any[] = [];
|
|
types: any[] = [];
|
|
|
|
range: (Date | undefined)[] | undefined = undefined;
|
|
lastRange: (Date | undefined)[] | undefined = undefined;
|
|
|
|
constructor(
|
|
private toastr: ToastrService,
|
|
private api: ApiClientService,
|
|
private translate: TranslateService
|
|
) { }
|
|
|
|
ngOnInit(): void {
|
|
Promise.all([
|
|
this.api.get("list"),
|
|
this.api.get("service_types")
|
|
]).then((values: any[]) => {
|
|
this.users = values[0];
|
|
this.types = values[1];
|
|
|
|
this.loadServices();
|
|
}).catch((err) => {
|
|
this.translate.get('edit_service.users_load_failed').subscribe((res: string) => {
|
|
this.toastr.error(res);
|
|
});
|
|
});
|
|
}
|
|
|
|
getUserNameById(id: number) {
|
|
let user = this.users.find((user) => user.id === id);
|
|
if (user) {
|
|
if(user.surname === null) return user.name;
|
|
return user.surname + " " + user.name;
|
|
}
|
|
return "";
|
|
}
|
|
getTypeNameById(id: number) {
|
|
let type = this.types.find((type) => type.id === id);
|
|
if (type) {
|
|
return type.name;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
extractStatsFromServices() {
|
|
let people: Record<number, number> = {};
|
|
let chiefs: Record<number, number> = {};
|
|
let drivers: Record<number, number> = {};
|
|
let types: Record<string, number> = {};
|
|
let villages: Record<string, number> = {};
|
|
let municipalities: Record<string, number> = {};
|
|
|
|
for (let service of this.services) {
|
|
let currPeople: Set<number> = new Set();
|
|
currPeople.add(service.chief_id);
|
|
chiefs[service.chief_id] = (chiefs[service.chief_id] || 0) + 1;
|
|
|
|
for (let person of service.drivers) {
|
|
currPeople.add(person.id);
|
|
drivers[person.id] = (drivers[person.id] || 0) + 1;
|
|
}
|
|
for (let person of service.crew) {
|
|
currPeople.add(person.id);
|
|
}
|
|
|
|
for (let person of currPeople) {
|
|
if (!people[person]) {
|
|
people[person] = 0;
|
|
}
|
|
people[person]++;
|
|
}
|
|
|
|
if (!types[service.type_id]) {
|
|
types[service.type_id] = 0;
|
|
}
|
|
types[service.type_id]++;
|
|
|
|
if (service.place.village === null) service.place.village = this.translate.instant("unknown");
|
|
// Capitalize first letter
|
|
service.place.village = service.place.village.charAt(0).toUpperCase() + service.place.village.slice(1);
|
|
if (!villages[service.place.village]) {
|
|
villages[service.place.village] = 0;
|
|
}
|
|
villages[service.place.village]++;
|
|
}
|
|
|
|
console.log(people, chiefs, drivers, types, villages, municipalities);
|
|
|
|
let peopleLabels: string[] = [], peopleValues: number[] = [];
|
|
Object.entries(people).sort(([,a],[,b]) => b-a).forEach(([key, value]) => {
|
|
peopleLabels.push(this.getUserNameById(parseInt(key)));
|
|
peopleValues.push(value);
|
|
});
|
|
this.chartServicesByUserData = {
|
|
labels: peopleLabels,
|
|
datasets: [
|
|
{
|
|
data: peopleValues,
|
|
}
|
|
]
|
|
};
|
|
|
|
let chiefsLabels: string[] = [], chiefsValues: number[] = [];
|
|
Object.entries(chiefs).sort(([,a],[,b]) => b-a).forEach(([key, value]) => {
|
|
chiefsLabels.push(this.getUserNameById(parseInt(key)));
|
|
chiefsValues.push(value);
|
|
});
|
|
this.chartServicesByChiefData = {
|
|
labels: chiefsLabels,
|
|
datasets: [
|
|
{
|
|
data: chiefsValues,
|
|
}
|
|
]
|
|
};
|
|
|
|
let driversLabels: string[] = [], driversValues: number[] = [];
|
|
Object.entries(drivers).sort(([,a],[,b]) => b-a).forEach(([key, value]) => {
|
|
driversLabels.push(this.getUserNameById(parseInt(key)));
|
|
driversValues.push(value);
|
|
});
|
|
this.chartServicesByDriverData = {
|
|
labels: driversLabels,
|
|
datasets: [
|
|
{
|
|
data: driversValues,
|
|
}
|
|
]
|
|
};
|
|
|
|
let typesLabels: string[] = [], typesValues: number[] = [];
|
|
Object.entries(types).sort(([,a],[,b]) => b-a).forEach(([key, value]) => {
|
|
typesLabels.push(this.getTypeNameById(parseInt(key)));
|
|
typesValues.push(value);
|
|
});
|
|
this.chartServicesByTypeData = {
|
|
labels: typesLabels,
|
|
datasets: [
|
|
{
|
|
data: typesValues,
|
|
}
|
|
]
|
|
};
|
|
|
|
let villagesLabels: string[] = [], villagesValues: number[] = [];
|
|
Object.entries(villages).sort(([,a],[,b]) => b-a).forEach(([key, value]) => {
|
|
villagesLabels.push(key);
|
|
villagesValues.push(value);
|
|
});
|
|
this.chartServicesByVillageData = {
|
|
labels: villagesLabels,
|
|
datasets: [
|
|
{
|
|
data: villagesValues,
|
|
}
|
|
]
|
|
};
|
|
}
|
|
|
|
loadServices() {
|
|
this.api.get("stats/services", {
|
|
from: this.servicesFilterStart ? this.servicesFilterStart.toISOString() : undefined,
|
|
to: this.servicesFilterEnd ? this.servicesFilterEnd.toISOString() : undefined
|
|
}).then((response: any) => {
|
|
this.services = response;
|
|
console.log(this.services);
|
|
|
|
this.serviceNumber = this.services.length;
|
|
|
|
let serviceMapFitBoundsTuple = [];
|
|
this.servicesMap.removeAllMarkers();
|
|
for (let service of this.services) {
|
|
const pos: LatLngTuple = [service.place.lat, service.place.lon];
|
|
serviceMapFitBoundsTuple.push(pos);
|
|
let marker = new Marker(pos, {
|
|
title: service.code
|
|
}).on("click", (e) => {
|
|
console.log(e);
|
|
});
|
|
this.servicesMap.addMarker(marker);
|
|
}
|
|
this.servicesMap.setBounds(serviceMapFitBoundsTuple);
|
|
|
|
this.extractStatsFromServices();
|
|
}).catch((error: any) => {
|
|
console.error(error);
|
|
this.toastr.error(this.translate.instant("Error while loading services"));
|
|
});
|
|
}
|
|
|
|
filterDateRangeChanged($event: Date[]) {
|
|
console.log($event);
|
|
if (typeof($event) !== "object" || ($event !== null && $event.length === 0)) {
|
|
this.servicesFilterStart = undefined;
|
|
this.servicesFilterEnd = undefined;
|
|
} else {
|
|
this.servicesFilterStart = $event[0];
|
|
this.servicesFilterEnd = $event[1];
|
|
}
|
|
if(this.lastRange !== this.range) this.loadServices();
|
|
this.lastRange = this.range;
|
|
}
|
|
}
|