@plusscommunities/pluss-maintenance-app-forms 6.0.8-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.
Files changed (90) hide show
  1. package/dist/module/actions/JobActions.js +20 -0
  2. package/dist/module/actions/JobActions.js.map +1 -0
  3. package/dist/module/actions/index.js +2 -0
  4. package/dist/module/actions/index.js.map +1 -0
  5. package/dist/module/actions/types.js +5 -0
  6. package/dist/module/actions/types.js.map +1 -0
  7. package/dist/module/apis/index.js +2 -0
  8. package/dist/module/apis/index.js.map +1 -0
  9. package/dist/module/apis/maintenanceActions.js +171 -0
  10. package/dist/module/apis/maintenanceActions.js.map +1 -0
  11. package/dist/module/components/FilterPopupMenu.js +271 -0
  12. package/dist/module/components/FilterPopupMenu.js.map +1 -0
  13. package/dist/module/components/MaintenanceList.js +360 -0
  14. package/dist/module/components/MaintenanceList.js.map +1 -0
  15. package/dist/module/components/MaintenanceListItem.js +322 -0
  16. package/dist/module/components/MaintenanceListItem.js.map +1 -0
  17. package/dist/module/components/MaintenanceWidgetItem.js +149 -0
  18. package/dist/module/components/MaintenanceWidgetItem.js.map +1 -0
  19. package/dist/module/components/StatusSelectorPopup.js +89 -0
  20. package/dist/module/components/StatusSelectorPopup.js.map +1 -0
  21. package/dist/module/components/WidgetLarge.js +9 -0
  22. package/dist/module/components/WidgetLarge.js.map +1 -0
  23. package/dist/module/components/WidgetSmall.js +171 -0
  24. package/dist/module/components/WidgetSmall.js.map +1 -0
  25. package/dist/module/core.config.js +17 -0
  26. package/dist/module/core.config.js.map +1 -0
  27. package/dist/module/feature.config.js +75 -0
  28. package/dist/module/feature.config.js.map +1 -0
  29. package/dist/module/helper.js +33 -0
  30. package/dist/module/helper.js.map +1 -0
  31. package/dist/module/images/speechbubble.png +0 -0
  32. package/dist/module/index.js +25 -0
  33. package/dist/module/index.js.map +1 -0
  34. package/dist/module/reducers/JobsReducer.js +63 -0
  35. package/dist/module/reducers/JobsReducer.js.map +1 -0
  36. package/dist/module/screens/JobTypePicker.js +130 -0
  37. package/dist/module/screens/JobTypePicker.js.map +1 -0
  38. package/dist/module/screens/MaintenancePage.js +92 -0
  39. package/dist/module/screens/MaintenancePage.js.map +1 -0
  40. package/dist/module/screens/RequestDetail.js +980 -0
  41. package/dist/module/screens/RequestDetail.js.map +1 -0
  42. package/dist/module/screens/RequestNotes.js +390 -0
  43. package/dist/module/screens/RequestNotes.js.map +1 -0
  44. package/dist/module/screens/ServiceRequest.js +1243 -0
  45. package/dist/module/screens/ServiceRequest.js.map +1 -0
  46. package/dist/module/values.config.a.js +30 -0
  47. package/dist/module/values.config.a.js.map +1 -0
  48. package/dist/module/values.config.b.js +30 -0
  49. package/dist/module/values.config.b.js.map +1 -0
  50. package/dist/module/values.config.c.js +30 -0
  51. package/dist/module/values.config.c.js.map +1 -0
  52. package/dist/module/values.config.d.js +30 -0
  53. package/dist/module/values.config.d.js.map +1 -0
  54. package/dist/module/values.config.default.js +35 -0
  55. package/dist/module/values.config.default.js.map +1 -0
  56. package/dist/module/values.config.forms.js +35 -0
  57. package/dist/module/values.config.forms.js.map +1 -0
  58. package/dist/module/values.config.js +35 -0
  59. package/dist/module/values.config.js.map +1 -0
  60. package/package.json +53 -0
  61. package/src/actions/JobActions.js +22 -0
  62. package/src/actions/index.js +1 -0
  63. package/src/actions/types.js +5 -0
  64. package/src/apis/index.js +1 -0
  65. package/src/apis/maintenanceActions.js +163 -0
  66. package/src/components/FilterPopupMenu.js +256 -0
  67. package/src/components/MaintenanceList.js +335 -0
  68. package/src/components/MaintenanceListItem.js +289 -0
  69. package/src/components/MaintenanceWidgetItem.js +132 -0
  70. package/src/components/StatusSelectorPopup.js +87 -0
  71. package/src/components/WidgetLarge.js +10 -0
  72. package/src/components/WidgetSmall.js +152 -0
  73. package/src/core.config.js +5 -0
  74. package/src/feature.config.js +73 -0
  75. package/src/helper.js +39 -0
  76. package/src/images/speechbubble.png +0 -0
  77. package/src/index.js +25 -0
  78. package/src/reducers/JobsReducer.js +51 -0
  79. package/src/screens/JobTypePicker.js +107 -0
  80. package/src/screens/MaintenancePage.js +96 -0
  81. package/src/screens/RequestDetail.js +915 -0
  82. package/src/screens/RequestNotes.js +418 -0
  83. package/src/screens/ServiceRequest.js +1219 -0
  84. package/src/values.config.a.js +30 -0
  85. package/src/values.config.b.js +30 -0
  86. package/src/values.config.c.js +30 -0
  87. package/src/values.config.d.js +30 -0
  88. package/src/values.config.default.js +35 -0
  89. package/src/values.config.forms.js +35 -0
  90. package/src/values.config.js +35 -0
@@ -0,0 +1,418 @@
1
+ import React, { Component } from 'react';
2
+ import { ScrollView, View, Text, TouchableOpacity, Modal, KeyboardAvoidingView, Platform } from 'react-native';
3
+ import { connect } from 'react-redux';
4
+ import { Icon } from 'react-native-elements';
5
+ import _ from 'lodash';
6
+ import moment from 'moment';
7
+ import { jobAdded } from '../actions';
8
+ import { maintenanceActions } from '../apis';
9
+ import { getBottomSpace } from 'react-native-iphone-x-helper';
10
+ import { Services } from '../feature.config';
11
+ import { Components, Colours, Helper } from '../core.config';
12
+ import { values } from '../values.config';
13
+
14
+ class RequestNotes extends Component {
15
+ constructor(props) {
16
+ super(props);
17
+
18
+ this.state = {
19
+ job: {},
20
+ selectedPDF: null,
21
+ noteAttachments: [],
22
+ noteInput: '',
23
+ addNoteOpen: false,
24
+ };
25
+ }
26
+
27
+ componentDidMount() {
28
+ this.updateJobState();
29
+ }
30
+
31
+ componentDidUpdate(prevProps) {
32
+ if (prevProps.jobs !== this.props.jobs) {
33
+ this.updateJobState();
34
+ }
35
+ }
36
+
37
+ updateJobState() {
38
+ const job = _.find(this.props.jobs, j => j.id === this.props.job.id) || this.props.job;
39
+ this.setState({ job });
40
+ }
41
+
42
+ onPressBack = () => {
43
+ Services.navigation.goBack();
44
+ };
45
+
46
+ onOpenAttachment = a => {
47
+ this.setState({
48
+ selectedPDF: a,
49
+ });
50
+ };
51
+
52
+ onCloseAttachment = () => {
53
+ this.setState({
54
+ selectedPDF: null,
55
+ });
56
+ };
57
+
58
+ onPressDeleteNote = n => {
59
+ this.setState({
60
+ noteToDelete: n,
61
+ });
62
+ };
63
+
64
+ onPressConfirmDelete = () => {
65
+ maintenanceActions.deleteNote(this.props.job.id, this.state.noteToDelete.Id);
66
+ const newNotes = _.filter(this.state.job.Notes, note => {
67
+ return note.Id !== this.state.noteToDelete.Id;
68
+ });
69
+ const newJob = { ...this.props.job };
70
+ newJob.Notes = newNotes;
71
+ this.props.jobAdded(newJob);
72
+ this.props.onChange && this.props.onChange();
73
+ this.setState({
74
+ job: newJob,
75
+ noteToDelete: null,
76
+ });
77
+ };
78
+
79
+ onPressCancelDelete = () => {
80
+ this.setState({ noteToDelete: null });
81
+ };
82
+
83
+ isReadyToSaveNote = () => {
84
+ if (
85
+ _.some(this.state.noteAttachments, n => {
86
+ return n.Uploading;
87
+ })
88
+ ) {
89
+ return false;
90
+ }
91
+ return !_.isEmpty(this.state.noteInput) || !_.isEmpty(this.state.noteAttachments);
92
+ };
93
+
94
+ openAddNote = () => {
95
+ this.setState({
96
+ addNoteOpen: true,
97
+ editingNote: null,
98
+ });
99
+ };
100
+
101
+ closeAddNote = () => {
102
+ const newState = {
103
+ addNoteOpen: false,
104
+ editingNote: null,
105
+ };
106
+ if (!!this.state.editingNote) {
107
+ newState.noteInput = '';
108
+ newState.noteAttachments = [];
109
+ }
110
+ this.setState(newState);
111
+ };
112
+
113
+ openEditNote = n => {
114
+ this.setState({
115
+ noteAttachments: n.Attachments || [],
116
+ noteInput: n.Note || '',
117
+ addNoteOpen: true,
118
+ editingNote: n.Id,
119
+ noteMenuOpen: null,
120
+ });
121
+ };
122
+
123
+ confirmAddNote = async () => {
124
+ if (!this.isReadyToSaveNote()) {
125
+ return;
126
+ }
127
+
128
+ try {
129
+ this.setState({ submittingNote: true });
130
+ const res = await (this.state.editingNote
131
+ ? maintenanceActions.editNote(
132
+ this.props.job.id,
133
+ this.state.editingNote,
134
+ this.state.noteInput,
135
+ this.state.noteAttachments.map(a => {
136
+ return {
137
+ Title: a.Title,
138
+ Source: a.Source,
139
+ };
140
+ }),
141
+ )
142
+ : maintenanceActions.addNote(
143
+ this.props.job.id,
144
+ this.state.noteInput,
145
+ this.state.noteAttachments.map(a => {
146
+ return {
147
+ Title: a.Title,
148
+ Source: a.Source,
149
+ };
150
+ }),
151
+ ));
152
+ this.setState(
153
+ {
154
+ job: res.data.job,
155
+ submittingNote: false,
156
+ addNoteOpen: false,
157
+ noteInput: '',
158
+ noteAttachments: [],
159
+ editingNote: null,
160
+ },
161
+ () => {
162
+ this.props.jobAdded(res.data.job);
163
+ this.props.onChange && this.props.onChange();
164
+ },
165
+ );
166
+ } catch (err) {
167
+ console.log('error');
168
+ console.log(err);
169
+ this.setState({
170
+ submittingNote: false,
171
+ });
172
+ }
173
+ };
174
+
175
+ renderAttachment(a, i) {
176
+ return (
177
+ <Components.Attachment
178
+ onPress={() => {
179
+ this.onOpenAttachment(a);
180
+ }}
181
+ key={i}
182
+ title={a.Title}
183
+ />
184
+ );
185
+ }
186
+
187
+ renderNote(n) {
188
+ return (
189
+ <View style={styles.noteContainer} key={n.Id}>
190
+ <View style={styles.noteContainerTop}>
191
+ <Components.ProfilePic Diameter={30} ProfilePic={n.User.profilePic} style={styles.profilePic} />
192
+ <View style={styles.noteContainerTopRight}>
193
+ {this.props.user.uid === n.User.id && (
194
+ <TouchableOpacity
195
+ onPress={() => {
196
+ this.onPressDeleteNote(n);
197
+ }}
198
+ >
199
+ <View style={[styles.noteContainerButtonContainer, { backgroundColor: this.props.colourBrandingMain }]}>
200
+ <Icon name="trash" type="font-awesome" iconStyle={styles.noteContainerButtonIcon} />
201
+ </View>
202
+ </TouchableOpacity>
203
+ )}
204
+ {this.props.user.uid === n.User.id && (
205
+ <TouchableOpacity
206
+ onPress={() => {
207
+ this.openEditNote(n);
208
+ }}
209
+ >
210
+ <View style={[styles.noteContainerButtonContainer, { backgroundColor: this.props.colourBrandingMain }]}>
211
+ <Icon name="pencil" type="font-awesome" iconStyle={styles.noteContainerButtonIcon} />
212
+ </View>
213
+ </TouchableOpacity>
214
+ )}
215
+ <View style={styles.noteContainerTopFill}>
216
+ <Text style={styles.noteContainerName}>{n.User.displayName}</Text>
217
+ </View>
218
+ </View>
219
+ </View>
220
+ <Text style={styles.noteContainerText}>{n.Note}</Text>
221
+ {(n.Attachments || []).map((a, i) => this.renderAttachment(a, i))}
222
+ <Text style={styles.noteTimestamp}>
223
+ {moment
224
+ .utc(n.Timestamp)
225
+ .local()
226
+ .format(Helper.TIMESTAMP_FORMAT)}
227
+ </Text>
228
+ </View>
229
+ );
230
+ }
231
+
232
+ renderNotes() {
233
+ return (this.state.job.Notes || []).map((n, i) => {
234
+ return this.renderNote(n, i);
235
+ });
236
+ }
237
+
238
+ renderPDF() {
239
+ if (_.isEmpty(this.state.selectedPDF)) {
240
+ return null;
241
+ }
242
+ return (
243
+ <Components.PDFPopup
244
+ source={this.state.selectedPDF.Source}
245
+ onClose={this.onCloseAttachment}
246
+ title={this.state.selectedPDF.Title}
247
+ pdfCount={1}
248
+ />
249
+ );
250
+ }
251
+
252
+ renderNoteDeleteConfirm() {
253
+ return (
254
+ <Components.ConfirmPopup
255
+ visible={!!this.state.noteToDelete}
256
+ onConfirm={this.onPressConfirmDelete}
257
+ onCancel={this.onPressCancelDelete}
258
+ onClose={this.onPressCancelDelete}
259
+ text="Are you sure you want to delete this note?"
260
+ />
261
+ );
262
+ }
263
+
264
+ renderFooterContent() {
265
+ if (this.state.submittingNote) {
266
+ return <Components.Spinner />;
267
+ }
268
+ return (
269
+ <Components.InlineButton color={this.props.colourBrandingMain} onPress={this.confirmAddNote} fillTouchable large>
270
+ Save
271
+ </Components.InlineButton>
272
+ );
273
+ }
274
+
275
+ renderAdd() {
276
+ return (
277
+ <Modal animationType="slide" visible={this.state.addNoteOpen}>
278
+ <KeyboardAvoidingView style={styles.container} behavior={Platform.OS === 'ios' && 'padding'}>
279
+ <Components.Header leftText="Cancel" onPressLeft={this.closeAddNote} text="" />
280
+ <ScrollView style={styles.scrollContainer} contentContainerStyle={styles.innerContainer}>
281
+ <Components.TextStyle type="pageHeading">Add Staff Note</Components.TextStyle>
282
+ <Components.GenericInputSection
283
+ label="Content"
284
+ placeholder="Insert your notes here..."
285
+ value={this.state.noteInput}
286
+ onChangeText={noteInput => this.setState({ noteInput })}
287
+ isValid={() => {
288
+ return !_.isEmpty(this.state.noteInput);
289
+ }}
290
+ autoCapitalize="sentences"
291
+ minHeight={135}
292
+ autoCorrect
293
+ multiline
294
+ autoGrow
295
+ required
296
+ squaredCorners
297
+ sectionStyle={styles.inputSection}
298
+ />
299
+ <Components.GenericInputSection label="Attachments" sectionStyle={styles.inputSection}>
300
+ {this.state.editingNote ? (
301
+ (this.state.noteAttachments || []).map((a, i) => this.renderAttachment(a, i))
302
+ ) : (
303
+ <Components.TextStyle type="body" style={styles.attachmentInfo}>
304
+ PDFs can only be attached to notes from the Community Manager.
305
+ </Components.TextStyle>
306
+ )}
307
+ </Components.GenericInputSection>
308
+ </ScrollView>
309
+ <View style={styles.popupFooter}>{this.renderFooterContent()}</View>
310
+ </KeyboardAvoidingView>
311
+ </Modal>
312
+ );
313
+ }
314
+
315
+ render() {
316
+ return (
317
+ <View style={styles.container}>
318
+ {this.renderPDF()}
319
+ {this.renderNoteDeleteConfirm()}
320
+ {this.renderAdd()}
321
+ <Components.Header leftIcon="angle-left" onPressLeft={this.onPressBack} text="Staff Notes" />
322
+ <ScrollView style={styles.scrollContainer} contentContainerStyle={styles.innerContainer}>
323
+ {this.renderNotes()}
324
+ </ScrollView>
325
+ <Components.AddButton onPress={this.openAddNote} />
326
+ </View>
327
+ );
328
+ }
329
+ }
330
+
331
+ const styles = {
332
+ container: {
333
+ flex: 1,
334
+ position: 'relative',
335
+ backgroundColor: '#fff',
336
+ },
337
+ scrollContainer: {
338
+ flex: 1,
339
+ },
340
+ innerContainer: {
341
+ padding: 16,
342
+ },
343
+ popupFooter: {
344
+ paddingHorizontal: 16,
345
+ paddingBottom: getBottomSpace() + 16,
346
+ },
347
+ noteContainer: {
348
+ ...Helper.getShadowStyle(),
349
+ padding: 8,
350
+ marginBottom: 16,
351
+ },
352
+ noteContainerTop: {
353
+ flexDirection: 'row',
354
+ alignItems: 'center',
355
+ },
356
+ profilePic: {
357
+ marginRight: 8,
358
+ },
359
+ noteContainerTopFill: {
360
+ flex: 1,
361
+ },
362
+ noteContainerName: {
363
+ fontFamily: 'sf-semibold',
364
+ fontSize: 13,
365
+ color: Colours.TEXT_DARKEST,
366
+ },
367
+ noteContainerText: {
368
+ marginTop: 8,
369
+ fontFamily: 'sf-regular',
370
+ fontSize: 13,
371
+ color: Colours.TEXT_DARKEST,
372
+ },
373
+ noteTimestamp: {
374
+ marginTop: 8,
375
+ fontFamily: 'sf-semibold',
376
+ fontSize: 11,
377
+ color: Colours.TEXT_LIGHT,
378
+ },
379
+ noteContainerTopRight: {
380
+ flex: 1,
381
+ flexDirection: 'row-reverse',
382
+ alignItems: 'center',
383
+ },
384
+ noteContainerButtonContainer: {
385
+ width: 24,
386
+ height: 24,
387
+ borderRadius: 12,
388
+ alignItems: 'center',
389
+ justifyContent: 'center',
390
+ marginLeft: 8,
391
+ },
392
+ noteContainerButtonIcon: {
393
+ fontSize: 13,
394
+ color: '#fff',
395
+ },
396
+ inputSection: {
397
+ marginTop: 24,
398
+ },
399
+ sectionHeading: {
400
+ fontFamily: 'qs-bold',
401
+ fontSize: 24,
402
+ color: Colours.TEXT_DARKEST,
403
+ },
404
+ attachmentInfo: {
405
+ marginTop: 8,
406
+ },
407
+ };
408
+
409
+ const mapStateToProps = state => {
410
+ return {
411
+ user: state.user,
412
+ colourBrandingMain: Colours.getMainBrandingColourFromState(state),
413
+ colourBrandingLight: Colours.getLightBrandingColourFromState(state),
414
+ jobs: state[values.reducerKey].jobs,
415
+ };
416
+ };
417
+
418
+ export default connect(mapStateToProps, { jobAdded })(RequestNotes);