Skip to content

Commit cb33897

Browse files
committed
update navbar avatar when edit profile
-use auth context in edit profile modal to set user after update
1 parent 1f134ac commit cb33897

File tree

3 files changed

+77
-27
lines changed

3 files changed

+77
-27
lines changed

frontend/src/components/EditProfileModal/index.tsx

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ import DeleteIcon from '@mui/icons-material/Delete';
1515
import { useForm } from "react-hook-form";
1616
import { useProfile } from "../../contexts/ProfileContext";
1717
import { bioValidator, nameValidator, profilePictureValidator } from "../../utils/validators";
18-
import { FAILED_PROFILE_UPDATE_MESSAGE, PROFILE_PIC_MAX_SIZE_ERROR_MESSAGE, USE_PROFILE_ERROR_MESSAGE } from "../../utils/constants";
18+
import { FAILED_PROFILE_UPDATE_MESSAGE, PROFILE_PIC_MAX_SIZE_ERROR_MESSAGE, USE_AUTH_ERROR_MESSAGE, USE_PROFILE_ERROR_MESSAGE } from "../../utils/constants";
1919
import { useRef, useState } from "react";
2020
import { Restore } from "@mui/icons-material";
2121
import { toast } from "react-toastify";
22+
import { useAuth } from "../../contexts/AuthContext";
2223

2324
interface EditProfileModalProps {
2425
onClose: () => void;
@@ -44,17 +45,17 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
4445
getFieldState,
4546
} = useForm<{
4647
profilePic: File | null;
47-
profilePictureUrl: string | null;
48+
profilePictureUrl: string;
4849
firstName: string;
4950
lastName: string;
5051
biography: string;
5152
}>({
5253
defaultValues: {
5354
profilePic: null,
54-
profilePictureUrl: currProfilePictureUrl || null,
55+
profilePictureUrl: currProfilePictureUrl || "",
5556
firstName: currFirstName,
5657
lastName: currLastName,
57-
biography: currBiography,
58+
biography: currBiography || "",
5859
},
5960
mode: "all",
6061
});
@@ -65,7 +66,15 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
6566
throw new Error(USE_PROFILE_ERROR_MESSAGE);
6667
}
6768

68-
const { uploadProfilePicture, updateProfile } = profile;
69+
const { user, uploadProfilePicture, updateProfile } = profile;
70+
71+
const auth = useAuth();
72+
73+
if (!auth) {
74+
throw new Error(USE_AUTH_ERROR_MESSAGE);
75+
}
76+
77+
const { setUser } = auth;
6978

7079
// profile pic functionality referenced and adapted from https://dreamix.eu/insights/uploading-files-with-react-hook-form/
7180
const [picPreview, setPicPreview] = useState<string | null>(currProfilePictureUrl || null);
@@ -81,7 +90,7 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
8190
setValue("profilePic", file, { shouldValidate: true, shouldDirty: true });
8291

8392
if (currProfilePictureUrl) {
84-
setValue("profilePictureUrl", null, { shouldDirty: true });
93+
setValue("profilePictureUrl", "", { shouldDirty: true });
8594
}
8695
}
8796
}
@@ -94,9 +103,9 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
94103
}
95104
}
96105
if (getFieldState("profilePictureUrl").isDirty) {
97-
setValue("profilePictureUrl", currProfilePictureUrl || null, { shouldDirty: true })
106+
setValue("profilePictureUrl", currProfilePictureUrl || "", { shouldDirty: true })
98107
}
99-
setPicPreview(currProfilePictureUrl || null);
108+
setPicPreview(currProfilePictureUrl || "");
100109
}
101110

102111
const onClickDelete = () => {
@@ -107,7 +116,7 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
107116
}
108117
}
109118
if (currProfilePictureUrl) {
110-
setValue("profilePictureUrl", null, { shouldDirty: true });
119+
setValue("profilePictureUrl", "", { shouldDirty: true });
111120
}
112121
setPicPreview(null);
113122
}
@@ -122,7 +131,6 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
122131
<StyledForm
123132
onSubmit={handleSubmit((data) => {
124133
if (data.profilePic) {
125-
//send to firebase and get the url back
126134
uploadProfilePicture(data.profilePic).then((res) => {
127135
if (res) {
128136
const url_data = {
@@ -131,7 +139,22 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
131139
biography: data.biography,
132140
profilePictureUrl: res.imageUrl,
133141
};
134-
updateProfile(url_data);
142+
updateProfile(url_data).then((res) => {
143+
if (res && user) {
144+
const updatedUser = {
145+
id: user.id,
146+
username: user.username,
147+
firstName: url_data.firstName,
148+
lastName: url_data.lastName,
149+
email: user.email,
150+
biography: url_data.biography,
151+
profilePictureUrl: url_data.profilePictureUrl,
152+
createdAt: user.createdAt,
153+
isAdmin: user.isAdmin,
154+
}
155+
setUser(updatedUser);
156+
}
157+
});
135158
onClose();
136159
} else {
137160
toast.error(FAILED_PROFILE_UPDATE_MESSAGE);
@@ -144,7 +167,22 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
144167
biography: data.biography,
145168
profilePictureUrl: data.profilePictureUrl,
146169
};
147-
updateProfile(url_data);
170+
updateProfile(url_data).then((res) => {
171+
if (res && user) {
172+
const updatedUser = {
173+
id: user.id,
174+
username: user.username,
175+
firstName: url_data.firstName,
176+
lastName: url_data.lastName,
177+
email: user.email,
178+
biography: url_data.biography,
179+
profilePictureUrl: url_data.profilePictureUrl,
180+
createdAt: user.createdAt,
181+
isAdmin: user.isAdmin,
182+
}
183+
setUser(updatedUser);
184+
}
185+
});
148186
onClose();
149187
}
150188
})}

frontend/src/contexts/AuthContext.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ type User = {
1313
firstName: string;
1414
lastName: string;
1515
email: string;
16-
biography: string;
17-
profilePictureUrl: string;
16+
biography?: string;
17+
profilePictureUrl?: string;
1818
createdAt: string;
1919
isAdmin: boolean;
2020
};
@@ -30,6 +30,7 @@ type AuthContextType = {
3030
login: (email: string, password: string) => void;
3131
logout: () => void;
3232
user: User | null;
33+
setUser: (data: User) => void;
3334
};
3435

3536
const AuthContext = createContext<AuthContextType | null>(null);
@@ -110,7 +111,7 @@ const AuthProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
110111
}
111112

112113
return (
113-
<AuthContext.Provider value={{ signup, login, logout, user }}>
114+
<AuthContext.Provider value={{ signup, login, logout, user, setUser }}>
114115
{children}
115116
</AuthContext.Provider>
116117
);

frontend/src/contexts/ProfileContext.tsx

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ import {
77
SUCCESS_PW_UPDATE_MESSAGE,
88
} from "../utils/constants";
99
import { toast } from "react-toastify";
10+
import axios from "axios";
1011

1112
interface UserProfileBase {
1213
firstName: string;
1314
lastName: string;
1415
biography?: string;
15-
profilePictureUrl?: string | null;
16+
profilePictureUrl?: string;
1617
}
1718

1819
interface UserProfile extends UserProfileBase {
@@ -29,7 +30,7 @@ type ProfileContextType = {
2930
passwordModalOpen: boolean;
3031
fetchUser: (userId: string) => void;
3132
uploadProfilePicture: (data: File) => Promise<{ message: string, imageUrl: string } | null>;
32-
updateProfile: (data: UserProfileBase) => void;
33+
updateProfile: (data: UserProfileBase) => Promise<boolean>;
3334
updatePassword: ({
3435
oldPassword,
3536
newPassword,
@@ -75,21 +76,31 @@ const ProfileContextProvider: React.FC<{ children: React.ReactNode }> = ({
7576
}
7677
}
7778

78-
const updateProfile = async (data: UserProfileBase) => {
79+
const updateProfile = async (
80+
data: UserProfileBase
81+
): Promise<boolean> => {
7982
const token = localStorage.getItem("token");
80-
await userClient
81-
.patch(`/users/${user?.id}`, data, {
83+
try {
84+
const res = await userClient
85+
.patch(`/users/${user?.id}`, data,
86+
{
8287
headers: { Authorization: `Bearer ${token}` },
8388
})
84-
.then((res) => {
85-
setUser(res.data.data);
86-
toast.success(SUCCESS_PROFILE_UPDATE_MESSAGE);
87-
})
88-
.catch((err) => {
89+
setUser(res.data.data);
90+
toast.success(SUCCESS_PROFILE_UPDATE_MESSAGE);
91+
return true;
92+
} catch (error) {
93+
console.error('Error:', error);
94+
if(axios.isAxiosError(error)) {
8995
const message =
90-
err.response?.data.message || FAILED_PROFILE_UPDATE_MESSAGE;
96+
error.response?.data.message || FAILED_PROFILE_UPDATE_MESSAGE;
9197
toast.error(message);
92-
});
98+
return false;
99+
} else {
100+
toast.error(FAILED_PROFILE_UPDATE_MESSAGE);
101+
return false;
102+
}
103+
}
93104
};
94105

95106
const updatePassword = async ({

0 commit comments

Comments
 (0)