labor-entry-page.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. const app = require('../app')
  2. const moment = require('moment-immutable')
  3. const { editIcon, calculatedIcon, dollarIcon } = require('../assets')
  4. app.component('appLaborEntryPage', {
  5. template: html`
  6. <app-user-area title-text="{{ctrl.terminalKey}} Labor Entry">
  7. <app-breadcrumb links="[
  8. { text: 'Home', link: '/dashboard' },
  9. { text: ctrl.terminalKey + ' Labor', link: '/labor/' + ctrl.terminalKey },
  10. { text: ctrl.startDate.format('L') + ' - ' + ctrl.endDate.format('L'), link: '/labor/' + ctrl.terminalKey + '/' + ctrl.startDate.format('YYYY-MM-DD') }
  11. ]"></app-breadcrumb>
  12. <p>For week of {{ctrl.startDate.format('LL')}} to {{ctrl.endDate.format('LL')}}</p>
  13. <div>
  14. <md-input-container class="md-margin">
  15. <label>Labor Cost</label>
  16. <input type="text" readonly value="{{ctrl.model.workweek.laborCost | currency}}" />
  17. <md-icon md-svg-src="${calculatedIcon}">
  18. <md-tooltip md-direction="down" style="height: 7em">
  19. This field is calculated, <br/>
  20. and cannot be edited directly. <br />
  21. Save your changes to update.
  22. </md-tooltip>
  23. </md-icon>
  24. </md-input-container>
  25. <md-input-container class="md-margin">
  26. <label>Labor Charge</label>
  27. <input type="number" min="0" step="0.01" ng-model="ctrl.model.workweek.laborCharge" />
  28. <md-icon md-svg-src="${dollarIcon}"></md-icon>
  29. </md-input-container>
  30. <md-input-container class="md-margin" ng-if="ctrl.model.workweek.laborCharge && ctrl.model.workweek.laborCost">
  31. <label>Difference</label>
  32. <input type="text" readonly value="{{(ctrl.model.workweek.laborCost - ctrl.model.workweek.laborCharge) | currency}} or {{(ctrl.model.workweek.laborCharge / ctrl.model.workweek.laborCost) * 100 | number : 1}}%" />
  33. <md-icon md-svg-src="${calculatedIcon}">
  34. <md-tooltip md-direction="down" style="height: 7em">
  35. This field is calculated, <br/>
  36. and cannot be edited directly. <br />
  37. Save your changes to update.
  38. </md-tooltip>
  39. </md-icon>
  40. </md-input-container>
  41. </div>
  42. <form name="form" ng-submit="ctrl.submit()">
  43. <table md-table md-progress="ctrl.promise">
  44. <colgroup>
  45. <col style="width: 15%" />
  46. <col ng-repeat="weekday in ctrl.model.weekdays" style="width: 12%" />
  47. </colgroup>
  48. <thead md-head>
  49. <tr md-row>
  50. <th md-column>Staff Member</th>
  51. <th md-column ng-repeat="weekday in ctrl.weekdays">
  52. <span hide show-xs>{{weekday.min}}</span>
  53. <span hide show-sm>{{weekday.short}}</span>
  54. <span hide show-gt-sm>{{weekday.name}}</span>
  55. </th>
  56. </tr>
  57. </thead>
  58. <tbody md-body>
  59. <tr md-row ng-repeat="sfl in ctrl.staffMemberLabor track by sfl.id">
  60. <td md-cell>
  61. {{ctrl.staffMembers[sfl.id].name}}
  62. </td>
  63. <td md-cell ng-repeat="day in sfl.days track by $index">
  64. <input
  65. class="hour-input md-button md-raised"
  66. tabindex="{{$index * ctrl.staffMemberLabor.length + ($parent.$index) + 1}}"
  67. ng-model="day.hours"
  68. type="number" min="0" step="0.01">
  69. </td>
  70. </tr>
  71. </tbody>
  72. </table>
  73. <div>
  74. <md-button type="submit" class="md-raised md-primary">Submit</md-button>
  75. </div>
  76. </form>
  77. </app-user-area>
  78. `,
  79. controllerAs: 'ctrl',
  80. controller: function(api, $routeParams, weekdays, $mdToast) {
  81. this.weekdays = weekdays
  82. this.terminalKey = $routeParams.terminal
  83. const week = moment($routeParams.week)
  84. if (!week.isSame(week.startOf('week'))) throw new Error('Date is not start of week')
  85. this.startDate = week
  86. this.endDate = week.endOf('week')
  87. api.staffMemberDictionary().then(staffMembers => {
  88. this.staffMembers = staffMembers
  89. })
  90. const load = () => {
  91. this.promise = api.get(`/api/labor/${$routeParams.terminal}/${$routeParams.week}`).then((model) => {
  92. this.model = model
  93. const staffMemberIds = this.model.workdays[0].labor.map(x => x.staffMemberId)
  94. this.staffMemberLabor = staffMemberIds.map((id, i) => ({
  95. id,
  96. days: this.model.workdays.map(wd => wd.labor[i])
  97. }))
  98. })
  99. }
  100. load()
  101. this.submit = async () => {
  102. const model = {
  103. workweek: this.model.workweek,
  104. workdays: this.model.workdays.map(workday => ({
  105. labor: workday.labor.map(labor => ({
  106. staffMemberId: labor.staffMemberId,
  107. hours: labor.hours || null
  108. }))
  109. }))
  110. }
  111. try {
  112. await api.patch(`/api/labor/${$routeParams.terminal}/${$routeParams.week}`, model)
  113. $mdToast.showSimple('Labor saved.')
  114. load()
  115. } catch (err) {
  116. window.err = err
  117. console.error(err)
  118. $mdToast.showSimple(`Could not save Labor: ${err.message || err.statusText || err}`)
  119. }
  120. }
  121. }
  122. })