placementt-core 1.20.231 → 1.300.4
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/.eslintrc.js +40 -40
- package/.gitattributes +2 -2
- package/deploy-all.js +75 -0
- package/lib/config.d.ts +0 -13
- package/lib/config.js +1 -3
- package/lib/config.js.map +1 -1
- package/lib/constants.d.ts +1 -0
- package/lib/constants.js +48 -1
- package/lib/constants.js.map +1 -1
- package/lib/features/config.d.ts +133 -133
- package/lib/features/config.js +35 -35
- package/lib/features/contacts/contacts.d.ts +75 -75
- package/lib/features/contacts/contacts.js +105 -105
- package/lib/features/downtime/useDowntime.d.ts +11 -11
- package/lib/features/downtime/useDowntime.js +22 -22
- package/lib/features/placements/studentPlacements/activePlacement.js +1 -1
- package/lib/features/placements/studentPlacements/activePlacement.js.map +1 -1
- package/lib/features/placements/studentPlacements/studentPlacementsSlice.d.ts +63 -63
- package/lib/features/placements/studentPlacements/studentPlacementsSlice.js +81 -81
- package/lib/features/providerPlacements/providerPlacementsSlice.d.ts +19 -19
- package/lib/features/providerPlacements/providerPlacementsSlice.js +24 -24
- package/lib/features/studentPlacements/studentPlacementsSlice.d.ts +62 -62
- package/lib/features/studentPlacements/studentPlacementsSlice.js +87 -87
- package/lib/features/studentPlacements/useStudentPlacements.d.ts +6 -6
- package/lib/features/studentPlacements/useStudentPlacements.js +18 -18
- package/lib/features/userSlice.d.ts +26 -26
- package/lib/features/userSlice.js +23 -23
- package/lib/features/users/useUserFunctions.d.ts +25 -25
- package/lib/features/users/useUserFunctions.js +124 -124
- package/lib/features/users/userSlice.d.ts +46 -46
- package/lib/features/users/userSlice.js +48 -48
- package/lib/firebase/firebase.d.ts +1 -1
- package/lib/firebase/firebase.js +8 -3
- package/lib/firebase/firebase.js.map +1 -1
- package/lib/firebase/firebaseConfig.js +1 -0
- package/lib/firebase/firebaseConfig.js.map +1 -1
- package/lib/firebase/readDatabase.js +7 -7
- package/lib/firebase/readDatabase.js.map +1 -1
- package/lib/hooks.d.ts +85 -192
- package/lib/hooks.js +731 -671
- package/lib/hooks.js.map +1 -1
- package/lib/images/GatsbyBenchmarks.d.ts +1 -2
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -1
- package/lib/index.js.map +1 -1
- package/lib/reduxHooks.d.ts +9 -56
- package/lib/reduxHooks.js +1 -45
- package/lib/reduxHooks.js.map +1 -1
- package/lib/tasksAndTips.js +368 -418
- package/lib/tasksAndTips.js.map +1 -1
- package/lib/typeDefinitions.d.ts +162 -83
- package/lib/util.d.ts +25 -1
- package/lib/util.js +329 -2
- package/lib/util.js.map +1 -1
- package/package.json +56 -56
- package/src/DatabaseDefinitions.ts +18 -18
- package/src/apiCalls.ts +128 -128
- package/src/config.ts +50 -53
- package/src/constants.ts +846 -796
- package/src/databaseTypes.ts +42 -42
- package/src/features/analytics/useAnalytics.tsx +63 -63
- package/src/features/contacts/contactsSlice.ts +147 -147
- package/src/features/contacts/useContacts.tsx +73 -73
- package/src/features/dropdown/useDropdown.tsx +52 -52
- package/src/features/global/downtime/useDowntime.tsx +23 -23
- package/src/features/global/users/useUserFunctions.tsx +132 -132
- package/src/features/jobs/jobsSlice.ts +71 -71
- package/src/features/placements/studentPlacements/activePlacement.ts +68 -68
- package/src/features/placements/studentPlacements/completedStudentPlacementsSlice.ts +97 -97
- package/src/features/placements/studentPlacements/upcomingStudentPlacementsSlice.ts +108 -108
- package/src/features/placements/studentPlacements/useStudentPlacements.tsx +9 -9
- package/src/features/placements/types.ts +10 -10
- package/src/features/referrals/useReferrals.tsx +56 -56
- package/src/features/updates/useUpdates.tsx +38 -38
- package/src/firebase/firebase.tsx +158 -153
- package/src/firebase/firebaseConfig.tsx +47 -45
- package/src/firebase/firebaseQuery.tsx +151 -151
- package/src/firebase/persistence.ts +84 -84
- package/src/firebase/readDatabase.tsx +236 -236
- package/src/firebase/util.tsx +352 -352
- package/src/firebase/writeDatabase.tsx +77 -77
- package/src/hooks.tsx +4476 -4463
- package/src/images/GatsbyBenchmarks.tsx +711 -711
- package/src/images/LogFuturePlacement.jsx +64 -64
- package/src/images/LogPreviousPlacement.jsx +228 -228
- package/src/images/gatsby_benchmarks.svg +466 -466
- package/src/images/log_future_placement.svg +114 -114
- package/src/images/log_previous_placement.svg +199 -199
- package/src/index.ts +34 -35
- package/src/readDatabase.tsx +3 -3
- package/src/reduxHooks.ts +295 -342
- package/src/tasksAndTips.ts +1267 -1267
- package/src/tutorialTips.ts +58 -58
- package/src/typeDefinitions.ts +1260 -1129
- package/src/util.ts +523 -177
- package/tsconfig.dev.json +5 -5
- package/tsconfig.json +21 -21
- package/lib/features/logs/logsSlice.d.ts +0 -93
- package/lib/features/logs/logsSlice.js +0 -146
- package/lib/features/logs/logsSlice.js.map +0 -1
- package/src/features/logs/logsSlice.ts +0 -208
package/lib/hooks.js
CHANGED
|
@@ -10,18 +10,17 @@ exports.useNewInstitutePlacementList = useNewInstitutePlacementList;
|
|
|
10
10
|
exports.useAlumniPaginator = useAlumniPaginator;
|
|
11
11
|
exports.useVeryOldInstitutePlacementList = useVeryOldInstitutePlacementList;
|
|
12
12
|
exports.useFilterTablePaginator = useFilterTablePaginator;
|
|
13
|
-
exports.
|
|
13
|
+
exports.useProviderContactPaginator = useProviderContactPaginator;
|
|
14
|
+
exports.useNewCohortUserPaginator = useNewCohortUserPaginator;
|
|
14
15
|
exports.useCohortUserPaginator = useCohortUserPaginator;
|
|
15
16
|
exports.useAdmissionsPaginator = useAdmissionsPaginator;
|
|
16
17
|
exports.useLazyLoadQueryList = useLazyLoadQueryList;
|
|
17
|
-
exports.usePublicPlacementListingLoader = usePublicPlacementListingLoader;
|
|
18
|
-
exports.useCreateApplicationRenderer = useCreateApplicationRenderer;
|
|
19
18
|
exports.useProposePlacementRenderer = useProposePlacementRenderer;
|
|
20
19
|
exports.useCreateCohortRenderer = useCreateCohortRenderer;
|
|
21
20
|
exports.useUserUploadHandler = useUserUploadHandler;
|
|
22
21
|
exports.useWorkflowEditor = useWorkflowEditor;
|
|
23
22
|
exports.useApplicantWorkflowEditor = useApplicantWorkflowEditor;
|
|
24
|
-
exports.
|
|
23
|
+
exports.useInstituteProviderContactsHandler = useInstituteProviderContactsHandler;
|
|
25
24
|
exports.useGetIndividualPlacementForPlacementPage = useGetIndividualPlacementForPlacementPage;
|
|
26
25
|
exports.useOnboardingPopup = useOnboardingPopup;
|
|
27
26
|
exports.useLoadAddresses = useLoadAddresses;
|
|
@@ -40,6 +39,7 @@ const util_1 = require("./firebase/util");
|
|
|
40
39
|
const writeDatabase_1 = require("./firebase/writeDatabase");
|
|
41
40
|
const algoliasearch_1 = __importDefault(require("algoliasearch"));
|
|
42
41
|
const storage_1 = require("firebase/storage");
|
|
42
|
+
const util_2 = require("./util");
|
|
43
43
|
const DEFAULTQUERYLIMIT = 5;
|
|
44
44
|
function useStudentPlacementList({ user, student, queryConstraint, ql = DEFAULTQUERYLIMIT }) {
|
|
45
45
|
const [loadMoreIcon, setLoadMoreIcon] = (0, react_1.useState)(true);
|
|
@@ -243,7 +243,7 @@ function useOldInstitutePlacementList({ id, user, cohort, queryConstraint, ql =
|
|
|
243
243
|
};
|
|
244
244
|
return ({ ...{ placements, loadMoreIcon, loadMorePlacements, setQuery, setInitialQueryLimit, reset, changeQueryConstraints } });
|
|
245
245
|
}
|
|
246
|
-
function useNewInstitutePlacementList({ id, user, filters, view, cohort, queryConstraints, ql = DEFAULTQUERYLIMIT, inProgress }) {
|
|
246
|
+
function useNewInstitutePlacementList({ id, user, uid, filters, initialSort, initialSearch, view, cohort, queryConstraints, ql = DEFAULTQUERYLIMIT, inProgress }) {
|
|
247
247
|
const [query, setQuery] = (0, react_1.useState)();
|
|
248
248
|
const sorts = {
|
|
249
249
|
["Student Forename - Asc"]: {
|
|
@@ -267,7 +267,7 @@ function useNewInstitutePlacementList({ id, user, filters, view, cohort, queryCo
|
|
|
267
267
|
direction: "asc",
|
|
268
268
|
},
|
|
269
269
|
["Student Email - Desc"]: {
|
|
270
|
-
value: "
|
|
270
|
+
value: "studentEmail",
|
|
271
271
|
direction: "desc",
|
|
272
272
|
},
|
|
273
273
|
["Provider email - Asc"]: {
|
|
@@ -284,27 +284,34 @@ function useNewInstitutePlacementList({ id, user, filters, view, cohort, queryCo
|
|
|
284
284
|
if (!(user.studentFilter && user.studentFilterValues))
|
|
285
285
|
return false;
|
|
286
286
|
const student = await (0, readDatabase_1.getUserById)(placement.uid).catch(() => false);
|
|
287
|
-
if (!student)
|
|
287
|
+
if (!student) {
|
|
288
|
+
console.log("No student");
|
|
288
289
|
return;
|
|
290
|
+
}
|
|
291
|
+
;
|
|
289
292
|
if (!user.studentFilterValues.includes(student.details[user.studentFilter])) {
|
|
293
|
+
console.log("filter not included. Filteres: ", user.studentFilterValues, "value", user.studentFilter, "-", student.details[user.studentFilter]);
|
|
290
294
|
return false;
|
|
291
295
|
}
|
|
292
296
|
}
|
|
293
297
|
return { ...placement, id: k };
|
|
294
298
|
};
|
|
295
|
-
const { tableData, pageUp, pageDown, setFilters, page, setView, loading, updateSearch, updateSort, sort } = useDataViewerPaginator({ view, filters, sorts, queryLimit: ql, data: query, additionalEntryProcessing: additionalProcessing, onSearch: async (s, sort, page, filters, limit) => await algoliaPlacementSearch(user, s, sort, page, filters, limit, cohort, inProgress) });
|
|
299
|
+
const { tableData, pageUp, pageDown, setFilters, page, setView, loading, updateSearch, updateSort, sort } = useDataViewerPaginator({ view, filters, sorts, queryLimit: ql, initialSort, initialSearch, data: query, additionalEntryProcessing: additionalProcessing, onSearch: async (s, sort, page, filters, limit) => await algoliaPlacementSearch(query || [], user, s, sort, page, filters, limit, cohort, inProgress) });
|
|
296
300
|
(0, react_1.useEffect)(() => {
|
|
297
301
|
var _a;
|
|
302
|
+
console.log("SET QUERY", user, queryConstraints, cohort);
|
|
298
303
|
// Sets the query of for the DataViewerPaginator
|
|
299
304
|
if (user.product !== "institutes" || user.userType !== "Staff") {
|
|
300
305
|
setQuery(undefined);
|
|
301
306
|
return;
|
|
302
307
|
}
|
|
303
|
-
if (((user.userGroup === "admin" || (cohort && user.viewCohorts === "some" && ((_a = user === null || user === void 0 ? void 0 : user.visibleCohorts) === null || _a === void 0 ? void 0 : _a.includes(cohort))) || (user.viewCohorts === "all" && user.viewStudents
|
|
308
|
+
if (((user.userGroup === "admin" || (cohort && user.viewCohorts === "some" && ((_a = user === null || user === void 0 ? void 0 : user.visibleCohorts) === null || _a === void 0 ? void 0 : _a.includes(cohort))) || (user.viewCohorts === "all" && user.viewStudents !== "none")))) {
|
|
304
309
|
const constraints = [["oId", "==", user.oId], ["draft", "==", false]];
|
|
305
310
|
cohort && constraints.push(["cohort", "==", cohort]);
|
|
311
|
+
uid && constraints.push(["uid", "==", uid]);
|
|
306
312
|
queryConstraints && constraints.unshift(...queryConstraints);
|
|
307
313
|
inProgress !== undefined && constraints.push(["inProgress", "==", inProgress]);
|
|
314
|
+
console.log("PLACEMENT CONSTRAINTS", constraints);
|
|
308
315
|
setQuery([{
|
|
309
316
|
path: ["placements"],
|
|
310
317
|
where: constraints
|
|
@@ -384,7 +391,7 @@ function useAlumniPaginator({ user, alumniConvoUser, filters, view, school, quer
|
|
|
384
391
|
}, [tableData]);
|
|
385
392
|
return { tableData, page, loading, setFilters, setView, pageUp, pageDown, sorts };
|
|
386
393
|
}
|
|
387
|
-
const algoliaPlacementSearch = async (user, query, sort, page, filters, limit, cohort, inProgress) => {
|
|
394
|
+
const algoliaPlacementSearch = async (data, user, query, sort, page, filters, limit, cohort, inProgress) => {
|
|
388
395
|
const algoliaClient = (0, algoliasearch_1.default)(process.env.NODE_ENV === "development" ? "A0ZB50I7VS" : "XMPXCMUUOJ", user.algoliaKey);
|
|
389
396
|
const placementsIndex = algoliaClient.initIndex(sort ? Object.values(sort[1]).join("_") : "placements");
|
|
390
397
|
// const usersIndex = algoliaClient.initIndex("users");
|
|
@@ -414,10 +421,34 @@ const algoliaPlacementSearch = async (user, query, sort, page, filters, limit, c
|
|
|
414
421
|
// }))
|
|
415
422
|
// }
|
|
416
423
|
// }
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
424
|
+
if (data.length === 0)
|
|
425
|
+
return {};
|
|
426
|
+
const constraints = data[0].where;
|
|
427
|
+
if (!(constraints === null || constraints === void 0 ? void 0 : constraints.length))
|
|
428
|
+
return {};
|
|
429
|
+
let placementSearchString = constraints.map(([k, e, v]) => {
|
|
430
|
+
if (e === "==")
|
|
431
|
+
return `${k}:${v}`; // Equality check
|
|
432
|
+
if (e === "!=")
|
|
433
|
+
return `${k}:-${v}`; // Not equal check
|
|
434
|
+
if (e === "<")
|
|
435
|
+
return `${k}:<${v}`; // Less than check
|
|
436
|
+
if (e === "<=")
|
|
437
|
+
return `${k}:<=${v}`; // Less than or equal check
|
|
438
|
+
if (e === ">")
|
|
439
|
+
return `${k}:>${v}`; // Greater than check
|
|
440
|
+
if (e === ">=")
|
|
441
|
+
return `${k}:>=${v}`; // Greater than or equal check
|
|
442
|
+
if (e === "array-contains")
|
|
443
|
+
return `${k}:${v}`; // Array contains check (string format)
|
|
444
|
+
if (e === "array-contains-any")
|
|
445
|
+
return `${k}:"${v.join('","')}"`; // Array contains any of the values (string format)
|
|
446
|
+
if (e === "in")
|
|
447
|
+
return `(${v.map((value) => `${k}:${value}`).join(' OR ')})`; // In check
|
|
448
|
+
if (e === "not-in")
|
|
449
|
+
return v.map((value) => `${k}:-${value}`).join(' AND '); // In check
|
|
450
|
+
return;
|
|
451
|
+
}).join(" AND ");
|
|
421
452
|
filters && Object.entries(filters).filter(([, filter]) => filter.value).map(([id, filter]) => {
|
|
422
453
|
placementSearchString = placementSearchString + ` AND ${id}:${filter.value}`;
|
|
423
454
|
});
|
|
@@ -784,181 +815,183 @@ function useFilterTablePaginator({ data }) {
|
|
|
784
815
|
}, [page]);
|
|
785
816
|
return ({ ...{ tableData, setPage, setFilters, page } });
|
|
786
817
|
}
|
|
787
|
-
function
|
|
788
|
-
const [
|
|
789
|
-
const [page, setPage] = (0, react_1.useState)([1, 0]);
|
|
790
|
-
const [filters, setFilters] = (0, react_1.useState)();
|
|
791
|
-
const [queryAnchor, setQueryAnchor] = (0, react_1.useState)({ startKey: "", endKey: "", startQueryPos: 0, endQueryPos: 0 });
|
|
792
|
-
const [prevEntryIds, setPrevEntryIds] = (0, react_1.useState)({});
|
|
818
|
+
function useProviderContactPaginator({ data, user, view, filters }) {
|
|
819
|
+
const [query, setQuery] = (0, react_1.useState)();
|
|
793
820
|
const firebaseQuery = new firebaseQuery_1.default();
|
|
794
|
-
const
|
|
795
|
-
|
|
796
|
-
if (
|
|
797
|
-
|
|
821
|
+
const getAdditionalData = async (k, v) => {
|
|
822
|
+
var _a, _b;
|
|
823
|
+
if ((_b = (_a = v.savedBy) === null || _a === void 0 ? void 0 : _a[user.oId].activities) === null || _b === void 0 ? void 0 : _b.includes("workExperience")) {
|
|
824
|
+
const placementsCount = await firebaseQuery.getCount("placementListings", [(0, firestore_1.where)(`savedBy.${user.oId}.exists`, "==", true), (0, firestore_1.where)("providerContactId", "==", k)]);
|
|
825
|
+
return { ...v, plcaements: placementsCount };
|
|
798
826
|
}
|
|
799
|
-
|
|
800
|
-
|
|
827
|
+
return v;
|
|
828
|
+
};
|
|
829
|
+
const { tableData, pageUp, pageDown, setFilters, page, setView, loading } = useDataViewerPaginator({ view, filters, queryLimit: 10, data: query, additionalEntryProcessing: getAdditionalData });
|
|
830
|
+
(0, react_1.useEffect)(() => {
|
|
831
|
+
const constraints = [
|
|
832
|
+
[`savedBy.${user.oId}.exists`, "==", true],
|
|
833
|
+
];
|
|
834
|
+
if (user.userType === "Students") {
|
|
835
|
+
constraints.push([`savedBy.${user.oId}.cohorts.${user.cohort}.listed`, "==", true]);
|
|
801
836
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
837
|
+
setQuery([{
|
|
838
|
+
path: ["providerContacts"],
|
|
839
|
+
where: constraints
|
|
840
|
+
}]);
|
|
841
|
+
}, [user]);
|
|
842
|
+
return ({ ...{ tableData, pageUp, pageDown, setFilters, page, setView, loading } });
|
|
843
|
+
}
|
|
844
|
+
const algoliaUsersSearch = async (data, user, query, sort, page, filters, limit, cohort) => {
|
|
845
|
+
const algoliaClient = (0, algoliasearch_1.default)(process.env.NODE_ENV === "development" ? "A0ZB50I7VS" : "XMPXCMUUOJ", user.algoliaKey);
|
|
846
|
+
const userIndex = algoliaClient.initIndex(sort ? `users_${Object.values(sort[1]).join("_")}` : "users");
|
|
847
|
+
const constraints = data[0].where;
|
|
848
|
+
if (!(constraints === null || constraints === void 0 ? void 0 : constraints.length))
|
|
849
|
+
return {};
|
|
850
|
+
let userSearchString = constraints.map(([k, e, v]) => {
|
|
851
|
+
if (e === "==")
|
|
852
|
+
return `${k}:${v}`; // Equality check
|
|
853
|
+
if (e === "!=")
|
|
854
|
+
return `${k}:-${v}`; // Not equal check
|
|
855
|
+
if (e === "<")
|
|
856
|
+
return `${k}:<${v}`; // Less than check
|
|
857
|
+
if (e === "<=")
|
|
858
|
+
return `${k}:<=${v}`; // Less than or equal check
|
|
859
|
+
if (e === ">")
|
|
860
|
+
return `${k}:>${v}`; // Greater than check
|
|
861
|
+
if (e === ">=")
|
|
862
|
+
return `${k}:>=${v}`; // Greater than or equal check
|
|
863
|
+
if (e === "array-contains")
|
|
864
|
+
return `${k}:${v}`; // Array contains check (string format)
|
|
865
|
+
if (e === "array-contains-any")
|
|
866
|
+
return `${k}:"${v.join('","')}"`; // Array contains any of the values (string format)
|
|
867
|
+
if (e === "in")
|
|
868
|
+
return `(${v.map((value) => `${k}:${value}`).join(' OR ')})`; // In check
|
|
869
|
+
if (e === "not-in")
|
|
870
|
+
return v.map((value) => `${k}:-${value}`).join(' AND '); // In check
|
|
871
|
+
return;
|
|
872
|
+
}).join(" AND ");
|
|
873
|
+
filters && Object.entries(filters).filter(([, filter]) => filter.value).map(([id, filter]) => {
|
|
874
|
+
userSearchString = userSearchString + ` AND ${id}:${filter.value}`;
|
|
875
|
+
});
|
|
876
|
+
console.log("QUERY", userSearchString);
|
|
877
|
+
const options = {
|
|
878
|
+
filters: userSearchString,
|
|
879
|
+
hitsPerPage: limit,
|
|
880
|
+
page: page ? page - 1 : undefined,
|
|
881
|
+
};
|
|
882
|
+
const searchUsersHits = await userIndex.search(query || "", options);
|
|
883
|
+
console.log(searchUsersHits.hits);
|
|
884
|
+
const i = (searchUsersHits ? (await Promise.all(searchUsersHits.hits.map(async (hit) => {
|
|
885
|
+
return [hit.objectID, hit];
|
|
886
|
+
}))) : []).filter((e) => e !== undefined);
|
|
887
|
+
return Object.fromEntries(i);
|
|
888
|
+
};
|
|
889
|
+
function useNewCohortUserPaginator({ user, institute, initialSort, filters, view, cohort, queryConstraints, ql = DEFAULTQUERYLIMIT, userType }) {
|
|
890
|
+
const [query, setQuery] = (0, react_1.useState)();
|
|
891
|
+
const firebaseQuery = new firebaseQuery_1.default();
|
|
892
|
+
const sorts = {
|
|
893
|
+
["Student Forename - Asc"]: {
|
|
894
|
+
value: "details.forename",
|
|
895
|
+
direction: "asc",
|
|
896
|
+
},
|
|
897
|
+
["Student Forename - Desc"]: {
|
|
898
|
+
value: "details.forename",
|
|
899
|
+
direction: "desc",
|
|
900
|
+
},
|
|
901
|
+
["Student Surname - Asc"]: {
|
|
902
|
+
value: "details.surname",
|
|
903
|
+
direction: "asc",
|
|
904
|
+
},
|
|
905
|
+
["Student Surname - Desc"]: {
|
|
906
|
+
value: "details.surname",
|
|
907
|
+
direction: "desc",
|
|
908
|
+
},
|
|
909
|
+
["Student Email - Asc"]: {
|
|
910
|
+
value: "email",
|
|
911
|
+
direction: "asc",
|
|
912
|
+
},
|
|
913
|
+
["Student Email - Desc"]: {
|
|
914
|
+
value: "email",
|
|
915
|
+
direction: "desc",
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
(0, react_1.useEffect)(() => {
|
|
919
|
+
const getAccess = async () => {
|
|
920
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
921
|
+
// Sets the query of for the DataViewerPaginator
|
|
922
|
+
if (user.product !== "institutes" || user.userType !== "Staff") {
|
|
923
|
+
setQuery(undefined);
|
|
924
|
+
return;
|
|
835
925
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
926
|
+
const constraints = [["oId", "==", user.oId], ["userType", "==", userType]];
|
|
927
|
+
cohort && constraints.push(["cohort", "==", cohort]);
|
|
928
|
+
queryConstraints && constraints.unshift(...queryConstraints);
|
|
929
|
+
const mSetQuery = (clear) => {
|
|
930
|
+
setQuery(clear ? undefined : [{
|
|
931
|
+
path: ["users"],
|
|
932
|
+
where: constraints
|
|
933
|
+
}]);
|
|
934
|
+
return;
|
|
935
|
+
};
|
|
936
|
+
if (institute.package === "institutes-one") {
|
|
937
|
+
if (user.userGroup === "admin" || (user.viewCohorts === "all" && user.viewStudents === "all"))
|
|
938
|
+
return mSetQuery();
|
|
939
|
+
if (!user.viewCohorts || user.viewCohorts === "none" || !user.viewStudents || user.viewStudents === "none" || (user.viewCohorts === "some" && !((_a = user.visibleCohorts) === null || _a === void 0 ? void 0 : _a.length)) || (user.viewStudents === "some" && !((_b = user.studentFilterValues) === null || _b === void 0 ? void 0 : _b.length)))
|
|
940
|
+
return mSetQuery(true);
|
|
941
|
+
if (user.viewStudents === "some") {
|
|
942
|
+
constraints.push([`details.${user.studentFilter}`, "in", user.studentFilterValues]);
|
|
839
943
|
}
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
944
|
+
if (cohort) {
|
|
945
|
+
const canViewCohort = user.viewCohorts === "all" || (user.viewCohorts === "some" && ((_c = user.visibleCohorts) === null || _c === void 0 ? void 0 : _c.includes("cohort")));
|
|
946
|
+
return mSetQuery(canViewCohort);
|
|
843
947
|
}
|
|
844
948
|
else {
|
|
845
|
-
|
|
949
|
+
// No cohort.
|
|
950
|
+
if (user.viewCohorts === "all")
|
|
951
|
+
return mSetQuery();
|
|
952
|
+
if (user.viewCohorts === "some" && user.visibleCohorts) {
|
|
953
|
+
constraints.push(["cohort", "in", user.visibleCohorts]);
|
|
954
|
+
return mSetQuery();
|
|
955
|
+
}
|
|
956
|
+
return mSetQuery(true);
|
|
846
957
|
}
|
|
847
958
|
}
|
|
848
|
-
|
|
849
|
-
if (
|
|
850
|
-
|
|
959
|
+
if (institute.package === "institutes-two") {
|
|
960
|
+
if (user.userGroup === "admin" || (user.viewSchools === "all" && user.viewCohorts === "all" && user.viewStudents === "all"))
|
|
961
|
+
return mSetQuery();
|
|
962
|
+
if (!user.viewCohorts || !user.viewSchools || user.viewSchools === "none" || user.viewCohorts === "none")
|
|
963
|
+
return mSetQuery(true);
|
|
964
|
+
if (!user.viewStudents || user.viewStudents === "none" || (user.viewStudents === "some" && !((_d = user.studentFilterValues) === null || _d === void 0 ? void 0 : _d.length)) || (user.viewCohorts === "some" && !((_e = user.visibleCohorts) === null || _e === void 0 ? void 0 : _e.length)) || (user.viewSchools === "some" && !((_f = user.visibleSchools) === null || _f === void 0 ? void 0 : _f.length)))
|
|
965
|
+
return mSetQuery(true);
|
|
966
|
+
if (user.viewStudents === "some") {
|
|
967
|
+
constraints.push([`details.${user.studentFilter}`, "in", user.studentFilterValues]);
|
|
968
|
+
}
|
|
969
|
+
if (cohort) {
|
|
970
|
+
if (user.viewCohorts === "some" && !((_g = user.visibleCohorts) === null || _g === void 0 ? void 0 : _g.includes(cohort)))
|
|
971
|
+
return mSetQuery(true);
|
|
972
|
+
if (user.viewSchools === "some") {
|
|
973
|
+
const cohortData = await firebaseQuery.getDocData(["cohorts", cohort]);
|
|
974
|
+
if (!cohortData.schoolId || !((_h = user.visibleSchools) === null || _h === void 0 ? void 0 : _h.includes(cohortData.schoolId)))
|
|
975
|
+
return mSetQuery(true);
|
|
976
|
+
}
|
|
851
977
|
}
|
|
852
978
|
else {
|
|
853
|
-
|
|
979
|
+
if (user.viewCohorts === "some" && user.visibleCohorts) {
|
|
980
|
+
constraints.push(["cohort", "in", user.visibleCohorts]);
|
|
981
|
+
}
|
|
982
|
+
else if (user.viewSchools === "some" && user.visibleSchools) {
|
|
983
|
+
const cohorts = await firebaseQuery.getDocsWhere("cohorts", [(0, firestore_1.where)("oId", "==", user.oId), (0, firestore_1.where)("schoolId", "in", user.visibleSchools)]);
|
|
984
|
+
constraints.push(["cohort", "in", Object.keys(cohorts || {})]);
|
|
985
|
+
}
|
|
854
986
|
}
|
|
987
|
+
return mSetQuery();
|
|
855
988
|
}
|
|
856
|
-
|
|
857
|
-
};
|
|
858
|
-
const constraints = createQuery(querySchema);
|
|
859
|
-
// console.log(queryId, "constraints", constraints)
|
|
860
|
-
const q = (0, firestore_1.query)((0, firestore_1.collection)(firebaseConfig_1.db, "savedPlacements"), ...(constraints));
|
|
861
|
-
const queryResults = {};
|
|
862
|
-
const queryData = await (0, firestore_1.getDocs)(q);
|
|
863
|
-
// console.log("queryData.size", queryData.size)
|
|
864
|
-
const reverseIfBack = (docs) => {
|
|
865
|
-
if (page[0] < page[1]) {
|
|
866
|
-
return docs.reverse();
|
|
867
|
-
}
|
|
868
|
-
return docs;
|
|
989
|
+
setQuery(undefined);
|
|
869
990
|
};
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
}
|
|
875
|
-
let position = Object.keys(itemList).length + (page[0] - 1) * 10 + index + 1;
|
|
876
|
-
if (page[0] < page[1]) {
|
|
877
|
-
position = (page[0]) * 10 - index - Object.keys(itemList).length;
|
|
878
|
-
}
|
|
879
|
-
// console.log(index, "doc.id", doc.id, position, "E", prevEntries[doc.id])
|
|
880
|
-
if (itemList[doc.id] || (prevEntries[doc.id] && prevEntries[doc.id] !== position)) {
|
|
881
|
-
console.log("Removing ", doc.id, ": E=", prevEntries[doc.id], ", G=", position);
|
|
882
|
-
return;
|
|
883
|
-
}
|
|
884
|
-
const item = doc.data();
|
|
885
|
-
item.id = doc.id;
|
|
886
|
-
queryResults[doc.id] = item;
|
|
887
|
-
index = index + 1;
|
|
888
|
-
if (prevEntries[doc.id])
|
|
889
|
-
return;
|
|
890
|
-
prevEntries[doc.id] = position;
|
|
891
|
-
});
|
|
892
|
-
if (cursorDirection === "decrease" || page[0] < page[1]) {
|
|
893
|
-
itemList = { ...Object.fromEntries(Object.entries(queryResults).reverse()), ...itemList };
|
|
894
|
-
}
|
|
895
|
-
else {
|
|
896
|
-
itemList = { ...itemList, ...queryResults };
|
|
897
|
-
}
|
|
898
|
-
setPrevEntryIds(prevEntries);
|
|
899
|
-
if (queryData.size < 10 && Object.keys(itemList).length < 10) {
|
|
900
|
-
if (page[0] > page[1] && cursorPos + 1 < data.length) {
|
|
901
|
-
console.log("Increase query index");
|
|
902
|
-
return getDataFromQuery(itemList, { ...currentQueryAnchor, endQueryPos: currentQueryAnchor.endQueryPos + 1 }, "increase", prevEntries);
|
|
903
|
-
}
|
|
904
|
-
else if (page[0] < page[1] && cursorPos > 0) {
|
|
905
|
-
console.log("Decrease query index");
|
|
906
|
-
return getDataFromQuery(itemList, { ...currentQueryAnchor, startQueryPos: currentQueryAnchor.startQueryPos - 1 }, "decrease", prevEntries);
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
if (Object.keys(itemList).length < 10 && queryData.size === 10) {
|
|
910
|
-
console.log("Shorter than ten");
|
|
911
|
-
// if(loadMoreFromQuery){return}
|
|
912
|
-
return getDataFromQuery(itemList, { ...currentQueryAnchor, startKey: Object.keys(itemList)[0], endKey: Object.keys(itemList).slice(-1)[0] }, undefined, prevEntries, true);
|
|
913
|
-
}
|
|
914
|
-
if (queryData.size === 0 &&
|
|
915
|
-
Object.keys(itemList).length === 0 &&
|
|
916
|
-
currentQueryAnchor.endQueryPos + 1 === data.length &&
|
|
917
|
-
page[0] > 1) {
|
|
918
|
-
setTableData({});
|
|
919
|
-
setQueryAnchor((a) => ({ ...a, startKey: "" }));
|
|
920
|
-
return;
|
|
921
|
-
}
|
|
922
|
-
setQueryAnchor({ ...currentQueryAnchor, startKey: Object.keys(itemList)[0], endKey: Object.keys(itemList).slice(-1)[0] });
|
|
923
|
-
const finalData = Object.fromEntries(await Promise.all(Object.entries(itemList).map(async ([k, v]) => {
|
|
924
|
-
const placement = await firebaseQuery.getDocData(["placementListings", v.placementId || ""]);
|
|
925
|
-
const address = await firebaseQuery.getDocData(["addresses", placement.addressId || ""]).catch(() => ({ ["address-line1"]: "Unknown address" }));
|
|
926
|
-
const provider = await firebaseQuery.getDocData(["providers", placement.providerId || ""]).catch(() => ({ name: "Unknown" }));
|
|
927
|
-
const status = provider.name !== "Unknown" ? getPlacementStatus(provider, placement, v) : "Deleted";
|
|
928
|
-
return [k, { ...address, ...provider, ...placement, email: placement.providerEmail, status: status, savedPlacement: v }];
|
|
929
|
-
})));
|
|
930
|
-
setTableData(finalData);
|
|
931
|
-
};
|
|
932
|
-
const getPlacementStatus = (provider, placement, savedPlacement) => {
|
|
933
|
-
if (savedPlacement.status === "Blocked")
|
|
934
|
-
return "blocked";
|
|
935
|
-
if (savedPlacement.status === "Accepted")
|
|
936
|
-
return "active";
|
|
937
|
-
if (user.product === "admin") {
|
|
938
|
-
if (placement.mapConsent === undefined)
|
|
939
|
-
return "notReviewed";
|
|
940
|
-
if (placement.mapConsent === false)
|
|
941
|
-
return "notPublic";
|
|
942
|
-
return "unknown";
|
|
943
|
-
}
|
|
944
|
-
;
|
|
945
|
-
if (!provider.insurance)
|
|
946
|
-
return "awaitingProviderApproval";
|
|
947
|
-
return "requiresApproval";
|
|
948
|
-
};
|
|
949
|
-
(0, react_1.useEffect)(() => {
|
|
950
|
-
if (!filters)
|
|
951
|
-
return;
|
|
952
|
-
setPage([1, 0]);
|
|
953
|
-
setTableData({});
|
|
954
|
-
setQueryAnchor({ startKey: "", endKey: "", startQueryPos: 0, endQueryPos: 0 });
|
|
955
|
-
setPrevEntryIds({});
|
|
956
|
-
}, [filters]);
|
|
957
|
-
// Fetch new data when queries or page change
|
|
958
|
-
(0, react_1.useEffect)(() => {
|
|
959
|
-
getDataFromQuery();
|
|
960
|
-
}, [page]);
|
|
961
|
-
return ({ ...{ tableData, setPage, setFilters, page } });
|
|
991
|
+
getAccess();
|
|
992
|
+
}, [user, queryConstraints, cohort]);
|
|
993
|
+
const { tableData, pageUp, pageDown, setFilters, page, setView, loading, updateSearch, updateSort, sort } = useDataViewerPaginator({ view, filters, initialSort, sorts, queryLimit: ql, data: query, onSearch: async (s, sort, page, filters, limit) => await algoliaUsersSearch(query || [], user, s, sort, page, filters, limit, cohort) });
|
|
994
|
+
return { tableData, page, loading, updateSearch, setFilters, setView, pageUp, pageDown, sorts, updateSort, sort };
|
|
962
995
|
}
|
|
963
996
|
function useCohortUserPaginator({ user, cohort, data, search, userType, sort }) {
|
|
964
997
|
const [tableData, setTableData] = (0, react_1.useState)({});
|
|
@@ -1281,394 +1314,433 @@ function useLazyLoadQueryList({ path, constraints, number, onItemFetched }) {
|
|
|
1281
1314
|
}, []);
|
|
1282
1315
|
return ({ ...{ items, loadMore, loadMoreIcon, reset } });
|
|
1283
1316
|
}
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1317
|
+
// type PublicPlacementListingLoaderParams = {
|
|
1318
|
+
// providerId?: string,
|
|
1319
|
+
// number: number,
|
|
1320
|
+
// }
|
|
1321
|
+
// export function usePublicPlacementListingLoader({providerId, number=5}:PublicPlacementListingLoaderParams) {
|
|
1322
|
+
// const [items, setItems] = useState<{[key:string]:{[key:string]:unknown}}>({});
|
|
1323
|
+
// const [loadMoreIcon, setLoadMoreIcon] = useState<boolean>(false);
|
|
1324
|
+
// const [lastItem, setLastItem] = useState<QueryDocumentSnapshot<DocumentData>>();
|
|
1325
|
+
// const firebaseQuery = new FirebaseQuery();
|
|
1326
|
+
// const reset = () => {
|
|
1327
|
+
// setItems({});
|
|
1328
|
+
// setLastItem(undefined);
|
|
1329
|
+
// };
|
|
1330
|
+
// const loadMore = async () => {
|
|
1331
|
+
// setLoadMoreIcon(true);
|
|
1332
|
+
// let formattedConstraints:QueryConstraint[] = [
|
|
1333
|
+
// where("status", "==", "listed"),
|
|
1334
|
+
// limit(number)
|
|
1335
|
+
// ];
|
|
1336
|
+
// if (providerId) {
|
|
1337
|
+
// formattedConstraints.push(where("providerId", "==", providerId));
|
|
1338
|
+
// }
|
|
1339
|
+
// if (lastItem) {
|
|
1340
|
+
// formattedConstraints.push(startAfter(lastItem));
|
|
1341
|
+
// }
|
|
1342
|
+
// const documents = await firebaseQuery.getDocsWhere("placementListings", formattedConstraints, true) as QuerySnapshot<DocumentData>;
|
|
1343
|
+
// console.log("docs", documents.docs);
|
|
1344
|
+
// setLastItem(documents.docs[documents.docs.length-1]);
|
|
1345
|
+
// const processedItems = Object.fromEntries(await Promise.all(Object.values(documents.docs).map(async (doc) => {
|
|
1346
|
+
// let itemObj = {...doc.data(), id: doc.id} as PlacementListing;
|
|
1347
|
+
// if (itemObj.addressId) {
|
|
1348
|
+
// const address = await firebaseQuery.getDocData(["addresses", itemObj.addressId]) as Address;
|
|
1349
|
+
// delete address.id;
|
|
1350
|
+
// itemObj = {...address, ...itemObj};
|
|
1351
|
+
// }
|
|
1352
|
+
// if (itemObj.applicantWorkflowId) {
|
|
1353
|
+
// const applicantWorkflow = (await firebaseQuery.getDocData(["applicantWorkflows", itemObj.applicantWorkflowId]) as ApplicantWorkflow).workflow.filter((i) => i.id === 1)[0];
|
|
1354
|
+
// const applicantFiles = applicantWorkflow.files ? Object.fromEntries(await Promise.all(applicantWorkflow.files?.map(async (fileId) => {
|
|
1355
|
+
// const file = await firebaseQuery.getDocData(["files", fileId]);
|
|
1356
|
+
// file.url = await getDownloadURL(ref(storage, `providers/${itemObj.providerId}/${file.fileName}`));
|
|
1357
|
+
// return [fileId, file];
|
|
1358
|
+
// }))) : [];
|
|
1359
|
+
// const applicantForms = applicantWorkflow.forms ? Object.fromEntries(await Promise.all(applicantWorkflow.forms?.map(async (formId) => {
|
|
1360
|
+
// return [formId, await firebaseQuery.getDocData(["forms", formId])];
|
|
1361
|
+
// }))) : [];
|
|
1362
|
+
// applicantWorkflow.viewableFiles = applicantFiles;
|
|
1363
|
+
// applicantWorkflow.formDetails = applicantForms;
|
|
1364
|
+
// itemObj = {...itemObj, applicantWorkflow: [applicantWorkflow]};
|
|
1365
|
+
// }
|
|
1366
|
+
// return [doc.id, itemObj];
|
|
1367
|
+
// })))
|
|
1368
|
+
// setItems((i) => ({...i, ...processedItems}));
|
|
1369
|
+
// setLoadMoreIcon(false);
|
|
1370
|
+
// };
|
|
1371
|
+
// useEffect(() => {
|
|
1372
|
+
// loadMore();
|
|
1373
|
+
// }, []);
|
|
1374
|
+
// return ({...{items, loadMore, loadMoreIcon, reset}});
|
|
1375
|
+
// }
|
|
1376
|
+
// export type ApplicationHookParams = {
|
|
1377
|
+
// successText: {
|
|
1378
|
+
// submitted: {
|
|
1379
|
+
// title: string;
|
|
1380
|
+
// desc: string;
|
|
1381
|
+
// };
|
|
1382
|
+
// draftSaved: {
|
|
1383
|
+
// title: string;
|
|
1384
|
+
// desc: string;
|
|
1385
|
+
// };
|
|
1386
|
+
// stageComplete: {
|
|
1387
|
+
// title: string;
|
|
1388
|
+
// desc: string;
|
|
1389
|
+
// };
|
|
1390
|
+
// outcome: {
|
|
1391
|
+
// title: string;
|
|
1392
|
+
// desc: string;
|
|
1393
|
+
// };
|
|
1394
|
+
// };
|
|
1395
|
+
// setSuccessPopup: import("react").Dispatch<import("react").SetStateAction<"submitted" | "draftSaved" | "stageComplete" | "outcome" | undefined>>;
|
|
1396
|
+
// openSuccessPopup: (type: "submitted" | "draftSaved" | "stageComplete" | "outcome") => void;
|
|
1397
|
+
// setFApplication: import("react").Dispatch<import("react").SetStateAction<Partial<Application>>>;
|
|
1398
|
+
// fApplication: Partial<Application>;
|
|
1399
|
+
// draftSaved: boolean;
|
|
1400
|
+
// profileUrl: string | undefined;
|
|
1401
|
+
// successPopup: "submitted" | "draftSaved" | "stageComplete" | "outcome" | undefined;
|
|
1402
|
+
// fApplicationId: string | undefined;
|
|
1403
|
+
// fListing: PlacementListing | false | undefined;
|
|
1404
|
+
// student: UserData | undefined;
|
|
1405
|
+
// fProvider: {
|
|
1406
|
+
// details?: ProviderData;
|
|
1407
|
+
// profile?: string;
|
|
1408
|
+
// id?: string;
|
|
1409
|
+
// } | undefined;
|
|
1410
|
+
// onFApply: (draft?: boolean) => Promise<void>;
|
|
1411
|
+
// setFormComplete: (formId: string, e: {
|
|
1412
|
+
// [key: string]: unknown;
|
|
1413
|
+
// }) => void;
|
|
1414
|
+
// viewFile: (file: string, onOpen: (url: string) => void) => void
|
|
1415
|
+
// addFile: (files: string[], fileId: number) => void;
|
|
1416
|
+
// uploadedFiles?: {
|
|
1417
|
+
// [key: string]: FileItem;
|
|
1418
|
+
// };
|
|
1419
|
+
// getCurrentStage: (stage: number) => Promise<{
|
|
1420
|
+
// stage: ApplicantStage;
|
|
1421
|
+
// completedSections: {
|
|
1422
|
+
// submitted?: string | undefined;
|
|
1423
|
+
// filesViewed?: string[] | undefined;
|
|
1424
|
+
// formsCompleted?: {
|
|
1425
|
+
// [key: string]: unknown;
|
|
1426
|
+
// } | undefined;
|
|
1427
|
+
// filesUploaded?: {
|
|
1428
|
+
// [key: number]: string[];
|
|
1429
|
+
// } | undefined;
|
|
1430
|
+
// };
|
|
1431
|
+
// }>;
|
|
1432
|
+
// currentStageComplete?: boolean;
|
|
1433
|
+
// progressStage: (type: number | "accept" | "reject", e?: {
|
|
1434
|
+
// feedback?: string;
|
|
1435
|
+
// }) => Promise<void>;
|
|
1436
|
+
// };
|
|
1437
|
+
// export function useCreateApplicationRenderer({user, listingId, listing, provider, application, applicationId, orgContext}:
|
|
1438
|
+
// {user:UserData, listingId:string, applicationId?: string, listing?: PlacementListing, application?: Partial<Application>,
|
|
1439
|
+
// orgContext?: {details: ProviderData, addresses: {[key: string]: OrganisationAddress}, applicantWorkflows: {[key: string]: ApplicantWorkflow}},
|
|
1440
|
+
// provider?: {details?: ProviderData, profile?: string, id?: string}}) {
|
|
1441
|
+
// const firebaseQuery = new FirebaseQuery();
|
|
1442
|
+
// let applicationWithoutAdditionalData = {...(application || {})} as any;
|
|
1443
|
+
// delete applicationWithoutAdditionalData.listing;
|
|
1444
|
+
// delete applicationWithoutAdditionalData.address;
|
|
1445
|
+
// delete applicationWithoutAdditionalData.provider;
|
|
1446
|
+
// const [fApplication, setFApplication] = useState<Partial<Application>>(application ? applicationWithoutAdditionalData : {
|
|
1447
|
+
// uid: user.userType === "Students" ? user.id : undefined,
|
|
1448
|
+
// listingId: listingId,
|
|
1449
|
+
// addressId: listing?.addressId,
|
|
1450
|
+
// stage: 1,
|
|
1451
|
+
// reqUserType: "Students",
|
|
1452
|
+
// status: "draft"});
|
|
1453
|
+
// const [fApplicationId, setFApplicationId] = useState<string|undefined>(applicationId);
|
|
1454
|
+
// const [draftSaved, setDraftSaved] = useState(false);
|
|
1455
|
+
// const [fProvider, setFProvider] = useState<{details?: ProviderData, profile?: string, id?: string}|undefined>(provider);
|
|
1456
|
+
// const [fListing, setFListing] = useState<PlacementListing|false|undefined>(Object.keys(listing || {}).length > 5 ? listing : undefined);
|
|
1457
|
+
// const [student, setStudent] = useState<UserData|undefined>(user.userType === "Students" ? user : undefined);
|
|
1458
|
+
// const [profileUrl, setProfileUrl] = useState<string>();
|
|
1459
|
+
// const [successPopup, setSuccessPopup] = useState<"submitted"|"draftSaved"|"stageComplete"|"outcome">();
|
|
1460
|
+
// const [uploadedFiles, setUploadedFiles] = useState<{[key: string]: FileItem}>();
|
|
1461
|
+
// const [currentStageComplete, setCurrentStageComplete] = useState<boolean>();
|
|
1462
|
+
// useEffect(() => {
|
|
1463
|
+
// const getListing = async () => {
|
|
1464
|
+
// console.log("Checking ID")
|
|
1465
|
+
// if (!listingId) return;
|
|
1466
|
+
// console.log("Getting listing")
|
|
1467
|
+
// console.log("LISTING PARAM", listing, Object.keys(listing || {}).length > 5);
|
|
1468
|
+
// const listingData = (Object.keys(listing || {}).length > 5) ? listing : (await firebaseQuery.getDocData(["placementListings", listingId]).catch(() => false) as PlacementListing|false);
|
|
1469
|
+
// console.log("LISTINGDATA", listingData, Object.keys(listing || {}).length > 5 ? {a: "string"} : "AAA");
|
|
1470
|
+
// const address = listingData ? (user.product === "providers" && orgContext) ? orgContext.addresses[listingData.addressId || ""] : await firebaseQuery.getDocData(["addresses", listingData.addressId as string]) as Address : undefined;
|
|
1471
|
+
// const workflow = listingData ? (user.product === "providers" && orgContext) ? orgContext.applicantWorkflows[listingData.applicantWorkflowId || ""] as ApplicantWorkflow : await firebaseQuery.getDocData(["applicantWorkflows", listingData.applicantWorkflowId as string]) as ApplicantWorkflow : undefined;
|
|
1472
|
+
// if (workflow && listingData) {
|
|
1473
|
+
// workflow.workflow = await Promise.all(workflow.workflow.map(async (s) => {
|
|
1474
|
+
// const applicantFiles = s.files ? Object.fromEntries(await Promise.all(s.files?.map(async (fileId: string) => {
|
|
1475
|
+
// const file = await firebaseQuery.getDocData(["files", fileId]);
|
|
1476
|
+
// file.url = await getDownloadURL(ref(storage, `providers/${listingData?.providerId}/${file.fileName}`));
|
|
1477
|
+
// return [fileId, file];
|
|
1478
|
+
// }))) : [];
|
|
1479
|
+
// const applicantForms = s.forms ? Object.fromEntries(await Promise.all(s.forms?.map(async (formId: string) => {
|
|
1480
|
+
// return [formId, await firebaseQuery.getDocData(["forms", formId])];
|
|
1481
|
+
// }))) : [];
|
|
1482
|
+
// return {...s, viewableFiles: applicantFiles, formDetails: applicantForms};
|
|
1483
|
+
// }));
|
|
1484
|
+
// delete workflow.id;
|
|
1485
|
+
// }
|
|
1486
|
+
// if (address) {
|
|
1487
|
+
// delete address.id;
|
|
1488
|
+
// }
|
|
1489
|
+
// console.log("Setting listing")
|
|
1490
|
+
// setFListing((listingData && workflow) ? {...listingData, ...address, applicantWorkflow: workflow.workflow} as PlacementListing : false);
|
|
1491
|
+
// if ((fProvider?.id === application?.providerId) && user.product === "providers") {
|
|
1492
|
+
// setFProvider({details: orgContext?.details, id: user.oId});
|
|
1493
|
+
// } else if (listingData && listingData?.providerId) {
|
|
1494
|
+
// console.log("Getting provider from DB");
|
|
1495
|
+
// const provider = await firebaseQuery.getDocData(["providers", listingData.providerId]) as ProviderData;
|
|
1496
|
+
// console.log("Provider", provider);
|
|
1497
|
+
// setFProvider({details: provider, id: listingData.providerId});
|
|
1498
|
+
// }
|
|
1499
|
+
// }
|
|
1500
|
+
// getListing();
|
|
1501
|
+
// }, [listingId, listing]);
|
|
1502
|
+
// useEffect(() => {
|
|
1503
|
+
// if (student?.id !== application?.uid) {
|
|
1504
|
+
// if (user.userType === "Students") {
|
|
1505
|
+
// setStudent(user);
|
|
1506
|
+
// } else if (user.product === "providers" && application?.uid) {
|
|
1507
|
+
// firebaseQuery.getDocData(["users", application.uid]).then((s) => setStudent(s as UserData));
|
|
1508
|
+
// }
|
|
1509
|
+
// }
|
|
1510
|
+
// }, []);
|
|
1511
|
+
// useEffect(() => {
|
|
1512
|
+
// setFListing(Object.keys(listing || {}).length > 5 ? listing : undefined);
|
|
1513
|
+
// }, [listing]);
|
|
1514
|
+
// useEffect(() => {
|
|
1515
|
+
// if (provider?.profile) return;
|
|
1516
|
+
// if (!provider?.id) return;
|
|
1517
|
+
// getDownloadURL(ref(storage, `providers/${provider?.id}/profilePic.png`)).then(setProfileUrl).catch(() => null);
|
|
1518
|
+
// }, [provider]);
|
|
1519
|
+
// useEffect(() => {
|
|
1520
|
+
// console.log("APPLICATIONID", applicationId);
|
|
1521
|
+
// if (!applicationId) {
|
|
1522
|
+
// if (!listingId) return;
|
|
1523
|
+
// firebaseQuery.getDocsWhere("applications", [where("status", "not-in", ["approved", "declined"]), where("uid", "==", user.id), where("listingId", "==", listingId)]).then((existingApplication) => {
|
|
1524
|
+
// console.log("EXISTING", existingApplication);
|
|
1525
|
+
// // get uploaded files
|
|
1526
|
+
// if (existingApplication && Object.keys(existingApplication).length) {
|
|
1527
|
+
// setFApplication(Object.values(existingApplication)[0]);
|
|
1528
|
+
// setFApplicationId(Object.keys(existingApplication)[0]);
|
|
1529
|
+
// }
|
|
1530
|
+
// });
|
|
1531
|
+
// return;
|
|
1532
|
+
// }
|
|
1533
|
+
// if (applicationId) {
|
|
1534
|
+
// setFApplicationId(applicationId);
|
|
1535
|
+
// if (application) {
|
|
1536
|
+
// let applicationWithoutAdditionalData = {...(application || {})} as any;
|
|
1537
|
+
// delete applicationWithoutAdditionalData.listing;
|
|
1538
|
+
// delete applicationWithoutAdditionalData.address;
|
|
1539
|
+
// delete applicationWithoutAdditionalData.provider;
|
|
1540
|
+
// setFApplication(applicationWithoutAdditionalData);
|
|
1541
|
+
// } else {
|
|
1542
|
+
// firebaseQuery.getDocData(["applications", applicationId]).then(setFApplication);
|
|
1543
|
+
// }
|
|
1544
|
+
// }
|
|
1545
|
+
// }, [application, applicationId]);
|
|
1546
|
+
// const getCurrentStage = async (stage: number): Promise<{
|
|
1547
|
+
// stage: ApplicantStage; completedSections: {
|
|
1548
|
+
// submitted?: string | undefined;
|
|
1549
|
+
// filesViewed?: string[] | undefined;
|
|
1550
|
+
// formsCompleted?: {
|
|
1551
|
+
// [key: string]: unknown;
|
|
1552
|
+
// } | undefined;
|
|
1553
|
+
// filesUploaded?: {
|
|
1554
|
+
// [key: number]: string[];
|
|
1555
|
+
// } | undefined;
|
|
1556
|
+
// };
|
|
1557
|
+
// }> => {
|
|
1558
|
+
// console.log("fLSITING CURRENT STAGE", fListing);
|
|
1559
|
+
// if (!fListing) throw new Error("Listing deleted");
|
|
1560
|
+
// if (!fListing?.applicantWorkflowId) throw new Error("No workflow stage");
|
|
1561
|
+
// const mApplicantWorkflow = (await firebaseQuery.getDocData(["applicantWorkflows", fListing.applicantWorkflowId]) as ApplicantWorkflow);
|
|
1562
|
+
// const stageObj = mApplicantWorkflow?.workflow?.find((s) => s.id === stage);
|
|
1563
|
+
// if (!stageObj) throw new Error("Can't find stage.");
|
|
1564
|
+
// const applicantFiles = stageObj.files ? Object.fromEntries(await Promise.all(stageObj.files?.map(async (fileId) => {
|
|
1565
|
+
// const file = await firebaseQuery.getDocData(["files", fileId]);
|
|
1566
|
+
// file.url = await getDownloadURL(ref(storage, `providers/${mApplicantWorkflow?.oId}/${file.fileName}`));
|
|
1567
|
+
// return [fileId, file];
|
|
1568
|
+
// }))) : [];
|
|
1569
|
+
// const applicantForms = stageObj.forms ? Object.fromEntries(await Promise.all(stageObj.forms?.map(async (formId) => {
|
|
1570
|
+
// return [formId, await firebaseQuery.getDocData(["forms", formId])];
|
|
1571
|
+
// }))) : [];
|
|
1572
|
+
// stageObj.viewableFiles = applicantFiles;
|
|
1573
|
+
// stageObj.formDetails = applicantForms;
|
|
1574
|
+
// return {stage: stageObj, completedSections: fApplication?.completedSections?.[stage] || {}};
|
|
1575
|
+
// };
|
|
1576
|
+
// useEffect(() => {
|
|
1577
|
+
// const getUploadedFiles = async () => {
|
|
1578
|
+
// if (!fApplication.completedSections) {
|
|
1579
|
+
// setUploadedFiles({});
|
|
1580
|
+
// return
|
|
1581
|
+
// };
|
|
1582
|
+
// const fileIds = Object.values(fApplication.completedSections)
|
|
1583
|
+
// .flatMap(stageData =>
|
|
1584
|
+
// Object.values(stageData.filesUploaded || {}).flatMap(fileIds => fileIds)
|
|
1585
|
+
// );
|
|
1586
|
+
// const fileDataPromises = fileIds.map(async (fileId) => {
|
|
1587
|
+
// const fileData = await firebaseQuery.getDocData(["files", fileId]) as FileItem;
|
|
1588
|
+
// fileData.url = await getDownloadURL(ref(storage, `userFiles/${fileData.fileName}`));
|
|
1589
|
+
// return [fileId, fileData] as [string, FileItem]
|
|
1590
|
+
// });
|
|
1591
|
+
// const fileDataArray = await Promise.all(fileDataPromises);
|
|
1592
|
+
// const fileDataObj = Object.fromEntries(fileDataArray)
|
|
1593
|
+
// setUploadedFiles(fileDataObj)
|
|
1594
|
+
// }
|
|
1595
|
+
// const addApplication = async () => {
|
|
1596
|
+
// console.log("ADDING APPLICATION");
|
|
1597
|
+
// if (!fListing || !fListing?.id || !fProvider?.id || !student?.id) return;
|
|
1598
|
+
// const applicationData = {
|
|
1599
|
+
// uid: student.id,
|
|
1600
|
+
// listingId: fListing?.id,
|
|
1601
|
+
// addressId: fListing.addressId,
|
|
1602
|
+
// applicantWorkflowId: fListing?.applicantWorkflowId,
|
|
1603
|
+
// providerId: fProvider.id,
|
|
1604
|
+
// stage: 1,
|
|
1605
|
+
// status: "draft",
|
|
1606
|
+
// created: (new Date()).toISOString(),
|
|
1607
|
+
// ...fApplication,
|
|
1608
|
+
// } as Partial<Application>;
|
|
1609
|
+
// const mApplicationId = (await firebaseQuery.add(["applications"], applicationData)).id;
|
|
1610
|
+
// console.log("APPLICATION ADDED");
|
|
1611
|
+
// setFApplicationId(mApplicationId);
|
|
1612
|
+
// setFApplication(applicationData);
|
|
1613
|
+
// setDraftSaved(true);
|
|
1614
|
+
// return;
|
|
1615
|
+
// };
|
|
1616
|
+
// getUploadedFiles();
|
|
1617
|
+
// console.log("Checking IDs");
|
|
1618
|
+
// if (!fListing || !fListing?.id || !fProvider?.id || !student?.id) return;
|
|
1619
|
+
// if (user.product === "providers") return;
|
|
1620
|
+
// console.log("Checking dates and sections");
|
|
1621
|
+
// if (!fApplication.completedSections && !fApplication.startDate && !fApplication.endDate) return;
|
|
1622
|
+
// console.log("Application updated");
|
|
1623
|
+
// if (!fApplicationId && !applicationId) {
|
|
1624
|
+
// // save new
|
|
1625
|
+
// console.log("Add application")
|
|
1626
|
+
// addApplication();
|
|
1627
|
+
// return;
|
|
1628
|
+
// }
|
|
1629
|
+
// // update
|
|
1630
|
+
// firebaseQuery.update(["applications", (fApplicationId || applicationId) as string], fApplication);
|
|
1631
|
+
// setDraftSaved(true);
|
|
1632
|
+
// }, [fApplication]);
|
|
1633
|
+
// const openSuccessPopup = (type: "submitted"|"draftSaved"|"stageComplete"|"outcome") => {
|
|
1634
|
+
// setSuccessPopup(type);
|
|
1635
|
+
// setTimeout(() => {
|
|
1636
|
+
// // onClose();
|
|
1637
|
+
// }, 1500);
|
|
1638
|
+
// };
|
|
1639
|
+
// useEffect(() => {
|
|
1640
|
+
// const areStagesCompleted = async ():Promise<boolean|undefined> => {
|
|
1641
|
+
// if (!fListing) return;
|
|
1642
|
+
// if (fApplication.stage === undefined) return undefined;
|
|
1643
|
+
// const currentStage = await getCurrentStage(fApplication.stage);
|
|
1644
|
+
// console.log("Checking current stage is complete");
|
|
1645
|
+
// for (const fileViewed of currentStage.stage?.files || []) {
|
|
1646
|
+
// console.log("Checking file viewed", fileViewed, "in", currentStage?.completedSections?.filesViewed);
|
|
1647
|
+
// if (!currentStage?.completedSections?.filesViewed?.includes(fileViewed)) {
|
|
1648
|
+
// console.log("File not viewed");
|
|
1649
|
+
// return false;
|
|
1650
|
+
// } else {
|
|
1651
|
+
// console.log("File viewed");
|
|
1652
|
+
// }
|
|
1653
|
+
// }
|
|
1654
|
+
// for (const formCompleted of currentStage?.stage?.forms || []) {
|
|
1655
|
+
// console.log("Checking form completed", formCompleted, "in", currentStage?.completedSections?.formsCompleted);
|
|
1656
|
+
// if (!Object.keys(currentStage?.completedSections?.formsCompleted || {}).includes(formCompleted)) {
|
|
1657
|
+
// console.log("Form not completed");
|
|
1658
|
+
// return false;
|
|
1659
|
+
// } else {
|
|
1660
|
+
// console.log("Form completed")
|
|
1661
|
+
// }
|
|
1662
|
+
// }
|
|
1663
|
+
// for (let i = 0; i++; i < (currentStage?.stage?.requiredFiles || []).length) {
|
|
1664
|
+
// if (!Object.keys(currentStage?.completedSections?.filesUploaded || {}).includes(i.toString())) {
|
|
1665
|
+
// console.log("Form not uploaded");
|
|
1666
|
+
// return false;
|
|
1667
|
+
// } else {
|
|
1668
|
+
// console.log("Form uploaded");
|
|
1669
|
+
// }
|
|
1670
|
+
// }
|
|
1671
|
+
// return true;
|
|
1672
|
+
// };
|
|
1673
|
+
// areStagesCompleted().then(setCurrentStageComplete);
|
|
1674
|
+
// }, [fApplication, fListing])
|
|
1675
|
+
// const viewFile = (file: string, onOpen: (url: string) => void) => {
|
|
1676
|
+
// if (fApplication.reqUserType !== user.userType) return;
|
|
1677
|
+
// if (fApplication.stage === undefined) throw new Error("Missing applciation stage.")
|
|
1678
|
+
// if (!fListing) throw new Error("No associated listing.");
|
|
1679
|
+
// const viewableFiles = fListing?.applicantWorkflow?.find((stage) => stage.id === fApplication.stage)?.viewableFiles;
|
|
1680
|
+
// setFApplication((a) => {
|
|
1681
|
+
// const oldA = {...a};
|
|
1682
|
+
// const viewedFiles = a.completedSections?.[1]?.filesViewed || [];
|
|
1683
|
+
// if (viewedFiles?.includes(file)) return a;
|
|
1684
|
+
// viewableFiles?.[file].url && onOpen(viewableFiles?.[file].url);
|
|
1685
|
+
// viewedFiles?.push(file);
|
|
1686
|
+
// const newA = editNestedObject(["completedSections", 1, "filesViewed"], oldA, viewedFiles) as Partial<Application>;
|
|
1687
|
+
// return newA;
|
|
1688
|
+
// });
|
|
1689
|
+
// };
|
|
1690
|
+
// const addFile = (files: string[], fileId: number) => {
|
|
1691
|
+
// if (fApplication.reqUserType !== user.userType) throw new Error(`Incorrect user type. Expected ${fApplication.reqUserType}, got: ${user.userType}`);
|
|
1692
|
+
// if (fApplication.stage === undefined) throw new Error("Missing applciation stage.")
|
|
1693
|
+
// if (!files.length) throw new Error("No files to upload");
|
|
1694
|
+
// setFApplication((a) => editNestedObject(["completedSections", fApplication.stage as number, "filesUploaded", fileId], a, files) as Application);
|
|
1695
|
+
// };
|
|
1696
|
+
// const setFormComplete = (formId: string, e: {[key: string]: unknown}) => {
|
|
1697
|
+
// if (fApplication.reqUserType !== user.userType) throw new Error(`Incorrect user type. Expected ${fApplication.reqUserType}, got: ${user.userType}`);
|
|
1698
|
+
// if (fApplication.stage === undefined) throw new Error("Missing applciation stage.")
|
|
1699
|
+
// setFApplication((a) => editNestedObject(["completedSections", fApplication.stage as number, "formsCompleted", formId], a, e) as Application);
|
|
1700
|
+
// };
|
|
1701
|
+
// const successText = {
|
|
1702
|
+
// submitted: {
|
|
1703
|
+
// title: "Application submitted",
|
|
1704
|
+
// desc: "We've sent your application to the placement provider. You will hear what the next steps are soon.",
|
|
1705
|
+
// },
|
|
1706
|
+
// draftSaved: {
|
|
1707
|
+
// title: "Draft saved",
|
|
1708
|
+
// desc: "Your draft has been saved. Go to the 'Applications' section from your home screen to edit.",
|
|
1709
|
+
// },
|
|
1710
|
+
// stageComplete: {
|
|
1711
|
+
// title: "Stage complete",
|
|
1712
|
+
// desc: "We have sent this to the next stage in the application process. We will update you with any progress.",
|
|
1713
|
+
// },
|
|
1714
|
+
// outcome: {
|
|
1715
|
+
// title: "Outcome submitted",
|
|
1716
|
+
// desc: "We have sent the student an email with the outcome of their application.",
|
|
1717
|
+
// },
|
|
1718
|
+
// };
|
|
1719
|
+
// const onFApply = async (draft?: boolean) => {
|
|
1720
|
+
// if (draft) {
|
|
1721
|
+
// openSuccessPopup("draftSaved")
|
|
1722
|
+
// return;
|
|
1723
|
+
// }
|
|
1724
|
+
// if (!fApplicationId) return;
|
|
1725
|
+
// // Check all items have been filled in.
|
|
1726
|
+
// if (!fApplication.startDate || !fApplication.endDate) throw new Error("Please select dates for your placement.");
|
|
1727
|
+
// await executeCallable("applications-submit", {applicationId: fApplicationId});
|
|
1728
|
+
// const newApplication = await firebaseQuery.getDocData(["applications", fApplicationId]) as Application;
|
|
1729
|
+
// setFApplication(newApplication);
|
|
1730
|
+
// openSuccessPopup("submitted")
|
|
1731
|
+
// };
|
|
1732
|
+
// const progressStage = async (type: number|"accept"|"reject", e?: {feedback?: string}) => {
|
|
1733
|
+
// // Check all stages completed.
|
|
1734
|
+
// if (!fApplicationId) return;
|
|
1735
|
+
// if (!currentStageComplete) throw new Error("Complete all forms before submitting.");
|
|
1736
|
+
// if (fApplication.reqUserType !== user.userType) throw new Error(`Incorrect user type. Expected ${fApplication.reqUserType}, got: ${user.userType}`);
|
|
1737
|
+
// if (fApplication.stage === undefined) throw new Error("Missing applciation stage.")
|
|
1738
|
+
// await executeCallable("applications-changeStage", {applicationId: fApplicationId, type: type, feedback: e?.feedback});
|
|
1739
|
+
// const newApplication = await firebaseQuery.getDocData(["applications", fApplicationId]) as Application;
|
|
1740
|
+
// setFApplication(newApplication);
|
|
1741
|
+
// };
|
|
1742
|
+
// return {successText, onFApply, progressStage, currentStageComplete, uploadedFiles, getCurrentStage, setFormComplete, viewFile, addFile, setSuccessPopup, openSuccessPopup, setFApplication, fApplication, draftSaved, profileUrl, successPopup, fApplicationId, fListing, student, fProvider}
|
|
1743
|
+
// }
|
|
1672
1744
|
function useProposePlacementRenderer({ user, orgContext, placement }) {
|
|
1673
1745
|
const [businessSectionComplete, setBusinessSectionComplete] = (0, react_1.useState)(false);
|
|
1674
1746
|
const [addressSectionComplete, setAddressSectionComplete] = (0, react_1.useState)(false);
|
|
@@ -1734,22 +1806,27 @@ function useProposePlacementRenderer({ user, orgContext, placement }) {
|
|
|
1734
1806
|
setFormData(undefined);
|
|
1735
1807
|
};
|
|
1736
1808
|
const proposePlacement = async (draft = false) => {
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1809
|
+
const getPlacementStatus = (startDate, endDate) => {
|
|
1810
|
+
const today = new Date();
|
|
1811
|
+
if (startDate <= today && endDate >= today)
|
|
1812
|
+
return { active: !draft ? true : false, inProgress: true, completed: false };
|
|
1813
|
+
else if (endDate <= today)
|
|
1814
|
+
return { completed: true, inProgress: false, active: false };
|
|
1815
|
+
return { completed: false, inProgress: true, active: false };
|
|
1816
|
+
};
|
|
1743
1817
|
if (!formData || !student) {
|
|
1744
1818
|
throw new Error("Cannot find placement details.");
|
|
1745
1819
|
}
|
|
1746
1820
|
try {
|
|
1747
1821
|
console.log("formData", formData);
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1822
|
+
const status = getPlacementStatus(new Date(formData.startDate), new Date(formData.endDate));
|
|
1823
|
+
const newFormData = { ...formData, ...status };
|
|
1824
|
+
if (newFormData.id && newFormData.uid && draft === newFormData.draft)
|
|
1825
|
+
await firebaseQuery.update(["placements", newFormData.id], newFormData);
|
|
1826
|
+
else
|
|
1827
|
+
await (0, writeDatabase_1.addPlacement)(newFormData, student.id, draft);
|
|
1751
1828
|
setComplete(true);
|
|
1752
|
-
return
|
|
1829
|
+
return { status };
|
|
1753
1830
|
}
|
|
1754
1831
|
catch (error) {
|
|
1755
1832
|
console.log("Error:", error);
|
|
@@ -1791,7 +1868,7 @@ const useRefDimensions = () => {
|
|
|
1791
1868
|
return { dimensions, refCallback };
|
|
1792
1869
|
};
|
|
1793
1870
|
exports.useRefDimensions = useRefDimensions;
|
|
1794
|
-
const cohortStages = ["info", "name", "placementType", "review", "created"];
|
|
1871
|
+
const cohortStages = ["info", "name", "placementType", "database", "review", "created"];
|
|
1795
1872
|
const defaultCohortData = {
|
|
1796
1873
|
name: "",
|
|
1797
1874
|
stage: "info",
|
|
@@ -2485,34 +2562,34 @@ function useGenericWorkflowEditor({ user, initialData, defaultData, onSubmit })
|
|
|
2485
2562
|
includedForms, fSubmitWorkflow, openPopup, snackbar, setSnackbar, setMousePosFunc, mousePos, tutorialActive,
|
|
2486
2563
|
onDeleteArrow, fWorkflowNodes, containerRef, setError, setArrows, setFWorkflowNodes } });
|
|
2487
2564
|
}
|
|
2488
|
-
function
|
|
2565
|
+
function useInstituteProviderContactsHandler({ user }) {
|
|
2489
2566
|
const [emptyCellsWarning, setEmptyCellsWarning] = (0, react_1.useState)(false);
|
|
2490
2567
|
const [alert, setAlert] = (0, react_1.useState)();
|
|
2491
|
-
const requiredFields = ["
|
|
2568
|
+
const requiredFields = ["business", "forename", "email"];
|
|
2492
2569
|
const { execute } = (0, firebase_1.useExecuteCallableJob)({ user: user });
|
|
2493
|
-
const checkData = (
|
|
2570
|
+
const checkData = (providerContacts) => {
|
|
2494
2571
|
setAlert(undefined);
|
|
2495
|
-
|
|
2496
|
-
if (!Object.entries(
|
|
2572
|
+
providerContacts = providerContacts.filter((u) => Object.entries(u).some(([, v]) => v));
|
|
2573
|
+
if (!Object.entries(providerContacts)) {
|
|
2497
2574
|
return [];
|
|
2498
2575
|
}
|
|
2499
|
-
console.log("P",
|
|
2500
|
-
if (
|
|
2576
|
+
console.log("P", providerContacts);
|
|
2577
|
+
if (providerContacts.filter((u) => u.email).length < providerContacts.length) {
|
|
2501
2578
|
setAlert({ msg: "Your data contains missing email addresses.", severity: "error" });
|
|
2502
2579
|
return false;
|
|
2503
2580
|
}
|
|
2504
2581
|
let emptyOptionalCell = false;
|
|
2505
2582
|
let emptyRequiredCell = false;
|
|
2506
|
-
for (const
|
|
2507
|
-
if (!checkEmailValidity(
|
|
2583
|
+
for (const providerContact of providerContacts) {
|
|
2584
|
+
if (!checkEmailValidity(providerContact)) {
|
|
2508
2585
|
return false;
|
|
2509
2586
|
}
|
|
2510
|
-
if (Object.keys(
|
|
2587
|
+
if (Object.keys(providerContact).includes("")) {
|
|
2511
2588
|
setAlert({ msg: "Data cannot be uploaded in unnamed columns.", severity: "error" });
|
|
2512
2589
|
return false;
|
|
2513
2590
|
}
|
|
2514
|
-
for (const field in
|
|
2515
|
-
if (!
|
|
2591
|
+
for (const field in providerContact) {
|
|
2592
|
+
if (!providerContact[field]) {
|
|
2516
2593
|
if (requiredFields.includes(field)) {
|
|
2517
2594
|
setAlert({ msg: "All users must contain " + requiredFields.join(", "), severity: "error" });
|
|
2518
2595
|
emptyRequiredCell = true;
|
|
@@ -2532,39 +2609,26 @@ function useInstitutePlacementListingHandler({ user }) {
|
|
|
2532
2609
|
else {
|
|
2533
2610
|
setEmptyCellsWarning(false);
|
|
2534
2611
|
}
|
|
2535
|
-
return
|
|
2612
|
+
return providerContacts;
|
|
2536
2613
|
};
|
|
2537
|
-
const checkEmailValidity = (
|
|
2538
|
-
if (!(0, util_1.validateEmail)(
|
|
2539
|
-
setAlert({ msg: `Error in email formatting: ${
|
|
2614
|
+
const checkEmailValidity = (providerContact) => {
|
|
2615
|
+
if (!(0, util_1.validateEmail)(providerContact.email)) {
|
|
2616
|
+
setAlert({ msg: `Error in email formatting: ${providerContact.email}. Amend errors and reupload.`, severity: "error" });
|
|
2540
2617
|
return false;
|
|
2541
2618
|
}
|
|
2542
2619
|
return true;
|
|
2543
2620
|
};
|
|
2544
|
-
const
|
|
2545
|
-
let
|
|
2546
|
-
console.log("PP",
|
|
2547
|
-
const cleanUpload = checkData(
|
|
2621
|
+
const uploadProviderContacts = async (providers, schoolId) => {
|
|
2622
|
+
let fProviders = [];
|
|
2623
|
+
console.log("PP", providers);
|
|
2624
|
+
const cleanUpload = checkData(providers);
|
|
2548
2625
|
if (!cleanUpload) {
|
|
2549
2626
|
return false;
|
|
2550
2627
|
}
|
|
2551
|
-
|
|
2628
|
+
fProviders = cleanUpload;
|
|
2552
2629
|
setAlert(undefined);
|
|
2553
|
-
if (
|
|
2554
|
-
|
|
2555
|
-
name: v.provider,
|
|
2556
|
-
title: v.jobTitle,
|
|
2557
|
-
providerEmail: v.email,
|
|
2558
|
-
providerPhone: v.phone,
|
|
2559
|
-
["address-line1"]: v.addressOne,
|
|
2560
|
-
["address-line2"]: v.addressTwo,
|
|
2561
|
-
locality: v.city,
|
|
2562
|
-
postal_code: v.postcode,
|
|
2563
|
-
country: v.country,
|
|
2564
|
-
}));
|
|
2565
|
-
console.log("P", placements);
|
|
2566
|
-
console.log("callable params", { placements: formattedPlacements, instituteId: user.product === "admin" ? "admin" : user.oId });
|
|
2567
|
-
execute("placementListing-add", { data: formattedPlacements, instituteId: user.product === "admin" ? "admin" : user.oId });
|
|
2630
|
+
if (fProviders.length) {
|
|
2631
|
+
execute("providerContacts-add", { providerContacts: fProviders, instituteId: user.product === "admin" ? "admin" : user.oId, schoolId: schoolId });
|
|
2568
2632
|
}
|
|
2569
2633
|
return true;
|
|
2570
2634
|
};
|
|
@@ -2572,7 +2636,7 @@ function useInstitutePlacementListingHandler({ user }) {
|
|
|
2572
2636
|
setAlert(undefined);
|
|
2573
2637
|
setEmptyCellsWarning(false);
|
|
2574
2638
|
};
|
|
2575
|
-
return ({ ...{
|
|
2639
|
+
return ({ ...{ uploadProviderContacts, alert, onChange } });
|
|
2576
2640
|
}
|
|
2577
2641
|
function useGetIndividualPlacementForPlacementPage({ user, placementId, organisation }) {
|
|
2578
2642
|
var _a;
|
|
@@ -2738,7 +2802,7 @@ function useGetIndividualPlacementForPlacementPage({ user, placementId, organisa
|
|
|
2738
2802
|
}
|
|
2739
2803
|
if (e === "noInsurance") {
|
|
2740
2804
|
if (!eliData) {
|
|
2741
|
-
const storageRef = (0, storage_1.ref)(firebaseConfig_1.storage, `insurance/${placement.
|
|
2805
|
+
const storageRef = (0, storage_1.ref)(firebaseConfig_1.storage, `insurance/${placement.providerContactId}.pdf`);
|
|
2742
2806
|
const file = await (0, storage_1.getDownloadURL)(storageRef).catch(() => placement.insuranceSkippedReason);
|
|
2743
2807
|
setELIData(file);
|
|
2744
2808
|
}
|
|
@@ -2773,14 +2837,14 @@ function useGetIndividualPlacementForPlacementPage({ user, placementId, organisa
|
|
|
2773
2837
|
const approveELI = async () => {
|
|
2774
2838
|
if (!placement)
|
|
2775
2839
|
return;
|
|
2776
|
-
await (0, firebase_1.executeCallable)("insurance-approve", { oId: user.oId,
|
|
2840
|
+
await (0, firebase_1.executeCallable)("insurance-approve", { oId: user.oId, providerContactId: placement.providerContactId });
|
|
2777
2841
|
setEliPopupOpen(false);
|
|
2778
2842
|
};
|
|
2779
2843
|
const rejectELI = async ({ reason }) => {
|
|
2780
2844
|
if (!placement || !institute)
|
|
2781
2845
|
return;
|
|
2782
|
-
console.log("Reject", { reason: reason, placement: placement, instituteName: institute.name
|
|
2783
|
-
await (0, firebase_1.executeCallable)("insurance-reject", { reason: reason, placementId: placementId, instituteName: institute.name
|
|
2846
|
+
console.log("Reject", { reason: reason, placement: placement, instituteName: institute.name });
|
|
2847
|
+
await (0, firebase_1.executeCallable)("insurance-reject", { reason: reason, placementId: placementId, instituteName: institute.name });
|
|
2784
2848
|
setRejectELIPopup(false);
|
|
2785
2849
|
setEliPopupOpen(false);
|
|
2786
2850
|
};
|
|
@@ -2799,10 +2863,12 @@ function useGetIndividualPlacementForPlacementPage({ user, placementId, organisa
|
|
|
2799
2863
|
if (!placement)
|
|
2800
2864
|
return;
|
|
2801
2865
|
if (!placement.providerId) {
|
|
2802
|
-
const res = await (0, firebase_1.executeCallable)("
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2866
|
+
const res = await (0, firebase_1.executeCallable)("providerContacts-uploadProviderDetails", {
|
|
2867
|
+
placement: {
|
|
2868
|
+
id: placementId,
|
|
2869
|
+
data: Object.fromEntries(Object.entries(placement).filter(([k]) => k !== "contactId")),
|
|
2870
|
+
stage: wStage,
|
|
2871
|
+
},
|
|
2806
2872
|
skipSearch: true
|
|
2807
2873
|
}).catch((e) => {
|
|
2808
2874
|
throw e;
|
|
@@ -3104,13 +3170,7 @@ function useLoadListings(user, queryConstraint, request) {
|
|
|
3104
3170
|
}), "placementListings", constraints, undefined, true);
|
|
3105
3171
|
};
|
|
3106
3172
|
(0, react_1.useEffect)(() => {
|
|
3107
|
-
let unsubscribe;
|
|
3108
3173
|
loadListings();
|
|
3109
|
-
return () => {
|
|
3110
|
-
if (unsubscribe) {
|
|
3111
|
-
unsubscribe(); // Unsubscribe from the snapshot listener when the component unmounts
|
|
3112
|
-
}
|
|
3113
|
-
};
|
|
3114
3174
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3115
3175
|
}, [queryConstraints]);
|
|
3116
3176
|
const onScrollBottom = () => {
|
|
@@ -3186,13 +3246,7 @@ function useLoadProviderPlacements(user, queryConstraint, placementId) {
|
|
|
3186
3246
|
}), "placements", constraints, undefined, true);
|
|
3187
3247
|
};
|
|
3188
3248
|
(0, react_1.useEffect)(() => {
|
|
3189
|
-
let unsubscribe;
|
|
3190
3249
|
loadListings();
|
|
3191
|
-
return () => {
|
|
3192
|
-
if (unsubscribe) {
|
|
3193
|
-
unsubscribe(); // Unsubscribe from the snapshot listener when the component unmounts
|
|
3194
|
-
}
|
|
3195
|
-
};
|
|
3196
3250
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3197
3251
|
}, [queryConstraints]);
|
|
3198
3252
|
const onScrollBottom = () => {
|
|
@@ -3272,13 +3326,7 @@ function useLoadApplications({ user, applicationType, listingId, queryConstraint
|
|
|
3272
3326
|
}), "applications", constraints, undefined, true);
|
|
3273
3327
|
};
|
|
3274
3328
|
(0, react_1.useEffect)(() => {
|
|
3275
|
-
let unsubscribe;
|
|
3276
3329
|
loadApplications();
|
|
3277
|
-
return () => {
|
|
3278
|
-
if (unsubscribe) {
|
|
3279
|
-
unsubscribe(); // Unsubscribe from the snapshot listener when the component unmounts
|
|
3280
|
-
}
|
|
3281
|
-
};
|
|
3282
3330
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3283
3331
|
}, [type, queryConstraints]);
|
|
3284
3332
|
const onScrollBottom = () => {
|
|
@@ -3289,7 +3337,7 @@ function useLoadApplications({ user, applicationType, listingId, queryConstraint
|
|
|
3289
3337
|
};
|
|
3290
3338
|
return { applications, type, setType, onScrollBottom, loading, changeQueryConstraints };
|
|
3291
3339
|
}
|
|
3292
|
-
function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, additionalEntryProcessing, formatItems, snapshot, filters: initialFilters, onSearch, data }) {
|
|
3340
|
+
function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, additionalEntryProcessing, formatItems, snapshot, filters: initialFilters, initialSort, initialSearch, onSearch, data }) {
|
|
3293
3341
|
const [tableData, setTableData] = (0, react_1.useState)(Array.isArray(data) ? Object.fromEntries(Object.entries(data).slice(0, queryLimit)) : {});
|
|
3294
3342
|
const [page, setPage] = (0, react_1.useState)([1, 0]);
|
|
3295
3343
|
const [view, setView] = (0, react_1.useState)(initialView);
|
|
@@ -3299,12 +3347,13 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, add
|
|
|
3299
3347
|
const [dataListenerUnsubscribe, setDataListenerUnsubscribe] = (0, react_1.useState)();
|
|
3300
3348
|
const [loading, setLoading] = (0, react_1.useState)(true);
|
|
3301
3349
|
const [searchString, setSearchString] = (0, react_1.useState)();
|
|
3302
|
-
const [sort, setSort] = (0, react_1.useState)();
|
|
3350
|
+
const [sort, setSort] = (0, react_1.useState)((initialSort && sorts && sorts[initialSort]) ? [initialSort, sorts[initialSort]] : undefined);
|
|
3351
|
+
const [fData, setFData] = (0, react_1.useState)(data);
|
|
3303
3352
|
const processedData = async (k, v) => additionalEntryProcessing ? await additionalEntryProcessing(k, v) : v;
|
|
3304
3353
|
const setTableDataFromDefinedData = async () => {
|
|
3305
|
-
if (!
|
|
3354
|
+
if (!fData || Array.isArray(fData))
|
|
3306
3355
|
return;
|
|
3307
|
-
const dataWithAdditionalProcessingPossibleNulls = (await Promise.all(Object.entries(
|
|
3356
|
+
const dataWithAdditionalProcessingPossibleNulls = (await Promise.all(Object.entries(fData).map(async ([k, v]) => [k, await processedData(k, v)])));
|
|
3308
3357
|
const dataWithAdditionalProcessing = dataWithAdditionalProcessingPossibleNulls.filter(([k, v]) => v);
|
|
3309
3358
|
const searchedData = searchString ? dataWithAdditionalProcessing.filter(([, v]) => {
|
|
3310
3359
|
const values = Object.values(v).join(", ");
|
|
@@ -3328,7 +3377,7 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, add
|
|
|
3328
3377
|
throw new Error("Tables must have a limit defined.");
|
|
3329
3378
|
const newData = filteredData.slice((page[0] - 1) * queryLimit, page[0] * queryLimit);
|
|
3330
3379
|
setTableData(Object.fromEntries(newData));
|
|
3331
|
-
if (Object.keys(Object.fromEntries(newData)).pop() === Object.keys(
|
|
3380
|
+
if (Object.keys(Object.fromEntries(newData)).pop() === Object.keys(fData).pop()) {
|
|
3332
3381
|
setLoading("loaded");
|
|
3333
3382
|
}
|
|
3334
3383
|
else {
|
|
@@ -3344,7 +3393,7 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, add
|
|
|
3344
3393
|
const getDataFromQuery = async (itemList = {}, currentQueryAnchor = queryAnchor, cursorDirection, prevEntries = prevEntryIds, loadMoreFromQuery = false) => {
|
|
3345
3394
|
// if (!filters) return;
|
|
3346
3395
|
setLoading(true);
|
|
3347
|
-
if (!Array.isArray(
|
|
3396
|
+
if (!Array.isArray(fData)) {
|
|
3348
3397
|
setTableDataFromDefinedData();
|
|
3349
3398
|
return;
|
|
3350
3399
|
}
|
|
@@ -3353,8 +3402,8 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, add
|
|
|
3353
3402
|
if (onSearch && (searchString || sort)) {
|
|
3354
3403
|
if (typeof onSearch === "boolean")
|
|
3355
3404
|
throw new Error("When using Firestore queries, an onSearch function should be passed to retrieve data externally. Additional processing is however completed in this hook.");
|
|
3356
|
-
const
|
|
3357
|
-
const dataWithAdditionalProcessing = await Promise.all(Object.entries(
|
|
3405
|
+
const searchData = await onSearch(searchString, sort, page[0], filters, queryLimit);
|
|
3406
|
+
const dataWithAdditionalProcessing = await Promise.all(Object.entries(searchData).map(async ([k, v]) => [k, await processedData(k, v)]));
|
|
3358
3407
|
setTableData((old) => {
|
|
3359
3408
|
if (view === "table") {
|
|
3360
3409
|
return { ...Object.fromEntries(dataWithAdditionalProcessing) };
|
|
@@ -3376,7 +3425,7 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, add
|
|
|
3376
3425
|
else {
|
|
3377
3426
|
cursorPos = currentQueryAnchor.startQueryPos;
|
|
3378
3427
|
}
|
|
3379
|
-
const querySchema =
|
|
3428
|
+
const querySchema = fData[cursorPos];
|
|
3380
3429
|
const createQuery = (queryData) => {
|
|
3381
3430
|
const constraints = [];
|
|
3382
3431
|
queryData.where && queryData.where.forEach((w) => {
|
|
@@ -3435,7 +3484,7 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, add
|
|
|
3435
3484
|
}
|
|
3436
3485
|
// Function to handle query snapshot
|
|
3437
3486
|
async function handleQuerySnapshot(querySnapshot) {
|
|
3438
|
-
if (!Array.isArray(
|
|
3487
|
+
if (!Array.isArray(fData))
|
|
3439
3488
|
throw new Error("Called querySnapshot but data is defined.");
|
|
3440
3489
|
if (!queryLimit)
|
|
3441
3490
|
throw new Error("Firestore queries must have a limit defined.");
|
|
@@ -3479,7 +3528,7 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, add
|
|
|
3479
3528
|
setPrevEntryIds(prevEntries);
|
|
3480
3529
|
if (querySnapshot.size < queryLimit && Object.keys(itemList).length < queryLimit) {
|
|
3481
3530
|
// If we have ran out of entries, increase or decrease the index.
|
|
3482
|
-
if (page[0] > page[1] && cursorPos + 1 <
|
|
3531
|
+
if (page[0] > page[1] && cursorPos + 1 < fData.length) {
|
|
3483
3532
|
return getDataFromQuery(itemList, { ...currentQueryAnchor, endQueryPos: currentQueryAnchor.endQueryPos + 1 }, "increase", prevEntries);
|
|
3484
3533
|
}
|
|
3485
3534
|
else if (page[0] < page[1] && cursorPos > 0) {
|
|
@@ -3492,7 +3541,7 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, add
|
|
|
3492
3541
|
}
|
|
3493
3542
|
if (querySnapshot.size === 0 &&
|
|
3494
3543
|
Object.keys(itemList).length === 0 &&
|
|
3495
|
-
currentQueryAnchor.endQueryPos + 1 ===
|
|
3544
|
+
currentQueryAnchor.endQueryPos + 1 === fData.length &&
|
|
3496
3545
|
page[0] > 1) {
|
|
3497
3546
|
if (view === "table") {
|
|
3498
3547
|
setTableData({});
|
|
@@ -3526,28 +3575,33 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, add
|
|
|
3526
3575
|
setDataListenerUnsubscribe(undefined);
|
|
3527
3576
|
};
|
|
3528
3577
|
(0, react_1.useEffect)(() => {
|
|
3529
|
-
|
|
3530
|
-
if (!filters)
|
|
3578
|
+
if ((0, util_2.objectsEqualNew)(fData, data))
|
|
3531
3579
|
return;
|
|
3532
|
-
console.log("
|
|
3533
|
-
|
|
3534
|
-
}, [filters]);
|
|
3535
|
-
(0, react_1.useEffect)(() => {
|
|
3536
|
-
console.log("View reset.");
|
|
3537
|
-
reset();
|
|
3538
|
-
}, [view]);
|
|
3539
|
-
(0, react_1.useEffect)(() => {
|
|
3540
|
-
console.log("search reset.");
|
|
3541
|
-
reset();
|
|
3542
|
-
}, [searchString]);
|
|
3543
|
-
(0, react_1.useEffect)(() => {
|
|
3544
|
-
console.log("data reset.");
|
|
3580
|
+
console.log("data reset.", fData, data);
|
|
3581
|
+
setFData(data);
|
|
3545
3582
|
reset();
|
|
3546
3583
|
}, [data]);
|
|
3547
|
-
|
|
3548
|
-
|
|
3584
|
+
const updateFilters = (fFilters) => {
|
|
3585
|
+
if (!(0, util_2.objectsEqualNew)(fFilters, filters)) {
|
|
3586
|
+
console.log("FILTER RESET", fFilters, filters);
|
|
3587
|
+
setFilters(fFilters);
|
|
3588
|
+
reset();
|
|
3589
|
+
}
|
|
3590
|
+
};
|
|
3591
|
+
const updateSearch = (search) => {
|
|
3592
|
+
if (searchString === search)
|
|
3593
|
+
return;
|
|
3594
|
+
console.log("SEARCH RESET", searchString, search);
|
|
3595
|
+
setSearchString(search);
|
|
3549
3596
|
reset();
|
|
3550
|
-
}
|
|
3597
|
+
};
|
|
3598
|
+
const updateView = (v) => {
|
|
3599
|
+
if (v === view)
|
|
3600
|
+
return;
|
|
3601
|
+
console.log("View reset", view, v);
|
|
3602
|
+
setView(v);
|
|
3603
|
+
reset();
|
|
3604
|
+
};
|
|
3551
3605
|
// Fetch new data when queries or page change
|
|
3552
3606
|
(0, react_1.useEffect)(() => {
|
|
3553
3607
|
getDataFromQuery();
|
|
@@ -3560,11 +3614,17 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, add
|
|
|
3560
3614
|
setPage((p) => ([p[0] - 1, p[0]]));
|
|
3561
3615
|
};
|
|
3562
3616
|
const updateSort = (sortLabel) => {
|
|
3563
|
-
if (!
|
|
3564
|
-
|
|
3565
|
-
|
|
3617
|
+
if (!sortLabel) {
|
|
3618
|
+
setSort(undefined);
|
|
3619
|
+
}
|
|
3620
|
+
else {
|
|
3621
|
+
if (!sorts || !sorts[sortLabel])
|
|
3622
|
+
return;
|
|
3623
|
+
setSort([sortLabel, sorts[sortLabel]]);
|
|
3624
|
+
}
|
|
3625
|
+
reset();
|
|
3566
3626
|
};
|
|
3567
|
-
return ({ ...{ tableData, pageUp, pageDown, setFilters, page: page[0], sorts, loading, sort, updateSort: updateSort, setView, updateSearch
|
|
3627
|
+
return ({ ...{ tableData, pageUp, pageDown, search: searchString, setFilters: updateFilters, page: page[0], sorts, loading, sort, updateSort: updateSort, setView: updateView, updateSearch } });
|
|
3568
3628
|
}
|
|
3569
3629
|
;
|
|
3570
3630
|
//# sourceMappingURL=hooks.js.map
|