integrasi cost management
This commit is contained in:
parent
38c936b389
commit
ad91c844d6
|
@ -28,17 +28,17 @@
|
||||||
<div class="navbar-container content" [hidden]="isMobile && !showNavbar">
|
<div class="navbar-container content" [hidden]="isMobile && !showNavbar">
|
||||||
<div class="collapse navbar-collapse" id="navbar-mobile">
|
<div class="collapse navbar-collapse" id="navbar-mobile">
|
||||||
<ul class="nav navbar-nav mr-auto float-left">
|
<ul class="nav navbar-nav mr-auto float-left">
|
||||||
<li class="nav-item d-none d-md-block"><a [routerLink]="" class="nav-link nav-link-expand"
|
<!-- <li class="nav-item d-none d-md-block"><a [routerLink]="" class="nav-link nav-link-expand"
|
||||||
(click)="toggleFullScreen()" *ngIf="maximize === 'on'"><i class="ficon feather ft-maximize"></i></a></li>
|
(click)="toggleFullScreen()" *ngIf="maximize === 'on'"><i class="ficon feather ft-maximize"></i></a></li>
|
||||||
<li class="nav-item nav-search"><a [routerLink]="" class="nav-link nav-link-search" (click)="clickSearch()"
|
<li class="nav-item nav-search"><a [routerLink]="" class="nav-link nav-link-search" (click)="clickSearch()"
|
||||||
*ngIf="search === 'on'"><i class="ficon feather ft-search"></i></a>
|
*ngIf="search === 'on'"><i class="ficon feather ft-search"></i></a>
|
||||||
<div class="search-input" [ngClass]="{'open': isHeaderSearchOpen}">
|
<div class="search-input" [ngClass]="{'open': isHeaderSearchOpen}">
|
||||||
<input class="input" type="text" placeholder="Explore Modern...">
|
<input class="input" type="text" placeholder="Explore Modern...">
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li> -->
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav float-right">
|
<ul class="nav navbar-nav float-right">
|
||||||
<li class="dropdown-language nav-item" ngbDropdown *ngIf="internationalization === 'on'">
|
<!-- <li class="dropdown-language nav-item" ngbDropdown *ngIf="internationalization === 'on'">
|
||||||
<a [routerLink]="" class="dropdown-toggle nav-link" ngbDropdownToggle id="dropdown-flag">
|
<a [routerLink]="" class="dropdown-toggle nav-link" ngbDropdownToggle id="dropdown-flag">
|
||||||
<i class="flag-icon flag-icon-gb"></i><span class="selected-language"></span>
|
<i class="flag-icon flag-icon-gb"></i><span class="selected-language"></span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
<i class="flag-icon flag-icon-de"></i> German
|
<i class="flag-icon flag-icon-de"></i> German
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li> -->
|
||||||
<li class="dropdown-notification nav-item dropdown" ngbDropdown *ngIf="notification === 'on'">
|
<li class="dropdown-notification nav-item dropdown" ngbDropdown *ngIf="notification === 'on'">
|
||||||
<a class="nav-link nav-link-label" ngbDropdownToggle>
|
<a class="nav-link nav-link-label" ngbDropdownToggle>
|
||||||
<i class="ficon feather ft-bell"></i>
|
<i class="ficon feather ft-bell"></i>
|
||||||
|
@ -133,7 +133,7 @@
|
||||||
href="javascript:void(0)">Read all notifications</a></li>
|
href="javascript:void(0)">Read all notifications</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-notification nav-item" ngbDropdown>
|
<!-- <li class="dropdown-notification nav-item" ngbDropdown>
|
||||||
<a class="nav-link nav-link-label" ngbDropdownToggle *ngIf="email === 'on'"><i
|
<a class="nav-link nav-link-label" ngbDropdownToggle *ngIf="email === 'on'"><i
|
||||||
class="ficon feather ft-mail"></i></a>
|
class="ficon feather ft-mail"></i></a>
|
||||||
<ul class="dropdown-menu-media dropdown-menu-right" ngbDropdownMenu>
|
<ul class="dropdown-menu-media dropdown-menu-right" ngbDropdownMenu>
|
||||||
|
@ -194,7 +194,7 @@
|
||||||
<li class="dropdown-menu-footer"><a class="dropdown-item text-muted text-center"
|
<li class="dropdown-menu-footer"><a class="dropdown-item text-muted text-center"
|
||||||
href="javascript:void(0)">Read all messages</a></li>
|
href="javascript:void(0)">Read all messages</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li> -->
|
||||||
|
|
||||||
<li class="dropdown-user nav-item" ngbDropdown>
|
<li class="dropdown-user nav-item" ngbDropdown>
|
||||||
<a class="nav-link dropdown-user-link" ngbDropdownToggle>
|
<a class="nav-link dropdown-user-link" ngbDropdownToggle>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,63 +1,253 @@
|
||||||
:host ::ng-deep .donut-chart1 .ct-series-a .ct-slice-donut {
|
|
||||||
stroke: green;
|
|
||||||
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-chart1 .ct-series-b .ct-slice-donut {
|
}
|
||||||
stroke: yellow;
|
|
||||||
stroke-width: 50px !important;
|
:host ::ng-deep .donut-chart2 .ct-series-b .ct-slice-donut {
|
||||||
}
|
stroke: #bef264;
|
||||||
|
stroke-width: 20px !important;
|
||||||
:host ::ng-deep .donut-chart1 .ct-series-c .ct-slice-donut {
|
}
|
||||||
stroke: orange;
|
|
||||||
stroke-width: 50px !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-chart1 .ct-series-d .ct-slice-donut {
|
}
|
||||||
stroke: red;
|
|
||||||
stroke-width: 50px !important;
|
:host ::ng-deep .donut-chart2 .ct-label {
|
||||||
}
|
fill: #111010;
|
||||||
|
color: rgba(0, 0, 0, 0.4);
|
||||||
:host ::ng-deep .donut-chart1 .ct-series-e .ct-slice-donut {
|
font-size: 1.75rem;
|
||||||
stroke: darkred;
|
line-height: 1;
|
||||||
stroke-width: 50px !important;
|
}
|
||||||
}
|
|
||||||
|
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-point {
|
||||||
:host ::ng-deep .donut-chart2 .ct-series-a .ct-slice-donut {
|
stroke: #bef264;
|
||||||
stroke: #8a8a8a;
|
}
|
||||||
stroke-width: 20px !important;
|
|
||||||
}
|
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-line {
|
||||||
|
stroke: #bef264;
|
||||||
:host ::ng-deep .donut-chart2 .ct-series-b .ct-slice-donut {
|
}
|
||||||
stroke: #bef264;
|
|
||||||
stroke-width: 20px !important;
|
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-area {
|
||||||
}
|
fill: #bef264;
|
||||||
|
fill-opacity: 1;
|
||||||
: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 .sp-line-total-cost .ct-point {
|
||||||
}
|
stroke-width: 0px;
|
||||||
|
}
|
||||||
:host ::ng-deep .donut-chart2 .ct-label {
|
|
||||||
fill: #111010;
|
.ct-chart-bar .ct-series .ct-bar {
|
||||||
color: rgba(0, 0, 0, 0.4);
|
stroke-width: 20px !important; /* Atur lebar bar sesuai kebutuhan */
|
||||||
font-size: 1.75rem;
|
}
|
||||||
line-height: 1;
|
|
||||||
}
|
.ct-chart-bar .ct-label.ct-horizontal {
|
||||||
|
margin-left: -10px !important; /* Mengatur margin label horizontal */
|
||||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-point {
|
margin-right: -10px !important;
|
||||||
stroke: #bef264;
|
}
|
||||||
}
|
|
||||||
|
:host ::ng-deep .donut-chart3 .ct-series-a .ct-bar {
|
||||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-line {
|
stroke: #cd560c;
|
||||||
stroke: #bef264;
|
fill: none;
|
||||||
}
|
stroke-width: 30px;
|
||||||
|
}
|
||||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-area {
|
|
||||||
fill: #bef264;
|
:host ::ng-deep .donut-chart3 .ct-series-b .ct-bar {
|
||||||
fill-opacity: 1;
|
stroke: #49cd0c;
|
||||||
}
|
fill: none;
|
||||||
|
stroke-width: 30px;
|
||||||
:host ::ng-deep .sp-line-total-cost .ct-point {
|
}
|
||||||
stroke-width: 0px;
|
|
||||||
}
|
/* table */
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header .datatable-header-cell .datatable-header-cell-label {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: medium;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #6B6F82;
|
||||||
|
}
|
||||||
|
:host ::ng-deep .ngx-datatable .datatable-row-center, .ngx-datatable .datatable-row-group, .ngx-datatable .datatable-row-right {
|
||||||
|
position: relative;
|
||||||
|
height: 50px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .datatable-icon-right:before {
|
||||||
|
font-family: 'icofont';
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .datatable-icon-skip:before {
|
||||||
|
font-family: 'icofont';
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .datatable-icon-left:before {
|
||||||
|
font-family: 'icofont';
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .datatable-icon-left:before {
|
||||||
|
content: "\2039";
|
||||||
|
font-size: x-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .datatable-icon-prev:before {
|
||||||
|
content: "\00AB";
|
||||||
|
font-size: x-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .datatable-icon-right:before {
|
||||||
|
content: "\203A";
|
||||||
|
font-size: x-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .datatable-icon-skip:before {
|
||||||
|
content: "\00BB";
|
||||||
|
font-size: x-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-left,
|
||||||
|
.ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-right,
|
||||||
|
.ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-prev {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 22px;
|
||||||
|
padding: 0px 09px;
|
||||||
|
background-color: #d4d2e7;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-right,
|
||||||
|
.ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-right {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 22px;
|
||||||
|
padding: 0px 09px;
|
||||||
|
background-color: #d4d2e7;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-skip {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 22px;
|
||||||
|
padding: 0px 09px;
|
||||||
|
background-color: #d4d2e7;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-prev {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 22px;
|
||||||
|
padding: 0px 09px;
|
||||||
|
background-color: #d4d2e7;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .datatable-footer .datatable-pager ul li:not(.disabled).active a,
|
||||||
|
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] ul[_ngcontent-c11] li[_ngcontent-c11]:not(.disabled):hover a[_ngcontent-c11] {
|
||||||
|
background-color: #d4d2e7;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: larger;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager a {
|
||||||
|
height: 32px;
|
||||||
|
min-width: 34px;
|
||||||
|
line-height: 22px;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin: 0 3px;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: top;
|
||||||
|
padding-top: 3px;
|
||||||
|
text-decoration: none;
|
||||||
|
vertical-align: bottom;
|
||||||
|
color: #7c8091;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-left,
|
||||||
|
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-right[_ngcontent-c11],
|
||||||
|
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-prev[_ngcontent-c11] {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 9px;
|
||||||
|
padding: 0px 08px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-left,
|
||||||
|
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-right[_ngcontent-c11],
|
||||||
|
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-prev[_ngcontent-c11] {
|
||||||
|
font-size: 0px;
|
||||||
|
line-height: 22px;
|
||||||
|
padding: 0px 09px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-right,
|
||||||
|
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-right[_ngcontent-c11],
|
||||||
|
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-prev[_ngcontent-c11] {
|
||||||
|
font-size: 0px;
|
||||||
|
line-height: 22px;
|
||||||
|
padding: 0px 09px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-skip,
|
||||||
|
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-right[_ngcontent-c11],
|
||||||
|
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-prev[_ngcontent-c11] {
|
||||||
|
font-size: 0px;
|
||||||
|
line-height: 22px;
|
||||||
|
padding: 0px 09px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-prev,
|
||||||
|
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-right[_ngcontent-c11],
|
||||||
|
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-prev[_ngcontent-c11] {
|
||||||
|
font-size: 0px;
|
||||||
|
line-height: 22px;
|
||||||
|
padding: 0px 09px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager ul li:not(.disabled):hover a {
|
||||||
|
background-color: #545454;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager ul li:not(.disabled).active a,
|
||||||
|
.ngx-datatable.bootstrap .datatable-footer .datatable-pager ul li:not(.disabled):hover a {
|
||||||
|
background-color: #545454;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||||
|
background: #727e8e;
|
||||||
|
color: #ededed;
|
||||||
|
margin-top: -1px;
|
||||||
|
overflow: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||||
|
font-weight: bold;
|
||||||
|
height: unset !important;
|
||||||
|
overflow: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable .datatable-footer .datatable-pager {
|
||||||
|
flex: 0 0 0%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable .datatable-footer .datatable-pager .pager {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .block-ui-wrapper {
|
||||||
|
background: rgba(255, 249, 249, 0.5) !important;
|
||||||
|
}
|
||||||
|
:host ::ng-deep .ngx-datatable .datatable-footer .selected-count .datatable-pager {
|
||||||
|
flex: 0 0 0%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .ngx-datatable {
|
||||||
|
display: -webkit-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
<div class="col-lg-4 col-12">
|
<div class="col-lg-4 col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h4 class="card-title text-center">Temperature and Humidity</h4>
|
<h4 class="card-title text-center">
|
||||||
|
Comparison of Water and Electricity Costs
|
||||||
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
|
@ -30,35 +32,25 @@
|
||||||
<div class="col-lg-4 col-12">
|
<div class="col-lg-4 col-12">
|
||||||
<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">
|
||||||
|
Comparison of Previous Month Costs
|
||||||
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="card-block">
|
<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
|
<div
|
||||||
class="text-center"
|
class="donut-chart3 text-center"
|
||||||
style="
|
style="height: 150px !important"
|
||||||
position: absolute;
|
|
||||||
top: 80%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<h3
|
<x-chartist
|
||||||
class="display-4 blue-grey darken-1"
|
*ngIf="barChart"
|
||||||
style="font-size: 2em"
|
[data]="barChart.data"
|
||||||
|
[type]="barChart.type"
|
||||||
|
[options]="barChart.options"
|
||||||
|
[responsiveOptions]="barChart.responsiveOptions"
|
||||||
|
[events]="barChart.events"
|
||||||
>
|
>
|
||||||
76 %
|
</x-chartist>
|
||||||
</h3>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -67,7 +59,9 @@
|
||||||
<div class="col-lg-4 col-12">
|
<div class="col-lg-4 col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h4 class="card-title text-center">Comparison of Actual Costs and Estimated Costs</h4>
|
<h4 class="card-title text-center">
|
||||||
|
Comparison of Actual Costs and Estimated Costs
|
||||||
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
|
@ -75,30 +69,36 @@
|
||||||
<div class="flex-grow-1">
|
<div class="flex-grow-1">
|
||||||
<ngb-progressbar
|
<ngb-progressbar
|
||||||
height="45px"
|
height="45px"
|
||||||
type="danger"
|
type="success"
|
||||||
[value]="89"
|
[value]="dataCompAct?.est_cost"
|
||||||
|
[max]="dataCompAct?.real_cost"
|
||||||
></ngb-progressbar>
|
></ngb-progressbar>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="ml-2 d-flex align-items-center"
|
class="ml-2 d-flex align-items-center"
|
||||||
style="height: 20px"
|
style="height: 20px"
|
||||||
>
|
>
|
||||||
<span class="text-bold-600">1.234.242</span>
|
<span class="text-bold-600">{{
|
||||||
|
dataCompAct?.est_cost
|
||||||
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<div class="flex-grow-1">
|
<div class="flex-grow-1">
|
||||||
<ngb-progressbar
|
<ngb-progressbar
|
||||||
height="45px"
|
height="45px"
|
||||||
type="success"
|
type="danger"
|
||||||
[value]="50"
|
[value]="dataCompAct?.real_cost"
|
||||||
|
[max]="dataCompAct?.real_cost"
|
||||||
></ngb-progressbar>
|
></ngb-progressbar>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="ml-2 d-flex align-items-center"
|
class="ml-2 d-flex align-items-center"
|
||||||
style="height: 20px"
|
style="height: 20px"
|
||||||
>
|
>
|
||||||
<span class="text-bold-600">1.545.232</span>
|
<span class="text-bold-600">{{
|
||||||
|
dataCompAct?.real_cost
|
||||||
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -107,6 +107,276 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<section id="configuration">
|
||||||
|
<div class="row">
|
||||||
|
<div
|
||||||
|
class="col-12"
|
||||||
|
*blockUI="'zeroConfiguration'; message: 'Loading'"
|
||||||
|
>
|
||||||
|
<m-card>
|
||||||
|
<!-- <ng-container mCardHeaderTitle> Device Table </ng-container> -->
|
||||||
|
<ng-container mCardBody>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<ng-select
|
||||||
|
[items]="dataBuildingList"
|
||||||
|
[searchable]="true"
|
||||||
|
bindLabel="name"
|
||||||
|
bindValue="id"
|
||||||
|
placeholder="Select Building"
|
||||||
|
[(ngModel)]="buildingSelected"
|
||||||
|
>
|
||||||
|
</ng-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<input
|
||||||
|
type="month"
|
||||||
|
class="form-control"
|
||||||
|
[(ngModel)]="dateSelected"
|
||||||
|
id="month12"
|
||||||
|
(focus)="focusElement('month12')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<ng-select
|
||||||
|
[items]="dataMasterCategori"
|
||||||
|
[searchable]="true"
|
||||||
|
bindLabel="name"
|
||||||
|
bindValue="id"
|
||||||
|
placeholder="Select Category"
|
||||||
|
[(ngModel)]="categorySelected"
|
||||||
|
>
|
||||||
|
</ng-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="d-flex">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="Search..."
|
||||||
|
[(ngModel)]="searchTerm"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-outline-success ml-2"
|
||||||
|
(click)="doFilter()"
|
||||||
|
>
|
||||||
|
<i class="la la-search"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-2">
|
||||||
|
<div class="col-4">
|
||||||
|
<div class="form-group">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="Kwh"
|
||||||
|
[(ngModel)]="kwhTerm"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-4">
|
||||||
|
<div class="form-group">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="Cost"
|
||||||
|
[(ngModel)]="costTerm"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-4">
|
||||||
|
<div class="d-flex justify-content-end">
|
||||||
|
<button
|
||||||
|
class="btn btn-secondary mr-2"
|
||||||
|
style="width: 100%"
|
||||||
|
(click)="syncData()"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="la la-spinner spinner"
|
||||||
|
*ngIf="spinnerActive"
|
||||||
|
></i>
|
||||||
|
<i class="la la-spinner" *ngIf="!spinnerActive"></i
|
||||||
|
>
|
||||||
|
<span>Syncing Data</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-secondary"
|
||||||
|
style="width: 100%"
|
||||||
|
(click)="addFieldValue()"
|
||||||
|
>
|
||||||
|
<i class="feather ft-plus"></i
|
||||||
|
>
|
||||||
|
<span>Add Actual Cost</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-dashboard">
|
||||||
|
<ngx-datatable
|
||||||
|
class="bootstrap table-bordered"
|
||||||
|
[limit]="5"
|
||||||
|
[rows]="data_cost"
|
||||||
|
[columnMode]="'force'"
|
||||||
|
[headerHeight]="50"
|
||||||
|
[footerHeight]="50"
|
||||||
|
[rowHeight]="50"
|
||||||
|
fxFlex="auto"
|
||||||
|
[scrollbarH]="true"
|
||||||
|
>
|
||||||
|
<ngx-datatable-column
|
||||||
|
name="#"
|
||||||
|
[flexGrow]="1"
|
||||||
|
[minWidth]="10"
|
||||||
|
>
|
||||||
|
<ng-template
|
||||||
|
ngx-datatable-cell-template
|
||||||
|
let-rowIndex="rowIndex"
|
||||||
|
>
|
||||||
|
{{ rowIndex + 1 }}
|
||||||
|
</ng-template>
|
||||||
|
</ngx-datatable-column>
|
||||||
|
<ngx-datatable-column
|
||||||
|
name="building"
|
||||||
|
[flexGrow]="1"
|
||||||
|
[minWidth]="90"
|
||||||
|
>
|
||||||
|
<ng-template ngx-datatable-header-template>
|
||||||
|
<span>Building</span>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template
|
||||||
|
let-value="value"
|
||||||
|
ngx-datatable-cell-template
|
||||||
|
>
|
||||||
|
{{ value }}
|
||||||
|
</ng-template>
|
||||||
|
</ngx-datatable-column>
|
||||||
|
<ngx-datatable-column
|
||||||
|
name="categoryName"
|
||||||
|
[flexGrow]="1"
|
||||||
|
[minWidth]="90"
|
||||||
|
>
|
||||||
|
<ng-template ngx-datatable-header-template>
|
||||||
|
<span>Category</span>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template
|
||||||
|
let-value="value"
|
||||||
|
ngx-datatable-cell-template
|
||||||
|
>
|
||||||
|
{{ value }}
|
||||||
|
</ng-template>
|
||||||
|
</ngx-datatable-column>
|
||||||
|
<ngx-datatable-column
|
||||||
|
name="estimationCost"
|
||||||
|
[flexGrow]="1"
|
||||||
|
[minWidth]="90"
|
||||||
|
>
|
||||||
|
<ng-template ngx-datatable-header-template>
|
||||||
|
<span>Estimation Cost</span>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template
|
||||||
|
let-value="value"
|
||||||
|
ngx-datatable-cell-template
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
value.toLocaleString("id-ID", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "IDR"
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
</ng-template>
|
||||||
|
</ngx-datatable-column>
|
||||||
|
<ngx-datatable-column
|
||||||
|
name="totalUse"
|
||||||
|
[flexGrow]="1"
|
||||||
|
[minWidth]="90"
|
||||||
|
>
|
||||||
|
<ng-template ngx-datatable-header-template>
|
||||||
|
<span>Total Use</span>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template
|
||||||
|
let-value="value"
|
||||||
|
ngx-datatable-cell-template
|
||||||
|
>
|
||||||
|
{{ value }} kWh
|
||||||
|
</ng-template>
|
||||||
|
</ngx-datatable-column>
|
||||||
|
<ngx-datatable-column
|
||||||
|
name="endDate"
|
||||||
|
[flexGrow]="1"
|
||||||
|
[minWidth]="90"
|
||||||
|
>
|
||||||
|
<ng-template ngx-datatable-header-template>
|
||||||
|
<span>Tanggal</span>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template
|
||||||
|
let-value="value"
|
||||||
|
ngx-datatable-cell-template
|
||||||
|
>
|
||||||
|
{{ value | date : "MM/yyyy" }}
|
||||||
|
</ng-template>
|
||||||
|
</ngx-datatable-column>
|
||||||
|
<ngx-datatable-column
|
||||||
|
name="status_id"
|
||||||
|
[flexGrow]="1"
|
||||||
|
[minWidth]="90"
|
||||||
|
>
|
||||||
|
<ng-template ngx-datatable-header-template>
|
||||||
|
<span>Status</span>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template
|
||||||
|
ngx-datatable-cell-template
|
||||||
|
let-value="value"
|
||||||
|
>
|
||||||
|
{{ value === 2 ? "Aktif" : "Tidak Aktif" }}
|
||||||
|
</ng-template>
|
||||||
|
</ngx-datatable-column>
|
||||||
|
<ngx-datatable-column
|
||||||
|
name="Actions"
|
||||||
|
[flexGrow]="1"
|
||||||
|
[minWidth]="150"
|
||||||
|
>
|
||||||
|
<ng-template
|
||||||
|
ngx-datatable-cell-template
|
||||||
|
let-rowIndex="rowIndex"
|
||||||
|
let-row="row"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-warning mr-1"
|
||||||
|
(click)="editRow(row)"
|
||||||
|
>
|
||||||
|
<i class="ficon feather ft-edit"></i>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-danger"
|
||||||
|
(click)="deleteRow(row)"
|
||||||
|
>
|
||||||
|
<i class="ficon feather ft-trash-2"></i>
|
||||||
|
</button>
|
||||||
|
</ng-template>
|
||||||
|
</ngx-datatable-column>
|
||||||
|
</ngx-datatable>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</m-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,50 +1,51 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { Router } from '@angular/router';
|
import { Router } from "@angular/router";
|
||||||
import { TableApiService } from 'src/app/_services/table-api.service';
|
import { TableApiService } from "src/app/_services/table-api.service";
|
||||||
|
import { BuildingService } from "../service/monitoring-api.service";
|
||||||
|
import { DatePipe } from "@angular/common";
|
||||||
|
import { CostManagementService } from "../service/cost-management.service";
|
||||||
|
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
|
||||||
|
import { ModalAddActualComponent } from "./modal-add-actual/modal-add-actual.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-cost-management',
|
selector: "app-cost-management",
|
||||||
templateUrl: './cost-management.component.html',
|
templateUrl: "./cost-management.component.html",
|
||||||
styleUrls: ['./cost-management.component.css']
|
styleUrls: ["./cost-management.component.css"],
|
||||||
})
|
})
|
||||||
export class CostManagementComponent implements OnInit{
|
export class CostManagementComponent implements OnInit {
|
||||||
public breadcrumb: any;
|
public breadcrumb: any;
|
||||||
data: any;
|
data: any;
|
||||||
filteredRows: any[];
|
filteredRows: any[];
|
||||||
|
data_cost: any;
|
||||||
searchTerm: string = "";
|
searchTerm: string = "";
|
||||||
|
kwhTerm: string = "";
|
||||||
|
costTerm: string = "";
|
||||||
rows: any = [];
|
rows: any = [];
|
||||||
|
dataMasterCategori: any;
|
||||||
|
dataBuildingList: any;
|
||||||
|
public focucedElement = "";
|
||||||
|
spinnerActive = false;
|
||||||
|
spinnerActiveActual = false;
|
||||||
|
|
||||||
donutChart1: any;
|
|
||||||
donutChart2: any;
|
donutChart2: any;
|
||||||
dataChart = {
|
|
||||||
donut: {
|
|
||||||
series: [50, 50],
|
|
||||||
labels: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
dataChart2 = {
|
|
||||||
donut: {
|
|
||||||
series: [50, 50],
|
|
||||||
labels: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
barChart: any;
|
barChart: any;
|
||||||
dataBar = {
|
|
||||||
"Bar": {
|
dateSelected: any;
|
||||||
"labels": [],
|
buildingSelected: any;
|
||||||
"series": [
|
categorySelected: any;
|
||||||
[
|
dataComp: any;
|
||||||
80,
|
dataCompPrev: any;
|
||||||
60
|
dataCompAct: any;
|
||||||
]
|
storedData: any;
|
||||||
]
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private tableApiservice: TableApiService,
|
private tableApiservice: TableApiService,
|
||||||
private router: Router
|
private router: Router,
|
||||||
|
private monitoringApiService: BuildingService,
|
||||||
|
private costService: CostManagementService,
|
||||||
|
private datePipe: DatePipe,
|
||||||
|
private modalService: NgbModal
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
@ -61,78 +62,223 @@ export class CostManagementComponent implements OnInit{
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
this.fetchData();
|
this.storedData = JSON.parse(localStorage.getItem("currentUser"));
|
||||||
|
this.buildingSelected = this.storedData.buildingId;
|
||||||
|
const currentDate = new Date();
|
||||||
|
this.dateSelected = currentDate.toISOString().slice(0, 7);
|
||||||
|
|
||||||
this.barChart = {
|
this.fetchData(this.storedData.buildingId, this.dateSelected, this.categorySelected);
|
||||||
type: 'Bar',
|
this.dataListMaster();
|
||||||
data: this.dataBar.Bar,
|
this.dataListBuilding();
|
||||||
options: {
|
|
||||||
fullwidth: true,
|
|
||||||
axisX: {
|
|
||||||
showGrid: false,
|
|
||||||
showLabel: false,
|
|
||||||
offset: 100
|
|
||||||
},
|
|
||||||
|
|
||||||
axisY: {
|
|
||||||
showGrid: false,
|
|
||||||
showLabel: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.donutChart1 = {
|
this.dataCompWaterElectCost(this.storedData.buildingId);
|
||||||
type: "Pie",
|
this.dataCompPrevMonthCost(this.storedData.buildingId);
|
||||||
data: this.dataChart.donut,
|
this.dataCompActEstCost(this.storedData.buildingId);
|
||||||
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(id, period, category) {
|
||||||
this.tableApiservice.getTableInitialisationData().subscribe((response) => {
|
this.costService.getCostManagement(id, period, category).subscribe((response) => {
|
||||||
this.data = response;
|
this.data = response.results.data;
|
||||||
this.filteredRows = this.data.rows;
|
this.filteredRows = this.data;
|
||||||
|
this.kwhTerm = response.results.kwh;
|
||||||
|
this.costTerm = response.results.cost;
|
||||||
|
|
||||||
|
this.data_cost = this.filteredRows.map((item) => ({
|
||||||
|
building: item.name,
|
||||||
|
categoryName: item.category_name,
|
||||||
|
estimationCost: item.estimation_cost,
|
||||||
|
totalUse: item.total_use,
|
||||||
|
endDate: item.end_date,
|
||||||
|
statusId: item.status_id,
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dataListMaster() {
|
||||||
|
this.monitoringApiService.getMasterListData().subscribe((data) => {
|
||||||
|
const dataCategory = data.data.find(
|
||||||
|
(item) => item.name === "master_category"
|
||||||
|
).headerDetailParam;
|
||||||
|
this.dataMasterCategori = dataCategory.filter(
|
||||||
|
(item) => item.status === "2"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dataListBuilding() {
|
||||||
|
this.monitoringApiService.getBuildingList().subscribe((data) => {
|
||||||
|
this.dataBuildingList = data.data.filter((item) => item.statusId === 2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dataCompWaterElectCost(buildingId) {
|
||||||
|
this.costService.getCompWaterElectCost(buildingId).subscribe((data) => {
|
||||||
|
this.dataComp = data.data;
|
||||||
|
const dataChart2 = {
|
||||||
|
donut: {
|
||||||
|
series: [this.dataComp.elect, this.dataComp.water],
|
||||||
|
labels: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
this.donutChart2 = {
|
||||||
|
type: "Pie",
|
||||||
|
data: 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// this.dataChart2.donut.labels = ["Water", "Electricity"];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dataCompPrevMonthCost(buildingId) {
|
||||||
|
this.costService.getCompPrevMonthCost(buildingId).subscribe((data) => {
|
||||||
|
this.dataCompPrev = data.data;
|
||||||
|
const randomValue = Math.floor(Math.random() * (100 - 50 + 1)) + 50;
|
||||||
|
const dataBar = {
|
||||||
|
Bar: {
|
||||||
|
labels: [[this.dataCompPrev[0].name], [this.dataCompPrev[1].name]],
|
||||||
|
series: [[randomValue], [this.dataCompPrev[1].value]],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
this.barChart = {
|
||||||
|
type: "Bar",
|
||||||
|
data: dataBar.Bar,
|
||||||
|
options: {
|
||||||
|
fullwidth: true,
|
||||||
|
width: "100px",
|
||||||
|
height: "150px",
|
||||||
|
seriesBarDistance: 100,
|
||||||
|
axisX: {
|
||||||
|
showGrid: false,
|
||||||
|
showLabel: false,
|
||||||
|
offset: 5,
|
||||||
|
},
|
||||||
|
axisY: {
|
||||||
|
showGrid: false,
|
||||||
|
showLabel: false,
|
||||||
|
scaleMinSpace: 30,
|
||||||
|
},
|
||||||
|
classNames: {
|
||||||
|
bar: "ct-bar", // Menambahkan kelas CSS ke batang
|
||||||
|
},
|
||||||
|
},
|
||||||
|
responsiveOptions: [
|
||||||
|
[
|
||||||
|
"screen and (max-width: 640px)",
|
||||||
|
{
|
||||||
|
seriesBarDistance: 100,
|
||||||
|
axisX: {
|
||||||
|
labelInterpolationFnc: function (value) {
|
||||||
|
return value[0];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dataCompActEstCost(buildingId) {
|
||||||
|
this.costService.getCompActEstCost(buildingId).subscribe((data) => {
|
||||||
|
this.dataCompAct = data.data[0];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
syncData() {
|
||||||
|
const dataDate = {
|
||||||
|
buildingId: this.buildingSelected,
|
||||||
|
periode: this.dateSelected,
|
||||||
|
};
|
||||||
|
this.spinnerActive = true;
|
||||||
|
this.costService.getSyncCost(dataDate).subscribe((data) => {
|
||||||
|
console.log(data);
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
this.spinnerActive = false;
|
||||||
|
this.fetchData(this.buildingSelected, this.dateSelected, this.categorySelected );
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
actualData() {
|
||||||
|
this.spinnerActiveActual = true;
|
||||||
|
this.costService
|
||||||
|
.getRealCostByBuildingId(4, this.dateSelected)
|
||||||
|
.subscribe((data) => {
|
||||||
|
console.log(data.data[0]);
|
||||||
|
// this.costTerm = data.data[0].est_cost
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
this.spinnerActiveActual = false;
|
||||||
|
this.fetchData(this.buildingSelected, this.dateSelected, this.categorySelected );
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
doFilter() {
|
||||||
|
const requestData = {
|
||||||
|
building: this.buildingSelected,
|
||||||
|
category: this.categorySelected,
|
||||||
|
date: this.dateSelected,
|
||||||
|
searchTerm: this.searchTerm,
|
||||||
|
};
|
||||||
|
this.fetchData(this.buildingSelected, this.dateSelected, this.categorySelected );
|
||||||
|
this.dataCompWaterElectCost(this.buildingSelected);
|
||||||
|
this.dataCompPrevMonthCost(this.buildingSelected);
|
||||||
|
this.dataCompActEstCost(this.buildingSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
addFieldValue() {
|
||||||
|
const modalRef = this.modalService.open(ModalAddActualComponent, {
|
||||||
|
size: "sm",
|
||||||
|
});
|
||||||
|
modalRef.componentInstance.newAttribute = {
|
||||||
|
id: null,
|
||||||
|
name: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
modalRef.result.then(
|
||||||
|
(result) => {
|
||||||
|
if (result) {
|
||||||
|
this.rows.push(result);
|
||||||
|
this.rows = [...this.rows];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(reason) => {
|
||||||
|
console.log(`Dismissed: ${reason}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
focusElement(focucedElement: any) {
|
||||||
|
this.focucedElement = focucedElement;
|
||||||
|
}
|
||||||
|
|
||||||
filterRows() {
|
filterRows() {
|
||||||
if (!this.searchTerm) {
|
if (!this.searchTerm) {
|
||||||
this.filteredRows = [...this.data.rows];
|
this.filteredRows = [...this.data.rows];
|
||||||
|
@ -147,8 +293,7 @@ export class CostManagementComponent implements OnInit{
|
||||||
const searchTermLC = this.searchTerm.toLowerCase();
|
const searchTermLC = this.searchTerm.toLowerCase();
|
||||||
return Object.values(row).some(
|
return Object.values(row).some(
|
||||||
(value) =>
|
(value) =>
|
||||||
value !== null &&
|
value !== null && value.toString().toLowerCase().includes(searchTermLC)
|
||||||
value.toString().toLowerCase().includes(searchTermLC)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,4 +314,6 @@ export class CostManagementComponent implements OnInit{
|
||||||
onTouchStart(event: Event) {
|
onTouchStart(event: Event) {
|
||||||
event.preventDefault(); // Add this if necessary
|
event.preventDefault(); // Add this if necessary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule, DatePipe } from '@angular/common';
|
||||||
import { CostManagementComponent } from './cost-management.component';
|
import { CostManagementComponent } from './cost-management.component';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { BreadcrumbModule } from 'src/app/_layout/breadcrumb/breadcrumb.module';
|
import { BreadcrumbModule } from 'src/app/_layout/breadcrumb/breadcrumb.module';
|
||||||
|
@ -15,13 +15,16 @@ import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { NgChartsModule } from 'ng2-charts';
|
import { NgChartsModule } from 'ng2-charts';
|
||||||
import { ChartistModule } from 'ng-chartist';
|
import { ChartistModule } from 'ng-chartist';
|
||||||
|
import { MatchHeightModule } from '../../partials/general/match-height/match-height.module';
|
||||||
|
import { ModalAddActualComponent } from './modal-add-actual/modal-add-actual.component';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
CostManagementComponent,
|
CostManagementComponent,
|
||||||
AddEditCostComponent
|
AddEditCostComponent,
|
||||||
|
ModalAddActualComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
@ -36,6 +39,7 @@ import { ChartistModule } from 'ng-chartist';
|
||||||
NgxDatatableModule,
|
NgxDatatableModule,
|
||||||
NgChartsModule,
|
NgChartsModule,
|
||||||
ChartistModule,
|
ChartistModule,
|
||||||
|
MatchHeightModule,
|
||||||
BlockUIModule.forRoot({
|
BlockUIModule.forRoot({
|
||||||
template: BlockTemplateComponent
|
template: BlockTemplateComponent
|
||||||
}),
|
}),
|
||||||
|
@ -60,6 +64,9 @@ import { ChartistModule } from 'ng-chartist';
|
||||||
data: { mode: 'view' }
|
data: { mode: 'view' }
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
]
|
],
|
||||||
|
providers: [
|
||||||
|
DatePipe // Add DatePipe to providers
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class CostManagementModule { }
|
export class CostManagementModule { }
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* modal-add-edit.component.css */
|
||||||
|
::ng-deep .modal-backdrop.show {
|
||||||
|
z-index: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep .input-group-append .btn {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
border-left: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
border-left: 1px solid #ced4da;
|
||||||
|
padding: 0.375rem 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep .input-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap; /* Prevents wrapping of the items */
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep .form-control {
|
||||||
|
flex-grow: 1; /* Ensures select takes up available space */
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep .input-group select,
|
||||||
|
::ng-deep .input-group .input-group-append .btn {
|
||||||
|
padding-right: 5px; /* Adjust padding if necessary */
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep .input-group .form-control {
|
||||||
|
margin-right: 2px; /* Adjust margin to make space */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(1.5em + 0.75rem + 2px);
|
||||||
|
padding: 0.375rem 0.75rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #495057;
|
||||||
|
background-color: #fff;
|
||||||
|
background-clip: padding-box;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<div class="modal-header">
|
||||||
|
<!-- <h4 class="modal-title">Add New Row</h4> -->
|
||||||
|
<button type="button" class="close" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form [formGroup]="myForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name">Name:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="name"
|
||||||
|
formControlName="name"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-secondary"
|
||||||
|
(click)="activeModal.dismiss('Cross click')"
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-primary" (click)="addRow()">
|
||||||
|
Save Changes
|
||||||
|
</button>
|
||||||
|
</div>
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ModalAddActualComponent } from './modal-add-actual.component';
|
||||||
|
|
||||||
|
describe('ModalAddActualComponent', () => {
|
||||||
|
let component: ModalAddActualComponent;
|
||||||
|
let fixture: ComponentFixture<ModalAddActualComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ ModalAddActualComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ModalAddActualComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-modal-add-actual',
|
||||||
|
templateUrl: './modal-add-actual.component.html',
|
||||||
|
styleUrls: ['./modal-add-actual.component.css']
|
||||||
|
})
|
||||||
|
export class ModalAddActualComponent {
|
||||||
|
@Input() newAttribute: any = {};
|
||||||
|
myForm: FormGroup;
|
||||||
|
|
||||||
|
constructor(public activeModal: NgbActiveModal, private fb: FormBuilder) {
|
||||||
|
this.createForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
createForm() {
|
||||||
|
this.myForm = this.fb.group({
|
||||||
|
name: ['', Validators.required],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addRow() {
|
||||||
|
if (this.myForm.valid) {
|
||||||
|
this.activeModal.close(this.myForm.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -94,7 +94,7 @@
|
||||||
[items]="singleSelectArray"
|
[items]="singleSelectArray"
|
||||||
[searchable]="true"
|
[searchable]="true"
|
||||||
bindLabel="item_text"
|
bindLabel="item_text"
|
||||||
placeholder="Select Month"
|
placeholder="Select Type"
|
||||||
[(ngModel)]="singlebasicSelected"
|
[(ngModel)]="singlebasicSelected"
|
||||||
>
|
>
|
||||||
</ng-select>
|
</ng-select>
|
||||||
|
|
|
@ -67,16 +67,14 @@ export class DeviceComponent implements OnInit {
|
||||||
console.log(this.filteredRows);
|
console.log(this.filteredRows);
|
||||||
this.totalOn = this.filteredRows.filter((row) => row.statusEntity.name.toLowerCase() === 'aktif').length
|
this.totalOn = this.filteredRows.filter((row) => row.statusEntity.name.toLowerCase() === 'aktif').length
|
||||||
this.totalOff = this.filteredRows.filter((row) => row.statusEntity.name.toLowerCase() === 'nonaktif').length
|
this.totalOff = this.filteredRows.filter((row) => row.statusEntity.name.toLowerCase() === 'nonaktif').length
|
||||||
// console.log(totalon);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
filterRows() {
|
filterRows() {
|
||||||
if (!this.searchTerm) {
|
if (!this.searchTerm) {
|
||||||
this.filteredRows = [...this.data.rows];
|
this.filteredRows = [...this.data.results.data];
|
||||||
} else {
|
} else {
|
||||||
this.filteredRows = this.data.rows.filter((row) =>
|
this.filteredRows = this.data.results.data.filter((row) =>
|
||||||
this.rowContainsSearchTerm(row)
|
this.rowContainsSearchTerm(row)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -135,14 +133,10 @@ export class DeviceComponent implements OnInit {
|
||||||
this.monitoringApiService.getSyncDeviceData().subscribe((res) => {
|
this.monitoringApiService.getSyncDeviceData().subscribe((res) => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Lakukan proses tambahan (misalnya, panggil API atau proses yang memakan waktu)
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// Selesaikan proses tambahan di sini
|
|
||||||
|
|
||||||
// Nonaktifkan spinner setelah proses selesai
|
|
||||||
this.spinnerActive = false;
|
this.spinnerActive = false;
|
||||||
this.fetchData();
|
this.fetchData();
|
||||||
}, 3000); // Ganti 3000 dengan waktu yang sesuai dengan proses tambahan Anda (dalam milidetik)
|
}, 3000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12" *blockUI="'barCharts'; message: 'Loading'">
|
<div class="col-12" *blockUI="'barCharts'; message: 'Loading'">
|
||||||
<m-card [options]="options">
|
<m-card [options]="options">
|
||||||
<ng-container mCardHeaderTitle> Appointment </ng-container>
|
<ng-container mCardHeaderTitle> </ng-container>
|
||||||
<ng-container mCardBody>
|
<ng-container mCardBody>
|
||||||
<div class="z" style="display: block">
|
<div class="z" style="display: block">
|
||||||
<canvas
|
<canvas
|
||||||
|
|
|
@ -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 CostManagementService {
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
getCostManagement(id, period, category): Observable<any> {
|
||||||
|
const baseUrl = `https://kapi.absys.ninja/hemat/cost_management`;
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
page: "1",
|
||||||
|
limit: "100",
|
||||||
|
building_id: id,
|
||||||
|
periode: period,
|
||||||
|
});
|
||||||
|
if (category) {
|
||||||
|
params.append("category_id", category);
|
||||||
|
}
|
||||||
|
const url = `${baseUrl}?${params.toString()}`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
getCompWaterElectCost(id): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/cost_management/card/comp-water-elect-cost?building_id=${id}`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
getCompPrevMonthCost(id): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/cost_management/card/comp-prev-month-cost?building_id=${id}`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
getCompActEstCost(id): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/cost_management/card/comp-act-est-cost?building_id=${id}`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
getSyncCost(data: any): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/cost_management/cost/sync`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||||
|
});
|
||||||
|
return this.http.post<any>(url, data, { headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
getRealCostByBuildingId(id: any, period: any): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/real-cost/get/byBuildingId?building_id=${id}&periode=${period}`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
}
|
|
@ -135,6 +135,15 @@ export class BuildingService {
|
||||||
return this.http.get<any>(url, { headers });
|
return this.http.get<any>(url, { headers });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCostManagement(page: number = 1, limit: number = 100, ): Observable<any> {
|
||||||
|
const url = `https://kapi.absys.ninja/hemat/cost_management?page=${page}&limit=${limit}&building_id=4&periode=2024-06`;
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||||
|
});
|
||||||
|
return this.http.get<any>(url, { headers });
|
||||||
|
}
|
||||||
|
|
||||||
postHeaderDetailParam(data: any): Observable<any> {
|
postHeaderDetailParam(data: any): Observable<any> {
|
||||||
const url = `https://kapi.absys.ninja/hemat/header-detail-param`;
|
const url = `https://kapi.absys.ninja/hemat/header-detail-param`;
|
||||||
const headers = new HttpHeaders({
|
const headers = new HttpHeaders({
|
||||||
|
|
|
@ -122,6 +122,7 @@ export class LoginComponent implements OnInit {
|
||||||
// Store the user profile information
|
// Store the user profile information
|
||||||
const userProfile = {
|
const userProfile = {
|
||||||
displayName: this.loginForm.value.email,
|
displayName: this.loginForm.value.email,
|
||||||
|
buildingId: 4
|
||||||
};
|
};
|
||||||
localStorage.setItem('currentUser', JSON.stringify(userProfile));
|
localStorage.setItem('currentUser', JSON.stringify(userProfile));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue