Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Michael Qian - Query email in db for inviteEmails functionality #78

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions backend/typescript/rest/serviceRequestRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
1 change: 1 addition & 0 deletions backend/typescript/services/implementations/userService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
24 changes: 23 additions & 1 deletion frontend/src/APIClients/ServiceRequestAPIClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,26 @@ const post = async ({
}
};

export default { get, getPlatformSignups, post };
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 };
3 changes: 0 additions & 3 deletions frontend/src/components/common/NavBarVolunteer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,6 @@ const NavBarVolunteer: React.FC<NavBarVolunteerProps> = ({firstName, lastName, r
Contact Us
</Flex>
</ChakraLink>
{/* <button type="button" className="btn btn-primary" onClick={() => showToast("test@example.com")}>
Test Toast
</button> */}
<Spacer />
{/* TODO: add logic behind notification button */}
<ChakraLink
Expand Down
33 changes: 28 additions & 5 deletions frontend/src/components/pages/CreateShift/CreateShiftMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import moment from "moment";

import { Button, ModalBody, ModalFooter, Box, FormControl, FormLabel, Input, Flex, Select, NumberDecrementStepper, NumberIncrementStepper, NumberInput, NumberInputField, NumberInputStepper, InputRightElement, InputGroup, FormHelperText, Tag, TagLabel, TagCloseButton, Wrap, WrapItem, useToast} from "@chakra-ui/react";
import { CreateShiftFormStepComponentType, CreateShiftFormStepProps, Frequency, ServiceRequestType } from '../../../types/ServiceRequestTypes';
import { titleCase } from '../../../utils/FormatUtils';
import { capitalizeName, titleCase } from '../../../utils/FormatUtils';
import EARLIEST_SHIFT_TIME from '../../../constants/ServiceRequestConstants';
import { validateEmail } from '../../../utils/ValidationUtils'
import ServiceRequestAPIClient from "../../../APIClients/ServiceRequestAPIClient";

const CreateShiftMain: CreateShiftFormStepComponentType = ({ onSubmit, updateFields, updateErrorFields, data, errors }: CreateShiftFormStepProps): React.ReactElement => {
const { requestName, shiftTime, shiftEndTime, frequency, currentEmail, inviteEmails, requestType } = data;
Expand Down Expand Up @@ -87,7 +88,7 @@ const CreateShiftMain: CreateShiftFormStepComponentType = ({ onSubmit, updateFie
}
};

const handleAddEmail = () => {
const handleAddEmail = async () => {
if (currentEmail && currentEmail.trim()) {
const emailError = validateEmail(currentEmail);
if (emailError) {
Expand All @@ -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);
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/utils/FormatUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(' ');
};