diff --git a/Client/src/Components/TabPanels/Account/ProfilePanel.jsx b/Client/src/Components/TabPanels/Account/ProfilePanel.jsx index a56b65919..122f1668b 100644 --- a/Client/src/Components/TabPanels/Account/ProfilePanel.jsx +++ b/Client/src/Components/TabPanels/Account/ProfilePanel.jsx @@ -12,11 +12,16 @@ import { imageValidation, } from "../../../Validation/validation"; import { useDispatch, useSelector } from "react-redux"; -import { update } from "../../../Features/Auth/authSlice"; +import { + clearAuthState, + deleteUser, + update, +} from "../../../Features/Auth/authSlice"; import ImageField from "../../TextFields/Image"; import ImageIcon from "@mui/icons-material/Image"; import ProgressUpload from "../../ProgressBars"; import { formatBytes } from "../../../Utils/fileUtils"; +import { clearMonitorState } from "../../../Features/Monitors/monitorsSlice"; /** * ProfilePanel component displays a form for editing user profile information @@ -158,7 +163,12 @@ const ProfilePanel = () => { // Initiates the account deletion process const handleDeleteAccount = () => { - //TODO - implement delete account function + dispatch(deleteUser(authToken)).then((action) => { + if (action.payload.success) { + dispatch(clearAuthState()); + dispatch(clearMonitorState()); + } + }); }; // Modal state and control functions diff --git a/Client/src/Features/Auth/authSlice.js b/Client/src/Features/Auth/authSlice.js index bc75e53f7..e50611648 100644 --- a/Client/src/Features/Auth/authSlice.js +++ b/Client/src/Features/Auth/authSlice.js @@ -70,6 +70,31 @@ export const update = createAsyncThunk( } ); +export const deleteUser = createAsyncThunk( + "auth/delete", + async (data, thunkApi) => { + const user = jwtDecode(data); + + //1.5s delay to show loading spinner + await new Promise((resolve) => setTimeout(resolve, 1500)); + + try { + const res = await axiosInstance.delete(`/auth/user/${user._id}`, { + headers: { + Authorization: `Bearer ${data}`, + "Content-Type": "multipart/form-data", + }, + }); + return res.data; + } catch (error) { + if (error.response && error.response.data) { + return thunkApi.rejectWithValue(error.response.data); + } + return thunkApi.rejectWithValue(error.message); + } + } +); + const handleAuthFulfilled = (state, action) => { state.isLoading = false; state.success = action.payload.success; @@ -97,6 +122,16 @@ const handleUpdateRejected = (state, action) => { ? action.payload.msg : "Failed to update profile data."; }; +const handleDeleteFulfilled = (state, action) => { + state.isLoading = false; + state.success = action.payload.success; + state.msg = action.payload.msg; +}; +const handleDeleteRejected = (state, action) => { + state.isLoading = false; + state.success = false; + state.msg = action.payload ? action.payload.msg : "Failed to delete account."; +}; const authSlice = createSlice({ name: "auth", @@ -111,25 +146,37 @@ const authSlice = createSlice({ }, }, extraReducers: (builder) => { + // Register thunk builder - // Register thunk .addCase(register.pending, (state) => { state.isLoading = true; }) .addCase(register.fulfilled, handleAuthFulfilled) - .addCase(register.rejected, handleAuthRejected) - // Login thunk + .addCase(register.rejected, handleAuthRejected); + + // Login thunk + builder .addCase(login.pending, (state) => { state.isLoading = true; }) .addCase(login.fulfilled, handleAuthFulfilled) - .addCase(login.rejected, handleAuthRejected) - // Update thunk + .addCase(login.rejected, handleAuthRejected); + + // Update thunk + builder .addCase(update.pending, (state) => { state.isLoading = true; }) .addCase(update.fulfilled, handleUpdateFulfilled) .addCase(update.rejected, handleUpdateRejected); + + // Delete thunk + builder + .addCase(deleteUser.pending, (state) => { + state.isLoading = true; + }) + .addCase(deleteUser.fulfilled, handleDeleteFulfilled) + .addCase(deleteUser.rejected, handleDeleteRejected); }, });