import {onAuthStateChanged, signInWithEmailAndPassword} from "firebase/auth"; import {httpsCallable} from "firebase/functions"; import {SetStateAction} from "react"; import {getUser} from "./readDatabase"; import {ExternalEvent, UserData} from "../typeDefinitions"; import FirebaseQuery from "./firebaseQuery"; import {auth, functions} from "./firebaseConfig"; import {addJob, Job, updateJob} from "../features/jobs/jobsSlice"; import { useAppDispatch } from "../reduxHooks"; export const authListener = (setUser: SetStateAction) => { return onAuthStateChanged(auth, (aUser) => { if (!aUser) { console.log("User not logged in."); setUser(false) return; } console.log("User logged in."); if (!aUser.email) { setUser(false); return; }; getUser(aUser.uid, setUser); }); }; export const login = async (credentials: {email: string, password: string}) => { return await signInWithEmailAndPassword(auth, credentials.email, credentials.password); }; export type RegistrationData = { email: string, passwordOne: string, instituteName: string, "address-line1": string, "address-line2": string, locality: string, postal_code: string, country: string, first_name: string, family_name: string } export const register = async (credentials: RegistrationData, type:"Institute"|"Provider"|"Student") => { return await executeCallable(`registration-register${type}`, credentials).catch((e) => { console.log("Error in regsiter", e); throw e; }).then(async (res) => { if (type === "Student") { await login({email: credentials.email, password: credentials.passwordOne}); } return (res.data as { msg: {uid: string}}).msg.uid as string; }); }; export const executeCallable = async (functionName: string, data: unknown) => { const funcCallable = httpsCallable(functions, functionName); const res = await funcCallable(data).catch((e) => { console.log("callableError", functionName, e); throw e; }); return res as {data: any}; }; export function useExecuteCallableJob({user}:{user: UserData}) { type CallableFunctionJobs = "userManagement-addUsers"|"userManagement-activateUsers"| "userManagement-deactivateUsers"|"userManagement-deleteUsers"|"admissions-createCohort"|"userManagement-uploadAnalytics"| "providerContacts-add"|"userManagement-sendParentWelcomeEmail"|"events-sendExternalEventInvites"|"events-sendEmployerConfirmations"| "placementListing-addToCohort"|"placementListing-delist"|"providerContacts-delete"|"events-addStudents"|"registration-registerInstitutes"| "events-careersHubAddSchool"|"events-studentJoinEvent"|"events-addStudents"|"userManagement-addStudentsToCohort"|"userManagement-removeFromCohort" const dispatch = useAppDispatch(); const execute = async (functionName:CallableFunctionJobs, data:{[key:string]:unknown}) => { const getCode = () => { switch (functionName) { case "userManagement-addUsers": return { title: "Add users", description: `Adding ${(data as {users:unknown[]}).users.length} ${(data as {userType:string}).userType.toLowerCase()}`, }; case "userManagement-activateUsers": return { title: "Activating users", description: `Attempting activation of ${Array.isArray((data as {users:{[key:string]:unknown}}).users) ? "multiple" : Object.entries((data as {users:{[key: string]: UserData}}).users).length} users.`, }; case "userManagement-deactivateUsers": return { title: "Deactivating users", description: `Deactivating ${Array.isArray((data as {users:{[key:string]:unknown}}).users) ? "multiple" : Object.entries((data as {users:{[key: string]: UserData}}).users).length || "multiple"} users.`, }; case "userManagement-removeFromCohort": return { title: "Removing users from cohort", description: `Removing ${Array.isArray((data as {users:{[key:string]:unknown}}).users) ? "multiple" : Object.entries((data as {users:{[key: string]: UserData}}).users).length || "multiple"} users from your cohort.`, }; case "userManagement-deleteUsers": return { title: "Deleting users", description: `Attempting deletion of ${Array.isArray((data as {users:{[key:string]:unknown}}).users) ? "multiple" : Object.entries((data as {users:{[key: string]: UserData}}).users).length || "multiple"} users.`, }; case "providerContacts-add": return { title: "Adding employer contacts", description: `Attempting addition of ${(data as {providerContacts:[]}).providerContacts.length} employer contacts`, }; case "userManagement-sendParentWelcomeEmail": return { title: "Sending parent welcome emails", description: `Sending parent welcome emails to ${Array.isArray((data as {users:{[key:string]:unknown}}).users) ? "multiple" : Object.entries((data as {users:{[key: string]: UserData}}).users).length || "multiple"} users.`, }; case "events-sendExternalEventInvites": return { title: `Sending email invites for event: ${(data as {data:{eventName: string}}).data.eventName}`, description: `Sending email invites for your event: '${(data as {data:{eventName: string}}).data.eventName}'. Check the event page to view email interactions.`, }; case "events-sendEmployerConfirmations": return { title: `Sending employer confirmation emails for event: ${(data as {data: {event: Partial}}).data.event.name}`, description: `Sending employer confirmation emails for your event: '${(data as {data: {event: Partial}}).data.event.name}' to ${(data as {data: {selectedEmployers: { allSelected: boolean; search: string | undefined; filters: unknown[][] | undefined; }|{[key: string]: unknown}}}).data.selectedEmployers.allSelected ? "all employers" : `${Object.keys((data as {data: {selectedEmployers: { allSelected: boolean; search: string | undefined; filters: unknown[][] | undefined; }|{[key: string]: unknown}}}).data.selectedEmployers).length} employers`}. Check the event page to view email interactions.`, }; case "events-addStudents": return { title: `Adding students to event event: ${(data as {event:Partial}).event.name}`, description: `Sending student email invites for your event: '${(data as {event:Partial}).event.name}'. Check the event page to view email interactions.`, }; case "placementListing-addToCohort": return { title: "Adding placement listings to cohort", description: "Students will be able to view all listings you add.", }; case "placementListing-delist": return { title: "Delisting placement listings from cohort", description: "Students will not be able to view selected listings.", }; case "providerContacts-delete": return { title: "Deleting provider contacts from database", description: "You will no longer have access to these contacts.", }; case "registration-registerInstitutes": return { title: `Inviting ${(data as {schools: {}[]}).schools.length} school${(data as {schools: {}[], type: "hub"|"trust"}).schools.length === 1 ? "" : "s"} to your ${(data as {schools: {}[], type: "hub"|"trust"}).type === "hub" ? "Careers Hub" : "trust"}`, description: `Sending invites to ${(data as {schools: {}[]}).schools.length} school${(data as {schools: {}[]}).schools.length === 1 ? "" : "s"}. Check back later for responses.`, }; case "events-careersHubAddSchool": const schoolData = data.schools as {groups?: string[], schools?: "all"|string[]}; const text:string[] = []; if (schoolData.schools){ text.push(`${schoolData.schools.length} school${schoolData.schools.length === 1 ? "" : "s"}`); } if (schoolData.groups && schoolData.groups.length){ text.push(`${schoolData.groups.length} school group${schoolData.groups.length === 1 ? "" : "s"}`); } return { title: `Inviting ${text.join(" and ")} to your event`, description: `Sending invites to ${text.join(" and ")}. Check back later for responses.`, }; case "events-studentJoinEvent": return { title: "Adding students to your event", description: "Sending invites to students. Check back later for responses.", }; case "events-addStudents": return { title: "Adding students to your event", description: "Sending invites to students. Check back later for responses.", }; case "userManagement-addStudentsToCohort": return { title: "Adding students to your cohort", description: "Students will appear in the students tab of your cohort once complete.", }; default: return; } }; const date = new Date(); const firebaseQuery = new FirebaseQuery(); const jobObject = { title: getCode()?.title, description: getCode()?.description, status: "processing", viewedBy: [], started: date.toISOString(), updated: date.toISOString(), oId: user.oId, product: user.product, }; const jobId = (await firebaseQuery.add(["jobs"], jobObject)).id; console.log("jobId", jobId); dispatch(addJob({ jobId: jobId, job: jobObject, })); const items = {...data, jobId: jobId}; const funcCallable = httpsCallable(functions, functionName); console.log(items); funcCallable(items).then(async () => { const jobResolved = await firebaseQuery.getDocData(["jobs", jobId]) as Job; dispatch(updateJob({ jobId: jobId, data: jobResolved } as Partial)); }); return { severity: "success", message: "Waiting on database. Check the orange progress icon on the top right of the screen. Once completed, you may need to reload the page.", jobId: jobId, }; }; return {execute}; }