Finished MUI for the most part
This commit is contained in:
Generated
+1224
-3148
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -5,8 +5,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.11.1",
|
"@emotion/react": "^11.11.1",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@mui/icons-material": "^5.14.3",
|
"@mui/icons-material": "^6.1.1",
|
||||||
"@mui/material": "^5.14.4",
|
"@mui/material": "^6.1.1",
|
||||||
"@reduxjs/toolkit": "^1.9.5",
|
"@reduxjs/toolkit": "^1.9.5",
|
||||||
"@testing-library/jest-dom": "^5.17.0",
|
"@testing-library/jest-dom": "^5.17.0",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,7 @@ import * as React from "react";
|
|||||||
import Avatar from "@mui/material/Avatar";
|
import Avatar from "@mui/material/Avatar";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import TextField from "@mui/material/TextField";
|
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 Box from "@mui/material/Box";
|
||||||
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
|
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
@@ -54,7 +54,7 @@ export default function SignUp() {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<Box component="form" noValidate onSubmit={handleSubmit} sx={{ mt: 3 }}>
|
<Box component="form" noValidate onSubmit={handleSubmit} sx={{ mt: 3 }}>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={12}>
|
<Grid size={{ xs: 12 }}>
|
||||||
<TextField
|
<TextField
|
||||||
name="name"
|
name="name"
|
||||||
required
|
required
|
||||||
@@ -64,7 +64,7 @@ export default function SignUp() {
|
|||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid size={{ xs: 12 }}>
|
||||||
<TextField
|
<TextField
|
||||||
required
|
required
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -73,7 +73,7 @@ export default function SignUp() {
|
|||||||
name="email"
|
name="email"
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid size={{ xs: 12 }}>
|
||||||
<TextField
|
<TextField
|
||||||
required
|
required
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -83,7 +83,7 @@ export default function SignUp() {
|
|||||||
id="password"
|
id="password"
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid size={{ xs: 12 }}>
|
||||||
<TextField
|
<TextField
|
||||||
required
|
required
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -103,7 +103,7 @@ export default function SignUp() {
|
|||||||
Sign Up
|
Sign Up
|
||||||
</Button>
|
</Button>
|
||||||
<Grid container justifyContent="flex-end">
|
<Grid container justifyContent="flex-end">
|
||||||
<Grid item>
|
<Grid>
|
||||||
Already have an account? <Link to={"/login"}>Sign in</Link>
|
Already have an account? <Link to={"/login"}>Sign in</Link>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import Experience from "./Experience";
|
|||||||
import Education from "./Education";
|
import Education from "./Education";
|
||||||
import { getCurrentProfile, deleteAccount } from "../../actions/profile";
|
import { getCurrentProfile, deleteAccount } from "../../actions/profile";
|
||||||
import { Box, Button, Typography } from "@mui/material";
|
import { Box, Button, Typography } from "@mui/material";
|
||||||
|
import { compose } from "redux";
|
||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@@ -19,13 +20,14 @@ const Dashboard = () => {
|
|||||||
const profile = useAppSelector((state) => state.profile.profile);
|
const profile = useAppSelector((state) => state.profile.profile);
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
component="main"
|
sx={{
|
||||||
justifyContent="center"
|
justifyContent: "center",
|
||||||
flexDirection="column"
|
flexDirection: "column",
|
||||||
minHeight="50vh"
|
minHeight: "50vh",
|
||||||
display="flex"
|
display: "flex",
|
||||||
alignItems="center"
|
alignItems: "center",
|
||||||
gap="1rem"
|
gap: "1rem",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant="h3" component="h2">
|
<Typography variant="h3" component="h2">
|
||||||
Dashboard{" "}
|
Dashboard{" "}
|
||||||
@@ -38,7 +40,7 @@ const Dashboard = () => {
|
|||||||
<DashboardActions />
|
<DashboardActions />
|
||||||
<Experience experience={profile.experience} />
|
<Experience experience={profile.experience} />
|
||||||
<Education education={profile.education} />
|
<Education education={profile.education} />
|
||||||
<Box sx={{ marginTop: "10vh" }}>
|
<Box sx={{ marginTop: "2vh" }}>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="error"
|
color="error"
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import { Link } from "react-router-dom";
|
|||||||
|
|
||||||
const DashboardActions = () => {
|
const DashboardActions = () => {
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: { xs: "grid", md: "flex" },
|
||||||
|
rowGap: { xs: "5px" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
component={Link}
|
component={Link}
|
||||||
to="/edit-profile"
|
to="/edit-profile"
|
||||||
|
|||||||
@@ -21,19 +21,26 @@ const Education = ({ education }: { education: EducationType[] }) => {
|
|||||||
const educations = education.map((edu) => (
|
const educations = education.map((edu) => (
|
||||||
<TableRow key={edu._id}>
|
<TableRow key={edu._id}>
|
||||||
<TableCell
|
<TableCell
|
||||||
// style={{
|
sx={{
|
||||||
// wordWrap: "break-word",
|
textWrap: "wrap",
|
||||||
// }}
|
wordBreak: "break-word",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{edu.school}
|
{edu.school}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell
|
<TableCell
|
||||||
// style={{ wordWrap: "break-word" }}
|
sx={{
|
||||||
|
textWrap: "wrap",
|
||||||
|
wordBreak: "break-word",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{edu.degree}
|
{edu.degree}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell
|
<TableCell
|
||||||
// style={{ wordWrap: "break-word" }}
|
sx={{
|
||||||
|
textWrap: "wrap",
|
||||||
|
wordBreak: "break-word",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{formatDate(edu.from)} - {edu.to ? formatDate(edu.to) : "Now"}
|
{formatDate(edu.from)} - {edu.to ? formatDate(edu.to) : "Now"}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@@ -56,13 +63,7 @@ const Education = ({ education }: { education: EducationType[] }) => {
|
|||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h2">Education Credentials</Typography>
|
<Typography variant="h2">Education Credentials</Typography>
|
||||||
<Table
|
<Table>
|
||||||
// style={{
|
|
||||||
// tableLayout: "fixed",
|
|
||||||
// width: "50%",
|
|
||||||
// alignSelf: "left",
|
|
||||||
// }}
|
|
||||||
>
|
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell>School</TableCell>
|
<TableCell>School</TableCell>
|
||||||
|
|||||||
@@ -20,9 +20,28 @@ const Experience = ({ experience }: { experience: ExperienceType[] }) => {
|
|||||||
if (!experience) return <></>;
|
if (!experience) return <></>;
|
||||||
const experiences = experience.map((exp) => (
|
const experiences = experience.map((exp) => (
|
||||||
<TableRow key={exp._id}>
|
<TableRow key={exp._id}>
|
||||||
<TableCell>{exp.company}</TableCell>
|
<TableCell
|
||||||
<TableCell>{exp.title}</TableCell>
|
sx={{
|
||||||
<TableCell>
|
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"}
|
{formatDate(exp.from)} - {exp.to ? formatDate(exp.to) : "Now"}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
|
|||||||
@@ -148,7 +148,6 @@ const Navbar = () => {
|
|||||||
Logout
|
Logout
|
||||||
</a>
|
</a>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
,
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
guestLinks.map((el) => (
|
guestLinks.map((el) => (
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Box, Button, Container, TextField, Typography } from "@mui/material";
|
import { Box, Button, Container, TextField, Typography } from "@mui/material";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
import { createAlert } from "../../actions/alert";
|
||||||
import { addComment } from "../../actions/post";
|
import { addComment } from "../../actions/post";
|
||||||
import { useAppDispatch } from "../../utils/hooks";
|
import { useAppDispatch } from "../../utils/hooks";
|
||||||
|
|
||||||
@@ -18,8 +19,14 @@ const CommentForm = ({ postId }: { postId: string }) => {
|
|||||||
gap="1rem"
|
gap="1rem"
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
dispatch(addComment(postId, { text }));
|
if (text.length > 250) {
|
||||||
setText("");
|
dispatch(
|
||||||
|
createAlert("Comment longer than 250 characters", "danger"),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
dispatch(addComment(postId, { text }));
|
||||||
|
setText("");
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TextField
|
<TextField
|
||||||
|
|||||||
@@ -40,7 +40,12 @@ const CommentItem = ({
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="subtitle1">{text}</Typography>
|
<Typography
|
||||||
|
variant="subtitle1"
|
||||||
|
sx={{ textWrap: "wrap", wordBreak: "break-word" }}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { Box, Button, Container, TextField, Typography } from "@mui/material";
|
import { Box, Button, Container, TextField, Typography } from "@mui/material";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
import { createAlert } from "../../actions/alert";
|
||||||
import { addPost } from "../../actions/post";
|
import { addPost } from "../../actions/post";
|
||||||
import { useAppDispatch } from "../../utils/hooks";
|
import { useAppDispatch } from "../../utils/hooks";
|
||||||
|
|
||||||
const PostForm = () => {
|
const PostForm = () => {
|
||||||
const [text, setText] = useState("");
|
const [text, setText] = useState("");
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const handleSumbit = {};
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Typography>Say Something...</Typography>
|
<Typography>Say Something...</Typography>
|
||||||
@@ -18,8 +18,12 @@ const PostForm = () => {
|
|||||||
sx={{ mt: 3, mb: 3 }}
|
sx={{ mt: 3, mb: 3 }}
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
dispatch(addPost({ text }));
|
if (text.length > 250) {
|
||||||
setText("");
|
dispatch(createAlert("Post longer than 250 characters", "danger"));
|
||||||
|
} else {
|
||||||
|
dispatch(addPost({ text }));
|
||||||
|
setText("");
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TextField
|
<TextField
|
||||||
@@ -27,7 +31,9 @@ const PostForm = () => {
|
|||||||
label="Create a post"
|
label="Create a post"
|
||||||
fullWidth
|
fullWidth
|
||||||
value={text}
|
value={text}
|
||||||
onChange={(e) => setText(e.target.value)}
|
onChange={(e) => {
|
||||||
|
return setText(e.target.value);
|
||||||
|
}}
|
||||||
multiline
|
multiline
|
||||||
rows={3}
|
rows={3}
|
||||||
required
|
required
|
||||||
|
|||||||
@@ -6,14 +6,12 @@ import { Post } from "../../types";
|
|||||||
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
|
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
CardHeader,
|
CardHeader,
|
||||||
Container,
|
Container,
|
||||||
Table,
|
|
||||||
TableCell,
|
|
||||||
TableRow,
|
|
||||||
Typography,
|
Typography,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
|
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
|
||||||
@@ -36,45 +34,42 @@ const PostItem = ({
|
|||||||
subheader={formatDate(date)}
|
subheader={formatDate(date)}
|
||||||
/>
|
/>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="subtitle1">{text}</Typography>
|
<Typography
|
||||||
|
variant="subtitle1"
|
||||||
|
sx={{ textWrap: "wrap", wordBreak: "break-word" }}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<Table>
|
<Box
|
||||||
<TableRow>
|
sx={{
|
||||||
<TableCell>
|
display: "flex",
|
||||||
<Button onClick={async () => await dispatch(addLike(_id))}>
|
justifyContent: "space-evenly",
|
||||||
<ThumbUpIcon />
|
alignItems: "center",
|
||||||
</Button>
|
}}
|
||||||
</TableCell>
|
>
|
||||||
<TableCell>
|
<Button onClick={async () => await dispatch(addLike(_id))}>
|
||||||
<Typography display="inline-flex" variant="button">
|
<ThumbUpIcon />
|
||||||
{likes.length}
|
</Button>
|
||||||
</Typography>
|
<Typography display="inline-flex" variant="button">
|
||||||
</TableCell>
|
{likes.length}
|
||||||
<TableCell>
|
</Typography>
|
||||||
<Button onClick={async () => await dispatch(removeLike(_id))}>
|
<Button onClick={async () => await dispatch(removeLike(_id))}>
|
||||||
<ThumbDownIcon />
|
<ThumbDownIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</TableCell>
|
<Button component={Link} to={`/posts/${_id}`}>
|
||||||
<TableCell>
|
<Typography>Comments </Typography>
|
||||||
<Button component={Link} to={`/posts/${_id}`}>
|
</Button>
|
||||||
<Typography>Comments </Typography>
|
<Typography display="inline-flex" variant="button">
|
||||||
</Button>
|
{comments.length}
|
||||||
</TableCell>
|
</Typography>
|
||||||
<TableCell>
|
{!auth.loading && auth.user !== null && user === auth.user._id && (
|
||||||
<Typography display="inline-flex" variant="button">
|
<Button onClick={async () => await dispatch(deletePost(_id))}>
|
||||||
{comments.length}
|
<DeleteIcon />
|
||||||
</Typography>
|
</Button>
|
||||||
</TableCell>
|
)}
|
||||||
<TableCell>
|
</Box>
|
||||||
{!auth.loading && auth.user !== null && user === auth.user._id && (
|
|
||||||
<Button onClick={async () => await dispatch(deletePost(_id))}>
|
|
||||||
<DeleteIcon />
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</Table>
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,15 +1,8 @@
|
|||||||
import styled from "@emotion/styled";
|
import styled from "@emotion/styled";
|
||||||
import {
|
import { Button, Box, Container, TextField, Typography } from "@mui/material";
|
||||||
Button,
|
|
||||||
Box,
|
|
||||||
Container,
|
|
||||||
TextField,
|
|
||||||
Typography,
|
|
||||||
Checkbox,
|
|
||||||
FormControlLabel,
|
|
||||||
} from "@mui/material";
|
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
|
import { createAlert } from "../../actions/alert";
|
||||||
import { addEducation } from "../../actions/profile";
|
import { addEducation } from "../../actions/profile";
|
||||||
import { useAppDispatch } from "../../utils/hooks";
|
import { useAppDispatch } from "../../utils/hooks";
|
||||||
|
|
||||||
@@ -51,6 +44,21 @@ const AddEducation = () => {
|
|||||||
const onChange = (
|
const onChange = (
|
||||||
event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,
|
event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,
|
||||||
) => setFormData({ ...formData, [event.target.name]: event.target.value });
|
) => setFormData({ ...formData, [event.target.name]: event.target.value });
|
||||||
|
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 (
|
return (
|
||||||
<Container maxWidth="sm">
|
<Container maxWidth="sm">
|
||||||
@@ -68,12 +76,7 @@ const AddEducation = () => {
|
|||||||
noValidate
|
noValidate
|
||||||
maxWidth="500px"
|
maxWidth="500px"
|
||||||
sx={{ mt: 3 }}
|
sx={{ mt: 3 }}
|
||||||
onSubmit={async (e) => {
|
onSubmit={onSubmit}
|
||||||
e.preventDefault();
|
|
||||||
await dispatch(addEducation(formData)).then(() =>
|
|
||||||
navigate("/dashboard"),
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<TextField
|
<TextField
|
||||||
name="school"
|
name="school"
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
import { Container } from "@mui/system";
|
import { Container } from "@mui/system";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
|
import { createAlert } from "../../actions/alert";
|
||||||
import { addExperience } from "../../actions/profile";
|
import { addExperience } from "../../actions/profile";
|
||||||
import { useAppDispatch } from "../../utils/hooks";
|
import { useAppDispatch } from "../../utils/hooks";
|
||||||
|
|
||||||
@@ -69,9 +70,30 @@ const AddExperience = () => {
|
|||||||
sx={{ mt: 3 }}
|
sx={{ mt: 3 }}
|
||||||
onSubmit={async (e) => {
|
onSubmit={async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
await dispatch(addExperience(formData)).then(() =>
|
if (formData.description.length > 250) {
|
||||||
navigate("/dashboard"),
|
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
|
<TextField
|
||||||
|
|||||||
@@ -2,16 +2,16 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Box,
|
Box,
|
||||||
Container,
|
Container,
|
||||||
CssBaseline,
|
|
||||||
Grid,
|
|
||||||
InputLabel,
|
InputLabel,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
Select,
|
Select,
|
||||||
TextField,
|
TextField,
|
||||||
Typography,
|
Typography,
|
||||||
} from "@mui/material";
|
} 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 { Link, useMatch, useNavigate } from "react-router-dom";
|
||||||
|
import { createAlert } from "../../actions/alert";
|
||||||
import { createProfile, getCurrentProfile } from "../../actions/profile";
|
import { createProfile, getCurrentProfile } from "../../actions/profile";
|
||||||
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
|
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
|
||||||
|
|
||||||
@@ -86,28 +86,52 @@ const ProfileForm = () => {
|
|||||||
const linkedin = data.get("linkedin") as string;
|
const linkedin = data.get("linkedin") as string;
|
||||||
const instagram = data.get("instagram") as string;
|
const instagram = data.get("instagram") as string;
|
||||||
const status = data.get("status") as string;
|
const status = data.get("status") as string;
|
||||||
await dispatch(
|
if (facebook?.length > 100) {
|
||||||
createProfile(
|
dispatch(createAlert("Facebook link is longer 100 characters", "danger"));
|
||||||
{
|
} else if (linkedin?.length > 100) {
|
||||||
website,
|
dispatch(createAlert("LinkedIn link is longer 100 characters", "danger"));
|
||||||
location,
|
} else if (youtube?.length > 100) {
|
||||||
skills,
|
dispatch(createAlert("Youtube link is longer 100 characters", "danger"));
|
||||||
githubusername,
|
} else if (instagram?.length > 100) {
|
||||||
company,
|
dispatch(
|
||||||
bio,
|
createAlert("Instagram link is longer 100 characters", "danger"),
|
||||||
twitter,
|
);
|
||||||
facebook,
|
} else if (website?.length > 100) {
|
||||||
youtube,
|
dispatch(createAlert("Website link is longer 100 characters", "danger"));
|
||||||
linkedin,
|
} else if (skills.length > 100) {
|
||||||
instagram,
|
dispatch(createAlert("Skills is longer 100 characters", "danger"));
|
||||||
status,
|
} else if (location?.length > 50) {
|
||||||
},
|
dispatch(createAlert("Location is longer 100 characters", "danger"));
|
||||||
editing,
|
} else if (githubusername?.length > 50) {
|
||||||
),
|
dispatch(
|
||||||
).then((res) => {
|
createAlert("Github username is longer 50 characters", "danger"),
|
||||||
console.log(res);
|
);
|
||||||
if (!editing) navigate("/dashboard");
|
} 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 (
|
return (
|
||||||
@@ -123,48 +147,48 @@ const ProfileForm = () => {
|
|||||||
<Typography variant="body2">* = required field</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 container spacing={2}>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextField name="company" fullWidth label="Company" autoFocus />
|
<TextField name="company" fullWidth label="Company" autoFocus />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<Typography paddingY="1rem">
|
<Typography paddingY="1rem">
|
||||||
Could be your own company or one you work for
|
Could be your own company or one you work for
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextField name="website" fullWidth label="Website" />
|
<TextField name="website" fullWidth label="Website" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<Typography paddingY="1rem">
|
<Typography paddingY="1rem">
|
||||||
Could be your own a or a company website
|
Could be your own a or a company website
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextField name="location" fullWidth label="Location" />
|
<TextField name="location" fullWidth label="Location" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<Typography paddingY="1rem">
|
<Typography paddingY="1rem">
|
||||||
City & state suggest(eg. Boston MA)
|
City & state suggest(eg. Boston MA)
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextField name="skills" required fullWidth label="Skills" />
|
<TextField name="skills" required fullWidth label="Skills" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<Typography>
|
<Typography>
|
||||||
Please use comma separeted values (eg. HTML, CSS, JavaScript, PHP)
|
Please use comma separeted values (eg. HTML, CSS, JavaScript, PHP)
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextField name="githubUser" fullWidth label="Github Username" />
|
<TextField name="githubUser" fullWidth label="Github Username" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<Typography>
|
<Typography>
|
||||||
If you want your latest repositories, add a Github link and
|
If you want your latest repositories, add a Github link and
|
||||||
include your username
|
include your username
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<InputLabel id="status">Status *</InputLabel>
|
<InputLabel id="status">Status *</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -187,15 +211,15 @@ const ProfileForm = () => {
|
|||||||
<MenuItem value="Other">Other</MenuItem>
|
<MenuItem value="Other">Other</MenuItem>
|
||||||
</Select>
|
</Select>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<Typography paddingTop="2.3rem">
|
<Typography paddingTop="2.3rem">
|
||||||
Select Profesional Status
|
Select Profesional Status
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid size={{ xs: 12 }}>
|
||||||
<Typography>Tell us a little about yourself</Typography>
|
<Typography>Tell us a little about yourself</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid size={{ xs: 12 }}>
|
||||||
<TextField
|
<TextField
|
||||||
name="bio"
|
name="bio"
|
||||||
multiline
|
multiline
|
||||||
@@ -204,7 +228,7 @@ const ProfileForm = () => {
|
|||||||
label="A short bio of yourself"
|
label="A short bio of yourself"
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid size={{ xs: 12 }}>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={() => toggleSocialInputs(!displaySocialInputs)}
|
onClick={() => toggleSocialInputs(!displaySocialInputs)}
|
||||||
@@ -214,33 +238,33 @@ const ProfileForm = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
{displaySocialInputs ? (
|
{displaySocialInputs ? (
|
||||||
<>
|
<>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextField fullWidth name="twitter" label="Twitter URL" />
|
<TextField fullWidth name="twitter" label="Twitter URL" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}></Grid>
|
<Grid size={{ xs: 6 }}></Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextField fullWidth name="facebook" label="FaceBook URL" />
|
<TextField fullWidth name="facebook" label="FaceBook URL" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}></Grid>
|
<Grid size={{ xs: 6 }}></Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextField fullWidth name="youtube" label="YouTube URL" />
|
<TextField fullWidth name="youtube" label="YouTube URL" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}></Grid>
|
<Grid size={{ xs: 6 }}></Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextField fullWidth name="linkedin" label="Linkedin URL" />
|
<TextField fullWidth name="linkedin" label="Linkedin URL" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}></Grid>
|
<Grid size={{ xs: 6 }}></Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextField fullWidth name="instagram" label="Instagram URL" />
|
<TextField fullWidth name="instagram" label="Instagram URL" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
<Grid item xs={8}>
|
<Grid size={{ xs: 8 }}>
|
||||||
<Button variant="contained" type="submit">
|
<Button variant="contained" type="submit">
|
||||||
Submit Changes
|
Submit Changes
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={2}>
|
<Grid size={{ xs: 2 }}>
|
||||||
<Button variant="outlined">
|
<Button variant="outlined">
|
||||||
<Link
|
<Link
|
||||||
style={{ color: "inherit", textDecoration: "none" }}
|
style={{ color: "inherit", textDecoration: "none" }}
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import ProfileGithub from "./ProfileGithub";
|
|||||||
import { getProfileById } from "../../actions/profile";
|
import { getProfileById } from "../../actions/profile";
|
||||||
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
|
import { useAppDispatch, useAppSelector } from "../../utils/hooks";
|
||||||
import { EducationType, ExperienceType } from "../../types";
|
import { EducationType, ExperienceType } from "../../types";
|
||||||
import { Box, Button, Card, Paper, Typography } from "@mui/material";
|
import { Box, Button, Card, Container, Paper, Typography } from "@mui/material";
|
||||||
|
import Grid from "@mui/material/Grid2";
|
||||||
|
|
||||||
const Profile = () => {
|
const Profile = () => {
|
||||||
const profile = useAppSelector((state) => state.profile.profile);
|
const profile = useAppSelector((state) => state.profile.profile);
|
||||||
@@ -25,26 +26,54 @@ const Profile = () => {
|
|||||||
}, [dispatch, id]);
|
}, [dispatch, id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box display="flex" flexDirection="column" alignItems="center">
|
<>
|
||||||
{profile === null ? (
|
{profile === null ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<Paper sx={{ display: "grid", justifyItems: "center", marginY: "5px" }}>
|
||||||
<Button component={Link} to="/profiles">
|
<div>
|
||||||
Back To Profiles
|
<Button
|
||||||
</Button>
|
variant="contained"
|
||||||
{auth.isAuthenticated &&
|
component={Link}
|
||||||
auth.loading === false &&
|
to="/profiles"
|
||||||
auth.user !== null &&
|
sx={{
|
||||||
auth.user._id === profile.user._id && (
|
width: "70px",
|
||||||
<Button component={Link} to="/edit-profile">
|
margin: "5px",
|
||||||
Edit Profile
|
}}
|
||||||
</Button>
|
>
|
||||||
)}
|
Back
|
||||||
<Paper elevation={9} sx={{ width: "90%" }}>
|
</Button>
|
||||||
<ProfileTop profile={profile} />
|
{auth.isAuthenticated &&
|
||||||
<ProfileAbout profile={profile} />
|
auth.loading === false &&
|
||||||
<Box>
|
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>
|
<Typography variant="h2">Experience</Typography>
|
||||||
{profile.experience.length > 0 ? (
|
{profile.experience.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
@@ -58,8 +87,8 @@ const Profile = () => {
|
|||||||
) : (
|
) : (
|
||||||
<Typography variant="h4">No experience credentials</Typography>
|
<Typography variant="h4">No experience credentials</Typography>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Grid>
|
||||||
<Box>
|
<Grid size={6}>
|
||||||
<Typography variant="h2">Education</Typography>
|
<Typography variant="h2">Education</Typography>
|
||||||
{profile.education.length > 0 ? (
|
{profile.education.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
@@ -73,14 +102,14 @@ const Profile = () => {
|
|||||||
) : (
|
) : (
|
||||||
<Typography variant="h4">No education credentials</Typography>
|
<Typography variant="h4">No education credentials</Typography>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Grid>
|
||||||
{profile.githubusername && (
|
{profile.githubusername && (
|
||||||
<ProfileGithub username={profile.githubusername} />
|
<ProfileGithub username={profile.githubusername} />
|
||||||
)}
|
)}
|
||||||
</Paper>
|
</Grid>
|
||||||
</>
|
</Paper>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Box, Typography } from "@mui/material";
|
import { Box, List, ListItem, Typography } from "@mui/material";
|
||||||
import React, { Fragment } from "react";
|
import React, { Fragment } from "react";
|
||||||
import { ProfileType } from "../../types";
|
import { ProfileType } from "../../types";
|
||||||
|
|
||||||
@@ -11,21 +11,32 @@ const ProfileAbout = ({
|
|||||||
}: {
|
}: {
|
||||||
profile: ProfileType;
|
profile: ProfileType;
|
||||||
}) => (
|
}) => (
|
||||||
<Box>
|
<Box sx={{ textWrap: "wrap", maxWidth: "100%" }}>
|
||||||
{bio && (
|
{bio && (
|
||||||
<>
|
<>
|
||||||
<Typography>{name.trim().split(" ")[0]}s Bio</Typography>
|
<Typography color="info" variant="h5">
|
||||||
<Typography>{bio}</Typography>
|
<b>{name.trim().split(" ")[0]}'s Bio</b>
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
textWrap: "wrap",
|
||||||
|
wordBreak: "break-word",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{bio}
|
||||||
|
</Typography>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Typography>Skill Set</Typography>
|
<Typography color="info" variant="h5">
|
||||||
<Box>
|
<b>Skill Set</b>
|
||||||
|
</Typography>
|
||||||
|
<List>
|
||||||
{skills.map((skill, index) => (
|
{skills.map((skill, index) => (
|
||||||
<Box key={index}>
|
<ListItem key={index}>
|
||||||
<Typography>{skill}</Typography>
|
<Typography>{skill}</Typography>
|
||||||
</Box>
|
</ListItem>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</List>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Box, Typography } from "@mui/material";
|
import { Paper, Typography } from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { EducationType } from "../../types";
|
import { EducationType } from "../../types";
|
||||||
import formatDate from "../../utils/formatDate";
|
import formatDate from "../../utils/formatDate";
|
||||||
@@ -8,15 +8,49 @@ const ProfileEducation = ({
|
|||||||
}: {
|
}: {
|
||||||
education: EducationType;
|
education: EducationType;
|
||||||
}) => (
|
}) => (
|
||||||
<Box>
|
<Paper elevation={12} sx={{ margin: "10px", padding: "4px" }}>
|
||||||
<Typography variant="h3">{school}</Typography>
|
<Typography
|
||||||
<Typography>
|
variant="h4"
|
||||||
|
sx={{
|
||||||
|
textWrap: "wrap",
|
||||||
|
wordBreak: "break-word",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{school}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
textWrap: "wrap",
|
||||||
|
wordBreak: "break-word",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{formatDate(from)} - {to ? formatDate(to) : "Now"}
|
{formatDate(from)} - {to ? formatDate(to) : "Now"}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>Degree: {degree}</Typography>
|
<Typography
|
||||||
<Typography>Field Of Study: {fieldofstudy}</Typography>
|
sx={{
|
||||||
<Typography>Description: {description}</Typography>
|
textWrap: "wrap",
|
||||||
</Box>
|
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;
|
export default ProfileEducation;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Box, Typography } from "@mui/material";
|
import { Paper, Typography } from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { ExperienceType } from "../../types";
|
import { ExperienceType } from "../../types";
|
||||||
import formatDate from "../../utils/formatDate";
|
import formatDate from "../../utils/formatDate";
|
||||||
@@ -8,15 +8,43 @@ const ProfileExperience = ({
|
|||||||
}: {
|
}: {
|
||||||
experience: ExperienceType;
|
experience: ExperienceType;
|
||||||
}) => (
|
}) => (
|
||||||
<Box>
|
<Paper elevation={12} sx={{ margin: "10px", padding: "4px" }}>
|
||||||
<Typography variant="h3">{company}</Typography>
|
<Typography
|
||||||
|
sx={{
|
||||||
|
textWrap: "wrap",
|
||||||
|
wordBreak: "break-word",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<b>{company}</b>
|
||||||
|
</Typography>
|
||||||
<Typography>
|
<Typography>
|
||||||
{formatDate(from)} - {to ? formatDate(to) : "Now"}
|
{formatDate(from)} - {to ? formatDate(to) : "Now"}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>Position: {title}</Typography>
|
<Typography
|
||||||
<Typography>Location: {location}</Typography>
|
sx={{
|
||||||
<Typography>Description: {description}</Typography>
|
textWrap: "wrap",
|
||||||
</Box>
|
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;
|
export default ProfileExperience;
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ const ProfileGithub = ({ username }: { username: string }) => {
|
|||||||
}, [dispatch, username]);
|
}, [dispatch, username]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="profile-github">
|
<div>
|
||||||
<h2 className="text-primary my-1">Github Repos</h2>
|
<h2>Github Repos</h2>
|
||||||
{repos.map((repo) => (
|
{repos.map((repo) => (
|
||||||
<div key={repo.id} className="repo bg-white p-1 my-1">
|
<div key={repo.id}>
|
||||||
<div>
|
<div>
|
||||||
<h4>
|
<h4>
|
||||||
<a href={repo.html_url} target="_blank" rel="noopener noreferrer">
|
<a href={repo.html_url} target="_blank" rel="noopener noreferrer">
|
||||||
@@ -27,13 +27,9 @@ const ProfileGithub = ({ username }: { username: string }) => {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<ul>
|
<ul>
|
||||||
<li className="badge badge-primary">
|
<li>Stars: {repo.stargazers_count}</li>
|
||||||
Stars: {repo.stargazers_count}
|
<li>Watchers: {repo.watchers_count}</li>
|
||||||
</li>
|
<li>Forks: {repo.forks_count}</li>
|
||||||
<li className="badge badge-dark">
|
|
||||||
Watchers: {repo.watchers_count}
|
|
||||||
</li>
|
|
||||||
<li className="badge badge-light">Forks: {repo.forks_count}</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { BorderAll } from "@mui/icons-material";
|
||||||
import { Avatar, Box, Card, CardHeader, Typography } from "@mui/material";
|
import { Avatar, Box, Card, CardHeader, Typography } from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { ProfileType } from "../../types";
|
import { ProfileType } from "../../types";
|
||||||
@@ -14,19 +15,18 @@ const ProfileTop = ({
|
|||||||
}: {
|
}: {
|
||||||
profile: ProfileType;
|
profile: ProfileType;
|
||||||
}) => {
|
}) => {
|
||||||
console.log(avatar)
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<img className="round-img my-1" src={avatar} alt="" />
|
<img src={avatar} alt="" />
|
||||||
<Typography variant="h1">{name}</Typography>
|
<Typography variant="h2">{name}</Typography>
|
||||||
<Typography>
|
<Typography sx={{ textWrap: "wrap" }}>
|
||||||
{status} {company ? <span> at {company}</span> : null}
|
{status} {company ? <span> at {company}</span> : null}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>{location ? <span>{location}</span> : null}</Typography>
|
{location ? <Typography>{location}</Typography> : null}
|
||||||
<Box>
|
<Box>
|
||||||
{website ? (
|
{website ? (
|
||||||
<a href={website} target="_blank" rel="noopener noreferrer">
|
<a href={website} target="_blank" rel="noopener noreferrer">
|
||||||
<i className="fas fa-globe fa-2x" />
|
<i>{website}</i>
|
||||||
</a>
|
</a>
|
||||||
) : null}
|
) : null}
|
||||||
{social
|
{social
|
||||||
@@ -38,8 +38,9 @@ const ProfileTop = ({
|
|||||||
href={value}
|
href={value}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
|
style={{ display: "block" }}
|
||||||
>
|
>
|
||||||
<i className={`fab fa-${key} fa-2x`}></i>
|
<i>{value}</i>
|
||||||
</a>
|
</a>
|
||||||
))
|
))
|
||||||
: null}
|
: null}
|
||||||
|
|||||||
@@ -22,18 +22,21 @@ const ProfileItem = ({
|
|||||||
profile: ProfileType;
|
profile: ProfileType;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<Paper sx={{ padding: "100px" }}>
|
<Paper sx={{ width: "250px", paddingX: "10px" }}>
|
||||||
<img src={avatar} alt="" />
|
<img src={avatar} alt="" />
|
||||||
<Box>
|
<Typography color="info">
|
||||||
<Typography>{name}</Typography>
|
<b>{name}</b>
|
||||||
<Typography>
|
</Typography>
|
||||||
{status} {company && <span> at {company}</span>}
|
<Typography>
|
||||||
</Typography>
|
{status} {company && <span> at {company}</span>}
|
||||||
<Typography>{location && <span>{location}</span>}</Typography>
|
</Typography>
|
||||||
<Button component={Link} to={`/profile/${_id}`}>
|
<Typography>{location && <span>{location}</span>}</Typography>
|
||||||
View Profile
|
<Button component={Link} to={`/profile/${_id}`} variant="outlined">
|
||||||
</Button>
|
View Profile
|
||||||
</Box>
|
</Button>
|
||||||
|
<Typography color="info">
|
||||||
|
<b>Skills:</b>
|
||||||
|
</Typography>
|
||||||
<List>
|
<List>
|
||||||
{skills.slice(0, 4).map((skill, index) => (
|
{skills.slice(0, 4).map((skill, index) => (
|
||||||
<ListItemText key={index}>{skill}</ListItemText>
|
<ListItemText key={index}>{skill}</ListItemText>
|
||||||
|
|||||||
@@ -17,28 +17,33 @@ const Profiles = () => {
|
|||||||
|
|
||||||
const { profiles, loading } = useAppSelector((state) => state.profile);
|
const { profiles, loading } = useAppSelector((state) => state.profile);
|
||||||
return (
|
return (
|
||||||
<Container maxWidth="sm">
|
<Container>
|
||||||
<Box display="flex" flexDirection="column" alignItems="center">
|
{loading ? (
|
||||||
{loading ? (
|
<Spinner />
|
||||||
<Spinner />
|
) : (
|
||||||
) : (
|
<>
|
||||||
<>
|
<Typography variant="h2">Developers</Typography>
|
||||||
<Typography variant="h2">Developers</Typography>
|
<Typography variant="h6">
|
||||||
<Typography variant="h6">
|
Browse and connect with developers
|
||||||
Browse and connect with developers
|
</Typography>
|
||||||
</Typography>
|
<Box
|
||||||
<Box display="flex" flexDirection="row">
|
sx={{
|
||||||
{profiles.length > 0 && Array.isArray(profiles) ? (
|
display: "flex",
|
||||||
profiles.map((profile) => (
|
justifyContent: "left",
|
||||||
<ProfileItem key={profile._id} profile={profile} />
|
gap: "10px",
|
||||||
))
|
flexWrap: "wrap",
|
||||||
) : (
|
}}
|
||||||
<Typography>No profiles found...</Typography>
|
>
|
||||||
)}
|
{profiles.length > 0 && Array.isArray(profiles) ? (
|
||||||
</Box>
|
profiles.map((profile) => (
|
||||||
</>
|
<ProfileItem key={profile._id} profile={profile} />
|
||||||
)}
|
))
|
||||||
</Box>
|
) : (
|
||||||
|
<Typography>No profiles found...</Typography>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 292 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.1 MiB |
@@ -2,7 +2,6 @@ import React from "react";
|
|||||||
import ReactDOM from "react-dom/client";
|
import ReactDOM from "react-dom/client";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
|
|
||||||
import "./App2.css";
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(
|
||||||
document.getElementById("root") as HTMLElement,
|
document.getElementById("root") as HTMLElement,
|
||||||
);
|
);
|
||||||
|
|||||||
+96
-106
@@ -1,41 +1,41 @@
|
|||||||
import express from 'express';
|
import express from "express";
|
||||||
import axios from 'axios';
|
import axios from "axios";
|
||||||
import config from 'config';
|
import config from "config";
|
||||||
|
|
||||||
import auth from '../../middleware/auth';
|
import auth from "../../middleware/auth";
|
||||||
import { check, validationResult } from 'express-validator';
|
import { check, validationResult } from "express-validator";
|
||||||
|
|
||||||
// bring in normalize to give us a proper url, regardless of what user entered
|
// bring in normalize to give us a proper url, regardless of what user entered
|
||||||
import normalize from 'normalize-url';
|
import normalize from "normalize-url";
|
||||||
import checkObjectId from '../../middleware/checkObjectId';
|
import checkObjectId from "../../middleware/checkObjectId";
|
||||||
|
|
||||||
import Profile from '../../models/Profile';
|
import Profile from "../../models/Profile";
|
||||||
import User from '../../models/User';
|
import User from "../../models/User";
|
||||||
import Post from '../../models/Post';
|
import Post from "../../models/Post";
|
||||||
import { isUserId } from '../../utils';
|
import { isUserId } from "../../utils";
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
// @route GET api/profile/me
|
// @route GET api/profile/me
|
||||||
// @desc Get current users profile
|
// @desc Get current users profile
|
||||||
// @access Private
|
// @access Private
|
||||||
router.get('/me', auth, async (req, res) => {
|
router.get("/me", auth, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
if (isUserId(req)) {
|
if (isUserId(req)) {
|
||||||
const profile = await Profile.findOne({
|
const profile = await Profile.findOne({
|
||||||
user: req.user.id
|
user: req.user.id,
|
||||||
}).populate('user', ['name', 'avatar']);
|
}).populate("user", ["name", "avatar"]);
|
||||||
|
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
return res.status(400).json({ msg: 'There is no profile for this user' });
|
return res
|
||||||
|
.status(400)
|
||||||
|
.json({ msg: "There is no profile for this user" });
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(profile);
|
res.json(profile);
|
||||||
}
|
}
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
if (typeof err === 'string')
|
if (typeof err === "string") console.error(err);
|
||||||
console.error(err)
|
else if (err instanceof Error) console.error(err.message);
|
||||||
else if (err instanceof Error)
|
res.status(500).send("Server Error");
|
||||||
console.error(err.message);
|
|
||||||
res.status(500).send('Server Error');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -43,10 +43,10 @@ router.get('/me', auth, async (req, res) => {
|
|||||||
// @desc Create or update user profile
|
// @desc Create or update user profile
|
||||||
// @access Private
|
// @access Private
|
||||||
router.post(
|
router.post(
|
||||||
'/',
|
"/",
|
||||||
auth,
|
auth,
|
||||||
check('status', 'Status is required').notEmpty(),
|
check("status", "Status is required").notEmpty(),
|
||||||
check('skills', 'Skills is required').notEmpty(),
|
check("skills", "Skills is required").notEmpty(),
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
const errors = validationResult(req);
|
const errors = validationResult(req);
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
@@ -71,17 +71,23 @@ router.post(
|
|||||||
const profileFields = {
|
const profileFields = {
|
||||||
user: req.user.id,
|
user: req.user.id,
|
||||||
website:
|
website:
|
||||||
website && website !== ''
|
website && website !== ""
|
||||||
? normalize(website, { forceHttps: true })
|
? normalize(website, { forceHttps: true })
|
||||||
: '',
|
: "",
|
||||||
skills: Array.isArray(skills)
|
skills: Array.isArray(skills)
|
||||||
? skills
|
? skills
|
||||||
: skills.split(',').map((skill: string) => ' ' + skill.trim()),
|
: skills.split(",").map((skill: string) => " " + skill.trim()),
|
||||||
...rest
|
...rest,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build socialFields object
|
// Build socialFields object
|
||||||
const socialFields: { [key: string]: any } = { youtube, twitter, instagram, linkedin, facebook };
|
const socialFields: { [key: string]: any } = {
|
||||||
|
youtube,
|
||||||
|
twitter,
|
||||||
|
instagram,
|
||||||
|
linkedin,
|
||||||
|
facebook,
|
||||||
|
};
|
||||||
|
|
||||||
// normalize social fields to ensure valid url
|
// normalize social fields to ensure valid url
|
||||||
for (const [key, value] of Object.entries(socialFields)) {
|
for (const [key, value] of Object.entries(socialFields)) {
|
||||||
@@ -96,33 +102,29 @@ router.post(
|
|||||||
let profile = await Profile.findOneAndUpdate(
|
let profile = await Profile.findOneAndUpdate(
|
||||||
{ user: req.user.id },
|
{ user: req.user.id },
|
||||||
{ $set: profileFields },
|
{ $set: profileFields },
|
||||||
{ new: true, upsert: true, setDefaultsOnInsert: true }
|
{ new: true, upsert: true, setDefaultsOnInsert: true },
|
||||||
);
|
);
|
||||||
return res.json(profile);
|
return res.json(profile);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
if (typeof err === 'string')
|
if (typeof err === "string") console.error(err);
|
||||||
console.error(err)
|
else if (err instanceof Error) console.error(err.message);
|
||||||
else if (err instanceof Error)
|
return res.status(500).send("Server Error");
|
||||||
console.error(err.message);
|
|
||||||
return res.status(500).send('Server Error');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// @route GET api/profile
|
// @route GET api/profile
|
||||||
// @desc Get all profiles
|
// @desc Get all profiles
|
||||||
// @access Public
|
// @access Public
|
||||||
router.get('/', async (req, res) => {
|
router.get("/", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const profiles = await Profile.find().populate('user', ['name', 'avatar']);
|
const profiles = await Profile.find().populate("user", ["name", "avatar"]);
|
||||||
res.json(profiles);
|
res.json(profiles);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
if (typeof err === 'string')
|
if (typeof err === "string") console.error(err);
|
||||||
console.error(err)
|
else if (err instanceof Error) console.error(err.message);
|
||||||
else if (err instanceof Error)
|
res.status(500).send("Server Error");
|
||||||
console.error(err.message);
|
|
||||||
res.status(500).send('Server Error');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -130,31 +132,29 @@ router.get('/', async (req, res) => {
|
|||||||
// @desc Get profile by user ID
|
// @desc Get profile by user ID
|
||||||
// @access Public
|
// @access Public
|
||||||
router.get(
|
router.get(
|
||||||
'/user/:user_id',
|
"/user/:user_id",
|
||||||
checkObjectId('user_id'),
|
checkObjectId("user_id"),
|
||||||
async ({ params: { user_id } }, res) => {
|
async ({ params: { user_id } }, res) => {
|
||||||
try {
|
try {
|
||||||
const profile = await Profile.findOne({
|
const profile = await Profile.findOne({
|
||||||
user: user_id
|
user: user_id,
|
||||||
}).populate('user', ['name', 'avatar']);
|
}).populate("user", ["name", "avatar"]);
|
||||||
|
|
||||||
if (!profile) return res.status(400).json({ msg: 'Profile not found' });
|
if (!profile) return res.status(400).json({ msg: "Profile not found" });
|
||||||
|
|
||||||
return res.json(profile);
|
return res.json(profile);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
if (typeof err === 'string')
|
if (typeof err === "string") console.error(err);
|
||||||
console.error(err)
|
else if (err instanceof Error) console.error(err.message);
|
||||||
else if (err instanceof Error)
|
return res.status(500).json({ msg: "Server error" });
|
||||||
console.error(err.message);
|
|
||||||
return res.status(500).json({ msg: 'Server error' });
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// @route DELETE api/profile
|
// @route DELETE api/profile
|
||||||
// @desc Delete profile, user & posts
|
// @desc Delete profile, user & posts
|
||||||
// @access Private
|
// @access Private
|
||||||
router.delete('/', auth, async (req, res) => {
|
router.delete("/", auth, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
// Remove user posts
|
// Remove user posts
|
||||||
// Remove profile
|
// Remove profile
|
||||||
@@ -163,16 +163,14 @@ router.delete('/', auth, async (req, res) => {
|
|||||||
await Promise.all([
|
await Promise.all([
|
||||||
Post.deleteMany({ user: req.user.id }),
|
Post.deleteMany({ user: req.user.id }),
|
||||||
Profile.findOneAndRemove({ user: req.user.id }),
|
Profile.findOneAndRemove({ user: req.user.id }),
|
||||||
User.findOneAndRemove({ _id: req.user.id })
|
User.findOneAndRemove({ _id: req.user.id }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
res.json({ msg: 'User deleted' });
|
res.json({ msg: "User deleted" });
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
if (typeof err === 'string')
|
if (typeof err === "string") console.error(err);
|
||||||
console.error(err)
|
else if (err instanceof Error) console.error(err.message);
|
||||||
else if (err instanceof Error)
|
res.status(500).send("Server Error");
|
||||||
console.error(err.message);
|
|
||||||
res.status(500).send('Server Error');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -180,11 +178,11 @@ router.delete('/', auth, async (req, res) => {
|
|||||||
// @desc Add profile experience
|
// @desc Add profile experience
|
||||||
// @access Private
|
// @access Private
|
||||||
router.put(
|
router.put(
|
||||||
'/experience',
|
"/experience",
|
||||||
auth,
|
auth,
|
||||||
check('title', 'Title is required').notEmpty(),
|
check("title", "Title is required").notEmpty(),
|
||||||
check('company', 'Company is required').notEmpty(),
|
check("company", "Company is required").notEmpty(),
|
||||||
check('from', 'From date is required and needs to be from the past')
|
check("from", "From date is required and needs to be from the past")
|
||||||
.notEmpty()
|
.notEmpty()
|
||||||
.custom((value, { req }) => (req.body.to ? value < req.body.to : true)),
|
.custom((value, { req }) => (req.body.to ? value < req.body.to : true)),
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
@@ -205,26 +203,24 @@ router.put(
|
|||||||
res.json(profile);
|
res.json(profile);
|
||||||
}
|
}
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
if (typeof err === 'string')
|
if (typeof err === "string") console.error(err);
|
||||||
console.error(err)
|
else if (err instanceof Error) console.error(err.message);
|
||||||
else if (err instanceof Error)
|
res.status(500).send("Server Error");
|
||||||
console.error(err.message);
|
|
||||||
res.status(500).send('Server Error');
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// @route DELETE api/profile/experience/:exp_id
|
// @route DELETE api/profile/experience/:exp_id
|
||||||
// @desc Delete experience from profile
|
// @desc Delete experience from profile
|
||||||
// @access Private
|
// @access Private
|
||||||
|
|
||||||
router.delete('/experience/:exp_id', auth, async (req, res) => {
|
router.delete("/experience/:exp_id", auth, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
if (isUserId(req)) {
|
if (isUserId(req)) {
|
||||||
const foundProfile = await Profile.findOne({ user: req.user.id });
|
const foundProfile = await Profile.findOne({ user: req.user.id });
|
||||||
if (foundProfile) {
|
if (foundProfile) {
|
||||||
foundProfile.experience = foundProfile.experience.filter(
|
foundProfile.experience = foundProfile.experience.filter(
|
||||||
(exp: any) => exp._id.toString() !== req.params.exp_id
|
(exp: any) => exp._id.toString() !== req.params.exp_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
await foundProfile.save();
|
await foundProfile.save();
|
||||||
@@ -232,11 +228,9 @@ router.delete('/experience/:exp_id', auth, async (req, res) => {
|
|||||||
return res.status(200).json(foundProfile);
|
return res.status(200).json(foundProfile);
|
||||||
}
|
}
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
if (typeof err === 'string')
|
if (typeof err === "string") console.error(err);
|
||||||
console.error(err)
|
else if (err instanceof Error) console.error(err.message);
|
||||||
else if (err instanceof Error)
|
return res.status(500).json({ msg: "Server error" });
|
||||||
console.error(err.message);
|
|
||||||
return res.status(500).json({ msg: 'Server error' });
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -244,12 +238,12 @@ router.delete('/experience/:exp_id', auth, async (req, res) => {
|
|||||||
// @desc Add profile education
|
// @desc Add profile education
|
||||||
// @access Private
|
// @access Private
|
||||||
router.put(
|
router.put(
|
||||||
'/education',
|
"/education",
|
||||||
auth,
|
auth,
|
||||||
check('school', 'School is required').notEmpty(),
|
check("school", "School is required").notEmpty(),
|
||||||
check('degree', 'Degree is required').notEmpty(),
|
check("degree", "Degree is required").notEmpty(),
|
||||||
check('fieldofstudy', 'Field of study is required').notEmpty(),
|
check("fieldofstudy", "Field of study is required").notEmpty(),
|
||||||
check('from', 'From date is required and needs to be from the past')
|
check("from", "From date is required and needs to be from the past")
|
||||||
.notEmpty()
|
.notEmpty()
|
||||||
.custom((value, { req }) => (req.body.to ? value < req.body.to : true)),
|
.custom((value, { req }) => (req.body.to ? value < req.body.to : true)),
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
@@ -269,62 +263,58 @@ router.put(
|
|||||||
res.json(profile);
|
res.json(profile);
|
||||||
}
|
}
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
if (typeof err === 'string')
|
if (typeof err === "string") console.error(err);
|
||||||
console.error(err)
|
else if (err instanceof Error) console.error(err.message);
|
||||||
else if (err instanceof Error)
|
res.status(500).send("Server Error");
|
||||||
console.error(err.message);
|
|
||||||
res.status(500).send('Server Error');
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// @route DELETE api/profile/education/:edu_id
|
// @route DELETE api/profile/education/:edu_id
|
||||||
// @desc Delete education from profile
|
// @desc Delete education from profile
|
||||||
// @access Private
|
// @access Private
|
||||||
|
|
||||||
router.delete('/education/:edu_id', auth, async (req, res) => {
|
router.delete("/education/:edu_id", auth, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
if (isUserId(req)) {
|
if (isUserId(req)) {
|
||||||
const foundProfile = await Profile.findOne({ user: req.user.id });
|
const foundProfile = await Profile.findOne({ user: req.user.id });
|
||||||
if (foundProfile) {
|
if (foundProfile) {
|
||||||
foundProfile.education = foundProfile.education.filter(
|
foundProfile.education = foundProfile.education.filter(
|
||||||
(edu: any) => edu._id.toString() !== req.params.edu_id
|
(edu: any) => edu._id.toString() !== req.params.edu_id,
|
||||||
);
|
);
|
||||||
await foundProfile.save();
|
await foundProfile.save();
|
||||||
}
|
}
|
||||||
return res.status(200).json(foundProfile);
|
return res.status(200).json(foundProfile);
|
||||||
}
|
}
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
if (typeof err === 'string')
|
if (typeof err === "string") console.error(err);
|
||||||
console.error(err)
|
else if (err instanceof Error) console.error(err.message);
|
||||||
else if (err instanceof Error)
|
return res.status(500).json({ msg: "Server error" });
|
||||||
console.error(err.message);
|
|
||||||
return res.status(500).json({ msg: 'Server error' });
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// @route GET api/profile/github/:username
|
// @route GET api/profile/github/:username
|
||||||
// @desc Get user repos from Github
|
// @desc Get user repos from Github
|
||||||
// @access Public
|
// @access Public
|
||||||
router.get('/github/:username', async (req, res) => {
|
router.get("/github/:username", async (req, res) => {
|
||||||
|
console.log(config.get("githubToken"));
|
||||||
|
console.log(req.params.username);
|
||||||
try {
|
try {
|
||||||
const uri = encodeURI(
|
const uri = encodeURI(
|
||||||
`https://api.github.com/users/${req.params.username}/repos?per_page=5&sort=created:asc`
|
`https://api.github.com/users/${req.params.username}/repos?per_page=5&sort=created:asc`,
|
||||||
);
|
);
|
||||||
const headers = {
|
const headers = {
|
||||||
'user-agent': 'node.js',
|
"user-agent": "node.js",
|
||||||
Authorization: `token ${config.get('githubToken')}`
|
Authorization: `token ${config.get("githubToken")}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
const gitHubResponse = await axios.get(uri, { headers });
|
const gitHubResponse = await axios.get(uri, { headers });
|
||||||
return res.json(gitHubResponse.data);
|
return res.json(gitHubResponse.data);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
if (typeof err === 'string')
|
if (typeof err === "string") console.error(err);
|
||||||
console.error(err)
|
else if (err instanceof Error) console.error(err.message);
|
||||||
else if (err instanceof Error)
|
return res.status(404).json({ msg: "No Github profile found" });
|
||||||
console.error(err.message);
|
|
||||||
return res.status(404).json({ msg: 'No Github profile found' });
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router;
|
||||||
|
|||||||
Reference in New Issue
Block a user