Skip to content

Commit

Permalink
feat(discussion): add replies logic
Browse files Browse the repository at this point in the history
  • Loading branch information
merely04 committed Feb 10, 2024
1 parent fa3e0fe commit 9e87f2a
Show file tree
Hide file tree
Showing 2 changed files with 205 additions and 38 deletions.
75 changes: 73 additions & 2 deletions src/pages/discussion/model.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
import * as typed from 'typed-contracts';
import {chainRoute} from 'atomic-router';
import {createStore, sample} from 'effector';
import {createEvent, createStore, sample} from 'effector';
import {attach} from 'effector/compat';
import {produce} from 'immer';

import {
apiV1CommentsGet,
apiV1CommentsGetOk,
ApiV1CommentsParentCommentIdRepliesGet,
apiV1CommentsParentCommentIdRepliesGet,
apiV1CommentsParentCommentIdRepliesGetOk,
ApiV1CommentsParentCommentIdRepliesPost,
apiV1CommentsParentCommentIdRepliesPost,
ApiV1CommentsPost,
apiV1CommentsPost,
apiV1DiscussionsDiscussionIdGet,
apiV1DiscussionsDiscussionIdGetOk,
} from '~/shared/api';
import {routes} from '~/shared/routes';

const getDiscussionFx = attach({effect: apiV1DiscussionsDiscussionIdGet});
const getCommentsFx = attach({effect: apiV1CommentsGet});
const commentDiscussionFx = attach({effect: apiV1CommentsPost});
const getRepliesFx = attach({effect: apiV1CommentsParentCommentIdRepliesGet});
const commentReplyFx = attach({effect: apiV1CommentsParentCommentIdRepliesPost});

export const currentRoute = routes.discussion;

Expand All @@ -35,6 +46,12 @@ export const $discussion = createStore<typed.Get<typeof apiV1DiscussionsDiscussi
);

export const $comments = createStore<typed.Get<typeof apiV1CommentsGetOk>>([]);
export const commentFormSubmit = createEvent<ApiV1CommentsPost>();

export type Replies = Record<string, typed.Get<typeof apiV1CommentsParentCommentIdRepliesGetOk>>;
export const $replies = createStore<Replies>({});
export const replyClicked = createEvent<ApiV1CommentsParentCommentIdRepliesGet>();
export const replyFormSubmit = createEvent<ApiV1CommentsParentCommentIdRepliesPost>();

sample({
clock: getDiscussionFx.doneData,
Expand All @@ -47,7 +64,7 @@ sample({
fn: ({answer}) => ({
query: {
discussionId: answer.id!,
size: 10,
size: 100,
page: 0,
},
}),
Expand All @@ -59,3 +76,57 @@ sample({
fn: (x) => x.answer,
target: $comments,
});

sample({
clock: commentFormSubmit,
target: commentDiscussionFx,
});

sample({
clock: commentDiscussionFx.doneData,
source: $discussion,
filter: Boolean,
fn: (discussion) => ({
query: {
discussionId: discussion.id!,
size: 100,
page: 0,
},
}),
target: getCommentsFx,
});

sample({
clock: replyClicked,
target: getRepliesFx,
});

sample({
clock: getRepliesFx.done,
source: $replies,
fn: (replies, {params, result}) =>
produce(replies, (draft) => {
// @ts-ignore
draft[params.path.parentCommentId] = result.answer;
}),
target: $replies,
});

sample({
clock: replyFormSubmit,
target: commentReplyFx,
});

sample({
clock: commentReplyFx.done,
fn: ({params}) => ({
path: {
parentCommentId: params.path.parentCommentId,
},
query: {
page: 0,
size: 100,
},
}),
target: getRepliesFx,
});
168 changes: 132 additions & 36 deletions src/pages/discussion/page.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,141 @@
import {useList, useUnit} from 'effector-react';
import {useUnit} from 'effector-react';

import {Post} from '~/widgets/post';

import {ReplyForm} from '~/features/reply-form';

import {apiV1CommentsPost} from '~/shared/api';
import {
ApiV1CommentsParentCommentIdRepliesGet,
ApiV1CommentsParentCommentIdRepliesPost,
} from '~/shared/api';
import {Container, ContainerSize, Page, Text, TextSize} from '~/shared/ui';
import {Card, CardSize} from '~/shared/ui/card';

import * as model from './model';
import {Replies} from './model';
import cls from './page.module.scss';

const buildReplyTree = (
id: string,
replies: Replies,
onReplyClicked: (payload: ApiV1CommentsParentCommentIdRepliesGet) => void,
onReplyFormSubmit: (payload: ApiV1CommentsParentCommentIdRepliesPost) => void,
) => {
return replies[id]?.map((reply) => {
const children = buildReplyTree(reply.id!, replies, onReplyClicked, onReplyFormSubmit);

return (
<Post
key={reply.id!}
replyId={id}
id={reply.id!}
author={{
id: reply.author!.id!,
username: reply.author!.username!,
displayName: reply.author!.display_name!,
avatarUrl: reply.author!.avatar_url!,
}}
date={new Date(reply.created_at!)}
text={reply.content!}
commentators={reply.first_replies_authors!.map((x) => ({
id: x.id!,
username: x.username!,
displayName: x.display_name!,
avatarUrl: x.avatar_url!,
}))}
commentsCount={reply.reply_count!}
canReply={true}
canReport={true}
onShownClick={(parentCommentId) =>
onReplyClicked({path: {parentCommentId}, query: {page: 0, size: 100}})
}
onReplyFormSubmit={(payload) =>
onReplyFormSubmit({
path: {parentCommentId: payload.postId},
body: {content: payload.value},
})
}
children={children}
/>
);
});
};

export const DiscussionPage = () => {
const [discussion] = useUnit([model.$discussion]);
const [discussion, comments, onCommentFormSubmit, onReplyClicked, replies, onReplyFormSubmit] =
useUnit([
model.$discussion,
model.$comments,
model.commentFormSubmit,
model.replyClicked,
model.$replies,
model.replyFormSubmit,
]);

// const comments = useList(model.$comments, (comment) => (
// <Post
// key={comment.id!}
// id={comment.id!}
// author={{
// id: comment.author!.id!,
// username: comment.author!.username!,
// displayName: comment.author!.display_name!,
// avatarUrl: comment.author!.avatar_url!,
// }}
// date={new Date(comment.created_at!)}
// text={comment.content!}
// commentators={comment.first_replies_authors!.map((x) => ({
// id: x.id!,
// username: x.username!,
// displayName: x.display_name!,
// avatarUrl: x.avatar_url!,
// }))}
// commentsCount={comment.reply_count!}
// canReply={true}
// canReport={true}
// onShownClick={(parentCommentId) =>
// onReplyClicked({path: {parentCommentId}, query: {page: 0, size: 20}})
// }
// />
// ));

const onFormSubmit = async (payload: {postId: string; value: string}) => {
await apiV1CommentsPost({
body: {
discussion_id: payload.postId,
content: payload.value,
},
});
};
const items = comments.map((comment) => {
const children = buildReplyTree(comment.id!, replies, onReplyClicked, onReplyFormSubmit);

const comments = useList(model.$comments, (comment) => (
<Post
key={comment.id!}
id={comment.id!}
author={{
id: comment.author!.id!,
username: comment.author!.username!,
displayName: comment.author!.display_name!,
avatarUrl: comment.author!.avatar_url!,
}}
date={new Date(comment.created_at!)}
text={comment.content!}
commentators={comment.first_replies_authors!.map((x) => ({
id: x.id!,
username: x.username!,
displayName: x.display_name!,
avatarUrl: x.avatar_url!,
}))}
commentsCount={comment.reply_count!}
canReply={true}
canReport={true}
/>
));
return (
<Post
key={comment.id!}
id={comment.id!}
author={{
id: comment.author!.id!,
username: comment.author!.username!,
displayName: comment.author!.display_name!,
avatarUrl: comment.author!.avatar_url!,
}}
date={new Date(comment.created_at!)}
text={comment.content!}
commentators={comment.first_replies_authors!.map((x) => ({
id: x.id!,
username: x.username!,
displayName: x.display_name!,
avatarUrl: x.avatar_url!,
}))}
commentsCount={comment.reply_count!}
canReply={true}
canReport={true}
onShownClick={(parentCommentId) =>
onReplyClicked({path: {parentCommentId}, query: {page: 0, size: 100}})
}
onReplyFormSubmit={(payload) =>
onReplyFormSubmit({
path: {parentCommentId: payload.postId},
body: {content: payload.value},
})
}
children={children}
/>
);
});

if (!discussion) {
return null;
Expand All @@ -63,11 +153,17 @@ export const DiscussionPage = () => {
</Container>

<Container size={ContainerSize.M} style={{marginTop: 50, marginBottom: 20}}>
{comments}
{...items}
</Container>

<Container size={ContainerSize.M}>
<ReplyForm postId={discussion.id!} maxLength={500} onSubmit={onFormSubmit} />
<ReplyForm
postId={discussion.id!}
maxLength={500}
onSubmit={(payload) =>
onCommentFormSubmit({body: {discussion_id: payload.postId, content: payload.value}})
}
/>
</Container>
</Page>
);
Expand Down

0 comments on commit 9e87f2a

Please sign in to comment.