@plusscommunities/pluss-maintenance-app 6.0.5 → 6.0.6-beta.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.
- package/dist/module/actions/types.js +4 -3
- package/dist/module/actions/types.js.map +1 -1
- package/dist/module/apis/maintenanceActions.js +17 -15
- package/dist/module/apis/maintenanceActions.js.map +1 -1
- package/dist/module/components/MaintenanceList.js +4 -3
- package/dist/module/components/MaintenanceList.js.map +1 -1
- package/dist/module/components/MaintenanceListItem.js +3 -2
- package/dist/module/components/MaintenanceListItem.js.map +1 -1
- package/dist/module/components/MaintenanceWidgetItem.js +2 -1
- package/dist/module/components/MaintenanceWidgetItem.js.map +1 -1
- package/dist/module/components/WidgetSmall.js +6 -3
- package/dist/module/components/WidgetSmall.js.map +1 -1
- package/dist/module/feature.config.js +18 -33
- package/dist/module/feature.config.js.map +1 -1
- package/dist/module/index.js +15 -10
- package/dist/module/index.js.map +1 -1
- package/dist/module/screens/MaintenancePage.js +7 -3
- package/dist/module/screens/MaintenancePage.js.map +1 -1
- package/dist/module/screens/RequestDetail.js +105 -30
- package/dist/module/screens/RequestDetail.js.map +1 -1
- package/dist/module/screens/RequestNotes.js +2 -1
- package/dist/module/screens/RequestNotes.js.map +1 -1
- package/dist/module/screens/ServiceRequest.js +552 -84
- package/dist/module/screens/ServiceRequest.js.map +1 -1
- package/dist/module/values.config.a.js +30 -0
- package/dist/module/values.config.a.js.map +1 -0
- package/dist/module/values.config.b.js +30 -0
- package/dist/module/values.config.b.js.map +1 -0
- package/dist/module/values.config.c.js +30 -0
- package/dist/module/values.config.c.js.map +1 -0
- package/dist/module/values.config.d.js +30 -0
- package/dist/module/values.config.d.js.map +1 -0
- package/dist/module/values.config.default.js +30 -0
- package/dist/module/values.config.default.js.map +1 -0
- package/dist/module/values.config.js +30 -0
- package/dist/module/values.config.js.map +1 -0
- package/package.json +9 -3
- package/src/actions/types.js +5 -3
- package/src/apis/maintenanceActions.js +30 -14
- package/src/components/MaintenanceList.js +5 -3
- package/src/components/MaintenanceListItem.js +7 -2
- package/src/components/MaintenanceWidgetItem.js +2 -1
- package/src/components/WidgetSmall.js +6 -3
- package/src/feature.config.js +18 -30
- package/src/index.js +15 -8
- package/src/screens/MaintenancePage.js +5 -4
- package/src/screens/RequestDetail.js +100 -32
- package/src/screens/RequestNotes.js +2 -1
- package/src/screens/ServiceRequest.js +591 -149
- package/src/values.config.a.js +30 -0
- package/src/values.config.b.js +30 -0
- package/src/values.config.c.js +30 -0
- package/src/values.config.d.js +30 -0
- package/src/values.config.default.js +30 -0
- package/src/values.config.js +30 -0
@@ -3,46 +3,120 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
|
|
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
4
|
import React, { Component } from 'react';
|
5
5
|
import { Dimensions, Platform, KeyboardAvoidingView, ScrollView, Text, TouchableOpacity, View, Switch, FlatList, ImageBackground, Keyboard } from 'react-native';
|
6
|
-
import
|
6
|
+
import DateTimePicker from 'react-native-modal-datetime-picker';
|
7
7
|
import { Icon } from 'react-native-elements';
|
8
|
+
import _ from 'lodash';
|
9
|
+
import moment from 'moment';
|
8
10
|
import { connect } from 'react-redux';
|
9
11
|
import { jobAdded } from '../actions';
|
10
12
|
import { maintenanceActions } from '../apis';
|
11
13
|
import { Services } from '../feature.config';
|
12
14
|
import { Components, Colours, Helper, Config } from '../core.config';
|
15
|
+
import { values } from '../values.config';
|
13
16
|
const PHOTO_SIZE = (Dimensions.get('window').width - 64) / 3;
|
14
17
|
class MaintenanceRequest extends Component {
|
15
18
|
constructor(props) {
|
16
19
|
super(props);
|
20
|
+
_defineProperty(this, "onChangeAnswer", (fieldId, answer) => {
|
21
|
+
const update = {
|
22
|
+
customFields: _.cloneDeep(this.state.customFields)
|
23
|
+
};
|
24
|
+
const field = update.customFields[fieldId];
|
25
|
+
field.answer = answer;
|
26
|
+
if (field.isTitle) update.title = field.answer;
|
27
|
+
this.setState(update);
|
28
|
+
});
|
29
|
+
_defineProperty(this, "onChangeToggleAnswer", (fieldId, answer) => {
|
30
|
+
const update = {
|
31
|
+
customFields: _.cloneDeep(this.state.customFields)
|
32
|
+
};
|
33
|
+
const field = update.customFields[fieldId];
|
34
|
+
field.answer = field.answer === answer ? undefined : answer;
|
35
|
+
if (field.isTitle) update.title = field.answer;
|
36
|
+
this.setState(update);
|
37
|
+
});
|
38
|
+
_defineProperty(this, "onChangeCheckboxAnswer", (fieldId, answer) => {
|
39
|
+
const update = {
|
40
|
+
customFields: _.cloneDeep(this.state.customFields)
|
41
|
+
};
|
42
|
+
const field = update.customFields[fieldId];
|
43
|
+
field.answer = _.xor(field.answer || [], [answer]);
|
44
|
+
if (field.isTitle) update.title = field.answer.join(', ');
|
45
|
+
this.setState(update);
|
46
|
+
});
|
47
|
+
_defineProperty(this, "onOpenDatePicker", (field, fieldId) => {
|
48
|
+
Keyboard.dismiss();
|
49
|
+
this.setState({
|
50
|
+
dateFieldId: fieldId,
|
51
|
+
popUpType: field.type,
|
52
|
+
isDateTimePickerVisible: true
|
53
|
+
});
|
54
|
+
});
|
55
|
+
_defineProperty(this, "onClearDate", fieldId => {
|
56
|
+
const update = {
|
57
|
+
customFields: _.cloneDeep(this.state.customFields)
|
58
|
+
};
|
59
|
+
const field = update.customFields[fieldId];
|
60
|
+
field.answer = undefined;
|
61
|
+
if (field.isTitle) update.title = field.answer;
|
62
|
+
this.setState(update);
|
63
|
+
});
|
64
|
+
_defineProperty(this, "onDateSelected", date => {
|
65
|
+
const {
|
66
|
+
customFields,
|
67
|
+
dateFieldId,
|
68
|
+
popUpType
|
69
|
+
} = this.state;
|
70
|
+
const update = {
|
71
|
+
customFields: _.cloneDeep(customFields),
|
72
|
+
isDateTimePickerVisible: false,
|
73
|
+
fieldId: null
|
74
|
+
};
|
75
|
+
const field = update.customFields[dateFieldId];
|
76
|
+
const dateObj = moment(date);
|
77
|
+
if (popUpType === 'date') {
|
78
|
+
field.answer = dateObj.format('YYYY-MM-DD');
|
79
|
+
if (field.isTitle) update.title = dateObj.format('DD MMM YYYY');
|
80
|
+
} else {
|
81
|
+
field.answer = dateObj.format('HH:mm');
|
82
|
+
if (field.isTitle) update.title = dateObj.format('h:mm a');
|
83
|
+
}
|
84
|
+
this.setState(update);
|
85
|
+
});
|
17
86
|
_defineProperty(this, "onUploadStarted", (uploadUri, imageUri) => {
|
18
|
-
const
|
19
|
-
|
87
|
+
const {
|
88
|
+
imageFieldId
|
89
|
+
} = this.state;
|
90
|
+
const imagesUpdate = this.getImages(imageFieldId);
|
91
|
+
imagesUpdate.splice(imagesUpdate.length - 1, 0, {
|
20
92
|
uploading: true,
|
21
93
|
uploadProgress: '0%',
|
22
94
|
uploadUri,
|
23
95
|
imageUri,
|
24
96
|
allowRetry: true
|
25
97
|
});
|
26
|
-
this.
|
27
|
-
images
|
28
|
-
});
|
98
|
+
this.setImages(imagesUpdate, imageFieldId);
|
29
99
|
});
|
30
100
|
_defineProperty(this, "onUploadProgress", progress => {
|
31
|
-
const
|
32
|
-
|
101
|
+
const {
|
102
|
+
imageFieldId
|
103
|
+
} = this.state;
|
104
|
+
const imagesUpdate = this.getImages(imageFieldId);
|
105
|
+
imagesUpdate.map(img => {
|
33
106
|
if (img.uploadUri === progress.uri) {
|
34
107
|
img.uploadProgress = progress.percentage;
|
35
108
|
img.uploading = true;
|
36
109
|
img.allowRetry = true;
|
37
110
|
}
|
38
111
|
});
|
39
|
-
this.
|
40
|
-
images
|
41
|
-
});
|
112
|
+
this.setImages(imagesUpdate, imageFieldId);
|
42
113
|
});
|
43
114
|
_defineProperty(this, "onUploadSuccess", async (uri, uploadUri) => {
|
44
|
-
const
|
45
|
-
|
115
|
+
const {
|
116
|
+
imageFieldId
|
117
|
+
} = this.state;
|
118
|
+
const imagesUpdate = this.getImages(imageFieldId);
|
119
|
+
imagesUpdate.map(img => {
|
46
120
|
if (img.uploadUri === uploadUri && img.uploading) {
|
47
121
|
img.url = uri.replace('/general/', '/general1400/');
|
48
122
|
img.thumbNailExists = false;
|
@@ -50,41 +124,81 @@ class MaintenanceRequest extends Component {
|
|
50
124
|
img.allowRetry = true;
|
51
125
|
}
|
52
126
|
});
|
53
|
-
this.
|
54
|
-
images
|
55
|
-
}, () => this.waitForThumbnails());
|
127
|
+
this.setImages(imagesUpdate, imageFieldId, () => this.waitForThumbnails());
|
56
128
|
});
|
57
129
|
_defineProperty(this, "onUploadFailed", uploadUri => {
|
58
|
-
const
|
59
|
-
|
130
|
+
const {
|
131
|
+
imageFieldId
|
132
|
+
} = this.state;
|
133
|
+
const imagesUpdate = this.getImages(imageFieldId);
|
134
|
+
imagesUpdate.map(img => {
|
60
135
|
if (img.uploadUri === uploadUri) {
|
61
136
|
img.uploading = true; // Requried for retry
|
62
137
|
img.uploadProgress = '';
|
63
138
|
img.allowRetry = true;
|
64
139
|
}
|
65
140
|
});
|
66
|
-
this.
|
67
|
-
images
|
68
|
-
});
|
141
|
+
this.setImages(imagesUpdate, imageFieldId);
|
69
142
|
});
|
70
143
|
_defineProperty(this, "onLibrarySelected", uri => {
|
71
|
-
const
|
72
|
-
|
144
|
+
const {
|
145
|
+
imageFieldId
|
146
|
+
} = this.state;
|
147
|
+
const imagesUpdate = this.getImages(imageFieldId);
|
148
|
+
imagesUpdate.splice(imagesUpdate.length - 1, 0, {
|
73
149
|
uploading: false,
|
74
150
|
allowRetry: false,
|
75
151
|
url: Helper.get1400(uri),
|
76
152
|
thumbNailExists: true,
|
77
153
|
thumbNailUrl: Helper.getThumb300(uri)
|
78
154
|
});
|
79
|
-
this.
|
80
|
-
images
|
81
|
-
});
|
155
|
+
this.setImages(imagesUpdate, imageFieldId);
|
82
156
|
});
|
83
|
-
_defineProperty(this, "
|
157
|
+
_defineProperty(this, "isFieldValid", (field, fieldId) => {
|
158
|
+
const {
|
159
|
+
mandatory,
|
160
|
+
type,
|
161
|
+
answer
|
162
|
+
} = field;
|
163
|
+
if (['staticTitle', 'staticText'].includes(type)) return true;
|
164
|
+
const imagesList = type === 'image' ? this.getImageUrls(fieldId) : [];
|
165
|
+
const checkMandatory = () => {
|
166
|
+
if (!mandatory) return true;
|
167
|
+
switch (type) {
|
168
|
+
case 'yn':
|
169
|
+
return _.isBoolean(answer);
|
170
|
+
case 'image':
|
171
|
+
return imagesList.length > 0;
|
172
|
+
case 'checkbox':
|
173
|
+
return _.isArray(answer) && answer.length > 0;
|
174
|
+
default:
|
175
|
+
return !_.isNil(answer) && !_.isEmpty(answer);
|
176
|
+
}
|
177
|
+
};
|
178
|
+
const checkFormat = () => {
|
179
|
+
if (_.isNil(answer) || _.isEmpty(answer)) return true;
|
180
|
+
switch (type) {
|
181
|
+
case 'email':
|
182
|
+
return Helper.isEmail(answer);
|
183
|
+
case 'date':
|
184
|
+
return moment(answer, 'YYYY-MM-DD', true).isValid();
|
185
|
+
case 'time':
|
186
|
+
return moment(answer, 'HH:mm', true).isValid();
|
187
|
+
default:
|
188
|
+
return true;
|
189
|
+
}
|
190
|
+
};
|
191
|
+
const valid = checkMandatory() && checkFormat();
|
192
|
+
return valid;
|
193
|
+
});
|
194
|
+
_defineProperty(this, "showUploadMenu", fieldId => {
|
84
195
|
Keyboard.dismiss();
|
85
196
|
if (this.state.uploadingImage || this.state.submitting) {
|
86
197
|
return;
|
87
198
|
}
|
199
|
+
if (fieldId) this.setState({
|
200
|
+
imageFieldId: fieldId
|
201
|
+
});
|
88
202
|
this.imageUploader.showUploadMenu();
|
89
203
|
});
|
90
204
|
_defineProperty(this, "submit", async () => {
|
@@ -100,12 +214,15 @@ class MaintenanceRequest extends Component {
|
|
100
214
|
y: 0
|
101
215
|
});
|
102
216
|
}, 100);
|
103
|
-
const images =
|
104
|
-
|
105
|
-
|
106
|
-
|
217
|
+
const images = this.getImageUrls();
|
218
|
+
|
219
|
+
// Fix custom images field answers
|
220
|
+
const customFields = _.cloneDeep(this.state.customFields);
|
221
|
+
const updatedCustomFields = customFields.map((field, fieldId) => {
|
222
|
+
if (field.type === 'image') field.answer = this.getImageUrls(fieldId);
|
223
|
+
return field;
|
107
224
|
});
|
108
|
-
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).then(res => {
|
225
|
+
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 => {
|
109
226
|
if (res.data.success) {
|
110
227
|
this.refreshRequest(res.data.searchResult);
|
111
228
|
if (this.props.onSubmissionSuccess) this.props.onSubmissionSuccess(res.data);
|
@@ -130,22 +247,71 @@ class MaintenanceRequest extends Component {
|
|
130
247
|
_defineProperty(this, "refreshRequest", async id => {
|
131
248
|
try {
|
132
249
|
const job = await maintenanceActions.getJob(Helper.getSite(this.props.site), id);
|
133
|
-
// console.log('refreshRequest', job?.data);
|
134
250
|
this.props.jobAdded(job.data);
|
135
251
|
} catch (error) {
|
136
252
|
console.log('refreshRequest error', error);
|
137
253
|
}
|
138
254
|
});
|
255
|
+
_defineProperty(this, "validateCustomFields", () => {
|
256
|
+
const {
|
257
|
+
customFields
|
258
|
+
} = this.state;
|
259
|
+
if (!customFields || customFields.length === 0) return true;
|
260
|
+
return customFields.every((field, index) => {
|
261
|
+
const isValid = this.isFieldValid(field, index);
|
262
|
+
return isValid;
|
263
|
+
});
|
264
|
+
});
|
265
|
+
_defineProperty(this, "getImages", (fieldId = null) => {
|
266
|
+
const {
|
267
|
+
images,
|
268
|
+
customFieldImages
|
269
|
+
} = this.state;
|
270
|
+
const imagesList = _.cloneDeep(fieldId ? customFieldImages[fieldId] : images);
|
271
|
+
if (!imagesList || !Array.isArray(imagesList) || imagesList.length === 0) {
|
272
|
+
return [{
|
273
|
+
add: true
|
274
|
+
}];
|
275
|
+
}
|
276
|
+
return imagesList;
|
277
|
+
});
|
278
|
+
_defineProperty(this, "setImages", (imagesList, fieldId = null, callback = null) => {
|
279
|
+
let update = {};
|
280
|
+
if (fieldId) {
|
281
|
+
const customFieldImages = _.cloneDeep(this.state.customFieldImages);
|
282
|
+
customFieldImages[fieldId] = imagesList;
|
283
|
+
update = {
|
284
|
+
customFieldImages
|
285
|
+
};
|
286
|
+
} else {
|
287
|
+
update = {
|
288
|
+
images: imagesList
|
289
|
+
};
|
290
|
+
}
|
291
|
+
this.setState(update, callback);
|
292
|
+
});
|
293
|
+
_defineProperty(this, "getImageUrls", (fieldId = null) => {
|
294
|
+
const imagesList = this.getImages(fieldId);
|
295
|
+
return _.filter(imagesList, img => {
|
296
|
+
return !img.uploading && !img.add;
|
297
|
+
}).map(img => {
|
298
|
+
return img.url;
|
299
|
+
});
|
300
|
+
});
|
139
301
|
_defineProperty(this, "waitForThumbnails", () => {
|
140
302
|
if (this.checkThumb) return;
|
141
303
|
this.checkThumb = setInterval(async () => {
|
142
|
-
const
|
143
|
-
|
304
|
+
const {
|
305
|
+
imageFieldId
|
306
|
+
} = this.state;
|
307
|
+
const imagesList = this.getImages(imageFieldId);
|
308
|
+
const imagesUpdate = [];
|
309
|
+
await Promise.all(imagesList.map(image => {
|
144
310
|
return new Promise(async resolve => {
|
145
311
|
const newImage = {
|
146
312
|
...image
|
147
313
|
};
|
148
|
-
|
314
|
+
imagesUpdate.push(newImage);
|
149
315
|
if (newImage.url && !newImage.thumbNailExists) {
|
150
316
|
newImage.uploading = false;
|
151
317
|
newImage.allowRetry = false;
|
@@ -155,22 +321,18 @@ class MaintenanceRequest extends Component {
|
|
155
321
|
resolve(true);
|
156
322
|
});
|
157
323
|
}));
|
158
|
-
const thumbnailsExist =
|
324
|
+
const thumbnailsExist = imagesUpdate.every(image => !image.url || image.thumbNailExists);
|
159
325
|
if (thumbnailsExist) {
|
160
326
|
clearInterval(this.checkThumb);
|
161
327
|
this.checkThumb = null;
|
162
|
-
this.
|
163
|
-
images
|
164
|
-
});
|
328
|
+
this.setImages(imagesUpdate, imageFieldId);
|
165
329
|
}
|
166
330
|
}, 2000);
|
167
331
|
});
|
168
|
-
_defineProperty(this, "removeImage", index => {
|
169
|
-
const
|
170
|
-
|
171
|
-
this.
|
172
|
-
images
|
173
|
-
});
|
332
|
+
_defineProperty(this, "removeImage", (index, fieldId) => {
|
333
|
+
const imagesUpdate = this.getImages(fieldId);
|
334
|
+
imagesUpdate.splice(index, 1);
|
335
|
+
this.setImages(imagesUpdate, fieldId);
|
174
336
|
});
|
175
337
|
_defineProperty(this, "toggleFullscreenVideo", url => {
|
176
338
|
if (typeof url !== 'string') url = '';
|
@@ -200,9 +362,20 @@ class MaintenanceRequest extends Component {
|
|
200
362
|
currentVideoUrl: '',
|
201
363
|
isHome: false,
|
202
364
|
types: [],
|
203
|
-
confirmationToShow: false
|
365
|
+
confirmationToShow: false,
|
366
|
+
customFields: [],
|
367
|
+
customFieldImages: {},
|
368
|
+
isDateTimePickerVisible: false,
|
369
|
+
popUpType: 'date',
|
370
|
+
dateFieldId: null,
|
371
|
+
imageFieldId: null
|
204
372
|
};
|
205
373
|
this.checkThumb = null;
|
374
|
+
this.keyboardTypes = {
|
375
|
+
phone: 'phone-pad',
|
376
|
+
email: 'email-address',
|
377
|
+
text: 'default'
|
378
|
+
};
|
206
379
|
}
|
207
380
|
componentDidMount() {
|
208
381
|
if (this.props.userType !== 'KIOSK') {
|
@@ -221,7 +394,7 @@ class MaintenanceRequest extends Component {
|
|
221
394
|
Services.navigation.goBack();
|
222
395
|
}
|
223
396
|
onPressType() {
|
224
|
-
Services.navigation.navigate(
|
397
|
+
Services.navigation.navigate(values.screenJobTypePicker, {
|
225
398
|
currentType: this.state.type,
|
226
399
|
types: this.state.types,
|
227
400
|
onSelectType: this.pickType.bind(this)
|
@@ -247,8 +420,14 @@ class MaintenanceRequest extends Component {
|
|
247
420
|
}],
|
248
421
|
submitting: false,
|
249
422
|
success: false,
|
250
|
-
fail: false
|
251
|
-
|
423
|
+
fail: false,
|
424
|
+
customFields: [],
|
425
|
+
customFieldImages: {},
|
426
|
+
isDateTimePickerVisible: false,
|
427
|
+
popUpType: 'date',
|
428
|
+
dateFieldId: null,
|
429
|
+
imageFieldId: null
|
430
|
+
}, () => this.pickType(this.state.type));
|
252
431
|
}
|
253
432
|
getJobTypes() {
|
254
433
|
const self = this;
|
@@ -259,20 +438,38 @@ class MaintenanceRequest extends Component {
|
|
259
438
|
self.getDefaultJob();
|
260
439
|
}).catch(() => {});
|
261
440
|
}
|
262
|
-
getDefaultJob() {
|
263
|
-
if (this.state.types.length !== 0 && this.state.jobId == null) {
|
264
|
-
this.setState({
|
265
|
-
type: this.state.types[0].typeName
|
266
|
-
});
|
267
|
-
}
|
268
|
-
}
|
269
441
|
pickType(type) {
|
442
|
+
const {
|
443
|
+
types
|
444
|
+
} = this.state;
|
445
|
+
const selected = types.find(t => t.typeName === type) || {};
|
270
446
|
this.setState({
|
271
|
-
type
|
447
|
+
type,
|
448
|
+
customFields: selected.hasCustomFields && selected.customFields.length > 0 ? _.cloneDeep(selected.customFields) : []
|
272
449
|
});
|
273
450
|
}
|
451
|
+
getDefaultJob() {
|
452
|
+
const {
|
453
|
+
types,
|
454
|
+
jobId
|
455
|
+
} = this.state;
|
456
|
+
if (types.length !== 0 && jobId == null) {
|
457
|
+
const defaultType = types[0];
|
458
|
+
this.pickType(defaultType.typeName);
|
459
|
+
}
|
460
|
+
}
|
274
461
|
submitRequest() {
|
275
|
-
|
462
|
+
const {
|
463
|
+
customFields,
|
464
|
+
submitting,
|
465
|
+
uploadingImage,
|
466
|
+
title,
|
467
|
+
roomNumber,
|
468
|
+
isHome,
|
469
|
+
times
|
470
|
+
} = this.state;
|
471
|
+
const hasCustomFields = customFields && customFields.length > 0;
|
472
|
+
if (submitting || !this.props.connected) {
|
276
473
|
if (!this.props.connected) {
|
277
474
|
this.setState({
|
278
475
|
error: {
|
@@ -282,25 +479,41 @@ class MaintenanceRequest extends Component {
|
|
282
479
|
}
|
283
480
|
return;
|
284
481
|
}
|
285
|
-
if (
|
286
|
-
return;
|
287
|
-
}
|
482
|
+
if (uploadingImage) return;
|
288
483
|
this.setState({
|
289
484
|
error: null,
|
290
485
|
showError: false
|
291
486
|
});
|
292
|
-
if (
|
293
|
-
|
294
|
-
|
487
|
+
if (title.length === 0 || !roomNumber || roomNumber.length === 0) {
|
488
|
+
console.log('submitRequest - error', {
|
489
|
+
title,
|
490
|
+
roomNumber
|
295
491
|
});
|
296
|
-
return;
|
297
|
-
}
|
298
|
-
if (this.state.isHome && this.state.times.length < 2) {
|
299
492
|
this.setState({
|
300
493
|
showError: true
|
301
494
|
});
|
302
495
|
return;
|
303
496
|
}
|
497
|
+
if (hasCustomFields) {
|
498
|
+
if (!this.validateCustomFields()) {
|
499
|
+
console.log('submitRequest - custom fields error');
|
500
|
+
this.setState({
|
501
|
+
showError: true
|
502
|
+
});
|
503
|
+
return;
|
504
|
+
}
|
505
|
+
} else {
|
506
|
+
if (isHome && times.length < 2) {
|
507
|
+
console.log('submitRequest - error', {
|
508
|
+
isHome,
|
509
|
+
times
|
510
|
+
});
|
511
|
+
this.setState({
|
512
|
+
showError: true
|
513
|
+
});
|
514
|
+
return;
|
515
|
+
}
|
516
|
+
}
|
304
517
|
this.submit();
|
305
518
|
}
|
306
519
|
renderUploadMenu() {
|
@@ -323,14 +536,15 @@ class MaintenanceRequest extends Component {
|
|
323
536
|
hideLibrary: true
|
324
537
|
});
|
325
538
|
}
|
326
|
-
renderImage(item, index) {
|
539
|
+
renderImage(item, index, fieldId = null) {
|
327
540
|
const isVideoUrl = Helper.isVideo(item.url);
|
541
|
+
const imagesList = this.getImages(fieldId);
|
328
542
|
if (item.add) {
|
329
543
|
return /*#__PURE__*/React.createElement(TouchableOpacity, {
|
330
544
|
activeOpacity: 0.8,
|
331
|
-
onPress: this.showUploadMenu
|
545
|
+
onPress: () => this.showUploadMenu(fieldId)
|
332
546
|
}, /*#__PURE__*/React.createElement(View, {
|
333
|
-
style: [styles.imageContainer,
|
547
|
+
style: [styles.imageContainer, imagesList.length > 1 && styles.imageContainerNotEmpty, index % 3 === 0 && {
|
334
548
|
marginLeft: 0
|
335
549
|
}, index > 2 && {
|
336
550
|
marginTop: 8
|
@@ -344,7 +558,7 @@ class MaintenanceRequest extends Component {
|
|
344
558
|
}))));
|
345
559
|
}
|
346
560
|
return /*#__PURE__*/React.createElement(View, {
|
347
|
-
style: [styles.imageContainer,
|
561
|
+
style: [styles.imageContainer, imagesList.length > 1 && styles.imageContainerNotEmpty, index % 3 === 0 && {
|
348
562
|
marginLeft: 0
|
349
563
|
}, index > 2 && {
|
350
564
|
marginTop: 8
|
@@ -366,7 +580,7 @@ class MaintenanceRequest extends Component {
|
|
366
580
|
iconStyle: styles.imageControlIcon
|
367
581
|
}))), /*#__PURE__*/React.createElement(TouchableOpacity, {
|
368
582
|
style: styles.removeImage,
|
369
|
-
onPress: this.removeImage
|
583
|
+
onPress: () => this.removeImage(index, fieldId)
|
370
584
|
}, /*#__PURE__*/React.createElement(Icon, {
|
371
585
|
name: "remove",
|
372
586
|
type: "font-awesome",
|
@@ -385,24 +599,196 @@ class MaintenanceRequest extends Component {
|
|
385
599
|
style: styles.requestSuccess
|
386
600
|
}, "Your request has been submitted. Thank you."));
|
387
601
|
}
|
388
|
-
renderImageList() {
|
602
|
+
renderImageList(fieldId = null) {
|
603
|
+
const imagesList = this.getImages(fieldId);
|
389
604
|
return /*#__PURE__*/React.createElement(View, {
|
390
605
|
style: styles.imageSection
|
391
606
|
}, /*#__PURE__*/React.createElement(View, {
|
392
|
-
style: [styles.imageListContainer,
|
607
|
+
style: [styles.imageListContainer, imagesList.length < 2 && styles.imageListContainerEmpty]
|
393
608
|
}, /*#__PURE__*/React.createElement(FlatList, {
|
394
609
|
keyboardShouldPersistTaps: "always",
|
395
610
|
enableEmptySections: true,
|
396
|
-
data:
|
611
|
+
data: imagesList,
|
397
612
|
renderItem: ({
|
398
613
|
item,
|
399
614
|
index
|
400
|
-
}) => this.renderImage(item, index),
|
615
|
+
}) => this.renderImage(item, index, fieldId),
|
401
616
|
keyExtractor: (item, index) => index,
|
402
617
|
numColumns: 3
|
403
618
|
})));
|
404
619
|
}
|
620
|
+
renderDateField(field, fieldId, sectionStyle) {
|
621
|
+
let displayText, placeHolder, icon, errorText;
|
622
|
+
if (field.type === 'date') {
|
623
|
+
displayText = field.answer ? moment(field.answer, 'YYYY-MM-DD').format('DD MMM YYYY') : '';
|
624
|
+
placeHolder = 'dd mmm yyyy';
|
625
|
+
icon = 'calendar';
|
626
|
+
errorText = 'Not a valid date';
|
627
|
+
} else {
|
628
|
+
displayText = field.answer ? moment(field.answer, 'HH:mm').format('h:mm a') : '';
|
629
|
+
placeHolder = '--:-- --';
|
630
|
+
icon = 'clock-o';
|
631
|
+
errorText = 'Not a valid time';
|
632
|
+
}
|
633
|
+
return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
|
634
|
+
key: fieldId,
|
635
|
+
label: field.label,
|
636
|
+
sectionStyle: sectionStyle,
|
637
|
+
isValid: () => this.isFieldValid(field, fieldId),
|
638
|
+
required: field.mandatory,
|
639
|
+
showError: this.state.showError,
|
640
|
+
errorText: errorText
|
641
|
+
}, /*#__PURE__*/React.createElement(View, {
|
642
|
+
style: styles.dateContainer
|
643
|
+
}, /*#__PURE__*/React.createElement(TouchableOpacity, {
|
644
|
+
style: styles.dateFieldButton,
|
645
|
+
onPress: () => this.onOpenDatePicker(field, fieldId)
|
646
|
+
}, /*#__PURE__*/React.createElement(View, {
|
647
|
+
style: styles.dateFieldContainer
|
648
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
649
|
+
style: styles.dateText
|
650
|
+
}, displayText || placeHolder), /*#__PURE__*/React.createElement(Icon, {
|
651
|
+
type: "font-awesome",
|
652
|
+
name: icon,
|
653
|
+
iconStyle: styles.dateIcon
|
654
|
+
}))), displayText ? /*#__PURE__*/React.createElement(TouchableOpacity, {
|
655
|
+
style: styles.dateClearButton,
|
656
|
+
onPress: () => this.onClearDate(fieldId)
|
657
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
658
|
+
type: "font-awesome",
|
659
|
+
name: "times",
|
660
|
+
iconStyle: styles.removeIcon
|
661
|
+
})) : null));
|
662
|
+
}
|
663
|
+
renderField(field, fieldId) {
|
664
|
+
const sectionStyle = {
|
665
|
+
marginTop: fieldId === 0 ? 24 : 0,
|
666
|
+
marginBottom: 24
|
667
|
+
};
|
668
|
+
switch (field.type) {
|
669
|
+
case 'yn':
|
670
|
+
return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
|
671
|
+
key: fieldId,
|
672
|
+
label: field.label,
|
673
|
+
sectionStyle: sectionStyle,
|
674
|
+
inputType: "toggle",
|
675
|
+
value: field.answer,
|
676
|
+
onChange: answer => this.onChangeToggleAnswer(fieldId, answer),
|
677
|
+
isValid: () => this.isFieldValid(field, fieldId),
|
678
|
+
showError: this.state.showError,
|
679
|
+
required: field.mandatory
|
680
|
+
});
|
681
|
+
case 'multichoice':
|
682
|
+
return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
|
683
|
+
key: fieldId,
|
684
|
+
label: field.label,
|
685
|
+
sectionStyle: sectionStyle,
|
686
|
+
inputType: "radio",
|
687
|
+
value: field.answer,
|
688
|
+
onChange: answer => this.onChangeToggleAnswer(fieldId, answer),
|
689
|
+
options: field.values.map(o => {
|
690
|
+
return {
|
691
|
+
Label: o,
|
692
|
+
Value: o
|
693
|
+
};
|
694
|
+
}),
|
695
|
+
isValid: () => this.isFieldValid(field, fieldId),
|
696
|
+
showError: this.state.showError,
|
697
|
+
required: field.mandatory
|
698
|
+
});
|
699
|
+
case 'checkbox':
|
700
|
+
return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
|
701
|
+
key: fieldId,
|
702
|
+
label: field.label,
|
703
|
+
sectionStyle: sectionStyle,
|
704
|
+
isValid: () => this.isFieldValid(field, fieldId),
|
705
|
+
showError: this.state.showError,
|
706
|
+
required: field.mandatory
|
707
|
+
}, field.values.map((o, i) => {
|
708
|
+
const isActive = field.answer && _.includes(field.answer, o);
|
709
|
+
return /*#__PURE__*/React.createElement(TouchableOpacity, {
|
710
|
+
onPress: () => this.onChangeCheckboxAnswer(fieldId, o),
|
711
|
+
key: i,
|
712
|
+
style: styles.multiChoiceOption,
|
713
|
+
hitSlop: {
|
714
|
+
top: 8,
|
715
|
+
left: 8,
|
716
|
+
bottom: 8,
|
717
|
+
right: 8
|
718
|
+
}
|
719
|
+
}, isActive ? /*#__PURE__*/React.createElement(Components.TickIcon, {
|
720
|
+
style: styles.tick,
|
721
|
+
size: 20,
|
722
|
+
color: this.props.colourBrandingMain
|
723
|
+
}) : /*#__PURE__*/React.createElement(View, {
|
724
|
+
style: styles.unticked
|
725
|
+
}), /*#__PURE__*/React.createElement(Text, {
|
726
|
+
style: styles.multiChoiceText
|
727
|
+
}, o));
|
728
|
+
}));
|
729
|
+
case 'text':
|
730
|
+
case 'email':
|
731
|
+
case 'phone':
|
732
|
+
return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
|
733
|
+
key: fieldId,
|
734
|
+
label: field.label,
|
735
|
+
placeholder: field.placeHolder,
|
736
|
+
value: field.answer,
|
737
|
+
onChangeText: val => this.onChangeAnswer(fieldId, val),
|
738
|
+
editable: true,
|
739
|
+
squaredCorners: true,
|
740
|
+
isValid: () => this.isFieldValid(field, fieldId),
|
741
|
+
showError: this.state.showError,
|
742
|
+
errorText: field.type === 'email' ? 'Not a valid email' : undefined,
|
743
|
+
required: field.mandatory,
|
744
|
+
sectionStyle: sectionStyle,
|
745
|
+
autoCapitalize: "sentences",
|
746
|
+
keyboardType: this.keyboardTypes[field.type]
|
747
|
+
});
|
748
|
+
case 'staticTitle':
|
749
|
+
return /*#__PURE__*/React.createElement(Text, {
|
750
|
+
key: fieldId,
|
751
|
+
style: [styles.staticTitle, {
|
752
|
+
color: this.props.colourBrandingMain
|
753
|
+
}, sectionStyle]
|
754
|
+
}, field.label);
|
755
|
+
case 'staticText':
|
756
|
+
return /*#__PURE__*/React.createElement(View, {
|
757
|
+
key: fieldId,
|
758
|
+
style: [styles.staticText, sectionStyle]
|
759
|
+
}, Helper.toParagraphed(field.label, styles.staticText));
|
760
|
+
case 'date':
|
761
|
+
case 'time':
|
762
|
+
return this.renderDateField(field, fieldId, sectionStyle);
|
763
|
+
case 'image':
|
764
|
+
return /*#__PURE__*/React.createElement(Components.GenericInputSection, {
|
765
|
+
key: fieldId,
|
766
|
+
label: field.label,
|
767
|
+
sectionStyle: sectionStyle,
|
768
|
+
isValid: () => this.isFieldValid(field, fieldId),
|
769
|
+
required: field.mandatory,
|
770
|
+
showError: this.state.showError
|
771
|
+
}, this.renderImageList(fieldId));
|
772
|
+
default:
|
773
|
+
return null;
|
774
|
+
}
|
775
|
+
}
|
776
|
+
renderCustomFields() {
|
777
|
+
const {
|
778
|
+
customFields
|
779
|
+
} = this.state;
|
780
|
+
if (!customFields || customFields.length === 0) return null;
|
781
|
+
return /*#__PURE__*/React.createElement(Components.FormCard, {
|
782
|
+
style: {
|
783
|
+
marginTop: 16
|
784
|
+
}
|
785
|
+
}, customFields.map((field, i) => this.renderField(field, i)));
|
786
|
+
}
|
405
787
|
renderForm() {
|
788
|
+
const {
|
789
|
+
customFields
|
790
|
+
} = this.state;
|
791
|
+
const hasCustomFields = customFields && customFields.length > 0;
|
406
792
|
return /*#__PURE__*/React.createElement(View, {
|
407
793
|
style: {
|
408
794
|
flex: 1
|
@@ -464,7 +850,7 @@ class MaintenanceRequest extends Component {
|
|
464
850
|
},
|
465
851
|
required: true,
|
466
852
|
errorText: "Please provide your address.",
|
467
|
-
showError: this.state.showError && this.state.roomNumber
|
853
|
+
showError: this.state.showError && (!this.state.roomNumber || this.state.roomNumber.length < 2)
|
468
854
|
})), /*#__PURE__*/React.createElement(Components.FormCard, {
|
469
855
|
style: {
|
470
856
|
marginTop: 16,
|
@@ -493,7 +879,7 @@ class MaintenanceRequest extends Component {
|
|
493
879
|
fontSize: 20,
|
494
880
|
color: this.props.colourBrandingMain
|
495
881
|
}]
|
496
|
-
})))), /*#__PURE__*/React.createElement(Components.FormCard, {
|
882
|
+
})))), hasCustomFields ? this.renderCustomFields() : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Components.FormCard, {
|
497
883
|
style: {
|
498
884
|
marginTop: 16
|
499
885
|
}
|
@@ -576,7 +962,7 @@ class MaintenanceRequest extends Component {
|
|
576
962
|
autoCorrect: true,
|
577
963
|
multiline: true,
|
578
964
|
autoGrow: true
|
579
|
-
})), this.renderImageList())));
|
965
|
+
})), this.renderImageList()))));
|
580
966
|
}
|
581
967
|
renderRegisterConfirmation() {
|
582
968
|
return /*#__PURE__*/React.createElement(Components.ConfirmationPopup, {
|
@@ -601,6 +987,12 @@ class MaintenanceRequest extends Component {
|
|
601
987
|
});
|
602
988
|
}
|
603
989
|
render() {
|
990
|
+
const {
|
991
|
+
submitting,
|
992
|
+
success,
|
993
|
+
isDateTimePickerVisible,
|
994
|
+
popUpType
|
995
|
+
} = this.state;
|
604
996
|
return /*#__PURE__*/React.createElement(KeyboardAvoidingView, {
|
605
997
|
behavior: Platform.OS === 'ios' && 'padding',
|
606
998
|
style: styles.viewContainer
|
@@ -609,11 +1001,19 @@ class MaintenanceRequest extends Component {
|
|
609
1001
|
}, /*#__PURE__*/React.createElement(Components.Header, {
|
610
1002
|
leftIcon: "angle-left",
|
611
1003
|
onPressLeft: this.onPressBack.bind(this),
|
612
|
-
text:
|
613
|
-
rightText:
|
1004
|
+
text: this.props.strings[`${values.featureKey}_textFeatureTitle`] || values.textFeatureTitle,
|
1005
|
+
rightText: submitting || success ? null : 'Done',
|
614
1006
|
onPressRight: this.submitRequest.bind(this),
|
615
1007
|
absoluteRight: true
|
616
|
-
}), this.renderForm()), this.renderRegisterConfirmation(), this.renderVideoPlayerPopup()
|
1008
|
+
}), this.renderForm()), this.renderRegisterConfirmation(), this.renderVideoPlayerPopup(), /*#__PURE__*/React.createElement(DateTimePicker, {
|
1009
|
+
isVisible: isDateTimePickerVisible,
|
1010
|
+
onConfirm: this.onDateSelected,
|
1011
|
+
onCancel: () => this.setState({
|
1012
|
+
isDateTimePickerVisible: false
|
1013
|
+
}),
|
1014
|
+
mode: popUpType,
|
1015
|
+
headerTextIOS: `Pick a ${popUpType}`
|
1016
|
+
}));
|
617
1017
|
}
|
618
1018
|
}
|
619
1019
|
const styles = {
|
@@ -715,9 +1115,76 @@ const styles = {
|
|
715
1115
|
height: 40,
|
716
1116
|
alignItems: 'center',
|
717
1117
|
justifyContent: 'center'
|
1118
|
+
},
|
1119
|
+
staticTitle: {
|
1120
|
+
fontSize: 20,
|
1121
|
+
fontFamily: 'sf-semibold',
|
1122
|
+
color: Colours.TEXT_DARKEST
|
1123
|
+
},
|
1124
|
+
staticText: {
|
1125
|
+
fontSize: 17,
|
1126
|
+
fontFamily: 'sf-regular',
|
1127
|
+
color: Colours.TEXT_DARKEST,
|
1128
|
+
lineHeight: 24
|
1129
|
+
},
|
1130
|
+
multiChoiceOption: {
|
1131
|
+
marginTop: 16,
|
1132
|
+
flexDirection: 'row',
|
1133
|
+
alignItems: 'center',
|
1134
|
+
minHeight: 20
|
1135
|
+
},
|
1136
|
+
multiChoiceText: {
|
1137
|
+
flex: 1,
|
1138
|
+
fontFamily: 'sf-medium',
|
1139
|
+
fontSize: 14,
|
1140
|
+
color: Colours.TEXT_DARK
|
1141
|
+
},
|
1142
|
+
tick: {
|
1143
|
+
marginRight: 10,
|
1144
|
+
borderRadius: 4
|
1145
|
+
},
|
1146
|
+
unticked: {
|
1147
|
+
marginRight: 10,
|
1148
|
+
width: 20,
|
1149
|
+
height: 20,
|
1150
|
+
borderColor: Colours.LINEGREY,
|
1151
|
+
borderWidth: 1,
|
1152
|
+
borderRadius: 4
|
1153
|
+
},
|
1154
|
+
dateContainer: {
|
1155
|
+
flexDirection: 'row',
|
1156
|
+
alignItems: 'center'
|
1157
|
+
},
|
1158
|
+
dateFieldButton: {
|
1159
|
+
flex: 1
|
1160
|
+
},
|
1161
|
+
dateFieldContainer: {
|
1162
|
+
flexDirection: 'row',
|
1163
|
+
borderRadius: 2,
|
1164
|
+
backgroundColor: '#ebeff2',
|
1165
|
+
padding: 8,
|
1166
|
+
marginTop: 8
|
1167
|
+
},
|
1168
|
+
dateText: {
|
1169
|
+
flex: 1,
|
1170
|
+
fontFamily: 'sf-regular',
|
1171
|
+
fontSize: 16,
|
1172
|
+
color: '#65686D'
|
1173
|
+
},
|
1174
|
+
dateIcon: {
|
1175
|
+
fontSize: 18,
|
1176
|
+
color: Colours.TEXT_BLUEGREY
|
1177
|
+
},
|
1178
|
+
dateClearButton: {
|
1179
|
+
paddingLeft: 12
|
1180
|
+
},
|
1181
|
+
removeIcon: {
|
1182
|
+
fontSize: 26,
|
1183
|
+
color: Colours.TEXT_BLUEGREY
|
718
1184
|
}
|
719
1185
|
};
|
720
1186
|
const mapStateToProps = state => {
|
1187
|
+
var _state$strings;
|
721
1188
|
const {
|
722
1189
|
user,
|
723
1190
|
connection
|
@@ -739,7 +1206,8 @@ const mapStateToProps = state => {
|
|
739
1206
|
site,
|
740
1207
|
unit,
|
741
1208
|
phoneNumber,
|
742
|
-
colourBrandingMain: Colours.getMainBrandingColourFromState(state)
|
1209
|
+
colourBrandingMain: Colours.getMainBrandingColourFromState(state),
|
1210
|
+
strings: ((_state$strings = state.strings) === null || _state$strings === void 0 ? void 0 : _state$strings.config) || {}
|
743
1211
|
};
|
744
1212
|
};
|
745
1213
|
export default connect(mapStateToProps, {
|