| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- const app = require('../app')
- const moment = require('moment-immutable')
- const _ = require('lodash')
- const { previousWeekIcon, previousDayIcon, nextDayIcon, nextWeekIcon } = require('../assets')
- app.component('appDashboardPage', {
- template: html`
- <app-user-area title-text="Dashboard">
- <div>
- <md-button
- class="md-fab"
- ng-click="$ctrl.setOffset($ctrl.offset - 7)">
- <md-icon md-svg-src="${previousWeekIcon}"></md-icon>
- </md-button>
- <md-button
- class="md-fab"
- ng-click="$ctrl.setOffset($ctrl.offset - 1)">
- <md-icon md-svg-src="${previousDayIcon}"></md-icon>
- </md-button>
- <span
- ng-repeat="workday in $ctrl.workdays track by workday.formatted"
- ng-init="
- invalid = workday.hasData && (!workday.hasLabor || !workday.hasService);
- valid = workday.hasData && workday.hasLabor && workday.hasService;
- tooltip = workday.hasData
- ? (
- workday.hasLabor && workday.hasService
- ? ''
- : workday.hasLabor
- ? workday.formatted + ' has Labor data, but no Service data.'
- : workday.hasService
- ? workday.formatted + ' has Service data, but no Service data.'
- : workday.formatted + ' is missing Labor and Service data.'
- ): 'No data exists for ' + workday.formatted + '.';"
- title="{{tooltip}}"
- ng-click="tooltip && $ctrl.$mdToast.showSimple(tooltip)">
- <md-button
- style="min-width: auto; width: 3em;"
- class="md-raised md-mini"
- ng-class="{
- 'md-primary': workday.date.valueOf() == $ctrl.date.valueOf()
- }"
- ng-disabled="!valid"
- ng-click="$ctrl.setDate(workday.date)"
- md-badge="{{
- invalid
- ? '!'
- : ''
- }}">
- {{workday.short}}
- </md-button>
- </span>
- <md-button
- class="md-fab"
- ng-click="$ctrl.setOffset($ctrl.offset + 1)">
- <md-icon md-svg-src="${nextDayIcon}"></md-icon>
- </md-button>
- <md-button
- class="md-fab"
- ng-click="$ctrl.setOffset($ctrl.offset + 7)">
- <md-icon md-svg-src="${nextWeekIcon}"></md-icon>
- </md-button>
- </div>
- <h2>{{$ctrl.date.format('LL')}}</h2>
- <div flex layout="row" ng-show="$ctrl.statistics">
- <md-card flex ng-repeat="serviceCategory in $ctrl.statistics.serviceCategories">
- <md-card-content>
- <h2>{{::$ctrl.serviceCategories[serviceCategory.key].name}}</h2>
- <div flex layout="row">
- <md-card flex="30" md-whiteframe="15">
- <md-card-title><md-card-title-text style="text-align: center">
- Cartons
- </md-card-title-text></md-card-title>
- <md-card-content>
- <h1 style="text-align: center">{{serviceCategory.lastMetrics[serviceCategory.serviceColumn] || 0}}</h1>
- </md-card-content>
- </md-card>
- <md-card flex="30" md-whiteframe="15">
- <md-card-title><md-card-title-text style="text-align: center">
- Labor Cost
- </md-card-title-text></md-card-title>
- <md-card-content>
- <h1 ng-if="serviceCategory.lastMetrics.laborCost" style="text-align: center">$\{{Math.floor(serviceCategory.lastMetrics.laborCost) || null}}</h1>
- <h1 ng-if="!serviceCategory.lastMetrics.laborCost" style="text-align: center">N/A</h1>
- </md-card-content>
- </md-card>
- <md-card flex="30" md-whiteframe="15">
- <md-card-title><md-card-title-text style="text-align: center">
- Cost per Carton
- </md-card-title-text></md-card-title>
- <md-card-content>
- <h1 ng-if="serviceCategory.lastMetrics.costPer" style="text-align: center">{{serviceCategory.lastMetrics.costPer | currency}}</h1>
- <h1 ng-if="!serviceCategory.lastMetrics.costPer" style="text-align: center">N/A</h1>
- </md-card-content>
- </md-card>
- </div>
- <div ng-repeat="terminal in serviceCategory.terminals">
- <table md-table>
- <thead>
- <th align="left">
- <h4>{{::$ctrl.terminals[terminal.terminal].name}}</h4>
- </th>
- <th align="right">
- <span ng-if="$index == 0">Cost per Carton</span>
- </th>
- </thead>
- <tbody>
- <tr ng-repeat="laborCategory in terminal.laborCategories">
- <th align="left">{{::$ctrl.laborCategories[laborCategory.laborCategory].name}}</th>
- <td align="right">{{laborCategory.costPer | currency}}</td>
- </tr>
- <tr ng-if="terminal.laborCategories.length > 1">
- <th align="left">All</th>
- <td align="right">{{terminal.costPer | currency}}</td>
- </tr>
- </tbody>
- </table>
- <hr />
- </div>
- <div ng-if="serviceCategory.terminals.length > 1">
- <table md-table>
- <thead>
- <th align="left">
- <h4>Overall</h4>
- </th>
- <th align="right"></th>
- </thead>
- <tbody>
- <tr ng-repeat="laborCategory in serviceCategory.laborCategories">
- <th align="left">{{::$ctrl.laborCategories[laborCategory.laborCategory].name}}</th>
- <td align="right">{{laborCategory.costPer | currency}}</td>
- </tr>
- <tr ng-if="serviceCategory.laborCategories.length > 1">
- <th align="left">All</th>
- <td align="right">{{serviceCategory.costPer | currency}}</td>
- </tr>
- </tbody>
- </table>
- </div>
- <md-card>
- <md-card-title>
- <md-card-title-text>Labor cost</md-card-title-text>
- </md-card-title>
- <md-card-content>
- <div style="width: 520px; height: 260px;" >
- <canvas class="chart chart-line" chart-data="serviceCategory.charts.laborCost.data" chart-colors="serviceCategory.charts.laborCost.colors"
- chart-labels="serviceCategory.charts.laborCost.labels" chart-series="serviceCategory.charts.laborCost.series" chart-options="serviceCategory.charts.laborCost.options">
- </canvas>
- </div>
- <div ng-repeat="color in serviceCategory.charts.laborCost.colors">
- <div style="background-color: {{color}}; width: 16px; height: 16px; display: inline-block; margin: 0 4px;"></div>
- {{$ctrl.charts.costPerCarton.series[$index]}}
- </div>
- </md-card-content>
- </md-card>
- <md-card>
- <md-card-title>
- <md-card-title-text>Cost per carton</md-card-title-text>
- </md-card-title>
- <md-card-content>
- <div style="width: 520px; height: 260px;" >
- <canvas class="chart chart-line" chart-data="serviceCategory.charts.costPerCarton.data" chart-colors="serviceCategory.charts.costPerCarton.colors"
- chart-labels="serviceCategory.charts.costPerCarton.labels" chart-series="serviceCategory.charts.costPerCarton.series" chart-options="serviceCategory.charts.costPerCarton.options">
- </canvas>
- </div>
- <div ng-repeat="color in serviceCategory.charts.costPerCarton.colors">
- <div style="background-color: {{color}}; width: 16px; height: 16px; display: inline-block; margin: 0 4px;"></div>
- {{$ctrl.charts.costPerCarton.series[$index]}}
- </div>
- </md-card-content>
- </md-card>
- </md-card-content>
- </md-card>
- </div>
- <div flex layout="column" ng-show="$ctrl.charts" layout-gt-sm="row">
- <md-card flex="50" class="mg-margin md-padding">
- <md-card-title>
- <md-card-title-text>
- <span class="md-headline">Labor Costs</span>
- <span class="md-subhead"></span>
- </md-card-title-text>
- </md-card-title>
- <md-card-content>
- <div style="width: 520px; height: 260px;" >
- <canvas class="chart chart-line" chart-data="$ctrl.charts.laborCost.data" chart-colors="$ctrl.charts.laborCost.colors"
- chart-labels="$ctrl.charts.laborCost.labels" chart-series="$ctrl.charts.laborCost.series" chart-options="$ctrl.charts.laborCost.options">
- </canvas>
- </div>
- <div ng-repeat="color in $ctrl.charts.laborCost.colors">
- <div style="background-color: {{color}}; width: 16px; height: 16px; display: inline-block; margin: 0 4px;"></div>
- {{$ctrl.charts.laborCost.series[$index]}}
- </div>
- </md-card-content>
- </md-card>
- <md-card flex="50" class="mg-margin md-padding">
- <md-card-title>
- <md-card-title-text>
- <span class="md-headline">Cost per Carton</span>
- <span class="md-subhead"></span>
- </md-card-title-text>
- </md-card-title>
- <md-card-content>
- <div style="width: 520px; height: 260px;" >
- <canvas class="chart chart-line" chart-data="$ctrl.charts.costPerCarton.data" chart-colors="$ctrl.charts.costPerCarton.colors"
- chart-labels="$ctrl.charts.costPerCarton.labels" chart-series="$ctrl.charts.costPerCarton.series" chart-options="$ctrl.charts.costPerCarton.options">
- </canvas>
- </div>
- <div ng-repeat="color in $ctrl.charts.costPerCarton.colors">
- <div style="background-color: {{color}}; width: 16px; height: 16px; display: inline-block; margin: 0 4px;"></div>
- {{$ctrl.charts.costPerCarton.series[$index]}}
- </div>
- </md-card-content>
- </md-card>
- </div>
- </app-user-area>
- `,
- controller: function(api, statistics, $scope, $mdToast) {
- this.$mdToast = $mdToast
- $scope.Math = Math
- const load = (date) => {
- api.statistics(date).then(stats => {
- this.statistics = stats
- stats.serviceCategories.forEach(serviceCategory => {
- serviceCategory.charts = {
- costPerCarton: statistics.chart({
- rows: serviceCategory.metricsOverTime,
- seriesField: 'key',
- dataField: 'costPer',
- labelsField: 'date',
- format: (label, value) => `${label}: $${value.toFixed(2)} per carton`
- }),
- laborCost: statistics.chart({
- rows: serviceCategory.metricsOverTime,
- seriesField: 'key',
- dataField: 'laborCost',
- labelsField: 'date',
- format: (label, value) => `${label}: $${value.toFixed(2)} labor cost`
- })
- }
- })
- this.charts = statistics.charts(stats.metricsOverTime)
- this.last = stats.last
- })
- }
- api.terminals().then(terminals => {
- this.terminals = terminals
- })
- api.laborCategories().then(laborCategories => {
- this.laborCategories = laborCategories
- })
- api.serviceCategories().then(serviceCategories => {
- this.serviceCategories = serviceCategories
- })
- api.get(`/api/workdays`).then(results => {
- const wds = {}
- results.workdays.forEach(wd => (wds[moment(wd.date).format('YYYY-MM-DD')] = wd))
- const getWorkdays = (offset) => {
- const dates = _.range(offset - 6, offset + 1)
- .map(x => {
- const date = moment().startOf('day').add(x, 'days')
- const workday = wds[date.format('YYYY-MM-DD')]
- return {
- date,
- formatted: date.format('L'),
- short: date.format('M/DD'),
- hasData: !!workday,
- hasLabor: workday && workday.hasLabor,
- hasService: workday && workday.hasService
- }
- })
- return dates
- }
- this.setOffset = (offset) => {
- this.offset = offset
- this.workdays = getWorkdays(offset)
- }
- this.setDate = (date) => {
- this.date = date
- this.now = moment()
- load(date)
- }
- const defaultWorkday = results.workdays.slice(0).reverse().find(x => x.hasLabor && x.hasService)
- if (defaultWorkday) {
- this.setDate(moment(defaultWorkday.date))
- this.setOffset(3 - (moment().diff(moment(defaultWorkday.date), 'days')))
- } else {
- this.setOffset(0)
- }
- // this.setDate(moment(
- // results.workdays
- // .map(wd => moment(wd.date).valueOf())
- // .sort()
- // .pop() || moment.now()
- // ))
- })
- // statistics.costPerCarton().then(statistics => {
- // Object.assign(this, statistics)
- // })
- }
- })
- window.moment = moment
|