integrasi dashboard energy monitoring
This commit is contained in:
parent
3f1c97ebe4
commit
38c936b389
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,63 @@
|
||||||
|
:host ::ng-deep .donut-chart1 .ct-series-a .ct-slice-donut {
|
||||||
|
stroke: green;
|
||||||
|
stroke-width: 50px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .donut-chart1 .ct-series-b .ct-slice-donut {
|
||||||
|
stroke: yellow;
|
||||||
|
stroke-width: 50px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .donut-chart1 .ct-series-c .ct-slice-donut {
|
||||||
|
stroke: orange;
|
||||||
|
stroke-width: 50px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .donut-chart1 .ct-series-d .ct-slice-donut {
|
||||||
|
stroke: red;
|
||||||
|
stroke-width: 50px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .donut-chart1 .ct-series-e .ct-slice-donut {
|
||||||
|
stroke: darkred;
|
||||||
|
stroke-width: 50px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .donut-chart2 .ct-series-a .ct-slice-donut {
|
||||||
|
stroke: #8a8a8a;
|
||||||
|
stroke-width: 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .donut-chart2 .ct-series-b .ct-slice-donut {
|
||||||
|
stroke: #bef264;
|
||||||
|
stroke-width: 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .donut-chart2 {
|
||||||
|
-webkit-filter: drop-shadow(0px 10px 11px rgba(187, 187, 187)) !important;
|
||||||
|
filter: drop-shadow(0px 10px 11px rgba(187, 187, 187));
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .donut-chart2 .ct-label {
|
||||||
|
fill: #111010;
|
||||||
|
color: rgba(0, 0, 0, 0.4);
|
||||||
|
font-size: 1.75rem;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-point {
|
||||||
|
stroke: #bef264;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-line {
|
||||||
|
stroke: #bef264;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-area {
|
||||||
|
fill: #bef264;
|
||||||
|
fill-opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .sp-line-total-cost .ct-point {
|
||||||
|
stroke-width: 0px;
|
||||||
|
}
|
|
@ -1,33 +1,108 @@
|
||||||
<div class="app-content content bg-maintenance-image">
|
<div class="app-content content">
|
||||||
<div class="content-wrapper">
|
<div class="content-wrapper">
|
||||||
|
<div class="content-header row mb-1">
|
||||||
|
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||||
|
</div>
|
||||||
<div class="content-body">
|
<div class="content-body">
|
||||||
<section class="flexbox-container">
|
<section>
|
||||||
<div class="col-12 d-flex align-items-center justify-content-center">
|
<div class="row">
|
||||||
<div class="col-md-4 col-10 box-shadow-2 p-0">
|
<div class="col-lg-4 col-12">
|
||||||
<div class="card border-grey border-lighten-3 px-1 py-1 box-shadow-3 m-0">
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4 class="card-title text-center">Temperature and Humidity</h4>
|
||||||
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<span class="card-title text-center">
|
<div class="card-block">
|
||||||
<img src="../../../../assets/images/logo/logo-dark-lg.png" class="img-fluid mx-auto d-block pt-2"
|
<div class="donut-chart2" style="height: 150px !important">
|
||||||
width="250" alt="logo">
|
<x-chartist
|
||||||
</span>
|
*ngIf="donutChart2"
|
||||||
|
[data]="donutChart2.data"
|
||||||
|
[type]="donutChart2.type"
|
||||||
|
[options]="donutChart2.options"
|
||||||
|
[responsiveOptions]="donutChart2.responsiveOptions"
|
||||||
|
[events]="donutChart2.events"
|
||||||
|
></x-chartist>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4 col-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4 class="card-title text-center">Air Quality</h4>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="donut-chart1" style="height: 150px !important">
|
||||||
|
<x-chartist
|
||||||
|
*ngIf="donutChart1"
|
||||||
|
[data]="donutChart1.data"
|
||||||
|
[type]="donutChart1.type"
|
||||||
|
[options]="donutChart1.options"
|
||||||
|
[responsiveOptions]="donutChart1.responsiveOptions"
|
||||||
|
[events]="donutChart1.events"
|
||||||
|
></x-chartist>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="text-center"
|
||||||
|
style="
|
||||||
|
position: absolute;
|
||||||
|
top: 80%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
class="display-4 blue-grey darken-1"
|
||||||
|
style="font-size: 2em"
|
||||||
|
>
|
||||||
|
76 %
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4 col-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4 class="card-title text-center">Comparison of Actual Costs and Estimated Costs</h4>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="d-flex align-items-center mb-2">
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<ngb-progressbar
|
||||||
|
height="45px"
|
||||||
|
type="danger"
|
||||||
|
[value]="89"
|
||||||
|
></ngb-progressbar>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ml-2 d-flex align-items-center"
|
||||||
|
style="height: 20px"
|
||||||
|
>
|
||||||
|
<span class="text-bold-600">1.234.242</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<ngb-progressbar
|
||||||
|
height="45px"
|
||||||
|
type="success"
|
||||||
|
[value]="50"
|
||||||
|
></ngb-progressbar>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ml-2 d-flex align-items-center"
|
||||||
|
style="height: 20px"
|
||||||
|
>
|
||||||
|
<span class="text-bold-600">1.545.232</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body text-center">
|
|
||||||
<h3>Coming Soon</h3>
|
|
||||||
<p>We're sorry for the inconvenience.
|
|
||||||
<br> Please check back later.</p>
|
|
||||||
<div class="mt-2"><i class="la la-cog spinner font-large-2"></i></div>
|
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
|
||||||
<!-- <p class="socialIcon card-text text-center pt-2 pb-2">
|
|
||||||
<a [routerLink]="" class="btn btn-social-icon mr-1 mb-1 btn-outline-facebook"><span
|
|
||||||
class="la la-facebook"></span></a>
|
|
||||||
<a [routerLink]="" class="btn btn-social-icon mr-1 mb-1 btn-outline-twitter"><span
|
|
||||||
class="la la-twitter"></span></a>
|
|
||||||
<a [routerLink]="" class="btn btn-social-icon mr-1 mb-1 btn-outline-linkedin"><span
|
|
||||||
class="la la-linkedin font-medium-4"></span></a>
|
|
||||||
<a [routerLink]="" class="btn btn-social-icon mr-1 mb-1 btn-outline-github"><span
|
|
||||||
class="la la-github font-medium-4"></span></a>
|
|
||||||
</p> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,6 +14,21 @@ export class CostManagementComponent implements OnInit{
|
||||||
searchTerm: string = "";
|
searchTerm: string = "";
|
||||||
rows: any = [];
|
rows: any = [];
|
||||||
|
|
||||||
|
donutChart1: any;
|
||||||
|
donutChart2: any;
|
||||||
|
dataChart = {
|
||||||
|
donut: {
|
||||||
|
series: [50, 50],
|
||||||
|
labels: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
dataChart2 = {
|
||||||
|
donut: {
|
||||||
|
series: [50, 50],
|
||||||
|
labels: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
barChart: any;
|
barChart: any;
|
||||||
dataBar = {
|
dataBar = {
|
||||||
"Bar": {
|
"Bar": {
|
||||||
|
@ -65,6 +80,50 @@ export class CostManagementComponent implements OnInit{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.donutChart1 = {
|
||||||
|
type: "Pie",
|
||||||
|
data: this.dataChart.donut,
|
||||||
|
options: {
|
||||||
|
fullwidth: true,
|
||||||
|
height: "300px",
|
||||||
|
donut: true,
|
||||||
|
donutWidth: 70,
|
||||||
|
startAngle: 270,
|
||||||
|
total: 200,
|
||||||
|
showLabel: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
this.donutChart2 = {
|
||||||
|
type: "Pie",
|
||||||
|
data: this.dataChart2.donut,
|
||||||
|
options: {
|
||||||
|
chartPadding: 0,
|
||||||
|
fullwidth: true,
|
||||||
|
height: "150px",
|
||||||
|
donut: true,
|
||||||
|
showLabel: true,
|
||||||
|
startAngle: 0,
|
||||||
|
labelInterpolationFnc: function (value) {
|
||||||
|
const total = 82;
|
||||||
|
return total + "C";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
draw(data: any): void {
|
||||||
|
if (data.type === "label") {
|
||||||
|
if (data.index === 0) {
|
||||||
|
data.element.attr({
|
||||||
|
dx: data.element.root().width() / 2,
|
||||||
|
dy: data.element.root().height() / 2,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data.element.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchData() {
|
fetchData() {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<div class="media d-flex">
|
<div class="media d-flex">
|
||||||
<div class="media-body text-left">
|
<div class="media-body text-left">
|
||||||
<h5>Electricity</h5>
|
<h5>Electricity</h5>
|
||||||
<h3 class="danger">278 Kwh</h3>
|
<h3 class="danger">{{ topCard?.kwh_consumption }} Kwh</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="align-self-center">
|
<div class="align-self-center">
|
||||||
<i class="icon-energy danger font-large-2 float-right"></i>
|
<i class="icon-energy danger font-large-2 float-right"></i>
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
<div class="media d-flex">
|
<div class="media d-flex">
|
||||||
<div class="media-body text-left">
|
<div class="media-body text-left">
|
||||||
<h5>Water</h5>
|
<h5>Water</h5>
|
||||||
<h3 class="success">156</h3>
|
<h3 class="success">{{ topCard?.water_consumption }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="align-self-center">
|
<div class="align-self-center">
|
||||||
<i
|
<i
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
<div class="media d-flex">
|
<div class="media d-flex">
|
||||||
<div class="media-body text-left">
|
<div class="media-body text-left">
|
||||||
<h5>Device</h5>
|
<h5>Device</h5>
|
||||||
<h3 class="warning">{{ device }}</h3>
|
<h3 class="warning">{{ topCard?.total_device }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="align-self-center">
|
<div class="align-self-center">
|
||||||
<i class="icon-bulb warning font-large-2 float-right"></i>
|
<i class="icon-bulb warning font-large-2 float-right"></i>
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
<div class="media d-flex">
|
<div class="media d-flex">
|
||||||
<div class="media-body text-left">
|
<div class="media-body text-left">
|
||||||
<h5>Room</h5>
|
<h5>Room</h5>
|
||||||
<h3 class="info">{{ room }}</h3>
|
<h3 class="info">{{ topCard?.total_room }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="align-self-center">
|
<div class="align-self-center">
|
||||||
<i class="icon-map info font-large-2 float-right"></i>
|
<i class="icon-map info font-large-2 float-right"></i>
|
||||||
|
@ -82,10 +82,7 @@
|
||||||
<section id="chartjs-bar-charts">
|
<section id="chartjs-bar-charts">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12" *blockUI="'barCharts'; message: 'Loading'">
|
<div class="col-12" *blockUI="'barCharts'; message: 'Loading'">
|
||||||
<m-card
|
<m-card [options]="options">
|
||||||
[options]="options"
|
|
||||||
(reloadFunction)="reloadBarCharts($event)"
|
|
||||||
>
|
|
||||||
<ng-container mCardHeaderTitle> Appointment </ng-container>
|
<ng-container mCardHeaderTitle> Appointment </ng-container>
|
||||||
<ng-container mCardBody>
|
<ng-container mCardBody>
|
||||||
<div class="z" style="display: block">
|
<div class="z" style="display: block">
|
||||||
|
@ -113,12 +110,17 @@
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h4 class="card-title text-center">Air Quality</h4>
|
<h4 class="card-title text-center">Summary Cost</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="text-center" style="height: 150px !important">
|
<div class="text-center" style="height: 150px !important">
|
||||||
<h2 class="font-large-3 text-bold-400">Rp 1.253.634.234</h2>
|
<h2 class="font-large-3 text-bold-400">
|
||||||
|
{{
|
||||||
|
summaryCost?.summary_cost
|
||||||
|
| currency : "Rp " : "symbol" : "1.0-0"
|
||||||
|
}}
|
||||||
|
</h2>
|
||||||
<p class="blue-grey lighten-2 mb-0 mt-2">
|
<p class="blue-grey lighten-2 mb-0 mt-2">
|
||||||
Based on the estimated costs you have
|
Based on the estimated costs you have
|
||||||
</p>
|
</p>
|
||||||
|
@ -158,7 +160,7 @@
|
||||||
class="display-4 blue-grey darken-1"
|
class="display-4 blue-grey darken-1"
|
||||||
style="font-size: 2em"
|
style="font-size: 2em"
|
||||||
>
|
>
|
||||||
76 %
|
{{ airQuality }}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -189,81 +191,27 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-6">
|
<div class="col-6" *ngFor="let item of deviceCategory?.usesd">
|
||||||
<div class="card overflow-hidden">
|
<div class="card overflow-hidden">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="card-body cleartfix">
|
<div class="card-body cleartfix">
|
||||||
<div class="media align-items-stretch mb-2">
|
<div class="media align-items-stretch mb-2">
|
||||||
<div class="align-self-center">
|
<div class="align-self-center">
|
||||||
<i class="icon-energy background-round info font-large-2 mr-2"></i>
|
<i
|
||||||
|
class="icon-bulb background-round info font-large-2 mr-2"
|
||||||
|
></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-body">
|
<div class="media-body">
|
||||||
<p>
|
<p>
|
||||||
General Lighting
|
{{ item.category_device }}
|
||||||
<span class="float-right text-bold-600">89%</span>
|
<span class="float-right text-bold-600"
|
||||||
|
>{{ item.value }}%</span
|
||||||
|
>
|
||||||
</p>
|
</p>
|
||||||
<ngb-progressbar
|
<ngb-progressbar
|
||||||
height="7px"
|
height="7px"
|
||||||
type="danger"
|
type="danger"
|
||||||
[value]="90"
|
[value]="item.value"
|
||||||
></ngb-progressbar>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="media align-items-stretch mt-2">
|
|
||||||
<div class="align-self-center">
|
|
||||||
<i class="icon-energy background-round info font-large-2 mr-2"></i>
|
|
||||||
</div>
|
|
||||||
<div class="media-body">
|
|
||||||
<p>
|
|
||||||
Accent Lighting
|
|
||||||
<span class="float-right text-bold-600">89%</span>
|
|
||||||
</p>
|
|
||||||
<ngb-progressbar
|
|
||||||
height="7px"
|
|
||||||
type="danger"
|
|
||||||
[value]="90"
|
|
||||||
></ngb-progressbar>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-6">
|
|
||||||
<div class="card overflow-hidden">
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="card-body cleartfix">
|
|
||||||
<div class="media align-items-stretch mb-2">
|
|
||||||
<div class="align-self-center">
|
|
||||||
<i class="icon-layers background-round info font-large-2 mr-2"></i>
|
|
||||||
</div>
|
|
||||||
<div class="media-body">
|
|
||||||
<p>
|
|
||||||
Floor Lighting
|
|
||||||
<span class="float-right text-bold-600">89%</span>
|
|
||||||
</p>
|
|
||||||
<ngb-progressbar
|
|
||||||
height="7px"
|
|
||||||
type="danger"
|
|
||||||
[value]="90"
|
|
||||||
></ngb-progressbar>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="media align-items-stretch mt-2">
|
|
||||||
<div class="align-self-center">
|
|
||||||
<i class="icon-bulb background-round info font-large-2 mr-2"></i>
|
|
||||||
</div>
|
|
||||||
<div class="media-body">
|
|
||||||
<p>
|
|
||||||
Last Lighting
|
|
||||||
<span class="float-right text-bold-600">89%</span>
|
|
||||||
</p>
|
|
||||||
<ngb-progressbar
|
|
||||||
height="7px"
|
|
||||||
type="danger"
|
|
||||||
[value]="90"
|
|
||||||
></ngb-progressbar>
|
></ngb-progressbar>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { Component } from "@angular/core";
|
import { Component, ElementRef, ViewChild } from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import { BuildingService } from "../../service/monitoring-api.service";
|
|
||||||
import * as chartsData from "./data";
|
|
||||||
import * as Chartist from 'chartist';
|
|
||||||
import { ChartOptions, ChartType, ChartDataset } from "chart.js";
|
import { ChartOptions, ChartType, ChartDataset } from "chart.js";
|
||||||
|
import { EnergyMonitoringService } from "../../service/energy-monitoring.service";
|
||||||
|
import { CurrencyPipe } from "@angular/common";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-detail",
|
selector: "app-detail",
|
||||||
templateUrl: "./detail.component.html",
|
templateUrl: "./detail.component.html",
|
||||||
styleUrls: ["./detail.component.css"],
|
styleUrls: ["./detail.component.css"],
|
||||||
|
providers: [CurrencyPipe],
|
||||||
})
|
})
|
||||||
export class DetailComponent {
|
export class DetailComponent {
|
||||||
data: any;
|
data: any;
|
||||||
|
@ -16,21 +16,18 @@ export class DetailComponent {
|
||||||
breadcrumb: any;
|
breadcrumb: any;
|
||||||
donutChart1: any;
|
donutChart1: any;
|
||||||
donutChart2: any;
|
donutChart2: any;
|
||||||
sparklineArea: any
|
|
||||||
|
|
||||||
dataChart = {
|
dataChart = {
|
||||||
"donut": {
|
donut: {
|
||||||
"series": [20, 20, 20, 20, 20],
|
series: [20, 20, 20, 20, 20],
|
||||||
"labels": []
|
},
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
dataChart2 = {
|
dataChart2 = {
|
||||||
"donut": {
|
donut: {
|
||||||
"series": [50, 50],
|
series: [50, 50],
|
||||||
"labels": []
|
},
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// chart bar
|
// chart bar
|
||||||
public barChartOptions: ChartOptions = {
|
public barChartOptions: ChartOptions = {
|
||||||
|
@ -41,13 +38,14 @@ export class DetailComponent {
|
||||||
},
|
},
|
||||||
y: {
|
y: {
|
||||||
stacked: true,
|
stacked: true,
|
||||||
|
beginAtZero: true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
public barChartLabels: string[] = [];
|
public barChartLabels: string[] = [];
|
||||||
public barChartType: ChartType = "bar";
|
public barChartType: ChartType = "bar";
|
||||||
public barChartLegend = true;
|
public barChartLegend = true;
|
||||||
|
|
||||||
public barChartData: ChartDataset[] = [
|
public barChartData: ChartDataset[] = [
|
||||||
{
|
{
|
||||||
data: [],
|
data: [],
|
||||||
|
@ -74,9 +72,9 @@ export class DetailComponent {
|
||||||
categoryPercentage: 0.5,
|
categoryPercentage: 0.5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "line", // override the default type
|
type: "line",
|
||||||
data: [],
|
data: [],
|
||||||
label: "Appointment",
|
label: "Weekly Kwh Average",
|
||||||
backgroundColor: "rgba(0,255,255,0)",
|
backgroundColor: "rgba(0,255,255,0)",
|
||||||
borderColor: "#1e9ff2",
|
borderColor: "#1e9ff2",
|
||||||
fill: false,
|
fill: false,
|
||||||
|
@ -85,6 +83,23 @@ export class DetailComponent {
|
||||||
pointBorderWidth: 2,
|
pointBorderWidth: 2,
|
||||||
pointHoverBorderWidth: 2,
|
pointHoverBorderWidth: 2,
|
||||||
pointRadius: 4,
|
pointRadius: 4,
|
||||||
|
tension: 0.3,
|
||||||
|
spanGaps: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "line",
|
||||||
|
data: [],
|
||||||
|
label: "Weekly Water Average",
|
||||||
|
backgroundColor: "rgba(0,255,255,0)",
|
||||||
|
borderColor: "#1e9ff2",
|
||||||
|
fill: false,
|
||||||
|
pointBorderColor: "#1e9ff2",
|
||||||
|
pointBackgroundColor: "#FFF",
|
||||||
|
pointBorderWidth: 2,
|
||||||
|
pointHoverBorderWidth: 2,
|
||||||
|
pointRadius: 4,
|
||||||
|
tension: 0.3,
|
||||||
|
spanGaps: true
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
//..........................
|
//..........................
|
||||||
|
@ -94,34 +109,52 @@ export class DetailComponent {
|
||||||
water: any;
|
water: any;
|
||||||
device: any;
|
device: any;
|
||||||
room: any;
|
room: any;
|
||||||
|
topCard: any;
|
||||||
|
summaryCost: any;
|
||||||
|
airQuality: any;
|
||||||
|
temperature: any;
|
||||||
|
deviceCategory: any;
|
||||||
|
chartKwhWater: any;
|
||||||
//......
|
//......
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private monitoringApiService: BuildingService
|
private energyMonitoringService: EnergyMonitoringService,
|
||||||
|
private currencyPipe: CurrencyPipe
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
get formattedSummaryCost(): string {
|
||||||
|
return this.currencyPipe.transform(
|
||||||
|
this.summaryCost.summary_cost,
|
||||||
|
"IDR",
|
||||||
|
"symbol",
|
||||||
|
"1.0-0"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.route.data.subscribe((data) => {
|
this.route.data.subscribe((data) => {
|
||||||
this.mode = data.mode;
|
this.mode = data.mode;
|
||||||
});
|
});
|
||||||
this.breadcrumbLink();
|
this.breadcrumbLink();
|
||||||
this.generateChartLabelsAndData();
|
|
||||||
|
|
||||||
this.route.params.subscribe((params) => {
|
this.route.params.subscribe((params) => {
|
||||||
const buildingId = params["id"];
|
const buildingId = params["id"];
|
||||||
if (buildingId) {
|
if (buildingId) {
|
||||||
this.fetchData(buildingId);
|
this.dataEnergyMonitoringTopCard(buildingId);
|
||||||
this.devicePerBuilding(buildingId);
|
this.dataEnergyMonitoringSummary(buildingId);
|
||||||
|
this.dataEnergyMonitoringSAir(buildingId);
|
||||||
|
this.dataEnergyMonitoringSTemperature(buildingId);
|
||||||
|
this.dataEnergyDeviceCategory(buildingId);
|
||||||
|
this.dataEnergyChartKwhWater(buildingId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.donutChart1 = {
|
this.donutChart1 = {
|
||||||
type: 'Pie',
|
type: "Pie",
|
||||||
data: this.dataChart.donut,
|
data: this.dataChart.donut,
|
||||||
options: {
|
options: {
|
||||||
fullwidth: true,
|
fullwidth: true,
|
||||||
height: '300px',
|
height: "300px",
|
||||||
donut: true,
|
donut: true,
|
||||||
donutWidth: 70,
|
donutWidth: 70,
|
||||||
startAngle: 270,
|
startAngle: 270,
|
||||||
|
@ -129,37 +162,6 @@ export class DetailComponent {
|
||||||
showLabel: true,
|
showLabel: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
this.donutChart2 = {
|
|
||||||
type: 'Pie',
|
|
||||||
data: this.dataChart2.donut,
|
|
||||||
options: {
|
|
||||||
chartPadding: 0,
|
|
||||||
fullwidth: true,
|
|
||||||
height: '150px',
|
|
||||||
donut: true,
|
|
||||||
showLabel: true,
|
|
||||||
startAngle: 0,
|
|
||||||
labelInterpolationFnc: function (value) {
|
|
||||||
const total = 82;
|
|
||||||
return total + 'C';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
events: {
|
|
||||||
draw(data: any): void {
|
|
||||||
if (data.type === 'label') {
|
|
||||||
if (data.index === 0) {
|
|
||||||
data.element.attr({
|
|
||||||
dx: data.element.root().width() / 2,
|
|
||||||
dy: data.element.root().height() / 2
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
data.element.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
breadcrumbLink() {
|
breadcrumbLink() {
|
||||||
|
@ -201,41 +203,140 @@ export class DetailComponent {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generateChartLabelsAndData() {
|
|
||||||
const now = new Date();
|
|
||||||
const year = now.getFullYear();
|
|
||||||
const month = now.getMonth();
|
|
||||||
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
||||||
|
|
||||||
for (let day = 1; day <= daysInMonth; day++) {
|
|
||||||
const date = new Date(year, month, day);
|
|
||||||
this.barChartLabels.push(date.toISOString().split("T")[0]); // Format YYYY-MM-DD
|
|
||||||
|
|
||||||
// Example data generation, replace with your actual data logic
|
|
||||||
this.barChartData[0].data?.push(Math.floor(Math.random() * 100));
|
|
||||||
this.barChartData[1].data?.push(Math.floor(Math.random() * 100));
|
|
||||||
this.barChartData[2].data?.push(Math.floor(Math.random() * 100));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//integrasi
|
//integrasi
|
||||||
fetchData(buildingId) {
|
dataEnergyMonitoringTopCard(buildingId) {
|
||||||
this.monitoringApiService
|
this.energyMonitoringService
|
||||||
.getRoomByBuildingId(buildingId)
|
.getDashboardTopCard(buildingId)
|
||||||
.subscribe((res) => {
|
.subscribe((res) => {
|
||||||
this.room = res.resp.map((entry) => entry.roomEntity).length;
|
this.topCard = res.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
dataEnergyMonitoringSummary(buildingId) {
|
||||||
devicePerBuilding(buildingId) {
|
this.energyMonitoringService
|
||||||
this.monitoringApiService
|
.getDashboardSummary(buildingId)
|
||||||
.listDevicePerBuilding(buildingId)
|
|
||||||
.subscribe((res) => {
|
.subscribe((res) => {
|
||||||
this.device = res.resp.reduce(
|
this.summaryCost = res.data;
|
||||||
(sum, item) => sum + item.total_device,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
dataEnergyMonitoringSAir(buildingId) {
|
||||||
|
this.energyMonitoringService
|
||||||
|
.getDashboardAirQuality(buildingId)
|
||||||
|
.subscribe((res) => {
|
||||||
|
this.airQuality = res.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
dataEnergyMonitoringSTemperature(buildingId) {
|
||||||
|
this.energyMonitoringService
|
||||||
|
.getDashboardTemperature(buildingId)
|
||||||
|
.subscribe((res) => {
|
||||||
|
this.temperature = res.data;
|
||||||
|
this.donutChart2 = {
|
||||||
|
type: "Pie",
|
||||||
|
data: this.dataChart2.donut,
|
||||||
|
options: {
|
||||||
|
chartPadding: 0,
|
||||||
|
fullwidth: true,
|
||||||
|
height: "150px",
|
||||||
|
donut: true,
|
||||||
|
showLabel: true,
|
||||||
|
startAngle: 0,
|
||||||
|
labelInterpolationFnc: (value) => {
|
||||||
|
const total = this.temperature;
|
||||||
|
return total + "°C";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
draw: (data: any) => {
|
||||||
|
if (data.type === "label") {
|
||||||
|
if (data.index === 0) {
|
||||||
|
data.element.attr({
|
||||||
|
dx: data.element.root().width() / 2,
|
||||||
|
dy: data.element.root().height() / 2,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data.element.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
dataEnergyDeviceCategory(buildingId) {
|
||||||
|
this.energyMonitoringService
|
||||||
|
.getDashboardDeviceCategory(buildingId)
|
||||||
|
.subscribe((res) => {
|
||||||
|
this.deviceCategory = res.data[0];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
dataEnergyChartKwhWater(buildingId) {
|
||||||
|
this.energyMonitoringService
|
||||||
|
.getDashboardChartKwhWater(buildingId)
|
||||||
|
.subscribe((res) => {
|
||||||
|
this.chartKwhWater = res.data;
|
||||||
|
this.barChartData[0].data = [];
|
||||||
|
this.barChartData[1].data = [];
|
||||||
|
this.chartKwhWater.forEach((entry) => {
|
||||||
|
this.barChartData[0].data.push(entry.kwh);
|
||||||
|
this.barChartData[1].data.push(entry.water);
|
||||||
|
this.barChartLabels.push(entry.day);
|
||||||
|
});
|
||||||
|
|
||||||
|
const weeklyKwh = this.aggregateKwhWeekly(this.chartKwhWater);
|
||||||
|
const weeklyWater = this.aggregateWaterWeekly(this.chartKwhWater);
|
||||||
|
|
||||||
|
// Populate Appointment data at every multiple of 7
|
||||||
|
let weekIndex = 0;
|
||||||
|
for (let i = 0; i < this.barChartData[0].data.length; i++) {
|
||||||
|
if (i % 7 === 6 && weekIndex < weeklyKwh.length) {
|
||||||
|
this.barChartData[2].data[i] = weeklyKwh[weekIndex++];
|
||||||
|
} else {
|
||||||
|
this.barChartData[2].data[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let weekIndexWater = 0;
|
||||||
|
for (let i = 0; i < this.barChartData[0].data.length; i++) {
|
||||||
|
if (i % 7 === 6 && weekIndexWater < weeklyWater.length) {
|
||||||
|
this.barChartData[3].data[i] = weeklyWater[weekIndexWater++];
|
||||||
|
} else {
|
||||||
|
this.barChartData[3].data[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
aggregateKwhWeekly(data: any[]): number[] {
|
||||||
|
const weeks = [];
|
||||||
|
let weekSum = 0;
|
||||||
|
let dayCount = 0;
|
||||||
|
|
||||||
|
data.forEach((entry, index) => {
|
||||||
|
weekSum += entry.kwh;
|
||||||
|
dayCount++;
|
||||||
|
if (dayCount === 7 || index === data.length - 1) {
|
||||||
|
weeks.push(weekSum);
|
||||||
|
weekSum = 0;
|
||||||
|
dayCount = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return weeks;
|
||||||
|
}
|
||||||
|
aggregateWaterWeekly(data: any[]): number[] {
|
||||||
|
const weeks = [];
|
||||||
|
let weekSum = 0;
|
||||||
|
let dayCount = 0;
|
||||||
|
|
||||||
|
data.forEach((entry, index) => {
|
||||||
|
weekSum += entry.water;
|
||||||
|
dayCount++;
|
||||||
|
if (dayCount === 7 || index === data.length - 1) {
|
||||||
|
weeks.push(weekSum);
|
||||||
|
weekSum = 0;
|
||||||
|
dayCount = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return weeks;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { HttpClient, HttpHeaders } from "@angular/common/http";
|
||||||
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: "root",
|
||||||
|
})
|
||||||
|
export class EnergyMonitoringService {
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
getListRoomData(): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/room/list`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
getDashboardTopCard(id): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/dashboard/top-card?building_id=${id}`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
getDashboardSummary(id): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/dashboard/summary-cost?building_id=${id}`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
getDashboardAirQuality(id): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/dashboard/air-quality?building_id=${id}`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
getDashboardTemperature(id): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/dashboard/temperature-humidity?building_id=${id}`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
getDashboardDeviceCategory(id): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/dashboard/device-category-use?building_id=${id}`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
getDashboardChartKwhWater(id): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/dashboard/chartKwhWater?building_id=${id}`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue