Skip to content

Commit 379a790

Browse files
committed
Implement write comment and reloading comments
1 parent 149db9c commit 379a790

File tree

6 files changed

+223
-14
lines changed

6 files changed

+223
-14
lines changed

src/containers/post/PostComments.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import * as React from 'react';
22
import PostCommentsTemplate from '../../components/post/PostCommentsTemplate';
33
import PostCommentsWriteContainer from './PostCommentsWriteContainer';
4+
import { Comment } from '../../lib/graphql/post';
45

5-
export interface PostCommentsProps {}
6+
export interface PostCommentsProps {
7+
comments: Comment[];
8+
postId: string;
9+
}
610

7-
const PostComments: React.FC<PostCommentsProps> = props => {
11+
const PostComments: React.FC<PostCommentsProps> = ({ comments, postId }) => {
812
return (
9-
<PostCommentsTemplate count={9}>
10-
<PostCommentsWriteContainer />
13+
<PostCommentsTemplate count={comments.length}>
14+
<PostCommentsWriteContainer postId={postId} />
1115
</PostCommentsTemplate>
1216
);
1317
};
Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,55 @@
1-
import * as React from 'react';
1+
import React, { useState, useCallback } from 'react';
22
import PostCommentsWrite from '../../components/post/PostCommentsWrite';
3-
export interface PostCommentWriteContainerProps {}
3+
import { Mutation, MutationResult } from 'react-apollo';
4+
import { WRITE_COMMENT, RELOAD_COMMENTS } from '../../lib/graphql/post';
5+
import gql from 'graphql-tag';
46

5-
const PostCommentsWriteContainer: React.FC<
6-
PostCommentWriteContainerProps
7-
> = props => {
8-
return <PostCommentsWrite />;
7+
export interface PostCommentsWriteContainerProps {
8+
postId: string;
9+
commentId?: string;
10+
}
11+
12+
const PostCommentsWriteContainer: React.FC<PostCommentsWriteContainerProps> = ({
13+
postId,
14+
}) => {
15+
const [comment, setComment] = useState('');
16+
const onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
17+
setComment(e.target.value);
18+
};
19+
return (
20+
<Mutation mutation={WRITE_COMMENT}>
21+
{(
22+
writeComment,
23+
{ data, loading, error, client }: MutationResult<Comment>,
24+
) => {
25+
const onWrite = async () => {
26+
try {
27+
await writeComment({
28+
variables: {
29+
post_id: postId,
30+
text: comment,
31+
},
32+
});
33+
setComment('');
34+
client.query({
35+
query: RELOAD_COMMENTS,
36+
variables: {
37+
id: postId,
38+
},
39+
fetchPolicy: 'network-only',
40+
});
41+
} catch (e) {}
42+
};
43+
return (
44+
<PostCommentsWrite
45+
onChange={onChange}
46+
comment={comment}
47+
onWrite={onWrite}
48+
/>
49+
);
50+
}}
51+
</Mutation>
52+
);
953
};
1054

1155
export default PostCommentsWriteContainer;

src/containers/post/PostViewer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const PostViewer: React.FC<PostViewerProps> = ({ username, urlSlug }) => {
4040
}
4141
/>
4242
<PostContent isMarkdown={post.is_markdown} body={post.body} />
43-
<PostComments />
43+
<PostComments comments={post.comments} postId={post.id} />
4444
</>
4545
);
4646
}}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import * as React from 'react';
2+
import { render, fireEvent } from 'react-testing-library';
3+
import PostCommentsWriteContainer, {
4+
PostCommentsWriteContainerProps,
5+
} from '../PostCommentsWriteContainer';
6+
7+
describe('PostCommentsWriteContainer', () => {
8+
const setup = (props: Partial<PostCommentsWriteContainerProps> = {}) => {
9+
const initialProps: PostCommentsWriteContainerProps = {};
10+
const utils = render(
11+
<PostCommentsWriteContainer {...initialProps} {...props} />,
12+
);
13+
14+
const textarea = utils.getByPlaceholderText(
15+
'댓글을 작성하세요',
16+
) as HTMLTextAreaElement;
17+
const writeButton = utils.getByText('댓글 작성');
18+
19+
return {
20+
textarea,
21+
writeButton,
22+
...utils,
23+
};
24+
};
25+
it('changes textarea', () => {
26+
const { textarea } = setup();
27+
fireEvent.change(textarea, {
28+
target: {
29+
value: 'hello',
30+
},
31+
});
32+
expect(textarea.value).toBe('hello');
33+
});
34+
});

src/containers/post/__tests__/PostViewer.test.tsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,69 @@ describe('PostViewer', () => {
4949
title: 'VELOPERT.LOG',
5050
},
5151
},
52+
comments_count: 8,
53+
comments: [
54+
{
55+
id: '70d24d3b-a6ce-46a3-86c5-1cba95843841',
56+
user: {
57+
id: '0bcdf3e5-a228-42c3-8b52-3f0dc118dfd8',
58+
username: 'blablabla',
59+
profile: {
60+
thumbnail: null,
61+
},
62+
},
63+
text: 'Hey there',
64+
replies_count: 0,
65+
},
66+
{
67+
id: '0f700ebd-0dec-469a-adb8-c47bae2b8f18',
68+
user: {
69+
id: '0bcdf3e5-a228-42c3-8b52-3f0dc118dfd8',
70+
username: 'blablabla',
71+
profile: {
72+
thumbnail: null,
73+
},
74+
},
75+
text: 'Hey there',
76+
replies_count: 0,
77+
},
78+
{
79+
id: '90f3b558-4af3-41bb-95dd-ed9571609f25',
80+
user: {
81+
id: '0bcdf3e5-a228-42c3-8b52-3f0dc118dfd8',
82+
username: 'blablabla',
83+
profile: {
84+
thumbnail: null,
85+
},
86+
},
87+
text: 'Hey there',
88+
replies_count: 0,
89+
},
90+
{
91+
id: 'd4365762-08e8-4928-a387-4255e4392291',
92+
user: {
93+
id: '0bcdf3e5-a228-42c3-8b52-3f0dc118dfd8',
94+
username: 'blablabla',
95+
profile: {
96+
thumbnail: null,
97+
},
98+
},
99+
text: 'Hey there',
100+
replies_count: 3,
101+
},
102+
{
103+
id: '383d590d-d3ed-4f07-994e-cbea3127195d',
104+
user: {
105+
id: '0bcdf3e5-a228-42c3-8b52-3f0dc118dfd8',
106+
username: 'blablabla',
107+
profile: {
108+
thumbnail: null,
109+
},
110+
},
111+
text: 'Hey there',
112+
replies_count: 0,
113+
},
114+
],
52115
},
53116
},
54117
},

src/lib/graphql/post.ts

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,25 @@ export type Post = {
1818
created_at: string;
1919
updated_at: string;
2020
short_description: string;
21-
comments: [any];
22-
tags: [string];
21+
comments: Comment[];
22+
tags: string[];
2323
comments_count: number;
2424
};
2525

26+
export interface Comment {
27+
id: string;
28+
user: {
29+
id: string;
30+
username: string;
31+
profile: {
32+
thumbnail: string;
33+
};
34+
};
35+
text: string;
36+
replies_count: number;
37+
replies?: Comment[];
38+
}
39+
2640
// Post Type for PostList
2741
export type PartialPost = {
2842
id: string;
@@ -33,7 +47,7 @@ export type PartialPost = {
3347
url_slug: string;
3448
is_private: boolean;
3549
released_at: string;
36-
tags: [string];
50+
tags: string[];
3751
comments_count: number;
3852
};
3953

@@ -62,6 +76,7 @@ export interface SinglePost {
6276
title: string;
6377
};
6478
};
79+
comments: Comment[];
6580
}
6681

6782
export const GET_POST_LIST = gql`
@@ -112,6 +127,38 @@ export const READ_POST = gql`
112127
title
113128
}
114129
}
130+
comments {
131+
id
132+
user {
133+
id
134+
username
135+
profile {
136+
thumbnail
137+
}
138+
}
139+
text
140+
replies_count
141+
}
142+
}
143+
}
144+
`;
145+
146+
export const RELOAD_COMMENTS = gql`
147+
query ReloadComments($id: ID!) {
148+
post(id: $id) {
149+
id
150+
comments {
151+
id
152+
user {
153+
id
154+
username
155+
profile {
156+
thumbnail
157+
}
158+
}
159+
text
160+
replies_count
161+
}
115162
}
116163
}
117164
`;
@@ -155,3 +202,20 @@ export const WRITE_POST = gql`
155202
}
156203
}
157204
`;
205+
206+
export const WRITE_COMMENT = gql`
207+
mutation WriteComment($post_id: ID!, $text: String!, $comment_id: ID) {
208+
writeComment(post_id: $post_id, text: $text, comment_id: $comment_id) {
209+
id
210+
user {
211+
id
212+
username
213+
profile {
214+
thumbnail
215+
}
216+
}
217+
text
218+
replies_count
219+
}
220+
}
221+
`;

0 commit comments

Comments
 (0)