Mern Social Network الجزء الثامن
فهاد الجزء الثامن من Mern Social Network غادي نزيدوا نكملوا الجزء الخاص بعرض وإضافة tweets ومنبعد غادي نشوفوا كيفاش نزيدو الإمكانية ديال متابعة وإلغاء متابعة المستخدمين.
نظرة سريعة بالفيديو
1- إضافة ل component Post
ف dossier components زيد fichier Post.js لي فيه غادي تعرض كل tweet على حدة مع التعليقات وعدد الإعجابات الخاصين بها.
الكود ديال الملف هو :
import React from "react";
import { isLogged } from "../helpers/auth";
import { useDispatch } from "react-redux";
import { likePost, unlikePost } from "../redux/actions/postActions";
import { deletePost } from "../redux/actions/postActions";
import CommentsList from "./CommentsList";
export default function Post({ post }) {
const [likes, setLikes] = React.useState([]);
const [like, setLike] = React.useState(false);
const [comments, setComments] = React.useState([]);
const date = new Date(post.createdAt);
const jwt = isLogged();
const dispatch = useDispatch();
const postedBy = post.postedBy._id || post.postedBy;
React.useEffect(() => {
setLikes(post && post.likes);
setComments(post && post.comments);
checklike(post && post.likes);
}, [post.likes, post.comments]);
function checklike(likes) {
let match = likes.indexOf(jwt.user._id) !== -1;
setLike(match);
}
return (
<div className="card mb-2 border border-primary">
<div className="card-header bg-light">
<div className="d-flex flex-row justify-content-start">
<img
src={`http://localhost:8888/api/user/photo/${postedBy}?${new Date().getTime()}`}
width="60"
height="60"
className="img-fluid rounded pr-2 mr-1"
alt={post.postedBy.name}
/>
<div className="post-by">
<h5 className="text-dark font-weight-bold">
{post.postedBy.name || jwt.user.name}
</h5>
<h5 className="text-danger font-weight-bold">
{date.toLocaleDateString()}
</h5>
{postedBy === jwt.user._id && (
<div className="align-self-end">
<i
onClick={() => dispatch(deletePost(jwt.token, post._id))}
className="fa fa-trash btn btn-danger"
></i>
</div>
)}
</div>
</div>
</div>
<div className="card-body">{post.text}</div>
<div className="card-footer">
<div className="d-flex justify-content-center align-items-center">
{like ? (
<>
<h5 className="mr-2">
<span className="badge badge-danger p-2 mr-2">
{" "}
{likes.length}{" "}
</span>
</h5>
<i
onClick={() =>
dispatch(unlikePost(jwt.token, jwt.user._id, post._id))
}
className="fa fa-heart text-danger mr-2"
></i>
</>
) : (
<>
<h5 className="mr-2">
<span className="badge badge-danger p-2 mr-2">
{" "}
{likes.length}{" "}
</span>
</h5>
<i
onClick={() =>
dispatch(likePost(jwt.token, jwt.user._id, post._id))
}
className="far fa-heart text-danger mr-2"
></i>
</>
)}
<h5 className="mr-2">
<span className="badge badge-primary p-2 mr-2">
{" "}
{comments.length}{" "}
</span>
</h5>
<i className="fa fa-comment text-primary"></i>
</div>
</div>
<CommentsList postId={post._id} comments={comments && comments} />
</div>
);
}
2- إضافة ل component AddPost
ف dossier components زيد fichier AddPost.js لي فيه غادي تكون الفورم ديال إضافة tweet فقاعدة البيانات.
الكود ديال الملف هو :
import React from "react";
import { useDispatch } from "react-redux";
import { isLogged } from "../helpers/auth";
import { addPost } from "../redux/actions/postActions";
export default function AddPost() {
const [post, setPost] = React.useState({
text: "",
});
const jwt = isLogged();
const dispatch = useDispatch();
function handleInputChange(event) {
setPost({ ...post, [event.target.name]: event.target.value });
}
function handleFormSubmit(event) {
event.preventDefault();
dispatch(addPost(jwt.token, jwt.user._id, post));
setPost({ ...post, text: "" });
}
return (
<div className="container">
<div className="row my-5">
<div className="col-md-6 mx-auto">
<h3 className="card-title">Publier</h3>
<form onSubmit={handleFormSubmit} className="card p-2">
<div className="form-group">
<textarea
rows="5"
cols="30"
name="text"
placeholder="Publier..."
value={post.text}
required
onChange={(event) => handleInputChange(event)}
className="form-control"
/>
</div>
<div className="form-group">
<button type="submit" className="btn btn-outline-primary">
Valider
</button>
</div>
</form>
</div>
</div>
</div>
);
}
3- إضافة ل component CommentsList
ف dossier components زيد fichier CommentsList.js لي فيه غادي يكونوا التعليقات كاملين لي تزادو والخاصين بكل تغريدة على حدة.
الكود ديال الملف هو :
import React from "react";
import { useDispatch } from "react-redux";
import { isLogged } from "../helpers/auth";
import { addComment } from "../redux/actions/postActions";
import Comment from "../components/Comment";
export default function CommentsList({ postId, comments }) {
const jwt = isLogged();
const dispatch = useDispatch();
const [text, setText] = React.useState("");
return (
<div>
<div className="p-4 my-2 d-flex flex-row align-items-center">
<img
src={`http://localhost:8888/api/user/photo/${jwt.user._id
}?${new Date().getTime()}`}
width="50"
height="50"
className="img-fluid rounded pr-2"
alt={jwt && jwt.user.name}
/>
<div className="form-group flex-grow-1">
<textarea
onKeyDown={(event) => {
if (event.keyCode === 13 && event.target.value) {
dispatch(addComment(jwt.token, jwt.user._id, postId, text));
setText("");
}
}}
rows="2"
cols="30"
name="text"
placeholder="Commenter..."
value={text}
required
onChange={(event) => setText(event.target.value)}
className="form-control"
/>
</div>
</div>
{comments.map((item, index) => (
<Comment comment={item} key={index} postId={postId} />
))}
</div>
);
}
4- إضافة ل component Comment
ف dossier components زيد fichier Comment.js لي فيه غادي يكون كل تعليق على حدة مع المعلومات ديال المستخدم لي زادو وإمكانية الحذف ديالو.
الكود ديال الملف هو :
import React from "react";
import { deleteComment } from "../redux/actions/postActions";
import { isLogged } from "../helpers/auth";
import { useDispatch } from "react-redux";
export default function Comment({ comment, postId }) {
const date = new Date(comment.created);
const jwt = isLogged();
const dispatch = useDispatch();
const postedBy = comment.postedBy._id || comment.postedBy;
return (
<div className="mb-2 col-12">
<div className="card-header bg-danger text-white rounded">
<div className="d-flex flex-row justify-content-start">
<img
src={`http://localhost:8888/api/user/photo/${postedBy}?${new Date().getTime()}`}
width="50"
height="50"
className="img-fluid rounded pr-2"
alt={comment.postedBy.name}
/>
</div>
<div>
<h5 className="text-white font-weight-bold">
{comment.postedBy.name || jwt.user.name}
</h5>
<h5 className="text-white font-weight-bold">
{date.toLocaleDateString()}
</h5>
</div>
{postedBy === jwt.user._id && (
<div className="col-12">
<i
onClick={() =>
dispatch(
deleteComment(jwt.token, jwt.user._id, postId, comment)
)
}
className="fa fa-trash btn btn-danger ml-auto"
></i>
</div>
)}
</div>
<div className="card-body border border-danger">
<div className="card-text">{comment.text}</div>
</div>
</div>
);
}