@plusscommunities/pluss-maintenance-app-forms 6.0.10 → 6.0.11-auth.0

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 (106) 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/index.js +1 -1
  4. package/dist/module/actions/index.js.map +1 -1
  5. package/dist/module/actions/types.js +4 -1
  6. package/dist/module/actions/types.js.map +1 -1
  7. package/dist/module/apis/index.js +4 -1
  8. package/dist/module/apis/index.js.map +1 -1
  9. package/dist/module/apis/maintenanceActions.js +61 -38
  10. package/dist/module/apis/maintenanceActions.js.map +1 -1
  11. package/dist/module/apis/userActions.js +23 -0
  12. package/dist/module/apis/userActions.js.map +1 -0
  13. package/dist/module/components/FilterPopupMenu.js +82 -58
  14. package/dist/module/components/FilterPopupMenu.js.map +1 -1
  15. package/dist/module/components/MaintenanceList.js +84 -92
  16. package/dist/module/components/MaintenanceList.js.map +1 -1
  17. package/dist/module/components/MaintenanceListItem.js +94 -80
  18. package/dist/module/components/MaintenanceListItem.js.map +1 -1
  19. package/dist/module/components/MaintenanceWidgetItem.js +39 -38
  20. package/dist/module/components/MaintenanceWidgetItem.js.map +1 -1
  21. package/dist/module/components/PrioritySelectorPopup.js +83 -0
  22. package/dist/module/components/PrioritySelectorPopup.js.map +1 -0
  23. package/dist/module/components/StatusSelectorPopup.js +23 -27
  24. package/dist/module/components/StatusSelectorPopup.js.map +1 -1
  25. package/dist/module/components/WidgetLarge.js +2 -2
  26. package/dist/module/components/WidgetLarge.js.map +1 -1
  27. package/dist/module/components/WidgetSmall.js +25 -20
  28. package/dist/module/components/WidgetSmall.js.map +1 -1
  29. package/dist/module/core.config.js +2 -3
  30. package/dist/module/core.config.js.map +1 -1
  31. package/dist/module/feature.config.js +17 -17
  32. package/dist/module/feature.config.js.map +1 -1
  33. package/dist/module/helper.js +41 -26
  34. package/dist/module/helper.js.map +1 -1
  35. package/dist/module/index.js +12 -10
  36. package/dist/module/index.js.map +1 -1
  37. package/dist/module/reducers/JobsReducer.js +36 -6
  38. package/dist/module/reducers/JobsReducer.js.map +1 -1
  39. package/dist/module/screens/JobTypePicker.js +18 -17
  40. package/dist/module/screens/JobTypePicker.js.map +1 -1
  41. package/dist/module/screens/MaintenancePage.js +10 -10
  42. package/dist/module/screens/MaintenancePage.js.map +1 -1
  43. package/dist/module/screens/MaintenanceUserPicker.js +219 -0
  44. package/dist/module/screens/MaintenanceUserPicker.js.map +1 -0
  45. package/dist/module/screens/RequestDetail.js +410 -142
  46. package/dist/module/screens/RequestDetail.js.map +1 -1
  47. package/dist/module/screens/RequestNotes.js +462 -52
  48. package/dist/module/screens/RequestNotes.js.map +1 -1
  49. package/dist/module/screens/ServiceRequest.js +519 -181
  50. package/dist/module/screens/ServiceRequest.js.map +1 -1
  51. package/dist/module/values.config.a.js +30 -23
  52. package/dist/module/values.config.a.js.map +1 -1
  53. package/dist/module/values.config.default.js +35 -28
  54. package/dist/module/values.config.default.js.map +1 -1
  55. package/dist/module/values.config.enquiry.js +43 -0
  56. package/dist/module/values.config.enquiry.js.map +1 -0
  57. package/dist/module/values.config.feedback.js +43 -0
  58. package/dist/module/values.config.feedback.js.map +1 -0
  59. package/dist/module/values.config.food.js +43 -0
  60. package/dist/module/values.config.food.js.map +1 -0
  61. package/dist/module/values.config.forms.js +35 -28
  62. package/dist/module/values.config.forms.js.map +1 -1
  63. package/dist/module/values.config.js +35 -28
  64. package/dist/module/values.config.js.map +1 -1
  65. package/package.json +55 -51
  66. package/src/actions/JobActions.js +75 -16
  67. package/src/actions/index.js +1 -1
  68. package/src/actions/types.js +4 -1
  69. package/src/apis/index.js +6 -1
  70. package/src/apis/maintenanceActions.js +189 -160
  71. package/src/apis/userActions.js +21 -0
  72. package/src/components/FilterPopupMenu.js +316 -230
  73. package/src/components/MaintenanceList.js +391 -326
  74. package/src/components/MaintenanceListItem.js +348 -274
  75. package/src/components/MaintenanceWidgetItem.js +146 -120
  76. package/src/components/PrioritySelectorPopup.js +93 -0
  77. package/src/components/StatusSelectorPopup.js +82 -76
  78. package/src/components/WidgetLarge.js +5 -5
  79. package/src/components/WidgetSmall.js +154 -131
  80. package/src/core.config.js +25 -3
  81. package/src/feature.config.js +62 -62
  82. package/src/helper.js +67 -30
  83. package/src/index.js +22 -20
  84. package/src/reducers/JobsReducer.js +85 -41
  85. package/src/screens/JobTypePicker.js +116 -92
  86. package/src/screens/MaintenancePage.js +89 -80
  87. package/src/screens/MaintenanceUserPicker.js +233 -0
  88. package/src/screens/RequestDetail.js +1354 -892
  89. package/src/screens/RequestNotes.js +946 -408
  90. package/src/screens/ServiceRequest.js +1808 -1222
  91. package/src/values.config.a.js +33 -26
  92. package/src/values.config.default.js +39 -32
  93. package/src/values.config.enquiry.js +43 -0
  94. package/src/values.config.feedback.js +43 -0
  95. package/src/values.config.food.js +43 -0
  96. package/src/values.config.forms.js +39 -32
  97. package/src/values.config.js +39 -32
  98. package/dist/module/values.config.b.js +0 -30
  99. package/dist/module/values.config.b.js.map +0 -1
  100. package/dist/module/values.config.c.js +0 -30
  101. package/dist/module/values.config.c.js.map +0 -1
  102. package/dist/module/values.config.d.js +0 -30
  103. package/dist/module/values.config.d.js.map +0 -1
  104. package/src/values.config.b.js +0 -30
  105. package/src/values.config.c.js +0 -30
  106. package/src/values.config.d.js +0 -30
@@ -1,31 +1,128 @@
1
1
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
2
2
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
3
3
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
4
- import React, { Component } from 'react';
5
- import { Dimensions, Platform, KeyboardAvoidingView, ScrollView, Text, TouchableOpacity, View, Switch, FlatList, ImageBackground, Keyboard } from 'react-native';
6
- import DateTimePicker from 'react-native-modal-datetime-picker';
7
- import { Icon } from 'react-native-elements';
8
- import _ from 'lodash';
9
- import moment from 'moment';
10
- import { connect } from 'react-redux';
11
- import { jobAdded } from '../actions';
12
- import { maintenanceActions } from '../apis';
13
- import { Services } from '../feature.config';
14
- import { Components, Colours, Helper, Config } from '../core.config';
15
- import { values } from '../values.config';
16
- const PHOTO_SIZE = (Dimensions.get('window').width - 64) / 3;
4
+ import React, { Component } from "react";
5
+ import { Text } from "@plusscommunities/pluss-core-app/components";
6
+ import { Dimensions, Platform, KeyboardAvoidingView, ScrollView, TouchableOpacity, View, Switch, FlatList, ImageBackground, Keyboard, Alert } from "react-native";
7
+ import DateTimePicker from "react-native-modal-datetime-picker";
8
+ import { Icon } from "@rneui/themed";
9
+ import _ from "lodash";
10
+ import moment from "moment";
11
+ import { connect } from "react-redux";
12
+ import { jobAdded } from "../actions";
13
+ import { maintenanceActions, userActions } from "../apis";
14
+ import { Services } from "../feature.config";
15
+ import { Components, Colours, Helper, Config } from "../core.config";
16
+ import { values } from "../values.config";
17
+ const PHOTO_SIZE = (Dimensions.get("window").width - 64) / 3;
17
18
  class MaintenanceRequest extends Component {
18
19
  constructor(props) {
19
20
  super(props);
21
+ _defineProperty(this, "checkUserPermissions", async () => {
22
+ var _this$props$permissio;
23
+ // PC-1255: Check if user has userManagement permission
24
+ const hasUserManagement = ((_this$props$permissio = this.props.permissions) === null || _this$props$permissio === void 0 ? void 0 : _this$props$permissio.includes("userManagement")) || false;
25
+ if (hasUserManagement) {
26
+ this.setState({
27
+ canCreateOnBehalf: true
28
+ });
29
+ // Load site users for picker
30
+ await this.loadSiteUsers();
31
+ } else {
32
+ // Default to logged-in user for non-staff or staff without permission
33
+ this.setDefaultUser();
34
+ }
35
+ });
36
+ _defineProperty(this, "loadSiteUsers", async () => {
37
+ try {
38
+ const response = await userActions.getSiteUsers(this.props.site);
39
+ let items = response.data.Items || [];
40
+ if (this.props.optionOnlyForResidents) {
41
+ items = _.filter(items, u => u.category === "resident");
42
+ }
43
+ const users = _.sortBy(response.data.Items || [], u => (u.displayName || "").toLowerCase());
44
+ this.setState({
45
+ users
46
+ });
47
+ } catch (error) {
48
+ console.log("Error loading site users:", error);
49
+ // Fall back to default user if loading fails
50
+ this.setDefaultUser();
51
+ }
52
+ });
53
+ _defineProperty(this, "setDefaultUser", () => {
54
+ if (this.props.userType !== "KIOSK") {
55
+ const defaultUser = {
56
+ userId: this.props.uid,
57
+ displayName: this.props.displayName,
58
+ profilePic: this.props.profilePic
59
+ };
60
+ this.setState({
61
+ selectedUser: defaultUser,
62
+ userName: this.props.displayName,
63
+ roomNumber: this.props.unit,
64
+ phone: !_.isEmpty(this.props.phoneNumber) ? this.props.phoneNumber : ""
65
+ });
66
+ }
67
+ });
20
68
  _defineProperty(this, "onChangeName", userName => {
21
69
  const update = {
22
70
  userName
23
71
  };
24
- if (!this.state.customFields || !_.some(this.state.customFields, 'isTitle')) {
72
+ if (!this.state.customFields || !_.some(this.state.customFields, "isTitle")) {
25
73
  update.title = userName;
26
74
  }
27
75
  this.setState(update);
28
76
  });
77
+ // PC-1255: Handle user picker navigation
78
+ _defineProperty(this, "onPressUser", () => {
79
+ const {
80
+ users,
81
+ selectedUser
82
+ } = this.state;
83
+ if (!users || users.length === 0) return;
84
+ Services.navigation.navigate(values.screenUserPicker, {
85
+ currentUser: selectedUser,
86
+ users,
87
+ onSelectUser: this.onSelectUser.bind(this)
88
+ });
89
+ });
90
+ // PC-1255: Handle user selection and auto-populate contact details
91
+ _defineProperty(this, "onSelectUser", async user => {
92
+ const update = {
93
+ selectedUser: user,
94
+ userName: user.displayName
95
+ };
96
+
97
+ // PC-1255: Try to fetch full user details for auto-population
98
+ try {
99
+ // getSiteUsers returns 'Id', but fetchUser expects 'userId'
100
+ const userId = user.userId || user.Id;
101
+ const response = await userActions.fetchUser(this.props.site, userId);
102
+ if (response.data && response.data.user) {
103
+ const userDetails = response.data.user;
104
+ if (userDetails.phoneNumber) {
105
+ update.phone = userDetails.phoneNumber;
106
+ }
107
+ if (userDetails.unit) {
108
+ update.roomNumber = userDetails.unit;
109
+ }
110
+ if (!this.state.customFields || !_.some(this.state.customFields, "isTitle")) {
111
+ update.title = userDetails.displayName || null;
112
+ }
113
+ }
114
+ } catch (error) {
115
+ // Permission denied (403) or other error - continue without auto-population
116
+ // User can still manually enter contact details
117
+ console.log("Could not fetch user details for auto-population:", error);
118
+ } finally {
119
+ // In any case, we still need a title. Inform the user to set one form field as a title.
120
+ if (!this.state.title && !update.title) {
121
+ update.title = "[Missing title - Set one of the form field as title in the community manager]";
122
+ }
123
+ }
124
+ this.setState(update);
125
+ });
29
126
  _defineProperty(this, "onChangeAnswer", (fieldId, answer) => {
30
127
  const update = {
31
128
  customFields: _.cloneDeep(this.state.customFields)
@@ -50,7 +147,7 @@ class MaintenanceRequest extends Component {
50
147
  };
51
148
  const field = update.customFields[fieldId];
52
149
  field.answer = _.xor(field.answer || [], [answer]);
53
- if (field.isTitle) update.title = field.answer.join(', ');
150
+ if (field.isTitle) update.title = field.answer.join(", ");
54
151
  this.setState(update);
55
152
  });
56
153
  _defineProperty(this, "onOpenDatePicker", (field, fieldId) => {
@@ -83,30 +180,30 @@ class MaintenanceRequest extends Component {
83
180
  };
84
181
  const field = update.customFields[dateFieldId];
85
182
  const dateObj = moment(date);
86
- if (popUpType === 'date') {
87
- field.answer = dateObj.format('YYYY-MM-DD');
88
- if (field.isTitle) update.title = dateObj.format('DD MMM YYYY');
183
+ if (popUpType === "date") {
184
+ field.answer = dateObj.format("YYYY-MM-DD");
185
+ if (field.isTitle) update.title = dateObj.format("DD MMM YYYY");
89
186
  } else {
90
- field.answer = dateObj.format('HH:mm');
91
- if (field.isTitle) update.title = dateObj.format('h:mm a');
187
+ field.answer = dateObj.format("HH:mm");
188
+ if (field.isTitle) update.title = dateObj.format("h:mm a");
92
189
  }
93
190
  this.setState(update);
94
191
  });
95
- _defineProperty(this, "onUploadStarted", (uploadUri, imageUri) => {
192
+ _defineProperty(this, "onUploadStartedImage", (uploadUri, imageUri) => {
96
193
  const {
97
194
  imageFieldId
98
195
  } = this.state;
99
196
  const imagesUpdate = this.getImages(imageFieldId);
100
197
  imagesUpdate.splice(imagesUpdate.length - 1, 0, {
101
198
  uploading: true,
102
- uploadProgress: '0%',
199
+ uploadProgress: "0%",
103
200
  uploadUri,
104
201
  imageUri,
105
202
  allowRetry: true
106
203
  });
107
204
  this.setImages(imagesUpdate, imageFieldId);
108
205
  });
109
- _defineProperty(this, "onUploadProgress", progress => {
206
+ _defineProperty(this, "onUploadProgressImage", progress => {
110
207
  const {
111
208
  imageFieldId
112
209
  } = this.state;
@@ -120,14 +217,14 @@ class MaintenanceRequest extends Component {
120
217
  });
121
218
  this.setImages(imagesUpdate, imageFieldId);
122
219
  });
123
- _defineProperty(this, "onUploadSuccess", async (uri, uploadUri) => {
220
+ _defineProperty(this, "onUploadSuccessImage", async (uri, uploadUri) => {
124
221
  const {
125
222
  imageFieldId
126
223
  } = this.state;
127
224
  const imagesUpdate = this.getImages(imageFieldId);
128
225
  imagesUpdate.map(img => {
129
226
  if (img.uploadUri === uploadUri && img.uploading) {
130
- img.url = uri.replace('/general/', '/general1400/');
227
+ img.url = uri.replace("/general/", "/general1400/");
131
228
  img.thumbNailExists = false;
132
229
  img.thumbNailUrl = Helper.getThumb300(img.url);
133
230
  img.allowRetry = true;
@@ -135,7 +232,7 @@ class MaintenanceRequest extends Component {
135
232
  });
136
233
  this.setImages(imagesUpdate, imageFieldId, () => this.waitForThumbnails());
137
234
  });
138
- _defineProperty(this, "onUploadFailed", uploadUri => {
235
+ _defineProperty(this, "onUploadFailedImage", uploadUri => {
139
236
  const {
140
237
  imageFieldId
141
238
  } = this.state;
@@ -143,13 +240,13 @@ class MaintenanceRequest extends Component {
143
240
  imagesUpdate.map(img => {
144
241
  if (img.uploadUri === uploadUri) {
145
242
  img.uploading = true; // Requried for retry
146
- img.uploadProgress = '';
243
+ img.uploadProgress = "";
147
244
  img.allowRetry = true;
148
245
  }
149
246
  });
150
247
  this.setImages(imagesUpdate, imageFieldId);
151
248
  });
152
- _defineProperty(this, "onLibrarySelected", uri => {
249
+ _defineProperty(this, "onLibrarySelectedImage", uri => {
153
250
  const {
154
251
  imageFieldId
155
252
  } = this.state;
@@ -163,22 +260,72 @@ class MaintenanceRequest extends Component {
163
260
  });
164
261
  this.setImages(imagesUpdate, imageFieldId);
165
262
  });
263
+ _defineProperty(this, "onUploadStartedDocument", (uploadUri, documentUri, documentName, documentExt, documentFieldId) => {
264
+ const documentsUpdate = this.getDocuments(documentFieldId);
265
+ documentsUpdate.splice(documentsUpdate.length - 1, 0, {
266
+ uploading: true,
267
+ uploadProgress: "0%",
268
+ uploadUri,
269
+ documentUri,
270
+ documentName,
271
+ documentExt,
272
+ allowRetry: true
273
+ });
274
+ this.setDocuments(documentsUpdate, documentFieldId);
275
+ });
276
+ _defineProperty(this, "onUploadProgressDocument", (progress, documentFieldId) => {
277
+ const documentsUpdate = this.getDocuments(documentFieldId);
278
+ documentsUpdate.map(doc => {
279
+ if (doc.uploadUri === progress.uri) {
280
+ doc.uploadProgress = progress.percentage;
281
+ doc.uploading = true;
282
+ doc.allowRetry = true;
283
+ }
284
+ });
285
+ this.setDocuments(documentsUpdate, documentFieldId);
286
+ });
287
+ _defineProperty(this, "onUploadSuccessDocument", async (uri, uploadUri, documentFieldId) => {
288
+ const documentsUpdate = this.getDocuments(documentFieldId);
289
+ documentsUpdate.map(doc => {
290
+ if (doc.uploadUri === uploadUri && doc.uploading) {
291
+ doc.uploading = false;
292
+ doc.uploadProgress = "100%";
293
+ doc.url = uri;
294
+ doc.allowRetry = true;
295
+ }
296
+ });
297
+ this.setDocuments(documentsUpdate, documentFieldId);
298
+ });
299
+ _defineProperty(this, "onUploadFailedDocument", (uploadUri, documentFieldId) => {
300
+ const documentsUpdate = this.getDocuments(documentFieldId);
301
+ documentsUpdate.map(doc => {
302
+ if (doc.uploadUri === uploadUri) {
303
+ doc.uploading = true; // Requried for retry
304
+ doc.uploadProgress = "";
305
+ doc.allowRetry = true;
306
+ }
307
+ });
308
+ this.setDocuments(documentsUpdate, documentFieldId);
309
+ });
166
310
  _defineProperty(this, "isFieldValid", (field, fieldId) => {
167
311
  const {
168
312
  mandatory,
169
313
  type,
170
314
  answer
171
315
  } = field;
172
- if (['staticTitle', 'staticText'].includes(type)) return true;
173
- const imagesList = type === 'image' ? this.getImageUrls(fieldId) : [];
316
+ if (["staticTitle", "staticText"].includes(type)) return true;
174
317
  const checkMandatory = () => {
175
318
  if (!mandatory) return true;
176
319
  switch (type) {
177
- case 'yn':
320
+ case "yn":
178
321
  return _.isBoolean(answer);
179
- case 'image':
322
+ case "image":
323
+ const imagesList = this.getImageUrls(fieldId);
180
324
  return imagesList.length > 0;
181
- case 'checkbox':
325
+ case "document":
326
+ const documentsList = this.getDocumentAnswers(fieldId);
327
+ return documentsList.length > 0;
328
+ case "checkbox":
182
329
  return _.isArray(answer) && answer.length > 0;
183
330
  default:
184
331
  return !_.isNil(answer) && !_.isEmpty(answer);
@@ -187,12 +334,12 @@ class MaintenanceRequest extends Component {
187
334
  const checkFormat = () => {
188
335
  if (_.isNil(answer) || _.isEmpty(answer)) return true;
189
336
  switch (type) {
190
- case 'email':
337
+ case "email":
191
338
  return Helper.isEmail(answer);
192
- case 'date':
193
- return moment(answer, 'YYYY-MM-DD', true).isValid();
194
- case 'time':
195
- return moment(answer, 'HH:mm', true).isValid();
339
+ case "date":
340
+ return moment(answer, "YYYY-MM-DD", true).isValid();
341
+ case "time":
342
+ return moment(answer, "HH:mm", true).isValid();
196
343
  default:
197
344
  return true;
198
345
  }
@@ -228,7 +375,8 @@ class MaintenanceRequest extends Component {
228
375
  // Fix custom images field answers
229
376
  const customFields = _.cloneDeep(this.state.customFields);
230
377
  const updatedCustomFields = customFields.map((field, fieldId) => {
231
- if (field.type === 'image') field.answer = this.getImageUrls(fieldId);
378
+ if (field.type === "image") field.answer = this.getImageUrls(fieldId);
379
+ if (field.type === "document") field.answer = this.getDocumentAnswers(fieldId);
232
380
  return field;
233
381
  });
234
382
  maintenanceActions.sendMaintenanceRequest(this.props.uid, this.state.userName, this.state.phone, this.state.roomNumber, this.state.title, description, null, this.state.type, images, Helper.getSite(this.props.site), this.state.isHome, this.state.times, updatedCustomFields).then(res => {
@@ -246,7 +394,7 @@ class MaintenanceRequest extends Component {
246
394
  });
247
395
  }
248
396
  }).catch(err => {
249
- console.log('maintenance submission fail.');
397
+ console.log("maintenance submission fail.");
250
398
  console.log(err);
251
399
  this.setState({
252
400
  submitting: false
@@ -258,7 +406,7 @@ class MaintenanceRequest extends Component {
258
406
  const job = await maintenanceActions.getJob(Helper.getSite(this.props.site), id);
259
407
  this.props.jobAdded(job.data);
260
408
  } catch (error) {
261
- console.log('refreshRequest error', error);
409
+ console.log("refreshRequest error", error);
262
410
  }
263
411
  });
264
412
  _defineProperty(this, "validateCustomFields", () => {
@@ -343,8 +491,41 @@ class MaintenanceRequest extends Component {
343
491
  imagesUpdate.splice(index, 1);
344
492
  this.setImages(imagesUpdate, fieldId);
345
493
  });
494
+ _defineProperty(this, "getDocuments", fieldId => {
495
+ const {
496
+ customFieldDocuments
497
+ } = this.state;
498
+ const documentsList = _.cloneDeep(customFieldDocuments[fieldId]) || [];
499
+ return documentsList;
500
+ });
501
+ _defineProperty(this, "setDocuments", (documentsList, fieldId) => {
502
+ let update = {};
503
+ const customFieldDocuments = _.cloneDeep(this.state.customFieldDocuments);
504
+ customFieldDocuments[fieldId] = documentsList;
505
+ update = {
506
+ customFieldDocuments
507
+ };
508
+ this.setState(update);
509
+ });
510
+ _defineProperty(this, "getDocumentAnswers", fieldId => {
511
+ const documentsList = this.getDocuments(fieldId);
512
+ return _.filter(documentsList, doc => {
513
+ return !doc.uploading && doc.url;
514
+ }).map(doc => {
515
+ return {
516
+ name: doc.documentName,
517
+ ext: doc.documentExt,
518
+ url: doc.url
519
+ };
520
+ });
521
+ });
522
+ _defineProperty(this, "removeDocument", (index, fieldId) => {
523
+ const documentsUpdate = this.getDocuments(fieldId);
524
+ documentsUpdate.splice(index, 1);
525
+ this.setDocuments(documentsUpdate, fieldId);
526
+ });
346
527
  _defineProperty(this, "toggleFullscreenVideo", url => {
347
- if (typeof url !== 'string') url = '';
528
+ if (typeof url !== "string") url = "";
348
529
  this.setState({
349
530
  showFullscreenVideo: url.length > 0,
350
531
  currentVideoUrl: url
@@ -357,44 +538,43 @@ class MaintenanceRequest extends Component {
357
538
  error: null,
358
539
  showError: false,
359
540
  loadingTypes: values.forceCustomFields,
360
- userName: '',
361
- roomNumber: '',
362
- phone: '',
363
- title: '',
364
- description: '',
365
- times: '',
366
- type: 'General',
541
+ userName: "",
542
+ roomNumber: "",
543
+ phone: "",
544
+ title: "",
545
+ description: "",
546
+ times: "",
547
+ type: "General",
367
548
  uploadingImage: false,
368
549
  images: [{
369
550
  add: true
370
551
  }],
371
552
  showFullscreenVideo: false,
372
- currentVideoUrl: '',
553
+ currentVideoUrl: "",
373
554
  isHome: false,
374
555
  types: [],
375
556
  confirmationToShow: false,
376
557
  customFields: [],
377
558
  customFieldImages: {},
559
+ customFieldDocuments: {},
378
560
  isDateTimePickerVisible: false,
379
- popUpType: 'date',
561
+ popUpType: "date",
380
562
  dateFieldId: null,
381
- imageFieldId: null
563
+ imageFieldId: null,
564
+ // PC-1255: On-behalf request fields
565
+ canCreateOnBehalf: false,
566
+ selectedUser: null,
567
+ users: []
382
568
  };
383
569
  this.checkThumb = null;
384
570
  this.keyboardTypes = {
385
- phone: 'phone-pad',
386
- email: 'email-address',
387
- text: 'default'
571
+ phone: "phone-pad",
572
+ email: "email-address",
573
+ text: "default"
388
574
  };
389
575
  }
390
576
  componentDidMount() {
391
- if (this.props.userType !== 'KIOSK') {
392
- this.setState({
393
- userName: this.props.displayName,
394
- roomNumber: this.props.unit,
395
- phone: !_.isEmpty(this.props.phoneNumber) ? this.props.phoneNumber : ''
396
- });
397
- }
577
+ this.checkUserPermissions();
398
578
  this.getJobTypes();
399
579
  }
400
580
  componentWillUnmount() {
@@ -420,9 +600,9 @@ class MaintenanceRequest extends Component {
420
600
  onConfirmationReset() {
421
601
  this.setState({
422
602
  confirmationToShow: false,
423
- title: '',
424
- description: '',
425
- times: '',
603
+ title: "",
604
+ description: "",
605
+ times: "",
426
606
  isHome: false,
427
607
  uploadingImage: false,
428
608
  images: [{
@@ -433,8 +613,9 @@ class MaintenanceRequest extends Component {
433
613
  fail: false,
434
614
  customFields: [],
435
615
  customFieldImages: {},
616
+ customFieldDocuments: {},
436
617
  isDateTimePickerVisible: false,
437
- popUpType: 'date',
618
+ popUpType: "date",
438
619
  dateFieldId: null,
439
620
  imageFieldId: null
440
621
  }, () => this.pickType(this.state.type));
@@ -443,9 +624,9 @@ class MaintenanceRequest extends Component {
443
624
  maintenanceActions.getJobTypes(Helper.getSite(this.props.site)).then(res => {
444
625
  this.setState({
445
626
  types: res.data
627
+ }, () => {
628
+ this.getDefaultJob();
446
629
  });
447
- console.log(res.data);
448
- this.getDefaultJob();
449
630
  }).catch(() => {});
450
631
  }
451
632
  pickType(type) {
@@ -454,7 +635,6 @@ class MaintenanceRequest extends Component {
454
635
  } = this.state;
455
636
  const selected = types.find(t => t.typeName === type) || {};
456
637
  if (values.forceCustomFields && !selected.hasCustomFields) {
457
- console.log(selected);
458
638
  this.setState({
459
639
  type,
460
640
  customFields: [],
@@ -467,7 +647,7 @@ class MaintenanceRequest extends Component {
467
647
  customFields: selected.hasCustomFields && selected.customFields.length > 0 ? _.cloneDeep(selected.customFields) : [],
468
648
  loadingTypes: false
469
649
  };
470
- if (!_.isEmpty(update.customFields) && !_.some(update.customFields, 'isTitle')) {
650
+ if (!_.isEmpty(update.customFields) && !_.some(update.customFields, "isTitle")) {
471
651
  update.title = this.state.userName;
472
652
  }
473
653
  this.setState(update);
@@ -490,14 +670,15 @@ class MaintenanceRequest extends Component {
490
670
  title,
491
671
  roomNumber,
492
672
  isHome,
493
- times
673
+ customFieldImages
494
674
  } = this.state;
495
675
  const hasCustomFields = customFields && customFields.length > 0;
676
+ function showFormErrorAlert() {}
496
677
  if (submitting || !this.props.connected) {
497
678
  if (!this.props.connected) {
498
679
  this.setState({
499
680
  error: {
500
- message: 'No internet connection detected'
681
+ message: "No internet connection detected"
501
682
  }
502
683
  });
503
684
  }
@@ -508,11 +689,22 @@ class MaintenanceRequest extends Component {
508
689
  error: null,
509
690
  showError: false
510
691
  });
692
+
693
+ // PC-1255: Validate user selection for on-behalf requests
694
+ if (this.state.canCreateOnBehalf && !this.state.selectedUser) {
695
+ console.log("submitRequest - no user selected for on-behalf request");
696
+ Alert.alert("Missing Information", "Please select a user to submit the form on behalf of");
697
+ this.setState({
698
+ showError: true
699
+ });
700
+ return;
701
+ }
511
702
  if (title.length === 0 || !roomNumber || roomNumber.length === 0) {
512
- console.log('submitRequest - error', {
703
+ console.log("submitRequest - error", {
513
704
  title,
514
705
  roomNumber
515
706
  });
707
+ Alert.alert("Missing Information", "Please fill out your address details");
516
708
  this.setState({
517
709
  showError: true
518
710
  });
@@ -520,7 +712,8 @@ class MaintenanceRequest extends Component {
520
712
  }
521
713
  if (hasCustomFields) {
522
714
  if (!this.validateCustomFields()) {
523
- console.log('submitRequest - custom fields error');
715
+ console.log("submitRequest - custom fields error");
716
+ Alert.alert("Invalid Information", "Please review the form for errors and try submitting again.");
524
717
  this.setState({
525
718
  showError: true
526
719
  });
@@ -528,10 +721,11 @@ class MaintenanceRequest extends Component {
528
721
  }
529
722
  } else {
530
723
  if (isHome && times.length < 2) {
531
- console.log('submitRequest - error', {
724
+ console.log("submitRequest - error", {
532
725
  isHome,
533
726
  times
534
727
  });
728
+ Alert.alert("Invalid Information", "Please review the form for errors and try submitting again.");
535
729
  this.setState({
536
730
  showError: true
537
731
  });
@@ -540,20 +734,20 @@ class MaintenanceRequest extends Component {
540
734
  }
541
735
  this.submit();
542
736
  }
543
- renderUploadMenu() {
737
+ renderImageUploader() {
544
738
  return /*#__PURE__*/React.createElement(Components.ImageUploader, {
545
739
  ref: ref => this.imageUploader = ref,
546
- onUploadStarted: this.onUploadStarted,
547
- onUploadSuccess: this.onUploadSuccess,
548
- onUploadFailed: this.onUploadFailed,
549
- onUploadProgress: this.onUploadProgress,
550
- onLibrarySelected: this.onLibrarySelected,
740
+ onUploadStarted: this.onUploadStartedImage,
741
+ onUploadSuccess: this.onUploadSuccessImage,
742
+ onUploadFailed: this.onUploadFailedImage,
743
+ onUploadProgress: this.onUploadProgressImage,
744
+ onLibrarySelected: this.onLibrarySelectedImage,
551
745
  size: {
552
746
  width: 1400
553
747
  },
554
748
  quality: 0.8,
555
- fileName: 'serviceImage',
556
- popupTitle: 'Upload Image',
749
+ fileName: "serviceImage",
750
+ popupTitle: "Upload Image",
557
751
  userId: this.props.uid,
558
752
  allowsEditing: false,
559
753
  multiple: true,
@@ -612,12 +806,40 @@ class MaintenanceRequest extends Component {
612
806
  style: styles.removeImage
613
807
  }))));
614
808
  }
809
+ renderDocument(item, index, fieldId) {
810
+ const {
811
+ colourBrandingMain
812
+ } = this.props;
813
+ return /*#__PURE__*/React.createElement(View, {
814
+ key: index,
815
+ style: styles.documentContainer
816
+ }, /*#__PURE__*/React.createElement(View, {
817
+ style: {
818
+ ...styles.documentTypeContainer,
819
+ backgroundColor: colourBrandingMain
820
+ }
821
+ }, /*#__PURE__*/React.createElement(Text, {
822
+ style: styles.documentTypeText
823
+ }, item.documentExt)), /*#__PURE__*/React.createElement(Text, {
824
+ style: styles.documentText
825
+ }, `${item.documentName}${item.uploading ? ` - ${item.uploadProgress}` : ""}`), !item.uploading && /*#__PURE__*/React.createElement(TouchableOpacity, {
826
+ style: styles.removeDocumentButton,
827
+ onPress: () => this.removeDocument(index, fieldId)
828
+ }, /*#__PURE__*/React.createElement(Icon, {
829
+ name: "remove",
830
+ type: "font-awesome",
831
+ iconStyle: {
832
+ ...styles.removeDocumentIcon,
833
+ color: colourBrandingMain
834
+ }
835
+ })));
836
+ }
615
837
  renderSuccess() {
616
838
  return /*#__PURE__*/React.createElement(View, {
617
839
  style: {
618
840
  padding: 16,
619
841
  flex: 1,
620
- backgroundColor: '#fff'
842
+ backgroundColor: "#fff"
621
843
  }
622
844
  }, /*#__PURE__*/React.createElement(Text, {
623
845
  style: styles.requestSuccess
@@ -626,8 +848,6 @@ class MaintenanceRequest extends Component {
626
848
  renderImageList(fieldId = null) {
627
849
  const imagesList = this.getImages(fieldId);
628
850
  return /*#__PURE__*/React.createElement(View, {
629
- style: styles.imageSection
630
- }, /*#__PURE__*/React.createElement(View, {
631
851
  style: [styles.imageListContainer, imagesList.length < 2 && styles.imageListContainerEmpty]
632
852
  }, /*#__PURE__*/React.createElement(FlatList, {
633
853
  keyboardShouldPersistTaps: "always",
@@ -639,20 +859,37 @@ class MaintenanceRequest extends Component {
639
859
  }) => this.renderImage(item, index, fieldId),
640
860
  keyExtractor: (item, index) => index,
641
861
  numColumns: 3
642
- })));
862
+ }));
863
+ }
864
+ renderDocumentList(fieldId) {
865
+ const documentsList = this.getDocuments(fieldId);
866
+ return /*#__PURE__*/React.createElement(View, {
867
+ style: styles.documentListContainer
868
+ }, documentsList.length > 0 ? documentsList.map((document, index) => this.renderDocument(document, index, fieldId)) : null, /*#__PURE__*/React.createElement(Components.DocumentUploader, {
869
+ buttonTitle: "Add Files",
870
+ allowedTypes: ["application/pdf"],
871
+ onUploadStarted: (uploadUri, uri, name, ext) => this.onUploadStartedDocument(uploadUri, uri, name, ext, fieldId),
872
+ onUploadProgress: progress => this.onUploadProgressDocument(progress, fieldId),
873
+ onUploadSuccess: (uri, uploadUri) => this.onUploadSuccessDocument(uri, uploadUri, fieldId),
874
+ onUploadFailed: uploadUri => this.onUploadFailedDocument(uploadUri, fieldId),
875
+ fileName: "serviceDocument",
876
+ userId: this.props.uid,
877
+ disabled: false,
878
+ multiple: true
879
+ }));
643
880
  }
644
881
  renderDateField(field, fieldId, sectionStyle) {
645
882
  let displayText, placeHolder, icon, errorText;
646
- if (field.type === 'date') {
647
- displayText = field.answer ? moment(field.answer, 'YYYY-MM-DD').format('DD MMM YYYY') : '';
648
- placeHolder = 'dd mmm yyyy';
649
- icon = 'calendar';
650
- errorText = 'Not a valid date';
883
+ if (field.type === "date") {
884
+ displayText = field.answer ? moment(field.answer, "YYYY-MM-DD").format("DD MMM YYYY") : "";
885
+ placeHolder = "dd mmm yyyy";
886
+ icon = "calendar";
887
+ errorText = "Not a valid date";
651
888
  } else {
652
- displayText = field.answer ? moment(field.answer, 'HH:mm').format('h:mm a') : '';
653
- placeHolder = '--:-- --';
654
- icon = 'clock-o';
655
- errorText = 'Not a valid time';
889
+ displayText = field.answer ? moment(field.answer, "HH:mm").format("h:mm a") : "";
890
+ placeHolder = "--:-- --";
891
+ icon = "clock-o";
892
+ errorText = "Not a valid time";
656
893
  }
657
894
  return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
658
895
  key: fieldId,
@@ -690,7 +927,7 @@ class MaintenanceRequest extends Component {
690
927
  marginBottom: 24
691
928
  };
692
929
  switch (field.type) {
693
- case 'yn':
930
+ case "yn":
694
931
  return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
695
932
  key: fieldId,
696
933
  label: field.label,
@@ -702,7 +939,7 @@ class MaintenanceRequest extends Component {
702
939
  showError: this.state.showError,
703
940
  required: field.mandatory
704
941
  });
705
- case 'multichoice':
942
+ case "multichoice":
706
943
  return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
707
944
  key: fieldId,
708
945
  label: field.label,
@@ -720,7 +957,7 @@ class MaintenanceRequest extends Component {
720
957
  showError: this.state.showError,
721
958
  required: field.mandatory
722
959
  });
723
- case 'checkbox':
960
+ case "checkbox":
724
961
  return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
725
962
  key: fieldId,
726
963
  label: field.label,
@@ -750,9 +987,9 @@ class MaintenanceRequest extends Component {
750
987
  style: styles.multiChoiceText
751
988
  }, o));
752
989
  }));
753
- case 'text':
754
- case 'email':
755
- case 'phone':
990
+ case "text":
991
+ case "email":
992
+ case "phone":
756
993
  return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
757
994
  key: fieldId,
758
995
  label: field.label,
@@ -763,28 +1000,28 @@ class MaintenanceRequest extends Component {
763
1000
  squaredCorners: true,
764
1001
  isValid: () => this.isFieldValid(field, fieldId),
765
1002
  showError: this.state.showError,
766
- errorText: field.type === 'email' ? 'Not a valid email' : undefined,
1003
+ errorText: field.type === "email" ? "Not a valid email" : undefined,
767
1004
  required: field.mandatory,
768
1005
  sectionStyle: sectionStyle,
769
1006
  autoCapitalize: "sentences",
770
1007
  keyboardType: this.keyboardTypes[field.type]
771
1008
  });
772
- case 'staticTitle':
1009
+ case "staticTitle":
773
1010
  return /*#__PURE__*/React.createElement(Text, {
774
1011
  key: fieldId,
775
1012
  style: [styles.staticTitle, {
776
1013
  color: this.props.colourBrandingMain
777
1014
  }, sectionStyle]
778
1015
  }, field.label);
779
- case 'staticText':
1016
+ case "staticText":
780
1017
  return /*#__PURE__*/React.createElement(View, {
781
1018
  key: fieldId,
782
1019
  style: [styles.staticText, sectionStyle]
783
1020
  }, Helper.toParagraphed(field.label, styles.staticText));
784
- case 'date':
785
- case 'time':
1021
+ case "date":
1022
+ case "time":
786
1023
  return this.renderDateField(field, fieldId, sectionStyle);
787
- case 'image':
1024
+ case "image":
788
1025
  return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
789
1026
  key: fieldId,
790
1027
  label: field.label,
@@ -793,6 +1030,15 @@ class MaintenanceRequest extends Component {
793
1030
  required: field.mandatory,
794
1031
  showError: this.state.showError
795
1032
  }, this.renderImageList(fieldId));
1033
+ case "document":
1034
+ return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
1035
+ key: fieldId,
1036
+ label: field.label,
1037
+ sectionStyle: sectionStyle,
1038
+ isValid: () => this.isFieldValid(field, fieldId),
1039
+ required: field.mandatory,
1040
+ showError: this.state.showError
1041
+ }, this.renderDocumentList(fieldId));
796
1042
  default:
797
1043
  return null;
798
1044
  }
@@ -809,6 +1055,7 @@ class MaintenanceRequest extends Component {
809
1055
  }, customFields.map((field, i) => this.renderField(field, i)));
810
1056
  }
811
1057
  renderForm() {
1058
+ var _this$state$selectedU, _this$state$selectedU2, _this$state$selectedU3;
812
1059
  const {
813
1060
  customFields,
814
1061
  loadingTypes
@@ -839,12 +1086,42 @@ class MaintenanceRequest extends Component {
839
1086
  style: {
840
1087
  marginTop: 16
841
1088
  }
842
- }, /*#__PURE__*/React.createElement(Components.FormCardSection, {
843
- label: 'Name',
844
- placeholder: 'Enter your name',
1089
+ }, this.state.canCreateOnBehalf && /*#__PURE__*/React.createElement(Components.FormCardSection, {
1090
+ label: "Select User",
1091
+ textValue: (_this$state$selectedU = this.state.selectedUser) === null || _this$state$selectedU === void 0 ? void 0 : _this$state$selectedU.displayName,
1092
+ hasContent: true,
1093
+ hasUnderline: true,
1094
+ required: true,
1095
+ errorText: "Please select a user.",
1096
+ showError: this.state.showError && !this.state.selectedUser,
1097
+ sectionStyle: {
1098
+ borderBottomWidth: 1,
1099
+ borderBottomColor: Colours.LINEGREY
1100
+ }
1101
+ }, /*#__PURE__*/React.createElement(TouchableOpacity, {
1102
+ onPress: this.onPressUser
1103
+ }, /*#__PURE__*/React.createElement(View, {
1104
+ style: styles.userPickerContainer
1105
+ }, /*#__PURE__*/React.createElement(View, {
1106
+ style: styles.profileContainer
1107
+ }, /*#__PURE__*/React.createElement(Components.ProfilePic, {
1108
+ ProfilePic: (_this$state$selectedU2 = this.state.selectedUser) === null || _this$state$selectedU2 === void 0 ? void 0 : _this$state$selectedU2.profilePic,
1109
+ Diameter: 30
1110
+ }), /*#__PURE__*/React.createElement(Text, {
1111
+ style: styles.nameText
1112
+ }, ((_this$state$selectedU3 = this.state.selectedUser) === null || _this$state$selectedU3 === void 0 ? void 0 : _this$state$selectedU3.displayName) || "Select User")), /*#__PURE__*/React.createElement(Icon, {
1113
+ name: "angle-right",
1114
+ type: "font-awesome",
1115
+ iconStyle: [styles.sectionTitle, {
1116
+ fontSize: 20,
1117
+ color: this.props.colourBrandingMain
1118
+ }]
1119
+ })))), !this.state.canCreateOnBehalf && /*#__PURE__*/React.createElement(Components.FormCardSection, {
1120
+ label: "Name",
1121
+ placeholder: "Enter your name",
845
1122
  textValue: this.state.userName,
846
1123
  onChangeText: userName => this.onChangeName(userName),
847
- editable: this.props.userType === 'KIOSK' && this.state.submitting === false,
1124
+ editable: this.props.userType === "KIOSK" && this.state.submitting === false,
848
1125
  isValid: () => {
849
1126
  return this.state.userName.length > 1;
850
1127
  },
@@ -853,18 +1130,18 @@ class MaintenanceRequest extends Component {
853
1130
  showError: this.state.showError && this.state.userName.length < 2,
854
1131
  hasUnderline: true
855
1132
  }), /*#__PURE__*/React.createElement(Components.FormCardSection, {
856
- label: 'Contact number',
857
- placeholder: 'Enter phone number',
1133
+ label: "Contact number",
1134
+ placeholder: "Enter phone number",
858
1135
  textValue: this.state.phone,
859
1136
  onChangeText: phone => this.setState({
860
1137
  phone
861
1138
  }),
862
1139
  editable: this.state.submitting === false,
863
1140
  hasUnderline: true,
864
- keyboardType: 'phone-pad'
1141
+ keyboardType: "phone-pad"
865
1142
  }), /*#__PURE__*/React.createElement(Components.FormCardSection, {
866
- label: 'Address',
867
- placeholder: 'Enter your address',
1143
+ label: "Address",
1144
+ placeholder: "Enter your address",
868
1145
  textValue: this.state.roomNumber,
869
1146
  onChangeText: roomNumber => this.setState({
870
1147
  roomNumber
@@ -882,8 +1159,8 @@ class MaintenanceRequest extends Component {
882
1159
  marginTop: 16,
883
1160
  paddingHorizontal: 24,
884
1161
  paddingVertical: 16,
885
- flexDirection: 'row',
886
- justifyContent: 'space-between'
1162
+ flexDirection: "row",
1163
+ justifyContent: "space-between"
887
1164
  }
888
1165
  }, /*#__PURE__*/React.createElement(Text, {
889
1166
  style: styles.sectionTitle
@@ -891,7 +1168,7 @@ class MaintenanceRequest extends Component {
891
1168
  onPress: this.onPressType.bind(this)
892
1169
  }, /*#__PURE__*/React.createElement(View, {
893
1170
  style: {
894
- flexDirection: 'row'
1171
+ flexDirection: "row"
895
1172
  }
896
1173
  }, /*#__PURE__*/React.createElement(Text, {
897
1174
  style: [styles.sectionTitle, {
@@ -910,8 +1187,8 @@ class MaintenanceRequest extends Component {
910
1187
  marginTop: 16
911
1188
  }
912
1189
  }, /*#__PURE__*/React.createElement(Components.FormCardSection, {
913
- label: 'Title',
914
- placeholder: 'Enter a title for your request',
1190
+ label: "Title",
1191
+ placeholder: "Enter a title for your request",
915
1192
  textValue: this.state.title,
916
1193
  onChangeText: title => this.setState({
917
1194
  title
@@ -928,8 +1205,8 @@ class MaintenanceRequest extends Component {
928
1205
  multiline: true,
929
1206
  autoGrow: true
930
1207
  }), /*#__PURE__*/React.createElement(Components.FormCardSection, {
931
- label: 'Description',
932
- placeholder: 'Describe your request here in detail',
1208
+ label: "Description",
1209
+ placeholder: "Describe your request here in detail",
933
1210
  textValue: this.state.description,
934
1211
  onChangeText: description => this.setState({
935
1212
  description
@@ -946,12 +1223,12 @@ class MaintenanceRequest extends Component {
946
1223
  }
947
1224
  }, /*#__PURE__*/React.createElement(View, {
948
1225
  style: [{
949
- width: '100%',
1226
+ width: "100%",
950
1227
  paddingVertical: 16,
951
- flexDirection: 'row',
952
- justifyContent: 'space-between',
953
- alignItems: 'center',
954
- position: 'relative'
1228
+ flexDirection: "row",
1229
+ justifyContent: "space-between",
1230
+ alignItems: "center",
1231
+ position: "relative"
955
1232
  }, this.state.isHome && {
956
1233
  borderBottomWidth: 1,
957
1234
  borderBottomColor: Colours.LINEGREY
@@ -965,13 +1242,13 @@ class MaintenanceRequest extends Component {
965
1242
  isHome: value
966
1243
  }),
967
1244
  trackColor: {
968
- false: '#ddd',
1245
+ false: "#ddd",
969
1246
  true: this.props.colourBrandingMain
970
1247
  },
971
- thumbColor: Platform.OS === 'android' ? '#fff' : null
1248
+ thumbColor: Platform.OS === "android" ? "#fff" : null
972
1249
  })), this.state.isHome && /*#__PURE__*/React.createElement(Components.FormCardSection, {
973
- label: 'Available times',
974
- placeholder: 'Describe your available times here in detail.',
1250
+ label: "Available times",
1251
+ placeholder: "Describe your available times here in detail.",
975
1252
  textValue: this.state.times,
976
1253
  onChangeText: times => this.setState({
977
1254
  times
@@ -993,7 +1270,7 @@ class MaintenanceRequest extends Component {
993
1270
  renderRegisterConfirmation() {
994
1271
  return /*#__PURE__*/React.createElement(Components.ConfirmationPopup, {
995
1272
  confirmText: `${values.textEntityName} submitted`,
996
- repeatText: 'Submit another',
1273
+ repeatText: "Submit another",
997
1274
  visible: this.state.confirmationToShow,
998
1275
  onClose: this.onCloseConfirmationPopup.bind(this),
999
1276
  onPressAction: this.onConfirmationReset.bind(this)
@@ -1017,8 +1294,8 @@ class MaintenanceRequest extends Component {
1017
1294
  return null;
1018
1295
  }
1019
1296
  return /*#__PURE__*/React.createElement(Components.WarningPopup, {
1020
- confirmText: 'No forms are available',
1021
- infoText: 'Check back later for forms.',
1297
+ confirmText: "No forms are available",
1298
+ infoText: "Check back later for forms.",
1022
1299
  visible: this.state.noType,
1023
1300
  onClose: this.onPressBack.bind(this),
1024
1301
  padHorizontal: true
@@ -1032,15 +1309,15 @@ class MaintenanceRequest extends Component {
1032
1309
  popUpType
1033
1310
  } = this.state;
1034
1311
  return /*#__PURE__*/React.createElement(KeyboardAvoidingView, {
1035
- behavior: Platform.OS === 'ios' && 'padding',
1312
+ behavior: "padding",
1036
1313
  style: styles.viewContainer
1037
- }, this.renderUploadMenu(), /*#__PURE__*/React.createElement(View, {
1314
+ }, this.renderImageUploader(), /*#__PURE__*/React.createElement(View, {
1038
1315
  style: styles.container
1039
1316
  }, /*#__PURE__*/React.createElement(Components.Header, {
1040
1317
  leftIcon: "angle-left",
1041
1318
  onPressLeft: this.onPressBack.bind(this),
1042
1319
  text: this.props.strings[`${values.featureKey}_textFeatureTitle`] || values.textFeatureTitle,
1043
- rightText: submitting || success ? null : 'Done',
1320
+ rightText: submitting || success ? null : "Done",
1044
1321
  onPressRight: this.submitRequest.bind(this),
1045
1322
  absoluteRight: true
1046
1323
  }), this.renderForm()), this.renderRegisterConfirmation(), this.renderVideoPlayerPopup(), this.renderNoType(), /*#__PURE__*/React.createElement(DateTimePicker, {
@@ -1050,54 +1327,60 @@ class MaintenanceRequest extends Component {
1050
1327
  isDateTimePickerVisible: false
1051
1328
  }),
1052
1329
  mode: popUpType,
1053
- headerTextIOS: `Pick a ${popUpType}`
1330
+ headerTextIOS: `Pick a ${popUpType}`,
1331
+ date: new Date()
1054
1332
  }));
1055
1333
  }
1056
1334
  }
1057
1335
  const styles = {
1058
1336
  viewContainer: {
1059
1337
  flex: 1,
1060
- backgroundColor: '#fff'
1338
+ backgroundColor: "#fff"
1061
1339
  },
1062
1340
  container: {
1063
1341
  flex: 1,
1064
- position: 'relative',
1065
- backgroundColor: '#f0f0f5'
1342
+ position: "relative",
1343
+ backgroundColor: "#f0f0f5"
1066
1344
  },
1067
1345
  errorText: {
1068
- fontFamily: 'sf-regular',
1346
+ fontFamily: "sf-regular",
1069
1347
  color: Colours.COLOUR_TANGERINE,
1070
1348
  fontSize: 16
1071
1349
  },
1072
1350
  requestSuccess: {
1073
- fontFamily: 'sf-regular',
1351
+ fontFamily: "sf-regular",
1074
1352
  color: Colours.TEXT_DARK,
1075
1353
  fontSize: 17,
1076
- textAlign: 'center'
1354
+ textAlign: "center"
1077
1355
  },
1078
1356
  sectionTitle: {
1079
- fontFamily: 'sf-regular',
1357
+ fontFamily: "sf-regular",
1080
1358
  fontSize: 17,
1081
1359
  color: Colours.TEXT_DARK
1082
1360
  },
1083
1361
  imageListContainer: {
1084
1362
  marginTop: 8,
1085
1363
  padding: 8,
1086
- flexDirection: 'row',
1364
+ flexDirection: "row",
1087
1365
  backgroundColor: Colours.BOXGREY,
1088
1366
  minHeight: 106
1089
1367
  },
1090
1368
  imageListContainerEmpty: {
1091
- justifyContent: 'center',
1092
- alignItems: 'center',
1093
- flexDirection: 'column'
1369
+ justifyContent: "center",
1370
+ alignItems: "center",
1371
+ flexDirection: "column"
1372
+ },
1373
+ documentListContainer: {
1374
+ marginTop: 8,
1375
+ flexDirection: "column",
1376
+ alignItems: "flex-start"
1094
1377
  },
1095
1378
  imageContainer: {
1096
1379
  width: PHOTO_SIZE,
1097
1380
  height: PHOTO_SIZE,
1098
- borderStyle: 'dashed',
1099
- justifyContent: 'center',
1100
- alignItems: 'center',
1381
+ borderStyle: "dashed",
1382
+ justifyContent: "center",
1383
+ alignItems: "center",
1101
1384
  borderWidth: 1,
1102
1385
  borderColor: Colours.LINEGREY,
1103
1386
  borderRadius: 4,
@@ -1106,13 +1389,13 @@ const styles = {
1106
1389
  imageContainerNotEmpty: {
1107
1390
  borderWidth: 1,
1108
1391
  borderColor: Colours.LINEGREY,
1109
- backgroundColor: '#fff',
1110
- borderStyle: 'dashed'
1392
+ backgroundColor: "#fff",
1393
+ borderStyle: "dashed"
1111
1394
  },
1112
1395
  imageBackground: {
1113
1396
  flex: 1,
1114
- height: '100%',
1115
- width: '100%',
1397
+ height: "100%",
1398
+ width: "100%",
1116
1399
  borderRadius: 4
1117
1400
  },
1118
1401
  imageCircle: {
@@ -1120,60 +1403,60 @@ const styles = {
1120
1403
  height: 90,
1121
1404
  borderRadius: 45,
1122
1405
  backgroundColor: Colours.PINKISH_GREY,
1123
- justifyContent: 'center'
1406
+ justifyContent: "center"
1124
1407
  },
1125
1408
  addImageIcon: {
1126
- color: '#fff',
1409
+ color: "#fff",
1127
1410
  fontSize: 32
1128
1411
  },
1129
1412
  imagePlayContainer: {
1130
- position: 'absolute',
1413
+ position: "absolute",
1131
1414
  top: 0,
1132
1415
  left: 0,
1133
1416
  right: 0,
1134
1417
  bottom: 0,
1135
- alignItems: 'center',
1136
- justifyContent: 'center'
1418
+ alignItems: "center",
1419
+ justifyContent: "center"
1137
1420
  },
1138
1421
  imageControlIcon: {
1139
- color: '#fff',
1422
+ color: "#fff",
1140
1423
  fontSize: 20,
1141
- textShadowColor: 'rgba(0,0,0,0.3)',
1424
+ textShadowColor: "rgba(0,0,0,0.3)",
1142
1425
  textShadowOffset: {
1143
1426
  width: 2,
1144
1427
  height: 2
1145
1428
  }
1146
1429
  },
1147
1430
  removeImage: {
1148
- position: 'absolute',
1431
+ position: "absolute",
1149
1432
  top: 0,
1150
1433
  right: 0,
1151
1434
  padding: 4,
1152
1435
  width: 40,
1153
1436
  height: 40,
1154
- alignItems: 'center',
1155
- justifyContent: 'center'
1437
+ alignItems: "center",
1438
+ justifyContent: "center"
1156
1439
  },
1157
1440
  staticTitle: {
1158
1441
  fontSize: 20,
1159
- fontFamily: 'sf-semibold',
1442
+ fontFamily: "sf-semibold",
1160
1443
  color: Colours.TEXT_DARKEST
1161
1444
  },
1162
1445
  staticText: {
1163
1446
  fontSize: 17,
1164
- fontFamily: 'sf-regular',
1447
+ fontFamily: "sf-regular",
1165
1448
  color: Colours.TEXT_DARKEST,
1166
1449
  lineHeight: 24
1167
1450
  },
1168
1451
  multiChoiceOption: {
1169
1452
  marginTop: 16,
1170
- flexDirection: 'row',
1171
- alignItems: 'center',
1453
+ flexDirection: "row",
1454
+ alignItems: "center",
1172
1455
  minHeight: 20
1173
1456
  },
1174
1457
  multiChoiceText: {
1175
1458
  flex: 1,
1176
- fontFamily: 'sf-medium',
1459
+ fontFamily: "sf-medium",
1177
1460
  fontSize: 14,
1178
1461
  color: Colours.TEXT_DARK
1179
1462
  },
@@ -1190,24 +1473,24 @@ const styles = {
1190
1473
  borderRadius: 4
1191
1474
  },
1192
1475
  dateContainer: {
1193
- flexDirection: 'row',
1194
- alignItems: 'center'
1476
+ flexDirection: "row",
1477
+ alignItems: "center"
1195
1478
  },
1196
1479
  dateFieldButton: {
1197
1480
  flex: 1
1198
1481
  },
1199
1482
  dateFieldContainer: {
1200
- flexDirection: 'row',
1483
+ flexDirection: "row",
1201
1484
  borderRadius: 2,
1202
- backgroundColor: '#ebeff2',
1485
+ backgroundColor: "#ebeff2",
1203
1486
  padding: 8,
1204
1487
  marginTop: 8
1205
1488
  },
1206
1489
  dateText: {
1207
1490
  flex: 1,
1208
- fontFamily: 'sf-regular',
1491
+ fontFamily: "sf-regular",
1209
1492
  fontSize: 16,
1210
- color: '#65686D'
1493
+ color: "#65686D"
1211
1494
  },
1212
1495
  dateIcon: {
1213
1496
  fontSize: 18,
@@ -1219,6 +1502,58 @@ const styles = {
1219
1502
  removeIcon: {
1220
1503
  fontSize: 26,
1221
1504
  color: Colours.TEXT_BLUEGREY
1505
+ },
1506
+ documentContainer: {
1507
+ flexDirection: "row",
1508
+ alignItems: "center",
1509
+ justifyContent: "space-between",
1510
+ paddingVertical: 4
1511
+ },
1512
+ documentTypeContainer: {
1513
+ width: 50,
1514
+ height: 60,
1515
+ justifyContent: "center",
1516
+ alignItems: "center",
1517
+ borderRadius: 5,
1518
+ marginRight: 8
1519
+ },
1520
+ documentTypeText: {
1521
+ color: "#fff",
1522
+ fontFamily: "sf-semibold",
1523
+ textAlign: "center"
1524
+ },
1525
+ documentText: {
1526
+ flex: 1,
1527
+ fontFamily: "sf-semibold",
1528
+ fontSize: 16,
1529
+ color: "#65686D"
1530
+ },
1531
+ removeDocumentButton: {
1532
+ padding: 4,
1533
+ width: 40,
1534
+ height: 40,
1535
+ alignItems: "center",
1536
+ justifyContent: "center",
1537
+ marginLeft: 8
1538
+ },
1539
+ removeDocumentIcon: {
1540
+ fontSize: 24
1541
+ },
1542
+ // PC-1255: User picker styles
1543
+ userPickerContainer: {
1544
+ flexDirection: "row",
1545
+ justifyContent: "space-between",
1546
+ alignItems: "center"
1547
+ },
1548
+ profileContainer: {
1549
+ flexDirection: "row",
1550
+ alignItems: "center"
1551
+ },
1552
+ nameText: {
1553
+ fontFamily: "sf-medium",
1554
+ fontSize: 16,
1555
+ color: Colours.TEXT_DARK,
1556
+ marginLeft: 8
1222
1557
  }
1223
1558
  };
1224
1559
  const mapStateToProps = state => {
@@ -1233,7 +1568,8 @@ const mapStateToProps = state => {
1233
1568
  uid,
1234
1569
  site,
1235
1570
  unit,
1236
- phoneNumber
1571
+ phoneNumber,
1572
+ permissions
1237
1573
  } = user;
1238
1574
  return {
1239
1575
  connected: connection.connected,
@@ -1244,8 +1580,10 @@ const mapStateToProps = state => {
1244
1580
  site,
1245
1581
  unit,
1246
1582
  phoneNumber,
1583
+ permissions,
1247
1584
  colourBrandingMain: Colours.getMainBrandingColourFromState(state),
1248
- strings: ((_state$strings = state.strings) === null || _state$strings === void 0 ? void 0 : _state$strings.config) || {}
1585
+ strings: ((_state$strings = state.strings) === null || _state$strings === void 0 ? void 0 : _state$strings.config) || {},
1586
+ optionOnlyForResidents: Helper.getSiteSettingFromState(state, values.optionOnlyForResidents)
1249
1587
  };
1250
1588
  };
1251
1589
  export default connect(mapStateToProps, {