placementt-core 11.0.803 → 11.0.914
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/lib/constants.d.ts +1 -0
- package/lib/constants.js +2 -1
- package/lib/constants.js.map +1 -1
- 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/readDatabase.js +7 -7
- package/lib/firebase/readDatabase.js.map +1 -1
- package/lib/hooks.d.ts +90 -180
- package/lib/hooks.js +739 -639
- package/lib/hooks.js.map +1 -1
- package/lib/reduxHooks.d.ts +66 -1
- package/lib/reduxHooks.js +70 -11
- package/lib/reduxHooks.js.map +1 -1
- package/lib/tasksAndTips.d.ts +14 -4
- package/lib/tasksAndTips.js +463 -454
- package/lib/tasksAndTips.js.map +1 -1
- package/lib/typeDefinitions.d.ts +198 -81
- package/lib/util.d.ts +8 -1
- package/lib/util.js +17 -3
- package/lib/util.js.map +1 -1
- package/package.json +7 -4
- package/src/constants.ts +2 -0
- package/src/firebase/firebase.tsx +8 -4
- package/src/firebase/readDatabase.tsx +7 -7
- package/src/hooks.tsx +834 -742
- package/src/reduxHooks.ts +76 -13
- package/src/tasksAndTips.ts +504 -446
- package/src/typeDefinitions.ts +247 -76
- package/src/util.ts +20 -3
package/src/hooks.tsx
CHANGED
|
@@ -11,13 +11,13 @@ import { getFiles, getFormsFromId, getPlacementbyId, getPlacementsWhere, getUser
|
|
|
11
11
|
import { arrayUniqueValues, arraysEqual, convertDate, editNestedObject, getAccess, getDateDiff, getUniqueId, objectsEqual, validateEmail } from "./firebase/util";
|
|
12
12
|
import { addPlacement, editPlacementStage, uploadFiles } from "./firebase/writeDatabase";
|
|
13
13
|
import {
|
|
14
|
-
|
|
14
|
+
AlumniConvoUser,
|
|
15
15
|
ApplicantStage,
|
|
16
|
-
ApplicantWorkflow,
|
|
17
16
|
Application,
|
|
18
17
|
ArrowObject, CohortData, CustomFormSchema, FileItem, FlagCodes, InstituteData, OnboardingDocs, PlacementListing, Products,
|
|
18
|
+
ProviderContactData,
|
|
19
19
|
ProviderData,
|
|
20
|
-
QueryObject, QueryObjectConstraint,
|
|
20
|
+
QueryObject, QueryObjectConstraint, SchoolData, Sorts, StudentPlacementData, UserData, UserGroupData, WorkflowStage
|
|
21
21
|
} from "./typeDefinitions";
|
|
22
22
|
import algoliasearch from "algoliasearch";
|
|
23
23
|
import {getDownloadURL, ref} from "firebase/storage";
|
|
@@ -348,7 +348,7 @@ export function useNewInstitutePlacementList({id, user, filters, view, cohort, q
|
|
|
348
348
|
direction: "asc",
|
|
349
349
|
},
|
|
350
350
|
["Student Email - Desc"]: {
|
|
351
|
-
value: "
|
|
351
|
+
value: "studentEmail",
|
|
352
352
|
direction: "desc",
|
|
353
353
|
},
|
|
354
354
|
["Provider email - Asc"]: {
|
|
@@ -367,17 +367,22 @@ export function useNewInstitutePlacementList({id, user, filters, view, cohort, q
|
|
|
367
367
|
|
|
368
368
|
const student = await getUserById(placement.uid).catch(() => false) as UserData|false;
|
|
369
369
|
|
|
370
|
-
if (!student)
|
|
370
|
+
if (!student) {
|
|
371
|
+
console.log("No student");
|
|
372
|
+
return
|
|
373
|
+
};
|
|
371
374
|
|
|
372
375
|
if (!user.studentFilterValues.includes(student.details[user.studentFilter])) {
|
|
376
|
+
console.log("filter not included. Filteres: ", user.studentFilterValues, "value", user.studentFilter, "-", student.details[user.studentFilter]);
|
|
373
377
|
return false;
|
|
374
378
|
}
|
|
375
379
|
}
|
|
380
|
+
console.log("Valid placement", k);
|
|
376
381
|
return {...placement, id: k};
|
|
377
382
|
}
|
|
378
383
|
|
|
379
384
|
|
|
380
|
-
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)})
|
|
385
|
+
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(query || [], user, s, sort, page, filters, limit, cohort, inProgress)})
|
|
381
386
|
|
|
382
387
|
useEffect(() => {
|
|
383
388
|
// Sets the query of for the DataViewerPaginator
|
|
@@ -385,7 +390,7 @@ export function useNewInstitutePlacementList({id, user, filters, view, cohort, q
|
|
|
385
390
|
setQuery(undefined);
|
|
386
391
|
return;
|
|
387
392
|
}
|
|
388
|
-
if (((user.userGroup === "admin" || (cohort && user.viewCohorts === "some" && user?.visibleCohorts?.includes(cohort as string)) || (user.viewCohorts === "all" && user.viewStudents
|
|
393
|
+
if (((user.userGroup === "admin" || (cohort && user.viewCohorts === "some" && user?.visibleCohorts?.includes(cohort as string)) || (user.viewCohorts === "all" && user.viewStudents !== "none")))) {
|
|
389
394
|
const constraints:QueryObjectConstraint = [["oId", "==", user.oId], ["draft", "==", false]];
|
|
390
395
|
|
|
391
396
|
cohort && constraints.push(["cohort", "==", cohort]);
|
|
@@ -405,7 +410,101 @@ export function useNewInstitutePlacementList({id, user, filters, view, cohort, q
|
|
|
405
410
|
}
|
|
406
411
|
|
|
407
412
|
|
|
408
|
-
|
|
413
|
+
|
|
414
|
+
type AlumniPaginatorParams = {
|
|
415
|
+
user?: UserData,
|
|
416
|
+
alumniConvoUser?: AlumniConvoUser,
|
|
417
|
+
school?: string,
|
|
418
|
+
queryConstraints?: QueryObjectConstraint,
|
|
419
|
+
ql?: number,
|
|
420
|
+
view: "list"|"table",
|
|
421
|
+
filters?: FilterObject,
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
export function useAlumniPaginator({user, alumniConvoUser, filters, view, school, queryConstraints, ql=DEFAULTQUERYLIMIT}:AlumniPaginatorParams) {
|
|
427
|
+
const [query, setQuery] = useState<QueryObject[]>();
|
|
428
|
+
|
|
429
|
+
const sorts:Sorts = {}
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
const {tableData, pageUp, pageDown, setFilters, page, setView, loading} = useDataViewerPaginator({view, filters, sorts, queryLimit: ql, data: query})
|
|
433
|
+
const firebaseQuery = new FirebaseQuery();
|
|
434
|
+
|
|
435
|
+
useEffect(() => {
|
|
436
|
+
const createQuery = async () => {
|
|
437
|
+
// Sets the query of for the DataViewerPaginator
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
const getQueryAccess = async () => {
|
|
441
|
+
const constraints:QueryObjectConstraint = [];
|
|
442
|
+
|
|
443
|
+
if (user) {
|
|
444
|
+
constraints.push(["oId", "==", user.oId]);
|
|
445
|
+
|
|
446
|
+
if (user.userGroup === "admin" && user.userType === "Staff") return constraints;
|
|
447
|
+
|
|
448
|
+
if (user.userType === "Staff") {
|
|
449
|
+
if (user.viewSchools === "all") return constraints;
|
|
450
|
+
|
|
451
|
+
if (user.viewSchools === "none") return false;
|
|
452
|
+
|
|
453
|
+
if (user.viewSchools === "some") {
|
|
454
|
+
if (!school) return false;
|
|
455
|
+
|
|
456
|
+
if (user?.visibleSchools?.includes(school as string)) return constraints;
|
|
457
|
+
}
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (alumniConvoUser) {
|
|
464
|
+
constraints.push(["oId", "==", alumniConvoUser.oId]);
|
|
465
|
+
console.log("ALUMNI CONVO USER");
|
|
466
|
+
|
|
467
|
+
if ((school || alumniConvoUser.schoolId) && school === alumniConvoUser.schoolId) return constraints;
|
|
468
|
+
console.log("ALUMNI ACCESS TRUE");
|
|
469
|
+
if (alumniConvoUser.schoolId) {
|
|
470
|
+
const school = await firebaseQuery.getDocData(["schools", alumniConvoUser.schoolId]) as SchoolData;
|
|
471
|
+
console.log("SCHOOL ACCESS", school, school.alumniConversations);
|
|
472
|
+
return school.alumniConversations ? constraints : false;
|
|
473
|
+
|
|
474
|
+
} else {
|
|
475
|
+
const institute = await firebaseQuery.getDocData(["institutes", alumniConvoUser.oId]) as InstituteData;
|
|
476
|
+
return institute.alumniConversations ? constraints : false;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
const constraints = await getQueryAccess();
|
|
482
|
+
console.log("CONSTRAINTS", constraints);
|
|
483
|
+
if (!constraints) return;
|
|
484
|
+
|
|
485
|
+
school && constraints.push(["schoolId", "==", school]);
|
|
486
|
+
queryConstraints && constraints.unshift(...queryConstraints);
|
|
487
|
+
|
|
488
|
+
return constraints;
|
|
489
|
+
}
|
|
490
|
+
console.log("Creating query");
|
|
491
|
+
createQuery().then((constraints) => {
|
|
492
|
+
setQuery([{
|
|
493
|
+
path: ["alumni"],
|
|
494
|
+
where: constraints
|
|
495
|
+
}])
|
|
496
|
+
})
|
|
497
|
+
}, [user, queryConstraints, school])
|
|
498
|
+
|
|
499
|
+
useEffect(() => {
|
|
500
|
+
console.log("Alumni data", query, tableData);
|
|
501
|
+
}, [tableData]);
|
|
502
|
+
|
|
503
|
+
return {tableData, page, loading, setFilters, setView, pageUp, pageDown, sorts}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
const algoliaPlacementSearch = async (data: QueryObject[], user: UserData, query?: string, sort?: [string, {value: string, direction: "asc"|"desc"}], page?: number, filters?: FilterObject, limit?: number, cohort?: string, inProgress?: boolean) => {
|
|
409
508
|
const algoliaClient = algoliasearch(process.env.NODE_ENV === "development" ? "A0ZB50I7VS" : "XMPXCMUUOJ", user.algoliaKey);
|
|
410
509
|
const placementsIndex = algoliaClient.initIndex(sort ? Object.values(sort[1]).join("_") : "placements");
|
|
411
510
|
// const usersIndex = algoliaClient.initIndex("users");
|
|
@@ -894,210 +993,222 @@ export function useFilterTablePaginator({data}:{data:{[key:string]:{[key:string]
|
|
|
894
993
|
return ({...{tableData, setPage, setFilters, page}});
|
|
895
994
|
}
|
|
896
995
|
|
|
897
|
-
export function
|
|
898
|
-
const [
|
|
899
|
-
const [page, setPage] = useState([1, 0]);
|
|
900
|
-
const [filters, setFilters] = useState<{[key:string]: unknown}>();
|
|
901
|
-
const [queryAnchor, setQueryAnchor] = useState<{startKey: string, endKey: string, startQueryPos: number, endQueryPos: number}>({startKey: "", endKey: "", startQueryPos: 0, endQueryPos: 0});
|
|
902
|
-
const [prevEntryIds, setPrevEntryIds] = useState<{[key:string]:number}>({});
|
|
996
|
+
export function useProviderContactPaginator({data, user, view, filters}:{data:QueryObject[], user: UserData, view: "list"|"table", filters?: FilterObject}) {
|
|
997
|
+
const [query, setQuery] = useState<QueryObject[]>();
|
|
903
998
|
const firebaseQuery = new FirebaseQuery();
|
|
904
999
|
|
|
905
|
-
const
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
cursorPos = currentQueryAnchor.endQueryPos;
|
|
910
|
-
} else {
|
|
911
|
-
cursorPos = currentQueryAnchor.startQueryPos;
|
|
1000
|
+
const getAdditionalData = async (k: string, v: ProviderContactData) => {
|
|
1001
|
+
if (v.savedBy?.[user.oId].activities?.includes("workExperience")) {
|
|
1002
|
+
const placementsCount = await firebaseQuery.getCount("placementListings", [where(`savedBy.${user.oId}.exists`, "==", true), where("providerContactId", "==", k)]);
|
|
1003
|
+
return {...v, plcaements: placementsCount};
|
|
912
1004
|
}
|
|
1005
|
+
return v;
|
|
1006
|
+
}
|
|
913
1007
|
|
|
914
|
-
|
|
1008
|
+
const {tableData, pageUp, pageDown, setFilters, page, setView, loading} = useDataViewerPaginator({view, filters, queryLimit: 10, data: query, additionalEntryProcessing: getAdditionalData})
|
|
915
1009
|
|
|
916
|
-
const createQuery = (queryData?:QueryObject) => {
|
|
917
|
-
const constraints:any[] = [
|
|
918
|
-
where("savedById", "==", user.userType === "Staff" ? user.oId : user.id),
|
|
919
|
-
where("savedByProduct", "==", user.product),
|
|
920
|
-
where("savedByUserType", "==", user.userType === "Staff" ? "Organisation" : "Student"),
|
|
921
|
-
]
|
|
922
1010
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
}
|
|
1011
|
+
useEffect(() => {
|
|
1012
|
+
const constraints:QueryObjectConstraint = [
|
|
1013
|
+
[`savedBy.${user.oId}.exists`, "==", true],
|
|
1014
|
+
]
|
|
926
1015
|
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1016
|
+
if (user.userType === "Students") {
|
|
1017
|
+
constraints.push([`savedBy.${user.oId}.cohorts.${user.cohort}.listed`, "==", true]);
|
|
1018
|
+
}
|
|
1019
|
+
setQuery([{
|
|
1020
|
+
path: ["providerContacts"],
|
|
1021
|
+
where: constraints
|
|
1022
|
+
}])
|
|
1023
|
+
}, [user]);
|
|
930
1024
|
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
});
|
|
1025
|
+
return ({...{tableData, pageUp, pageDown, setFilters, page, setView, loading}});
|
|
1026
|
+
}
|
|
934
1027
|
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
}
|
|
1028
|
+
type UserPaginatorParams = {
|
|
1029
|
+
user: UserData,
|
|
1030
|
+
cohort?: string,
|
|
1031
|
+
data: QueryObject[],
|
|
1032
|
+
search?: string,
|
|
1033
|
+
userType: "Staff"|"Students",
|
|
1034
|
+
sort?: string
|
|
1035
|
+
}
|
|
944
1036
|
|
|
945
1037
|
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
return constraints;
|
|
970
|
-
};
|
|
1038
|
+
const algoliaUsersSearch = async (data: QueryObject[], user: UserData, query?: string, sort?: [string, {value: string, direction: "asc"|"desc"}], page?: number, filters?: FilterObject, limit?: number, cohort?: string) => {
|
|
1039
|
+
const algoliaClient = algoliasearch(process.env.NODE_ENV === "development" ? "A0ZB50I7VS" : "XMPXCMUUOJ", user.algoliaKey);
|
|
1040
|
+
console.log("SORT", sort);
|
|
1041
|
+
const userIndex = algoliaClient.initIndex(sort ? `users_${Object.values(sort[1]).join("_")}` : "users");
|
|
1042
|
+
const constraints = data[0].where;
|
|
1043
|
+
|
|
1044
|
+
if (!constraints?.length) return {};
|
|
1045
|
+
|
|
1046
|
+
let userSearchString = constraints.map(([k, e, v]) => {
|
|
1047
|
+
if (e === "==") return `${k}:"${v}"`; // Equality check
|
|
1048
|
+
if (e === "!=") return `${k}:-"${v}"`; // Not equal check
|
|
1049
|
+
if (e === "<") return `${k}:<${v}`; // Less than check
|
|
1050
|
+
if (e === "<=") return `${k}:<=${v}`; // Less than or equal check
|
|
1051
|
+
if (e === ">") return `${k}:>${v}`; // Greater than check
|
|
1052
|
+
if (e === ">=") return `${k}:>=${v}`; // Greater than or equal check
|
|
1053
|
+
if (e === "array-contains") return `${k}:"${v}"`; // Array contains check (string format)
|
|
1054
|
+
if (e === "array-contains-any") return `${k}:"${(v as string[]).join('","')}"`; // Array contains any of the values (string format)
|
|
1055
|
+
if (e === "in") return `${k}:(${(v as string[]).join('","')})`; // In check
|
|
1056
|
+
if (e === "not-in") return `${k}:(-${(v as string[]).join('","')})`; // Not in check
|
|
1057
|
+
return;
|
|
1058
|
+
}).join(" AND ");
|
|
971
1059
|
|
|
972
|
-
|
|
973
|
-
// console.log(queryId, "constraints", constraints)
|
|
1060
|
+
console.log("QUERY", userSearchString);
|
|
974
1061
|
|
|
975
|
-
|
|
976
|
-
|
|
1062
|
+
filters && Object.entries(filters).filter(([, filter]) => filter.value).map(([id, filter]) => {
|
|
1063
|
+
userSearchString = userSearchString + ` AND ${id}:${filter.value}`;
|
|
1064
|
+
});
|
|
977
1065
|
|
|
978
|
-
const
|
|
1066
|
+
const options = {
|
|
1067
|
+
filters: userSearchString,
|
|
1068
|
+
hitsPerPage: limit,
|
|
1069
|
+
page: page ? page - 1 : undefined,
|
|
1070
|
+
}
|
|
979
1071
|
|
|
980
|
-
|
|
1072
|
+
const searchUsersHits = await userIndex.search<UserData>(query || "", options);
|
|
981
1073
|
|
|
1074
|
+
console.log(searchUsersHits.hits);
|
|
1075
|
+
|
|
1076
|
+
const i = (searchUsersHits ? (await Promise.all(searchUsersHits.hits.map(async (hit) => {
|
|
1077
|
+
return [hit.objectID, hit];
|
|
1078
|
+
}))) : []).filter((e) => e !== undefined) as [string, UserData][];
|
|
982
1079
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
return docs.reverse();
|
|
986
|
-
}
|
|
987
|
-
return docs;
|
|
988
|
-
};
|
|
1080
|
+
return Object.fromEntries(i)
|
|
1081
|
+
}
|
|
989
1082
|
|
|
990
|
-
let index = 0;
|
|
991
|
-
reverseIfBack(queryData.docs).forEach(async (doc: QueryDocumentSnapshot) => {
|
|
992
|
-
if (Object.keys(queryResults).length + Object.keys(itemList).length === 10) {
|
|
993
|
-
return;
|
|
994
|
-
}
|
|
995
1083
|
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1084
|
+
type NewUserPaginatorParams = {
|
|
1085
|
+
user: UserData,
|
|
1086
|
+
cohort?: string,
|
|
1087
|
+
queryConstraints?: QueryObjectConstraint,
|
|
1088
|
+
ql?: number,
|
|
1089
|
+
view: "list"|"table",
|
|
1090
|
+
filters?: FilterObject,
|
|
1091
|
+
institute: InstituteData,
|
|
1092
|
+
userType: "Staff"|"Students"
|
|
1093
|
+
}
|
|
1000
1094
|
|
|
1001
|
-
// console.log(index, "doc.id", doc.id, position, "E", prevEntries[doc.id])
|
|
1002
1095
|
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
return;
|
|
1006
|
-
}
|
|
1096
|
+
export function useNewCohortUserPaginator({user, institute, filters, view, cohort, queryConstraints, ql=DEFAULTQUERYLIMIT, userType}:NewUserPaginatorParams) {
|
|
1097
|
+
const [query, setQuery] = useState<QueryObject[]>();
|
|
1007
1098
|
|
|
1008
|
-
|
|
1009
|
-
item.id = doc.id;
|
|
1010
|
-
queryResults[doc.id] = item;
|
|
1011
|
-
index = index+1;
|
|
1012
|
-
if (prevEntries[doc.id]) return;
|
|
1013
|
-
prevEntries[doc.id] = position;
|
|
1014
|
-
});
|
|
1099
|
+
const firebaseQuery = new FirebaseQuery();
|
|
1015
1100
|
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1101
|
+
const sorts:Sorts = {
|
|
1102
|
+
["Student Forename - Asc"]: {
|
|
1103
|
+
value: "details.forename",
|
|
1104
|
+
direction: "asc",
|
|
1105
|
+
},
|
|
1106
|
+
["Student Forename - Desc"]: {
|
|
1107
|
+
value: "details.forename",
|
|
1108
|
+
direction: "desc",
|
|
1109
|
+
},
|
|
1110
|
+
["Student Surname - Asc"]: {
|
|
1111
|
+
value: "details.surname",
|
|
1112
|
+
direction: "asc",
|
|
1113
|
+
},
|
|
1114
|
+
["Student Surname - Desc"]: {
|
|
1115
|
+
value: "details.surname",
|
|
1116
|
+
direction: "desc",
|
|
1117
|
+
},
|
|
1118
|
+
["Student Email - Asc"]: {
|
|
1119
|
+
value: "email",
|
|
1120
|
+
direction: "asc",
|
|
1121
|
+
},
|
|
1122
|
+
["Student Email - Desc"]: {
|
|
1123
|
+
value: "email",
|
|
1124
|
+
direction: "desc",
|
|
1020
1125
|
}
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
useEffect(() => {
|
|
1021
1129
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
return getDataFromQuery(itemList, {...currentQueryAnchor, endQueryPos: currentQueryAnchor.endQueryPos+1}, "increase", prevEntries);
|
|
1028
|
-
} else if (page[0] < page[1] && cursorPos > 0) {
|
|
1029
|
-
console.log("Decrease query index");
|
|
1030
|
-
return getDataFromQuery(itemList, {...currentQueryAnchor, startQueryPos: currentQueryAnchor.startQueryPos-1}, "decrease", prevEntries);
|
|
1130
|
+
const getAccess = async () => {
|
|
1131
|
+
// Sets the query of for the DataViewerPaginator
|
|
1132
|
+
if(user.product !== "institutes" || user.userType !== "Staff") {
|
|
1133
|
+
setQuery(undefined);
|
|
1134
|
+
return;
|
|
1031
1135
|
}
|
|
1032
|
-
}
|
|
1033
1136
|
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
return getDataFromQuery(itemList, {...currentQueryAnchor, startKey: Object.keys(itemList)[0], endKey: Object.keys(itemList).slice(-1)[0]}, undefined, prevEntries, true);
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
if (queryData.size === 0 &&
|
|
1041
|
-
Object.keys(itemList).length === 0 &&
|
|
1042
|
-
currentQueryAnchor.endQueryPos+1 === data.length &&
|
|
1043
|
-
page[0] > 1) {
|
|
1044
|
-
setTableData({});
|
|
1045
|
-
setQueryAnchor((a) => ({...a, startKey: ""}));
|
|
1046
|
-
return;
|
|
1047
|
-
}
|
|
1137
|
+
const constraints:QueryObjectConstraint = [["oId", "==", user.oId], ["userType", "==", userType]];
|
|
1138
|
+
cohort && constraints.push(["cohort", "==", cohort]);
|
|
1139
|
+
queryConstraints && constraints.unshift(...queryConstraints);
|
|
1048
1140
|
|
|
1049
|
-
|
|
1141
|
+
const mSetQuery = (clear?: boolean) => {
|
|
1142
|
+
setQuery(clear ? undefined : [{
|
|
1143
|
+
path: ["users"],
|
|
1144
|
+
where: constraints
|
|
1145
|
+
}]);
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
1050
1148
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
};
|
|
1149
|
+
if (institute.package === "institutes-one") {
|
|
1150
|
+
if (user.userGroup === "admin" || (user.viewCohorts === "all" && user.viewStudents === "all")) return mSetQuery();
|
|
1151
|
+
|
|
1152
|
+
if (!user.viewCohorts || user.viewCohorts === "none" || !user.viewStudents || user.viewStudents === "none" || (user.viewCohorts === "some" && !user.visibleCohorts?.length) || (user.viewStudents === "some" && !user.studentFilterValues?.length)) return mSetQuery(true);
|
|
1153
|
+
|
|
1154
|
+
if (user.viewStudents === "some") {
|
|
1155
|
+
constraints.push([`details.${user.studentFilter}`, "in", user.studentFilterValues as string[]]);
|
|
1156
|
+
}
|
|
1060
1157
|
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1158
|
+
if (cohort) {
|
|
1159
|
+
const canViewCohort = user.viewCohorts === "all" || (user.viewCohorts === "some" && user.visibleCohorts?.includes("cohort"));
|
|
1160
|
+
return mSetQuery(canViewCohort);
|
|
1161
|
+
} else {
|
|
1162
|
+
// No cohort.
|
|
1163
|
+
if (user.viewCohorts === "all") return mSetQuery();
|
|
1164
|
+
if (user.viewCohorts === "some" && user.visibleCohorts) {
|
|
1165
|
+
constraints.push(["cohort", "in", user.visibleCohorts]);
|
|
1166
|
+
return mSetQuery()
|
|
1167
|
+
}
|
|
1168
|
+
return mSetQuery(true);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1064
1171
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
if (placement.mapConsent === false) return "notPublic";
|
|
1068
|
-
return "unknown";
|
|
1069
|
-
};
|
|
1172
|
+
if (institute.package === "institutes-two") {
|
|
1173
|
+
if (user.userGroup === "admin" || (user.viewSchools === "all" && user.viewCohorts === "all" && user.viewStudents === "all")) return mSetQuery();
|
|
1070
1174
|
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1175
|
+
if (!user.viewCohorts || !user.viewSchools || user.viewSchools === "none" || user.viewCohorts === "none") return mSetQuery(true);
|
|
1176
|
+
if (!user.viewStudents || user.viewStudents === "none" || (user.viewStudents === "some" && !user.studentFilterValues?.length) || (user.viewCohorts === "some" && !user.visibleCohorts?.length) || (user.viewSchools === "some" && !user.visibleSchools?.length)) return mSetQuery(true);
|
|
1177
|
+
|
|
1178
|
+
if (user.viewStudents === "some") {
|
|
1179
|
+
constraints.push([`details.${user.studentFilter}`, "in", user.studentFilterValues as string[]]);
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
if (cohort) {
|
|
1183
|
+
if (user.viewCohorts === "some" && !user.visibleCohorts?.includes(cohort)) return mSetQuery(true);
|
|
1184
|
+
|
|
1185
|
+
if (user.viewSchools === "some") {
|
|
1186
|
+
const cohortData = await firebaseQuery.getDocData(["cohorts", cohort]) as CohortData;
|
|
1187
|
+
if (!cohortData.schoolId || !user.visibleSchools?.includes(cohortData.schoolId)) return mSetQuery(true)
|
|
1188
|
+
}
|
|
1189
|
+
} else {
|
|
1190
|
+
if (user.viewCohorts === "some" && user.visibleCohorts) {
|
|
1191
|
+
constraints.push(["cohort", "in", user.visibleCohorts]);
|
|
1192
|
+
} else if (user.viewSchools === "some" && user.visibleSchools) {
|
|
1193
|
+
const cohorts = await firebaseQuery.getDocsWhere("cohorts", [where("oId", "==", user.oId), where("schoolId", "in", user.visibleSchools)]);
|
|
1194
|
+
constraints.push(["cohort", "in", Object.keys(cohorts || {})]);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
return mSetQuery();
|
|
1198
|
+
}
|
|
1199
|
+
setQuery(undefined)
|
|
1200
|
+
}
|
|
1201
|
+
getAccess();
|
|
1202
|
+
}, [user, queryConstraints, cohort])
|
|
1075
1203
|
|
|
1076
|
-
useEffect(() => {
|
|
1077
|
-
if (!filters) return;
|
|
1078
1204
|
|
|
1079
|
-
|
|
1080
|
-
setTableData({});
|
|
1081
|
-
setQueryAnchor({startKey: "", endKey: "", startQueryPos: 0, endQueryPos: 0});
|
|
1082
|
-
setPrevEntryIds({});
|
|
1083
|
-
}, [filters]);
|
|
1205
|
+
const {tableData, pageUp, pageDown, setFilters, page, setView, loading, updateSearch, updateSort, sort} = useDataViewerPaginator({view, filters, sorts, queryLimit: ql, data: query, onSearch: async (s, sort, page, filters, limit) => await algoliaUsersSearch(query || [], user, s, sort, page, filters, limit, cohort)})
|
|
1084
1206
|
|
|
1085
|
-
// Fetch new data when queries or page change
|
|
1086
|
-
useEffect(() => {
|
|
1087
|
-
getDataFromQuery();
|
|
1088
|
-
}, [page]);
|
|
1089
1207
|
|
|
1090
|
-
return
|
|
1208
|
+
return {tableData, page, loading, updateSearch, setFilters, setView, pageUp, pageDown, sorts, updateSort, sort}
|
|
1091
1209
|
}
|
|
1092
1210
|
|
|
1093
|
-
|
|
1094
|
-
user: UserData,
|
|
1095
|
-
cohort?: string,
|
|
1096
|
-
data: QueryObject[],
|
|
1097
|
-
search?: string,
|
|
1098
|
-
userType: "Staff"|"Students",
|
|
1099
|
-
sort?: string
|
|
1100
|
-
}
|
|
1211
|
+
|
|
1101
1212
|
|
|
1102
1213
|
export function useCohortUserPaginator({user, cohort, data, search, userType, sort}:UserPaginatorParams) {
|
|
1103
1214
|
const [tableData, setTableData] = useState<{[key:string]:{[key:string]: unknown}}>({});
|
|
@@ -1130,8 +1241,8 @@ export function useCohortUserPaginator({user, cohort, data, search, userType, so
|
|
|
1130
1241
|
}
|
|
1131
1242
|
if (
|
|
1132
1243
|
(!user.viewCohorts && user.userGroup !== "admin") ||
|
|
1133
|
-
user.viewCohorts === "none" ||
|
|
1134
|
-
(user.viewCohorts === "some" && cohort !== "all" && !user.visibleCohorts?.includes(cohort || ""))) {
|
|
1244
|
+
(user.viewCohorts === "none" && user.userGroup !== "admin") ||
|
|
1245
|
+
(user.viewCohorts === "some" && user.userGroup !== "admin" && cohort !== "all" && !user.visibleCohorts?.includes(cohort || ""))) {
|
|
1135
1246
|
setQueries(undefined);
|
|
1136
1247
|
return;
|
|
1137
1248
|
}
|
|
@@ -1476,514 +1587,514 @@ export function useLazyLoadQueryList({path, constraints, number, onItemFetched}:
|
|
|
1476
1587
|
}
|
|
1477
1588
|
|
|
1478
1589
|
|
|
1479
|
-
type PublicPlacementListingLoaderParams = {
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
|
-
export function usePublicPlacementListingLoader({providerId, number=5}:PublicPlacementListingLoaderParams) {
|
|
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
|
-
export type ApplicationHookParams = {
|
|
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
|
-
export function useCreateApplicationRenderer({user, listingId, listing, provider, application, applicationId, orgContext}:
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1590
|
+
// type PublicPlacementListingLoaderParams = {
|
|
1591
|
+
// providerId?: string,
|
|
1592
|
+
// number: number,
|
|
1593
|
+
// }
|
|
1594
|
+
|
|
1595
|
+
// export function usePublicPlacementListingLoader({providerId, number=5}:PublicPlacementListingLoaderParams) {
|
|
1596
|
+
// const [items, setItems] = useState<{[key:string]:{[key:string]:unknown}}>({});
|
|
1597
|
+
// const [loadMoreIcon, setLoadMoreIcon] = useState<boolean>(false);
|
|
1598
|
+
|
|
1599
|
+
// const [lastItem, setLastItem] = useState<QueryDocumentSnapshot<DocumentData>>();
|
|
1600
|
+
// const firebaseQuery = new FirebaseQuery();
|
|
1601
|
+
|
|
1602
|
+
// const reset = () => {
|
|
1603
|
+
// setItems({});
|
|
1604
|
+
// setLastItem(undefined);
|
|
1605
|
+
// };
|
|
1606
|
+
|
|
1607
|
+
// const loadMore = async () => {
|
|
1608
|
+
// setLoadMoreIcon(true);
|
|
1609
|
+
// let formattedConstraints:QueryConstraint[] = [
|
|
1610
|
+
// where("status", "==", "listed"),
|
|
1611
|
+
// limit(number)
|
|
1612
|
+
// ];
|
|
1613
|
+
|
|
1614
|
+
// if (providerId) {
|
|
1615
|
+
// formattedConstraints.push(where("providerId", "==", providerId));
|
|
1616
|
+
// }
|
|
1617
|
+
// if (lastItem) {
|
|
1618
|
+
// formattedConstraints.push(startAfter(lastItem));
|
|
1619
|
+
// }
|
|
1620
|
+
// const documents = await firebaseQuery.getDocsWhere("placementListings", formattedConstraints, true) as QuerySnapshot<DocumentData>;
|
|
1621
|
+
|
|
1622
|
+
// console.log("docs", documents.docs);
|
|
1623
|
+
// setLastItem(documents.docs[documents.docs.length-1]);
|
|
1624
|
+
|
|
1625
|
+
// const processedItems = Object.fromEntries(await Promise.all(Object.values(documents.docs).map(async (doc) => {
|
|
1626
|
+
// let itemObj = {...doc.data(), id: doc.id} as PlacementListing;
|
|
1627
|
+
|
|
1628
|
+
// if (itemObj.addressId) {
|
|
1629
|
+
// const address = await firebaseQuery.getDocData(["addresses", itemObj.addressId]) as Address;
|
|
1630
|
+
// delete address.id;
|
|
1631
|
+
// itemObj = {...address, ...itemObj};
|
|
1632
|
+
// }
|
|
1633
|
+
// if (itemObj.applicantWorkflowId) {
|
|
1634
|
+
// const applicantWorkflow = (await firebaseQuery.getDocData(["applicantWorkflows", itemObj.applicantWorkflowId]) as ApplicantWorkflow).workflow.filter((i) => i.id === 1)[0];
|
|
1635
|
+
// const applicantFiles = applicantWorkflow.files ? Object.fromEntries(await Promise.all(applicantWorkflow.files?.map(async (fileId) => {
|
|
1636
|
+
// const file = await firebaseQuery.getDocData(["files", fileId]);
|
|
1637
|
+
// file.url = await getDownloadURL(ref(storage, `providers/${itemObj.providerId}/${file.fileName}`));
|
|
1638
|
+
|
|
1639
|
+
// return [fileId, file];
|
|
1640
|
+
// }))) : [];
|
|
1641
|
+
// const applicantForms = applicantWorkflow.forms ? Object.fromEntries(await Promise.all(applicantWorkflow.forms?.map(async (formId) => {
|
|
1642
|
+
// return [formId, await firebaseQuery.getDocData(["forms", formId])];
|
|
1643
|
+
// }))) : [];
|
|
1644
|
+
|
|
1645
|
+
// applicantWorkflow.viewableFiles = applicantFiles;
|
|
1646
|
+
// applicantWorkflow.formDetails = applicantForms;
|
|
1647
|
+
// itemObj = {...itemObj, applicantWorkflow: [applicantWorkflow]};
|
|
1648
|
+
// }
|
|
1649
|
+
// return [doc.id, itemObj];
|
|
1650
|
+
// })))
|
|
1651
|
+
|
|
1652
|
+
// setItems((i) => ({...i, ...processedItems}));
|
|
1653
|
+
// setLoadMoreIcon(false);
|
|
1654
|
+
// };
|
|
1655
|
+
// useEffect(() => {
|
|
1656
|
+
// loadMore();
|
|
1657
|
+
// }, []);
|
|
1658
|
+
|
|
1659
|
+
// return ({...{items, loadMore, loadMoreIcon, reset}});
|
|
1660
|
+
// }
|
|
1661
|
+
|
|
1662
|
+
// export type ApplicationHookParams = {
|
|
1663
|
+
// successText: {
|
|
1664
|
+
// submitted: {
|
|
1665
|
+
// title: string;
|
|
1666
|
+
// desc: string;
|
|
1667
|
+
// };
|
|
1668
|
+
// draftSaved: {
|
|
1669
|
+
// title: string;
|
|
1670
|
+
// desc: string;
|
|
1671
|
+
// };
|
|
1672
|
+
// stageComplete: {
|
|
1673
|
+
// title: string;
|
|
1674
|
+
// desc: string;
|
|
1675
|
+
// };
|
|
1676
|
+
// outcome: {
|
|
1677
|
+
// title: string;
|
|
1678
|
+
// desc: string;
|
|
1679
|
+
// };
|
|
1680
|
+
// };
|
|
1681
|
+
// setSuccessPopup: import("react").Dispatch<import("react").SetStateAction<"submitted" | "draftSaved" | "stageComplete" | "outcome" | undefined>>;
|
|
1682
|
+
// openSuccessPopup: (type: "submitted" | "draftSaved" | "stageComplete" | "outcome") => void;
|
|
1683
|
+
// setFApplication: import("react").Dispatch<import("react").SetStateAction<Partial<Application>>>;
|
|
1684
|
+
// fApplication: Partial<Application>;
|
|
1685
|
+
// draftSaved: boolean;
|
|
1686
|
+
// profileUrl: string | undefined;
|
|
1687
|
+
// successPopup: "submitted" | "draftSaved" | "stageComplete" | "outcome" | undefined;
|
|
1688
|
+
// fApplicationId: string | undefined;
|
|
1689
|
+
// fListing: PlacementListing | false | undefined;
|
|
1690
|
+
// student: UserData | undefined;
|
|
1691
|
+
// fProvider: {
|
|
1692
|
+
// details?: ProviderData;
|
|
1693
|
+
// profile?: string;
|
|
1694
|
+
// id?: string;
|
|
1695
|
+
// } | undefined;
|
|
1696
|
+
// onFApply: (draft?: boolean) => Promise<void>;
|
|
1697
|
+
// setFormComplete: (formId: string, e: {
|
|
1698
|
+
// [key: string]: unknown;
|
|
1699
|
+
// }) => void;
|
|
1700
|
+
// viewFile: (file: string, onOpen: (url: string) => void) => void
|
|
1701
|
+
// addFile: (files: string[], fileId: number) => void;
|
|
1702
|
+
// uploadedFiles?: {
|
|
1703
|
+
// [key: string]: FileItem;
|
|
1704
|
+
// };
|
|
1705
|
+
// getCurrentStage: (stage: number) => Promise<{
|
|
1706
|
+
// stage: ApplicantStage;
|
|
1707
|
+
// completedSections: {
|
|
1708
|
+
// submitted?: string | undefined;
|
|
1709
|
+
// filesViewed?: string[] | undefined;
|
|
1710
|
+
// formsCompleted?: {
|
|
1711
|
+
// [key: string]: unknown;
|
|
1712
|
+
// } | undefined;
|
|
1713
|
+
// filesUploaded?: {
|
|
1714
|
+
// [key: number]: string[];
|
|
1715
|
+
// } | undefined;
|
|
1716
|
+
// };
|
|
1717
|
+
// }>;
|
|
1718
|
+
// currentStageComplete?: boolean;
|
|
1719
|
+
// progressStage: (type: number | "accept" | "reject", e?: {
|
|
1720
|
+
// feedback?: string;
|
|
1721
|
+
// }) => Promise<void>;
|
|
1722
|
+
// };
|
|
1723
|
+
|
|
1724
|
+
// export function useCreateApplicationRenderer({user, listingId, listing, provider, application, applicationId, orgContext}:
|
|
1725
|
+
// {user:UserData, listingId:string, applicationId?: string, listing?: PlacementListing, application?: Partial<Application>,
|
|
1726
|
+
// orgContext?: {details: ProviderData, addresses: {[key: string]: OrganisationAddress}, applicantWorkflows: {[key: string]: ApplicantWorkflow}},
|
|
1727
|
+
// provider?: {details?: ProviderData, profile?: string, id?: string}}) {
|
|
1728
|
+
|
|
1729
|
+
// const firebaseQuery = new FirebaseQuery();
|
|
1730
|
+
|
|
1731
|
+
// let applicationWithoutAdditionalData = {...(application || {})} as any;
|
|
1732
|
+
// delete applicationWithoutAdditionalData.listing;
|
|
1733
|
+
// delete applicationWithoutAdditionalData.address;
|
|
1734
|
+
// delete applicationWithoutAdditionalData.provider;
|
|
1624
1735
|
|
|
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
|
-
|
|
1736
|
+
// const [fApplication, setFApplication] = useState<Partial<Application>>(application ? applicationWithoutAdditionalData : {
|
|
1737
|
+
// uid: user.userType === "Students" ? user.id : undefined,
|
|
1738
|
+
// listingId: listingId,
|
|
1739
|
+
// addressId: listing?.addressId,
|
|
1740
|
+
// stage: 1,
|
|
1741
|
+
// reqUserType: "Students",
|
|
1742
|
+
// status: "draft"});
|
|
1743
|
+
// const [fApplicationId, setFApplicationId] = useState<string|undefined>(applicationId);
|
|
1744
|
+
// const [draftSaved, setDraftSaved] = useState(false);
|
|
1745
|
+
// const [fProvider, setFProvider] = useState<{details?: ProviderData, profile?: string, id?: string}|undefined>(provider);
|
|
1746
|
+
// const [fListing, setFListing] = useState<PlacementListing|false|undefined>(Object.keys(listing || {}).length > 5 ? listing : undefined);
|
|
1747
|
+
// const [student, setStudent] = useState<UserData|undefined>(user.userType === "Students" ? user : undefined);
|
|
1748
|
+
// const [profileUrl, setProfileUrl] = useState<string>();
|
|
1749
|
+
// const [successPopup, setSuccessPopup] = useState<"submitted"|"draftSaved"|"stageComplete"|"outcome">();
|
|
1750
|
+
// const [uploadedFiles, setUploadedFiles] = useState<{[key: string]: FileItem}>();
|
|
1751
|
+
// const [currentStageComplete, setCurrentStageComplete] = useState<boolean>();
|
|
1752
|
+
|
|
1753
|
+
// useEffect(() => {
|
|
1754
|
+
// const getListing = async () => {
|
|
1755
|
+
// console.log("Checking ID")
|
|
1756
|
+
// if (!listingId) return;
|
|
1757
|
+
// console.log("Getting listing")
|
|
1758
|
+
// console.log("LISTING PARAM", listing, Object.keys(listing || {}).length > 5);
|
|
1759
|
+
|
|
1760
|
+
// const listingData = (Object.keys(listing || {}).length > 5) ? listing : (await firebaseQuery.getDocData(["placementListings", listingId]).catch(() => false) as PlacementListing|false);
|
|
1650
1761
|
|
|
1651
|
-
|
|
1762
|
+
// console.log("LISTINGDATA", listingData, Object.keys(listing || {}).length > 5 ? {a: "string"} : "AAA");
|
|
1652
1763
|
|
|
1653
1764
|
|
|
1654
1765
|
|
|
1655
|
-
|
|
1656
|
-
|
|
1766
|
+
// const address = listingData ? (user.product === "providers" && orgContext) ? orgContext.addresses[listingData.addressId || ""] : await firebaseQuery.getDocData(["addresses", listingData.addressId as string]) as Address : undefined;
|
|
1767
|
+
// const workflow = listingData ? (user.product === "providers" && orgContext) ? orgContext.applicantWorkflows[listingData.applicantWorkflowId || ""] as ApplicantWorkflow : await firebaseQuery.getDocData(["applicantWorkflows", listingData.applicantWorkflowId as string]) as ApplicantWorkflow : undefined;
|
|
1657
1768
|
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1769
|
+
// if (workflow && listingData) {
|
|
1770
|
+
// workflow.workflow = await Promise.all(workflow.workflow.map(async (s) => {
|
|
1771
|
+
// const applicantFiles = s.files ? Object.fromEntries(await Promise.all(s.files?.map(async (fileId: string) => {
|
|
1772
|
+
// const file = await firebaseQuery.getDocData(["files", fileId]);
|
|
1773
|
+
// file.url = await getDownloadURL(ref(storage, `providers/${listingData?.providerId}/${file.fileName}`));
|
|
1663
1774
|
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1775
|
+
// return [fileId, file];
|
|
1776
|
+
// }))) : [];
|
|
1777
|
+
// const applicantForms = s.forms ? Object.fromEntries(await Promise.all(s.forms?.map(async (formId: string) => {
|
|
1778
|
+
// return [formId, await firebaseQuery.getDocData(["forms", formId])];
|
|
1779
|
+
// }))) : [];
|
|
1669
1780
|
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1781
|
+
// return {...s, viewableFiles: applicantFiles, formDetails: applicantForms};
|
|
1782
|
+
// }));
|
|
1783
|
+
// delete workflow.id;
|
|
1784
|
+
// }
|
|
1785
|
+
// if (address) {
|
|
1786
|
+
// delete address.id;
|
|
1787
|
+
// }
|
|
1788
|
+
|
|
1789
|
+
// console.log("Setting listing")
|
|
1790
|
+
// setFListing((listingData && workflow) ? {...listingData, ...address, applicantWorkflow: workflow.workflow} as PlacementListing : false);
|
|
1791
|
+
|
|
1792
|
+
|
|
1793
|
+
// if ((fProvider?.id === application?.providerId) && user.product === "providers") {
|
|
1794
|
+
// setFProvider({details: orgContext?.details, id: user.oId});
|
|
1795
|
+
// } else if (listingData && listingData?.providerId) {
|
|
1796
|
+
// console.log("Getting provider from DB");
|
|
1797
|
+
// const provider = await firebaseQuery.getDocData(["providers", listingData.providerId]) as ProviderData;
|
|
1798
|
+
// console.log("Provider", provider);
|
|
1799
|
+
// setFProvider({details: provider, id: listingData.providerId});
|
|
1800
|
+
// }
|
|
1801
|
+
// }
|
|
1802
|
+
|
|
1803
|
+
// getListing();
|
|
1804
|
+
// }, [listingId, listing]);
|
|
1694
1805
|
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1806
|
+
// useEffect(() => {
|
|
1807
|
+
// if (student?.id !== application?.uid) {
|
|
1808
|
+
// if (user.userType === "Students") {
|
|
1809
|
+
// setStudent(user);
|
|
1810
|
+
// } else if (user.product === "providers" && application?.uid) {
|
|
1811
|
+
// firebaseQuery.getDocData(["users", application.uid]).then((s) => setStudent(s as UserData));
|
|
1812
|
+
// }
|
|
1813
|
+
// }
|
|
1814
|
+
// }, []);
|
|
1704
1815
|
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1816
|
+
// useEffect(() => {
|
|
1817
|
+
// setFListing(Object.keys(listing || {}).length > 5 ? listing : undefined);
|
|
1818
|
+
// }, [listing]);
|
|
1708
1819
|
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1820
|
+
// useEffect(() => {
|
|
1821
|
+
// if (provider?.profile) return;
|
|
1822
|
+
// if (!provider?.id) return;
|
|
1712
1823
|
|
|
1713
|
-
|
|
1714
|
-
|
|
1824
|
+
// getDownloadURL(ref(storage, `providers/${provider?.id}/profilePic.png`)).then(setProfileUrl).catch(() => null);
|
|
1825
|
+
// }, [provider]);
|
|
1715
1826
|
|
|
1716
1827
|
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1828
|
+
// useEffect(() => {
|
|
1829
|
+
// console.log("APPLICATIONID", applicationId);
|
|
1830
|
+
// if (!applicationId) {
|
|
1831
|
+
// if (!listingId) return;
|
|
1832
|
+
// firebaseQuery.getDocsWhere("applications", [where("status", "not-in", ["approved", "declined"]), where("uid", "==", user.id), where("listingId", "==", listingId)]).then((existingApplication) => {
|
|
1833
|
+
// console.log("EXISTING", existingApplication);
|
|
1834
|
+
// // get uploaded files
|
|
1835
|
+
// if (existingApplication && Object.keys(existingApplication).length) {
|
|
1836
|
+
// setFApplication(Object.values(existingApplication)[0]);
|
|
1837
|
+
// setFApplicationId(Object.keys(existingApplication)[0]);
|
|
1838
|
+
// }
|
|
1839
|
+
// });
|
|
1840
|
+
// return;
|
|
1841
|
+
// }
|
|
1842
|
+
// if (applicationId) {
|
|
1843
|
+
// setFApplicationId(applicationId);
|
|
1844
|
+
// if (application) {
|
|
1845
|
+
// let applicationWithoutAdditionalData = {...(application || {})} as any;
|
|
1846
|
+
// delete applicationWithoutAdditionalData.listing;
|
|
1847
|
+
// delete applicationWithoutAdditionalData.address;
|
|
1848
|
+
// delete applicationWithoutAdditionalData.provider;
|
|
1849
|
+
// setFApplication(applicationWithoutAdditionalData);
|
|
1850
|
+
// } else {
|
|
1851
|
+
// firebaseQuery.getDocData(["applications", applicationId]).then(setFApplication);
|
|
1852
|
+
// }
|
|
1853
|
+
// }
|
|
1854
|
+
// }, [application, applicationId]);
|
|
1855
|
+
|
|
1856
|
+
// const getCurrentStage = async (stage: number): Promise<{
|
|
1857
|
+
// stage: ApplicantStage; completedSections: {
|
|
1858
|
+
// submitted?: string | undefined;
|
|
1859
|
+
// filesViewed?: string[] | undefined;
|
|
1860
|
+
// formsCompleted?: {
|
|
1861
|
+
// [key: string]: unknown;
|
|
1862
|
+
// } | undefined;
|
|
1863
|
+
// filesUploaded?: {
|
|
1864
|
+
// [key: number]: string[];
|
|
1865
|
+
// } | undefined;
|
|
1866
|
+
// };
|
|
1867
|
+
// }> => {
|
|
1868
|
+
// console.log("fLSITING CURRENT STAGE", fListing);
|
|
1869
|
+
// if (!fListing) throw new Error("Listing deleted");
|
|
1870
|
+
// if (!fListing?.applicantWorkflowId) throw new Error("No workflow stage");
|
|
1871
|
+
|
|
1872
|
+
// const mApplicantWorkflow = (await firebaseQuery.getDocData(["applicantWorkflows", fListing.applicantWorkflowId]) as ApplicantWorkflow);
|
|
1873
|
+
|
|
1874
|
+
// const stageObj = mApplicantWorkflow?.workflow?.find((s) => s.id === stage);
|
|
1875
|
+
|
|
1876
|
+
// if (!stageObj) throw new Error("Can't find stage.");
|
|
1877
|
+
|
|
1878
|
+
// const applicantFiles = stageObj.files ? Object.fromEntries(await Promise.all(stageObj.files?.map(async (fileId) => {
|
|
1879
|
+
// const file = await firebaseQuery.getDocData(["files", fileId]);
|
|
1880
|
+
// file.url = await getDownloadURL(ref(storage, `providers/${mApplicantWorkflow?.oId}/${file.fileName}`));
|
|
1881
|
+
|
|
1882
|
+
// return [fileId, file];
|
|
1883
|
+
// }))) : [];
|
|
1884
|
+
// const applicantForms = stageObj.forms ? Object.fromEntries(await Promise.all(stageObj.forms?.map(async (formId) => {
|
|
1885
|
+
// return [formId, await firebaseQuery.getDocData(["forms", formId])];
|
|
1886
|
+
// }))) : [];
|
|
1887
|
+
|
|
1888
|
+
// stageObj.viewableFiles = applicantFiles;
|
|
1889
|
+
// stageObj.formDetails = applicantForms;
|
|
1779
1890
|
|
|
1780
|
-
|
|
1781
|
-
|
|
1891
|
+
// return {stage: stageObj, completedSections: fApplication?.completedSections?.[stage] || {}};
|
|
1892
|
+
// };
|
|
1782
1893
|
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1894
|
+
// useEffect(() => {
|
|
1895
|
+
// const getUploadedFiles = async () => {
|
|
1896
|
+
// if (!fApplication.completedSections) {
|
|
1897
|
+
// setUploadedFiles({});
|
|
1898
|
+
// return
|
|
1899
|
+
// };
|
|
1789
1900
|
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1901
|
+
// const fileIds = Object.values(fApplication.completedSections)
|
|
1902
|
+
// .flatMap(stageData =>
|
|
1903
|
+
// Object.values(stageData.filesUploaded || {}).flatMap(fileIds => fileIds)
|
|
1904
|
+
// );
|
|
1794
1905
|
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1906
|
+
// const fileDataPromises = fileIds.map(async (fileId) => {
|
|
1907
|
+
// const fileData = await firebaseQuery.getDocData(["files", fileId]) as FileItem;
|
|
1908
|
+
// fileData.url = await getDownloadURL(ref(storage, `userFiles/${fileData.fileName}`));
|
|
1798
1909
|
|
|
1799
|
-
|
|
1800
|
-
|
|
1910
|
+
// return [fileId, fileData] as [string, FileItem]
|
|
1911
|
+
// });
|
|
1801
1912
|
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1913
|
+
// const fileDataArray = await Promise.all(fileDataPromises);
|
|
1914
|
+
// const fileDataObj = Object.fromEntries(fileDataArray)
|
|
1915
|
+
// setUploadedFiles(fileDataObj)
|
|
1916
|
+
// }
|
|
1917
|
+
|
|
1918
|
+
// const addApplication = async () => {
|
|
1919
|
+
// console.log("ADDING APPLICATION");
|
|
1920
|
+
// if (!fListing || !fListing?.id || !fProvider?.id || !student?.id) return;
|
|
1921
|
+
|
|
1922
|
+
// const applicationData = {
|
|
1923
|
+
// uid: student.id,
|
|
1924
|
+
// listingId: fListing?.id,
|
|
1925
|
+
// addressId: fListing.addressId,
|
|
1926
|
+
// applicantWorkflowId: fListing?.applicantWorkflowId,
|
|
1927
|
+
// providerId: fProvider.id,
|
|
1928
|
+
// stage: 1,
|
|
1929
|
+
// status: "draft",
|
|
1930
|
+
// created: (new Date()).toISOString(),
|
|
1931
|
+
// ...fApplication,
|
|
1932
|
+
// } as Partial<Application>;
|
|
1933
|
+
// const mApplicationId = (await firebaseQuery.add(["applications"], applicationData)).id;
|
|
1934
|
+
// console.log("APPLICATION ADDED");
|
|
1935
|
+
// setFApplicationId(mApplicationId);
|
|
1936
|
+
// setFApplication(applicationData);
|
|
1937
|
+
// setDraftSaved(true);
|
|
1938
|
+
// return;
|
|
1939
|
+
// };
|
|
1940
|
+
// getUploadedFiles();
|
|
1941
|
+
|
|
1942
|
+
// console.log("Checking IDs");
|
|
1943
|
+
|
|
1944
|
+
// if (!fListing || !fListing?.id || !fProvider?.id || !student?.id) return;
|
|
1945
|
+
// if (user.product === "providers") return;
|
|
1946
|
+
|
|
1947
|
+
// console.log("Checking dates and sections");
|
|
1948
|
+
// if (!fApplication.completedSections && !fApplication.startDate && !fApplication.endDate) return;
|
|
1949
|
+
|
|
1950
|
+
// console.log("Application updated");
|
|
1951
|
+
// if (!fApplicationId && !applicationId) {
|
|
1952
|
+
// // save new
|
|
1953
|
+
// console.log("Add application")
|
|
1954
|
+
// addApplication();
|
|
1955
|
+
// return;
|
|
1956
|
+
// }
|
|
1957
|
+
// // update
|
|
1958
|
+
// firebaseQuery.update(["applications", (fApplicationId || applicationId) as string], fApplication);
|
|
1959
|
+
// setDraftSaved(true);
|
|
1960
|
+
// }, [fApplication]);
|
|
1850
1961
|
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1962
|
+
// const openSuccessPopup = (type: "submitted"|"draftSaved"|"stageComplete"|"outcome") => {
|
|
1963
|
+
// setSuccessPopup(type);
|
|
1964
|
+
// setTimeout(() => {
|
|
1965
|
+
// // onClose();
|
|
1966
|
+
// }, 1500);
|
|
1967
|
+
// };
|
|
1857
1968
|
|
|
1858
|
-
|
|
1969
|
+
// useEffect(() => {
|
|
1859
1970
|
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1971
|
+
// const areStagesCompleted = async ():Promise<boolean|undefined> => {
|
|
1972
|
+
// if (!fListing) return;
|
|
1973
|
+
// if (fApplication.stage === undefined) return undefined;
|
|
1974
|
+
// const currentStage = await getCurrentStage(fApplication.stage);
|
|
1864
1975
|
|
|
1865
|
-
|
|
1976
|
+
// console.log("Checking current stage is complete");
|
|
1866
1977
|
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1978
|
+
// for (const fileViewed of currentStage.stage?.files || []) {
|
|
1979
|
+
// console.log("Checking file viewed", fileViewed, "in", currentStage?.completedSections?.filesViewed);
|
|
1980
|
+
// if (!currentStage?.completedSections?.filesViewed?.includes(fileViewed)) {
|
|
1981
|
+
// console.log("File not viewed");
|
|
1982
|
+
// return false;
|
|
1983
|
+
// } else {
|
|
1984
|
+
// console.log("File viewed");
|
|
1985
|
+
// }
|
|
1986
|
+
// }
|
|
1987
|
+
// for (const formCompleted of currentStage?.stage?.forms || []) {
|
|
1988
|
+
// console.log("Checking form completed", formCompleted, "in", currentStage?.completedSections?.formsCompleted);
|
|
1989
|
+
|
|
1990
|
+
// if (!Object.keys(currentStage?.completedSections?.formsCompleted || {}).includes(formCompleted)) {
|
|
1991
|
+
// console.log("Form not completed");
|
|
1992
|
+
// return false;
|
|
1993
|
+
// } else {
|
|
1994
|
+
// console.log("Form completed")
|
|
1995
|
+
// }
|
|
1996
|
+
// }
|
|
1997
|
+
// for (let i = 0; i++; i < (currentStage?.stage?.requiredFiles || []).length) {
|
|
1998
|
+
// if (!Object.keys(currentStage?.completedSections?.filesUploaded || {}).includes(i.toString())) {
|
|
1999
|
+
// console.log("Form not uploaded");
|
|
2000
|
+
// return false;
|
|
2001
|
+
// } else {
|
|
2002
|
+
// console.log("Form uploaded");
|
|
2003
|
+
// }
|
|
2004
|
+
// }
|
|
1894
2005
|
|
|
1895
|
-
|
|
1896
|
-
|
|
2006
|
+
// return true;
|
|
2007
|
+
// };
|
|
1897
2008
|
|
|
1898
|
-
|
|
1899
|
-
|
|
2009
|
+
// areStagesCompleted().then(setCurrentStageComplete);
|
|
2010
|
+
// }, [fApplication, fListing])
|
|
1900
2011
|
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
2012
|
+
// const viewFile = (file: string, onOpen: (url: string) => void) => {
|
|
2013
|
+
// if (fApplication.reqUserType !== user.userType) return;
|
|
2014
|
+
// if (fApplication.stage === undefined) throw new Error("Missing applciation stage.")
|
|
2015
|
+
// if (!fListing) throw new Error("No associated listing.");
|
|
1905
2016
|
|
|
1906
|
-
|
|
2017
|
+
// const viewableFiles = fListing?.applicantWorkflow?.find((stage) => stage.id === fApplication.stage)?.viewableFiles;
|
|
1907
2018
|
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
2019
|
+
// setFApplication((a) => {
|
|
2020
|
+
// const oldA = {...a};
|
|
2021
|
+
// const viewedFiles = a.completedSections?.[1]?.filesViewed || [];
|
|
2022
|
+
// if (viewedFiles?.includes(file)) return a;
|
|
1912
2023
|
|
|
1913
|
-
|
|
1914
|
-
|
|
2024
|
+
// viewableFiles?.[file].url && onOpen(viewableFiles?.[file].url);
|
|
2025
|
+
// viewedFiles?.push(file);
|
|
1915
2026
|
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
2027
|
+
// const newA = editNestedObject(["completedSections", 1, "filesViewed"], oldA, viewedFiles) as Partial<Application>;
|
|
2028
|
+
// return newA;
|
|
2029
|
+
// });
|
|
2030
|
+
// };
|
|
2031
|
+
|
|
2032
|
+
// const addFile = (files: string[], fileId: number) => {
|
|
2033
|
+
// if (fApplication.reqUserType !== user.userType) throw new Error(`Incorrect user type. Expected ${fApplication.reqUserType}, got: ${user.userType}`);
|
|
2034
|
+
// if (fApplication.stage === undefined) throw new Error("Missing applciation stage.")
|
|
2035
|
+
|
|
2036
|
+
// if (!files.length) throw new Error("No files to upload");
|
|
2037
|
+
// setFApplication((a) => editNestedObject(["completedSections", fApplication.stage as number, "filesUploaded", fileId], a, files) as Application);
|
|
2038
|
+
// };
|
|
2039
|
+
|
|
2040
|
+
// const setFormComplete = (formId: string, e: {[key: string]: unknown}) => {
|
|
2041
|
+
// if (fApplication.reqUserType !== user.userType) throw new Error(`Incorrect user type. Expected ${fApplication.reqUserType}, got: ${user.userType}`);
|
|
2042
|
+
// if (fApplication.stage === undefined) throw new Error("Missing applciation stage.")
|
|
2043
|
+
// setFApplication((a) => editNestedObject(["completedSections", fApplication.stage as number, "formsCompleted", formId], a, e) as Application);
|
|
2044
|
+
// };
|
|
1934
2045
|
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
2046
|
+
// const successText = {
|
|
2047
|
+
// submitted: {
|
|
2048
|
+
// title: "Application submitted",
|
|
2049
|
+
// desc: "We've sent your application to the placement provider. You will hear what the next steps are soon.",
|
|
2050
|
+
// },
|
|
2051
|
+
// draftSaved: {
|
|
2052
|
+
// title: "Draft saved",
|
|
2053
|
+
// desc: "Your draft has been saved. Go to the 'Applications' section from your home screen to edit.",
|
|
2054
|
+
// },
|
|
2055
|
+
// stageComplete: {
|
|
2056
|
+
// title: "Stage complete",
|
|
2057
|
+
// desc: "We have sent this to the next stage in the application process. We will update you with any progress.",
|
|
2058
|
+
// },
|
|
2059
|
+
// outcome: {
|
|
2060
|
+
// title: "Outcome submitted",
|
|
2061
|
+
// desc: "We have sent the student an email with the outcome of their application.",
|
|
2062
|
+
// },
|
|
2063
|
+
// };
|
|
2064
|
+
|
|
2065
|
+
// const onFApply = async (draft?: boolean) => {
|
|
2066
|
+
// if (draft) {
|
|
2067
|
+
// openSuccessPopup("draftSaved")
|
|
2068
|
+
// return;
|
|
2069
|
+
// }
|
|
2070
|
+
|
|
2071
|
+
// if (!fApplicationId) return;
|
|
1961
2072
|
|
|
1962
|
-
|
|
1963
|
-
|
|
2073
|
+
// // Check all items have been filled in.
|
|
2074
|
+
// if (!fApplication.startDate || !fApplication.endDate) throw new Error("Please select dates for your placement.");
|
|
1964
2075
|
|
|
1965
|
-
|
|
2076
|
+
// await executeCallable("applications-submit", {applicationId: fApplicationId});
|
|
1966
2077
|
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
2078
|
+
// const newApplication = await firebaseQuery.getDocData(["applications", fApplicationId]) as Application;
|
|
2079
|
+
// setFApplication(newApplication);
|
|
2080
|
+
// openSuccessPopup("submitted")
|
|
2081
|
+
// };
|
|
1971
2082
|
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
2083
|
+
// const progressStage = async (type: number|"accept"|"reject", e?: {feedback?: string}) => {
|
|
2084
|
+
// // Check all stages completed.
|
|
2085
|
+
// if (!fApplicationId) return;
|
|
2086
|
+
// if (!currentStageComplete) throw new Error("Complete all forms before submitting.");
|
|
2087
|
+
// if (fApplication.reqUserType !== user.userType) throw new Error(`Incorrect user type. Expected ${fApplication.reqUserType}, got: ${user.userType}`);
|
|
2088
|
+
// if (fApplication.stage === undefined) throw new Error("Missing applciation stage.")
|
|
2089
|
+
|
|
2090
|
+
// await executeCallable("applications-changeStage", {applicationId: fApplicationId, type: type, feedback: e?.feedback});
|
|
2091
|
+
// const newApplication = await firebaseQuery.getDocData(["applications", fApplicationId]) as Application;
|
|
2092
|
+
// setFApplication(newApplication);
|
|
2093
|
+
// };
|
|
1983
2094
|
|
|
1984
2095
|
|
|
1985
|
-
|
|
1986
|
-
}
|
|
2096
|
+
// return {successText, onFApply, progressStage, currentStageComplete, uploadedFiles, getCurrentStage, setFormComplete, viewFile, addFile, setSuccessPopup, openSuccessPopup, setFApplication, fApplication, draftSaved, profileUrl, successPopup, fApplicationId, fListing, student, fProvider}
|
|
2097
|
+
// }
|
|
1987
2098
|
|
|
1988
2099
|
export function useProposePlacementRenderer({user, orgContext, placement}:
|
|
1989
2100
|
{user:UserData, orgContext?: {details: InstituteData, userGroups: {[key:string]: UserGroupData}, forms: {[key:string]: unknown}, cohorts: {[key:string]: CohortData}},
|
|
@@ -2046,11 +2157,9 @@ export function useProposePlacementRenderer({user, orgContext, placement}:
|
|
|
2046
2157
|
|
|
2047
2158
|
const submitSection = (type:"dates"|"provider"|"address", data:{[key:string]:unknown}) => {
|
|
2048
2159
|
setFormData((f) => {
|
|
2049
|
-
const { id, ...values } = data
|
|
2050
2160
|
return {
|
|
2051
2161
|
...f,
|
|
2052
|
-
...
|
|
2053
|
-
id: (placement?.placementId || formData?.id) as string
|
|
2162
|
+
...data
|
|
2054
2163
|
} as StudentPlacementData;
|
|
2055
2164
|
});
|
|
2056
2165
|
if (placement?.placementId && type === "dates") {
|
|
@@ -2137,8 +2246,8 @@ type CreateCohortRendererParams = {
|
|
|
2137
2246
|
initialData ?: CohortData
|
|
2138
2247
|
}
|
|
2139
2248
|
|
|
2140
|
-
export type CreateCohortStages = "info"|"name"|"placementType"|"review";
|
|
2141
|
-
const cohortStages = ["info", "name", "placementType", "review", "created"];
|
|
2249
|
+
export type CreateCohortStages = "info"|"name"|"placementType"|"database"|"review";
|
|
2250
|
+
const cohortStages = ["info", "name", "placementType", "database", "review", "created"];
|
|
2142
2251
|
|
|
2143
2252
|
const defaultCohortData:CohortData = {
|
|
2144
2253
|
name: "",
|
|
@@ -3039,41 +3148,42 @@ function useGenericWorkflowEditor({user, initialData, defaultData, onSubmit}: Ge
|
|
|
3039
3148
|
onDeleteArrow, fWorkflowNodes, containerRef, setError, setArrows, setFWorkflowNodes}});
|
|
3040
3149
|
}
|
|
3041
3150
|
|
|
3042
|
-
type
|
|
3151
|
+
type InstituteProviderContactUploadParams = {
|
|
3043
3152
|
user: UserData,
|
|
3044
3153
|
onComplete?: () => void
|
|
3045
3154
|
}
|
|
3046
3155
|
|
|
3047
|
-
export type
|
|
3048
|
-
|
|
3049
|
-
|
|
3156
|
+
export type InstituteProviderContactUpload = {
|
|
3157
|
+
business: string;
|
|
3158
|
+
forename?: string;
|
|
3159
|
+
surname?: string;
|
|
3050
3160
|
email: string;
|
|
3051
3161
|
phone?: string;
|
|
3052
|
-
addressOne
|
|
3053
|
-
addressTwo
|
|
3054
|
-
city
|
|
3055
|
-
postcode
|
|
3056
|
-
country
|
|
3162
|
+
addressOne?: string;
|
|
3163
|
+
addressTwo?: string;
|
|
3164
|
+
city?: string;
|
|
3165
|
+
postcode?: string;
|
|
3166
|
+
country?: string;
|
|
3057
3167
|
};
|
|
3058
3168
|
|
|
3059
|
-
export function
|
|
3169
|
+
export function useInstituteProviderContactsHandler({user}: InstituteProviderContactUploadParams) {
|
|
3060
3170
|
const [emptyCellsWarning, setEmptyCellsWarning] = useState(false);
|
|
3061
3171
|
const [alert, setAlert] = useState<{severity: "warning"|"error"|"success"|"info", msg: string}>();
|
|
3062
3172
|
|
|
3063
|
-
const requiredFields = ["
|
|
3173
|
+
const requiredFields = ["business", "forename", "email"];
|
|
3064
3174
|
const {execute} = useExecuteCallableJob({user: user});
|
|
3065
3175
|
|
|
3066
|
-
const checkData = (
|
|
3176
|
+
const checkData = (providerContacts: InstituteProviderContactUpload[]) => {
|
|
3067
3177
|
setAlert(undefined);
|
|
3068
3178
|
|
|
3069
|
-
|
|
3179
|
+
providerContacts = providerContacts.filter((u) => Object.entries(u).some(([, v]) => v));
|
|
3070
3180
|
|
|
3071
|
-
if (!Object.entries(
|
|
3181
|
+
if (!Object.entries(providerContacts)) {
|
|
3072
3182
|
return [];
|
|
3073
3183
|
}
|
|
3074
|
-
console.log("P",
|
|
3184
|
+
console.log("P", providerContacts);
|
|
3075
3185
|
|
|
3076
|
-
if (
|
|
3186
|
+
if (providerContacts.filter((u) => u.email).length < providerContacts.length) {
|
|
3077
3187
|
setAlert({msg: "Your data contains missing email addresses.", severity: "error"});
|
|
3078
3188
|
return false;
|
|
3079
3189
|
}
|
|
@@ -3081,18 +3191,18 @@ export function useInstitutePlacementListingHandler({user}: InstitutePlacementLi
|
|
|
3081
3191
|
let emptyOptionalCell = false;
|
|
3082
3192
|
let emptyRequiredCell = false;
|
|
3083
3193
|
|
|
3084
|
-
for (const
|
|
3085
|
-
if (!checkEmailValidity(
|
|
3194
|
+
for (const providerContact of providerContacts ) {
|
|
3195
|
+
if (!checkEmailValidity(providerContact)) {
|
|
3086
3196
|
return false;
|
|
3087
3197
|
}
|
|
3088
3198
|
|
|
3089
|
-
if (Object.keys(
|
|
3199
|
+
if (Object.keys(providerContact).includes("")) {
|
|
3090
3200
|
setAlert({msg: "Data cannot be uploaded in unnamed columns.", severity: "error"});
|
|
3091
3201
|
return false;
|
|
3092
3202
|
}
|
|
3093
3203
|
|
|
3094
|
-
for (const field in
|
|
3095
|
-
if (!
|
|
3204
|
+
for (const field in providerContact) {
|
|
3205
|
+
if (!providerContact[field]) {
|
|
3096
3206
|
if (requiredFields.includes(field)) {
|
|
3097
3207
|
setAlert({msg: "All users must contain "+requiredFields.join(", "), severity: "error"});
|
|
3098
3208
|
emptyRequiredCell = true;
|
|
@@ -3113,44 +3223,30 @@ export function useInstitutePlacementListingHandler({user}: InstitutePlacementLi
|
|
|
3113
3223
|
} else {
|
|
3114
3224
|
setEmptyCellsWarning(false);
|
|
3115
3225
|
}
|
|
3116
|
-
return
|
|
3226
|
+
return providerContacts;
|
|
3117
3227
|
};
|
|
3118
3228
|
|
|
3119
|
-
const checkEmailValidity = (
|
|
3120
|
-
if (!validateEmail(
|
|
3121
|
-
setAlert({msg: `Error in email formatting: ${
|
|
3229
|
+
const checkEmailValidity = (providerContact: InstituteProviderContactUpload) => {
|
|
3230
|
+
if (!validateEmail(providerContact.email as string)) {
|
|
3231
|
+
setAlert({msg: `Error in email formatting: ${providerContact.email}. Amend errors and reupload.`, severity: "error"});
|
|
3122
3232
|
return false;
|
|
3123
3233
|
}
|
|
3124
3234
|
return true;
|
|
3125
3235
|
};
|
|
3126
3236
|
|
|
3127
|
-
const
|
|
3128
|
-
let
|
|
3129
|
-
console.log("PP",
|
|
3237
|
+
const uploadProviderContacts = async (providers: InstituteProviderContactUpload[], schoolId?: string) => {
|
|
3238
|
+
let fProviders:InstituteProviderContactUpload[] = [];
|
|
3239
|
+
console.log("PP", providers);
|
|
3130
3240
|
|
|
3131
|
-
const cleanUpload = checkData(
|
|
3241
|
+
const cleanUpload = checkData(providers);
|
|
3132
3242
|
if (!cleanUpload) {
|
|
3133
3243
|
return false;
|
|
3134
3244
|
}
|
|
3135
|
-
|
|
3245
|
+
fProviders = cleanUpload;
|
|
3136
3246
|
|
|
3137
3247
|
setAlert(undefined);
|
|
3138
|
-
if (
|
|
3139
|
-
|
|
3140
|
-
({
|
|
3141
|
-
name: v.provider,
|
|
3142
|
-
title: v.jobTitle,
|
|
3143
|
-
providerEmail: v.email,
|
|
3144
|
-
providerPhone: v.phone,
|
|
3145
|
-
["address-line1"]: v.addressOne,
|
|
3146
|
-
["address-line2"]: v.addressTwo,
|
|
3147
|
-
locality: v.city,
|
|
3148
|
-
postal_code: v.postcode,
|
|
3149
|
-
country: v.country,
|
|
3150
|
-
}));
|
|
3151
|
-
console.log("P", placements);
|
|
3152
|
-
console.log("callable params", {placements: formattedPlacements, instituteId: user.product === "admin" ? "admin" : user.oId});
|
|
3153
|
-
execute("placementListing-add", {data: formattedPlacements, instituteId: user.product === "admin" ? "admin" : user.oId});
|
|
3248
|
+
if (fProviders.length) {
|
|
3249
|
+
execute("providerContacts-add", {providerContacts: fProviders, instituteId: user.product === "admin" ? "admin" : user.oId, schoolId: schoolId});
|
|
3154
3250
|
}
|
|
3155
3251
|
return true;
|
|
3156
3252
|
};
|
|
@@ -3160,7 +3256,7 @@ export function useInstitutePlacementListingHandler({user}: InstitutePlacementLi
|
|
|
3160
3256
|
setEmptyCellsWarning(false);
|
|
3161
3257
|
};
|
|
3162
3258
|
|
|
3163
|
-
return ({...{
|
|
3259
|
+
return ({...{uploadProviderContacts, alert, onChange}});
|
|
3164
3260
|
}
|
|
3165
3261
|
|
|
3166
3262
|
|
|
@@ -3175,7 +3271,7 @@ export function useGetIndividualPlacementForPlacementPage({user, placementId, or
|
|
|
3175
3271
|
const [disableEmail, setDisableEmail] = useState({parent: false, provider: false});
|
|
3176
3272
|
const [rejectELIPopup, setRejectELIPopup] = useState(false);
|
|
3177
3273
|
const [eliPopupOpen, setEliPopupOpen] = useState(false);
|
|
3178
|
-
const [
|
|
3274
|
+
const [eliData, setELIData] = useState<string>();
|
|
3179
3275
|
|
|
3180
3276
|
const [rejectExternalDocPopup, setRejectExternalDocPopup] = useState<"riskAssessment"|"dbsCheck"|false>(false);
|
|
3181
3277
|
const [externalDocPopupOpen, setExternalDocPopupOpen] = useState<"riskAssessment"|"dbsCheck"|false>(false);
|
|
@@ -3356,10 +3452,10 @@ export function useGetIndividualPlacementForPlacementPage({user, placementId, or
|
|
|
3356
3452
|
setShareStudentRequestPopup(true);
|
|
3357
3453
|
}
|
|
3358
3454
|
if (e === "noInsurance") {
|
|
3359
|
-
if (!
|
|
3360
|
-
const storageRef = ref(storage, `insurance/${placement.
|
|
3361
|
-
const file = await getDownloadURL(storageRef);
|
|
3362
|
-
|
|
3455
|
+
if (!eliData) {
|
|
3456
|
+
const storageRef = ref(storage, `insurance/${placement.providerContactId}.pdf`);
|
|
3457
|
+
const file = await getDownloadURL(storageRef).catch(() => placement.insuranceSkippedReason);
|
|
3458
|
+
setELIData(file);
|
|
3363
3459
|
}
|
|
3364
3460
|
setEliPopupOpen(true);
|
|
3365
3461
|
}
|
|
@@ -3391,15 +3487,15 @@ export function useGetIndividualPlacementForPlacementPage({user, placementId, or
|
|
|
3391
3487
|
|
|
3392
3488
|
const approveELI = async () => {
|
|
3393
3489
|
if (!placement) return;
|
|
3394
|
-
await executeCallable("insurance-approve", {oId: user.oId,
|
|
3490
|
+
await executeCallable("insurance-approve", {oId: user.oId, providerContactId: placement.providerContactId});
|
|
3395
3491
|
setEliPopupOpen(false);
|
|
3396
3492
|
};
|
|
3397
3493
|
|
|
3398
3494
|
const rejectELI = async ({reason}:{reason: string}) => {
|
|
3399
3495
|
if (!placement || !institute) return;
|
|
3400
3496
|
|
|
3401
|
-
console.log("Reject", {reason: reason, placement: placement, instituteName: institute.name
|
|
3402
|
-
await executeCallable("insurance-reject", {reason: reason, placementId: placementId, instituteName: institute.name
|
|
3497
|
+
console.log("Reject", {reason: reason, placement: placement, instituteName: institute.name});
|
|
3498
|
+
await executeCallable("insurance-reject", {reason: reason, placementId: placementId, instituteName: institute.name});
|
|
3403
3499
|
setRejectELIPopup(false);
|
|
3404
3500
|
setEliPopupOpen(false);
|
|
3405
3501
|
};
|
|
@@ -3420,10 +3516,12 @@ export function useGetIndividualPlacementForPlacementPage({user, placementId, or
|
|
|
3420
3516
|
const manuallyConfigureProvider = async () => {
|
|
3421
3517
|
if (!placement) return;
|
|
3422
3518
|
if (!placement.providerId) {
|
|
3423
|
-
const res = await executeCallable("
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3519
|
+
const res = await executeCallable("providerContacts-uploadProviderDetails", {
|
|
3520
|
+
placement: {
|
|
3521
|
+
id: placementId,
|
|
3522
|
+
data: Object.fromEntries(Object.entries(placement).filter(([k]) => k !== "contactId")),
|
|
3523
|
+
stage: wStage,
|
|
3524
|
+
},
|
|
3427
3525
|
skipSearch: true}).catch((e) => {
|
|
3428
3526
|
throw e;
|
|
3429
3527
|
});
|
|
@@ -3447,7 +3545,7 @@ export function useGetIndividualPlacementForPlacementPage({user, placementId, or
|
|
|
3447
3545
|
await executeCallable("placement-withdraw", {placementId: placementId});
|
|
3448
3546
|
}
|
|
3449
3547
|
|
|
3450
|
-
return {placement, wStage, student, workflow, editable, withdrawFromPlacementPopup, addOnboardingDocsPopup, setAddOnboardingDocsPopup, dismissOnboardingPopup, setDismissOnboardingPopup, setWithdrawFromPlacementPopup, withdrawFromPlacement, onFlagClick, setUploadInsurance, setUploadProviderDocPopup, setUploadRA, setUploadDBS, onboardingStatus, setSkipStagePopup, onboardingPopup, setViewExternalLinkPopup, setOnboardingPopup, setRejectELIPopup,
|
|
3548
|
+
return {placement, wStage, student, workflow, editable, withdrawFromPlacementPopup, addOnboardingDocsPopup, setAddOnboardingDocsPopup, dismissOnboardingPopup, setDismissOnboardingPopup, setWithdrawFromPlacementPopup, withdrawFromPlacement, onFlagClick, setUploadInsurance, setUploadProviderDocPopup, setUploadRA, setUploadDBS, onboardingStatus, setSkipStagePopup, onboardingPopup, setViewExternalLinkPopup, setOnboardingPopup, setRejectELIPopup, eliData, riskAssessmentURL, dbsCheckURL, setExternalLinkCopied, skipStagePopup, snackbar, setSnackbar, cohort, disableEmail, rejectELIPopup, eliPopupOpen, rejectExternalDocPopup, externalDocPopupOpen, viewExternalLinkPopup, externalLinkCopied, uploadInsurance, uploadRA, uploadDBS, editStage, sendEmail, canEdit, approveELI, setEliPopupOpen, uploadProviderDocPopup, rejectELI, setRejectExternalDocPopup, setExternalDocPopupOpen, approveProviderDoc, rejectProviderDoc, manuallyConfigureProvider, institute, shareStudentRequestPopup, setShareStudentRequestPopup}
|
|
3451
3549
|
}
|
|
3452
3550
|
|
|
3453
3551
|
export function useOnboardingPopup({onboarding, providerId, placementId, user, onClose}:{onboarding: (
|
|
@@ -3810,17 +3908,8 @@ export function useLoadListings(user: UserData, queryConstraint?: QueryConstrain
|
|
|
3810
3908
|
};
|
|
3811
3909
|
|
|
3812
3910
|
useEffect(() => {
|
|
3813
|
-
let unsubscribe: () => void;
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
3911
|
|
|
3817
3912
|
loadListings();
|
|
3818
|
-
|
|
3819
|
-
return () => {
|
|
3820
|
-
if (unsubscribe) {
|
|
3821
|
-
unsubscribe(); // Unsubscribe from the snapshot listener when the component unmounts
|
|
3822
|
-
}
|
|
3823
|
-
};
|
|
3824
3913
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3825
3914
|
}, [queryConstraints]);
|
|
3826
3915
|
|
|
@@ -3911,17 +4000,7 @@ export function useLoadProviderPlacements(user: UserData, queryConstraint?: Quer
|
|
|
3911
4000
|
};
|
|
3912
4001
|
|
|
3913
4002
|
useEffect(() => {
|
|
3914
|
-
let unsubscribe: () => void;
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
4003
|
loadListings();
|
|
3919
|
-
|
|
3920
|
-
return () => {
|
|
3921
|
-
if (unsubscribe) {
|
|
3922
|
-
unsubscribe(); // Unsubscribe from the snapshot listener when the component unmounts
|
|
3923
|
-
}
|
|
3924
|
-
};
|
|
3925
4004
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3926
4005
|
}, [queryConstraints]);
|
|
3927
4006
|
|
|
@@ -4016,14 +4095,7 @@ export function useLoadApplications({user, applicationType, listingId, queryCons
|
|
|
4016
4095
|
};
|
|
4017
4096
|
|
|
4018
4097
|
useEffect(() => {
|
|
4019
|
-
let unsubscribe: () => void;
|
|
4020
|
-
|
|
4021
4098
|
loadApplications();
|
|
4022
|
-
return () => {
|
|
4023
|
-
if (unsubscribe) {
|
|
4024
|
-
unsubscribe(); // Unsubscribe from the snapshot listener when the component unmounts
|
|
4025
|
-
}
|
|
4026
|
-
};
|
|
4027
4099
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
4028
4100
|
}, [type, queryConstraints]);
|
|
4029
4101
|
|
|
@@ -4060,7 +4132,7 @@ export type DataViewerPaginater = {
|
|
|
4060
4132
|
sorts?: Sorts
|
|
4061
4133
|
}
|
|
4062
4134
|
|
|
4063
|
-
export function useDataViewerPaginator({view: initialView, sorts, queryLimit, additionalEntryProcessing, formatItems, snapshot, filters: initialFilters, onSearch, data}:DataViewerPaginater) {
|
|
4135
|
+
export function useDataViewerPaginator({view: initialView, sorts, queryLimit=10, additionalEntryProcessing, formatItems, snapshot, filters: initialFilters, onSearch, data}:DataViewerPaginater) {
|
|
4064
4136
|
const [tableData, setTableData] = useState<{[key:string]:{[key:string]: unknown}}>(Array.isArray(data) ? Object.fromEntries(Object.entries(data).slice(0, queryLimit)) : {});
|
|
4065
4137
|
const [page, setPage] = useState([1, 0]);
|
|
4066
4138
|
const [view, setView] = useState(initialView);
|
|
@@ -4117,7 +4189,7 @@ export function useDataViewerPaginator({view: initialView, sorts, queryLimit, ad
|
|
|
4117
4189
|
const getDataFromQuery = async (
|
|
4118
4190
|
itemList: {[key: string]: any} = {}, currentQueryAnchor=queryAnchor, cursorDirection?:"increase"|"decrease"|undefined, prevEntries=prevEntryIds, loadMoreFromQuery=false):Promise<any> => {
|
|
4119
4191
|
|
|
4120
|
-
if (!filters) return;
|
|
4192
|
+
// if (!filters) return;
|
|
4121
4193
|
setLoading(true);
|
|
4122
4194
|
if (!Array.isArray(data)) {
|
|
4123
4195
|
setTableDataFromDefinedData();
|
|
@@ -4127,8 +4199,8 @@ export function useDataViewerPaginator({view: initialView, sorts, queryLimit, ad
|
|
|
4127
4199
|
|
|
4128
4200
|
if (onSearch && (searchString || sort)) {
|
|
4129
4201
|
if (typeof onSearch === "boolean") 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.");
|
|
4130
|
-
const
|
|
4131
|
-
const dataWithAdditionalProcessing: [string, any][] = await Promise.all(Object.entries(
|
|
4202
|
+
const searchData = await onSearch(searchString, sort, page[0], filters, queryLimit);
|
|
4203
|
+
const dataWithAdditionalProcessing: [string, any][] = await Promise.all(Object.entries(searchData).map(async ([k, v]) => [k, await processedData(k, v)]));
|
|
4132
4204
|
|
|
4133
4205
|
setTableData((old) => {
|
|
4134
4206
|
if (view === "table") {
|
|
@@ -4287,8 +4359,11 @@ export function useDataViewerPaginator({view: initialView, sorts, queryLimit, ad
|
|
|
4287
4359
|
Object.keys(itemList).length === 0 &&
|
|
4288
4360
|
currentQueryAnchor.endQueryPos+1 === data.length &&
|
|
4289
4361
|
page[0] > 1) {
|
|
4290
|
-
|
|
4362
|
+
if (view === "table") {
|
|
4363
|
+
setTableData({});
|
|
4364
|
+
}
|
|
4291
4365
|
setQueryAnchor((a) => ({...a, startKey: ""}));
|
|
4366
|
+
setLoading("loaded");
|
|
4292
4367
|
return;
|
|
4293
4368
|
}
|
|
4294
4369
|
|
|
@@ -4327,8 +4402,25 @@ export function useDataViewerPaginator({view: initialView, sorts, queryLimit, ad
|
|
|
4327
4402
|
}, [filters]);
|
|
4328
4403
|
|
|
4329
4404
|
useEffect(() => {
|
|
4405
|
+
console.log("View reset.")
|
|
4330
4406
|
reset();
|
|
4331
|
-
}, [view
|
|
4407
|
+
}, [view]);
|
|
4408
|
+
|
|
4409
|
+
useEffect(() => {
|
|
4410
|
+
console.log("search reset.")
|
|
4411
|
+
reset();
|
|
4412
|
+
}, [searchString]);
|
|
4413
|
+
|
|
4414
|
+
useEffect(() => {
|
|
4415
|
+
console.log("data reset.")
|
|
4416
|
+
reset();
|
|
4417
|
+
}, [data]);
|
|
4418
|
+
|
|
4419
|
+
useEffect(() => {
|
|
4420
|
+
console.log("sort reset.")
|
|
4421
|
+
reset();
|
|
4422
|
+
}, [sort]);
|
|
4423
|
+
|
|
4332
4424
|
|
|
4333
4425
|
// Fetch new data when queries or page change
|
|
4334
4426
|
useEffect(() => {
|