@plusscommunities/pluss-maintenance-app 6.0.17 → 6.0.19
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/apis/maintenanceActions.js +8 -0
- package/dist/module/apis/maintenanceActions.js.map +1 -1
- package/dist/module/screens/RequestDetail.js +117 -2
- package/dist/module/screens/RequestDetail.js.map +1 -1
- package/dist/module/screens/ServiceRequest.js +8 -0
- package/dist/module/screens/ServiceRequest.js.map +1 -1
- package/package.json +1 -1
- package/src/apis/maintenanceActions.js +6 -0
- package/src/screens/RequestDetail.js +103 -0
- package/src/screens/ServiceRequest.js +10 -1
|
@@ -38,6 +38,8 @@ class RequestDetail extends Component {
|
|
|
38
38
|
showMessages: false,
|
|
39
39
|
assignees: [],
|
|
40
40
|
selectedPDF: null,
|
|
41
|
+
externalSync: null,
|
|
42
|
+
loadingExternalSync: false,
|
|
41
43
|
};
|
|
42
44
|
|
|
43
45
|
this.scrollView = React.createRef();
|
|
@@ -51,6 +53,7 @@ class RequestDetail extends Component {
|
|
|
51
53
|
this.getJob();
|
|
52
54
|
this.updateJobState(this.props.job);
|
|
53
55
|
this.getAssignees();
|
|
56
|
+
this.getExternalSync();
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
getJob = async () => {
|
|
@@ -60,6 +63,8 @@ class RequestDetail extends Component {
|
|
|
60
63
|
// console.log('getJob', JSON.stringify(res.data, null, 2));
|
|
61
64
|
this.props.jobAdded(res.data);
|
|
62
65
|
this.updateJobState(res.data);
|
|
66
|
+
// Refresh external sync data when job is refreshed
|
|
67
|
+
this.getExternalSync();
|
|
63
68
|
} catch (error) {
|
|
64
69
|
console.log('getJob error', error.toString());
|
|
65
70
|
// check for 403 or 404 error
|
|
@@ -85,6 +90,24 @@ class RequestDetail extends Component {
|
|
|
85
90
|
}
|
|
86
91
|
};
|
|
87
92
|
|
|
93
|
+
getExternalSync = async () => {
|
|
94
|
+
// Only fetch if user has maintenance tracking permission
|
|
95
|
+
if (!this.hasPermission()) return;
|
|
96
|
+
if (!this.props.job?.id) return;
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
this.setState({ loadingExternalSync: true });
|
|
100
|
+
const res = await maintenanceActions.getExternalSync(this.props.job.id);
|
|
101
|
+
this.setState({ externalSync: res.data, loadingExternalSync: false });
|
|
102
|
+
} catch (error) {
|
|
103
|
+
// 404 is expected if no sync - don't show error
|
|
104
|
+
if (error.response?.status !== 404) {
|
|
105
|
+
console.log('getExternalSync error', error);
|
|
106
|
+
}
|
|
107
|
+
this.setState({ loadingExternalSync: false });
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
88
111
|
updateJobState(defaultJob) {
|
|
89
112
|
const job = _.find(this.props.jobs, j => j.id === this.props.job.id) || defaultJob;
|
|
90
113
|
if (!job) {
|
|
@@ -542,6 +565,43 @@ class RequestDetail extends Component {
|
|
|
542
565
|
return content;
|
|
543
566
|
}
|
|
544
567
|
|
|
568
|
+
renderExternalSync() {
|
|
569
|
+
const { externalSync, loadingExternalSync } = this.state;
|
|
570
|
+
|
|
571
|
+
// Only show if user has permission and external sync data exists
|
|
572
|
+
if (!this.hasPermission()) return null;
|
|
573
|
+
if (!externalSync || loadingExternalSync) return null;
|
|
574
|
+
|
|
575
|
+
return (
|
|
576
|
+
<View style={[styles.externalSyncContainer, Helper.getShadowStyle()]}>
|
|
577
|
+
<View style={styles.externalSyncHeader}>
|
|
578
|
+
<Text style={styles.externalSyncTitle}>External Sync</Text>
|
|
579
|
+
<Icon name="sync" type="material" iconStyle={[styles.externalSyncIcon, { color: this.props.colourBrandingMain }]} />
|
|
580
|
+
</View>
|
|
581
|
+
<View style={styles.externalSyncContent}>
|
|
582
|
+
{externalSync.systemType && (
|
|
583
|
+
<View style={styles.externalSyncRow}>
|
|
584
|
+
<Text style={styles.externalSyncLabel}>System:</Text>
|
|
585
|
+
<Text style={styles.externalSyncValue}>{externalSync.systemType}</Text>
|
|
586
|
+
</View>
|
|
587
|
+
)}
|
|
588
|
+
{externalSync.externalId && (
|
|
589
|
+
<View style={styles.externalSyncRow}>
|
|
590
|
+
<Text style={styles.externalSyncLabel}>External ID:</Text>
|
|
591
|
+
<Text style={styles.externalSyncValue}>{externalSync.externalId}</Text>
|
|
592
|
+
</View>
|
|
593
|
+
)}
|
|
594
|
+
{externalSync.syncedAt && (
|
|
595
|
+
<View style={styles.externalSyncRow}>
|
|
596
|
+
<Text style={styles.externalSyncLabel}>Synced:</Text>
|
|
597
|
+
<Text style={styles.externalSyncValue}>{moment(externalSync.syncedAt).format('D MMM YYYY h:mma')}</Text>
|
|
598
|
+
</View>
|
|
599
|
+
)}
|
|
600
|
+
</View>
|
|
601
|
+
</View>
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
|
|
545
605
|
renderCustomFields() {
|
|
546
606
|
const { job } = this.state;
|
|
547
607
|
const { customFields } = job;
|
|
@@ -620,6 +680,7 @@ class RequestDetail extends Component {
|
|
|
620
680
|
{!_.isEmpty(job.phone) && <Text style={styles.phoneText}>{job.phone}</Text>}
|
|
621
681
|
</View>
|
|
622
682
|
</View>
|
|
683
|
+
{this.renderExternalSync()}
|
|
623
684
|
</View>
|
|
624
685
|
)}
|
|
625
686
|
</View>
|
|
@@ -1028,6 +1089,48 @@ const styles = StyleSheet.create({
|
|
|
1028
1089
|
fontSize: 16,
|
|
1029
1090
|
color: '#65686D',
|
|
1030
1091
|
},
|
|
1092
|
+
externalSyncContainer: {
|
|
1093
|
+
backgroundColor: '#fff',
|
|
1094
|
+
marginBottom: 16,
|
|
1095
|
+
borderRadius: 8,
|
|
1096
|
+
padding: 16,
|
|
1097
|
+
},
|
|
1098
|
+
externalSyncHeader: {
|
|
1099
|
+
flexDirection: 'row',
|
|
1100
|
+
justifyContent: 'space-between',
|
|
1101
|
+
alignItems: 'center',
|
|
1102
|
+
marginBottom: 12,
|
|
1103
|
+
paddingBottom: 12,
|
|
1104
|
+
borderBottomWidth: 1,
|
|
1105
|
+
borderBottomColor: Colours.LINEGREY,
|
|
1106
|
+
},
|
|
1107
|
+
externalSyncTitle: {
|
|
1108
|
+
fontFamily: 'sf-semibold',
|
|
1109
|
+
fontSize: 16,
|
|
1110
|
+
color: Colours.TEXT_DARKEST,
|
|
1111
|
+
},
|
|
1112
|
+
externalSyncIcon: {
|
|
1113
|
+
fontSize: 20,
|
|
1114
|
+
},
|
|
1115
|
+
externalSyncContent: {
|
|
1116
|
+
paddingTop: 4,
|
|
1117
|
+
},
|
|
1118
|
+
externalSyncRow: {
|
|
1119
|
+
flexDirection: 'row',
|
|
1120
|
+
marginBottom: 10,
|
|
1121
|
+
},
|
|
1122
|
+
externalSyncLabel: {
|
|
1123
|
+
fontFamily: 'sf-semibold',
|
|
1124
|
+
fontSize: 14,
|
|
1125
|
+
color: Colours.TEXT_DARK,
|
|
1126
|
+
width: 100,
|
|
1127
|
+
},
|
|
1128
|
+
externalSyncValue: {
|
|
1129
|
+
fontFamily: 'sf-regular',
|
|
1130
|
+
fontSize: 14,
|
|
1131
|
+
color: Colours.TEXT_DARKEST,
|
|
1132
|
+
flex: 1,
|
|
1133
|
+
},
|
|
1031
1134
|
});
|
|
1032
1135
|
|
|
1033
1136
|
const mapStateToProps = state => {
|
|
@@ -173,16 +173,25 @@ class MaintenanceRequest extends Component {
|
|
|
173
173
|
if (userDetails.unit) {
|
|
174
174
|
update.roomNumber = userDetails.unit;
|
|
175
175
|
}
|
|
176
|
+
if (!this.state.customFields || !_.some(this.state.customFields, 'isTitle')) {
|
|
177
|
+
update.title = userDetails.displayName || null;
|
|
178
|
+
}
|
|
176
179
|
}
|
|
177
180
|
} catch (error) {
|
|
178
181
|
// Permission denied (403) or other error - continue without auto-population
|
|
179
182
|
// User can still manually enter contact details
|
|
180
183
|
console.log('Could not fetch user details for auto-population:', error);
|
|
181
|
-
}
|
|
184
|
+
} finally {
|
|
185
|
+
// In any case, we still need a title. Inform the user to set one form field as a title.
|
|
186
|
+
if (!state.title && !update.title) {
|
|
187
|
+
update.title = "[Missing title - Set one of the form field as title in the community manager]"
|
|
188
|
+
}
|
|
182
189
|
|
|
190
|
+
}
|
|
183
191
|
this.setState(update);
|
|
184
192
|
};
|
|
185
193
|
|
|
194
|
+
|
|
186
195
|
onChangeAnswer = (fieldId, answer) => {
|
|
187
196
|
const update = { customFields: _.cloneDeep(this.state.customFields) };
|
|
188
197
|
const field = update.customFields[fieldId];
|