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