Added MaterialUI

This commit is contained in:
Malak
2024-08-18 14:42:24 +03:00
committed by QkoSad
parent 7cd63ec826
commit 78ba14cc98
24 changed files with 738 additions and 667 deletions
+18 -20
View File
@@ -1,30 +1,27 @@
import * as React from 'react';
import * as React from "react";
import { Link, Navigate } from "react-router-dom";
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
import { login } from "../../actions/auth";
import Avatar from '@mui/material/Avatar';
import Button from '@mui/material/Button';
import CssBaseline from '@mui/material/CssBaseline';
import TextField from '@mui/material/TextField';
import Box from '@mui/material/Box';
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import Typography from '@mui/material/Typography';
import Container from '@mui/material/Container';
import Avatar from "@mui/material/Avatar";
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
import Box from "@mui/material/Box";
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
import Typography from "@mui/material/Typography";
import Container from "@mui/material/Container";
export default function Login() {
const dispatch = useAppDispatch();
const isAuthenticated = useAppSelector((state) => state.auth.isAuthenticated);
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
const email = data.get('email') as string
const password = data.get('pasword') as string
if (email && password)
dispatch(login(email, password));
const email = data.get("email") as string;
const password = data.get("password") as string;
if (email && password) dispatch(login(email, password));
};
if (isAuthenticated) {
@@ -33,16 +30,15 @@ export default function Login() {
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<Box
sx={{
marginTop: 8,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
<Avatar sx={{ m: 1, bgcolor: "secondary.main" }}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
@@ -78,8 +74,10 @@ export default function Login() {
LOG IN
</Button>
</Box>
<Typography variant="body1">
Don't have an account? <Link to="/register">Sign Up</Link>
</Typography>
</Box>
<p> Don't have an account? <Link to="/register">Sign Up</Link></p>
</Container>
);
}
+18 -25
View File
@@ -3,17 +3,15 @@ import { Navigate, Link } from "react-router-dom";
import { createAlert } from "../../actions/alert";
import { register } from "../../actions/auth";
import * as React from 'react';
import Avatar from '@mui/material/Avatar';
import Button from '@mui/material/Button';
import CssBaseline from '@mui/material/CssBaseline';
import TextField from '@mui/material/TextField';
import Grid from '@mui/material/Grid';
import Box from '@mui/material/Box';
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import Typography from '@mui/material/Typography';
import Container from '@mui/material/Container';
import * as React from "react";
import Avatar from "@mui/material/Avatar";
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
import Grid from "@mui/material/Grid";
import Box from "@mui/material/Box";
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
import Typography from "@mui/material/Typography";
import Container from "@mui/material/Container";
export default function SignUp() {
const isAuthenticated = useAppSelector((state) => state.auth.isAuthenticated);
@@ -23,14 +21,13 @@ export default function SignUp() {
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
const password = data.get('password') as string
const password2 = data.get('password') as string
const email = data.get('email') as string
const name = data.get('name') as string
const password = data.get("password") as string;
const password2 = data.get("password") as string;
const email = data.get("email") as string;
const name = data.get("name") as string;
if (password !== password2) {
dispatch(createAlert("Passwords do not match", "danger"));
} else {
console.log(name,email, password)
dispatch(register({ name, email, password }));
}
};
@@ -41,16 +38,15 @@ export default function SignUp() {
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<Box
sx={{
marginTop: 8,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
<Avatar sx={{ m: 1, bgcolor: "secondary.main" }}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
@@ -108,10 +104,7 @@ export default function SignUp() {
</Button>
<Grid container justifyContent="flex-end">
<Grid item>
Already have an account?{' '}
<Link to={'/login'} >
Sign in
</Link>
Already have an account? <Link to={"/login"}>Sign in</Link>
</Grid>
</Grid>
</Box>
+28 -14
View File
@@ -5,7 +5,7 @@ import DashboardActions from "./DashboardActions";
import Experience from "./Experience";
import Education from "./Education";
import { getCurrentProfile, deleteAccount } from "../../actions/profile";
import { Box, Typography } from "@mui/material";
import { Box, Button, Typography } from "@mui/material";
const Dashboard = () => {
const dispatch = useAppDispatch();
@@ -18,30 +18,44 @@ const Dashboard = () => {
const user = useAppSelector((state) => state.auth.user);
const profile = useAppSelector((state) => state.profile.profile);
return (
<Box component='main' justifyContent='center' flexDirection='column' minHeight='50vh' display='flex' alignItems='center'>
<Typography variant="h3" component='h2'>Dashboard </Typography>
<Typography variant="h5" component='h3' display='block'> Welcome {user && user.name}</Typography>
<Box
component="main"
justifyContent="center"
flexDirection="column"
minHeight="50vh"
display="flex"
alignItems="center"
gap="1rem"
>
<Typography variant="h3" component="h2">
Dashboard{" "}
</Typography>
<Typography variant="h5" component="h3" display="block">
Welcome {user && user.name}
</Typography>
{profile !== null ? (
<>
<DashboardActions />
<Experience experience={profile.experience} />
<Education education={profile.education} />
<div className="my-2">
<button
className="btn btn-danger"
<Box sx={{ marginTop: "10vh" }}>
<Button
variant="contained"
color="error"
onClick={async () => await dispatch(deleteAccount())}
>
<i className="fas fa-user" /> Delete My Account
</button>
</div>
Delete My Account
</Button>
</Box>
</>
) : (
<>
<Typography>You have not yet setup a profile, please add some info</Typography>
<Link to="/create-profile">
<Typography variant="h6">
You have not yet setup a profile, please add some info
</Typography>
<Button component={Link} to="/create-profile" variant="contained">
Create Profile
</Link>
</Button>
</>
)}
</Box>
@@ -1,19 +1,35 @@
import { Box, Button } from "@mui/material";
import React from "react";
import { Link } from "react-router-dom";
const DashboardActions = () => {
return (
<div className="dash-buttons">
<Link to="/edit-profile" className="btn btn-light">
<i className="fas fa-user-circle text-primary" /> Edit Profile
</Link>
<Link to="/add-experience" className="btn btn-light">
<i className="fab fa-black-tie text-primary" /> Add Experience
</Link>
<Link to="/add-education" className="btn btn-light">
<i className="fas fa-graduation-cap text-primary" /> Add Education
</Link>
</div>
<Box>
<Button
component={Link}
to="/edit-profile"
variant="outlined"
sx={{ marginX: "1rem" }}
>
Edit Profile
</Button>
<Button
component={Link}
to="/add-experience"
variant="outlined"
sx={{ marginX: "1rem" }}
>
Add Experience
</Button>
<Button
component={Link}
to="/add-education"
variant="outlined"
sx={{ marginX: "1rem" }}
>
Add Education
</Button>
</Box>
);
};
+12 -3
View File
@@ -3,6 +3,7 @@ import { deleteEducation } from "../../actions/profile";
import formatDate from "../../utils/formatDate";
import { EducationType } from "../../types";
import { useAppDispatch } from "../../utils/hooks";
import { Box, Typography } from "@mui/material";
const Education = ({ education }: { education: EducationType[] }) => {
const dispatch = useAppDispatch();
@@ -24,9 +25,17 @@ const Education = ({ education }: { education: EducationType[] }) => {
</tr>
));
if (education.length === 0)
return (
<Box>
<Typography variant="h5">
You have no education added to your profile, consider adding some.
</Typography>
</Box>
);
return (
<Fragment>
<h2 className="my-2">Education Credentials</h2>
<>
<Typography variant='h5'>Education Credentials</Typography>
<table className="table">
<thead>
<tr>
@@ -38,7 +47,7 @@ const Education = ({ education }: { education: EducationType[] }) => {
</thead>
<tbody>{educations}</tbody>
</table>
</Fragment>
</>
);
};
@@ -1,4 +1,5 @@
import React, { Fragment } from "react";
import { Typography } from "@mui/material";
import React from "react";
import { deleteExperience } from "../../actions/profile";
import { ExperienceType } from "../../types";
import formatDate from "../../utils/formatDate";
@@ -24,8 +25,13 @@ const Experience = ({ experience }: { experience: ExperienceType[] }) => {
</tr>
));
if (experiences.length === 0)
return (
<Typography variant="h5">You have no experiences, consider adding some.</Typography>
);
return (
<Fragment>
<>
<h2 className="my-2">Experience Credentials</h2>
<table className="table">
<thead>
@@ -38,7 +44,7 @@ const Experience = ({ experience }: { experience: ExperienceType[] }) => {
</thead>
<tbody>{experiences}</tbody>
</table>
</Fragment>
</>
);
};
+33 -20
View File
@@ -1,4 +1,4 @@
import React from "react";
import { Box, Button, Typography } from "@mui/material";
import { Link, Navigate } from "react-router-dom";
import { useAppSelector } from "../../utils/hooks";
@@ -9,25 +9,38 @@ const Landing = () => {
}
return (
<section className="landing">
<div className="dark-overlay">
<div className="landing-inner">
<h1 className="x-large">Developer Connector</h1>
<p className="lead">
Create a developer profile/portfolio, share posts and get help from
other developers
</p>
<div className="buttons">
<Link to="/register" className="btn btn-primary">
Sign Up
</Link>
<Link to="/login" className="btn btn-light">
Login
</Link>
</div>
</div>
</div>
</section>
<Box
component="main"
justifyContent="center"
flexDirection="column"
minHeight="75vh"
display="flex"
alignItems="center"
>
<Typography variant="h3">Developer Connector</Typography>
<Typography variant="body1">
Create a developer profile/portfolio, share posts and get help from
other developers
</Typography>
<Box>
<Button
component={Link}
variant="contained"
sx={{ margin: 3 }}
to="/register"
>
Sign Up
</Button>
<Button
component={Link}
to="/login"
variant="contained"
sx={{ margin: 3 }}
>
Login
</Button>
</Box>
</Box>
);
};
+111 -76
View File
@@ -1,4 +1,4 @@
import React from "react";
import React from "react";
import { Link } from "react-router-dom";
import { logOut } from "../../reducers/auth";
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
@@ -15,14 +15,14 @@ import MenuItem from "@mui/material/MenuItem";
import MenuIcon from "@mui/icons-material/Menu";
import AdbIcon from "@mui/icons-material/Adb";
const linkStyle = { color: 'inherit', textDecoration: 'none' }
const linkStyle = { color: "inherit", textDecoration: "none" };
const Navbar = () => {
const isAuthenticated = useAppSelector((state) => state.auth.isAuthenticated);
const dispatch = useAppDispatch();
const [anchorElNav, setAnchorElNav] = React.useState<null | HTMLElement>(
null,
null
);
const handleOpenNavMenu = (event: React.MouseEvent<HTMLElement>) => {
setAnchorElNav(event.currentTarget);
@@ -30,74 +30,39 @@ const Navbar = () => {
const handleCloseNavMenu = () => {
setAnchorElNav(null);
};
const authLinksSmall = [
(<MenuItem onClick={handleCloseNavMenu} key={1}>
<Link style={linkStyle} to={'/profiles'}>Developers</Link>
</MenuItem>),
(<MenuItem onClick={handleCloseNavMenu} key={2}>
<Link style={linkStyle} to={'/posts'}>Posts</Link>
</MenuItem>),
(<MenuItem onClick={handleCloseNavMenu} key={3}>
<Link style={linkStyle} to={'/profile'}>Profile</Link>
</MenuItem>),
(<MenuItem onClick={handleCloseNavMenu} key={4}>
<a style={linkStyle} onClick={() => dispatch(logOut())} href="#!">
<span>Logout</span>
</a>
</MenuItem>)]
const guestLinksSmall = [
(
<MenuItem onClick={handleCloseNavMenu} key={1}>
<Link style={linkStyle} to={'/profiles'}>Developers</Link>
</MenuItem>),
(<MenuItem onClick={handleCloseNavMenu} key={2}>
<Link style={linkStyle} to={'/register'}>Register</Link>
</MenuItem>),
(<MenuItem onClick={handleCloseNavMenu} key={3}>
<Link style={linkStyle} to={'/login'}>Login</Link>
</MenuItem>)]
const authLinksBig = [
(<Button key={1}
sx={{ my: 2, color: "white", display: "block" }}
>
<Link style={linkStyle} to={'/profiles'} >Developers</Link>
</Button>),
(<Button key={2}
sx={{ my: 2, color: "white", display: "block" }}
>
<Link style={linkStyle} to={'/posts'}>posts</Link>
</Button>),
(<Button
key={3} sx={{ my: 2, color: "white", display: "block" }}
>
<Link style={linkStyle} to={'/profile'}>Profile</Link>
</Button>
), (<Button
key={4} sx={{ my: 2, color: "white", display: "block" }}
>
<a style={linkStyle} onClick={() => dispatch(logOut())} href="#!">
<span>Logout</span>
</a>
</Button>
)]
const guestLinksBig = [
(<Button key={1}
sx={{ my: 2, color: "white", display: "block" }}
>
<Link style={linkStyle} to={'/profiles'} >Developers</Link>
</Button>),
(<Button key={2}
sx={{ my: 2, color: "white", display: "block" }}
>
<Link style={linkStyle} to={'/register'}>Register</Link>
</Button>),
(<Button key={3}
sx={{ my: 2, color: "white", display: "block" }}
>
<Link style={linkStyle} to={'/login'}>Login</Link>
</Button>)
const authLinks = [
{
id: 1,
to: "/profiles",
message: "Developers",
},
{
id: 2,
to: "/posts",
message: "Posts",
},
{
id: 3,
to: "/dashboard",
message: "Profile",
},
];
const guestLinks = [
{
id: 1,
to: "/profiles",
message: "Developers",
},
{
id: 2,
to: "/register",
message: "Register",
},
{
id: 3,
to: "/login",
message: "Login",
},
];
return (
@@ -110,7 +75,6 @@ const Navbar = () => {
<Typography
variant="h6"
noWrap
component="h6"
sx={{
mr: 2,
display: { xs: "none", md: "flex" },
@@ -120,8 +84,10 @@ const Navbar = () => {
color: "inherit",
textDecoration: "none",
}}
component={Link}
to="/posts"
>
<Link style={linkStyle} to={"/posts"}>DevConnect</Link>
DevConnect
</Typography>
{/* Small display menu*/}
<Box
@@ -160,7 +126,42 @@ const Navbar = () => {
display: { xs: "block", md: "none" },
}}
>
{isAuthenticated ? authLinksSmall.map(el => el) : guestLinksSmall.map(el => el)}
{isAuthenticated ? (
<>
{" "}
{authLinks.map((el) => (
<MenuItem
component={Link}
to={el.to}
onClick={handleCloseNavMenu}
key={el.id}
>
{el.message}
</MenuItem>
))}
<MenuItem onClick={handleCloseNavMenu} key={4}>
<a
style={linkStyle}
onClick={() => dispatch(logOut())}
href="#!"
>
Logout
</a>
</MenuItem>
,
</>
) : (
guestLinks.map((el) => (
<MenuItem
component={Link}
to={el.to}
onClick={handleCloseNavMenu}
key={el.id}
>
{el.message}
</MenuItem>
))
)}
</Menu>
</Box>
{/* Icon for small display */}
@@ -180,11 +181,45 @@ const Navbar = () => {
textDecoration: "none",
}}
>
<Link style={linkStyle} to={"/posts"}>DevConnect</Link>
<Link style={linkStyle} to={"/posts"}>
DevConnect
</Link>
</Typography>
{/* Menu bar for big display*/}
<Box sx={{ flexGrow: 1, display: { xs: "none", md: "flex" } }}>
{isAuthenticated ? authLinksBig.map(el => el) : guestLinksBig.map(el => el)}
{isAuthenticated ? (
<>
{authLinks.map((el) => (
<Button
key={el.id}
sx={{ my: 2, color: "white", display: "block" }}
component={Link}
to={el.to}
>
{el.message}
</Button>
))}
<Button
key={4}
sx={{ my: 2, color: "white", display: "block" }}
onClick={() => dispatch(logOut())}
href="#!"
>
Logout
</Button>
</>
) : (
guestLinks.map((el) => (
<Button
key={el.id}
sx={{ my: 2, color: "white", display: "block" }}
component={Link}
to={el.to}
>
{el.message}
</Button>
))
)}
</Box>
</Toolbar>
</Container>
+17 -14
View File
@@ -1,3 +1,4 @@
import { Box, Button, Container, TextField, Typography } from "@mui/material";
import React, { useState } from "react";
import { addComment } from "../../actions/post";
import { useAppDispatch } from "../../utils/hooks";
@@ -7,30 +8,32 @@ const CommentForm = ({ postId }: { postId: string }) => {
const dispatch = useAppDispatch();
return (
<div className="post-form">
<div className="bg-primary p">
<h3>Leave a Comment</h3>
</div>
<form
className="form my-1"
<Container maxWidth="sm">
<Typography>Leave a Comment</Typography>
<Box
component="form"
display="flex"
flexDirection="column"
alignItems="left"
gap="1rem"
onSubmit={async (e) => {
e.preventDefault();
await dispatch(addComment(postId, { text }));
setText("");
}}
>
<textarea
<TextField
name="text"
cols={30}
rows={5}
placeholder="Comment the post"
label="Comment the post"
fullWidth
multiline
rows={4}
value={text}
onChange={(e) => setText(e.target.value)}
required
/>
<input type="submit" className="btn btn-dark my-1" value="Submit" />
</form>
</div>
<Button>Submit</Button>
</Box>
</Container>
);
};
+33 -21
View File
@@ -4,10 +4,22 @@ import formatDate from "../../utils/formatDate";
import { deleteComment } from "../../actions/post";
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
import { Comment } from "../../types";
import {
Avatar,
Box,
Button,
Card,
CardContent,
CardHeader,
Container,
Typography,
} from "@mui/material";
import DeleteIcon from "@mui/icons-material/Delete";
interface CommentItemProps {
postId: string;
comment: Comment;
}
const CommentItem = ({
postId,
comment: { _id, text, name, avatar, user, date },
@@ -15,27 +27,27 @@ const CommentItem = ({
const dispatch = useAppDispatch();
const auth = useAppSelector((state) => state.auth);
return (
<div className="post bg-white p-1 my-1">
<div>
<Link to={`/profile/${user}`}>
<img className="round-img" src={avatar} alt="" />
<h4>{name}</h4>
</Link>
</div>
<div>
<p className="my-1">{text}</p>
<p className="post-date">Posted on {formatDate(date)}</p>
{!auth.loading && auth.user !== null && user === auth.user._id && (
<button
onClick={async () => await dispatch(deleteComment(postId, _id))}
type="button"
className="btn btn-danger"
>
<i className="fas fa-times" />
</button>
)}
</div>
</div>
<Container maxWidth="sm">
<Card variant="outlined">
<CardHeader
avatar={<Avatar src={avatar}>R</Avatar>}
title={<Link to={`/profile/${user}`}>{name}</Link>}
subheader={formatDate(date)}
/>
<CardContent>
<Typography variant="subtitle1">{text}</Typography>
</CardContent>
<Box display={"inline"}>
{!auth.loading && auth.user !== null && user === auth.user._id && (
<Button
onClick={async () => await dispatch(deleteComment(postId, _id))}
>
<DeleteIcon />
</Button>
)}
</Box>
</Card>
</Container>
);
};
+6 -7
View File
@@ -6,6 +6,7 @@ import CommentForm from "../post/CommentForm";
import CommentItem from "../post/CommentItem";
import { getPost } from "../../actions/post";
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
import { Box, Button, Container } from "@mui/material";
const Post = () => {
const dispatch = useAppDispatch();
@@ -21,18 +22,16 @@ const Post = () => {
return loading || post === null ? (
<Spinner />
) : (
<section className="container">
<Link to="/posts" className="btn">
Back To Posts
</Link>
<Box display="flex" flexDirection="column" gap="1rem" alignItems="center">
<Button component={Link} to="/posts">
Back to Posts
</Button>
<PostItem post={post} />
<CommentForm postId={post._id} />
<div className="comments">
{post.comments.map((comment) => (
<CommentItem key={comment._id} comment={comment} postId={post._id} />
))}
</div>
</section>
</Box>
);
};
+18 -14
View File
@@ -1,3 +1,4 @@
import { Box, Button, Container, TextField, Typography } from "@mui/material";
import React, { useState } from "react";
import { addPost } from "../../actions/post";
import { useAppDispatch } from "../../utils/hooks";
@@ -6,30 +7,33 @@ const PostForm = () => {
const [text, setText] = useState("");
const dispatch = useAppDispatch();
return (
<div className="post-form">
<div className="bg-primary p">
<h3>Say Something...</h3>
</div>
<form
className="form my-1"
<Box>
<Typography>Say Something...</Typography>
<Box
component="form"
display="flex"
gap="1rem"
noValidate
sx={{ mt: 3,mb:3 }}
onSubmit={async (e) => {
e.preventDefault();
await dispatch(addPost({ text }));
setText("");
}}
>
<textarea
<TextField
name="text"
cols={30}
rows={5}
placeholder="Create a post"
label="Create a post"
fullWidth
value={text}
onChange={(e) => setText(e.target.value)}
onChange={(e)=> setText(e.target.value)}
multiline
rows={3}
required
/>
<input type="submit" className="btn btn-dark my-1" value="Submit" />
</form>
</div>
<Button variant="contained">Submit</Button>
</Box>
</Box>
);
};
+46 -40
View File
@@ -4,6 +4,20 @@ import formatDate from "../../utils/formatDate";
import { addLike, removeLike, deletePost } from "../../actions/post";
import { Post } from "../../types";
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
import {
Avatar,
Box,
Button,
Card,
CardContent,
CardHeader,
CardMedia,
Container,
Typography,
} from "@mui/material";
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
import ThumbUpIcon from "@mui/icons-material/ThumbUp";
import DeleteIcon from "@mui/icons-material/Delete";
const PostItem = ({
post: { _id, text, name, avatar, user, likes, comments, date },
@@ -13,48 +27,40 @@ const PostItem = ({
const dispatch = useAppDispatch();
const auth = useAppSelector((state) => state.auth);
return (
<div className="post bg-white p-1 my-1">
<div>
<Link to={`/profile/${user}`}>
<img className="round-img" src={avatar} alt="" />
<h4>{name}</h4>
</Link>
</div>
<div>
<p className="my-1">{text}</p>
<p className="post-date">Posted on {formatDate(date)}</p>
<button
onClick={async () => await dispatch(addLike(_id))}
type="button"
className="btn btn-light"
>
<i className="fas fa-thumbs-up" />{" "}
<span>{likes.length > 0 && <span>{likes.length}</span>}</span>
</button>
<button
onClick={async () => await dispatch(removeLike(_id))}
type="button"
className="btn btn-light"
>
<i className="fas fa-thumbs-down" />
</button>
<Link to={`/posts/${_id}`} className="btn btn-primary">
Discussion{" "}
{comments.length > 0 && (
<span className="comment-count">{comments.length}</span>
)}
</Link>
<Container maxWidth="sm">
<Card variant="outlined">
<CardHeader
avatar={<Avatar src={avatar}>R</Avatar>}
title={<Link to={`/profile/${user}`}>{name}</Link>}
subheader={formatDate(date)}
/>
<CardContent>
<Typography variant="subtitle1">{text}</Typography>
</CardContent>
</Card>
<Box>
<Button onClick={async () => await dispatch(addLike(_id))}>
<ThumbUpIcon />
</Button>
<Typography display="inline-flex" variant="button">
{likes.length}
</Typography>
<Button onClick={async () => await dispatch(removeLike(_id))}>
<ThumbDownIcon />
</Button>
<Button component={Link} to={`/posts/${_id}`}>
<Typography>Comments </Typography>
</Button>
<Typography display="inline-flex" variant="button">
{comments.length}
</Typography>
{!auth.loading && auth.user !== null && user === auth.user._id && (
<button
onClick={async () => await dispatch(deletePost(_id))}
type="button"
className="btn btn-danger"
>
<i className="fas fa-times" />
</button>
<Button onClick={async () => await dispatch(deletePost(_id))}>
<DeleteIcon />
</Button>
)}
</div>
</div>
</Box>
</Container>
);
};
export default PostItem;
+8 -11
View File
@@ -3,6 +3,7 @@ import PostItem from "./PostItem";
import PostForm from "./PostForm";
import { getPosts } from "../../actions/post";
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
import { Box, Container, Typography } from "@mui/material";
const Posts = () => {
const dispatch = useAppDispatch();
@@ -15,18 +16,14 @@ const Posts = () => {
const posts = useAppSelector((state) => state.post.posts);
return (
<section className="container">
<h1 className="large text-primary">Posts</h1>
<p className="lead">
<i className="fas fa-user" /> Welcome to the community
</p>
<Container maxWidth="sm">
<Typography variant="h3">Posts</Typography>
<Typography variant='h4'>Welcome to the community</Typography>
<PostForm />
<div className="posts">
{posts.map((post) => (
<PostItem key={post._id} post={post} />
))}
</div>
</section>
{posts.map((post) => (
<PostItem key={post._id} post={post} />
))}
</Container>
);
};
@@ -1,8 +1,37 @@
import styled from "@emotion/styled";
import {
Button,
Box,
Container,
TextField,
Typography,
Checkbox,
FormControlLabel,
} from "@mui/material";
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { addEducation } from "../../actions/profile";
import { useAppDispatch } from "../../utils/hooks";
const StyledInput = styled("input")`
border-radius: 4px;
border-color: #c4c4c4;
border-width: 1px;
padding: 16.5px 14px;
min-width: 0;
display: block;
margin: 0;
height: 1.4375em;
box-sizing: content-box;
color: currentcolor;
letter-spacing: inherit;
font: inherit;
cursor: text;
&:focus {
outline: 2px solid #1976d2;
border-color: transparent;
}
`;
const AddEducation = () => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
@@ -20,99 +49,69 @@ const AddEducation = () => {
formData;
const onChange = (
event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,
event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
) => setFormData({ ...formData, [event.target.name]: event.target.value });
return (
<section className="container">
<h1 className="large text-primary">Add Your Education</h1>
<p className="lead">
<i className="fas fa-code-branch" /> Add any school or bootcamp that you
have attended
</p>
<small>* = required field</small>
<form
className="form"
<Container maxWidth="sm">
<Typography variant="h4">Add Your Education</Typography>
<Typography variant="body1">
Add any school or bootcamp that you have attended
</Typography>
<Typography variant="body2">* = required field</Typography>
<Box
component="form"
display="flex"
flexDirection="column"
alignItems="left"
gap="1rem"
noValidate
maxWidth="500px"
sx={{ mt: 3 }}
onSubmit={async (e) => {
e.preventDefault();
await dispatch(addEducation(formData)).then(() =>
navigate("/dashboard"),
navigate("/dashboard")
);
// i have no idea how this works used to work, i removed the navigate function from the addEducation and it does now
}}
>
<div className="form-group">
<input
type="text"
placeholder="* School or Bootcamp"
name="school"
value={school}
onChange={onChange}
required
<TextField
name="school"
label="School or Bootcamp"
fullWidth
autoFocus
/>
<TextField name="degree" label="Gegree or Certificate" fullWidth />
<TextField name="fieldofstudy" label="Field of Study" fullWidth />
<Typography variant="body1">From Date</Typography>
<StyledInput type="date" name="from" value={from} onChange={onChange} />
<Typography>
<FormControlLabel
control={
<Checkbox
checked={current}
onChange={() => setFormData({ ...formData, current: !current })}
inputProps={{ "aria-label": "controlled" }}
/>
}
label="Current"
/>
</div>
<div className="form-group">
<input
type="text"
placeholder="* Degree or Certificate"
name="degree"
value={degree}
onChange={onChange}
required
/>
</div>
<div className="form-group">
<input
type="text"
placeholder="Field of Study"
name="fieldofstudy"
value={fieldofstudy}
onChange={onChange}
/>
</div>
<div className="form-group">
<h4>From Date</h4>
<input type="date" name="from" value={from} onChange={onChange} />
</div>
<div className="form-group">
<p>
<input
type="checkbox"
name="current"
checked={current}
//TODO this fuckery here
value={current as unknown as string}
onChange={() => setFormData({ ...formData, current: !current })}
/>{" "}
Current School
</p>
</div>
<div className="form-group">
<h4>To Date</h4>
<input
type="date"
name="to"
value={to}
onChange={onChange}
disabled={current}
/>
</div>
<div className="form-group">
<textarea
name="description"
cols={30}
rows={5}
placeholder="Program Description"
value={description}
onChange={onChange}
/>
</div>
<input type="submit" className="btn btn-primary my-1" />
<Link className="btn btn-light my-1" to="/dashboard">
Go Back
</Link>
</form>
</section>
</Typography>
<Typography>To Date</Typography>
<StyledInput type="date" name="from" value={to} onChange={onChange} />
<TextField
name="desc"
label="Program description"
multiline
rows={4}
fullWidth
/>
<Button variant="contained">Sumbit Query</Button>
</Box>
<Button component={Link} to="/dashboard">
Go Back
</Button>
</Container>
);
};
@@ -1,3 +1,13 @@
import styled from "@emotion/styled";
import {
Box,
Button,
Checkbox,
FormControlLabel,
TextField,
Typography,
} from "@mui/material";
import { Container } from "@mui/system";
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { addExperience } from "../../actions/profile";
@@ -18,100 +28,84 @@ const AddExperience = () => {
const { company, title, location, from, to, current, description } = formData;
const StyledInput = styled("input")`
border-radius: 4px;
border-color: #c4c4c4;
border-width: 1px;
padding: 16.5px 14px;
min-width: 0;
display: block;
margin: 0;
height: 1.4375em;
box-sizing: content-box;
color: currentcolor;
letter-spacing: inherit;
font: inherit;
cursor: text;
&:focus {
outline: 2px solid #1976d2;
border-color: transparent;
}
`;
const onChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => setFormData({ ...formData, [e.target.name]: e.target.value });
return (
<section className="container">
<h1 className="large text-primary">Add An Experience</h1>
<p className="lead">
<i className="fas fa-code-branch" /> Add any developer/programming
positions that you have had in the past
</p>
<small>* = required field</small>
<form
className="form"
<Container maxWidth="sm">
<Typography variant="h4">Add An Experience</Typography>
<Typography variant="body1">
Add any developer/programming positions that you have had in the past
</Typography>
<Typography variant="body2">* = required field</Typography>
<Box
component="form"
display="flex"
flexDirection="column"
alignItems="left"
gap="1rem"
noValidate
maxWidth="500px"
sx={{ mt: 3 }}
onSubmit={async (e) => {
e.preventDefault();
await dispatch(addExperience(formData)).then(() =>
navigate("/dashboard"),
navigate("/dashboard")
);
}}
>
<div className="form-group">
<input
type="text"
placeholder="* Job Title"
name="title"
value={title}
onChange={onChange}
required
<TextField name="title" label="Job Title" fullWidth required />
<TextField name="company" label="Company" required />
<TextField name="location" label="Location" />
<Typography variant="body1">From Date</Typography>
<StyledInput type="date" name="from" value={from} onChange={onChange} />
<Typography>
<FormControlLabel
control={
<Checkbox
checked={current}
onChange={() => setFormData({ ...formData, current: !current })}
inputProps={{ "aria-label": "controlled" }}
/>
}
label="Current"
/>
</div>
<div className="form-group">
<input
type="text"
placeholder="* Company"
name="company"
value={company}
onChange={onChange}
required
/>
</div>
<div className="form-group">
<input
type="text"
placeholder="Location"
name="location"
value={location}
onChange={onChange}
/>
</div>
<div className="form-group">
<h4>From Date</h4>
<input type="date" name="from" value={from} onChange={onChange} />
</div>
<div className="form-group">
<p>
<input
type="checkbox"
name="current"
checked={current}
value={current as unknown as string}
onChange={() => {
setFormData({ ...formData, current: !current });
}}
/>{" "}
Current Job
</p>
</div>
<div className="form-group">
<h4>To Date</h4>
<input
type="date"
name="to"
value={to}
onChange={onChange}
disabled={current}
/>
</div>
<div className="form-group">
<textarea
name="description"
cols={30}
rows={5}
placeholder="Job Description"
value={description}
onChange={onChange}
/>
</div>
<input type="submit" className="btn btn-primary my-1" />
<Link className="btn btn-light my-1" to="/dashboard">
Go Back
</Link>
</form>
</section>
</Typography>
<Typography>To Date</Typography>
<StyledInput type="date" name="from" value={to} onChange={onChange} />
<TextField
name="desc"
label="Job description"
multiline
rows={4}
fullWidth
/>
<Button variant="contained">Sumbit Query</Button>
</Box>
<Button component={Link} to="/dashboard">
Go Back
</Button>
</Container>
);
};
@@ -1,4 +1,15 @@
import { Button, Box, Container, CssBaseline, Grid, InputLabel, MenuItem, Select, TextField, Typography } from "@mui/material";
import {
Button,
Box,
Container,
CssBaseline,
Grid,
InputLabel,
MenuItem,
Select,
TextField,
Typography,
} from "@mui/material";
import React, { Fragment, useState, useEffect } from "react";
import { Link, useMatch, useNavigate } from "react-router-dom";
import { createProfile, getCurrentProfile } from "../../actions/profile";
@@ -58,103 +69,86 @@ const ProfileForm = () => {
}
}, [loading, dispatch, profile]);
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
const editing = profile ? true : false;
e.preventDefault();
const data = new FormData(e.currentTarget);
const website = data.get('website') as string
const location = data.get('location') as string
const skills = data.get('skills') as string
const githubusername = data.get('githubUser') as string
const company = data.get('company') as string
const bio = data.get('bio') as string
const twitter = data.get('twitter') as string
const facebook = data.get('facebook') as string
const youtube = data.get('youtube') as string
const linkedin = data.get('linkedin') as string
const instagram = data.get('instagram') as string
const status =data.get('status') as string
console.log(data)
await dispatch(createProfile({
website,
location,
skills,
githubusername,
company,
bio,
twitter,
facebook,
youtube,
linkedin,
instagram,
status
}, editing)).then(() => {
const website = data.get("website") as string;
const location = data.get("location") as string;
const skills = data.get("skills") as string;
const githubusername = data.get("githubUser") as string;
const company = data.get("company") as string;
const bio = data.get("bio") as string;
const twitter = data.get("twitter") as string;
const facebook = data.get("facebook") as string;
const youtube = data.get("youtube") as string;
const linkedin = data.get("linkedin") as string;
const instagram = data.get("instagram") as string;
const status = data.get("status") as string;
console.log(data);
await dispatch(
createProfile(
{
website,
location,
skills,
githubusername,
company,
bio,
twitter,
facebook,
youtube,
linkedin,
instagram,
status,
},
editing,
),
).then(() => {
if (!editing) navigate("/dashboard");
});
};
return (
<Container className="container">
<CssBaseline />
<Typography component='h1' variant="h4">
<Container maxWidth='md'>
<Typography component="h1" variant="h4">
{creatingProfile ? "Create Your Profile" : "Edit Your Profile"}
</Typography>
<Typography component='p' variant='body1'>
<Typography component="p" variant="body1">
{creatingProfile
? ` Let's get some information to make your`
: " Add some changes to your profile"}
</Typography>
<Typography variant="body2">* = required field</Typography>
<Box
component="form"
noValidate onSubmit={onSubmit} sx={{ mt: 3 }}>
<Box component="form" noValidate onSubmit={onSubmit} sx={{ mt: 3 }}>
<Grid container spacing={2}>
<Grid item xs={6}>
<TextField
name="company"
fullWidth
label="Company"
autoFocus
/>
<TextField name="company" fullWidth label="Company" autoFocus />
</Grid>
<Grid item xs={6}>
<Typography paddingY='1rem'>
<Typography paddingY="1rem">
Could be your own company or onee you work for
</Typography>
</Grid>
<Grid item xs={6}>
<TextField
name="website"
fullWidth
label="Website"
/>
<TextField name="website" fullWidth label="Website" />
</Grid>
<Grid item xs={6}>
<Typography paddingY='1rem'>
<Typography paddingY="1rem">
Could be your own a or a company website
</Typography>
</Grid>
<Grid item xs={6}>
<TextField
name="location"
fullWidth
label="Location"
/>
<TextField name="location" fullWidth label="Location" />
</Grid>
<Grid item xs={6}>
<Typography paddingY='1rem'>
<Typography paddingY="1rem">
City & state suggest(eg. Boston MA)
</Typography>
</Grid>
<Grid item xs={6}>
<TextField
name="skills"
required
fullWidth
label="Skills"
/>
<TextField name="skills" required fullWidth label="Skills" />
</Grid>
<Grid item xs={6}>
<Typography>
@@ -162,24 +156,22 @@ const ProfileForm = () => {
</Typography>
</Grid>
<Grid item xs={6}>
<TextField
name="githubUser"
fullWidth
label="Github Username"
/>
<TextField name="githubUser" fullWidth label="Github Username" />
</Grid>
<Grid item xs={6}>
<Typography>
If you want your latest reepos add a Github link, include your username
If you want your latest reepos add a Github link, include your
username
</Typography>
</Grid>
<Grid item xs={6}>
<InputLabel id='status'>Status *</InputLabel>
<Select fullWidth
<InputLabel id="status">Status *</InputLabel>
<Select
fullWidth
labelId="status"
name='status'
name="status"
required
placeholder='Select Profesional status'
placeholder="Select Profesional status"
defaultValue={""}
>
<MenuItem value="">None</MenuItem>
@@ -187,21 +179,23 @@ const ProfileForm = () => {
<MenuItem value="Junior Developer">Junior Developer</MenuItem>
<MenuItem value="Senior Developer">Senior Developer</MenuItem>
<MenuItem value="Manager">Manager</MenuItem>
<MenuItem value="Student or Learning">Student or Learning</MenuItem>
<MenuItem value="Student or Learning">
Student or Learning
</MenuItem>
<MenuItem value="Instructor">Instructor or Teacher</MenuItem>
<MenuItem value="Intern">Intern</MenuItem>
<MenuItem value="Other">Other</MenuItem>
</Select>
</Grid>
<Grid item xs={6}>
<Typography paddingTop='2.3rem' >Select Profesional Status</Typography>
</Grid>
<Grid item xs={12}>
<Typography>
Tell us a little about yourself
<Typography paddingTop="2.3rem">
Select Profesional Status
</Typography>
</Grid>
<Grid item xs={12} >
<Grid item xs={12}>
<Typography>Tell us a little about yourself</Typography>
</Grid>
<Grid item xs={12}>
<TextField
name="bio"
multiline
@@ -212,63 +206,48 @@ const ProfileForm = () => {
</Grid>
<Grid item xs={12}>
<Button
variant='contained'
onClick={() => toggleSocialInputs(!displaySocialInputs)}>
variant="contained"
onClick={() => toggleSocialInputs(!displaySocialInputs)}
>
Add Social Network Links
</Button>
</Grid>
{displaySocialInputs ? (
<>
<Grid item xs={6}>
<TextField
fullWidth
name="twitter"
label="Twitter URL"
/>
<TextField fullWidth name="twitter" label="Twitter URL" />
</Grid>
<Grid item xs={6}></Grid>
<Grid item xs={6}>
<TextField fullWidth name="facebook" label="FaceBook URL" />
</Grid>
<Grid item xs={6}></Grid>
<Grid item xs={6}>
<TextField
fullWidth
name="facebook"
label="FaceBook URL"
/>
<TextField fullWidth name="youtube" label="YouTube URL" />
</Grid>
<Grid item xs={6}></Grid>
<Grid item xs={6}>
<TextField fullWidth name="linkedin" label="Linkedin URL" />
</Grid>
<Grid item xs={6}></Grid>
<Grid item xs={6}>
<TextField
fullWidth
name="youtube"
label="YouTube URL"
/>
<TextField fullWidth name="instagram" label="Instagram URL" />
</Grid>
<Grid item xs={6}>
</Grid>
<Grid item xs={6}>
<TextField
fullWidth
name="linkedin"
label="Linkedin URL"
/>
</Grid>
<Grid item xs={6}>
</Grid>
<Grid item xs={6}>
<TextField
fullWidth
name="instagram"
label="Instagram URL"
/>
</Grid>
</>) : null}
</>
) : null}
<Grid item xs={8}>
<Button variant='contained' type="submit">Sumbit query</Button>
<Button variant="contained" type="submit">
Sumbit query
</Button>
</Grid>
<Grid item xs={2}>
<Button variant='outlined' >
<Link style={{ color: 'inherit', textDecoration: 'none' }} to='/dashboard'>Go Back</Link>
<Button variant="outlined">
<Link
style={{ color: "inherit", textDecoration: "none" }}
to="/dashboard"
>
Go Back
</Link>
</Button>
</Grid>
</Grid>
+23 -24
View File
@@ -9,6 +9,7 @@ import ProfileGithub from "./ProfileGithub";
import { getProfileById } from "../../actions/profile";
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
import { EducationType, ExperienceType } from "../../types";
import { Box, Button, Card, Paper, Typography } from "@mui/material";
const Profile = () => {
const profile = useAppSelector((state) => state.profile.profile);
@@ -24,64 +25,62 @@ const Profile = () => {
}, [dispatch, id]);
return (
<section className="container">
<Box display="flex" flexDirection="column" alignItems="center">
{profile === null ? (
<Spinner />
) : (
<Fragment>
<Link to="/profiles" className="btn btn-light">
<>
<Button component={Link} to="/profiles">
Back To Profiles
</Link>
</Button>
{auth.isAuthenticated &&
auth.loading === false &&
auth.user !== null &&
auth.user._id === profile.user._id && (
<Link to="/edit-profile" className="btn btn-dark">
<Button component={Link} to="/edit-profilee">
Edit Profile
</Link>
</Button>
)}
<div className="profile-grid my-1">
<Paper elevation={9} sx={{width:'90%'}}>
<ProfileTop profile={profile} />
<ProfileAbout profile={profile} />
<div className="profile-exp bg-white p-2">
<h2 className="text-primary">Experience</h2>
<Box>
<Typography variant="h2">Experience</Typography>
{profile.experience.length > 0 ? (
<Fragment>
<>
{profile.experience.map((experience: ExperienceType) => (
<ProfileExperience
key={experience._id}
experience={experience}
/>
))}
</Fragment>
</>
) : (
<h4>No experience credentials</h4>
<Typography variant="h4">No experience credentials</Typography>
)}
</div>
<div className="profile-edu bg-white p-2">
<h2 className="text-primary">Education</h2>
</Box>
<Box>
<Typography variant="h2">Education</Typography>
{profile.education.length > 0 ? (
<Fragment>
<>
{profile.education.map((education: EducationType) => (
<ProfileEducation
key={education._id}
education={education}
/>
))}
</Fragment>
</>
) : (
<h4>No education credentials</h4>
<Typography variant="h4">No education credentials</Typography>
)}
</div>
</Box>
{profile.githubusername && (
<ProfileGithub username={profile.githubusername} />
)}
</div>
</Fragment>
</Paper>
</>
)}
</section>
</Box>
);
};
+13 -13
View File
@@ -1,3 +1,4 @@
import { Box, Typography } from "@mui/material";
import React, { Fragment } from "react";
import { ProfileType } from "../../types";
@@ -10,23 +11,22 @@ const ProfileAbout = ({
}: {
profile: ProfileType;
}) => (
<div className="profile-about bg-light p-2">
<Box>
{bio && (
<Fragment>
<h2 className="text-primary">{name.trim().split(" ")[0]}s Bio</h2>
<p>{bio}</p>
<div className="line" />
</Fragment>
<>
<Typography>{name.trim().split(" ")[0]}s Bio</Typography>
<Typography>{bio}</Typography>
</>
)}
<h2 className="text-primary">Skill Set</h2>
<div className="skills">
<Typography>Skill Set</Typography>
<Box>
{skills.map((skill, index) => (
<div key={index} className="p-1">
<i className="fas fa-check" /> {skill}
</div>
<Box>
<Typography>{skill}</Typography>
</Box>
))}
</div>
</div>
</Box>
</Box>
);
export default ProfileAbout;
@@ -1,3 +1,4 @@
import { Box, Typography } from "@mui/material";
import React from "react";
import { EducationType } from "../../types";
import formatDate from "../../utils/formatDate";
@@ -7,21 +8,15 @@ const ProfileEducation = ({
}: {
education: EducationType;
}) => (
<div>
<h3 className="text-dark">{school}</h3>
<p>
<Box>
<Typography variant="h3">{school}</Typography>
<Typography>
{formatDate(from)} - {to ? formatDate(to) : "Now"}
</p>
<p>
<strong>Degree: </strong> {degree}
</p>
<p>
<strong>Field Of Study: </strong> {fieldofstudy}
</p>
<p>
<strong>Description: </strong> {description}
</p>
</div>
</Typography>
<Typography>Degree: {degree}</Typography>
<Typography>Field Of Study: {fieldofstudy}</Typography>
<Typography>Description: {description}</Typography>
</Box>
);
export default ProfileEducation;
@@ -1,3 +1,4 @@
import { Box, Typography } from "@mui/material";
import React from "react";
import { ExperienceType } from "../../types";
import formatDate from "../../utils/formatDate";
@@ -7,21 +8,15 @@ const ProfileExperience = ({
}: {
experience: ExperienceType;
}) => (
<div>
<h3 className="text-dark">{company}</h3>
<p>
<Box>
<Typography variant="h3">{company}</Typography>
<Typography>
{formatDate(from)} - {to ? formatDate(to) : "Now"}
</p>
<p>
<strong>Position: </strong> {title}
</p>
<p>
<strong>Location: </strong> {location}
</p>
<p>
<strong>Description: </strong> {description}
</p>
</div>
</Typography>
<Typography>Position: {title}</Typography>
<Typography>Location: {location}</Typography>
<Typography>Description: {description}</Typography>
</Box>
);
export default ProfileExperience;
+10 -8
View File
@@ -1,3 +1,4 @@
import { Avatar, Box, Card, CardHeader, Typography } from "@mui/material";
import React from "react";
import { ProfileType } from "../../types";
@@ -13,15 +14,16 @@ const ProfileTop = ({
}: {
profile: ProfileType;
}) => {
console.log(avatar)
return (
<div className="profile-top bg-primary p-2">
<>
<img className="round-img my-1" src={avatar} alt="" />
<h1 className="large">{name}</h1>
<p className="lead">
<Typography variant="h1">{name}</Typography>
<Typography>
{status} {company ? <span> at {company}</span> : null}
</p>
<p>{location ? <span>{location}</span> : null}</p>
<div className="icons my-1">
</Typography>
<Typography>{location ? <span>{location}</span> : null}</Typography>
<Box>
{website ? (
<a href={website} target="_blank" rel="noopener noreferrer">
<i className="fas fa-globe fa-2x" />
@@ -41,8 +43,8 @@ const ProfileTop = ({
</a>
))
: null}
</div>
</div>
</Box>
</>
);
};
+11 -10
View File
@@ -1,3 +1,4 @@
import { Box, Button, Paper, Typography } from "@mui/material";
import React from "react";
import { Link } from "react-router-dom";
import { ProfileType } from "../../types";
@@ -14,18 +15,18 @@ const ProfileItem = ({
profile: ProfileType;
}) => {
return (
<div className="profile bg-light">
<Paper>
<img src={avatar} alt="" className="round-img" />
<div>
<h2>{name}</h2>
<p>
<Box>
<Typography>{name}</Typography>
<Typography>
{status} {company && <span> at {company}</span>}
</p>
<p className="my-1">{location && <span>{location}</span>}</p>
<Link to={`/profile/${_id}`} className="btn btn-primary">
</Typography>
<Typography>{location && <span>{location}</span>}</Typography>
<Button component={Link} to={`/profile/${_id}`}>
View Profile
</Link>
</div>
</Button>
</Box>
<ul>
{skills.slice(0, 4).map((skill, index) => (
<li key={index} className="text-primary">
@@ -33,7 +34,7 @@ const ProfileItem = ({
</li>
))}
</ul>
</div>
</Paper>
);
};
+24 -22
View File
@@ -3,6 +3,7 @@ import Spinner from "../layout/Spinner";
import ProfileItem from "./ProfileItem";
import { getProfiles } from "../../actions/profile";
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
import { Box, Container, Typography } from "@mui/material";
const Profiles = () => {
const dispatch = useAppDispatch();
@@ -16,28 +17,29 @@ const Profiles = () => {
const { profiles, loading } = useAppSelector((state) => state.profile);
return (
<section className="container">
{loading ? (
<Spinner />
) : (
<Fragment>
<h1 className="large text-primary">Developers</h1>
<p className="lead">
<i className="fab fa-connectdevelop" /> Browse and connect with
developers
</p>
<div className="profiles">
{profiles.length > 0 ? (
profiles.map((profile) => (
<ProfileItem key={profile._id} profile={profile} />
))
) : (
<h4>No profiles found...</h4>
)}
</div>
</Fragment>
)}
</section>
<Container maxWidth="sm">
<Box display="flex" flexDirection="column" alignItems="center">
{loading ? (
<Spinner />
) : (
<>
<Typography variant="h2">Developers</Typography>
<Typography variant="h6">
Browse and connect with developers
</Typography>
<Box>
{profiles.length > 0 ? (
profiles.map((profile) => (
<ProfileItem key={profile._id} profile={profile} />
))
) : (
<Typography>No profiles found...</Typography>
)}
</Box>
</>
)}
</Box>
</Container>
);
};