dashboard-page.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. const app = require('../app')
  2. const moment = require('moment-immutable')
  3. const _ = require('lodash')
  4. const { previousWeekIcon, previousDayIcon, nextDayIcon, nextWeekIcon } = require('../assets')
  5. app.component('appDashboardPage', {
  6. template: html`
  7. <app-user-area title-text="Dashboard">
  8. <div>
  9. <md-button
  10. class="md-fab"
  11. ng-click="$ctrl.setOffset($ctrl.offset - 7)">
  12. <md-icon md-svg-src="${previousWeekIcon}"></md-icon>
  13. </md-button>
  14. <md-button
  15. class="md-fab"
  16. ng-click="$ctrl.setOffset($ctrl.offset - 1)">
  17. <md-icon md-svg-src="${previousDayIcon}"></md-icon>
  18. </md-button>
  19. <md-button
  20. style="min-width: auto; width: 3em;"
  21. class="md-raised md-mini"
  22. ng-repeat="workday in $ctrl.workdays track by workday.formatted"
  23. ng-class="{
  24. 'md-primary': workday.date.valueOf() == $ctrl.date.valueOf()
  25. }"
  26. ng-disabled="!workday.hasData"
  27. ng-click="$ctrl.setDate(workday.date)"
  28. >
  29. {{workday.short}}
  30. </md-button>
  31. <md-button
  32. class="md-fab"
  33. ng-click="$ctrl.setOffset($ctrl.offset + 1)">
  34. <md-icon md-svg-src="${nextDayIcon}"></md-icon>
  35. </md-button>
  36. <md-button
  37. class="md-fab"
  38. ng-click="$ctrl.setOffset($ctrl.offset + 7)">
  39. <md-icon md-svg-src="${nextWeekIcon}"></md-icon>
  40. </md-button>
  41. </div>
  42. <h2>{{$ctrl.date.format('LL')}}</h2>
  43. <div flex layout="row" ng-show="$ctrl.statistics">
  44. <md-card flex ng-repeat="serviceCategory in $ctrl.statistics.serviceCategories">
  45. <md-card-content>
  46. <h2>{{::$ctrl.serviceCategories[serviceCategory.serviceCategory].name}}</h2>
  47. <div flex layout="row">
  48. <md-card flex="30" md-whiteframe="15">
  49. <md-card-title><md-card-title-text style="text-align: center">
  50. Cartons
  51. </md-card-title-text></md-card-title>
  52. <md-card-content>
  53. <h1 style="text-align: center">{{serviceCategory.lastMetrics[serviceCategory.serviceColumn]}}</h1>
  54. </md-card-content>
  55. </md-card>
  56. <md-card flex="30" md-whiteframe="15">
  57. <md-card-title><md-card-title-text style="text-align: center">
  58. Labor Cost
  59. </md-card-title-text></md-card-title>
  60. <md-card-content>
  61. <h1 ng-if="serviceCategory.lastMetrics.laborCost" style="text-align: center">$\{{Math.floor(serviceCategory.lastMetrics.laborCost) || null}}</h1>
  62. </md-card-content>
  63. </md-card>
  64. <md-card flex="30" md-whiteframe="15">
  65. <md-card-title><md-card-title-text style="text-align: center">
  66. Cost per Carton
  67. </md-card-title-text></md-card-title>
  68. <md-card-content>
  69. <h1 style="text-align: center">{{serviceCategory.lastMetrics.costPer | currency}}</h1>
  70. </md-card-content>
  71. </md-card>
  72. </div>
  73. <div ng-repeat="terminal in serviceCategory.terminals">
  74. <table md-table>
  75. <thead>
  76. <th align="left">
  77. <h4>{{::$ctrl.terminals[terminal.terminal].name}}</h4>
  78. </th>
  79. <th align="right">
  80. <span ng-if="$index == 0">Cost per Carton</span>
  81. </th>
  82. </thead>
  83. <tbody>
  84. <tr ng-repeat="laborCategory in terminal.laborCategories">
  85. <th align="left">{{::$ctrl.laborCategories[laborCategory.laborCategory].name}}</th>
  86. <td align="right">{{laborCategory.costPer | currency}}</td>
  87. </tr>
  88. <tr ng-if="terminal.laborCategories.length > 1">
  89. <th align="left">All</th>
  90. <td align="right">{{terminal.costPer | currency}}</td>
  91. </tr>
  92. </tbody>
  93. </table>
  94. <hr />
  95. </div>
  96. <div ng-if="serviceCategory.terminals.length > 1">
  97. <table md-table>
  98. <thead>
  99. <th align="left">
  100. <h4>Overall</h4>
  101. </th>
  102. <th align="right"></th>
  103. </thead>
  104. <tbody>
  105. <tr ng-repeat="laborCategory in serviceCategory.laborCategories">
  106. <th align="left">{{::$ctrl.laborCategories[laborCategory.laborCategory].name}}</th>
  107. <td align="right">{{laborCategory.costPer | currency}}</td>
  108. </tr>
  109. <tr ng-if="serviceCategory.laborCategories.length > 1">
  110. <th align="left">All</th>
  111. <td align="right">{{serviceCategory.costPer | currency}}</td>
  112. </tr>
  113. </tbody>
  114. </table>
  115. </div>
  116. </md-card-content>
  117. </md-card>
  118. </div>
  119. <div flex layout="column" ng-show="$ctrl.charts" layout-gt-sm="row">
  120. <md-card flex="50" class="mg-margin md-padding">
  121. <md-card-title>
  122. <md-card-title-text>
  123. <span class="md-headline">Labor Costs</span>
  124. <span class="md-subhead"></span>
  125. </md-card-title-text>
  126. </md-card-title>
  127. <md-card-content>
  128. <div style="width: 520px; height: 260px;" >
  129. <canvas class="chart chart-line" chart-data="$ctrl.charts.laborCost.data" chart-colors="$ctrl.charts.laborCost.colors"
  130. chart-labels="$ctrl.charts.laborCost.labels" chart-series="$ctrl.charts.laborCost.series" chart-options="$ctrl.charts.laborCost.options">
  131. </canvas>
  132. </div>
  133. <div ng-repeat="color in $ctrl.charts.laborCost.colors">
  134. <div style="background-color: {{color}}; width: 16px; height: 16px; display: inline-block; margin: 0 4px;"></div>
  135. {{$ctrl.charts.laborCost.series[$index]}}
  136. </div>
  137. </md-card-content>
  138. </md-card>
  139. <md-card flex="50" class="mg-margin md-padding">
  140. <md-card-title>
  141. <md-card-title-text>
  142. <span class="md-headline">Cost per Carton</span>
  143. <span class="md-subhead"></span>
  144. </md-card-title-text>
  145. </md-card-title>
  146. <md-card-content>
  147. <div style="width: 520px; height: 260px;" >
  148. <canvas class="chart chart-line" chart-data="$ctrl.charts.costPerCarton.data" chart-colors="$ctrl.charts.costPerCarton.colors"
  149. chart-labels="$ctrl.charts.costPerCarton.labels" chart-series="$ctrl.charts.costPerCarton.series" chart-options="$ctrl.charts.costPerCarton.options">
  150. </canvas>
  151. </div>
  152. <div ng-repeat="color in $ctrl.charts.costPerCarton.colors">
  153. <div style="background-color: {{color}}; width: 16px; height: 16px; display: inline-block; margin: 0 4px;"></div>
  154. {{$ctrl.charts.costPerCarton.series[$index]}}
  155. </div>
  156. </md-card-content>
  157. </md-card>
  158. </div>
  159. </app-user-area>
  160. `,
  161. controller: function(api, statistics, $scope) {
  162. $scope.Math = Math
  163. const load = (date) => {
  164. api.statistics(date).then(stats => {
  165. this.statistics = stats
  166. this.charts = statistics.charts(stats.metricsOverTime)
  167. this.last = stats.last
  168. })
  169. }
  170. api.terminals().then(terminals => {
  171. this.terminals = terminals
  172. })
  173. api.laborCategories().then(laborCategories => {
  174. this.laborCategories = laborCategories
  175. })
  176. api.serviceCategories().then(serviceCategories => {
  177. this.serviceCategories = serviceCategories
  178. })
  179. api.get(`/api/workdays`).then(workdays => {
  180. const wds = {}
  181. workdays.dates.forEach(x => (wds[x] = true))
  182. const getWorkdays = (offset) => {
  183. const dates = _.range(offset - 6, offset + 1)
  184. .map(x => {
  185. const date = moment().startOf('day').add(x, 'days')
  186. return {
  187. date,
  188. formatted: date.format('L'),
  189. short: date.format('M/DD'),
  190. hasData: wds[date.format('YYYY-MM-DD')]
  191. }
  192. })
  193. return dates
  194. }
  195. this.setOffset = (offset) => {
  196. this.offset = offset
  197. this.workdays = getWorkdays(offset)
  198. }
  199. this.setDate = (date) => {
  200. this.date = date
  201. this.now = moment()
  202. load(date)
  203. }
  204. this.setOffset(0)
  205. this.setDate(moment(
  206. workdays.dates
  207. .map(x => moment(x).valueOf())
  208. .sort()
  209. .pop() || moment.now()
  210. ))
  211. })
  212. // statistics.costPerCarton().then(statistics => {
  213. // Object.assign(this, statistics)
  214. // })
  215. }
  216. })
  217. window.moment = moment