Home page and navigate to login/register page if not logged in
This commit is contained in:
@@ -19,3 +19,4 @@ Table:
|
||||
| 14.07.2023 | Navbar | 10 |
|
||||
| 16.07.2023 | Login and register page | 20 |
|
||||
| 16.07.2023 | Fix mock schema and move mock injections out of index.js | 1 |
|
||||
| 18.07.2023 | Home page and navigate to login/register page if not logged in | 20 |
|
||||
|
||||
@@ -11,6 +11,7 @@ import { themeSettings } from "theme";
|
||||
function App() {
|
||||
const mode = useSelector((state) => state.mode);
|
||||
const theme = useMemo(() => createTheme(themeSettings(mode)), [mode]);
|
||||
const isLogged = Boolean(useSelector((state) => state.token));
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
@@ -19,8 +20,14 @@ function App() {
|
||||
<CssBaseline />
|
||||
<Routes>
|
||||
<Route path="/" element={<LoginPage />} />
|
||||
<Route path="/home" element={<HomePage />} />
|
||||
<Route path="/profile/:userId" element={<ProfilePage />} />
|
||||
<Route
|
||||
path="/home"
|
||||
element={isLogged ? <HomePage /> : <Navigate to="/" />}
|
||||
/>
|
||||
<Route
|
||||
path="/profile/:userId"
|
||||
element={isLogged ? <ProfilePage /> : <Navigate to="/" />}
|
||||
/>
|
||||
</Routes>
|
||||
</ThemeProvider>
|
||||
</BrowserRouter>
|
||||
|
||||
20
client/src/components/ProfilePhoto.jsx
Normal file
20
client/src/components/ProfilePhoto.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Box } from "@mui/material";
|
||||
|
||||
const ProfilePhoto = ({ image, size = "60px" }) => {
|
||||
return (
|
||||
<Box width={size} height={size}>
|
||||
<img
|
||||
style={{
|
||||
objectFit: "cover",
|
||||
borderRadius: "50%",
|
||||
}}
|
||||
width={size}
|
||||
height={size}
|
||||
alt="profile"
|
||||
src={`http://localhost:3001/assets/${image}`}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProfilePhoto;
|
||||
10
client/src/components/WidgetWrapper.jsx
Normal file
10
client/src/components/WidgetWrapper.jsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Box } from "@mui/material";
|
||||
import { styled } from "@mui/system";
|
||||
|
||||
const WidgetWrapper = styled(Box)(({ theme }) => ({
|
||||
padding: " 1.5 rem 1.5 rem 0.75rem 1.5rem",
|
||||
backgroundColor: theme.palette.background.alt,
|
||||
borderRadius: "0.75rem",
|
||||
}));
|
||||
|
||||
export default WidgetWrapper;
|
||||
@@ -1,7 +1,33 @@
|
||||
import { Box, useMediaQuery } from "@mui/material";
|
||||
import { useSelector } from "react-redux";
|
||||
import Navbar from "scenes/navbar";
|
||||
import UserWidget from "scenes/widgets/UserWidget";
|
||||
|
||||
const HomePage = () => {
|
||||
return (
|
||||
<div>homepage</div>
|
||||
)
|
||||
const isNotMobile = useMediaQuery("(min-width: 1000px)");
|
||||
const { _id, profilePicturePath } = useSelector((state) => state.user);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Navbar />
|
||||
<Box
|
||||
width="100%"
|
||||
padding="2rem 6%"
|
||||
display={isNotMobile ? "flex" : "block"}
|
||||
gap="0.5rem"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Box flexBasis={isNotMobile ? "26%" : undefined}>
|
||||
<UserWidget userId={_id} profilePicturePath={profilePicturePath} />
|
||||
</Box>
|
||||
<Box
|
||||
flexBasis={isNotMobile ? "42%" : undefined}
|
||||
mt={isNotMobile ? undefined : "2rem"}
|
||||
></Box>
|
||||
{isNotMobile && <Box flexBasis="26%"></Box>}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default HomePage;
|
||||
|
||||
132
client/src/scenes/widgets/UserWidget.jsx
Normal file
132
client/src/scenes/widgets/UserWidget.jsx
Normal file
@@ -0,0 +1,132 @@
|
||||
import {
|
||||
ManageAccountsOutlined,
|
||||
EditOutlined,
|
||||
LocationOnOutlined,
|
||||
FavoriteOutlined,
|
||||
} from "@mui/icons-material";
|
||||
import { Box, Typography, Divider, useTheme } from "@mui/material";
|
||||
import ProfilePhoto from "components/ProfilePhoto";
|
||||
import WidgetWrapper from "components/WidgetWrapper";
|
||||
import FlexBetween from "components/FlexBetween";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const UserWidget = ({ userId, profilePicturePath }) => {
|
||||
const [user, setUser] = useState(null);
|
||||
const { palette } = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const token = useSelector((state) => state.token);
|
||||
const dark = palette.neutral.dark;
|
||||
const medium = palette.neutral.medium;
|
||||
const main = palette.neutral.main;
|
||||
|
||||
const getUser = async () => {
|
||||
const response = await fetch(`http://localhost:3001/users/${userId}`, {
|
||||
method: "GET",
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
const data = await response.json();
|
||||
setUser(data);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getUser();
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
if (!user) return null;
|
||||
|
||||
const { firstName, lastName, location, description, friends } = user;
|
||||
|
||||
return (
|
||||
<WidgetWrapper>
|
||||
<FlexBetween
|
||||
gap="0.5rem"
|
||||
pb="1.1rem"
|
||||
onClick={() => navigate(`/profile/${userId}`)}
|
||||
>
|
||||
<FlexBetween gap="1rem">
|
||||
<ProfilePhoto image={profilePicturePath} />
|
||||
<Box>
|
||||
<Typography
|
||||
variant="h4"
|
||||
color={dark}
|
||||
fontWeight="500"
|
||||
sx={{
|
||||
"&:hover": {
|
||||
color: palette.primary.main,
|
||||
cursor: "pointer",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{firstName} {lastName}
|
||||
</Typography>
|
||||
<Typography color={medium}>
|
||||
{friends.length} friend(s)
|
||||
</Typography>
|
||||
</Box>
|
||||
</FlexBetween>
|
||||
<ManageAccountsOutlined />
|
||||
</FlexBetween>
|
||||
|
||||
<Divider />
|
||||
<Box p="1rem 0">
|
||||
<Box display="flex" alignItems="center" gap="1rem" mb="0.5rem">
|
||||
<LocationOnOutlined fontSize="large" sx={{ color: main }} />
|
||||
<Typography color={medium}>{location}</Typography>
|
||||
</Box>
|
||||
<Box display="flex" alignItems="center" gap="1rem">
|
||||
<FavoriteOutlined fontSize="large" sx={{ color: main }} />
|
||||
<Typography color={medium}>{description}</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
<Divider />
|
||||
<Box p="1rem 0">
|
||||
<Typography fontSize="1rem" fontWeight="500" color={main} mb="1rem">
|
||||
Other platforms
|
||||
</Typography>
|
||||
<FlexBetween gap="1rem" mb="0.5rem">
|
||||
<FlexBetween gap="1rem">
|
||||
<img src="../../public/assets/icons/facebook.svg" alt="facebook" />
|
||||
<Box>
|
||||
<Typography color={main} fontWeight="500">
|
||||
Facebook
|
||||
</Typography>
|
||||
<Typography color={medium}>Social media</Typography>
|
||||
</Box>
|
||||
</FlexBetween>
|
||||
<EditOutlined sx={{ color: main }} />
|
||||
</FlexBetween>
|
||||
<FlexBetween gap="1rem">
|
||||
<FlexBetween gap="1rem">
|
||||
<img
|
||||
src="../../public/assets/icons/instagram.svg"
|
||||
alt="instagram"
|
||||
/>
|
||||
<Box>
|
||||
<Typography color={main} fontWeight="500">
|
||||
Instagram
|
||||
</Typography>
|
||||
<Typography color={medium}>Social media</Typography>
|
||||
</Box>
|
||||
</FlexBetween>
|
||||
<EditOutlined sx={{ color: main }} />
|
||||
</FlexBetween>
|
||||
<FlexBetween gap="1rem">
|
||||
<FlexBetween gap="1rem">
|
||||
<img src="../../public/assets/icons/linkedin.svg" alt="linkedin" />
|
||||
<Box>
|
||||
<Typography color={main} fontWeight="500">
|
||||
LinkedIn
|
||||
</Typography>
|
||||
<Typography color={medium}>Network platform</Typography>
|
||||
</Box>
|
||||
</FlexBetween>
|
||||
<EditOutlined sx={{ color: main }} />
|
||||
</FlexBetween>
|
||||
</Box>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserWidget;
|
||||
Reference in New Issue
Block a user