placementt-core 11.0.803 → 11.0.892

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/hooks.js CHANGED
@@ -7,20 +7,19 @@ exports.useRefDimensions = void 0;
7
7
  exports.useStudentPlacementList = useStudentPlacementList;
8
8
  exports.useOldInstitutePlacementList = useOldInstitutePlacementList;
9
9
  exports.useNewInstitutePlacementList = useNewInstitutePlacementList;
10
+ exports.useAlumniPaginator = useAlumniPaginator;
10
11
  exports.useVeryOldInstitutePlacementList = useVeryOldInstitutePlacementList;
11
12
  exports.useFilterTablePaginator = useFilterTablePaginator;
12
- exports.usePlacementListingPaginator = usePlacementListingPaginator;
13
+ exports.useProviderContactPaginator = useProviderContactPaginator;
13
14
  exports.useCohortUserPaginator = useCohortUserPaginator;
14
15
  exports.useAdmissionsPaginator = useAdmissionsPaginator;
15
16
  exports.useLazyLoadQueryList = useLazyLoadQueryList;
16
- exports.usePublicPlacementListingLoader = usePublicPlacementListingLoader;
17
- exports.useCreateApplicationRenderer = useCreateApplicationRenderer;
18
17
  exports.useProposePlacementRenderer = useProposePlacementRenderer;
19
18
  exports.useCreateCohortRenderer = useCreateCohortRenderer;
20
19
  exports.useUserUploadHandler = useUserUploadHandler;
21
20
  exports.useWorkflowEditor = useWorkflowEditor;
22
21
  exports.useApplicantWorkflowEditor = useApplicantWorkflowEditor;
23
- exports.useInstitutePlacementListingHandler = useInstitutePlacementListingHandler;
22
+ exports.useInstituteProviderContactsHandler = useInstituteProviderContactsHandler;
24
23
  exports.useGetIndividualPlacementForPlacementPage = useGetIndividualPlacementForPlacementPage;
25
24
  exports.useOnboardingPopup = useOnboardingPopup;
26
25
  exports.useLoadAddresses = useLoadAddresses;
@@ -314,6 +313,75 @@ function useNewInstitutePlacementList({ id, user, filters, view, cohort, queryCo
314
313
  }, [user, queryConstraints, cohort]);
315
314
  return { tableData, page, loading, updateSearch, setFilters, setView, pageUp, pageDown, sorts, updateSort, sort };
316
315
  }
316
+ function useAlumniPaginator({ user, alumniConvoUser, filters, view, school, queryConstraints, ql = DEFAULTQUERYLIMIT }) {
317
+ const [query, setQuery] = (0, react_1.useState)();
318
+ const sorts = {};
319
+ const { tableData, pageUp, pageDown, setFilters, page, setView, loading } = useDataViewerPaginator({ view, filters, sorts, queryLimit: ql, data: query });
320
+ const firebaseQuery = new firebaseQuery_1.default();
321
+ (0, react_1.useEffect)(() => {
322
+ const createQuery = async () => {
323
+ // Sets the query of for the DataViewerPaginator
324
+ const getQueryAccess = async () => {
325
+ var _a;
326
+ const constraints = [];
327
+ if (user) {
328
+ constraints.push(["oId", "==", user.oId]);
329
+ if (user.userGroup === "admin" && user.userType === "Staff")
330
+ return constraints;
331
+ if (user.userType === "Staff") {
332
+ if (user.viewSchools === "all")
333
+ return constraints;
334
+ if (user.viewSchools === "none")
335
+ return false;
336
+ if (user.viewSchools === "some") {
337
+ if (!school)
338
+ return false;
339
+ if ((_a = user === null || user === void 0 ? void 0 : user.visibleSchools) === null || _a === void 0 ? void 0 : _a.includes(school))
340
+ return constraints;
341
+ }
342
+ return false;
343
+ }
344
+ return false;
345
+ }
346
+ if (alumniConvoUser) {
347
+ constraints.push(["oId", "==", alumniConvoUser.oId]);
348
+ console.log("ALUMNI CONVO USER");
349
+ if ((school || alumniConvoUser.schoolId) && school === alumniConvoUser.schoolId)
350
+ return constraints;
351
+ console.log("ALUMNI ACCESS TRUE");
352
+ if (alumniConvoUser.schoolId) {
353
+ const school = await firebaseQuery.getDocData(["schools", alumniConvoUser.schoolId]);
354
+ console.log("SCHOOL ACCESS", school, school.alumniConversations);
355
+ return school.alumniConversations ? constraints : false;
356
+ }
357
+ else {
358
+ const institute = await firebaseQuery.getDocData(["institutes", alumniConvoUser.oId]);
359
+ return institute.alumniConversations ? constraints : false;
360
+ }
361
+ }
362
+ return false;
363
+ };
364
+ const constraints = await getQueryAccess();
365
+ console.log("CONSTRAINTS", constraints);
366
+ if (!constraints)
367
+ return;
368
+ school && constraints.push(["schoolId", "==", school]);
369
+ queryConstraints && constraints.unshift(...queryConstraints);
370
+ return constraints;
371
+ };
372
+ console.log("Creating query");
373
+ createQuery().then((constraints) => {
374
+ setQuery([{
375
+ path: ["alumni"],
376
+ where: constraints
377
+ }]);
378
+ });
379
+ }, [user, queryConstraints, school]);
380
+ (0, react_1.useEffect)(() => {
381
+ console.log("Alumni data", query, tableData);
382
+ }, [tableData]);
383
+ return { tableData, page, loading, setFilters, setView, pageUp, pageDown, sorts };
384
+ }
317
385
  const algoliaPlacementSearch = async (user, query, sort, page, filters, limit, cohort, inProgress) => {
318
386
  const algoliaClient = (0, algoliasearch_1.default)(process.env.NODE_ENV === "development" ? "A0ZB50I7VS" : "XMPXCMUUOJ", user.algoliaKey);
319
387
  const placementsIndex = algoliaClient.initIndex(sort ? Object.values(sort[1]).join("_") : "placements");
@@ -714,181 +782,31 @@ function useFilterTablePaginator({ data }) {
714
782
  }, [page]);
715
783
  return ({ ...{ tableData, setPage, setFilters, page } });
716
784
  }
717
- function usePlacementListingPaginator({ data, user }) {
718
- const [tableData, setTableData] = (0, react_1.useState)({});
719
- const [page, setPage] = (0, react_1.useState)([1, 0]);
720
- const [filters, setFilters] = (0, react_1.useState)();
721
- const [queryAnchor, setQueryAnchor] = (0, react_1.useState)({ startKey: "", endKey: "", startQueryPos: 0, endQueryPos: 0 });
722
- const [prevEntryIds, setPrevEntryIds] = (0, react_1.useState)({});
785
+ function useProviderContactPaginator({ data, user, view, filters }) {
786
+ const [query, setQuery] = (0, react_1.useState)();
723
787
  const firebaseQuery = new firebaseQuery_1.default();
724
- const getDataFromQuery = async (itemList = {}, currentQueryAnchor = queryAnchor, cursorDirection, prevEntries = prevEntryIds, loadMoreFromQuery = false) => {
725
- let cursorPos;
726
- if (page[0] > page[1]) {
727
- cursorPos = currentQueryAnchor.endQueryPos;
728
- }
729
- else {
730
- cursorPos = currentQueryAnchor.startQueryPos;
731
- }
732
- const querySchema = data === null || data === void 0 ? void 0 : data[cursorPos];
733
- const createQuery = (queryData) => {
734
- const constraints = [
735
- (0, firestore_1.where)("savedById", "==", user.userType === "Staff" ? user.oId : user.id),
736
- (0, firestore_1.where)("savedByProduct", "==", user.product),
737
- (0, firestore_1.where)("savedByUserType", "==", user.userType === "Staff" ? "Organisation" : "Student"),
738
- ];
739
- if (user.userType === "Students") {
740
- constraints.push((0, firestore_1.where)("listed", "==", true));
741
- }
742
- (queryData === null || queryData === void 0 ? void 0 : queryData.where) && queryData.where.forEach((w) => {
743
- constraints.push((0, firestore_1.where)(...w));
744
- });
745
- filters && Object.entries(filters).forEach(([key, value]) => {
746
- constraints.push((0, firestore_1.where)(key, "==", value));
747
- });
748
- if (queryData === null || queryData === void 0 ? void 0 : queryData.orderBy) {
749
- if (queryData.orderBy === "documentId") {
750
- constraints.push((0, firestore_1.orderBy)((0, firestore_1.documentId)()));
751
- }
752
- else {
753
- constraints.push((0, firestore_1.orderBy)(queryData.orderBy));
754
- }
755
- }
756
- else {
757
- constraints.push((0, firestore_1.orderBy)((0, firestore_1.documentId)()));
758
- }
759
- if (page[0] > page[1] && !cursorDirection) { // Going up
760
- currentQueryAnchor.endKey && constraints.push((0, firestore_1.startAfter)(currentQueryAnchor.endKey));
761
- constraints.push((0, firestore_1.limit)(10));
762
- if (!loadMoreFromQuery) {
763
- currentQueryAnchor = { ...currentQueryAnchor, startQueryPos: currentQueryAnchor.endQueryPos };
764
- }
765
- }
766
- else if (page[0] < page[1] && !cursorDirection) { // Going down
767
- if (!loadMoreFromQuery) {
768
- currentQueryAnchor = { ...currentQueryAnchor, endQueryPos: currentQueryAnchor.startQueryPos };
769
- }
770
- constraints.push((0, firestore_1.limitToLast)(10));
771
- if (currentQueryAnchor.startKey) {
772
- currentQueryAnchor.startKey && constraints.push((0, firestore_1.endBefore)(currentQueryAnchor.startKey));
773
- }
774
- else {
775
- currentQueryAnchor.startKey && constraints.push((0, firestore_1.endAt)(currentQueryAnchor.startKey));
776
- }
777
- }
778
- else {
779
- if (cursorDirection === "decrease") {
780
- constraints.push((0, firestore_1.limitToLast)(10));
781
- }
782
- else {
783
- constraints.push((0, firestore_1.limit)(10));
784
- }
785
- }
786
- return constraints;
787
- };
788
- const constraints = createQuery(querySchema);
789
- // console.log(queryId, "constraints", constraints)
790
- const q = (0, firestore_1.query)((0, firestore_1.collection)(firebaseConfig_1.db, "savedPlacements"), ...(constraints));
791
- const queryResults = {};
792
- const queryData = await (0, firestore_1.getDocs)(q);
793
- // console.log("queryData.size", queryData.size)
794
- const reverseIfBack = (docs) => {
795
- if (page[0] < page[1]) {
796
- return docs.reverse();
797
- }
798
- return docs;
799
- };
800
- let index = 0;
801
- reverseIfBack(queryData.docs).forEach(async (doc) => {
802
- if (Object.keys(queryResults).length + Object.keys(itemList).length === 10) {
803
- return;
804
- }
805
- let position = Object.keys(itemList).length + (page[0] - 1) * 10 + index + 1;
806
- if (page[0] < page[1]) {
807
- position = (page[0]) * 10 - index - Object.keys(itemList).length;
808
- }
809
- // console.log(index, "doc.id", doc.id, position, "E", prevEntries[doc.id])
810
- if (itemList[doc.id] || (prevEntries[doc.id] && prevEntries[doc.id] !== position)) {
811
- console.log("Removing ", doc.id, ": E=", prevEntries[doc.id], ", G=", position);
812
- return;
813
- }
814
- const item = doc.data();
815
- item.id = doc.id;
816
- queryResults[doc.id] = item;
817
- index = index + 1;
818
- if (prevEntries[doc.id])
819
- return;
820
- prevEntries[doc.id] = position;
821
- });
822
- if (cursorDirection === "decrease" || page[0] < page[1]) {
823
- itemList = { ...Object.fromEntries(Object.entries(queryResults).reverse()), ...itemList };
824
- }
825
- else {
826
- itemList = { ...itemList, ...queryResults };
827
- }
828
- setPrevEntryIds(prevEntries);
829
- if (queryData.size < 10 && Object.keys(itemList).length < 10) {
830
- if (page[0] > page[1] && cursorPos + 1 < data.length) {
831
- console.log("Increase query index");
832
- return getDataFromQuery(itemList, { ...currentQueryAnchor, endQueryPos: currentQueryAnchor.endQueryPos + 1 }, "increase", prevEntries);
833
- }
834
- else if (page[0] < page[1] && cursorPos > 0) {
835
- console.log("Decrease query index");
836
- return getDataFromQuery(itemList, { ...currentQueryAnchor, startQueryPos: currentQueryAnchor.startQueryPos - 1 }, "decrease", prevEntries);
837
- }
838
- }
839
- if (Object.keys(itemList).length < 10 && queryData.size === 10) {
840
- console.log("Shorter than ten");
841
- // if(loadMoreFromQuery){return}
842
- return getDataFromQuery(itemList, { ...currentQueryAnchor, startKey: Object.keys(itemList)[0], endKey: Object.keys(itemList).slice(-1)[0] }, undefined, prevEntries, true);
843
- }
844
- if (queryData.size === 0 &&
845
- Object.keys(itemList).length === 0 &&
846
- currentQueryAnchor.endQueryPos + 1 === data.length &&
847
- page[0] > 1) {
848
- setTableData({});
849
- setQueryAnchor((a) => ({ ...a, startKey: "" }));
850
- return;
851
- }
852
- setQueryAnchor({ ...currentQueryAnchor, startKey: Object.keys(itemList)[0], endKey: Object.keys(itemList).slice(-1)[0] });
853
- const finalData = Object.fromEntries(await Promise.all(Object.entries(itemList).map(async ([k, v]) => {
854
- const placement = await firebaseQuery.getDocData(["placementListings", v.placementId || ""]);
855
- const address = await firebaseQuery.getDocData(["addresses", placement.addressId || ""]).catch(() => ({ ["address-line1"]: "Unknown address" }));
856
- const provider = await firebaseQuery.getDocData(["providers", placement.providerId || ""]).catch(() => ({ name: "Unknown" }));
857
- const status = provider.name !== "Unknown" ? getPlacementStatus(provider, placement, v) : "Deleted";
858
- return [k, { ...address, ...provider, ...placement, email: placement.providerEmail, status: status, savedPlacement: v }];
859
- })));
860
- setTableData(finalData);
861
- };
862
- const getPlacementStatus = (provider, placement, savedPlacement) => {
863
- if (savedPlacement.status === "Blocked")
864
- return "blocked";
865
- if (savedPlacement.status === "Accepted")
866
- return "active";
867
- if (user.product === "admin") {
868
- if (placement.mapConsent === undefined)
869
- return "notReviewed";
870
- if (placement.mapConsent === false)
871
- return "notPublic";
872
- return "unknown";
788
+ const getAdditionalData = async (k, v) => {
789
+ var _a, _b;
790
+ if ((_b = (_a = v.savedBy) === null || _a === void 0 ? void 0 : _a[user.oId].activities) === null || _b === void 0 ? void 0 : _b.includes("workExperience")) {
791
+ const placementsCount = await firebaseQuery.getCount("placementListings", [(0, firestore_1.where)(`savedBy.${user.oId}.exists`, "==", true), (0, firestore_1.where)("providerContactId", "==", k)]);
792
+ return { ...v, plcaements: placementsCount };
873
793
  }
874
- ;
875
- if (!provider.insurance)
876
- return "awaitingProviderApproval";
877
- return "requiresApproval";
794
+ return v;
878
795
  };
796
+ const { tableData, pageUp, pageDown, setFilters, page, setView, loading } = useDataViewerPaginator({ view, filters, queryLimit: 20, data: query, additionalEntryProcessing: getAdditionalData });
879
797
  (0, react_1.useEffect)(() => {
880
- if (!filters)
881
- return;
882
- setPage([1, 0]);
883
- setTableData({});
884
- setQueryAnchor({ startKey: "", endKey: "", startQueryPos: 0, endQueryPos: 0 });
885
- setPrevEntryIds({});
886
- }, [filters]);
887
- // Fetch new data when queries or page change
888
- (0, react_1.useEffect)(() => {
889
- getDataFromQuery();
890
- }, [page]);
891
- return ({ ...{ tableData, setPage, setFilters, page } });
798
+ const constraints = [
799
+ [`savedBy.${user.oId}.exists`, "==", true],
800
+ ];
801
+ if (user.userType === "Students") {
802
+ constraints.push([`savedBy.${user.oId}.cohorts.${user.cohort}.listed`, "==", true]);
803
+ }
804
+ setQuery([{
805
+ path: ["providerContacts"],
806
+ where: constraints
807
+ }]);
808
+ }, [user]);
809
+ return ({ ...{ tableData, pageUp, pageDown, setFilters, page, setView, loading } });
892
810
  }
893
811
  function useCohortUserPaginator({ user, cohort, data, search, userType, sort }) {
894
812
  const [tableData, setTableData] = (0, react_1.useState)({});
@@ -918,8 +836,8 @@ function useCohortUserPaginator({ user, cohort, data, search, userType, sort })
918
836
  return;
919
837
  }
920
838
  if ((!user.viewCohorts && user.userGroup !== "admin") ||
921
- user.viewCohorts === "none" ||
922
- (user.viewCohorts === "some" && cohort !== "all" && !((_a = user.visibleCohorts) === null || _a === void 0 ? void 0 : _a.includes(cohort || "")))) {
839
+ (user.viewCohorts === "none" && user.userGroup !== "admin") ||
840
+ (user.viewCohorts === "some" && user.userGroup !== "admin" && cohort !== "all" && !((_a = user.visibleCohorts) === null || _a === void 0 ? void 0 : _a.includes(cohort || "")))) {
923
841
  setQueries(undefined);
924
842
  return;
925
843
  }
@@ -1211,394 +1129,433 @@ function useLazyLoadQueryList({ path, constraints, number, onItemFetched }) {
1211
1129
  }, []);
1212
1130
  return ({ ...{ items, loadMore, loadMoreIcon, reset } });
1213
1131
  }
1214
- function usePublicPlacementListingLoader({ providerId, number = 5 }) {
1215
- const [items, setItems] = (0, react_1.useState)({});
1216
- const [loadMoreIcon, setLoadMoreIcon] = (0, react_1.useState)(false);
1217
- const [lastItem, setLastItem] = (0, react_1.useState)();
1218
- const firebaseQuery = new firebaseQuery_1.default();
1219
- const reset = () => {
1220
- setItems({});
1221
- setLastItem(undefined);
1222
- };
1223
- const loadMore = async () => {
1224
- setLoadMoreIcon(true);
1225
- let formattedConstraints = [
1226
- (0, firestore_1.where)("status", "==", "listed"),
1227
- (0, firestore_1.limit)(number)
1228
- ];
1229
- if (providerId) {
1230
- formattedConstraints.push((0, firestore_1.where)("providerId", "==", providerId));
1231
- }
1232
- if (lastItem) {
1233
- formattedConstraints.push((0, firestore_1.startAfter)(lastItem));
1234
- }
1235
- const documents = await firebaseQuery.getDocsWhere("placementListings", formattedConstraints, true);
1236
- console.log("docs", documents.docs);
1237
- setLastItem(documents.docs[documents.docs.length - 1]);
1238
- const processedItems = Object.fromEntries(await Promise.all(Object.values(documents.docs).map(async (doc) => {
1239
- var _a, _b;
1240
- let itemObj = { ...doc.data(), id: doc.id };
1241
- if (itemObj.addressId) {
1242
- const address = await firebaseQuery.getDocData(["addresses", itemObj.addressId]);
1243
- delete address.id;
1244
- itemObj = { ...address, ...itemObj };
1245
- }
1246
- if (itemObj.applicantWorkflowId) {
1247
- const applicantWorkflow = (await firebaseQuery.getDocData(["applicantWorkflows", itemObj.applicantWorkflowId])).workflow.filter((i) => i.id === 1)[0];
1248
- const applicantFiles = applicantWorkflow.files ? Object.fromEntries(await Promise.all((_a = applicantWorkflow.files) === null || _a === void 0 ? void 0 : _a.map(async (fileId) => {
1249
- const file = await firebaseQuery.getDocData(["files", fileId]);
1250
- file.url = await (0, storage_1.getDownloadURL)((0, storage_1.ref)(firebaseConfig_1.storage, `providers/${itemObj.providerId}/${file.fileName}`));
1251
- return [fileId, file];
1252
- }))) : [];
1253
- const applicantForms = applicantWorkflow.forms ? Object.fromEntries(await Promise.all((_b = applicantWorkflow.forms) === null || _b === void 0 ? void 0 : _b.map(async (formId) => {
1254
- return [formId, await firebaseQuery.getDocData(["forms", formId])];
1255
- }))) : [];
1256
- applicantWorkflow.viewableFiles = applicantFiles;
1257
- applicantWorkflow.formDetails = applicantForms;
1258
- itemObj = { ...itemObj, applicantWorkflow: [applicantWorkflow] };
1259
- }
1260
- return [doc.id, itemObj];
1261
- })));
1262
- setItems((i) => ({ ...i, ...processedItems }));
1263
- setLoadMoreIcon(false);
1264
- };
1265
- (0, react_1.useEffect)(() => {
1266
- loadMore();
1267
- }, []);
1268
- return ({ ...{ items, loadMore, loadMoreIcon, reset } });
1269
- }
1270
- function useCreateApplicationRenderer({ user, listingId, listing, provider, application, applicationId, orgContext }) {
1271
- const firebaseQuery = new firebaseQuery_1.default();
1272
- let applicationWithoutAdditionalData = { ...(application || {}) };
1273
- delete applicationWithoutAdditionalData.listing;
1274
- delete applicationWithoutAdditionalData.address;
1275
- delete applicationWithoutAdditionalData.provider;
1276
- const [fApplication, setFApplication] = (0, react_1.useState)(application ? applicationWithoutAdditionalData : {
1277
- uid: user.userType === "Students" ? user.id : undefined,
1278
- listingId: listingId,
1279
- addressId: listing === null || listing === void 0 ? void 0 : listing.addressId,
1280
- stage: 1,
1281
- reqUserType: "Students",
1282
- status: "draft"
1283
- });
1284
- const [fApplicationId, setFApplicationId] = (0, react_1.useState)(applicationId);
1285
- const [draftSaved, setDraftSaved] = (0, react_1.useState)(false);
1286
- const [fProvider, setFProvider] = (0, react_1.useState)(provider);
1287
- const [fListing, setFListing] = (0, react_1.useState)(Object.keys(listing || {}).length > 5 ? listing : undefined);
1288
- const [student, setStudent] = (0, react_1.useState)(user.userType === "Students" ? user : undefined);
1289
- const [profileUrl, setProfileUrl] = (0, react_1.useState)();
1290
- const [successPopup, setSuccessPopup] = (0, react_1.useState)();
1291
- const [uploadedFiles, setUploadedFiles] = (0, react_1.useState)();
1292
- const [currentStageComplete, setCurrentStageComplete] = (0, react_1.useState)();
1293
- (0, react_1.useEffect)(() => {
1294
- const getListing = async () => {
1295
- console.log("Checking ID");
1296
- if (!listingId)
1297
- return;
1298
- console.log("Getting listing");
1299
- console.log("LISTING PARAM", listing, Object.keys(listing || {}).length > 5);
1300
- const listingData = (Object.keys(listing || {}).length > 5) ? listing : await firebaseQuery.getDocData(["placementListings", listingId]).catch(() => false);
1301
- console.log("LISTINGDATA", listingData, Object.keys(listing || {}).length > 5 ? { a: "string" } : "AAA");
1302
- const address = listingData ? (user.product === "providers" && orgContext) ? orgContext.addresses[listingData.addressId || ""] : await firebaseQuery.getDocData(["addresses", listingData.addressId]) : undefined;
1303
- const workflow = listingData ? (user.product === "providers" && orgContext) ? orgContext.applicantWorkflows[listingData.applicantWorkflowId || ""] : await firebaseQuery.getDocData(["applicantWorkflows", listingData.applicantWorkflowId]) : undefined;
1304
- if (workflow && listingData) {
1305
- workflow.workflow = await Promise.all(workflow.workflow.map(async (s) => {
1306
- var _a, _b;
1307
- const applicantFiles = s.files ? Object.fromEntries(await Promise.all((_a = s.files) === null || _a === void 0 ? void 0 : _a.map(async (fileId) => {
1308
- const file = await firebaseQuery.getDocData(["files", fileId]);
1309
- file.url = await (0, storage_1.getDownloadURL)((0, storage_1.ref)(firebaseConfig_1.storage, `providers/${listingData === null || listingData === void 0 ? void 0 : listingData.providerId}/${file.fileName}`));
1310
- return [fileId, file];
1311
- }))) : [];
1312
- const applicantForms = s.forms ? Object.fromEntries(await Promise.all((_b = s.forms) === null || _b === void 0 ? void 0 : _b.map(async (formId) => {
1313
- return [formId, await firebaseQuery.getDocData(["forms", formId])];
1314
- }))) : [];
1315
- return { ...s, viewableFiles: applicantFiles, formDetails: applicantForms };
1316
- }));
1317
- delete workflow.id;
1318
- }
1319
- if (address) {
1320
- delete address.id;
1321
- }
1322
- console.log("Setting listing");
1323
- setFListing((listingData && workflow) ? { ...listingData, ...address, applicantWorkflow: workflow.workflow } : false);
1324
- if (((fProvider === null || fProvider === void 0 ? void 0 : fProvider.id) === (application === null || application === void 0 ? void 0 : application.providerId)) && user.product === "providers") {
1325
- setFProvider({ details: orgContext === null || orgContext === void 0 ? void 0 : orgContext.details, id: user.oId });
1326
- }
1327
- else if (listingData && (listingData === null || listingData === void 0 ? void 0 : listingData.providerId)) {
1328
- console.log("Getting provider from DB");
1329
- const provider = await firebaseQuery.getDocData(["providers", listingData.providerId]);
1330
- console.log("Provider", provider);
1331
- setFProvider({ details: provider, id: listingData.providerId });
1332
- }
1333
- };
1334
- getListing();
1335
- }, [listingId, listing]);
1336
- (0, react_1.useEffect)(() => {
1337
- if ((student === null || student === void 0 ? void 0 : student.id) !== (application === null || application === void 0 ? void 0 : application.uid)) {
1338
- if (user.userType === "Students") {
1339
- setStudent(user);
1340
- }
1341
- else if (user.product === "providers" && (application === null || application === void 0 ? void 0 : application.uid)) {
1342
- firebaseQuery.getDocData(["users", application.uid]).then((s) => setStudent(s));
1343
- }
1344
- }
1345
- }, []);
1346
- (0, react_1.useEffect)(() => {
1347
- setFListing(Object.keys(listing || {}).length > 5 ? listing : undefined);
1348
- }, [listing]);
1349
- (0, react_1.useEffect)(() => {
1350
- if (provider === null || provider === void 0 ? void 0 : provider.profile)
1351
- return;
1352
- if (!(provider === null || provider === void 0 ? void 0 : provider.id))
1353
- return;
1354
- (0, storage_1.getDownloadURL)((0, storage_1.ref)(firebaseConfig_1.storage, `providers/${provider === null || provider === void 0 ? void 0 : provider.id}/profilePic.png`)).then(setProfileUrl).catch(() => null);
1355
- }, [provider]);
1356
- (0, react_1.useEffect)(() => {
1357
- console.log("APPLICATIONID", applicationId);
1358
- if (!applicationId) {
1359
- if (!listingId)
1360
- return;
1361
- firebaseQuery.getDocsWhere("applications", [(0, firestore_1.where)("status", "not-in", ["approved", "declined"]), (0, firestore_1.where)("uid", "==", user.id), (0, firestore_1.where)("listingId", "==", listingId)]).then((existingApplication) => {
1362
- console.log("EXISTING", existingApplication);
1363
- // get uploaded files
1364
- if (existingApplication && Object.keys(existingApplication).length) {
1365
- setFApplication(Object.values(existingApplication)[0]);
1366
- setFApplicationId(Object.keys(existingApplication)[0]);
1367
- }
1368
- });
1369
- return;
1370
- }
1371
- if (applicationId) {
1372
- setFApplicationId(applicationId);
1373
- if (application) {
1374
- let applicationWithoutAdditionalData = { ...(application || {}) };
1375
- delete applicationWithoutAdditionalData.listing;
1376
- delete applicationWithoutAdditionalData.address;
1377
- delete applicationWithoutAdditionalData.provider;
1378
- setFApplication(applicationWithoutAdditionalData);
1379
- }
1380
- else {
1381
- firebaseQuery.getDocData(["applications", applicationId]).then(setFApplication);
1382
- }
1383
- }
1384
- }, [application, applicationId]);
1385
- const getCurrentStage = async (stage) => {
1386
- var _a, _b, _c, _d;
1387
- console.log("fLSITING CURRENT STAGE", fListing);
1388
- if (!fListing)
1389
- throw new Error("Listing deleted");
1390
- if (!(fListing === null || fListing === void 0 ? void 0 : fListing.applicantWorkflowId))
1391
- throw new Error("No workflow stage");
1392
- const mApplicantWorkflow = await firebaseQuery.getDocData(["applicantWorkflows", fListing.applicantWorkflowId]);
1393
- const stageObj = (_a = mApplicantWorkflow === null || mApplicantWorkflow === void 0 ? void 0 : mApplicantWorkflow.workflow) === null || _a === void 0 ? void 0 : _a.find((s) => s.id === stage);
1394
- if (!stageObj)
1395
- throw new Error("Can't find stage.");
1396
- const applicantFiles = stageObj.files ? Object.fromEntries(await Promise.all((_b = stageObj.files) === null || _b === void 0 ? void 0 : _b.map(async (fileId) => {
1397
- const file = await firebaseQuery.getDocData(["files", fileId]);
1398
- file.url = await (0, storage_1.getDownloadURL)((0, storage_1.ref)(firebaseConfig_1.storage, `providers/${mApplicantWorkflow === null || mApplicantWorkflow === void 0 ? void 0 : mApplicantWorkflow.oId}/${file.fileName}`));
1399
- return [fileId, file];
1400
- }))) : [];
1401
- const applicantForms = stageObj.forms ? Object.fromEntries(await Promise.all((_c = stageObj.forms) === null || _c === void 0 ? void 0 : _c.map(async (formId) => {
1402
- return [formId, await firebaseQuery.getDocData(["forms", formId])];
1403
- }))) : [];
1404
- stageObj.viewableFiles = applicantFiles;
1405
- stageObj.formDetails = applicantForms;
1406
- return { stage: stageObj, completedSections: ((_d = fApplication === null || fApplication === void 0 ? void 0 : fApplication.completedSections) === null || _d === void 0 ? void 0 : _d[stage]) || {} };
1407
- };
1408
- (0, react_1.useEffect)(() => {
1409
- const getUploadedFiles = async () => {
1410
- if (!fApplication.completedSections) {
1411
- setUploadedFiles({});
1412
- return;
1413
- }
1414
- ;
1415
- const fileIds = Object.values(fApplication.completedSections)
1416
- .flatMap(stageData => Object.values(stageData.filesUploaded || {}).flatMap(fileIds => fileIds));
1417
- const fileDataPromises = fileIds.map(async (fileId) => {
1418
- const fileData = await firebaseQuery.getDocData(["files", fileId]);
1419
- fileData.url = await (0, storage_1.getDownloadURL)((0, storage_1.ref)(firebaseConfig_1.storage, `userFiles/${fileData.fileName}`));
1420
- return [fileId, fileData];
1421
- });
1422
- const fileDataArray = await Promise.all(fileDataPromises);
1423
- const fileDataObj = Object.fromEntries(fileDataArray);
1424
- setUploadedFiles(fileDataObj);
1425
- };
1426
- const addApplication = async () => {
1427
- console.log("ADDING APPLICATION");
1428
- if (!fListing || !(fListing === null || fListing === void 0 ? void 0 : fListing.id) || !(fProvider === null || fProvider === void 0 ? void 0 : fProvider.id) || !(student === null || student === void 0 ? void 0 : student.id))
1429
- return;
1430
- const applicationData = {
1431
- uid: student.id,
1432
- listingId: fListing === null || fListing === void 0 ? void 0 : fListing.id,
1433
- addressId: fListing.addressId,
1434
- applicantWorkflowId: fListing === null || fListing === void 0 ? void 0 : fListing.applicantWorkflowId,
1435
- providerId: fProvider.id,
1436
- stage: 1,
1437
- status: "draft",
1438
- created: (new Date()).toISOString(),
1439
- ...fApplication,
1440
- };
1441
- const mApplicationId = (await firebaseQuery.add(["applications"], applicationData)).id;
1442
- console.log("APPLICATION ADDED");
1443
- setFApplicationId(mApplicationId);
1444
- setFApplication(applicationData);
1445
- setDraftSaved(true);
1446
- return;
1447
- };
1448
- getUploadedFiles();
1449
- console.log("Checking IDs");
1450
- if (!fListing || !(fListing === null || fListing === void 0 ? void 0 : fListing.id) || !(fProvider === null || fProvider === void 0 ? void 0 : fProvider.id) || !(student === null || student === void 0 ? void 0 : student.id))
1451
- return;
1452
- if (user.product === "providers")
1453
- return;
1454
- console.log("Checking dates and sections");
1455
- if (!fApplication.completedSections && !fApplication.startDate && !fApplication.endDate)
1456
- return;
1457
- console.log("Application updated");
1458
- if (!fApplicationId && !applicationId) {
1459
- // save new
1460
- console.log("Add application");
1461
- addApplication();
1462
- return;
1463
- }
1464
- // update
1465
- firebaseQuery.update(["applications", (fApplicationId || applicationId)], fApplication);
1466
- setDraftSaved(true);
1467
- }, [fApplication]);
1468
- const openSuccessPopup = (type) => {
1469
- setSuccessPopup(type);
1470
- setTimeout(() => {
1471
- // onClose();
1472
- }, 1500);
1473
- };
1474
- (0, react_1.useEffect)(() => {
1475
- const areStagesCompleted = async () => {
1476
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
1477
- if (!fListing)
1478
- return;
1479
- if (fApplication.stage === undefined)
1480
- return undefined;
1481
- const currentStage = await getCurrentStage(fApplication.stage);
1482
- console.log("Checking current stage is complete");
1483
- for (const fileViewed of ((_a = currentStage.stage) === null || _a === void 0 ? void 0 : _a.files) || []) {
1484
- console.log("Checking file viewed", fileViewed, "in", (_b = currentStage === null || currentStage === void 0 ? void 0 : currentStage.completedSections) === null || _b === void 0 ? void 0 : _b.filesViewed);
1485
- if (!((_d = (_c = currentStage === null || currentStage === void 0 ? void 0 : currentStage.completedSections) === null || _c === void 0 ? void 0 : _c.filesViewed) === null || _d === void 0 ? void 0 : _d.includes(fileViewed))) {
1486
- console.log("File not viewed");
1487
- return false;
1488
- }
1489
- else {
1490
- console.log("File viewed");
1491
- }
1492
- }
1493
- for (const formCompleted of ((_e = currentStage === null || currentStage === void 0 ? void 0 : currentStage.stage) === null || _e === void 0 ? void 0 : _e.forms) || []) {
1494
- console.log("Checking form completed", formCompleted, "in", (_f = currentStage === null || currentStage === void 0 ? void 0 : currentStage.completedSections) === null || _f === void 0 ? void 0 : _f.formsCompleted);
1495
- if (!Object.keys(((_g = currentStage === null || currentStage === void 0 ? void 0 : currentStage.completedSections) === null || _g === void 0 ? void 0 : _g.formsCompleted) || {}).includes(formCompleted)) {
1496
- console.log("Form not completed");
1497
- return false;
1498
- }
1499
- else {
1500
- console.log("Form completed");
1501
- }
1502
- }
1503
- for (let i = 0; i++; i < (((_h = currentStage === null || currentStage === void 0 ? void 0 : currentStage.stage) === null || _h === void 0 ? void 0 : _h.requiredFiles) || []).length) {
1504
- if (!Object.keys(((_j = currentStage === null || currentStage === void 0 ? void 0 : currentStage.completedSections) === null || _j === void 0 ? void 0 : _j.filesUploaded) || {}).includes(i.toString())) {
1505
- console.log("Form not uploaded");
1506
- return false;
1507
- }
1508
- else {
1509
- console.log("Form uploaded");
1510
- }
1511
- }
1512
- return true;
1513
- };
1514
- areStagesCompleted().then(setCurrentStageComplete);
1515
- }, [fApplication, fListing]);
1516
- const viewFile = (file, onOpen) => {
1517
- var _a, _b;
1518
- if (fApplication.reqUserType !== user.userType)
1519
- return;
1520
- if (fApplication.stage === undefined)
1521
- throw new Error("Missing applciation stage.");
1522
- if (!fListing)
1523
- throw new Error("No associated listing.");
1524
- const viewableFiles = (_b = (_a = fListing === null || fListing === void 0 ? void 0 : fListing.applicantWorkflow) === null || _a === void 0 ? void 0 : _a.find((stage) => stage.id === fApplication.stage)) === null || _b === void 0 ? void 0 : _b.viewableFiles;
1525
- setFApplication((a) => {
1526
- var _a, _b;
1527
- const oldA = { ...a };
1528
- const viewedFiles = ((_b = (_a = a.completedSections) === null || _a === void 0 ? void 0 : _a[1]) === null || _b === void 0 ? void 0 : _b.filesViewed) || [];
1529
- if (viewedFiles === null || viewedFiles === void 0 ? void 0 : viewedFiles.includes(file))
1530
- return a;
1531
- (viewableFiles === null || viewableFiles === void 0 ? void 0 : viewableFiles[file].url) && onOpen(viewableFiles === null || viewableFiles === void 0 ? void 0 : viewableFiles[file].url);
1532
- viewedFiles === null || viewedFiles === void 0 ? void 0 : viewedFiles.push(file);
1533
- const newA = (0, util_1.editNestedObject)(["completedSections", 1, "filesViewed"], oldA, viewedFiles);
1534
- return newA;
1535
- });
1536
- };
1537
- const addFile = (files, fileId) => {
1538
- if (fApplication.reqUserType !== user.userType)
1539
- throw new Error(`Incorrect user type. Expected ${fApplication.reqUserType}, got: ${user.userType}`);
1540
- if (fApplication.stage === undefined)
1541
- throw new Error("Missing applciation stage.");
1542
- if (!files.length)
1543
- throw new Error("No files to upload");
1544
- setFApplication((a) => (0, util_1.editNestedObject)(["completedSections", fApplication.stage, "filesUploaded", fileId], a, files));
1545
- };
1546
- const setFormComplete = (formId, e) => {
1547
- if (fApplication.reqUserType !== user.userType)
1548
- throw new Error(`Incorrect user type. Expected ${fApplication.reqUserType}, got: ${user.userType}`);
1549
- if (fApplication.stage === undefined)
1550
- throw new Error("Missing applciation stage.");
1551
- setFApplication((a) => (0, util_1.editNestedObject)(["completedSections", fApplication.stage, "formsCompleted", formId], a, e));
1552
- };
1553
- const successText = {
1554
- submitted: {
1555
- title: "Application submitted",
1556
- desc: "We've sent your application to the placement provider. You will hear what the next steps are soon.",
1557
- },
1558
- draftSaved: {
1559
- title: "Draft saved",
1560
- desc: "Your draft has been saved. Go to the 'Applications' section from your home screen to edit.",
1561
- },
1562
- stageComplete: {
1563
- title: "Stage complete",
1564
- desc: "We have sent this to the next stage in the application process. We will update you with any progress.",
1565
- },
1566
- outcome: {
1567
- title: "Outcome submitted",
1568
- desc: "We have sent the student an email with the outcome of their application.",
1569
- },
1570
- };
1571
- const onFApply = async (draft) => {
1572
- if (draft) {
1573
- openSuccessPopup("draftSaved");
1574
- return;
1575
- }
1576
- if (!fApplicationId)
1577
- return;
1578
- // Check all items have been filled in.
1579
- if (!fApplication.startDate || !fApplication.endDate)
1580
- throw new Error("Please select dates for your placement.");
1581
- await (0, firebase_1.executeCallable)("applications-submit", { applicationId: fApplicationId });
1582
- const newApplication = await firebaseQuery.getDocData(["applications", fApplicationId]);
1583
- setFApplication(newApplication);
1584
- openSuccessPopup("submitted");
1585
- };
1586
- const progressStage = async (type, e) => {
1587
- // Check all stages completed.
1588
- if (!fApplicationId)
1589
- return;
1590
- if (!currentStageComplete)
1591
- throw new Error("Complete all forms before submitting.");
1592
- if (fApplication.reqUserType !== user.userType)
1593
- throw new Error(`Incorrect user type. Expected ${fApplication.reqUserType}, got: ${user.userType}`);
1594
- if (fApplication.stage === undefined)
1595
- throw new Error("Missing applciation stage.");
1596
- await (0, firebase_1.executeCallable)("applications-changeStage", { applicationId: fApplicationId, type: type, feedback: e === null || e === void 0 ? void 0 : e.feedback });
1597
- const newApplication = await firebaseQuery.getDocData(["applications", fApplicationId]);
1598
- setFApplication(newApplication);
1599
- };
1600
- return { successText, onFApply, progressStage, currentStageComplete, uploadedFiles, getCurrentStage, setFormComplete, viewFile, addFile, setSuccessPopup, openSuccessPopup, setFApplication, fApplication, draftSaved, profileUrl, successPopup, fApplicationId, fListing, student, fProvider };
1601
- }
1132
+ // type PublicPlacementListingLoaderParams = {
1133
+ // providerId?: string,
1134
+ // number: number,
1135
+ // }
1136
+ // export function usePublicPlacementListingLoader({providerId, number=5}:PublicPlacementListingLoaderParams) {
1137
+ // const [items, setItems] = useState<{[key:string]:{[key:string]:unknown}}>({});
1138
+ // const [loadMoreIcon, setLoadMoreIcon] = useState<boolean>(false);
1139
+ // const [lastItem, setLastItem] = useState<QueryDocumentSnapshot<DocumentData>>();
1140
+ // const firebaseQuery = new FirebaseQuery();
1141
+ // const reset = () => {
1142
+ // setItems({});
1143
+ // setLastItem(undefined);
1144
+ // };
1145
+ // const loadMore = async () => {
1146
+ // setLoadMoreIcon(true);
1147
+ // let formattedConstraints:QueryConstraint[] = [
1148
+ // where("status", "==", "listed"),
1149
+ // limit(number)
1150
+ // ];
1151
+ // if (providerId) {
1152
+ // formattedConstraints.push(where("providerId", "==", providerId));
1153
+ // }
1154
+ // if (lastItem) {
1155
+ // formattedConstraints.push(startAfter(lastItem));
1156
+ // }
1157
+ // const documents = await firebaseQuery.getDocsWhere("placementListings", formattedConstraints, true) as QuerySnapshot<DocumentData>;
1158
+ // console.log("docs", documents.docs);
1159
+ // setLastItem(documents.docs[documents.docs.length-1]);
1160
+ // const processedItems = Object.fromEntries(await Promise.all(Object.values(documents.docs).map(async (doc) => {
1161
+ // let itemObj = {...doc.data(), id: doc.id} as PlacementListing;
1162
+ // if (itemObj.addressId) {
1163
+ // const address = await firebaseQuery.getDocData(["addresses", itemObj.addressId]) as Address;
1164
+ // delete address.id;
1165
+ // itemObj = {...address, ...itemObj};
1166
+ // }
1167
+ // if (itemObj.applicantWorkflowId) {
1168
+ // const applicantWorkflow = (await firebaseQuery.getDocData(["applicantWorkflows", itemObj.applicantWorkflowId]) as ApplicantWorkflow).workflow.filter((i) => i.id === 1)[0];
1169
+ // const applicantFiles = applicantWorkflow.files ? Object.fromEntries(await Promise.all(applicantWorkflow.files?.map(async (fileId) => {
1170
+ // const file = await firebaseQuery.getDocData(["files", fileId]);
1171
+ // file.url = await getDownloadURL(ref(storage, `providers/${itemObj.providerId}/${file.fileName}`));
1172
+ // return [fileId, file];
1173
+ // }))) : [];
1174
+ // const applicantForms = applicantWorkflow.forms ? Object.fromEntries(await Promise.all(applicantWorkflow.forms?.map(async (formId) => {
1175
+ // return [formId, await firebaseQuery.getDocData(["forms", formId])];
1176
+ // }))) : [];
1177
+ // applicantWorkflow.viewableFiles = applicantFiles;
1178
+ // applicantWorkflow.formDetails = applicantForms;
1179
+ // itemObj = {...itemObj, applicantWorkflow: [applicantWorkflow]};
1180
+ // }
1181
+ // return [doc.id, itemObj];
1182
+ // })))
1183
+ // setItems((i) => ({...i, ...processedItems}));
1184
+ // setLoadMoreIcon(false);
1185
+ // };
1186
+ // useEffect(() => {
1187
+ // loadMore();
1188
+ // }, []);
1189
+ // return ({...{items, loadMore, loadMoreIcon, reset}});
1190
+ // }
1191
+ // export type ApplicationHookParams = {
1192
+ // successText: {
1193
+ // submitted: {
1194
+ // title: string;
1195
+ // desc: string;
1196
+ // };
1197
+ // draftSaved: {
1198
+ // title: string;
1199
+ // desc: string;
1200
+ // };
1201
+ // stageComplete: {
1202
+ // title: string;
1203
+ // desc: string;
1204
+ // };
1205
+ // outcome: {
1206
+ // title: string;
1207
+ // desc: string;
1208
+ // };
1209
+ // };
1210
+ // setSuccessPopup: import("react").Dispatch<import("react").SetStateAction<"submitted" | "draftSaved" | "stageComplete" | "outcome" | undefined>>;
1211
+ // openSuccessPopup: (type: "submitted" | "draftSaved" | "stageComplete" | "outcome") => void;
1212
+ // setFApplication: import("react").Dispatch<import("react").SetStateAction<Partial<Application>>>;
1213
+ // fApplication: Partial<Application>;
1214
+ // draftSaved: boolean;
1215
+ // profileUrl: string | undefined;
1216
+ // successPopup: "submitted" | "draftSaved" | "stageComplete" | "outcome" | undefined;
1217
+ // fApplicationId: string | undefined;
1218
+ // fListing: PlacementListing | false | undefined;
1219
+ // student: UserData | undefined;
1220
+ // fProvider: {
1221
+ // details?: ProviderData;
1222
+ // profile?: string;
1223
+ // id?: string;
1224
+ // } | undefined;
1225
+ // onFApply: (draft?: boolean) => Promise<void>;
1226
+ // setFormComplete: (formId: string, e: {
1227
+ // [key: string]: unknown;
1228
+ // }) => void;
1229
+ // viewFile: (file: string, onOpen: (url: string) => void) => void
1230
+ // addFile: (files: string[], fileId: number) => void;
1231
+ // uploadedFiles?: {
1232
+ // [key: string]: FileItem;
1233
+ // };
1234
+ // getCurrentStage: (stage: number) => Promise<{
1235
+ // stage: ApplicantStage;
1236
+ // completedSections: {
1237
+ // submitted?: string | undefined;
1238
+ // filesViewed?: string[] | undefined;
1239
+ // formsCompleted?: {
1240
+ // [key: string]: unknown;
1241
+ // } | undefined;
1242
+ // filesUploaded?: {
1243
+ // [key: number]: string[];
1244
+ // } | undefined;
1245
+ // };
1246
+ // }>;
1247
+ // currentStageComplete?: boolean;
1248
+ // progressStage: (type: number | "accept" | "reject", e?: {
1249
+ // feedback?: string;
1250
+ // }) => Promise<void>;
1251
+ // };
1252
+ // export function useCreateApplicationRenderer({user, listingId, listing, provider, application, applicationId, orgContext}:
1253
+ // {user:UserData, listingId:string, applicationId?: string, listing?: PlacementListing, application?: Partial<Application>,
1254
+ // orgContext?: {details: ProviderData, addresses: {[key: string]: OrganisationAddress}, applicantWorkflows: {[key: string]: ApplicantWorkflow}},
1255
+ // provider?: {details?: ProviderData, profile?: string, id?: string}}) {
1256
+ // const firebaseQuery = new FirebaseQuery();
1257
+ // let applicationWithoutAdditionalData = {...(application || {})} as any;
1258
+ // delete applicationWithoutAdditionalData.listing;
1259
+ // delete applicationWithoutAdditionalData.address;
1260
+ // delete applicationWithoutAdditionalData.provider;
1261
+ // const [fApplication, setFApplication] = useState<Partial<Application>>(application ? applicationWithoutAdditionalData : {
1262
+ // uid: user.userType === "Students" ? user.id : undefined,
1263
+ // listingId: listingId,
1264
+ // addressId: listing?.addressId,
1265
+ // stage: 1,
1266
+ // reqUserType: "Students",
1267
+ // status: "draft"});
1268
+ // const [fApplicationId, setFApplicationId] = useState<string|undefined>(applicationId);
1269
+ // const [draftSaved, setDraftSaved] = useState(false);
1270
+ // const [fProvider, setFProvider] = useState<{details?: ProviderData, profile?: string, id?: string}|undefined>(provider);
1271
+ // const [fListing, setFListing] = useState<PlacementListing|false|undefined>(Object.keys(listing || {}).length > 5 ? listing : undefined);
1272
+ // const [student, setStudent] = useState<UserData|undefined>(user.userType === "Students" ? user : undefined);
1273
+ // const [profileUrl, setProfileUrl] = useState<string>();
1274
+ // const [successPopup, setSuccessPopup] = useState<"submitted"|"draftSaved"|"stageComplete"|"outcome">();
1275
+ // const [uploadedFiles, setUploadedFiles] = useState<{[key: string]: FileItem}>();
1276
+ // const [currentStageComplete, setCurrentStageComplete] = useState<boolean>();
1277
+ // useEffect(() => {
1278
+ // const getListing = async () => {
1279
+ // console.log("Checking ID")
1280
+ // if (!listingId) return;
1281
+ // console.log("Getting listing")
1282
+ // console.log("LISTING PARAM", listing, Object.keys(listing || {}).length > 5);
1283
+ // const listingData = (Object.keys(listing || {}).length > 5) ? listing : (await firebaseQuery.getDocData(["placementListings", listingId]).catch(() => false) as PlacementListing|false);
1284
+ // console.log("LISTINGDATA", listingData, Object.keys(listing || {}).length > 5 ? {a: "string"} : "AAA");
1285
+ // const address = listingData ? (user.product === "providers" && orgContext) ? orgContext.addresses[listingData.addressId || ""] : await firebaseQuery.getDocData(["addresses", listingData.addressId as string]) as Address : undefined;
1286
+ // const workflow = listingData ? (user.product === "providers" && orgContext) ? orgContext.applicantWorkflows[listingData.applicantWorkflowId || ""] as ApplicantWorkflow : await firebaseQuery.getDocData(["applicantWorkflows", listingData.applicantWorkflowId as string]) as ApplicantWorkflow : undefined;
1287
+ // if (workflow && listingData) {
1288
+ // workflow.workflow = await Promise.all(workflow.workflow.map(async (s) => {
1289
+ // const applicantFiles = s.files ? Object.fromEntries(await Promise.all(s.files?.map(async (fileId: string) => {
1290
+ // const file = await firebaseQuery.getDocData(["files", fileId]);
1291
+ // file.url = await getDownloadURL(ref(storage, `providers/${listingData?.providerId}/${file.fileName}`));
1292
+ // return [fileId, file];
1293
+ // }))) : [];
1294
+ // const applicantForms = s.forms ? Object.fromEntries(await Promise.all(s.forms?.map(async (formId: string) => {
1295
+ // return [formId, await firebaseQuery.getDocData(["forms", formId])];
1296
+ // }))) : [];
1297
+ // return {...s, viewableFiles: applicantFiles, formDetails: applicantForms};
1298
+ // }));
1299
+ // delete workflow.id;
1300
+ // }
1301
+ // if (address) {
1302
+ // delete address.id;
1303
+ // }
1304
+ // console.log("Setting listing")
1305
+ // setFListing((listingData && workflow) ? {...listingData, ...address, applicantWorkflow: workflow.workflow} as PlacementListing : false);
1306
+ // if ((fProvider?.id === application?.providerId) && user.product === "providers") {
1307
+ // setFProvider({details: orgContext?.details, id: user.oId});
1308
+ // } else if (listingData && listingData?.providerId) {
1309
+ // console.log("Getting provider from DB");
1310
+ // const provider = await firebaseQuery.getDocData(["providers", listingData.providerId]) as ProviderData;
1311
+ // console.log("Provider", provider);
1312
+ // setFProvider({details: provider, id: listingData.providerId});
1313
+ // }
1314
+ // }
1315
+ // getListing();
1316
+ // }, [listingId, listing]);
1317
+ // useEffect(() => {
1318
+ // if (student?.id !== application?.uid) {
1319
+ // if (user.userType === "Students") {
1320
+ // setStudent(user);
1321
+ // } else if (user.product === "providers" && application?.uid) {
1322
+ // firebaseQuery.getDocData(["users", application.uid]).then((s) => setStudent(s as UserData));
1323
+ // }
1324
+ // }
1325
+ // }, []);
1326
+ // useEffect(() => {
1327
+ // setFListing(Object.keys(listing || {}).length > 5 ? listing : undefined);
1328
+ // }, [listing]);
1329
+ // useEffect(() => {
1330
+ // if (provider?.profile) return;
1331
+ // if (!provider?.id) return;
1332
+ // getDownloadURL(ref(storage, `providers/${provider?.id}/profilePic.png`)).then(setProfileUrl).catch(() => null);
1333
+ // }, [provider]);
1334
+ // useEffect(() => {
1335
+ // console.log("APPLICATIONID", applicationId);
1336
+ // if (!applicationId) {
1337
+ // if (!listingId) return;
1338
+ // firebaseQuery.getDocsWhere("applications", [where("status", "not-in", ["approved", "declined"]), where("uid", "==", user.id), where("listingId", "==", listingId)]).then((existingApplication) => {
1339
+ // console.log("EXISTING", existingApplication);
1340
+ // // get uploaded files
1341
+ // if (existingApplication && Object.keys(existingApplication).length) {
1342
+ // setFApplication(Object.values(existingApplication)[0]);
1343
+ // setFApplicationId(Object.keys(existingApplication)[0]);
1344
+ // }
1345
+ // });
1346
+ // return;
1347
+ // }
1348
+ // if (applicationId) {
1349
+ // setFApplicationId(applicationId);
1350
+ // if (application) {
1351
+ // let applicationWithoutAdditionalData = {...(application || {})} as any;
1352
+ // delete applicationWithoutAdditionalData.listing;
1353
+ // delete applicationWithoutAdditionalData.address;
1354
+ // delete applicationWithoutAdditionalData.provider;
1355
+ // setFApplication(applicationWithoutAdditionalData);
1356
+ // } else {
1357
+ // firebaseQuery.getDocData(["applications", applicationId]).then(setFApplication);
1358
+ // }
1359
+ // }
1360
+ // }, [application, applicationId]);
1361
+ // const getCurrentStage = async (stage: number): Promise<{
1362
+ // stage: ApplicantStage; completedSections: {
1363
+ // submitted?: string | undefined;
1364
+ // filesViewed?: string[] | undefined;
1365
+ // formsCompleted?: {
1366
+ // [key: string]: unknown;
1367
+ // } | undefined;
1368
+ // filesUploaded?: {
1369
+ // [key: number]: string[];
1370
+ // } | undefined;
1371
+ // };
1372
+ // }> => {
1373
+ // console.log("fLSITING CURRENT STAGE", fListing);
1374
+ // if (!fListing) throw new Error("Listing deleted");
1375
+ // if (!fListing?.applicantWorkflowId) throw new Error("No workflow stage");
1376
+ // const mApplicantWorkflow = (await firebaseQuery.getDocData(["applicantWorkflows", fListing.applicantWorkflowId]) as ApplicantWorkflow);
1377
+ // const stageObj = mApplicantWorkflow?.workflow?.find((s) => s.id === stage);
1378
+ // if (!stageObj) throw new Error("Can't find stage.");
1379
+ // const applicantFiles = stageObj.files ? Object.fromEntries(await Promise.all(stageObj.files?.map(async (fileId) => {
1380
+ // const file = await firebaseQuery.getDocData(["files", fileId]);
1381
+ // file.url = await getDownloadURL(ref(storage, `providers/${mApplicantWorkflow?.oId}/${file.fileName}`));
1382
+ // return [fileId, file];
1383
+ // }))) : [];
1384
+ // const applicantForms = stageObj.forms ? Object.fromEntries(await Promise.all(stageObj.forms?.map(async (formId) => {
1385
+ // return [formId, await firebaseQuery.getDocData(["forms", formId])];
1386
+ // }))) : [];
1387
+ // stageObj.viewableFiles = applicantFiles;
1388
+ // stageObj.formDetails = applicantForms;
1389
+ // return {stage: stageObj, completedSections: fApplication?.completedSections?.[stage] || {}};
1390
+ // };
1391
+ // useEffect(() => {
1392
+ // const getUploadedFiles = async () => {
1393
+ // if (!fApplication.completedSections) {
1394
+ // setUploadedFiles({});
1395
+ // return
1396
+ // };
1397
+ // const fileIds = Object.values(fApplication.completedSections)
1398
+ // .flatMap(stageData =>
1399
+ // Object.values(stageData.filesUploaded || {}).flatMap(fileIds => fileIds)
1400
+ // );
1401
+ // const fileDataPromises = fileIds.map(async (fileId) => {
1402
+ // const fileData = await firebaseQuery.getDocData(["files", fileId]) as FileItem;
1403
+ // fileData.url = await getDownloadURL(ref(storage, `userFiles/${fileData.fileName}`));
1404
+ // return [fileId, fileData] as [string, FileItem]
1405
+ // });
1406
+ // const fileDataArray = await Promise.all(fileDataPromises);
1407
+ // const fileDataObj = Object.fromEntries(fileDataArray)
1408
+ // setUploadedFiles(fileDataObj)
1409
+ // }
1410
+ // const addApplication = async () => {
1411
+ // console.log("ADDING APPLICATION");
1412
+ // if (!fListing || !fListing?.id || !fProvider?.id || !student?.id) return;
1413
+ // const applicationData = {
1414
+ // uid: student.id,
1415
+ // listingId: fListing?.id,
1416
+ // addressId: fListing.addressId,
1417
+ // applicantWorkflowId: fListing?.applicantWorkflowId,
1418
+ // providerId: fProvider.id,
1419
+ // stage: 1,
1420
+ // status: "draft",
1421
+ // created: (new Date()).toISOString(),
1422
+ // ...fApplication,
1423
+ // } as Partial<Application>;
1424
+ // const mApplicationId = (await firebaseQuery.add(["applications"], applicationData)).id;
1425
+ // console.log("APPLICATION ADDED");
1426
+ // setFApplicationId(mApplicationId);
1427
+ // setFApplication(applicationData);
1428
+ // setDraftSaved(true);
1429
+ // return;
1430
+ // };
1431
+ // getUploadedFiles();
1432
+ // console.log("Checking IDs");
1433
+ // if (!fListing || !fListing?.id || !fProvider?.id || !student?.id) return;
1434
+ // if (user.product === "providers") return;
1435
+ // console.log("Checking dates and sections");
1436
+ // if (!fApplication.completedSections && !fApplication.startDate && !fApplication.endDate) return;
1437
+ // console.log("Application updated");
1438
+ // if (!fApplicationId && !applicationId) {
1439
+ // // save new
1440
+ // console.log("Add application")
1441
+ // addApplication();
1442
+ // return;
1443
+ // }
1444
+ // // update
1445
+ // firebaseQuery.update(["applications", (fApplicationId || applicationId) as string], fApplication);
1446
+ // setDraftSaved(true);
1447
+ // }, [fApplication]);
1448
+ // const openSuccessPopup = (type: "submitted"|"draftSaved"|"stageComplete"|"outcome") => {
1449
+ // setSuccessPopup(type);
1450
+ // setTimeout(() => {
1451
+ // // onClose();
1452
+ // }, 1500);
1453
+ // };
1454
+ // useEffect(() => {
1455
+ // const areStagesCompleted = async ():Promise<boolean|undefined> => {
1456
+ // if (!fListing) return;
1457
+ // if (fApplication.stage === undefined) return undefined;
1458
+ // const currentStage = await getCurrentStage(fApplication.stage);
1459
+ // console.log("Checking current stage is complete");
1460
+ // for (const fileViewed of currentStage.stage?.files || []) {
1461
+ // console.log("Checking file viewed", fileViewed, "in", currentStage?.completedSections?.filesViewed);
1462
+ // if (!currentStage?.completedSections?.filesViewed?.includes(fileViewed)) {
1463
+ // console.log("File not viewed");
1464
+ // return false;
1465
+ // } else {
1466
+ // console.log("File viewed");
1467
+ // }
1468
+ // }
1469
+ // for (const formCompleted of currentStage?.stage?.forms || []) {
1470
+ // console.log("Checking form completed", formCompleted, "in", currentStage?.completedSections?.formsCompleted);
1471
+ // if (!Object.keys(currentStage?.completedSections?.formsCompleted || {}).includes(formCompleted)) {
1472
+ // console.log("Form not completed");
1473
+ // return false;
1474
+ // } else {
1475
+ // console.log("Form completed")
1476
+ // }
1477
+ // }
1478
+ // for (let i = 0; i++; i < (currentStage?.stage?.requiredFiles || []).length) {
1479
+ // if (!Object.keys(currentStage?.completedSections?.filesUploaded || {}).includes(i.toString())) {
1480
+ // console.log("Form not uploaded");
1481
+ // return false;
1482
+ // } else {
1483
+ // console.log("Form uploaded");
1484
+ // }
1485
+ // }
1486
+ // return true;
1487
+ // };
1488
+ // areStagesCompleted().then(setCurrentStageComplete);
1489
+ // }, [fApplication, fListing])
1490
+ // const viewFile = (file: string, onOpen: (url: string) => void) => {
1491
+ // if (fApplication.reqUserType !== user.userType) return;
1492
+ // if (fApplication.stage === undefined) throw new Error("Missing applciation stage.")
1493
+ // if (!fListing) throw new Error("No associated listing.");
1494
+ // const viewableFiles = fListing?.applicantWorkflow?.find((stage) => stage.id === fApplication.stage)?.viewableFiles;
1495
+ // setFApplication((a) => {
1496
+ // const oldA = {...a};
1497
+ // const viewedFiles = a.completedSections?.[1]?.filesViewed || [];
1498
+ // if (viewedFiles?.includes(file)) return a;
1499
+ // viewableFiles?.[file].url && onOpen(viewableFiles?.[file].url);
1500
+ // viewedFiles?.push(file);
1501
+ // const newA = editNestedObject(["completedSections", 1, "filesViewed"], oldA, viewedFiles) as Partial<Application>;
1502
+ // return newA;
1503
+ // });
1504
+ // };
1505
+ // const addFile = (files: string[], fileId: number) => {
1506
+ // if (fApplication.reqUserType !== user.userType) throw new Error(`Incorrect user type. Expected ${fApplication.reqUserType}, got: ${user.userType}`);
1507
+ // if (fApplication.stage === undefined) throw new Error("Missing applciation stage.")
1508
+ // if (!files.length) throw new Error("No files to upload");
1509
+ // setFApplication((a) => editNestedObject(["completedSections", fApplication.stage as number, "filesUploaded", fileId], a, files) as Application);
1510
+ // };
1511
+ // const setFormComplete = (formId: string, e: {[key: string]: unknown}) => {
1512
+ // if (fApplication.reqUserType !== user.userType) throw new Error(`Incorrect user type. Expected ${fApplication.reqUserType}, got: ${user.userType}`);
1513
+ // if (fApplication.stage === undefined) throw new Error("Missing applciation stage.")
1514
+ // setFApplication((a) => editNestedObject(["completedSections", fApplication.stage as number, "formsCompleted", formId], a, e) as Application);
1515
+ // };
1516
+ // const successText = {
1517
+ // submitted: {
1518
+ // title: "Application submitted",
1519
+ // desc: "We've sent your application to the placement provider. You will hear what the next steps are soon.",
1520
+ // },
1521
+ // draftSaved: {
1522
+ // title: "Draft saved",
1523
+ // desc: "Your draft has been saved. Go to the 'Applications' section from your home screen to edit.",
1524
+ // },
1525
+ // stageComplete: {
1526
+ // title: "Stage complete",
1527
+ // desc: "We have sent this to the next stage in the application process. We will update you with any progress.",
1528
+ // },
1529
+ // outcome: {
1530
+ // title: "Outcome submitted",
1531
+ // desc: "We have sent the student an email with the outcome of their application.",
1532
+ // },
1533
+ // };
1534
+ // const onFApply = async (draft?: boolean) => {
1535
+ // if (draft) {
1536
+ // openSuccessPopup("draftSaved")
1537
+ // return;
1538
+ // }
1539
+ // if (!fApplicationId) return;
1540
+ // // Check all items have been filled in.
1541
+ // if (!fApplication.startDate || !fApplication.endDate) throw new Error("Please select dates for your placement.");
1542
+ // await executeCallable("applications-submit", {applicationId: fApplicationId});
1543
+ // const newApplication = await firebaseQuery.getDocData(["applications", fApplicationId]) as Application;
1544
+ // setFApplication(newApplication);
1545
+ // openSuccessPopup("submitted")
1546
+ // };
1547
+ // const progressStage = async (type: number|"accept"|"reject", e?: {feedback?: string}) => {
1548
+ // // Check all stages completed.
1549
+ // if (!fApplicationId) return;
1550
+ // if (!currentStageComplete) throw new Error("Complete all forms before submitting.");
1551
+ // if (fApplication.reqUserType !== user.userType) throw new Error(`Incorrect user type. Expected ${fApplication.reqUserType}, got: ${user.userType}`);
1552
+ // if (fApplication.stage === undefined) throw new Error("Missing applciation stage.")
1553
+ // await executeCallable("applications-changeStage", {applicationId: fApplicationId, type: type, feedback: e?.feedback});
1554
+ // const newApplication = await firebaseQuery.getDocData(["applications", fApplicationId]) as Application;
1555
+ // setFApplication(newApplication);
1556
+ // };
1557
+ // return {successText, onFApply, progressStage, currentStageComplete, uploadedFiles, getCurrentStage, setFormComplete, viewFile, addFile, setSuccessPopup, openSuccessPopup, setFApplication, fApplication, draftSaved, profileUrl, successPopup, fApplicationId, fListing, student, fProvider}
1558
+ // }
1602
1559
  function useProposePlacementRenderer({ user, orgContext, placement }) {
1603
1560
  const [businessSectionComplete, setBusinessSectionComplete] = (0, react_1.useState)(false);
1604
1561
  const [addressSectionComplete, setAddressSectionComplete] = (0, react_1.useState)(false);
@@ -1649,11 +1606,9 @@ function useProposePlacementRenderer({ user, orgContext, placement }) {
1649
1606
  }, [cohort]);
1650
1607
  const submitSection = (type, data) => {
1651
1608
  setFormData((f) => {
1652
- const { id, ...values } = data;
1653
1609
  return {
1654
1610
  ...f,
1655
- ...values,
1656
- id: ((placement === null || placement === void 0 ? void 0 : placement.placementId) || (formData === null || formData === void 0 ? void 0 : formData.id))
1611
+ ...data
1657
1612
  };
1658
1613
  });
1659
1614
  if ((placement === null || placement === void 0 ? void 0 : placement.placementId) && type === "dates") {
@@ -2422,34 +2377,34 @@ function useGenericWorkflowEditor({ user, initialData, defaultData, onSubmit })
2422
2377
  includedForms, fSubmitWorkflow, openPopup, snackbar, setSnackbar, setMousePosFunc, mousePos, tutorialActive,
2423
2378
  onDeleteArrow, fWorkflowNodes, containerRef, setError, setArrows, setFWorkflowNodes } });
2424
2379
  }
2425
- function useInstitutePlacementListingHandler({ user }) {
2380
+ function useInstituteProviderContactsHandler({ user }) {
2426
2381
  const [emptyCellsWarning, setEmptyCellsWarning] = (0, react_1.useState)(false);
2427
2382
  const [alert, setAlert] = (0, react_1.useState)();
2428
- const requiredFields = ["name", "jobTitle", "email", "addressOne", "city", "postCode", "country"];
2383
+ const requiredFields = ["business", "forename", "email"];
2429
2384
  const { execute } = (0, firebase_1.useExecuteCallableJob)({ user: user });
2430
- const checkData = (placements) => {
2385
+ const checkData = (providerContacts) => {
2431
2386
  setAlert(undefined);
2432
- placements = placements.filter((u) => Object.entries(u).some(([, v]) => v));
2433
- if (!Object.entries(placements)) {
2387
+ providerContacts = providerContacts.filter((u) => Object.entries(u).some(([, v]) => v));
2388
+ if (!Object.entries(providerContacts)) {
2434
2389
  return [];
2435
2390
  }
2436
- console.log("P", placements);
2437
- if (placements.filter((u) => u.email).length < placements.length) {
2391
+ console.log("P", providerContacts);
2392
+ if (providerContacts.filter((u) => u.email).length < providerContacts.length) {
2438
2393
  setAlert({ msg: "Your data contains missing email addresses.", severity: "error" });
2439
2394
  return false;
2440
2395
  }
2441
2396
  let emptyOptionalCell = false;
2442
2397
  let emptyRequiredCell = false;
2443
- for (const placement of placements) {
2444
- if (!checkEmailValidity(placement)) {
2398
+ for (const providerContact of providerContacts) {
2399
+ if (!checkEmailValidity(providerContact)) {
2445
2400
  return false;
2446
2401
  }
2447
- if (Object.keys(placement).includes("")) {
2402
+ if (Object.keys(providerContact).includes("")) {
2448
2403
  setAlert({ msg: "Data cannot be uploaded in unnamed columns.", severity: "error" });
2449
2404
  return false;
2450
2405
  }
2451
- for (const field in placement) {
2452
- if (!placement[field]) {
2406
+ for (const field in providerContact) {
2407
+ if (!providerContact[field]) {
2453
2408
  if (requiredFields.includes(field)) {
2454
2409
  setAlert({ msg: "All users must contain " + requiredFields.join(", "), severity: "error" });
2455
2410
  emptyRequiredCell = true;
@@ -2469,39 +2424,26 @@ function useInstitutePlacementListingHandler({ user }) {
2469
2424
  else {
2470
2425
  setEmptyCellsWarning(false);
2471
2426
  }
2472
- return placements;
2427
+ return providerContacts;
2473
2428
  };
2474
- const checkEmailValidity = (placement) => {
2475
- if (!(0, util_1.validateEmail)(placement.email)) {
2476
- setAlert({ msg: `Error in email formatting: ${placement.email}. Amend errors and reupload.`, severity: "error" });
2429
+ const checkEmailValidity = (providerContact) => {
2430
+ if (!(0, util_1.validateEmail)(providerContact.email)) {
2431
+ setAlert({ msg: `Error in email formatting: ${providerContact.email}. Amend errors and reupload.`, severity: "error" });
2477
2432
  return false;
2478
2433
  }
2479
2434
  return true;
2480
2435
  };
2481
- const uploadPlacements = async (placements) => {
2482
- let fPlacements = [];
2483
- console.log("PP", placements);
2484
- const cleanUpload = checkData(placements);
2436
+ const uploadProviderContacts = async (providers, schoolId) => {
2437
+ let fProviders = [];
2438
+ console.log("PP", providers);
2439
+ const cleanUpload = checkData(providers);
2485
2440
  if (!cleanUpload) {
2486
2441
  return false;
2487
2442
  }
2488
- fPlacements = cleanUpload;
2443
+ fProviders = cleanUpload;
2489
2444
  setAlert(undefined);
2490
- if (fPlacements.length) {
2491
- const formattedPlacements = fPlacements.map((v) => ({
2492
- name: v.provider,
2493
- title: v.jobTitle,
2494
- providerEmail: v.email,
2495
- providerPhone: v.phone,
2496
- ["address-line1"]: v.addressOne,
2497
- ["address-line2"]: v.addressTwo,
2498
- locality: v.city,
2499
- postal_code: v.postcode,
2500
- country: v.country,
2501
- }));
2502
- console.log("P", placements);
2503
- console.log("callable params", { placements: formattedPlacements, instituteId: user.product === "admin" ? "admin" : user.oId });
2504
- execute("placementListing-add", { data: formattedPlacements, instituteId: user.product === "admin" ? "admin" : user.oId });
2445
+ if (fProviders.length) {
2446
+ execute("providerContacts-add", { providerContacts: fProviders, instituteId: user.product === "admin" ? "admin" : user.oId, schoolId: schoolId });
2505
2447
  }
2506
2448
  return true;
2507
2449
  };
@@ -2509,7 +2451,7 @@ function useInstitutePlacementListingHandler({ user }) {
2509
2451
  setAlert(undefined);
2510
2452
  setEmptyCellsWarning(false);
2511
2453
  };
2512
- return ({ ...{ uploadPlacements, alert, onChange } });
2454
+ return ({ ...{ uploadProviderContacts, alert, onChange } });
2513
2455
  }
2514
2456
  function useGetIndividualPlacementForPlacementPage({ user, placementId, organisation }) {
2515
2457
  var _a;
@@ -2523,7 +2465,7 @@ function useGetIndividualPlacementForPlacementPage({ user, placementId, organisa
2523
2465
  const [disableEmail, setDisableEmail] = (0, react_1.useState)({ parent: false, provider: false });
2524
2466
  const [rejectELIPopup, setRejectELIPopup] = (0, react_1.useState)(false);
2525
2467
  const [eliPopupOpen, setEliPopupOpen] = (0, react_1.useState)(false);
2526
- const [eliURL, setELIURL] = (0, react_1.useState)("");
2468
+ const [eliData, setELIData] = (0, react_1.useState)();
2527
2469
  const [rejectExternalDocPopup, setRejectExternalDocPopup] = (0, react_1.useState)(false);
2528
2470
  const [externalDocPopupOpen, setExternalDocPopupOpen] = (0, react_1.useState)(false);
2529
2471
  const [riskAssessmentURL, setRiskAssessmentURL] = (0, react_1.useState)("");
@@ -2674,10 +2616,10 @@ function useGetIndividualPlacementForPlacementPage({ user, placementId, organisa
2674
2616
  setShareStudentRequestPopup(true);
2675
2617
  }
2676
2618
  if (e === "noInsurance") {
2677
- if (!eliURL) {
2619
+ if (!eliData) {
2678
2620
  const storageRef = (0, storage_1.ref)(firebaseConfig_1.storage, `insurance/${placement.providerId}.pdf`);
2679
- const file = await (0, storage_1.getDownloadURL)(storageRef);
2680
- setELIURL(file);
2621
+ const file = await (0, storage_1.getDownloadURL)(storageRef).catch(() => placement.insuranceSkippedReason);
2622
+ setELIData(file);
2681
2623
  }
2682
2624
  setEliPopupOpen(true);
2683
2625
  }
@@ -2710,14 +2652,14 @@ function useGetIndividualPlacementForPlacementPage({ user, placementId, organisa
2710
2652
  const approveELI = async () => {
2711
2653
  if (!placement)
2712
2654
  return;
2713
- await (0, firebase_1.executeCallable)("insurance-approve", { oId: user.oId, providerId: placement.providerId });
2655
+ await (0, firebase_1.executeCallable)("insurance-approve", { oId: user.oId, providerContactId: placement.providerContactId });
2714
2656
  setEliPopupOpen(false);
2715
2657
  };
2716
2658
  const rejectELI = async ({ reason }) => {
2717
2659
  if (!placement || !institute)
2718
2660
  return;
2719
- console.log("Reject", { reason: reason, placement: placement, instituteName: institute.name, staffEmail: user.email });
2720
- await (0, firebase_1.executeCallable)("insurance-reject", { reason: reason, placementId: placementId, instituteName: institute.name, staffEmail: user.email });
2661
+ console.log("Reject", { reason: reason, placement: placement, instituteName: institute.name });
2662
+ await (0, firebase_1.executeCallable)("insurance-reject", { reason: reason, placementId: placementId, instituteName: institute.name });
2721
2663
  setRejectELIPopup(false);
2722
2664
  setEliPopupOpen(false);
2723
2665
  };
@@ -2736,10 +2678,12 @@ function useGetIndividualPlacementForPlacementPage({ user, placementId, organisa
2736
2678
  if (!placement)
2737
2679
  return;
2738
2680
  if (!placement.providerId) {
2739
- const res = await (0, firebase_1.executeCallable)("placement-uploadProviderDetails", {
2740
- pId: placementId,
2741
- placement: Object.fromEntries(Object.entries(placement).filter(([k]) => k !== "contactId")),
2742
- stage: wStage,
2681
+ const res = await (0, firebase_1.executeCallable)("providerContacts-uploadProviderDetails", {
2682
+ placement: {
2683
+ id: placementId,
2684
+ data: Object.fromEntries(Object.entries(placement).filter(([k]) => k !== "contactId")),
2685
+ stage: wStage,
2686
+ },
2743
2687
  skipSearch: true
2744
2688
  }).catch((e) => {
2745
2689
  throw e;
@@ -2765,7 +2709,7 @@ function useGetIndividualPlacementForPlacementPage({ user, placementId, organisa
2765
2709
  throw new Error("Must be a student to withdraw.");
2766
2710
  await (0, firebase_1.executeCallable)("placement-withdraw", { placementId: placementId });
2767
2711
  };
2768
- return { placement, wStage, student, workflow, editable, withdrawFromPlacementPopup, addOnboardingDocsPopup, setAddOnboardingDocsPopup, dismissOnboardingPopup, setDismissOnboardingPopup, setWithdrawFromPlacementPopup, withdrawFromPlacement, onFlagClick, setUploadInsurance, setUploadProviderDocPopup, setUploadRA, setUploadDBS, onboardingStatus, setSkipStagePopup, onboardingPopup, setViewExternalLinkPopup, setOnboardingPopup, setRejectELIPopup, eliURL, 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 };
2712
+ 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 };
2769
2713
  }
2770
2714
  function useOnboardingPopup({ onboarding, providerId, placementId, user, onClose }) {
2771
2715
  const [fileUploadPopup, setFileUploadPopup] = (0, react_1.useState)(false);
@@ -3041,13 +2985,7 @@ function useLoadListings(user, queryConstraint, request) {
3041
2985
  }), "placementListings", constraints, undefined, true);
3042
2986
  };
3043
2987
  (0, react_1.useEffect)(() => {
3044
- let unsubscribe;
3045
2988
  loadListings();
3046
- return () => {
3047
- if (unsubscribe) {
3048
- unsubscribe(); // Unsubscribe from the snapshot listener when the component unmounts
3049
- }
3050
- };
3051
2989
  // eslint-disable-next-line react-hooks/exhaustive-deps
3052
2990
  }, [queryConstraints]);
3053
2991
  const onScrollBottom = () => {
@@ -3123,13 +3061,7 @@ function useLoadProviderPlacements(user, queryConstraint, placementId) {
3123
3061
  }), "placements", constraints, undefined, true);
3124
3062
  };
3125
3063
  (0, react_1.useEffect)(() => {
3126
- let unsubscribe;
3127
3064
  loadListings();
3128
- return () => {
3129
- if (unsubscribe) {
3130
- unsubscribe(); // Unsubscribe from the snapshot listener when the component unmounts
3131
- }
3132
- };
3133
3065
  // eslint-disable-next-line react-hooks/exhaustive-deps
3134
3066
  }, [queryConstraints]);
3135
3067
  const onScrollBottom = () => {
@@ -3209,13 +3141,7 @@ function useLoadApplications({ user, applicationType, listingId, queryConstraint
3209
3141
  }), "applications", constraints, undefined, true);
3210
3142
  };
3211
3143
  (0, react_1.useEffect)(() => {
3212
- let unsubscribe;
3213
3144
  loadApplications();
3214
- return () => {
3215
- if (unsubscribe) {
3216
- unsubscribe(); // Unsubscribe from the snapshot listener when the component unmounts
3217
- }
3218
- };
3219
3145
  // eslint-disable-next-line react-hooks/exhaustive-deps
3220
3146
  }, [type, queryConstraints]);
3221
3147
  const onScrollBottom = () => {
@@ -3226,7 +3152,7 @@ function useLoadApplications({ user, applicationType, listingId, queryConstraint
3226
3152
  };
3227
3153
  return { applications, type, setType, onScrollBottom, loading, changeQueryConstraints };
3228
3154
  }
3229
- function useDataViewerPaginator({ view: initialView, sorts, queryLimit, additionalEntryProcessing, formatItems, snapshot, filters: initialFilters, onSearch, data }) {
3155
+ function useDataViewerPaginator({ view: initialView, sorts, queryLimit = 10, additionalEntryProcessing, formatItems, snapshot, filters: initialFilters, onSearch, data }) {
3230
3156
  const [tableData, setTableData] = (0, react_1.useState)(Array.isArray(data) ? Object.fromEntries(Object.entries(data).slice(0, queryLimit)) : {});
3231
3157
  const [page, setPage] = (0, react_1.useState)([1, 0]);
3232
3158
  const [view, setView] = (0, react_1.useState)(initialView);
@@ -3279,8 +3205,7 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit, addition
3279
3205
  }
3280
3206
  };
3281
3207
  const getDataFromQuery = async (itemList = {}, currentQueryAnchor = queryAnchor, cursorDirection, prevEntries = prevEntryIds, loadMoreFromQuery = false) => {
3282
- if (!filters)
3283
- return;
3208
+ // if (!filters) return;
3284
3209
  setLoading(true);
3285
3210
  if (!Array.isArray(data)) {
3286
3211
  setTableDataFromDefinedData();
@@ -3432,8 +3357,11 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit, addition
3432
3357
  Object.keys(itemList).length === 0 &&
3433
3358
  currentQueryAnchor.endQueryPos + 1 === data.length &&
3434
3359
  page[0] > 1) {
3435
- setTableData({});
3360
+ if (view === "table") {
3361
+ setTableData({});
3362
+ }
3436
3363
  setQueryAnchor((a) => ({ ...a, startKey: "" }));
3364
+ setLoading("loaded");
3437
3365
  return;
3438
3366
  }
3439
3367
  if (querySnapshot.size < queryLimit) {
@@ -3468,8 +3396,21 @@ function useDataViewerPaginator({ view: initialView, sorts, queryLimit, addition
3468
3396
  reset();
3469
3397
  }, [filters]);
3470
3398
  (0, react_1.useEffect)(() => {
3399
+ console.log("View reset.");
3400
+ reset();
3401
+ }, [view]);
3402
+ (0, react_1.useEffect)(() => {
3403
+ console.log("search reset.");
3404
+ reset();
3405
+ }, [searchString]);
3406
+ (0, react_1.useEffect)(() => {
3407
+ console.log("data reset.");
3408
+ reset();
3409
+ }, [data]);
3410
+ (0, react_1.useEffect)(() => {
3411
+ console.log("sort reset.");
3471
3412
  reset();
3472
- }, [view, searchString, data, sort]);
3413
+ }, [sort]);
3473
3414
  // Fetch new data when queries or page change
3474
3415
  (0, react_1.useEffect)(() => {
3475
3416
  getDataFromQuery();