Added MaterialUI
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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,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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user