Skip to content

Commit 3a0887d

Browse files
authored
feat(web-ui): show reactions in ui (#665)
1 parent c40b422 commit 3a0887d

File tree

6 files changed

+111
-6
lines changed

6 files changed

+111
-6
lines changed

services/web-ui/public/locales/en/blog.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,9 @@
3232
"delete": "Delete"
3333
},
3434
"no-posts": "Seems like no one has posted anything here yet. Be the first one to make a post!",
35-
"published": "published"
35+
"published": "published",
36+
"reactions": {
37+
"count_one": "{{count}} like",
38+
"count_other": "{{count}} likes"
39+
}
3640
}

services/web-ui/public/locales/sv/blog.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,9 @@
3232
"delete": "Ta bort"
3333
},
3434
"no-posts": "Det ser ut som att ingen har postat någonting än. Bli den första att göra ett inlägg!",
35-
"published": "publicerade"
35+
"published": "publicerade",
36+
"reactions": {
37+
"count_one": "{{count}} person gillar detta",
38+
"count_other": "{{count}} personer gillar detta"
39+
}
3640
}

services/web-ui/src/pages/BlogPostListPage/components/BlogPost/BlogPost.stories.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ const BLOG_POST: BlogPostDetails = {
4949
id: 1,
5050
name: "John Doe",
5151
},
52+
reactions: {
53+
count: 0,
54+
currentProfileReactionId: undefined,
55+
},
5256
};
5357

5458
const COMMENT: BlogPostCommentDetails = {

services/web-ui/src/pages/BlogPostListPage/components/BlogPost/BlogPost.tsx

+14-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ReactElement, useState } from "react";
22

3-
import { FavoriteBorder, ModeCommentOutlined } from "@mui/icons-material";
3+
import { ModeCommentOutlined } from "@mui/icons-material";
44
import {
55
Avatar,
66
Box,
@@ -21,6 +21,7 @@ import { useTranslation } from "src/core/i18n";
2121
import { timeSince } from "src/utils/time";
2222

2323
import { BlogPostCommentForm } from "../BlogPostCommentForm/BlogPostComment.form";
24+
import { BlogPostLikeButton } from "../BlogPostLikeButton/BlogPostLikeButton";
2425
import { BlogPostMenu } from "../BlogPostMenu";
2526
import { BlogPostPhotos } from "../BlogPostPhotos/BlogPostPhotos";
2627

@@ -60,15 +61,24 @@ export function BlogPost({ post }: BlogPostProps): ReactElement {
6061
<BlogPostPhotos photos={post.photos} />
6162

6263
<CardActions disableSpacing>
63-
<IconButton aria-label="like" disabled sx={{ display: "none" }}>
64-
<FavoriteBorder />
65-
</IconButton>
64+
<BlogPostLikeButton
65+
blogPostId={post.id}
66+
reactionId={post.reactions.currentProfileReactionId}
67+
/>
6668

6769
<IconButton aria-label="comment" onClick={() => setShowComments(true)}>
6870
<ModeCommentOutlined />
6971
</IconButton>
7072
</CardActions>
7173

74+
{post.reactions.count > 0 && (
75+
<CardContent sx={{ py: 0 }}>
76+
<Typography variant="subtitle2">
77+
{t("reactions.count", { count: post.reactions.count })}
78+
</Typography>
79+
</CardContent>
80+
)}
81+
7282
{post.comments.length > 0 && (
7383
<CardActions disableSpacing>
7484
<Button onClick={() => setShowComments(!showComments)}>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { ReactElement } from "react";
2+
3+
import { Favorite, FavoriteBorder } from "@mui/icons-material";
4+
import { IconButton } from "@mui/material";
5+
6+
import {
7+
CreateBlogPostReactionCommand,
8+
DeleteBlogPostReactionRequest,
9+
} from "src/api";
10+
import { blogsApi } from "src/apis";
11+
import {
12+
CacheKeysConstants,
13+
useMutation,
14+
useQueryClient,
15+
} from "src/core/query";
16+
17+
interface BlogPostLikeButtonProps {
18+
blogPostId: string;
19+
reactionId?: string;
20+
}
21+
22+
export function BlogPostLikeButton({
23+
blogPostId,
24+
reactionId,
25+
}: BlogPostLikeButtonProps): ReactElement {
26+
const createMutation = useMutation({
27+
mutationFn: (
28+
createBlogPostReactionCommand: CreateBlogPostReactionCommand
29+
) => blogsApi.createBlogPostReaction({ createBlogPostReactionCommand }),
30+
});
31+
32+
const deleteMutation = useMutation({
33+
mutationFn: (
34+
deleteBlogPostReactionCommand: DeleteBlogPostReactionRequest
35+
) => blogsApi.deleteBlogPostReaction(deleteBlogPostReactionCommand),
36+
});
37+
38+
const queryClient = useQueryClient();
39+
40+
async function handleToggleReaction(): Promise<void> {
41+
if (reactionId) {
42+
await deleteMutation.mutateAsync(
43+
{ reactionId },
44+
{
45+
onSuccess: () => {
46+
queryClient.invalidateQueries({
47+
queryKey: [CacheKeysConstants.BlogPosts],
48+
});
49+
},
50+
}
51+
);
52+
return;
53+
}
54+
55+
await createMutation.mutateAsync(
56+
{ blogPostId, reaction: ":like" },
57+
{
58+
onSuccess: () => {
59+
queryClient.invalidateQueries({
60+
queryKey: [CacheKeysConstants.BlogPosts],
61+
});
62+
},
63+
}
64+
);
65+
}
66+
67+
const isLoading = createMutation.isPending || deleteMutation.isPaused;
68+
69+
return (
70+
<IconButton
71+
aria-label="like"
72+
color={reactionId ? "primary" : "default"}
73+
disabled={isLoading}
74+
onClick={handleToggleReaction}
75+
>
76+
{reactionId ? <Favorite /> : <FavoriteBorder />}
77+
</IconButton>
78+
);
79+
}

services/web-ui/src/pages/BlogPostPage/components/BlogPost/BlogPost.stories.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ const BLOG_POST: BlogPostDetails = {
4949
id: 1,
5050
name: "John Doe",
5151
},
52+
reactions: {
53+
count: 0,
54+
currentProfileReactionId: undefined,
55+
},
5256
};
5357

5458
const COMMENT: BlogPostCommentDetails = {

0 commit comments

Comments
 (0)