@plusscommunities/pluss-maintenance-app-forms 8.0.12 → 8.0.13

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.
@@ -23,7 +23,7 @@ export const maintenanceActions = {
23
23
  data: { site, status, type },
24
24
  });
25
25
  },
26
- getJobs2: (site, status, priority, type, lastKey) => {
26
+ getJobs2: (site, status, priority, type, lastKey, assignee) => {
27
27
  const query = { site };
28
28
  if (status) {
29
29
  query.status = status;
@@ -37,13 +37,21 @@ export const maintenanceActions = {
37
37
  if (lastKey) {
38
38
  query.lastKey = JSON.stringify(lastKey);
39
39
  }
40
+ if (assignee) {
41
+ query.assignee = assignee;
42
+ }
40
43
  return Session.authedFunction({
41
44
  method: "GET",
42
45
  url: Helper.getUrl(values.serviceKey, "get/requests", query),
43
46
  });
44
47
  },
48
+ /**
49
+ * @deprecated Use getJobs2 with pagination instead.
50
+ * This method recursively fetches ALL pages which can be slow for large datasets.
51
+ * For better performance, use getJobs2 directly and implement pagination in the UI.
52
+ */
45
53
  getJobsRecursive: (site, status, priority, type, lastKey, jobs = []) => {
46
- return new Promise((resolve) => {
54
+ return new Promise((resolve, reject) => {
47
55
  maintenanceActions
48
56
  .getJobs2(site, status, priority, type, lastKey)
49
57
  .then((jobRes) => {
@@ -51,17 +59,19 @@ export const maintenanceActions = {
51
59
  if (!jobRes.data.LastKey) {
52
60
  return resolve(newJobs);
53
61
  }
54
- return resolve(
55
- maintenanceActions.getJobsRecursive(
62
+ maintenanceActions
63
+ .getJobsRecursive(
56
64
  site,
57
65
  status,
58
66
  priority,
59
67
  type,
60
68
  jobRes.data.LastKey,
61
69
  newJobs,
62
- ),
63
- );
64
- });
70
+ )
71
+ .then(resolve)
72
+ .catch(reject);
73
+ })
74
+ .catch(reject);
65
75
  });
66
76
  },
67
77
  sendMaintenanceRequest: (
@@ -25,6 +25,9 @@ class MaintenanceList extends Component {
25
25
  types: [],
26
26
  filteredList: props.jobs,
27
27
  loading: false,
28
+ loadingMore: false,
29
+ hasMore: true,
30
+ lastKey: null,
28
31
  searchText: "",
29
32
  showFilterPopup: false,
30
33
  };
@@ -51,22 +54,25 @@ class MaintenanceList extends Component {
51
54
  this.onLoadingChanged(true, async () => {
52
55
  try {
53
56
  const { jobfilters } = this.props;
54
- const res = await maintenanceActions.getJobsRecursive(
57
+ const res = await maintenanceActions.getJobs2(
55
58
  this.props.site,
56
59
  jobfilters.status,
57
60
  jobfilters.priority,
58
61
  jobfilters.type,
62
+ null, // No lastKey = first page
63
+ jobfilters.assignee,
59
64
  );
60
- // console.log('refresh', res ? JSON.stringify(res[0], null, 2) : null);
61
- if (
62
- !_.isEmpty(jobfilters.status) ||
63
- !_.isEmpty(jobfilters.priority) ||
64
- !_.isEmpty(jobfilters.type)
65
- ) {
66
- this.props.jobsAdded(res);
67
- } else {
68
- this.props.jobsLoaded(res);
69
- }
65
+
66
+ const jobs = res.data.Items;
67
+ const lastKey = res.data.LastKey;
68
+
69
+ // Always replace jobs on refresh (filters are server-side)
70
+ this.props.jobsLoaded(jobs);
71
+
72
+ this.setState({
73
+ lastKey,
74
+ hasMore: !!lastKey,
75
+ });
70
76
  } catch (error) {
71
77
  console.log("refresh error", error);
72
78
  } finally {
@@ -75,6 +81,42 @@ class MaintenanceList extends Component {
75
81
  });
76
82
  };
77
83
 
84
+ loadMore = () => {
85
+ const { loading, loadingMore, hasMore, lastKey, searchText } = this.state;
86
+
87
+ // Don't load if already loading, no more pages, or during search
88
+ if (loading || loadingMore || !hasMore || !lastKey || searchText) return;
89
+
90
+ this.setState({ loadingMore: true }, async () => {
91
+ try {
92
+ const { jobfilters } = this.props;
93
+ const res = await maintenanceActions.getJobs2(
94
+ this.props.site,
95
+ jobfilters.status,
96
+ jobfilters.priority,
97
+ jobfilters.type,
98
+ lastKey,
99
+ jobfilters.assignee,
100
+ );
101
+
102
+ const newJobs = res.data.Items;
103
+ const newLastKey = res.data.LastKey;
104
+
105
+ // Append to existing jobs
106
+ this.props.jobsAdded(newJobs);
107
+
108
+ this.setState({
109
+ lastKey: newLastKey,
110
+ hasMore: !!newLastKey,
111
+ });
112
+ } catch (error) {
113
+ console.log("loadMore error", error);
114
+ } finally {
115
+ this.setState({ loadingMore: false });
116
+ }
117
+ });
118
+ };
119
+
78
120
  refreshTypes = async () => {
79
121
  const { data } = await maintenanceActions.getJobTypes(
80
122
  Helper.getSite(this.props.site),
@@ -116,12 +158,13 @@ class MaintenanceList extends Component {
116
158
  }
117
159
 
118
160
  resetDataSource = (source = "") => {
119
- const { jobfilters } = this.props;
120
161
  const { searchText } = this.state;
121
162
  const { jobs } = this.props;
122
163
 
123
164
  let filteredList = jobs;
124
165
  let jobIdMatch = null;
166
+
167
+ // Client-side search filtering (search is not supported server-side)
125
168
  if (searchText) {
126
169
  jobIdMatch = _.find(jobs, (j) => j.jobId === searchText);
127
170
  filteredList = jobs.filter((j) => {
@@ -135,22 +178,10 @@ class MaintenanceList extends Component {
135
178
  });
136
179
  if (!jobIdMatch) this.fetchJob(searchText);
137
180
  }
138
- if (jobfilters.status)
139
- filteredList = filteredList.filter((j) =>
140
- jobfilters.status.includes(j.status),
141
- );
142
- if (jobfilters.priority)
143
- filteredList = filteredList.filter((j) =>
144
- jobfilters.priority.includes(j.priority),
145
- );
146
- if (jobfilters.type)
147
- filteredList = filteredList.filter((j) =>
148
- jobfilters.type.includes(j.type),
149
- );
150
- if (jobfilters.assignee)
151
- filteredList = filteredList.filter((j) =>
152
- jobfilters.assignee.includes(j.AssigneeId),
153
- );
181
+
182
+ // Note: status, priority, type, and assignee filters are applied server-side
183
+ // via getJobs2, so no client-side filtering needed for those
184
+
154
185
  if (jobIdMatch) {
155
186
  const jobIndex = filteredList.indexOf(jobIdMatch);
156
187
  if (jobIndex > -1) {
@@ -158,7 +189,8 @@ class MaintenanceList extends Component {
158
189
  }
159
190
  filteredList.unshift(jobIdMatch);
160
191
  }
161
- if (source !== "search") this.refresh();
192
+ // Only refresh on initial load, not on filter changes (pagination handles data)
193
+ if (source !== "search" && source !== "filter") this.refresh();
162
194
 
163
195
  this.setState({ filteredList });
164
196
  };
@@ -188,6 +220,10 @@ class MaintenanceList extends Component {
188
220
  onSelectFilter = (selected) => {
189
221
  this.props.jobsFilterLoaded(selected);
190
222
  this.onToggleFilter();
223
+ // Reset pagination and clear existing list before refresh
224
+ this.setState({ lastKey: null, hasMore: true, filteredList: [] }, () => {
225
+ this.refresh();
226
+ });
191
227
  };
192
228
 
193
229
  getFilterButtonText = () => {
@@ -286,10 +322,23 @@ class MaintenanceList extends Component {
286
322
  )}
287
323
  ListEmptyComponent={this.renderEmptyList()}
288
324
  ListHeaderComponent={this.renderListHeader()}
325
+ ListFooterComponent={this.renderListFooter()}
326
+ onEndReached={this.loadMore}
327
+ onEndReachedThreshold={0.5}
289
328
  />
290
329
  );
291
330
  }
292
331
 
332
+ renderListFooter = () => {
333
+ if (!this.state.loadingMore) return null;
334
+
335
+ return (
336
+ <View style={styles.loadingMore}>
337
+ <Components.LoadingIndicator visible={true} />
338
+ </View>
339
+ );
340
+ };
341
+
293
342
  renderFilterPopup() {
294
343
  const { jobfilters } = this.props;
295
344
  const { showFilterPopup, types } = this.state;
@@ -363,6 +412,10 @@ const styles = StyleSheet.create({
363
412
  fontFamily: "sf-semibold",
364
413
  fontSize: 16,
365
414
  },
415
+ loadingMore: {
416
+ paddingVertical: 20,
417
+ alignItems: "center",
418
+ },
366
419
  });
367
420
 
368
421
  const mapStateToProps = (state) => {
@@ -80,13 +80,19 @@ class RequestDetail extends Component {
80
80
  this.getExternalSync();
81
81
  } catch (error) {
82
82
  console.log("getJob error", error.toString());
83
- // check for 403 or 404 error
84
- if (error.response.status === 403 || error.response.status === 404) {
83
+ // Log full error details for debugging
84
+ console.log("getJob error details:", {
85
+ message: error.message,
86
+ code: error.code,
87
+ responseStatus: error.response?.status,
88
+ responseData: error.response?.data,
89
+ });
90
+ // check for 403 or 404 error (use optional chaining to prevent crash)
91
+ if (error.response?.status === 403 || error.response?.status === 404) {
85
92
  this.setState({
86
93
  forbidden: true,
87
94
  });
88
95
  }
89
- console.log("getJob error", error);
90
96
  } finally {
91
97
  this.setState({ loading: false });
92
98
  }
@@ -572,9 +572,13 @@ class MaintenanceRequest extends Component {
572
572
  return field;
573
573
  });
574
574
 
575
+ const userID = this.state.canCreateOnBehalf && this.state.selectedUser
576
+ ? (this.state.selectedUser.userId || this.state.selectedUser.Id)
577
+ : this.props.uid;
578
+
575
579
  maintenanceActions
576
580
  .sendMaintenanceRequest(
577
- this.props.uid,
581
+ userID,
578
582
  this.state.userName,
579
583
  this.state.phone,
580
584
  this.state.roomNumber,