diff --git a/backend/typescript/rest/serviceRequestRoutes.ts b/backend/typescript/rest/serviceRequestRoutes.ts index 20a5278..293b440 100644 --- a/backend/typescript/rest/serviceRequestRoutes.ts +++ b/backend/typescript/rest/serviceRequestRoutes.ts @@ -160,4 +160,26 @@ serviceRequestRouter.delete("/delete/:id", isAuthorizedByRole(new Set(["ADMIN", } }); +/* Get user by email - this is for displaying first/last name for email invitation*/ +serviceRequestRouter.get("/user-by-email", isAuthorizedByRole(new Set(["ADMIN", "VOLUNTEER"])), async (req, res) => { + const { email } = req.query; + + if (!email || typeof email !== "string") { + return res.status(400).json({ error: "A valid email query parameter is required." }); + } + + try { + const user = await userService.getUserByEmail(email.trim()); + if (user) { + res.status(200).json({ firstName: user.firstName, lastName: user.lastName }); + } else { + res.status(404).json({ message: "User not found" }); + } + } catch (error: unknown) { + res.status(404).json({ error: getErrorMessage(error) }); + } +}); + + + export default serviceRequestRouter; diff --git a/backend/typescript/services/implementations/userService.ts b/backend/typescript/services/implementations/userService.ts index 8e0523c..1190132 100644 --- a/backend/typescript/services/implementations/userService.ts +++ b/backend/typescript/services/implementations/userService.ts @@ -72,6 +72,7 @@ class UserService implements IUserService { throw new Error(`userId with authId ${firebaseUser.uid} not found.`); } } catch (error: unknown) { + console.log("CATCH ERROR") Logger.error(`Failed to get user. Reason = ${getErrorMessage(error)}`); throw error; } diff --git a/frontend/src/APIClients/ServiceRequestAPIClient.ts b/frontend/src/APIClients/ServiceRequestAPIClient.ts index 7a29179..320863a 100644 --- a/frontend/src/APIClients/ServiceRequestAPIClient.ts +++ b/frontend/src/APIClients/ServiceRequestAPIClient.ts @@ -77,4 +77,26 @@ const post = async ({ } }; -export default { get, getPlatformSignups, post }; \ No newline at end of file +const getUserByEmail = async (email: string): Promise<{ firstName: string; lastName: string } | null> => { + const bearerToken = `Bearer ${getLocalStorageObjProperty( + AUTHENTICATED_USER_KEY, + "accessToken", + )}`; + try { + console.log(`/user-by-email?email=${encodeURIComponent(email)}`) + const { data } = await baseAPIClient.get(`/serviceRequests/user-by-email?email=${encodeURIComponent(String(email))}`, { + headers: { Authorization: bearerToken }, + }); + return data; // { firstName: string; lastName: string } + } catch (error: any) { + if (error.response?.status === 404) { + console.warn("User not found for email:", email); + return null; + } + // console.error("Error fetching user by email:", error); + throw error; + } +}; + + +export default { get, getPlatformSignups, post, getUserByEmail }; \ No newline at end of file diff --git a/frontend/src/components/common/NavBarVolunteer.tsx b/frontend/src/components/common/NavBarVolunteer.tsx index 1bef582..64af0ed 100644 --- a/frontend/src/components/common/NavBarVolunteer.tsx +++ b/frontend/src/components/common/NavBarVolunteer.tsx @@ -102,9 +102,6 @@ const NavBarVolunteer: React.FC = ({firstName, lastName, r Contact Us - {/* */} {/* TODO: add logic behind notification button */} { const { requestName, shiftTime, shiftEndTime, frequency, currentEmail, inviteEmails, requestType } = data; @@ -87,7 +88,7 @@ const CreateShiftMain: CreateShiftFormStepComponentType = ({ onSubmit, updateFie } }; - const handleAddEmail = () => { + const handleAddEmail = async () => { if (currentEmail && currentEmail.trim()) { const emailError = validateEmail(currentEmail); if (emailError) { @@ -99,12 +100,34 @@ const CreateShiftMain: CreateShiftFormStepComponentType = ({ onSubmit, updateFie duration: 5000, isClosable: true, }); - return; // Stop execution if email is invalid + return; } - const updatedEmails = [...(inviteEmails || []), currentEmail.trim()]; - updateFields({ inviteEmails: updatedEmails, currentEmail: "" }); + + try { + const user = await ServiceRequestAPIClient.getUserByEmail(currentEmail.trim()); + + if (user) { + // If user exists in the database, add their full name + const displayName = capitalizeName(`${user.firstName} ${user.lastName}`); + const updatedEmails = [...(inviteEmails || []), displayName]; + updateFields({ inviteEmails: updatedEmails, currentEmail: "" }); + } else { + // If user doesn't exist, add the email as-is (this part doesn't work right now so I put the logic in the catch block) + const updatedEmails = [...(inviteEmails || []), currentEmail.trim()]; + updateFields({ inviteEmails: updatedEmails, currentEmail: "" }); + } + } catch (error) { + console.error("User not Found:", error); + // Add the email if there's an error + const updatedEmails = [...(inviteEmails || []), currentEmail.trim()]; + updateFields({ inviteEmails: updatedEmails, currentEmail: "" }); + } + console.log(inviteEmails); } }; + + + const handleRemoveEmail = (index: number) => { const updatedEmails = (inviteEmails || []).filter((_, i) => i !== index); diff --git a/frontend/src/utils/FormatUtils.ts b/frontend/src/utils/FormatUtils.ts index ce7e6dd..b481caa 100644 --- a/frontend/src/utils/FormatUtils.ts +++ b/frontend/src/utils/FormatUtils.ts @@ -2,3 +2,12 @@ export const titleCase = (value: string): string => { return value[0].toUpperCase() + value.slice(1).toLowerCase(); }; + + +export const capitalizeName = (name: string) => { + if (!name) return ''; + return name + .split(' ') + .map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()) + .join(' '); +}; \ No newline at end of file