diff --git a/client/src/app/AppThemeProvider.tsx b/client/src/app/AppThemeProvider.tsx
new file mode 100644
index 0000000..6ab02b3
--- /dev/null
+++ b/client/src/app/AppThemeProvider.tsx
@@ -0,0 +1,19 @@
+import { ThemeProvider } from "@emotion/react";
+import React from "react";
+import { useSelector } from "react-redux";
+import { selectDarkMode } from "./loginSlice";
+import { createTheme } from "@mui/material";
+
+const AppThemeProvider = ({ children }: { children: React.ReactNode }) => {
+ const darkThemeEnabled = useSelector(selectDarkMode);
+
+ const defaultTheme = createTheme({
+ palette: {
+ mode: darkThemeEnabled ? "dark" : "light",
+ },
+ });
+
+ return {children};
+};
+
+export default AppThemeProvider;
diff --git a/client/src/app/loginSlice.ts b/client/src/app/loginSlice.ts
index a788094..2a6de36 100644
--- a/client/src/app/loginSlice.ts
+++ b/client/src/app/loginSlice.ts
@@ -13,25 +13,32 @@ interface loginState {
loggedIn: boolean;
status: Status;
error: string | null;
+ darkMode: boolean;
userInfo: {
firstName: string;
lastName: string;
jwt: string;
id: number;
profilePictureId: string;
+ notifications: Notification[];
+ isPrivate: boolean;
};
}
+const storageDarkMode = localStorage.getItem("darkMode") === "true";
const initialState: loginState = {
loggedIn: false,
status: Status.idle,
+ darkMode: storageDarkMode || false,
error: null,
userInfo: {
+ isPrivate: false,
firstName: "",
lastName: "",
jwt: "",
id: -1,
profilePictureId: "",
+ notifications: [],
},
};
@@ -46,6 +53,8 @@ export const loginSlice = createSlice({
state.userInfo.firstName = action.payload.firstName;
state.userInfo.lastName = action.payload.lastName;
state.userInfo.profilePictureId = action.payload.profilePictureId;
+ state.userInfo.notifications = action.payload.notifications;
+ state.userInfo.isPrivate = action.payload.isPrivate;
},
logoff: (state) => {
state.loggedIn = false;
@@ -57,6 +66,12 @@ export const loginSlice = createSlice({
setError: (state, action) => {
state.error = action.payload;
},
+ setDarkMode: (state, action) => {
+ state.darkMode = action.payload;
+ },
+ setPrivate: (state, action) => {
+ state.userInfo.isPrivate = action.payload;
+ },
},
});
@@ -93,6 +108,7 @@ export const postLogin =
lastName: userResponse.data.lastName,
id: userResponse.data.id,
profilePictureId: userResponse.data.profilePictureId,
+ notifications: userResponse.data.notifications,
})
);
dispatch(setStatus(Status.succeeded));
@@ -120,6 +136,22 @@ export const postSignup =
}
};
+export const updateMe =
+ (isPrivate: boolean): AppThunk =>
+ async (dispatch) => {
+ const userApi = new UsersApi(
+ new Configuration({
+ basePath: process.env.REACT_APP_BACKEND_URL,
+ accessToken: localStorage.getItem("jwt") || "",
+ })
+ );
+ console.log("From inside updateME dispatch, param is:", isPrivate);
+
+ await userApi.usersMePatch({ isPrivate });
+ const userResponse = await userApi.usersMeGet();
+ dispatch(setPrivate(userResponse.data.isPrivate));
+ };
+
export const postLogout = (): AppThunk => async (dispatch) => {
localStorage.removeItem("jwt");
sessionStorage.removeItem("jwt");
@@ -131,7 +163,8 @@ const addJWT = async (token: string) => {
localStorage.setItem("jwt", token);
};
-export const { login, logoff, setStatus, setError } = loginSlice.actions;
+export const { login, logoff, setStatus, setError, setDarkMode, setPrivate } =
+ loginSlice.actions;
export default loginSlice.reducer;
@@ -143,3 +176,6 @@ export const selectUserInfo = (state: { login: loginState }) =>
export const selectErrorMessage = (state: { login: loginState }) =>
state.login.error;
+
+export const selectDarkMode = (state: { login: loginState }) =>
+ state.login.darkMode;
diff --git a/client/src/components/topAppBar.tsx b/client/src/components/topAppBar.tsx
index 2f382ed..75dbdfd 100644
--- a/client/src/components/topAppBar.tsx
+++ b/client/src/components/topAppBar.tsx
@@ -12,6 +12,7 @@ import {useSelector} from "react-redux";
import { postLogout, selectUserInfo } from "../app/loginSlice";
import { useAppDispatch } from "../app/store";
import { AppAvatar } from "./appAvatar";
+import { useNavigate } from "react-router-dom";
interface TopAppBarProps {
height: number;
@@ -19,12 +20,12 @@ interface TopAppBarProps {
function TopAppBar(props: TopAppBarProps) {
const dispatch = useAppDispatch();
+ const navigate = useNavigate();
const userInfo = useSelector(selectUserInfo);
const [anchorElUser, setAnchorElUser] = React.useState(
null
);
-
const handleOpenUserMenu = (event: React.MouseEvent) => {
setAnchorElUser(event.currentTarget);
};
@@ -38,6 +39,16 @@ function TopAppBar(props: TopAppBarProps) {
setAnchorElUser(null);
};
+ const handleProfileClick = () => {
+ navigate("/me");
+ setAnchorElUser(null);
+ };
+
+ const handleSettingsClick = () => {
+ navigate("/settings");
+ setAnchorElUser(null);
+ };
+
return (
-