Skip to content

Commit

Permalink
feature: number of likes on the post, user can see if has already lik…
Browse files Browse the repository at this point in the history
…ed the post
  • Loading branch information
rdtabb committed Sep 24, 2023
1 parent 3e37727 commit caea540
Show file tree
Hide file tree
Showing 15 changed files with 282 additions and 171 deletions.
23 changes: 21 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { lazy, Suspense } from "react";
import { Routes, Route } from "react-router-dom";
import ErrorBoundary from "./components/ErrorBoundary/ErrorBoundary";
import useGeneralContext from "./hooks/useContextHooks/useGeneralContext";
Expand All @@ -8,6 +9,10 @@ import Usersearch from "./components/Userlist/Usersearch";
import Auser from "./components/AnotherUser/Auser";
import LikedPosts from "./components/LikedPosts/LikedPosts";
import Chat from "./components/Chat/Chat";
import Loading from "./components/LoadingStates/LoadingPosts";

const LazyLikedPosts = lazy(() => import("./components/LikedPosts/LikedPosts"));
const LazyChat = lazy(() => import("./components/Chat/Chat"));

export const cookies = new Cookies();

Expand All @@ -33,8 +38,22 @@ const App = () => {
<Route path="/" element={<Profile />} />
<Route path="/usersearch" element={<Usersearch />} />
<Route path="/user/:id" element={<Auser />} />
<Route path="/likedposts" element={<LikedPosts />} />
<Route path="/chat" element={<Chat />} />
<Route
path="/likedposts"
element={
<Suspense fallback={<Loading />}>
<LazyLikedPosts />
</Suspense>
}
/>
<Route
path="/chat"
element={
<Suspense fallback={<h1>Loading chat...</h1>}>
<LazyChat />
</Suspense>
}
/>
</Routes>
</ErrorBoundary>
);
Expand Down
93 changes: 54 additions & 39 deletions src/components/AnotherUser/Afeed.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,43 @@
import { memo } from "react";
import { Post, LikePostMutation } from "../../types/Types";
import { doc, updateDoc, getDoc } from "firebase/firestore";
import { db } from "../../firebase-config";
import { memo, useCallback } from "react";
import { Post } from "../../types/Types";
import { handleUnlike, handleLike } from "../../methods/methods";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import useModal from "../../hooks/useModal";

type AfeedProps = {
posts: Post[];
username?: string;
uid?: string;
};

const Afeed = ({ posts, username }: AfeedProps) => {
const Afeed = ({ posts, uid: target_id }: AfeedProps) => {
const queryClient = useQueryClient();
const uid: string = localStorage.getItem("uid")!;
const { openImagePopup } = useModal();

const handleLikeQuery = async (props: LikePostMutation) => {
const uid = localStorage.getItem("uid")!;
const userdoc = doc(db, "users", uid);
const dataSnap = await getDoc(userdoc);
const dataset = dataSnap.data();
const likedPosts = dataset?.liked;
props.e.target.classList.remove("explosive");
props.e.target.classList.add("explosive");
const id = likedPosts.length ? likedPosts[0].id + 1 : 1;
const post = {
id,
city: props.name,
imgsrc: props.src,
creator: username,
};
const newPosts = [post, ...likedPosts];
const updateLiked = { liked: newPosts };
await updateDoc(userdoc, updateLiked);
};
const likeMutation = useMutation({
mutationFn: handleLike,
onSuccess: () => {
queryClient.invalidateQueries(["auserdata"]);
},
});

const likePostMutation = useMutation({
mutationFn: handleLikeQuery,
const unlikeMutation = useMutation({
mutationFn: handleUnlike,
onSuccess: () => {
queryClient.invalidateQueries(["userdataset"]);
queryClient.invalidateQueries(["auserdata"]);
},
});

const isLiked = useCallback(
(post: Post) => {
if (!post.likes.length) return false;

return post.likes.some((like) => like.user_id === uid);
},
[likeMutation, unlikeMutation],
);

return (
<section className="cards">
{posts.map((post) => (
Expand All @@ -55,18 +52,36 @@ const Afeed = ({ posts, username }: AfeedProps) => {
</div>
<div className="card__action">
<h2 className="card__description">{post.city}</h2>
<button
type="button"
className="card__like card__like--auser"
onClick={(e) =>
likePostMutation.mutate({
e,
name: post.city,
src: post.imgsrc,
username,
})
}
></button>
<div className="card__like-count">
<button
type="button"
className={isLiked(post) ? "card__like--active" : "card__like"}
onClick={
isLiked(post)
? () =>
unlikeMutation.mutate({
post_id: post.id,
user_id: target_id,
target_post: post,
posts,
like: {
user_id: uid,
},
})
: () =>
likeMutation.mutate({
post_id: post.id,
user_id: target_id,
target_post: post,
posts,
like: {
user_id: uid,
},
})
}
></button>
<p className="card__count">{post.likes.length}</p>
</div>
</div>
</article>
))}
Expand Down
9 changes: 5 additions & 4 deletions src/components/AnotherUser/Aposts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ import Afeed from "./Afeed";
import NoPosts from "./NoPosts";
import type { Post } from "../../types/Types";

type apostsprops = {
type APostsProps = {
posts: Post[];
name: string | undefined;
name?: string;
uid?: string;
};

const Aposts = ({ posts, name }: apostsprops) => {
const Aposts = ({ posts, name, uid }: APostsProps) => {
return (
<>
{posts.length ? (
<Afeed posts={posts} username={name} />
<Afeed uid={uid} posts={posts} username={name} />
) : (
<NoPosts name={name} />
)}
Expand Down
6 changes: 5 additions & 1 deletion src/components/AnotherUser/Auser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ const Auser = () => {
{auserData.isLoading ? (
<Loading />
) : (
<Aposts posts={auserData.data?.newPosts} name={auserData.data?.name} />
<Aposts
uid={id}
posts={auserData.data?.newPosts}
name={auserData.data?.name}
/>
)}
<Footer />
<>{openPopupType === "image" && <Auserpopup id={id} />}</>
Expand Down
2 changes: 1 addition & 1 deletion src/components/AnotherUser/Auserpopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const Auserpopup = ({ id }: PropsType) => {
});

useEffect(() => {
if (window.innerWidth > 690) setFocus("comment");
if (window.innerWidth > 69) setFocus("comment");
}, []);

return (
Expand Down
64 changes: 10 additions & 54 deletions src/components/LoadingStates/LoadingComments.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,15 @@
import React from "react";

const LoadingComments = () => {
return (
<>
<li className="comment comment--empty">
<img className="comment__icon" alt="" />
<article>
<div className="comment__info">
<p className="comment__creator"></p>
<p className="comment__date"></p>
</div>
<p className="comment__message"></p>
</article>
</li>
<li className="comment comment--empty">
<img className="comment__icon" alt="" />
<article>
<div className="comment__info">
<p className="comment__creator"></p>
<p className="comment__date"></p>
</div>
<p className="comment__message"></p>
</article>
</li>
<li className="comment comment--empty">
<img className="comment__icon" alt="" />
<article>
<div className="comment__info">
<p className="comment__creator"></p>
<p className="comment__date"></p>
</div>
<p className="comment__message"></p>
</article>
</li>
<li className="comment comment--empty">
<img className="comment__icon" alt="" />
<article>
<div className="comment__info">
<p className="comment__creator"></p>
<p className="comment__date"></p>
</div>
<p className="comment__message"></p>
</article>
</li>
<li className="comment comment--empty">
<img className="comment__icon" alt="" />
<article>
<div className="comment__info">
<p className="comment__creator"></p>
<p className="comment__date"></p>
</div>
<p className="comment__message"></p>
</article>
</li>
</>
<li className="comment comment--empty">
<img className="comment__icon" alt="" />
<article>
<div className="comment__info">
<p className="comment__creator"></p>
<p className="comment__date"></p>
</div>
<p className="comment__message"></p>
</article>
</li>
);
};

Expand Down
4 changes: 2 additions & 2 deletions src/components/Profile/AvatarImage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { memo } from "react";
import { useDispatch } from "react-redux";
import { setOpenPopupType } from "../../features/modal/modalSlice";
import EditPopupIcon from '../../assets/editPopupIcon.svg'
import EditPopupIcon from "../../assets/editPopupIcon.svg";

type AvatarImageProps = {
userPicture: string;
userPicture?: string;
};

const AvatarImage = ({ userPicture }: AvatarImageProps) => {
Expand Down
62 changes: 50 additions & 12 deletions src/components/Profile/Feed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import {
setSelectedPost,
setOpenPopupType,
} from "../../features/modal/modalSlice";
import { handleLike, handleDelete } from "../../methods/methods";
import { handleLike, handleDelete, handleUnlike } from "../../methods/methods";
import { Post } from "../../types/Types";
import { memo } from "react";
import { memo, useCallback } from "react";

type FeedProps = {
posts: Post[];
};

const Feed = ({ posts }: FeedProps) => {
const uid: string = localStorage.getItem("uid")!;
const queryClient = useQueryClient();
const selectedPost = useSelector(
(state: RootState) => state.modal.selectedPost,
Expand All @@ -27,6 +28,13 @@ const Feed = ({ posts }: FeedProps) => {
},
});

const unlikeMutation = useMutation({
mutationFn: handleUnlike,
onSuccess: () => {
queryClient.invalidateQueries(["postsdata"]);
},
});

const deleteMutation = useMutation({
mutationFn: handleDelete,
onSuccess: () => {
Expand All @@ -40,6 +48,14 @@ const Feed = ({ posts }: FeedProps) => {
if (selectedPost?.id !== post.id) dispatch(setSelectedPost(post));
};

const isLiked = useCallback(
(post: Post) => {
if (!post.likes.length) return false;
return post.likes.some((like) => like.user_id === uid);
},
[likeMutation, unlikeMutation],
);

return (
<section className="cards">
{posts.map((post: Post) => (
Expand All @@ -55,18 +71,40 @@ const Feed = ({ posts }: FeedProps) => {

<div className="card__action">
<h2 className="card__description">{post.city}</h2>
<button
onClick={() =>
likeMutation.mutate({
id: post.id,
posts: posts,
})
}
type="button"
className={post.liked ? "card__like--active" : "card__like"}
></button>
<div className="card__like-count">
<button
name="likePostButton"
type="button"
className={isLiked(post) ? "card__like--active" : "card__like"}
onClick={
isLiked(post)
? () =>
unlikeMutation.mutate({
post_id: post.id,
user_id: uid,
target_post: post,
posts,
like: {
user_id: uid,
},
})
: () =>
likeMutation.mutate({
post_id: post.id,
user_id: uid,
target_post: post,
posts,
like: {
user_id: uid,
},
})
}
></button>
<p className="card__count">{post.likes.length}</p>
</div>
</div>
<button
name="deletePostButton"
onClick={() =>
deleteMutation.mutate({
id: post.id,
Expand Down
Loading

0 comments on commit caea540

Please sign in to comment.