🐛 PostListItems were not updating successfully when liked or edited

Signed-off-by: Pau Costa <mico@micodev.es>
main
Pau Costa Ferrer 2024-02-12 12:04:21 +01:00
parent 2d9042235c
commit a5e6a9505b
5 changed files with 112 additions and 25 deletions

View File

@ -55,23 +55,41 @@ export const fetchGlobalPosts = (): AppThunk => async (dispatch: any) => {
}; };
export const likePost = export const likePost =
(postId: number): AppThunk => (postId: number, postType?: "global" | "followed"): AppThunk =>
async (dispatch: any) => { async (dispatch: any) => {
const postApi = createApi(store); const postApi = createApi(store);
dispatch(setStatus(Status.loading)); dispatch(setStatus(Status.loading));
await postApi.likePost(postId); await postApi.likePost(postId);
dispatch(setStatus(Status.idle)); dispatch(setStatus(Status.idle));
if (postType === "global") {
dispatch(fetchGlobalPosts());
} else if (postType === "followed") {
dispatch(fetchFollowedPosts());
} else {
dispatch(fetchFollowedPosts());
dispatch(fetchGlobalPosts());
}
}; };
export const unLikePost = export const unLikePost =
(postId: number): AppThunk => (postId: number, postType?: "global" | "followed"): AppThunk =>
async (dispatch: any) => { async (dispatch: any) => {
const postApi = createApi(store); const postApi = createApi(store);
dispatch(setStatus(Status.loading)); dispatch(setStatus(Status.loading));
await postApi.unlikePost(postId); await postApi.unlikePost(postId);
dispatch(setStatus(Status.idle)); dispatch(setStatus(Status.idle));
if (postType === "global") {
dispatch(fetchGlobalPosts());
} else if (postType === "followed") {
dispatch(fetchFollowedPosts());
} else {
dispatch(fetchFollowedPosts());
dispatch(fetchGlobalPosts());
}
}; };
export const fetchAPost = export const fetchAPost =
@ -95,7 +113,7 @@ export const commentAPost =
dispatch(fetchAPost(postId)); dispatch(fetchAPost(postId));
dispatch(setStatus(Status.idle)); dispatch(setStatus(Status.idle));
}; };
export const createPost = export const createPost =
(title: string, content: string): AppThunk => (title: string, content: string): AppThunk =>
async (dispatch: any) => { async (dispatch: any) => {
@ -107,6 +125,28 @@ export const createPost =
dispatch(setStatus(Status.idle)); dispatch(setStatus(Status.idle));
}; };
export const updatePost =
(postId: number, title: string, content: string): AppThunk =>
async (dispatch: any) => {
const postApi = createApi(store);
dispatch(setStatus(Status.loading));
await postApi.updatePost(postId, { title, content });
dispatch(fetchAPost(postId));
dispatch(fetchGlobalPosts());
dispatch(setStatus(Status.idle));
};
export const deletePost =
(postId: number): AppThunk =>
async (dispatch: any) => {
const postApi = createApi(store);
dispatch(setStatus(Status.loading));
await postApi.deletePost(postId);
dispatch(setStatus(Status.idle));
};
export const { setFollowedPosts, setGlobalPosts, setStatus, setAPost } = export const { setFollowedPosts, setGlobalPosts, setStatus, setAPost } =
postSlice.actions; postSlice.actions;

View File

@ -21,7 +21,8 @@ import { selectUserInfo } from "../app/loginSlice";
interface PostListItemProps { interface PostListItemProps {
post: Post; post: Post;
postType: "all" | "user"; postType: "feed" | "user";
feedType?: "global" | "followed";
} }
export default function PostListItem(props: PostListItemProps) { export default function PostListItem(props: PostListItemProps) {
@ -40,19 +41,19 @@ export default function PostListItem(props: PostListItemProps) {
props.post.likedBy?.some((user) => user.id === userInfo.id) || false props.post.likedBy?.some((user) => user.id === userInfo.id) || false
); );
setNumberOfLikes(props.post.likedBy?.length || 0); setNumberOfLikes(props.post.likedBy?.length || 0);
}, [props.post.likedBy, userInfo.id]); }, [props.post, userInfo.id]);
const handleLike = () => { const handleLike = () => {
if (!liked) { if (!liked) {
setNumberOfLikes(numberOfLikes + 1); setNumberOfLikes(numberOfLikes + 1);
dispatch(likePost(props.post.id as number)); dispatch(likePost(props.post.id as number, props.feedType));
} }
// If the user has already liked the post, unlike it // If the user has already liked the post, unlike it
else { else {
setNumberOfLikes(numberOfLikes - 1); setNumberOfLikes(numberOfLikes - 1);
dispatch(unLikePost(props.post.id as number)); dispatch(unLikePost(props.post.id as number, props.feedType));
} }
setLiked((prevState) => !prevState); setLiked(!liked);
}; };
const handlePostClick = () => { const handlePostClick = () => {

View File

@ -1,6 +1,11 @@
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { commentAPost, fetchAPost, selectAPost } from "../app/postSlice"; import {
commentAPost,
deletePost,
fetchAPost,
selectAPost,
} from "../app/postSlice";
import { useAppDispatch } from "../app/store"; import { useAppDispatch } from "../app/store";
import { useEffect } from "react"; import { useEffect } from "react";
import React from "react"; import React from "react";
@ -14,13 +19,16 @@ import {
Typography, Typography,
} from "@mui/material"; } from "@mui/material";
import { AppAvatar } from "../components/appAvatar"; import { AppAvatar } from "../components/appAvatar";
import { selectUserInfo } from "../app/loginSlice";
export default function PostView() { export default function PostView() {
const postId = useParams<{ id: string }>().id; const postId = useParams<{ id: string }>().id;
const storePost = useSelector(selectAPost); const storePost = useSelector(selectAPost);
const selfUser = useSelector(selectUserInfo);
const [postToDisplay, setPostToDisplay] = React.useState<Post | null>(null); const [postToDisplay, setPostToDisplay] = React.useState<Post | null>(null);
const [newComentText, setNewCommentText] = React.useState(""); const [newComentText, setNewCommentText] = React.useState("");
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
dispatch(fetchAPost(parseInt(postId!, 10))); dispatch(fetchAPost(parseInt(postId!, 10)));
@ -41,6 +49,11 @@ export default function PostView() {
setNewCommentText(""); setNewCommentText("");
}; };
const handleDeletePost = () => {
dispatch(deletePost(postToDisplay!.id!));
navigate("/global");
};
return ( return (
<Box <Box
sx={{ sx={{
@ -77,6 +90,14 @@ export default function PostView() {
</Paper> </Paper>
</Box> </Box>
<Box sx={{ width: "100%" }}> <Box sx={{ width: "100%" }}>
{postToDisplay?.createdBy?.id === selfUser?.id && (
<Box>
<Button onClick={() => navigate("edit")}>Edit</Button>
<Button color="warning" onClick={handleDeletePost}>
Delete
</Button>
</Box>
)}
<TextField <TextField
label="Add a comment..." label="Add a comment..."
fullWidth fullWidth

View File

@ -14,7 +14,8 @@ import PostListItem from "../components/postListItem";
import { Status } from "../util/types"; import { Status } from "../util/types";
interface PostListProps { interface PostListProps {
type: "all" | "user"; type: "feed" | "user";
feedType?: "global" | "followed";
} }
export default function PostList(props: PostListProps) { export default function PostList(props: PostListProps) {
@ -25,12 +26,20 @@ export default function PostList(props: PostListProps) {
const [posts, setPosts] = useState<Post[]>([]); const [posts, setPosts] = useState<Post[]>([]);
useEffect(() => { useEffect(() => {
dispatch(fetchGlobalPosts()); if (props.feedType === "global") {
dispatch(fetchFollowedPosts()); dispatch(fetchGlobalPosts());
}, []); } else {
dispatch(fetchFollowedPosts());
}
}, [props.feedType]);
useEffect(() => { useEffect(() => {
const postsToDisplay = props.type === "all" ? globalPosts : followedPosts; let postsToDisplay: Post[];
if (props.feedType === "global") {
postsToDisplay = globalPosts;
} else {
postsToDisplay = followedPosts;
}
let sortedPosts: Post[] = []; let sortedPosts: Post[] = [];
if (postsToDisplay.length > 0) { if (postsToDisplay.length > 0) {
@ -43,7 +52,7 @@ export default function PostList(props: PostListProps) {
}); });
} }
setPosts(sortedPosts); setPosts(sortedPosts);
}, [followedPosts, globalPosts, props.type]); }, [followedPosts, globalPosts, props.feedType]);
return ( return (
<Box <Box
@ -58,17 +67,27 @@ export default function PostList(props: PostListProps) {
<CircularProgress /> <CircularProgress />
) : ( ) : (
<> <>
{props.type === "all" && ( {props.feedType === "global" && (
<List> <List>
{posts.map((post: Post) => ( {posts.map((post: Post) => (
<PostListItem post={post} postType="all" key={post.id} /> <PostListItem
post={post}
postType="feed"
feedType="global"
key={post.id}
/>
))} ))}
</List> </List>
)} )}
{props.type === "user" && ( {props.feedType === "followed" && (
<List> <List>
{followedPosts.map((post: Post) => ( {followedPosts.map((post: Post) => (
<PostListItem post={post} postType="user" key={post.id} /> <PostListItem
post={post}
postType="feed"
feedType="followed"
key={post.id}
/>
))} ))}
{followedPosts.length === 0 && ( {followedPosts.length === 0 && (
<Box <Box

View File

@ -28,12 +28,18 @@ export class Post {
public deleteSensitiveFields(){ public deleteSensitiveFields(){
this.createdBy.deleteSensitiveFields() this.createdBy.deleteSensitiveFields()
if(this.likedBy.length > 0){ if (this.likedBy) {
this.likedBy.forEach(user => user.deleteSensitiveFields()) if (this.likedBy.length > 0) {
} this.likedBy.forEach((user) => user.deleteSensitiveFields());
if(this.comments.length > 0){ }
this.comments.forEach(comment => comment.createdBy.deleteSensitiveFields())
} }
if (this.comments) {
if (this.comments.length > 0) {
this.comments.forEach((comment) =>
comment.createdBy.deleteSensitiveFields()
);
}
}
} }