Skip to content

Commit

Permalink
Email notifications setting using checkbox (#244)
Browse files Browse the repository at this point in the history
* Made initial changes to implementation of emailNotifications and checkbox

* Changed default value

* Implemented if statements in both controllers before sending email and added updatePreferences in profileForm

* Updated functionality so checkbox actually reflects user's current preferences

* use hook-form for email preferences

* chore: Update query key in ProfileForm component

* Use /users instead of /users/search

* FIX: Checkbox does not show the actual state on page load, always remains unchecked.

---------

Co-authored-by: Akinfolami Akin-Alamu <aoa9@cornell.edu>
Co-authored-by: Jason Zheng <jasonz4200@gmail.com>
  • Loading branch information
3 people authored Jun 8, 2024
1 parent dc0ac40 commit b3cd1c2
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 44 deletions.
39 changes: 24 additions & 15 deletions backend/src/events/controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,11 +360,14 @@ const addAttendee = async (eventID: string, userID: string) => {
eventLocation,
textBody
);
await sendEmail(
userEmail,
"Your registration was successful.",
updatedHtml
);
const userPreferences = await userController.getUserPreferences(userID);
if (userPreferences?.preferences?.sendEmailNotification === true) {
await sendEmail(
userEmail,
"Your registration was successful.",
updatedHtml
);
}
}
if (eventIsInThePast) {
return Promise.reject("Event is past, cannot enroll new user");
Expand Down Expand Up @@ -417,11 +420,14 @@ const deleteAttendee = async (
eventLocation,
textBody
);
await sendEmail(
userEmail,
"Your event cancellation was successful.",
updatedHtml
);
const userPreferences = await userController.getUserPreferences(userID);
if (userPreferences?.preferences?.sendEmailNotification === true) {
await sendEmail(
userEmail,
"Your event cancellation was successful.",
updatedHtml
);
}
}

// update db
Expand Down Expand Up @@ -503,11 +509,14 @@ const confirmUser = async (eventID: string, userID: string) => {
eventLocation,
textBody
);
await sendEmail(
userEmail,
"Your attendance has been confirmed",
updatedHtml
);
const userPreferences = await userController.getUserPreferences(userID);
if (userPreferences?.preferences?.sendEmailNotification === true) {
await sendEmail(
userEmail,
"Your attendance has been confirmed",
updatedHtml
);
}
}

return await prisma.eventEnrollment.update({
Expand Down
32 changes: 18 additions & 14 deletions backend/src/users/controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ const getUsers = async (
},
include: {
profile: true,
preferences: true,
events: eventId
? {
where: {
Expand Down Expand Up @@ -605,20 +606,23 @@ const editRole = async (userId: string, role: string) => {
var textBodyVS = "Your role has changed from volunteer to supervisor.";

if (process.env.NODE_ENV != "test") {
if (prevUserRole === "SUPERVISOR" && role === "ADMIN") {
const updatedHtml = replaceUserInputs(
stringUserUpdate,
userName,
textBodySA
);
await sendEmail(userEmail, "Your email subject", updatedHtml);
} else if (prevUserRole === "VOLUNTEER" && role === "SUPERVISOR") {
const updatedHtml = replaceUserInputs(
stringUserUpdate,
userName,
textBodyVS
);
await sendEmail(userEmail, "Your role has changed.", updatedHtml);
const userPreferences = await userController.getUserPreferences(userId);
if (userPreferences?.preferences?.sendEmailNotification === true) {
if (prevUserRole === "SUPERVISOR" && role === "ADMIN") {
const updatedHtml = replaceUserInputs(
stringUserUpdate,
userName,
textBodySA
);
await sendEmail(userEmail, "Your email subject", updatedHtml);
} else if (prevUserRole === "VOLUNTEER" && role === "SUPERVISOR") {
const updatedHtml = replaceUserInputs(
stringUserUpdate,
userName,
textBodyVS
);
await sendEmail(userEmail, "Your role has changed.", updatedHtml);
}
}
}
return prisma.user.update({
Expand Down
39 changes: 28 additions & 11 deletions frontend/src/components/organisms/ProfileForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { api } from "@/utils/api";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { updatePassword } from "firebase/auth";
import { User } from "firebase/auth";
import { Controller } from "react-hook-form";

type FormValues = {
email: string;
Expand All @@ -34,6 +35,7 @@ type formData = {
verified?: boolean;
disciplinaryNotices?: number;
imageUrl?: string;
sendEmailNotification: boolean;
};

interface ProfileFormProps {
Expand Down Expand Up @@ -76,6 +78,7 @@ const ProfileForm = ({ userDetails }: ProfileFormProps) => {
/** React hook form */
const {
register,
control,
handleSubmit,
watch,
reset,
Expand All @@ -89,18 +92,12 @@ const ProfileForm = ({ userDetails }: ProfileFormProps) => {
oldPassword: "",
newPassword: "",
confirmNewPassword: "",
emailNotifications: false,
emailNotifications: userDetails.sendEmailNotification,
},
});

/** Handles checkbox */

// TODO: Implement this
const [checked, setChecked] = useState(false);
const handleCheckbox = () => {
setChecked((checked) => !checked);
};

/** Tanstack query mutation to reauthenticate the user session */
const ReAuthenticateUserSession = useMutation({
mutationFn: async (data: any) => {
Expand Down Expand Up @@ -140,12 +137,26 @@ const ProfileForm = ({ userDetails }: ProfileFormProps) => {
retry: false,
});

/** Tanstack query mutation to update the user profile */
const updatePreferencesInDB = useMutation({
mutationFn: async (emailNotifications: boolean) => {
return api.put(`/users/${userDetails.id}/preferences`, {
sendEmailNotification: emailNotifications,
});
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["profile"] });
},
retry: false,
});

/** Handles form submit */
const handleChanges: SubmitHandler<FormValues> = async (data) => {
try {
await ReAuthenticateUserSession.mutateAsync(data);
await updateUserPasswordInFirebase.mutateAsync(data);
await updateProfileInDB.mutateAsync(data);
await updatePreferencesInDB.mutateAsync(data.emailNotifications);
setSuccessNotificationOpen(true);
} catch (error: any) {
setErrorNotificationOpen(true);
Expand Down Expand Up @@ -254,10 +265,16 @@ const ProfileForm = ({ userDetails }: ProfileFormProps) => {
},
})}
/>
<Checkbox
checked={checked}
onChange={handleCheckbox}
label="Email notifications"
<Controller
name="emailNotifications"
control={control}
render={({ field }) => (
<Checkbox
{...field}
label="Email notifications"
checked={field.value}
/>
)}
/>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
<div className="order-1 sm:order-2">
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/pages/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ const Profile = () => {
const { data, isLoading, isError } = useQuery({
queryKey: ["profile", user?.email],
queryFn: async () => {
const { data } = await api.get(`/users/search/?email=${user?.email}`);
return data["data"][0];
const { data } = await api.get(`/users?email=${user?.email}`);
return data["data"]["result"][0];
},
});

Expand Down Expand Up @@ -102,6 +102,7 @@ const Profile = () => {
<ProfileForm
userDetails={{
...data.profile,
...data.preferences,
...data,
}}
/>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import {
* @returns the userid
*/
export const fetchUserIdFromDatabase = async (email: string) => {
const { data } = await api.get(`/users/search/?email=${email}`);
return data["data"][0]["id"];
const { data } = await api.get(`/users?email=${email}`);
return data["data"]["result"][0]["id"];
};

/**
Expand Down

0 comments on commit b3cd1c2

Please sign in to comment.