diff --git a/.gitignore b/.gitignore index 6b223e3..f122144 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules App.css +start_in_tmux.sh diff --git a/client/src/actions/post.ts b/client/src/actions/post.ts index 01aedb8..80f39d7 100755 --- a/client/src/actions/post.ts +++ b/client/src/actions/post.ts @@ -121,7 +121,6 @@ export const addPost = (formData: { text: string }): AppThunk => async (dispatch) => { try { - console.log(1); const res = await api.post("/posts", formData); dispatch(addPostAction(res.data)); @@ -170,7 +169,6 @@ export const getPost = } } }; -// Add comment export const addComment = (postId: string, formData: { text: string }): AppThunk => async (dispatch) => { @@ -181,6 +179,7 @@ export const addComment = dispatch(createAlert("Comment Added", "success")); } catch (err: unknown) { + console.log(err); if (err instanceof AxiosError) { if ( err !== undefined && diff --git a/client/src/actions/profile.ts b/client/src/actions/profile.ts index d06c3ae..81d04b1 100755 --- a/client/src/actions/profile.ts +++ b/client/src/actions/profile.ts @@ -96,6 +96,7 @@ export const createProfile = try { const res = await api.post("/profile", formData); + console.log(res); dispatch(getProfile(res.data)); dispatch( diff --git a/client/src/components/dashboard/Education.tsx b/client/src/components/dashboard/Education.tsx index 873cfcd..9c4d9f4 100755 --- a/client/src/components/dashboard/Education.tsx +++ b/client/src/components/dashboard/Education.tsx @@ -3,27 +3,46 @@ import { deleteEducation } from "../../actions/profile"; import formatDate from "../../utils/formatDate"; import { EducationType } from "../../types"; import { useAppDispatch } from "../../utils/hooks"; -import { Box, Typography } from "@mui/material"; +import { + Box, + Button, + TableRow, + Table, + TableBody, + TableCell, + TableHead, + Typography, + TableContainer, +} from "@mui/material"; const Education = ({ education }: { education: EducationType[] }) => { const dispatch = useAppDispatch(); if (!education) return <>; const educations = education.map((edu) => ( - - {edu.school} - {edu.degree} - + + + {edu.school} + + + {edu.degree} + + {formatDate(edu.from)} - {edu.to ? formatDate(edu.to) : "Now"} - - - - - + + + )); if (education.length === 0) @@ -35,20 +54,26 @@ const Education = ({ education }: { education: EducationType[] }) => { ); return ( - <> - Education Credentials - - - - - - - - - {educations} -
SchoolDegreeYears -
- + + Education Credentials + + + + School + Degree + Years + + + + {educations} +
+
); }; diff --git a/client/src/components/dashboard/Experience.tsx b/client/src/components/dashboard/Experience.tsx index 12b8649..052a64a 100755 --- a/client/src/components/dashboard/Experience.tsx +++ b/client/src/components/dashboard/Experience.tsx @@ -1,29 +1,36 @@ -import { Typography } from "@mui/material"; import React from "react"; import { deleteExperience } from "../../actions/profile"; import { ExperienceType } from "../../types"; import formatDate from "../../utils/formatDate"; import { useAppDispatch } from "../../utils/hooks"; +import { + Box, + Button, + TableRow, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + Typography, +} from "@mui/material"; const Experience = ({ experience }: { experience: ExperienceType[] }) => { const dispatch = useAppDispatch(); if (!experience) return <>; const experiences = experience.map((exp) => ( - - {exp.company} - {exp.title} - + + {exp.company} + {exp.title} + {formatDate(exp.from)} - {exp.to ? formatDate(exp.to) : "Now"} - - - - - + + + )); if (experiences.length === 0) @@ -34,20 +41,22 @@ const Experience = ({ experience }: { experience: ExperienceType[] }) => { ); return ( - <> -

Experience Credentials

- - - - - - - - - {experiences} -
CompanyTitleYears -
- + + Experience Credentials + + + + + Company + Title + Years + + + + {experiences} +
+
+
); }; diff --git a/client/src/components/layout/Alert.tsx b/client/src/components/layout/Alert.tsx index 0de1fc6..a124c6b 100755 --- a/client/src/components/layout/Alert.tsx +++ b/client/src/components/layout/Alert.tsx @@ -1,15 +1,22 @@ -import React from "react"; +import { Box } from "@mui/material"; +import AlertMUI from "@mui/material/Alert"; import { useAppSelector } from "../../utils/hooks"; const Alert = () => { const alerts = useAppSelector((state) => state.alert); return ( -
- {alerts.map((alert) => ( -
- {alert.msg} -
- ))} -
+ + {alerts.map((alert) => + alert.alertType === "danger" ? ( + + {alert.msg} + + ) : ( + + {alert.msg} + + ), + )} + ); }; diff --git a/client/src/components/post/CommentForm.tsx b/client/src/components/post/CommentForm.tsx index 898005e..f0b8e5e 100755 --- a/client/src/components/post/CommentForm.tsx +++ b/client/src/components/post/CommentForm.tsx @@ -16,9 +16,9 @@ const CommentForm = ({ postId }: { postId: string }) => { flexDirection="column" alignItems="left" gap="1rem" - onSubmit={async (e) => { + onSubmit={(e) => { e.preventDefault(); - await dispatch(addComment(postId, { text })); + dispatch(addComment(postId, { text })); setText(""); }} > @@ -31,7 +31,7 @@ const CommentForm = ({ postId }: { postId: string }) => { value={text} onChange={(e) => setText(e.target.value)} /> - + ); diff --git a/client/src/components/post/CommentItem.tsx b/client/src/components/post/CommentItem.tsx index 331553e..5935fce 100755 --- a/client/src/components/post/CommentItem.tsx +++ b/client/src/components/post/CommentItem.tsx @@ -34,18 +34,14 @@ const CommentItem = ({ title={{name}} subheader={formatDate(date)} /> + {!auth.loading && auth.user !== null && user === auth.user._id && ( + + )} {text} - - {!auth.loading && auth.user !== null && user === auth.user._id && ( - - )} - ); diff --git a/client/src/components/posts/PostForm.tsx b/client/src/components/posts/PostForm.tsx index cbe0d67..bbaca04 100755 --- a/client/src/components/posts/PostForm.tsx +++ b/client/src/components/posts/PostForm.tsx @@ -6,8 +6,9 @@ import { useAppDispatch } from "../../utils/hooks"; const PostForm = () => { const [text, setText] = useState(""); const dispatch = useAppDispatch(); + const handleSumbit = {}; return ( - + Say Something... { gap="1rem" noValidate sx={{ mt: 3, mb: 3 }} - onSubmit={async (e) => { - console.log(1); + onSubmit={(e) => { e.preventDefault(); - await dispatch(addPost({ text })); + dispatch(addPost({ text })); setText(""); }} > @@ -32,9 +32,11 @@ const PostForm = () => { rows={3} required /> - + - + ); }; diff --git a/client/src/components/posts/PostItem.tsx b/client/src/components/posts/PostItem.tsx index 882f3e4..fd4533c 100755 --- a/client/src/components/posts/PostItem.tsx +++ b/client/src/components/posts/PostItem.tsx @@ -6,13 +6,14 @@ import { Post } from "../../types"; import { useAppDispatch, useAppSelector } from "../../utils/hooks"; import { Avatar, - Box, Button, Card, CardContent, CardHeader, - CardMedia, Container, + Table, + TableCell, + TableRow, Typography, } from "@mui/material"; import ThumbDownIcon from "@mui/icons-material/ThumbDown"; @@ -38,28 +39,42 @@ const PostItem = ({ {text} - - - - {likes.length} - - - - - {comments.length} - - {!auth.loading && auth.user !== null && user === auth.user._id && ( - - )} - + + + + + + + + {likes.length} + + + + + + + + + + + {comments.length} + + + + {!auth.loading && auth.user !== null && user === auth.user._id && ( + + )} + + +
); }; diff --git a/client/src/components/profile-forms/AddEducation.tsx b/client/src/components/profile-forms/AddEducation.tsx index 098c50c..53c0a42 100755 --- a/client/src/components/profile-forms/AddEducation.tsx +++ b/client/src/components/profile-forms/AddEducation.tsx @@ -49,7 +49,7 @@ const AddEducation = () => { formData; const onChange = ( - event: React.ChangeEvent + event: React.ChangeEvent, ) => setFormData({ ...formData, [event.target.name]: event.target.value }); return ( @@ -71,7 +71,7 @@ const AddEducation = () => { onSubmit={async (e) => { e.preventDefault(); await dispatch(addEducation(formData)).then(() => - navigate("/dashboard") + navigate("/dashboard"), ); }} > @@ -79,34 +79,52 @@ const AddEducation = () => { name="school" label="School or Bootcamp" fullWidth + value={school} + onChange={onChange} autoFocus /> - - + + From Date - - setFormData({ ...formData, current: !current })} - inputProps={{ "aria-label": "controlled" }} - /> - } - label="Current" - /> - + {/* */} + {/* setFormData({ ...formData, current: !current })} */} + {/* inputProps={{ "aria-label": "controlled" }} */} + {/* /> */} + {/* } */} + {/* label="Current" */} + {/* /> */} + {/* */} To Date - + - + + diff --git a/client/src/components/profile/Profile.tsx b/client/src/components/profile/Profile.tsx index 9db8ad4..a8154be 100755 --- a/client/src/components/profile/Profile.tsx +++ b/client/src/components/profile/Profile.tsx @@ -37,11 +37,11 @@ const Profile = () => { auth.loading === false && auth.user !== null && auth.user._id === profile.user._id && ( - )} - + diff --git a/client/src/components/profile/ProfileAbout.tsx b/client/src/components/profile/ProfileAbout.tsx index c1e3c4d..5520201 100755 --- a/client/src/components/profile/ProfileAbout.tsx +++ b/client/src/components/profile/ProfileAbout.tsx @@ -21,7 +21,7 @@ const ProfileAbout = ({ Skill Set {skills.map((skill, index) => ( - + {skill} ))} diff --git a/client/src/components/profiles/ProfileItem.tsx b/client/src/components/profiles/ProfileItem.tsx index 269b267..d8ccc2d 100755 --- a/client/src/components/profiles/ProfileItem.tsx +++ b/client/src/components/profiles/ProfileItem.tsx @@ -1,4 +1,11 @@ -import { Box, Button, Paper, Typography } from "@mui/material"; +import { + Box, + Button, + List, + ListItemText, + Paper, + Typography, +} from "@mui/material"; import React from "react"; import { Link } from "react-router-dom"; import { ProfileType } from "../../types"; @@ -15,8 +22,8 @@ const ProfileItem = ({ profile: ProfileType; }) => { return ( - - + + {name} @@ -27,13 +34,11 @@ const ProfileItem = ({ View Profile -
    + {skills.slice(0, 4).map((skill, index) => ( -
  • - {skill} -
  • + {skill} ))} -
+
); }; diff --git a/client/src/components/profiles/Profiles.tsx b/client/src/components/profiles/Profiles.tsx index 7391b41..5786004 100755 --- a/client/src/components/profiles/Profiles.tsx +++ b/client/src/components/profiles/Profiles.tsx @@ -27,7 +27,7 @@ const Profiles = () => { Browse and connect with developers - + {profiles.length > 0 && Array.isArray(profiles) ? ( profiles.map((profile) => ( diff --git a/server/config/config.js b/server/config/config.js deleted file mode 100644 index 8744a2e..0000000 --- a/server/config/config.js +++ /dev/null @@ -1,5 +0,0 @@ -const MONGO_URL = process.env.MONGO_URL || undefined; - -module.exports = { - MONGO_URL, -}; diff --git a/server/config/db.ts b/server/config/db.ts index c556e42..c2cf9c8 100755 --- a/server/config/db.ts +++ b/server/config/db.ts @@ -1,20 +1,18 @@ import mongoose from "mongoose"; -// import config from "config"; -const { MONGO_URL } = require("./config"); +import config from "config"; -// const db = config.get('mongoURI'); +const db = process.env.MONGO_URL + ? process.env.MONGO_URL + : config.get("mongoURI"); const connectDB = async () => { try { - if (typeof MONGO_URL === "string") await mongoose.connect(MONGO_URL); + if (typeof db === "string") await mongoose.connect(db); console.log("MongoDB Connected..."); } catch (err: unknown) { if (typeof err === "string") console.error(err); - else if (err instanceof Error) { - console.error(err.message); - console.log(MONGO_URL); - } + else if (err instanceof Error) console.error(err.message); process.exit(1); } }; diff --git a/server/middleware/auth.ts b/server/middleware/auth.ts index e0cab3e..71378d8 100755 --- a/server/middleware/auth.ts +++ b/server/middleware/auth.ts @@ -1,34 +1,32 @@ -import config from 'config' -import jwt from 'jsonwebtoken' -import type { Request, Response, NextFunction } from 'express'; +import config from "config"; +import jwt from "jsonwebtoken"; +import type { Request, Response, NextFunction } from "express"; -interface ResponseAndUser extends Request { user?: string } +interface ResponseAndUser extends Request { + user?: string; +} function auth(req: ResponseAndUser, res: Response, next: NextFunction) { - // Get token from header - const token = req.header('x-auth-token'); + const token = req.header("x-auth-token"); // Check if not token if (!token) { - return res.status(401).json({ msg: 'No token, authorization denied' }); + return res.status(401).json({ msg: "No token, authorization denied" }); } // Verify token try { - jwt.verify(token, config.get('jwtSecret'), (error, decoded) => { + jwt.verify(token, config.get("jwtSecret"), (error, decoded) => { if (error) { - return res.status(401).json({ msg: 'Token is not valid' }); + return res.status(401).json({ msg: "Token is not valid" }); } else { - if (decoded && typeof decoded !== "string") - req.user = decoded?.user; + if (decoded && typeof decoded !== "string") req.user = decoded?.user; next(); } }); } catch (err) { - console.error('something wrong with auth middleware'); - res.status(500).json({ msg: 'Server Error' }); + console.error("something wrong with auth middleware"); + res.status(500).json({ msg: "Server Error" }); } - -}; -export default auth - +} +export default auth; diff --git a/server/routers/api/posts.ts b/server/routers/api/posts.ts index c649603..628bbaa 100755 --- a/server/routers/api/posts.ts +++ b/server/routers/api/posts.ts @@ -1,12 +1,10 @@ - -import express, { Request, Response } from 'express' +import express, { Request, Response } from "express"; import { check, validationResult } from "express-validator"; import auth from "../../middleware/auth"; import Post from "../../models/Post"; import User from "../../models/User"; import checkObjectId from "../../middleware/checkObjectId"; -import { isUserId } from '../../utils'; - +import { isUserId } from "../../utils"; const router = express.Router(); @@ -36,22 +34,18 @@ router.post( }); const post = await newPost.save(); res.json(post); + } else { + throw new Error("Error finding the user"); } - else { - throw new Error('Error finding the user') - } - } - else { - throw new Error('Error finding the user') + } else { + throw new Error("Error finding the user"); } } catch (err: unknown) { - if (typeof err === 'string') - console.error(err) - else if (err instanceof Error) - console.error(err.message); + if (typeof err === "string") console.error(err); + else if (err instanceof Error) console.error(err.message); res.status(500).send("Server Error"); } - } + }, ); // @route GET api/posts @@ -62,10 +56,8 @@ router.get("/", auth, async (req, res) => { const posts = await Post.find().sort({ date: -1 }); res.json(posts); } catch (err: unknown) { - if (typeof err === 'string') - console.error(err) - else if (err instanceof Error) - console.error(err.message); + if (typeof err === "string") console.error(err); + else if (err instanceof Error) console.error(err.message); res.status(500).send("Server Error"); } }); @@ -83,10 +75,8 @@ router.get("/:id", auth, checkObjectId("id"), async (req, res) => { res.json(post); } catch (err: unknown) { - if (typeof err === 'string') - console.error(err) - else if (err instanceof Error) - console.error(err.message); + if (typeof err === "string") console.error(err); + else if (err instanceof Error) console.error(err.message); res.status(500).send("Server Error"); } @@ -95,35 +85,35 @@ router.get("/:id", auth, checkObjectId("id"), async (req, res) => { // @route DELETE api/posts/:id // @desc Delete a post // @access Private -router.delete("/:id", [auth, checkObjectId("id")], async (req: Request, res: Response) => { - try { - const post = await Post.findOne({ _id: req.params.id }); +router.delete( + "/:id", + [auth, checkObjectId("id")], + async (req: Request, res: Response) => { + try { + const post = await Post.findOne({ _id: req.params.id }); - if (!post) { - return res.status(404).json({ msg: "Post not found" }); - } - - // Check user - if (post.user && isUserId(req)) { - if (post.user.toString() !== req.user.id) { - return res.status(401).json({ msg: "User not authorized" }); + if (!post) { + return res.status(404).json({ msg: "Post not found" }); } - } - else { - throw new Error('Error in req.user') - } - await post.deleteOne(); - res.json({ msg: "Post removed" }); + // Check user + if (post.user && isUserId(req)) { + if (post.user.toString() !== req.user.id) { + return res.status(401).json({ msg: "User not authorized" }); + } + } else { + throw new Error("Error in req.user"); + } + await post.deleteOne(); - } catch (err: unknown) { - if (typeof err === 'string') - console.error(err) - else if (err instanceof Error) - console.error(err.message); - res.status(500).send("Server Error"); - } -}); + res.json({ msg: "Post removed" }); + } catch (err: unknown) { + if (typeof err === "string") console.error(err); + else if (err instanceof Error) console.error(err.message); + res.status(500).send("Server Error"); + } + }, +); // @route PUT api/posts/like/:id // @desc Like a post @@ -138,19 +128,17 @@ router.put("/like/:id", auth, checkObjectId("id"), async (req, res) => { return res.status(400).json({ msg: "Post already liked" }); } - const user: any = req.user.id + const user: any = req.user.id; // can't make string into ObjectID post.likes.unshift({ user }); await post.save(); - return res.json(post.likes) - }; + return res.json(post.likes); + } } catch (err: unknown) { - if (typeof err === 'string') - console.error(err) - else if (err instanceof Error) - console.error(err.message); + if (typeof err === "string") console.error(err); + else if (err instanceof Error) console.error(err.message); res.status(500).send("Server Error"); } }); @@ -164,29 +152,23 @@ router.put("/unlike/:id", auth, checkObjectId("id"), async (req, res) => { // Check if the post has not yet been liked if (post && isUserId(req)) { - if (!post.likes.some((like) => like.user?.toString() === req.user.id)) { return res.status(400).json({ msg: "Post has not yet been liked" }); } // remove the like - post.likes = post.likes.filter( - ({ user }) => { - if (user) - return user.toString() !== req.user.id - return false - } - ); + post.likes = post.likes.filter(({ user }) => { + if (user) return user.toString() !== req.user.id; + return false; + }); await post.save(); return res.json(post.likes); } } catch (err: unknown) { - if (typeof err === 'string') - console.error(err) - else if (err instanceof Error) - console.error(err.message); + if (typeof err === "string") console.error(err); + else if (err instanceof Error) console.error(err.message); res.status(500).send("Server Error"); } }); @@ -220,20 +202,15 @@ router.post( post.comments.unshift(newComment as any); await post.save(); res.json(post.comments); - } - throw new Error('Error in finding post') - } - throw new Error('Error in finding user') - } - throw new Error('Error in parsing the req') + } else throw new Error("Error in finding post"); + } else throw new Error("Error in finding user"); + } else throw new Error("Error in parsing the req"); } catch (err: unknown) { - if (typeof err === 'string') - console.error(err) - else if (err instanceof Error) - console.error(err.message); + if (typeof err === "string") console.error(err); + else if (err instanceof Error) console.error(err.message); res.status(500).send("Server Error"); } - } + }, ); // @route DELETE api/posts/comment/:id/:comment_id @@ -246,19 +223,24 @@ router.delete("/comment/:id/:comment_id", auth, async (req, res) => { // Pull out comment if (post) { const comment = post.comments.find( - (comment: any) => comment.id === req.params.comment_id + (comment: any) => comment.id === req.params.comment_id, ); // Make sure comment exists if (!comment) { return res.status(404).json({ msg: "Comment does not exist" }); } // Check user - if ('user' in comment && comment.user && isUserId(req) && comment.user.toString() !== req.user.id) { + if ( + "user" in comment && + comment.user && + isUserId(req) && + comment.user.toString() !== req.user.id + ) { return res.status(401).json({ msg: "User not authorized" }); } post.comments = post.comments.filter( - ({ id }: any) => id !== req.params.comment_id + ({ id }: any) => id !== req.params.comment_id, ); await post.save(); @@ -266,12 +248,10 @@ router.delete("/comment/:id/:comment_id", auth, async (req, res) => { return res.json(post.comments); } } catch (err: unknown) { - if (typeof err === 'string') - console.error(err) - else if (err instanceof Error) - console.error(err.message); + if (typeof err === "string") console.error(err); + else if (err instanceof Error) console.error(err.message); return res.status(500).send("Server Error"); } }); -module.exports = router +module.exports = router; diff --git a/server/server.ts b/server/server.ts index 538693b..ad7e537 100644 --- a/server/server.ts +++ b/server/server.ts @@ -16,6 +16,7 @@ app.use("/api/posts", require("./routers/api/posts")); // Serve static assets in production if (process.env.NODE_ENV === "production") { + console.log("in production"); app.use(express.static("client/build")); app.get("*", (req, res) => [ res.sendFile(path.resolve(__dirname, "client", "build", "index.html")),