placementt-core 1.20.211 → 11.10.151

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 (130) hide show
  1. package/.eslintrc.js +40 -40
  2. package/.gitattributes +2 -2
  3. package/lib/config.d.ts +0 -1
  4. package/lib/constants.d.ts +6 -2
  5. package/lib/constants.js +136 -136
  6. package/lib/constants.js.map +1 -1
  7. package/lib/features/analytics/useAnalytics.d.ts +0 -1
  8. package/lib/features/analytics/useAnalytics.js +3 -4
  9. package/lib/features/analytics/useAnalytics.js.map +1 -1
  10. package/lib/features/config.d.ts +133 -133
  11. package/lib/features/config.js +35 -35
  12. package/lib/features/contacts/contacts.d.ts +75 -75
  13. package/lib/features/contacts/contacts.js +105 -105
  14. package/lib/features/contacts/contactsSlice.d.ts +5 -5
  15. package/lib/features/contacts/useContacts.js +1 -2
  16. package/lib/features/contacts/useContacts.js.map +1 -1
  17. package/lib/features/downtime/useDowntime.d.ts +11 -11
  18. package/lib/features/downtime/useDowntime.js +22 -22
  19. package/lib/features/dropdown/useDropdown.d.ts +2 -3
  20. package/lib/features/dropdown/useDropdown.js +1 -2
  21. package/lib/features/dropdown/useDropdown.js.map +1 -1
  22. package/lib/features/global/downtime/useDowntime.d.ts +0 -1
  23. package/lib/features/global/downtime/useDowntime.js +1 -2
  24. package/lib/features/global/downtime/useDowntime.js.map +1 -1
  25. package/lib/features/global/users/useUserFunctions.d.ts +0 -1
  26. package/lib/features/global/users/useUserFunctions.js +7 -8
  27. package/lib/features/global/users/useUserFunctions.js.map +1 -1
  28. package/lib/features/placements/studentPlacements/activePlacement.d.ts +1 -1
  29. package/lib/features/placements/studentPlacements/completedStudentPlacementsSlice.d.ts +2 -2
  30. package/lib/features/placements/studentPlacements/studentPlacementsSlice.d.ts +63 -63
  31. package/lib/features/placements/studentPlacements/studentPlacementsSlice.js +81 -81
  32. package/lib/features/placements/studentPlacements/upcomingStudentPlacementsSlice.d.ts +2 -2
  33. package/lib/features/placements/studentPlacements/useStudentPlacements.d.ts +0 -1
  34. package/lib/features/placements/studentPlacements/useStudentPlacements.js +1 -2
  35. package/lib/features/placements/studentPlacements/useStudentPlacements.js.map +1 -1
  36. package/lib/features/providerPlacements/providerPlacementsSlice.d.ts +19 -19
  37. package/lib/features/providerPlacements/providerPlacementsSlice.js +24 -24
  38. package/lib/features/referrals/useReferrals.d.ts +0 -1
  39. package/lib/features/referrals/useReferrals.js +1 -2
  40. package/lib/features/referrals/useReferrals.js.map +1 -1
  41. package/lib/features/studentPlacements/studentPlacementsSlice.d.ts +62 -62
  42. package/lib/features/studentPlacements/studentPlacementsSlice.js +87 -87
  43. package/lib/features/studentPlacements/useStudentPlacements.d.ts +6 -6
  44. package/lib/features/studentPlacements/useStudentPlacements.js +18 -18
  45. package/lib/features/updates/useUpdates.js +1 -2
  46. package/lib/features/updates/useUpdates.js.map +1 -1
  47. package/lib/features/userSlice.d.ts +26 -26
  48. package/lib/features/userSlice.js +23 -23
  49. package/lib/features/users/useUserFunctions.d.ts +25 -25
  50. package/lib/features/users/useUserFunctions.js +124 -124
  51. package/lib/features/users/userSlice.d.ts +46 -46
  52. package/lib/features/users/userSlice.js +48 -48
  53. package/lib/firebase/firebase.d.ts +3 -1
  54. package/lib/firebase/firebase.js +9 -3
  55. package/lib/firebase/firebase.js.map +1 -1
  56. package/lib/firebase/firebaseConfig.js +3 -0
  57. package/lib/firebase/firebaseConfig.js.map +1 -1
  58. package/lib/firebase/firebaseQuery.d.ts +3 -1
  59. package/lib/firebase/firebaseQuery.js +11 -1
  60. package/lib/firebase/firebaseQuery.js.map +1 -1
  61. package/lib/firebase/persistence.js +2 -2
  62. package/lib/firebase/persistence.js.map +1 -1
  63. package/lib/firebase/readDatabase.d.ts +8 -7
  64. package/lib/firebase/readDatabase.js +41 -8
  65. package/lib/firebase/readDatabase.js.map +1 -1
  66. package/lib/firebase/util.d.ts +3 -4
  67. package/lib/firebase/util.js +49 -4
  68. package/lib/firebase/util.js.map +1 -1
  69. package/lib/firebase/writeDatabase.d.ts +7 -3
  70. package/lib/firebase/writeDatabase.js +9 -2
  71. package/lib/firebase/writeDatabase.js.map +1 -1
  72. package/lib/hooks.d.ts +476 -20
  73. package/lib/hooks.js +1855 -237
  74. package/lib/hooks.js.map +1 -1
  75. package/lib/images/GatsbyBenchmarks.d.ts +0 -1
  76. package/lib/images/GatsbyBenchmarks.js +1 -1
  77. package/lib/images/GatsbyBenchmarks.js.map +1 -1
  78. package/lib/reduxHooks.d.ts +9 -2
  79. package/lib/reduxHooks.js +36 -9
  80. package/lib/reduxHooks.js.map +1 -1
  81. package/lib/tasksAndTips.d.ts +25 -5
  82. package/lib/tasksAndTips.js +517 -48
  83. package/lib/tasksAndTips.js.map +1 -1
  84. package/lib/typeDefinitions.d.ts +472 -55
  85. package/lib/util.d.ts +1 -0
  86. package/lib/util.js +85 -7
  87. package/lib/util.js.map +1 -1
  88. package/package.json +52 -49
  89. package/src/DatabaseDefinitions.ts +18 -18
  90. package/src/apiCalls.ts +128 -128
  91. package/src/config.ts +50 -50
  92. package/src/constants.ts +714 -707
  93. package/src/databaseTypes.ts +42 -42
  94. package/src/features/analytics/useAnalytics.tsx +64 -64
  95. package/src/features/contacts/contactsSlice.ts +147 -147
  96. package/src/features/contacts/useContacts.tsx +73 -73
  97. package/src/features/dropdown/useDropdown.tsx +52 -52
  98. package/src/features/global/downtime/useDowntime.tsx +23 -23
  99. package/src/features/global/users/useUserFunctions.tsx +132 -132
  100. package/src/features/jobs/jobsSlice.ts +65 -65
  101. package/src/features/placements/studentPlacements/activePlacement.ts +68 -68
  102. package/src/features/placements/studentPlacements/completedStudentPlacementsSlice.ts +97 -97
  103. package/src/features/placements/studentPlacements/upcomingStudentPlacementsSlice.ts +108 -108
  104. package/src/features/placements/studentPlacements/useStudentPlacements.tsx +9 -9
  105. package/src/features/placements/types.ts +10 -10
  106. package/src/features/referrals/useReferrals.tsx +56 -56
  107. package/src/features/updates/useUpdates.tsx +38 -38
  108. package/src/firebase/firebase.tsx +144 -138
  109. package/src/firebase/firebaseConfig.tsx +45 -42
  110. package/src/firebase/firebaseQuery.tsx +150 -140
  111. package/src/firebase/persistence.ts +84 -84
  112. package/src/firebase/readDatabase.tsx +235 -197
  113. package/src/firebase/util.tsx +352 -308
  114. package/src/firebase/writeDatabase.tsx +77 -68
  115. package/src/hooks.tsx +4029 -1928
  116. package/src/images/GatsbyBenchmarks.tsx +711 -711
  117. package/src/images/LogFuturePlacement.jsx +64 -64
  118. package/src/images/LogPreviousPlacement.jsx +228 -228
  119. package/src/images/gatsby_benchmarks.svg +466 -466
  120. package/src/images/log_future_placement.svg +114 -114
  121. package/src/images/log_previous_placement.svg +199 -199
  122. package/src/index.ts +34 -34
  123. package/src/readDatabase.tsx +3 -3
  124. package/src/reduxHooks.ts +231 -200
  125. package/src/tasksAndTips.ts +917 -410
  126. package/src/tutorialTips.ts +58 -58
  127. package/src/typeDefinitions.ts +893 -503
  128. package/src/util.ts +137 -47
  129. package/tsconfig.dev.json +5 -5
  130. package/tsconfig.json +21 -21
@@ -3,22 +3,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.dismissTip = exports.getTipsOrTasks = void 0;
6
+ exports.dismissTip = exports.getTasks = exports.getTips = void 0;
7
7
  const firestore_1 = require("firebase/firestore");
8
8
  const firebaseQuery_1 = __importDefault(require("./firebase/firebaseQuery"));
9
+ const util_1 = require("./firebase/util");
10
+ const util_2 = require("./firebase/util");
9
11
  const firebaseQuery = new firebaseQuery_1.default;
10
- const tips = {
12
+ const providerTips = {};
13
+ const studentTips = {};
14
+ const instituteTips = {
11
15
  createCohort: {
12
- callback: async (user, _, cohorts) => {
13
- if (!Array.isArray(cohorts))
16
+ callback: async (user) => {
17
+ if (!(0, util_1.getAccess)(user, "createCohorts"))
14
18
  return;
15
- const returnObj = {
16
- link: "",
17
- dismissible: true,
18
- };
19
- if (!cohorts.length) {
19
+ const cohorts = await firebaseQuery.getCount("cohorts", [(0, firestore_1.where)("product", "==", user.product), (0, firestore_1.where)("oId", "==", user.oId)]);
20
+ if (cohorts === 0) {
20
21
  return {
21
- ...returnObj,
22
22
  title: "Create a cohort",
23
23
  message: "Create a cohort to manage your students, process their placements and track their progress",
24
24
  link: "/institutes/cohorts/new",
@@ -51,32 +51,6 @@ const tips = {
51
51
  return undefined;
52
52
  },
53
53
  },
54
- uploadStudents: {
55
- callback: async (user, _, cohorts) => {
56
- if (!Array.isArray(cohorts))
57
- return;
58
- if (user.product !== "institutes")
59
- return;
60
- const returnObj = {
61
- link: "",
62
- dismissible: true,
63
- };
64
- const items = await Promise.all(cohorts.map(async ([id, cohort]) => {
65
- const studentCount = (await firebaseQuery.getCount(["users"], [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("userType", "==", "Students"), (0, firestore_1.where)("cohort", "==", id)]));
66
- if (studentCount === 0) {
67
- return {
68
- ...returnObj,
69
- title: "Upload students",
70
- message: `Your cohort '${cohort.name}' has no students. Add them in the cohort 'Students' tab`,
71
- link: `/institutes/cohorts/${id}/students`,
72
- buttonTitle: "Upload students",
73
- };
74
- }
75
- return;
76
- }));
77
- return items.filter((v) => v);
78
- },
79
- },
80
54
  uploadPlacements: {
81
55
  callback: async (user) => {
82
56
  const returnObj = {
@@ -154,9 +128,11 @@ const tips = {
154
128
  },
155
129
  };
156
130
  // Accept a cohort to any task
157
- const tasks = {
131
+ const instituteTasks = {
158
132
  requiredStage: {
159
133
  callback: async (user, _, cohorts) => {
134
+ if (!(0, util_1.getAccess)(user, "signOffPlacements"))
135
+ return;
160
136
  if (!Array.isArray(cohorts)) {
161
137
  const placementCount = (await firebaseQuery.getCount(["placements"], [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("cohort", "==", cohorts.id), (0, firestore_1.where)("reqUserType", "==", user.userType)]));
162
138
  if (placementCount > 0) {
@@ -189,6 +165,8 @@ const tasks = {
189
165
  },
190
166
  verifyInsurance: {
191
167
  callback: async (user, _, cohorts) => {
168
+ if (!(0, util_1.getAccess)(user, "verifyInsurance"))
169
+ return;
192
170
  if (!Array.isArray(cohorts)) {
193
171
  const placementCount = (await firebaseQuery.getCount(["placements"], [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("cohort", "==", cohorts.id), (0, firestore_1.where)("insurance", "==", "awaitingReview")]));
194
172
  if (placementCount > 0) {
@@ -197,7 +175,7 @@ const tasks = {
197
175
  severity: "primary",
198
176
  title: `${placementCount} placements have insurance that require review.`,
199
177
  message: `Your cohort '${cohorts.name}' has employer's liability insurance documents that require review`,
200
- link: `/institutes/cohorts/${cohorts.id}/placements`,
178
+ link: `/institutes/cohorts/${cohorts.id}/placements?id=upcoming&insurance=awaitingReview`,
201
179
  };
202
180
  }
203
181
  return;
@@ -210,7 +188,75 @@ const tasks = {
210
188
  severity: "primary",
211
189
  title: `${placementCount} placements in '${cohort.name}' have insurance that require review.`,
212
190
  message: `Your cohort '${cohort.name}' has employer's liability insurance documents that require review`,
213
- link: `/institutes/cohorts/${cohort.id}/placements`,
191
+ link: `/institutes/cohorts/${cohort.id}/placements?id=upcoming&insurance=awaitingReview`,
192
+ buttonTitle: "Review placements",
193
+ };
194
+ }
195
+ return;
196
+ }));
197
+ return items.filter((v) => v);
198
+ },
199
+ },
200
+ verifyDbsCheck: {
201
+ callback: async (user, _, cohorts) => {
202
+ if (!(0, util_1.getAccess)(user, "verifyDbsChecks"))
203
+ return;
204
+ if (!Array.isArray(cohorts)) {
205
+ const placementCount = (await firebaseQuery.getCount(["placements"], [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("cohort", "==", cohorts.id), (0, firestore_1.where)("dbsCheck", "==", "awaitingReview")]));
206
+ if (placementCount > 0) {
207
+ return {
208
+ dismissible: false,
209
+ severity: "primary",
210
+ title: `${placementCount} placements have DBS checks that require review.`,
211
+ message: `Your cohort '${cohorts.name}' has DBS checks that require review`,
212
+ link: `/institutes/cohorts/${cohorts.id}/placements?id=upcoming&dbsCheck=awaitingReview`,
213
+ };
214
+ }
215
+ return;
216
+ }
217
+ const items = await Promise.all(cohorts.map(async ([id, cohort]) => {
218
+ const placementCount = (await firebaseQuery.getCount(["placements"], [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("cohort", "==", id), (0, firestore_1.where)("dbsCheck", "==", "awaitingReview")]));
219
+ if (placementCount > 0) {
220
+ return {
221
+ dismissible: false,
222
+ severity: "primary",
223
+ title: `${placementCount} placements in '${cohort.name}' have DBS checks that require review.`,
224
+ message: `Your cohort '${cohort.name}' has DBS checks that require review`,
225
+ link: `/institutes/cohorts/${cohort.id}/placements?id=upcoming&dbsCheck=awaitingReview`,
226
+ buttonTitle: "Review placements",
227
+ };
228
+ }
229
+ return;
230
+ }));
231
+ return items.filter((v) => v);
232
+ },
233
+ },
234
+ verifyRiskAssessment: {
235
+ callback: async (user, _, cohorts) => {
236
+ if (!(0, util_1.getAccess)(user, "verifyRiskAssessments"))
237
+ return;
238
+ if (!Array.isArray(cohorts)) {
239
+ const placementCount = (await firebaseQuery.getCount(["placements"], [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("cohort", "==", cohorts.id), (0, firestore_1.where)("riskAssessment", "==", "awaitingReview")]));
240
+ if (placementCount > 0) {
241
+ return {
242
+ dismissible: false,
243
+ severity: "primary",
244
+ title: `${placementCount} placements have risk assessments that require review.`,
245
+ message: `Your cohort '${cohorts.name}' has risk assessents that require review`,
246
+ link: `/institutes/cohorts/${cohorts.id}/placements?id=upcoming&riskAssessment=awaitingReview`,
247
+ };
248
+ }
249
+ return;
250
+ }
251
+ const items = await Promise.all(cohorts.map(async ([id, cohort]) => {
252
+ const placementCount = (await firebaseQuery.getCount(["placements"], [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("cohort", "==", id), (0, firestore_1.where)("riskAssessment", "==", "awaitingReview")]));
253
+ if (placementCount > 0) {
254
+ return {
255
+ dismissible: false,
256
+ severity: "primary",
257
+ title: `${placementCount} placements in '${cohort.name}' have risk assessments that require review.`,
258
+ message: `Your cohort '${cohort.name}' has risk assessments that require review`,
259
+ link: `/institutes/cohorts/${cohort.id}/placements?id=upcoming&riskAssessment=awaitingReview`,
214
260
  buttonTitle: "Review placements",
215
261
  };
216
262
  }
@@ -222,7 +268,12 @@ const tasks = {
222
268
  missingParentEmail: {
223
269
  callback: async (user, _, cohorts) => {
224
270
  var _a, _b, _c;
271
+ if (!(0, util_1.getAccess)(user, "editStudents"))
272
+ return;
225
273
  if (!Array.isArray(cohorts)) {
274
+ const requiresParents = Boolean(cohorts.workflow.find((node) => node.userType === "Parent"));
275
+ if (!requiresParents)
276
+ return;
226
277
  const constraints = [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("cohort", "==", cohorts.id), (0, firestore_1.where)("details.parentEmail", "==", "null")];
227
278
  if (((_a = user.groupData) === null || _a === void 0 ? void 0 : _a.viewStudents) === "filter") {
228
279
  constraints.push((0, firestore_1.where)(`details.${((_b = user.groupData) === null || _b === void 0 ? void 0 : _b.filterUsersBy) || ""}`, "==", ((_c = user.groupData) === null || _c === void 0 ? void 0 : _c.filterUsersValue) || ""));
@@ -234,13 +285,16 @@ const tasks = {
234
285
  severity: "info",
235
286
  title: `${studentCount} students do not have a parent email.`,
236
287
  message: `Your cohort '${cohorts.name}' has students without a parent email. To allow proper processing of their placements, add these emails.`,
237
- link: `/institutes/cohorts/${cohorts.id}/students`,
288
+ link: `/institutes/cohorts/${cohorts.id}/students?parentEmail=false`,
238
289
  };
239
290
  }
240
291
  return;
241
292
  }
242
293
  const items = await Promise.all(cohorts.map(async ([id, cohort]) => {
243
294
  var _a, _b, _c;
295
+ const requiresParents = Boolean(cohort.workflow.find((node) => node.userType === "Parent"));
296
+ if (!requiresParents)
297
+ return;
244
298
  const constraints = [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("cohort", "==", id), (0, firestore_1.where)("details.parentEmail", "==", "null")];
245
299
  if (((_a = user.groupData) === null || _a === void 0 ? void 0 : _a.viewStudents) === "filter") {
246
300
  constraints.push((0, firestore_1.where)(`details.${((_b = user.groupData) === null || _b === void 0 ? void 0 : _b.filterUsersBy) || ""}`, "==", ((_c = user.groupData) === null || _c === void 0 ? void 0 : _c.filterUsersValue) || ""));
@@ -252,7 +306,7 @@ const tasks = {
252
306
  severity: "info",
253
307
  title: `${studentCount} students in '${cohort.name}' do not have a parent email.`,
254
308
  message: `Your cohort '${cohort.name}' has students without a parent email. To allow proper processing of their placements, add these emails.`,
255
- link: `/institutes/cohorts/${cohort.id}/students`,
309
+ link: `/institutes/cohorts/${cohort.id}/students?parentEmail=false`,
256
310
  buttonTitle: "View students",
257
311
  };
258
312
  }
@@ -264,6 +318,8 @@ const tasks = {
264
318
  inactiveStudents: {
265
319
  callback: async (user, _, cohorts) => {
266
320
  var _a, _b, _c;
321
+ if (!(0, util_1.getAccess)(user, "activateStudents"))
322
+ return;
267
323
  if (!Array.isArray(cohorts)) {
268
324
  const constraints = [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("cohort", "==", cohorts.id), (0, firestore_1.where)("status", "==", "inactive")];
269
325
  if (((_a = user.groupData) === null || _a === void 0 ? void 0 : _a.viewStudents) === "filter") {
@@ -276,7 +332,7 @@ const tasks = {
276
332
  severity: "info",
277
333
  title: `${studentCount} students in are inactive.`,
278
334
  message: `Your cohort '${cohorts.name}' has inactive students. Activate them to enable them to use the platform.`,
279
- link: `/institutes/cohorts/${cohorts.id}/students`,
335
+ link: `/institutes/cohorts/${cohorts.id}/students?status=inactive`,
280
336
  };
281
337
  }
282
338
  return;
@@ -294,7 +350,7 @@ const tasks = {
294
350
  severity: "info",
295
351
  title: `${studentCount} students in '${cohort.name}' are inactive.`,
296
352
  message: `Your cohort '${cohort.name}' has inactive students. Activate them to enable them to use the platform.`,
297
- link: `/institutes/cohorts/${cohort.id}/students`,
353
+ link: `/institutes/cohorts/${cohort.id}/students?status=inactive`,
298
354
  buttonTitle: "Review placements",
299
355
  };
300
356
  }
@@ -303,12 +359,43 @@ const tasks = {
303
359
  return items.filter((v) => v);
304
360
  },
305
361
  },
362
+ uploadStudents: {
363
+ callback: async (user, _, cohorts) => {
364
+ if (!Array.isArray(cohorts))
365
+ return;
366
+ if (!(0, util_1.getAccess)(user, "addStudents"))
367
+ return;
368
+ if (user.product !== "institutes")
369
+ return;
370
+ const returnObj = {
371
+ link: "",
372
+ dismissible: true,
373
+ severity: "warning",
374
+ };
375
+ const items = await Promise.all(cohorts.map(async ([id, cohort]) => {
376
+ const studentCount = (await firebaseQuery.getCount(["users"], [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("userType", "==", "Students"), (0, firestore_1.where)("cohort", "==", id)]));
377
+ if (studentCount === 0) {
378
+ return {
379
+ ...returnObj,
380
+ title: "Upload students",
381
+ message: `Your cohort '${cohort.name}' has no students. Add them in the cohort 'Students' tab`,
382
+ link: `/institutes/cohorts/${id}/students`,
383
+ buttonTitle: "Upload students",
384
+ };
385
+ }
386
+ return;
387
+ }));
388
+ return items.filter((v) => v);
389
+ },
390
+ },
306
391
  inactiveStaff: {
307
392
  callback: async (user, _, cohorts) => {
393
+ if (!(0, util_1.getAccess)(user, "addStaff"))
394
+ return;
308
395
  if (!Array.isArray(cohorts) || user.product === "students")
309
396
  return;
310
397
  const returnObj = {
311
- link: `/${user.product}/cohorts/staff/all`,
398
+ link: `/${user.product}/cohorts/staff/all?status=inactive`,
312
399
  dismissible: false,
313
400
  severity: "info",
314
401
  };
@@ -331,6 +418,8 @@ const tasks = {
331
418
  },
332
419
  approveExternalPlacement: {
333
420
  callback: async (user, _, cohort) => {
421
+ if (!(0, util_1.getAccess)(user, "verifyListings"))
422
+ return;
334
423
  if (!Array.isArray(cohort))
335
424
  return;
336
425
  const externalCount = await firebaseQuery.getCount(["placementListings"], [(0, firestore_1.where)(`savedBy.${user.oId}.exists`, "==", true), (0, firestore_1.where)(`savedBy.${user.oId}.status`, "==", "uploaded"), (0, firestore_1.where)("mapConsent", "==", "institute")]);
@@ -349,10 +438,314 @@ const tasks = {
349
438
  },
350
439
  },
351
440
  };
352
- const getTipsOrTasks = async (type, user, organisation, cohort) => {
353
- const includedItems = Object.entries(type === "tasks" ? tasks : tips).filter(([k]) => { var _a; return !((_a = user.dismissedTips) === null || _a === void 0 ? void 0 : _a.includes(k)); });
441
+ const studentTasks = {
442
+ completeOnboarding: {
443
+ callback: async (user) => {
444
+ const placementsWithoutOnboarding = await firebaseQuery.getDocsWhere("placements", [(0, firestore_1.where)("uid", "==", user.id), (0, firestore_1.where)("onboarding.deadline", "<=", (0, util_2.convertDate)(new Date(), "dbstring")), (0, firestore_1.where)("onboarding.completed.submitted", "==", false)]);
445
+ console.log("placementsWithoutONboarding", placementsWithoutOnboarding);
446
+ if (Object.keys(placementsWithoutOnboarding).length === 0)
447
+ return;
448
+ const items = Object.entries(placementsWithoutOnboarding).map(([k, placement]) => ({
449
+ dismissible: false,
450
+ severity: "primary",
451
+ title: `Complete required onboarding documents for ${placement.name}`,
452
+ message: `${placement.name} has requested you to complete some onboarding documents.`,
453
+ link: `/${user.product}/placements/${k}`,
454
+ buttonTitle: "View onboarding",
455
+ }));
456
+ return items;
457
+ },
458
+ }
459
+ };
460
+ const providerTasks = {
461
+ requestedVisibleAddresses: {
462
+ callback: async (user) => {
463
+ if (!(0, util_1.getAccess)(user, "addStaff"))
464
+ return;
465
+ const accessRequests = await firebaseQuery.getCount("users", [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("product", "==", "providers"), (0, firestore_1.orderBy)("requestedVisibleAddresses")]) - ((Array.isArray(user === null || user === void 0 ? void 0 : user.requestedVisibleAddresses) && (user === null || user === void 0 ? void 0 : user.requestedVisibleAddresses.length) > 0) ? 1 : 0);
466
+ if (accessRequests === 0)
467
+ return;
468
+ if (accessRequests === 1) {
469
+ const userRequestingAccess = Object.entries(await firebaseQuery.getDocsWhere("users", [(0, firestore_1.where)("product", "==", "providers"), (0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.orderBy)("requestedVisibleAddresses")]) || {})[0];
470
+ return {
471
+ dismissible: false,
472
+ severity: "primary",
473
+ title: `${userRequestingAccess[1].details.forename} ${userRequestingAccess[1].details.surname} has requested access to view addresses.`,
474
+ message: `Click to review the addresses and grant access to the user.`,
475
+ link: `/${user.product}/users/${userRequestingAccess[0]}`,
476
+ buttonTitle: "View request",
477
+ };
478
+ }
479
+ return {
480
+ dismissible: false,
481
+ severity: "warning",
482
+ title: `Multiple users have requested access to view addresses.`,
483
+ message: `Click to review the addresses and grant access to the user.`,
484
+ link: `/${user.product}/organisation/staff/all`,
485
+ buttonTitle: "View request",
486
+ };
487
+ },
488
+ },
489
+ requestedVisiblePlacementListings: {
490
+ callback: async (user) => {
491
+ if (!(0, util_1.getAccess)(user, "addStaff"))
492
+ return;
493
+ const accessRequests = await firebaseQuery.getCount("users", [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("product", "==", "providers"), (0, firestore_1.orderBy)("requestedVisibleListings")]) - ((Array.isArray(user === null || user === void 0 ? void 0 : user.requestedVisibleListings) && (user === null || user === void 0 ? void 0 : user.requestedVisibleListings.length) > 0) ? 1 : 0);
494
+ ;
495
+ if (accessRequests === 0)
496
+ return;
497
+ if (accessRequests === 1) {
498
+ const userRequestingAccess = Object.entries(await firebaseQuery.getDocsWhere("users", [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("product", "==", "providers"), (0, firestore_1.orderBy)("requestedVisibleListings")]) || {})[0];
499
+ return {
500
+ dismissible: false,
501
+ severity: "primary",
502
+ title: `${userRequestingAccess[1].details.forename} ${userRequestingAccess[1].details.surname} has requested access to view placement listings.`,
503
+ message: `Click to review the placement listings and grant access to the user.`,
504
+ link: `/${user.product}/users/${userRequestingAccess[0]}`,
505
+ buttonTitle: "View request",
506
+ };
507
+ }
508
+ return {
509
+ dismissible: false,
510
+ severity: "warning",
511
+ title: `Multiple users have requested access to view placement listings.`,
512
+ message: `Click to review the placement listings and grant access to the user.`,
513
+ link: `/${user.product}/organisation/staff/all`,
514
+ buttonTitle: "View request",
515
+ };
516
+ },
517
+ },
518
+ applicationRequireReview: {
519
+ callback: async (user) => {
520
+ const applicationCount = await firebaseQuery.getCount("applications", [(0, firestore_1.where)("providerId", "==", user.oId), (0, firestore_1.where)("reqUserType", "==", "Staff"), (0, firestore_1.where)("status", "==", "submitted")]);
521
+ if (applicationCount === 0)
522
+ return;
523
+ return {
524
+ dismissible: false,
525
+ severity: "primary",
526
+ title: `${applicationCount} applications require your review.`,
527
+ message: `Click to view ${applicationCount} that require your attention.`,
528
+ link: `/${user.product}/placementListings/applicants`,
529
+ buttonTitle: "View applications",
530
+ };
531
+ },
532
+ },
533
+ completeStudentDocs: {
534
+ callback: async (user) => {
535
+ return;
536
+ return {};
537
+ },
538
+ },
539
+ reviewOnboarding: {
540
+ callback: async (user) => {
541
+ const toReview = await firebaseQuery.getCount("placements", [(0, firestore_1.where)("providerId", "==", user.oId), (0, firestore_1.where)("onboarding.completed.accepted", "==", false), (0, firestore_1.where)("onboarding.completed.submitted", "==", true), (0, firestore_1.where)("endDate", ">=", (0, util_1.dateToString)(new Date()))]);
542
+ if (toReview === 0)
543
+ return;
544
+ if (toReview === 1) {
545
+ const placement = Object.entries(await firebaseQuery.getDocsWhere("placements", [(0, firestore_1.where)("providerId", "==", user.oId), (0, firestore_1.where)("onboarding.completed.accepted", "==", false), (0, firestore_1.where)("onboarding.completed.submitted", "==", true), (0, firestore_1.where)("endDate", ">=", (0, util_1.dateToString)(new Date()))]) || {})[0];
546
+ const student = await firebaseQuery.getDocData(["users", placement[1].uid]);
547
+ return {
548
+ dismissible: false,
549
+ severity: "primary",
550
+ title: `${student.details.forename} ${student.details.surname} has completed their onboarding for their placement from ${(0, util_2.convertDate)(placement[1].startDate, "visual")} to ${(0, util_2.convertDate)(placement[1].endDate, "visual")}`,
551
+ message: `Click to view the placement and review the onboarding.`,
552
+ link: `/${user.product}/placements/${placement[0]}`,
553
+ buttonTitle: "View",
554
+ };
555
+ }
556
+ return {
557
+ dismissible: false,
558
+ severity: "primary",
559
+ title: `${toReview} student have completed their onboarding.`,
560
+ message: `Click to view your placements and approve completed onboarding`,
561
+ link: `/${user.product}/placementListings/placements`,
562
+ buttonTitle: "View placements",
563
+ };
564
+ },
565
+ },
566
+ uploadOnboarding: {
567
+ callback: async (user) => {
568
+ const withoutOnboarding = await firebaseQuery.getCount("placements", [(0, firestore_1.where)("providerId", "==", user.oId), (0, firestore_1.where)("onboarding", "==", null), (0, firestore_1.where)("endDate", ">=", (0, util_1.dateToString)(new Date()))]);
569
+ if (withoutOnboarding === 0)
570
+ return;
571
+ if (withoutOnboarding === 1) {
572
+ const placement = Object.entries(await firebaseQuery.getDocsWhere("placements", [(0, firestore_1.where)("providerId", "==", user.oId), (0, firestore_1.where)("onboarding", "==", null), (0, firestore_1.where)("endDate", ">=", (0, util_1.dateToString)(new Date()))]) || {})[0];
573
+ const student = await firebaseQuery.getDocData(["users", placement[1].uid]);
574
+ return {
575
+ dismissible: false,
576
+ severity: "primary",
577
+ title: `Send onboarding documents to ${student.details.forename} ${student.details.surname}'s placement from ${(0, util_2.convertDate)(placement[1].startDate, "visual")} to ${(0, util_2.convertDate)(placement[1].endDate, "visual")}`,
578
+ message: `Click to view the placement and add or dismiss onboarding reminders.`,
579
+ link: `/${user.product}/placements/${placement[0]}`,
580
+ buttonTitle: "View",
581
+ };
582
+ }
583
+ return {
584
+ dismissible: false,
585
+ severity: "primary",
586
+ title: `Set up onboarding for ${withoutOnboarding} placements to prepare yourself and your students.`,
587
+ message: `Click to view your placements and add or dismiss onboarding reminders.`,
588
+ link: `/${user.product}/placementListings/placements`,
589
+ buttonTitle: "View placements",
590
+ };
591
+ },
592
+ },
593
+ completeListing: {
594
+ callback: async (user) => {
595
+ const incompleteListings = await firebaseQuery.getCount("placementListings", [(0, firestore_1.where)("providerId", "==", user.oId), (0, firestore_1.where)("status", "==", "draft")]);
596
+ if (incompleteListings === 0)
597
+ return;
598
+ if (incompleteListings === 1) {
599
+ const incompleteListing = Object.entries(await firebaseQuery.getDocsWhere("placementListings", [(0, firestore_1.where)("providerId", "==", user.oId), (0, firestore_1.where)("status", "==", "draft")]) || {})[0];
600
+ const address = incompleteListing[1].addressId ? await firebaseQuery.getDocData(["addresses", incompleteListing[1].addressId]) : undefined;
601
+ return {
602
+ dismissible: false,
603
+ severity: "info",
604
+ title: `Your listing '${incompleteListing[1].title || "unnamed"}' at ${address ? `${address["address-line1"]}, ${address.postal_code.toUpperCase()}, ${(0, util_1.capitaliseWords)((0, util_1.camelCaseToNormal)(address.country))}` : "unknown address"} requires more information before publishing.`,
605
+ message: `Click to complete and publish the placement listing.`,
606
+ link: `/${user.product}/addListing/${incompleteListing[0]}`,
607
+ buttonTitle: "View listing",
608
+ };
609
+ }
610
+ return {
611
+ dismissible: false,
612
+ severity: "info",
613
+ title: `You have ${incompleteListings} draft listings waiting to be published.`,
614
+ message: `Click to review and publish the placement listings.`,
615
+ link: `/${user.product}/placementListings/listings`,
616
+ buttonTitle: "View listings",
617
+ };
618
+ },
619
+ },
620
+ completeAddress: {
621
+ callback: async (user) => {
622
+ const incompleteAddresses = await firebaseQuery.getCount("addresses", [(0, firestore_1.where)("product", "==", "providers"), (0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("stage", "!=", "complete")]);
623
+ if (incompleteAddresses === 0)
624
+ return;
625
+ if (incompleteAddresses === 1) {
626
+ const address = Object.entries(await firebaseQuery.getDocsWhere("addresses", [(0, firestore_1.where)("product", "==", "providers"), (0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("stage", "!=", "complete")]) || {})[0];
627
+ return {
628
+ dismissible: false,
629
+ severity: "info",
630
+ title: `Your address: ${address[1]["address-line1"]}, ${address[1].postal_code.toUpperCase()}, ${(0, util_1.capitaliseWords)((0, util_1.camelCaseToNormal)(address[1].country))} is currently incomplete.`,
631
+ message: `Click to complete the addresses.`,
632
+ link: `/${user.product}/addAddress/${address[0]}`,
633
+ buttonTitle: "View address",
634
+ };
635
+ }
636
+ return {
637
+ dismissible: false,
638
+ severity: "info",
639
+ title: `You have ${incompleteAddresses} draft addresses waiting to be published.`,
640
+ message: `Click to review the addresses.`,
641
+ link: `/${user.product}/organisation/addresses`,
642
+ buttonTitle: "View addresses",
643
+ };
644
+ },
645
+ },
646
+ registrationRequests: {
647
+ callback: async (user) => {
648
+ const regRequests = await firebaseQuery.getCount("requests", [(0, firestore_1.where)("product", "==", user.product), (0, firestore_1.where)("oId", "==", user.oId)]);
649
+ if (regRequests === 0)
650
+ return;
651
+ if (regRequests === 1) {
652
+ const request = Object.entries(await firebaseQuery.getDocsWhere("requests", [(0, firestore_1.where)("product", "==", user.product), (0, firestore_1.where)("oId", "==", user.oId)]) || {})[0];
653
+ return {
654
+ dismissible: false,
655
+ severity: "primary",
656
+ title: `${request[1].forename} ${request[1].surname} has requested to access your organisation.`,
657
+ message: `Click to review these request.`,
658
+ link: `/${user.product}/organisation/staff/requests`,
659
+ buttonTitle: "View requests",
660
+ };
661
+ }
662
+ return {
663
+ dismissible: false,
664
+ severity: "primary",
665
+ title: `${regRequests} people have requested to register with your organisation.`,
666
+ message: `Click to review these requests.`,
667
+ link: `/${user.product}/organisation/staff/requests`,
668
+ buttonTitle: "View requests",
669
+ };
670
+ },
671
+ },
672
+ activateStaff: {
673
+ callback: async (user) => {
674
+ const inactiveAccounts = await firebaseQuery.getCount("users", [(0, firestore_1.where)("product", "==", user.product), (0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("status", "==", "inactive")]);
675
+ if (inactiveAccounts === 0)
676
+ return;
677
+ if (inactiveAccounts === 1) {
678
+ const account = Object.entries(await firebaseQuery.getDocsWhere("users", [(0, firestore_1.where)("product", "==", user.product), (0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("status", "==", "inactive")]) || {})[0];
679
+ return {
680
+ dismissible: false,
681
+ severity: "info",
682
+ title: `Activate ${account[1].details.forename} ${account[1].details.surname}'s staff account.`,
683
+ message: "Activate this account to give the user access to Placementt.",
684
+ link: `/${user.product}/organisation/staff/all`,
685
+ buttonTitle: "View accounts",
686
+ };
687
+ }
688
+ return {
689
+ dismissible: false,
690
+ severity: "info",
691
+ title: `${inactiveAccounts} staff have inactive active accounts.`,
692
+ message: "Activate these accounts to give the user access to Placementt.",
693
+ link: `/${user.product}/organisation/staff/all`,
694
+ buttonTitle: "View accounts",
695
+ };
696
+ },
697
+ },
698
+ placementStarting: {
699
+ callback: async (user) => {
700
+ const sevenDaysInFuture = new Date();
701
+ sevenDaysInFuture.setDate(sevenDaysInFuture.getDate() + 7);
702
+ const placementsStartingSoon = await firebaseQuery.getCount("placements", [(0, firestore_1.where)("providerId", "==", user.oId), (0, firestore_1.where)("startDate", "<=", (0, util_2.convertDate)(sevenDaysInFuture, "dbstring")), (0, firestore_1.where)("startDate", ">", (0, util_1.dateToString)(new Date()))]);
703
+ if (placementsStartingSoon === 0)
704
+ return;
705
+ if (placementsStartingSoon === 1) {
706
+ const placement = Object.entries(await firebaseQuery.getDocsWhere("placements", [(0, firestore_1.where)("providerId", "==", user.oId), (0, firestore_1.where)("startDate", "<=", (0, util_2.convertDate)(sevenDaysInFuture, "dbstring")), (0, firestore_1.where)("startDate", ">", (0, util_1.dateToString)(new Date()))]) || {})[0];
707
+ const student = await firebaseQuery.getDocData(["users", placement[1].uid]);
708
+ return {
709
+ dismissible: false,
710
+ severity: "success",
711
+ title: `${student.details.forename} ${student.details.surname}'s placement from ${(0, util_2.convertDate)(placement[1].startDate, "visual")} to ${(0, util_2.convertDate)(placement[1].endDate, "visual")} is starting in less than a week.`,
712
+ message: `Click to view the placement and acquaint yourself with the student.`,
713
+ link: `/${user.product}/placements/${placement[0]}`,
714
+ buttonTitle: "View",
715
+ };
716
+ }
717
+ return {
718
+ dismissible: false,
719
+ severity: "success",
720
+ title: `${placementsStartingSoon} placements starting soon.`,
721
+ message: `Click to view scheduled placements.`,
722
+ link: `/${user.product}/placementListings/placements`,
723
+ buttonTitle: "View placements",
724
+ };
725
+ },
726
+ },
727
+ completeFeedback: {
728
+ callback: async (user) => {
729
+ return;
730
+ return {};
731
+ },
732
+ },
733
+ setUpFeedback: {
734
+ callback: async (user) => {
735
+ return;
736
+ return {};
737
+ },
738
+ },
739
+ };
740
+ const getTips = async (user, organisation) => {
741
+ const tipsObject = {
742
+ providers: providerTips,
743
+ institutes: instituteTips,
744
+ studentTips: studentTips,
745
+ };
746
+ const includedItems = Object.entries(tipsObject[user.product]).filter(([k]) => { var _a; return !((_a = user.dismissedTips) === null || _a === void 0 ? void 0 : _a.includes(k)); });
354
747
  const processedTips = await includedItems.reduce(async (acc, [itemName, item]) => {
355
- const queryResult = await item.callback(user, organisation, cohort);
748
+ const queryResult = await item.callback(user, organisation);
356
749
  if (!queryResult)
357
750
  return await acc;
358
751
  const queryResultArray = Array.isArray(queryResult) ? queryResult : [queryResult];
@@ -362,7 +755,83 @@ const getTipsOrTasks = async (type, user, organisation, cohort) => {
362
755
  }, Promise.resolve([]));
363
756
  return processedTips;
364
757
  };
365
- exports.getTipsOrTasks = getTipsOrTasks;
758
+ exports.getTips = getTips;
759
+ const getTasks = async (user, organisation, cohort) => {
760
+ // Cohort is either a specific one or all.
761
+ if (user.product === "institutes" && user.userType === "Staff" && organisation) {
762
+ return await getInstituteTasks(user, organisation, cohort);
763
+ }
764
+ if (user.product === "students" || user.userType === "Students") {
765
+ return await getStudentTasks(user, organisation, cohort);
766
+ }
767
+ if (user.product === "providers" && organisation) {
768
+ return await getProviderTasks(user, organisation);
769
+ }
770
+ return [];
771
+ };
772
+ exports.getTasks = getTasks;
773
+ const getStudentTasks = async (user, organisation, cohort) => {
774
+ const processedTasks = await Object.entries(studentTasks).reduce(async (acc, [itemName, item]) => {
775
+ const queryResult = await item.callback(user);
776
+ if (!queryResult)
777
+ return await acc;
778
+ const queryResultArray = Array.isArray(queryResult) ? queryResult : [queryResult];
779
+ const results = queryResultArray.map((r) => ({ itemName: itemName, ...r }));
780
+ (await acc).push(...results);
781
+ return await acc;
782
+ }, Promise.resolve([]));
783
+ return processedTasks;
784
+ };
785
+ const getProviderTasks = async (user, organisation, cohort) => {
786
+ const processedTasks = await Object.entries(providerTasks).reduce(async (acc, [itemName, item]) => {
787
+ const queryResult = await item.callback(user);
788
+ if (!queryResult)
789
+ return await acc;
790
+ const queryResultArray = Array.isArray(queryResult) ? queryResult : [queryResult];
791
+ const results = queryResultArray.map((r) => ({ itemName: itemName, ...r }));
792
+ (await acc).push(...results);
793
+ return await acc;
794
+ }, Promise.resolve([]));
795
+ return processedTasks;
796
+ };
797
+ const getInstituteTasks = async (user, organisation, cohort) => {
798
+ var _a;
799
+ let fCohort = cohort;
800
+ if (!fCohort) {
801
+ // get all associated cohorts.
802
+ if (user.viewCohorts === "none")
803
+ return ([]);
804
+ if (user.userGroup === "admin" || user.viewCohorts === "all") {
805
+ const cohorts = await firebaseQuery.getDocsWhere("cohorts", [(0, firestore_1.where)("product", "==", user.product), (0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("stage", "==", "created")]);
806
+ fCohort = Object.entries(cohorts);
807
+ }
808
+ if (user.viewCohorts === "some") {
809
+ const cohorts = await ((_a = user.visibleCohorts) === null || _a === void 0 ? void 0 : _a.split(",").reduce(async (acc, cohortId) => {
810
+ const cohort = await firebaseQuery.getDocData(["cohorts", cohortId]);
811
+ if (cohort.stage !== "created") {
812
+ return acc;
813
+ }
814
+ acc[cohortId] = cohort;
815
+ return acc;
816
+ }, Promise.resolve([])));
817
+ fCohort = cohorts;
818
+ }
819
+ }
820
+ const processedTasks = await Object.entries(instituteTasks).reduce(async (acc, [itemName, item]) => {
821
+ if (!fCohort) {
822
+ console.log("No cohorts to retrieve tasks for");
823
+ return ([]);
824
+ }
825
+ const queryResult = await item.callback(user, organisation, fCohort);
826
+ if (!queryResult)
827
+ return await acc;
828
+ const queryResultArray = Array.isArray(queryResult) ? queryResult : [queryResult];
829
+ const results = queryResultArray.map((r) => ({ itemName: itemName, ...r }));
830
+ (await acc).push(...results);
831
+ return await acc;
832
+ }, Promise.resolve([]));
833
+ return processedTasks;
834
+ };
366
835
  /*
367
836
  export const getTasks = async (user: UserData):Promise<{[key:string]: TaskQueryReturnObject}> => {
368
837
  return Object.fromEntries((await Promise.all(Object.entries(tasks).filter(([k]) => !user.dismissedTasks?.includes(k)).map(async ([taskName, task]) => {