Finished MUI for the most part

This commit is contained in:
QkoSad
2024-09-27 21:43:06 +03:00
parent be03889ff3
commit 9bc2015426
29 changed files with 1762 additions and 4102 deletions
+1224 -3148
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -5,8 +5,8 @@
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.14.3",
"@mui/material": "^5.14.4",
"@mui/icons-material": "^6.1.1",
"@mui/material": "^6.1.1",
"@reduxjs/toolkit": "^1.9.5",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
-584
View File
@@ -1,584 +0,0 @@
/* Global Styles */
:root {
--primary-color: #17a2b8;
--dark-color: #343a40;
--light-color: #f4f4f4;
--danger-color: #dc3545;
--success-color: #28a745;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: "Raleway", sans-serif;
font-size: 1rem;
line-height: 1.6;
background-color: #fff;
color: #333;
}
a {
color: var(--primary-color);
text-decoration: none;
}
ul {
list-style: none;
}
img {
width: 100%;
}
/* Utilities */
.container {
max-width: 1100px;
margin: auto;
overflow: hidden;
padding: 0 2rem;
margin-top: 6rem;
margin-bottom: 3rem;
}
/* Text Styles*/
.x-large {
font-size: 4rem;
line-height: 1.2;
margin-bottom: 1rem;
}
.large {
font-size: 3rem;
line-height: 1.2;
margin-bottom: 1rem;
}
.lead {
font-size: 1.5rem;
margin-bottom: 1rem;
}
.text-center {
text-align: center;
}
.text-primary {
color: var(--primary-color);
}
.text-dark {
color: var(--dark-color);
}
/* Padding */
.p {
padding: 0.5rem;
}
.p-1 {
padding: 1rem;
}
.p-2 {
padding: 2rem;
}
.p-3 {
padding: 3rem;
}
.py {
padding: 0.5rem 0;
}
.py-1 {
padding: 1rem 0;
}
.py-2 {
padding: 2rem 0;
}
.py-3 {
padding: 3rem 0;
}
/* Margin */
.m {
margin: 0.5rem;
}
.m-1 {
margin: 1rem;
}
.m-2 {
margin: 2rem;
}
.m-3 {
margin: 3rem;
}
.my {
margin: 0.5rem 0;
}
.my-1 {
margin: 1rem 0;
}
.my-2 {
margin: 2rem 0;
}
.my-3 {
margin: 3rem 0;
}
.btn {
display: inline-block;
background: var(--light-color);
color: #333;
padding: 0.4rem 1.3rem;
font-size: 1rem;
border: none;
cursor: pointer;
margin-right: 0.5rem;
transition: opacity 0.2s ease-in;
outline: none;
}
.badge {
font-size: 0.8rem;
padding: 0.1rem;
text-align: center;
margin: 0.3rem;
background: var(--light-color);
color: #333;
}
.alert {
padding: 0.8rem;
margin: 1rem 0;
opacity: 0.9;
background: var(--light-color);
color: #333;
}
.btn-primary,
.bg-primary,
.badge-primary,
.alert-primary {
background: var(--primary-color);
color: #fff;
}
.btn-light,
.bg-light,
.badge-light,
.alert-light {
background: var(--light-color);
color: #333;
}
.btn-dark,
.bg-dark,
.badge-dark,
.alert-dark {
background: var(--dark-color);
color: #fff;
}
.btn-danger,
.bg-danger,
.badge-danger,
.alert-danger {
background: var(--danger-color);
color: #fff;
}
.btn-success,
.bg-success,
.badge-success,
.alert-success {
background: var(--success-color);
color: #fff;
}
.btn-white,
.bg-white,
.badge-white,
.alert-white {
background: #fff;
color: #333;
border: #ccc solid 1px;
}
.btn:hover {
opacity: 0.8;
}
.bg-light,
.badge-light {
border: #ccc solid 1px;
}
.round-img {
border-radius: 50%;
}
.line {
height: 1px;
background: #ccc;
margin: 1.5rem 0;
}
/* Overlay */
.dark-overlay {
background-color: rgba(0, 0, 0, 0.7);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* Forms */
.form .form-group {
margin: 1.2rem 0;
}
.form .form-text {
display: block;
margin-top: 0.3rem;
color: #888;
}
.form input[type="text"],
.form input[type="email"],
.form input[type="password"],
.form input[type="date"],
.form select,
.form textarea {
display: block;
width: 100%;
padding: 0.4rem;
font-size: 1.2rem;
border: 1px solid #ccc;
}
.form input[type="submit"],
button {
font: inherit;
}
.form .social-input {
display: flex;
}
.form .social-input i {
padding: 0.5rem;
width: 4rem;
}
.form .social-input i.fa-twitter {
color: #38a1f3;
}
.form .social-input i.fa-facebook {
color: #3b5998;
}
.form .social-input i.fa-instagram {
color: #3f729b;
}
.form .social-input i.fa-youtube {
color: #c4302b;
}
.form .social-input i.fa-linkedin {
color: #0077b5;
}
.table th,
.table td {
padding: 1rem;
text-align: left;
}
.table th {
background: var(--light-color);
}
/* Navbar */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.7rem 2rem;
position: fixed;
z-index: 1;
width: 100%;
top: 0;
border-bottom: solid 1px var(--primary-color);
opacity: 0.9;
}
.navbar ul {
display: flex;
}
.navbar a {
color: #fff;
padding: 0.45rem;
margin: 0 0.25rem;
}
.navbar a:hover {
color: var(--primary-color);
}
.navbar .welcome span {
margin-right: 0.6rem;
}
/* Landing Page */
.landing {
position: relative;
background: url("./img/vimCheatSheet.jpg") no-repeat center center/cover;
height: 100vh;
}
.landing-inner {
color: #fff;
height: 100%;
width: 80%;
margin: auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
/* Profiles Page */
.profile {
display: grid;
grid-template-columns: 2fr 4fr 2fr;
align-items: center;
grid-gap: 2rem;
padding: 1rem;
line-height: 1.8;
margin-bottom: 1rem;
}
/* Profile Page */
.profile-grid {
display: grid;
grid-template-areas:
"top top"
"about about"
"exp edu"
"github github";
grid-gap: 1rem;
}
.profile-top {
grid-area: top;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
.profile-top img {
width: 250px;
}
.profile-top .icons a {
color: #fff;
margin: 0 0.3rem;
}
.profile-top .icons a:hover {
color: var(--dark-color);
}
.profile-about {
grid-area: about;
text-align: center;
}
.profile-about .skills {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.profile-exp {
grid-area: exp;
}
.profile-edu {
grid-area: edu;
}
.profile-exp h2,
.profile-edu h2 {
margin-bottom: 1rem;
}
.profile-exp > div,
.profile-edu > div {
margin-bottom: 1rem;
padding-bottom: 1rem;
border-bottom: #ccc 1px dotted;
}
.profile-exp > div:last-child,
.profile-edu > div:last-child {
border: 0;
}
.profile-exp p,
.profile-edu p {
margin: 0.5rem 0;
}
.profile-github {
grid-area: github;
}
.profile-github .repo {
display: flex;
}
.profile-github .repo > div:first-child {
flex: 7;
flex-basis: 70%;
}
.profile-github > div:last-child {
flex: 3;
flex-basis: 20%;
}
/* Posts Page */
.post-form .post-form-header {
background: var(--primary-color);
padding: 0.5rem;
}
.post {
display: grid;
grid-template-columns: 1fr 4fr;
grid-gap: 2rem;
align-items: center;
}
.post > div:first-child {
text-align: center;
}
.post img {
width: 100px;
}
.post .comment-count {
background: var(--light-color);
color: var(--primary-color);
padding: 0.1rem 0.2rem;
border-radius: 5px;
font-size: 0.8rem;
}
.post .post-date {
color: #aaa;
font-size: 0.8rem;
margin-bottom: 0.5rem;
}
/* Mobile Styles */
@media (max-width: 700px) {
.container {
margin-top: 8rem;
}
.hide-sm {
display: none;
}
/* Text Styles */
.x-large {
font-size: 3rem;
}
.large {
font-size: 2rem;
}
.lead {
font-size: 1rem;
}
/* Navbar */
.navbar {
display: block;
text-align: center;
}
.navbar ul {
text-align: center;
justify-content: center;
}
.navbar h1 {
margin-bottom: 1rem;
}
.navbar .welcome {
display: none;
}
/* Profiles Page */
.profile {
grid-template-columns: 1fr;
text-align: center;
}
.profile ul {
display: none;
}
/* Profile Page */
.profile-top img,
.profile img {
width: 200px;
margin: auto;
}
.profile-grid {
grid-template-areas:
"top"
"about"
"exp"
"edu"
"github";
}
.profile-about .skills {
flex-direction: column;
}
.dash-buttons a {
display: block;
width: 100%;
margin-bottom: 0.2rem;
}
.post {
grid-template-columns: 1fr;
}
.post a,
.post button {
padding: 0.3rem 0.4rem;
}
}
.alert-wrapper {
position: fixed;
top: 4rem;
right: 2rem;
display: inline-block;
}
-16
View File
@@ -1,16 +0,0 @@
.datePicker :hover {
border-color: "#212121";
}
.datePicker :focus {
border-color: "#1976d2";
border-width: "2px";
}
.datePicker{
color:"red";
background:"red";
}
.colormebaby{
background-color:"red";
color:"red"
}
+6 -6
View File
@@ -7,7 +7,7 @@ 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 Grid from "@mui/material/Grid2";
import Box from "@mui/material/Box";
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
import Typography from "@mui/material/Typography";
@@ -54,7 +54,7 @@ export default function SignUp() {
</Typography>
<Box component="form" noValidate onSubmit={handleSubmit} sx={{ mt: 3 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Grid size={{ xs: 12 }}>
<TextField
name="name"
required
@@ -64,7 +64,7 @@ export default function SignUp() {
autoFocus
/>
</Grid>
<Grid item xs={12}>
<Grid size={{ xs: 12 }}>
<TextField
required
fullWidth
@@ -73,7 +73,7 @@ export default function SignUp() {
name="email"
/>
</Grid>
<Grid item xs={12}>
<Grid size={{ xs: 12 }}>
<TextField
required
fullWidth
@@ -83,7 +83,7 @@ export default function SignUp() {
id="password"
/>
</Grid>
<Grid item xs={12}>
<Grid size={{ xs: 12 }}>
<TextField
required
fullWidth
@@ -103,7 +103,7 @@ export default function SignUp() {
Sign Up
</Button>
<Grid container justifyContent="flex-end">
<Grid item>
<Grid>
Already have an account? <Link to={"/login"}>Sign in</Link>
</Grid>
</Grid>
+10 -8
View File
@@ -6,6 +6,7 @@ import Experience from "./Experience";
import Education from "./Education";
import { getCurrentProfile, deleteAccount } from "../../actions/profile";
import { Box, Button, Typography } from "@mui/material";
import { compose } from "redux";
const Dashboard = () => {
const dispatch = useAppDispatch();
@@ -19,13 +20,14 @@ const Dashboard = () => {
const profile = useAppSelector((state) => state.profile.profile);
return (
<Box
component="main"
justifyContent="center"
flexDirection="column"
minHeight="50vh"
display="flex"
alignItems="center"
gap="1rem"
sx={{
justifyContent: "center",
flexDirection: "column",
minHeight: "50vh",
display: "flex",
alignItems: "center",
gap: "1rem",
}}
>
<Typography variant="h3" component="h2">
Dashboard{" "}
@@ -38,7 +40,7 @@ const Dashboard = () => {
<DashboardActions />
<Experience experience={profile.experience} />
<Education education={profile.education} />
<Box sx={{ marginTop: "10vh" }}>
<Box sx={{ marginTop: "2vh" }}>
<Button
variant="contained"
color="error"
@@ -4,7 +4,12 @@ import { Link } from "react-router-dom";
const DashboardActions = () => {
return (
<Box>
<Box
sx={{
display: { xs: "grid", md: "flex" },
rowGap: { xs: "5px" },
}}
>
<Button
component={Link}
to="/edit-profile"
+13 -12
View File
@@ -21,19 +21,26 @@ const Education = ({ education }: { education: EducationType[] }) => {
const educations = education.map((edu) => (
<TableRow key={edu._id}>
<TableCell
// style={{
// wordWrap: "break-word",
// }}
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
{edu.school}
</TableCell>
<TableCell
// style={{ wordWrap: "break-word" }}
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
{edu.degree}
</TableCell>
<TableCell
// style={{ wordWrap: "break-word" }}
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
{formatDate(edu.from)} - {edu.to ? formatDate(edu.to) : "Now"}
</TableCell>
@@ -56,13 +63,7 @@ const Education = ({ education }: { education: EducationType[] }) => {
return (
<Box>
<Typography variant="h2">Education Credentials</Typography>
<Table
// style={{
// tableLayout: "fixed",
// width: "50%",
// alignSelf: "left",
// }}
>
<Table>
<TableHead>
<TableRow>
<TableCell>School</TableCell>
+22 -3
View File
@@ -20,9 +20,28 @@ const Experience = ({ experience }: { experience: ExperienceType[] }) => {
if (!experience) return <></>;
const experiences = experience.map((exp) => (
<TableRow key={exp._id}>
<TableCell>{exp.company}</TableCell>
<TableCell>{exp.title}</TableCell>
<TableCell>
<TableCell
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
{exp.company}
</TableCell>
<TableCell
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
{exp.title}
</TableCell>
<TableCell
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
{formatDate(exp.from)} - {exp.to ? formatDate(exp.to) : "Now"}
</TableCell>
<TableCell>
-1
View File
@@ -148,7 +148,6 @@ const Navbar = () => {
Logout
</a>
</MenuItem>
,
</div>
) : (
guestLinks.map((el) => (
+9 -2
View File
@@ -1,5 +1,6 @@
import { Box, Button, Container, TextField, Typography } from "@mui/material";
import React, { useState } from "react";
import { createAlert } from "../../actions/alert";
import { addComment } from "../../actions/post";
import { useAppDispatch } from "../../utils/hooks";
@@ -18,8 +19,14 @@ const CommentForm = ({ postId }: { postId: string }) => {
gap="1rem"
onSubmit={(e) => {
e.preventDefault();
dispatch(addComment(postId, { text }));
setText("");
if (text.length > 250) {
dispatch(
createAlert("Comment longer than 250 characters", "danger"),
);
} else {
dispatch(addComment(postId, { text }));
setText("");
}
}}
>
<TextField
+6 -1
View File
@@ -40,7 +40,12 @@ const CommentItem = ({
</Button>
)}
<CardContent>
<Typography variant="subtitle1">{text}</Typography>
<Typography
variant="subtitle1"
sx={{ textWrap: "wrap", wordBreak: "break-word" }}
>
{text}
</Typography>
</CardContent>
</Card>
</Container>
+10 -4
View File
@@ -1,12 +1,12 @@
import { Box, Button, Container, TextField, Typography } from "@mui/material";
import React, { useState } from "react";
import { createAlert } from "../../actions/alert";
import { addPost } from "../../actions/post";
import { useAppDispatch } from "../../utils/hooks";
const PostForm = () => {
const [text, setText] = useState("");
const dispatch = useAppDispatch();
const handleSumbit = {};
return (
<Container>
<Typography>Say Something...</Typography>
@@ -18,8 +18,12 @@ const PostForm = () => {
sx={{ mt: 3, mb: 3 }}
onSubmit={(e) => {
e.preventDefault();
dispatch(addPost({ text }));
setText("");
if (text.length > 250) {
dispatch(createAlert("Post longer than 250 characters", "danger"));
} else {
dispatch(addPost({ text }));
setText("");
}
}}
>
<TextField
@@ -27,7 +31,9 @@ const PostForm = () => {
label="Create a post"
fullWidth
value={text}
onChange={(e) => setText(e.target.value)}
onChange={(e) => {
return setText(e.target.value);
}}
multiline
rows={3}
required
+35 -40
View File
@@ -6,14 +6,12 @@ import { Post } from "../../types";
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
import {
Avatar,
Box,
Button,
Card,
CardContent,
CardHeader,
Container,
Table,
TableCell,
TableRow,
Typography,
} from "@mui/material";
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
@@ -36,45 +34,42 @@ const PostItem = ({
subheader={formatDate(date)}
/>
<CardContent>
<Typography variant="subtitle1">{text}</Typography>
<Typography
variant="subtitle1"
sx={{ textWrap: "wrap", wordBreak: "break-word" }}
>
{text}
</Typography>
</CardContent>
</Card>
<Table>
<TableRow>
<TableCell>
<Button onClick={async () => await dispatch(addLike(_id))}>
<ThumbUpIcon />
</Button>
</TableCell>
<TableCell>
<Typography display="inline-flex" variant="button">
{likes.length}
</Typography>
</TableCell>
<TableCell>
<Button onClick={async () => await dispatch(removeLike(_id))}>
<ThumbDownIcon />
</Button>
</TableCell>
<TableCell>
<Button component={Link} to={`/posts/${_id}`}>
<Typography>Comments </Typography>
</Button>
</TableCell>
<TableCell>
<Typography display="inline-flex" variant="button">
{comments.length}
</Typography>
</TableCell>
<TableCell>
{!auth.loading && auth.user !== null && user === auth.user._id && (
<Button onClick={async () => await dispatch(deletePost(_id))}>
<DeleteIcon />
</Button>
)}
</TableCell>
</TableRow>
</Table>
<Box
sx={{
display: "flex",
justifyContent: "space-evenly",
alignItems: "center",
}}
>
<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))}>
<DeleteIcon />
</Button>
)}
</Box>
</Container>
);
};
@@ -1,15 +1,8 @@
import styled from "@emotion/styled";
import {
Button,
Box,
Container,
TextField,
Typography,
Checkbox,
FormControlLabel,
} from "@mui/material";
import { Button, Box, Container, TextField, Typography } from "@mui/material";
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { createAlert } from "../../actions/alert";
import { addEducation } from "../../actions/profile";
import { useAppDispatch } from "../../utils/hooks";
@@ -51,6 +44,21 @@ const AddEducation = () => {
const onChange = (
event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,
) => setFormData({ ...formData, [event.target.name]: event.target.value });
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (formData.degree.length > 50) {
dispatch(createAlert("Degree is longer 50 characters", "danger"));
} else if (formData.fieldofstudy.length > 50) {
dispatch(createAlert("Field of study is longer 50 characters", "danger"));
} else if (formData.description.length > 250) {
dispatch(
createAlert("Description name is longer 250 characters", "danger"),
);
} else if (formData.school.length > 50) {
dispatch(createAlert("School name is longer 50 characters", "danger"));
} else
await dispatch(addEducation(formData)).then(() => navigate("/dashboard"));
};
return (
<Container maxWidth="sm">
@@ -68,12 +76,7 @@ const AddEducation = () => {
noValidate
maxWidth="500px"
sx={{ mt: 3 }}
onSubmit={async (e) => {
e.preventDefault();
await dispatch(addEducation(formData)).then(() =>
navigate("/dashboard"),
);
}}
onSubmit={onSubmit}
>
<TextField
name="school"
@@ -10,6 +10,7 @@ import {
import { Container } from "@mui/system";
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { createAlert } from "../../actions/alert";
import { addExperience } from "../../actions/profile";
import { useAppDispatch } from "../../utils/hooks";
@@ -69,9 +70,30 @@ const AddExperience = () => {
sx={{ mt: 3 }}
onSubmit={async (e) => {
e.preventDefault();
await dispatch(addExperience(formData)).then(() =>
navigate("/dashboard"),
);
if (formData.description.length > 250) {
dispatch(
createAlert("Job description is longer 250 characters", "danger"),
);
} else if (formData.location.length > 50) {
dispatch(
createAlert("Location is longer than 50 characters", "danger"),
);
} else if (formData.title.length > 50) {
dispatch(
createAlert("Job title is longer than 50 characters", "danger"),
);
} else if (formData.company.length > 50) {
dispatch(
createAlert(
"Company name is longer than 50 characters",
"danger",
),
);
} else {
await dispatch(addExperience(formData)).then(() =>
navigate("/dashboard"),
);
}
}}
>
<TextField
@@ -2,16 +2,16 @@ import {
Button,
Box,
Container,
CssBaseline,
Grid,
InputLabel,
MenuItem,
Select,
TextField,
Typography,
} from "@mui/material";
import React, { Fragment, useState, useEffect } from "react";
import Grid from "@mui/material/Grid2";
import React, { useState, useEffect } from "react";
import { Link, useMatch, useNavigate } from "react-router-dom";
import { createAlert } from "../../actions/alert";
import { createProfile, getCurrentProfile } from "../../actions/profile";
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
@@ -86,28 +86,52 @@ const ProfileForm = () => {
const linkedin = data.get("linkedin") as string;
const instagram = data.get("instagram") as string;
const status = data.get("status") as string;
await dispatch(
createProfile(
{
website,
location,
skills,
githubusername,
company,
bio,
twitter,
facebook,
youtube,
linkedin,
instagram,
status,
},
editing,
),
).then((res) => {
console.log(res);
if (!editing) navigate("/dashboard");
});
if (facebook?.length > 100) {
dispatch(createAlert("Facebook link is longer 100 characters", "danger"));
} else if (linkedin?.length > 100) {
dispatch(createAlert("LinkedIn link is longer 100 characters", "danger"));
} else if (youtube?.length > 100) {
dispatch(createAlert("Youtube link is longer 100 characters", "danger"));
} else if (instagram?.length > 100) {
dispatch(
createAlert("Instagram link is longer 100 characters", "danger"),
);
} else if (website?.length > 100) {
dispatch(createAlert("Website link is longer 100 characters", "danger"));
} else if (skills.length > 100) {
dispatch(createAlert("Skills is longer 100 characters", "danger"));
} else if (location?.length > 50) {
dispatch(createAlert("Location is longer 100 characters", "danger"));
} else if (githubusername?.length > 50) {
dispatch(
createAlert("Github username is longer 50 characters", "danger"),
);
} else if (company?.length > 50) {
dispatch(createAlert("Company name is longer 50 characters", "danger"));
} else if (bio?.length > 250) {
dispatch(createAlert("Bio name is longer 250 characters", "danger"));
} else
await dispatch(
createProfile(
{
website,
location,
skills,
githubusername,
company,
bio,
twitter,
facebook,
youtube,
linkedin,
instagram,
status,
},
editing,
),
).then(() => {
if (!editing) navigate("/dashboard");
});
};
return (
@@ -123,48 +147,48 @@ const ProfileForm = () => {
<Typography variant="body2">* = required field</Typography>
<Box component="form" noValidate onSubmit={onSubmit} sx={{ mt: 3 }}>
<Grid container spacing={2}>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<TextField name="company" fullWidth label="Company" autoFocus />
</Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<Typography paddingY="1rem">
Could be your own company or one you work for
</Typography>
</Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<TextField name="website" fullWidth label="Website" />
</Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<Typography paddingY="1rem">
Could be your own a or a company website
</Typography>
</Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<TextField name="location" fullWidth label="Location" />
</Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<Typography paddingY="1rem">
City & state suggest(eg. Boston MA)
</Typography>
</Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<TextField name="skills" required fullWidth label="Skills" />
</Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<Typography>
Please use comma separeted values (eg. HTML, CSS, JavaScript, PHP)
</Typography>
</Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<TextField name="githubUser" fullWidth label="Github Username" />
</Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<Typography>
If you want your latest repositories, add a Github link and
include your username
</Typography>
</Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<InputLabel id="status">Status *</InputLabel>
<Select
fullWidth
@@ -187,15 +211,15 @@ const ProfileForm = () => {
<MenuItem value="Other">Other</MenuItem>
</Select>
</Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<Typography paddingTop="2.3rem">
Select Profesional Status
</Typography>
</Grid>
<Grid item xs={12}>
<Grid size={{ xs: 12 }}>
<Typography>Tell us a little about yourself</Typography>
</Grid>
<Grid item xs={12}>
<Grid size={{ xs: 12 }}>
<TextField
name="bio"
multiline
@@ -204,7 +228,7 @@ const ProfileForm = () => {
label="A short bio of yourself"
/>
</Grid>
<Grid item xs={12}>
<Grid size={{ xs: 12 }}>
<Button
variant="contained"
onClick={() => toggleSocialInputs(!displaySocialInputs)}
@@ -214,33 +238,33 @@ const ProfileForm = () => {
</Grid>
{displaySocialInputs ? (
<>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}>
<TextField fullWidth name="twitter" label="Twitter URL" />
</Grid>
<Grid item xs={6}></Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}></Grid>
<Grid size={{ xs: 6 }}>
<TextField fullWidth name="facebook" label="FaceBook URL" />
</Grid>
<Grid item xs={6}></Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}></Grid>
<Grid size={{ xs: 6 }}>
<TextField fullWidth name="youtube" label="YouTube URL" />
</Grid>
<Grid item xs={6}></Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}></Grid>
<Grid size={{ xs: 6 }}>
<TextField fullWidth name="linkedin" label="Linkedin URL" />
</Grid>
<Grid item xs={6}></Grid>
<Grid item xs={6}>
<Grid size={{ xs: 6 }}></Grid>
<Grid size={{ xs: 6 }}>
<TextField fullWidth name="instagram" label="Instagram URL" />
</Grid>
</>
) : null}
<Grid item xs={8}>
<Grid size={{ xs: 8 }}>
<Button variant="contained" type="submit">
Submit Changes
</Button>
</Grid>
<Grid item xs={2}>
<Grid size={{ xs: 2 }}>
<Button variant="outlined">
<Link
style={{ color: "inherit", textDecoration: "none" }}
+53 -24
View File
@@ -9,7 +9,8 @@ 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";
import { Box, Button, Card, Container, Paper, Typography } from "@mui/material";
import Grid from "@mui/material/Grid2";
const Profile = () => {
const profile = useAppSelector((state) => state.profile.profile);
@@ -25,26 +26,54 @@ const Profile = () => {
}, [dispatch, id]);
return (
<Box display="flex" flexDirection="column" alignItems="center">
<>
{profile === null ? (
<Spinner />
) : (
<>
<Button component={Link} to="/profiles">
Back To Profiles
</Button>
{auth.isAuthenticated &&
auth.loading === false &&
auth.user !== null &&
auth.user._id === profile.user._id && (
<Button component={Link} to="/edit-profile">
Edit Profile
</Button>
)}
<Paper elevation={9} sx={{ width: "90%" }}>
<ProfileTop profile={profile} />
<ProfileAbout profile={profile} />
<Box>
<Paper sx={{ display: "grid", justifyItems: "center", marginY: "5px" }}>
<div>
<Button
variant="contained"
component={Link}
to="/profiles"
sx={{
width: "70px",
margin: "5px",
}}
>
Back
</Button>
{auth.isAuthenticated &&
auth.loading === false &&
auth.user !== null &&
auth.user._id === profile.user._id && (
<Button
component={Link}
to="/edit-profile"
variant="outlined"
sx={{
width: "70px",
}}
>
Edit
</Button>
)}
</div>
<Grid
container
spacing={2}
rowSpacing={"30px"}
sx={{
marginX: "20%",
}}
>
<Grid size={{ sm: 12, lg: 4 }}>
<ProfileTop profile={profile} />
</Grid>
<Grid size={{ sm: 12, lg: 8 }}>
<ProfileAbout profile={profile} />
</Grid>
<Grid size={{ xs: 12, md: 6 }}>
<Typography variant="h2">Experience</Typography>
{profile.experience.length > 0 ? (
<>
@@ -58,8 +87,8 @@ const Profile = () => {
) : (
<Typography variant="h4">No experience credentials</Typography>
)}
</Box>
<Box>
</Grid>
<Grid size={6}>
<Typography variant="h2">Education</Typography>
{profile.education.length > 0 ? (
<>
@@ -73,14 +102,14 @@ const Profile = () => {
) : (
<Typography variant="h4">No education credentials</Typography>
)}
</Box>
</Grid>
{profile.githubusername && (
<ProfileGithub username={profile.githubusername} />
)}
</Paper>
</>
</Grid>
</Paper>
)}
</Box>
</>
);
};
+20 -9
View File
@@ -1,4 +1,4 @@
import { Box, Typography } from "@mui/material";
import { Box, List, ListItem, Typography } from "@mui/material";
import React, { Fragment } from "react";
import { ProfileType } from "../../types";
@@ -11,21 +11,32 @@ const ProfileAbout = ({
}: {
profile: ProfileType;
}) => (
<Box>
<Box sx={{ textWrap: "wrap", maxWidth: "100%" }}>
{bio && (
<>
<Typography>{name.trim().split(" ")[0]}s Bio</Typography>
<Typography>{bio}</Typography>
<Typography color="info" variant="h5">
<b>{name.trim().split(" ")[0]}'s Bio</b>
</Typography>
<Typography
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
{bio}
</Typography>
</>
)}
<Typography>Skill Set</Typography>
<Box>
<Typography color="info" variant="h5">
<b>Skill Set</b>
</Typography>
<List>
{skills.map((skill, index) => (
<Box key={index}>
<ListItem key={index}>
<Typography>{skill}</Typography>
</Box>
</ListItem>
))}
</Box>
</List>
</Box>
);
@@ -1,4 +1,4 @@
import { Box, Typography } from "@mui/material";
import { Paper, Typography } from "@mui/material";
import React from "react";
import { EducationType } from "../../types";
import formatDate from "../../utils/formatDate";
@@ -8,15 +8,49 @@ const ProfileEducation = ({
}: {
education: EducationType;
}) => (
<Box>
<Typography variant="h3">{school}</Typography>
<Typography>
<Paper elevation={12} sx={{ margin: "10px", padding: "4px" }}>
<Typography
variant="h4"
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
{school}
</Typography>
<Typography
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
{formatDate(from)} - {to ? formatDate(to) : "Now"}
</Typography>
<Typography>Degree: {degree}</Typography>
<Typography>Field Of Study: {fieldofstudy}</Typography>
<Typography>Description: {description}</Typography>
</Box>
<Typography
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
<b>Degree:</b> {degree}
</Typography>
<Typography
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
<b>Field Of Study:</b> {fieldofstudy}
</Typography>
<Typography
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
<b>Description:</b> {description}
</Typography>
</Paper>
);
export default ProfileEducation;
@@ -1,4 +1,4 @@
import { Box, Typography } from "@mui/material";
import { Paper, Typography } from "@mui/material";
import React from "react";
import { ExperienceType } from "../../types";
import formatDate from "../../utils/formatDate";
@@ -8,15 +8,43 @@ const ProfileExperience = ({
}: {
experience: ExperienceType;
}) => (
<Box>
<Typography variant="h3">{company}</Typography>
<Paper elevation={12} sx={{ margin: "10px", padding: "4px" }}>
<Typography
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
<b>{company}</b>
</Typography>
<Typography>
{formatDate(from)} - {to ? formatDate(to) : "Now"}
</Typography>
<Typography>Position: {title}</Typography>
<Typography>Location: {location}</Typography>
<Typography>Description: {description}</Typography>
</Box>
<Typography
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
<b>Position:</b> {title}
</Typography>
<Typography
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
<b>Location:</b> {location}
</Typography>
<Typography
sx={{
textWrap: "wrap",
wordBreak: "break-word",
}}
>
<b>Description:</b> {description}
</Typography>
</Paper>
);
export default ProfileExperience;
@@ -13,10 +13,10 @@ const ProfileGithub = ({ username }: { username: string }) => {
}, [dispatch, username]);
return (
<div className="profile-github">
<h2 className="text-primary my-1">Github Repos</h2>
<div>
<h2>Github Repos</h2>
{repos.map((repo) => (
<div key={repo.id} className="repo bg-white p-1 my-1">
<div key={repo.id}>
<div>
<h4>
<a href={repo.html_url} target="_blank" rel="noopener noreferrer">
@@ -27,13 +27,9 @@ const ProfileGithub = ({ username }: { username: string }) => {
</div>
<div>
<ul>
<li className="badge badge-primary">
Stars: {repo.stargazers_count}
</li>
<li className="badge badge-dark">
Watchers: {repo.watchers_count}
</li>
<li className="badge badge-light">Forks: {repo.forks_count}</li>
<li>Stars: {repo.stargazers_count}</li>
<li>Watchers: {repo.watchers_count}</li>
<li>Forks: {repo.forks_count}</li>
</ul>
</div>
</div>
+8 -7
View File
@@ -1,3 +1,4 @@
import { BorderAll } from "@mui/icons-material";
import { Avatar, Box, Card, CardHeader, Typography } from "@mui/material";
import React from "react";
import { ProfileType } from "../../types";
@@ -14,19 +15,18 @@ const ProfileTop = ({
}: {
profile: ProfileType;
}) => {
console.log(avatar)
return (
<>
<img className="round-img my-1" src={avatar} alt="" />
<Typography variant="h1">{name}</Typography>
<Typography>
<img src={avatar} alt="" />
<Typography variant="h2">{name}</Typography>
<Typography sx={{ textWrap: "wrap" }}>
{status} {company ? <span> at {company}</span> : null}
</Typography>
<Typography>{location ? <span>{location}</span> : null}</Typography>
{location ? <Typography>{location}</Typography> : null}
<Box>
{website ? (
<a href={website} target="_blank" rel="noopener noreferrer">
<i className="fas fa-globe fa-2x" />
<i>{website}</i>
</a>
) : null}
{social
@@ -38,8 +38,9 @@ const ProfileTop = ({
href={value}
target="_blank"
rel="noopener noreferrer"
style={{ display: "block" }}
>
<i className={`fab fa-${key} fa-2x`}></i>
<i>{value}</i>
</a>
))
: null}
+14 -11
View File
@@ -22,18 +22,21 @@ const ProfileItem = ({
profile: ProfileType;
}) => {
return (
<Paper sx={{ padding: "100px" }}>
<Paper sx={{ width: "250px", paddingX: "10px" }}>
<img src={avatar} alt="" />
<Box>
<Typography>{name}</Typography>
<Typography>
{status} {company && <span> at {company}</span>}
</Typography>
<Typography>{location && <span>{location}</span>}</Typography>
<Button component={Link} to={`/profile/${_id}`}>
View Profile
</Button>
</Box>
<Typography color="info">
<b>{name}</b>
</Typography>
<Typography>
{status} {company && <span> at {company}</span>}
</Typography>
<Typography>{location && <span>{location}</span>}</Typography>
<Button component={Link} to={`/profile/${_id}`} variant="outlined">
View Profile
</Button>
<Typography color="info">
<b>Skills:</b>
</Typography>
<List>
{skills.slice(0, 4).map((skill, index) => (
<ListItemText key={index}>{skill}</ListItemText>
+27 -22
View File
@@ -17,28 +17,33 @@ const Profiles = () => {
const { profiles, loading } = useAppSelector((state) => state.profile);
return (
<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 display="flex" flexDirection="row">
{profiles.length > 0 && Array.isArray(profiles) ? (
profiles.map((profile) => (
<ProfileItem key={profile._id} profile={profile} />
))
) : (
<Typography>No profiles found...</Typography>
)}
</Box>
</>
)}
</Box>
<Container>
{loading ? (
<Spinner />
) : (
<>
<Typography variant="h2">Developers</Typography>
<Typography variant="h6">
Browse and connect with developers
</Typography>
<Box
sx={{
display: "flex",
justifyContent: "left",
gap: "10px",
flexWrap: "wrap",
}}
>
{profiles.length > 0 && Array.isArray(profiles) ? (
profiles.map((profile) => (
<ProfileItem key={profile._id} profile={profile} />
))
) : (
<Typography>No profiles found...</Typography>
)}
</Box>
</>
)}
</Container>
);
};
Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 MiB

-1
View File
@@ -2,7 +2,6 @@ import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./App2.css";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement,
);