@plusscommunities/pluss-maintenance-app 7.0.0-beta.0 → 7.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/module/actions/JobActions.js +44 -1
  2. package/dist/module/actions/JobActions.js.map +1 -1
  3. package/dist/module/actions/types.js +3 -0
  4. package/dist/module/actions/types.js.map +1 -1
  5. package/dist/module/apis/index.js +2 -0
  6. package/dist/module/apis/index.js.map +1 -1
  7. package/dist/module/apis/maintenanceActions.js +21 -6
  8. package/dist/module/apis/maintenanceActions.js.map +1 -1
  9. package/dist/module/components/FilterPopupMenu.js +34 -18
  10. package/dist/module/components/FilterPopupMenu.js.map +1 -1
  11. package/dist/module/components/MaintenanceList.js +47 -56
  12. package/dist/module/components/MaintenanceList.js.map +1 -1
  13. package/dist/module/components/MaintenanceListItem.js +39 -26
  14. package/dist/module/components/MaintenanceListItem.js.map +1 -1
  15. package/dist/module/components/MaintenanceWidgetItem.js +12 -12
  16. package/dist/module/components/MaintenanceWidgetItem.js.map +1 -1
  17. package/dist/module/components/PrioritySelectorPopup.js +82 -0
  18. package/dist/module/components/PrioritySelectorPopup.js.map +1 -0
  19. package/dist/module/components/StatusSelectorPopup.js +9 -14
  20. package/dist/module/components/StatusSelectorPopup.js.map +1 -1
  21. package/dist/module/components/WidgetSmall.js +7 -3
  22. package/dist/module/components/WidgetSmall.js.map +1 -1
  23. package/dist/module/helper.js +39 -25
  24. package/dist/module/helper.js.map +1 -1
  25. package/dist/module/reducers/JobsReducer.js +31 -2
  26. package/dist/module/reducers/JobsReducer.js.map +1 -1
  27. package/dist/module/screens/RequestDetail.js +90 -18
  28. package/dist/module/screens/RequestDetail.js.map +1 -1
  29. package/dist/module/screens/RequestNotes.js +430 -21
  30. package/dist/module/screens/RequestNotes.js.map +1 -1
  31. package/dist/module/values.config.a.js +6 -1
  32. package/dist/module/values.config.a.js.map +1 -1
  33. package/dist/module/values.config.default.js +6 -1
  34. package/dist/module/values.config.default.js.map +1 -1
  35. package/dist/module/values.config.forms.js +6 -1
  36. package/dist/module/values.config.forms.js.map +1 -1
  37. package/dist/module/values.config.js +34 -29
  38. package/dist/module/values.config.js.map +1 -1
  39. package/package.json +2 -2
  40. package/src/actions/JobActions.js +53 -1
  41. package/src/actions/types.js +4 -0
  42. package/src/apis/index.js +4 -0
  43. package/src/apis/maintenanceActions.js +18 -6
  44. package/src/components/FilterPopupMenu.js +40 -21
  45. package/src/components/MaintenanceList.js +38 -47
  46. package/src/components/MaintenanceListItem.js +35 -21
  47. package/src/components/MaintenanceWidgetItem.js +16 -12
  48. package/src/components/PrioritySelectorPopup.js +79 -0
  49. package/src/components/StatusSelectorPopup.js +8 -14
  50. package/src/components/WidgetSmall.js +5 -3
  51. package/src/helper.js +50 -21
  52. package/src/reducers/JobsReducer.js +25 -1
  53. package/src/screens/RequestDetail.js +87 -24
  54. package/src/screens/RequestNotes.js +429 -30
  55. package/src/values.config.a.js +5 -0
  56. package/src/values.config.default.js +5 -0
  57. package/src/values.config.forms.js +5 -0
  58. package/src/values.config.js +34 -29
package/src/helper.js CHANGED
@@ -1,39 +1,68 @@
1
- import { label } from 'aws-amplify';
2
1
  import { Colours } from './core.config';
3
2
 
3
+ const STATUS_NOT_ACTIONED = 'Not Actioned';
4
+ const STATUS_IN_PROGRESS = 'In Progress';
5
+ const STATUS_COMPLETED = 'Completed';
6
+
4
7
  const jobStatusOptions = [
5
8
  {
6
- name: 'Unassigned',
7
- label: 'Open',
9
+ text: 'Open',
10
+ order: 0,
8
11
  color: Colours.LINEGREY,
12
+ category: STATUS_NOT_ACTIONED,
9
13
  },
10
14
  {
11
- name: 'In Progress',
12
- label: 'In Progress',
15
+ text: 'In Progress',
16
+ order: 1,
13
17
  color: Colours.COLOUR_TEAL,
18
+ category: STATUS_IN_PROGRESS,
14
19
  },
15
20
  {
16
- name: 'Completed',
17
- label: 'Completed',
21
+ text: 'Completed',
22
+ order: 2,
18
23
  color: Colours.COLOUR_GREEN_LIGHT,
24
+ category: STATUS_COMPLETED,
19
25
  },
20
26
  ];
21
27
 
22
- const getJobStatusColour = status => {
23
- const option = jobStatusOptions.find(item => item.name === status);
24
- return option ? option.color : jobStatusOptions[0].color;
25
- };
28
+ const jobPriorityOptions = [
29
+ {
30
+ label: 'Low',
31
+ color: Colours.COLOUR_GREEN,
32
+ default: true,
33
+ },
34
+ {
35
+ label: 'Medium',
36
+ color: Colours.COLOUR_TANGERINE,
37
+ },
38
+ {
39
+ label: 'High',
40
+ color: Colours.COLOUR_RED,
41
+ },
42
+ ];
26
43
 
27
- const getJobStatusLabel = status => {
28
- const option = jobStatusOptions.find(item => item.name === status);
29
- return option ? option.label : jobStatusOptions[0].label;
30
- };
44
+ const getJobStatusOptions = props => props?.statusTypes?.length ? props?.statusTypes : jobStatusOptions;
31
45
 
32
- const getJobStatusProps = status => {
33
- const statusText = getJobStatusLabel(status) || jobStatusOptions[0].label;
34
- const statusColor = getJobStatusColour(statusText);
46
+ const getDefaultJobStatuses = props => getJobStatusOptions(props).filter(s => s.category === STATUS_NOT_ACTIONED);
35
47
 
36
- return { statusText, statusColor };
37
- };
48
+ const getIncompleteJobStatuses = props => getJobStatusOptions(props).filter(s => s.category === STATUS_IN_PROGRESS);
38
49
 
39
- export { jobStatusOptions, getJobStatusColour, getJobStatusProps, getJobStatusLabel };
50
+ const getJobStatus = (status, props) => {
51
+ const statusOptions = getJobStatusOptions(props);
52
+ // console.log('getJobStatus', JSON.stringify({ status, statusOptions }, null, 2));
53
+ let statusOption = null;
54
+ if (status) statusOption = statusOptions.find(s => s.text === status);
55
+ return statusOption || getDefaultJobStatuses(props)[0];
56
+ }
57
+
58
+ const getJobPriority = priority => jobPriorityOptions.find(p => p.label === priority) || jobPriorityOptions.find(p => p.default);
59
+
60
+ export {
61
+ jobStatusOptions,
62
+ jobPriorityOptions,
63
+ getJobStatusOptions,
64
+ getDefaultJobStatuses,
65
+ getIncompleteJobStatuses,
66
+ getJobStatus,
67
+ getJobPriority,
68
+ };
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable no-param-reassign */
2
2
  import _ from 'lodash';
3
3
  import { REHYDRATE } from 'redux-persist';
4
- import { JOBS_LOADED, JOB_ADDED, JOBS_ADDED } from '../actions/types';
4
+ import { JOBS_LOADED, JOB_ADDED, JOBS_ADDED, JOBS_STATUSES_LOADED, JOBS_HIDE_SEEN, JOB_FILTER_LOADED } from '../actions/types';
5
5
  import { ActionTypes } from '../core.config';
6
6
  import { values } from '../values.config';
7
7
 
@@ -9,11 +9,22 @@ const REDUCER_KEY = values.reducerKey;
9
9
 
10
10
  const INITIAL_STATE = {
11
11
  jobs: [],
12
+ jobstatuses: [],
13
+ hideSeen: false,
14
+ jobfilters: {
15
+ status: '',
16
+ statusText: '',
17
+ priority: '',
18
+ type: '',
19
+ assignee: '',
20
+ assigneeName: '',
21
+ },
12
22
  };
13
23
 
14
24
  export default (state = INITIAL_STATE, action) => {
15
25
  let updateJobs = [];
16
26
  let index = 0;
27
+ let jobstatuses = [];
17
28
 
18
29
  switch (action.type) {
19
30
  case ActionTypes.LOGOUT:
@@ -36,6 +47,19 @@ export default (state = INITIAL_STATE, action) => {
36
47
  updateJobs.push(action.payload);
37
48
  }
38
49
  return { ...state, jobs: updateJobs };
50
+ case JOBS_STATUSES_LOADED:
51
+ jobstatuses = _.orderBy(
52
+ _.unionWith(action.payload, state.jobstatuses, (v1, v2) => {
53
+ return v1 != null && v2 != null && v1.text === v2.text;
54
+ }),
55
+ 'order',
56
+ 'asc',
57
+ );
58
+ return { ...state, jobstatuses };
59
+ case JOBS_HIDE_SEEN:
60
+ return { ...state, hideSeen: action.payload };
61
+ case JOB_FILTER_LOADED:
62
+ return { ...state, jobfilters: action.payload };
39
63
  case REHYDRATE:
40
64
  if (!action.payload) return state;
41
65
  if (action.payload[REDUCER_KEY]) {
@@ -6,9 +6,10 @@ import _ from 'lodash';
6
6
  import moment from 'moment';
7
7
  import { connect } from 'react-redux';
8
8
  import { maintenanceActions } from '../apis';
9
- import { jobAdded } from '../actions';
9
+ import { jobAdded, jobStatusesUpdate, jobHideSeenUpdate } from '../actions';
10
10
  import StatusSelectorPopup from '../components/StatusSelectorPopup';
11
- import { jobStatusOptions, getJobStatusProps } from '../helper';
11
+ import PrioritySelectorPopup from '../components/PrioritySelectorPopup';
12
+ import { getJobStatus, getJobPriority } from '../helper';
12
13
  import { Services } from '../feature.config';
13
14
  import { Colours, Helper, Components, Config } from '../core.config';
14
15
  import { values } from '../values.config';
@@ -22,11 +23,13 @@ class RequestDetail extends Component {
22
23
  isDateTimePickerVisible: false,
23
24
  popUpType: '',
24
25
  status: '',
26
+ priority: '',
25
27
  expectedDate: null,
26
28
  expectedDateText: '',
27
29
  seen: false,
28
30
  showMore: true,
29
31
  showStatusPopup: false,
32
+ showPriorityPopup: false,
30
33
  loading: false,
31
34
  showFullscreenVideo: false,
32
35
  currentVideoUrl: '',
@@ -42,6 +45,8 @@ class RequestDetail extends Component {
42
45
  }
43
46
 
44
47
  componentDidMount() {
48
+ this.props.jobStatusesUpdate(this.props.job.site);
49
+ this.props.jobHideSeenUpdate(this.props.job.site);
45
50
  this.getJob();
46
51
  this.updateJobState(this.props.job);
47
52
  this.getAssignees();
@@ -51,6 +56,7 @@ class RequestDetail extends Component {
51
56
  this.setState({ loading: true }, async () => {
52
57
  try {
53
58
  const res = await maintenanceActions.getJob(this.props.job.site, this.props.job.id);
59
+ // console.log('getJob', JSON.stringify(res.data, null, 2));
54
60
  this.props.jobAdded(res.data);
55
61
  this.updateJobState(res.data);
56
62
  } catch (error) {
@@ -155,6 +161,20 @@ class RequestDetail extends Component {
155
161
  });
156
162
  };
157
163
 
164
+ updateJobPriority = () => {
165
+ this.setState({ loading: true }, async () => {
166
+ try {
167
+ const res = await maintenanceActions.editJobPriority(this.props.job.id, this.state.priority);
168
+ this.props.jobAdded(res.data.job);
169
+ this.getJob();
170
+ } catch (error) {
171
+ console.log('updateJobPriority error', error);
172
+ } finally {
173
+ this.setState({ loading: false });
174
+ }
175
+ });
176
+ };
177
+
158
178
  onPressBack = () => {
159
179
  Services.navigation.goBack();
160
180
  };
@@ -168,11 +188,27 @@ class RequestDetail extends Component {
168
188
  };
169
189
 
170
190
  onSelectStatus = status => {
191
+ if (this.state.loading) return;
171
192
  this.setState({ status, showStatusPopup: false }, () => {
172
193
  this.updateJobStatus();
173
194
  });
174
195
  };
175
196
 
197
+ onOpenPriorityPicker = () => {
198
+ this.setState({ showPriorityPopup: true });
199
+ };
200
+
201
+ onClosePriorityPopup = () => {
202
+ this.setState({ showPriorityPopup: false });
203
+ };
204
+
205
+ onSelectPriority = priority => {
206
+ if (this.state.loading) return;
207
+ this.setState({ priority, showPriorityPopup: false }, () => {
208
+ this.updateJobPriority();
209
+ });
210
+ };
211
+
176
212
  openStaffNotes = () => {
177
213
  Services.navigation.navigate(values.screenRequestNotes, { job: this.state.job, onChange: this.getJob });
178
214
  };
@@ -294,9 +330,11 @@ class RequestDetail extends Component {
294
330
 
295
331
  renderTop() {
296
332
  const { status, job } = this.state;
297
- const { statusText, statusColor } = getJobStatusProps(status);
333
+ const statusOption = getJobStatus(status, this.props);
334
+ const priority = getJobPriority(job.priority);
298
335
  const canEdit = this.hasPermission();
299
- const showSeen = !status || status === jobStatusOptions[0].name;
336
+ const isStaff = this.props.user.category === 'staff'
337
+ const showSeen = !status || status === getJobStatus(null, this.props).text;
300
338
 
301
339
  return (
302
340
  <View style={{ ...Helper.getShadowStyle() }}>
@@ -311,7 +349,7 @@ class RequestDetail extends Component {
311
349
  {job.type}
312
350
  </Text>
313
351
  </View>
314
- {showSeen && this.state.seen && (
352
+ {!this.props.hideSeen && showSeen && this.state.seen && (
315
353
  <View style={styles.jobSeenContainer}>
316
354
  <Icon name="check" type="font-awesome" iconStyle={[styles.jobSeenIcon, { color: this.props.colourBrandingMain }]} />
317
355
  <Text style={[styles.jobSeenText, { color: this.props.colourBrandingMain }]}>Seen</Text>
@@ -341,22 +379,34 @@ class RequestDetail extends Component {
341
379
  </TouchableOpacity>
342
380
  </View> */}
343
381
  </View>
344
- <View style={styles.jobStatusExpectedContainer}>
345
- <View style={styles.jobStatusOuterContainer}>
346
- <Text style={styles.jobStatusHeading}>STATUS</Text>
347
- <TouchableOpacity onPress={canEdit ? this.onOpenStatusPicker : null}>
348
- <View style={[styles.jobStatusContainer, { backgroundColor: statusColor }]}>
349
- <Text style={styles.jobStatusText}>{statusText}</Text>
382
+ <View style={styles.jobInfoContainer}>
383
+ <View style={styles.jobStatusExpectedContainer}>
384
+ <View style={styles.jobStatusOuterContainer}>
385
+ <Text style={styles.jobStatusHeading}>STATUS</Text>
386
+ <TouchableOpacity onPress={canEdit ? this.onOpenStatusPicker : null}>
387
+ <View style={[styles.jobStatusContainer, { backgroundColor: statusOption.color }]}>
388
+ <Text style={styles.jobStatusText}>{statusOption?.text}</Text>
389
+ </View>
390
+ </TouchableOpacity>
391
+ </View>
392
+ {this.hasPermission() && (
393
+ <View style={styles.jobStatusOuterContainer}>
394
+ <Text style={styles.jobStatusHeading}>STAFF NOTES</Text>
395
+ <TouchableOpacity onPress={this.openStaffNotes}>
396
+ <View style={[styles.jobStatusContainer, { backgroundColor: this.props.colourBrandingMain }]}>
397
+ <Icon name="pencil-square-o" type="font-awesome" iconStyle={styles.jobStatusIcon} />
398
+ <Text style={styles.jobStatusText}>Notes ({(job.Notes || []).length})</Text>
399
+ </View>
400
+ </TouchableOpacity>
350
401
  </View>
351
- </TouchableOpacity>
402
+ )}
352
403
  </View>
353
- {this.hasPermission() && (
354
- <View style={styles.jobStatusOuterContainer}>
355
- <Text style={styles.jobStatusHeading}>STAFF NOTES</Text>
356
- <TouchableOpacity onPress={this.openStaffNotes}>
357
- <View style={[styles.jobStatusContainer, { backgroundColor: this.props.colourBrandingMain }]}>
358
- <Icon name="pencil-square-o" type="font-awesome" iconStyle={styles.jobStatusIcon} />
359
- <Text style={styles.jobStatusText}>Notes ({(job.Notes || []).length})</Text>
404
+ {isStaff && (
405
+ <View style={styles.jobPriorityOuterContainer}>
406
+ <Text style={styles.jobStatusHeading}>PRIORITY</Text>
407
+ <TouchableOpacity onPress={canEdit ? this.onOpenPriorityPicker : null}>
408
+ <View style={[styles.jobStatusContainer, { backgroundColor: priority.color }]}>
409
+ <Text style={styles.jobStatusText}>{priority.label}</Text>
360
410
  </View>
361
411
  </TouchableOpacity>
362
412
  </View>
@@ -603,6 +653,11 @@ class RequestDetail extends Component {
603
653
  return <StatusSelectorPopup onClose={this.onCloseStatusPopup} onSelect={this.onSelectStatus} />;
604
654
  }
605
655
 
656
+ renderPriorityPopup() {
657
+ if (!this.state.showPriorityPopup) return null;
658
+ return <PrioritySelectorPopup onClose={this.onClosePriorityPopup} onSelect={this.onSelectPriority} />;
659
+ }
660
+
606
661
  render() {
607
662
  if (this.state.forbidden) {
608
663
  return <Components.Forbidden />;
@@ -621,6 +676,7 @@ class RequestDetail extends Component {
621
676
  </ScrollView>
622
677
  {this.renderMessagesReply()}
623
678
  {this.renderStatusPopup()}
679
+ {this.renderPriorityPopup()}
624
680
  {this.renderImagePopup()}
625
681
  <DateTimePicker
626
682
  isVisible={this.state.isDateTimePickerVisible}
@@ -694,15 +750,17 @@ const styles = StyleSheet.create({
694
750
  fontSize: 13,
695
751
  color: Colours.TEXT_LIGHT,
696
752
  },
697
- jobStatusExpectedContainer: {
698
- flexDirection: 'row',
699
- alignItems: 'flex-start',
700
- justifyContent: 'space-between',
753
+ jobInfoContainer: {
701
754
  borderTopWidth: 1,
702
755
  borderTopColor: Colours.LINEGREY,
703
756
  paddingVertical: 14,
704
757
  paddingHorizontal: 12,
705
758
  },
759
+ jobStatusExpectedContainer: {
760
+ flexDirection: 'row',
761
+ alignItems: 'flex-start',
762
+ justifyContent: 'space-between',
763
+ },
706
764
  jobStatusOuterContainer: {
707
765
  // marginRight: 50,
708
766
  },
@@ -734,6 +792,9 @@ const styles = StyleSheet.create({
734
792
  flex: 1,
735
793
  textAlign: 'center',
736
794
  },
795
+ jobPriorityOuterContainer: {
796
+ marginTop: 12,
797
+ },
737
798
  jobExpectedDateContainer: {
738
799
  backgroundColor: Colours.BOXGREY,
739
800
  flexDirection: 'row',
@@ -908,7 +969,9 @@ const mapStateToProps = state => {
908
969
  user: state.user,
909
970
  colourBrandingMain: Colours.getMainBrandingColourFromState(state),
910
971
  jobs: state[values.reducerKey].jobs,
972
+ statusTypes: state[values.reducerKey].jobstatuses,
973
+ hideSeen: state[values.reducerKey].hideSeen,
911
974
  };
912
975
  };
913
976
 
914
- export default connect(mapStateToProps, { jobAdded })(RequestDetail);
977
+ export default connect(mapStateToProps, { jobAdded, jobStatusesUpdate, jobHideSeenUpdate })(RequestDetail);