aboutsummaryrefslogtreecommitdiffstats
path: root/src/services/graphql/comments.ts
blob: 28ddfd0105740e573e5016323175f91e8474bbd3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import { Comment } from '@ts/types/app';
import { RawComment } from '@ts/types/raw-data';
import { getAuthorFromRawData } from '@utils/helpers/author';
import { fetchAPI, getAPIUrl, SendCommentVars } from './api';
import { sendCommentMutation } from './comments.mutation';
import { commentsQuery } from './comments.query';

/**
 * Create a comments tree with replies.
 *
 * @param {Comment[]} comments - A flatten comments list.
 * @returns {Comment[]} An array of comments with replies.
 */
export const buildCommentsTree = (comments: Comment[]): Comment[] => {
  type CommentsHashTable = {
    [key: string]: Comment;
  };

  const hashTable: CommentsHashTable = Object.create(null);
  const commentsTree: Comment[] = [];

  comments.forEach(
    (comment) => (hashTable[comment.id] = { ...comment, replies: [] })
  );

  comments.forEach((comment) => {
    if (!comment.parentId) {
      commentsTree.push(hashTable[comment.id]);
    } else {
      hashTable[comment.parentId].replies.push(hashTable[comment.id]);
    }
  });

  return commentsTree;
};

/**
 * Convert a comment from RawComment to Comment type.
 *
 * @param {RawComment} comment - A raw comment.
 * @returns {Comment} A formatted comment.
 */
export const getCommentFromRawData = (comment: RawComment): Comment => {
  const { author, databaseId, date, parentDatabaseId, ...data } = comment;

  return {
    id: databaseId,
    meta: {
      author: getAuthorFromRawData(author.node, 'comment'),
      date,
    },
    parentId: parentDatabaseId,
    replies: [],
    ...data,
  };
};

/**
 * Retrieve a comments list by post id.
 *
 * @param {number} id - A post id.
 * @returns {Promise<Comment[]>} The comments list.
 */
export const getPostComments = async (id: number): Promise<Comment[]> => {
  const response = await fetchAPI<RawComment, typeof commentsQuery>({
    api: getAPIUrl(),
    query: commentsQuery,
    variables: { contentId: id },
  });

  const comments = response.comments.nodes.map((comment) =>
    getCommentFromRawData(comment)
  );

  return buildCommentsTree(comments);
};

export type SentComment = {
  clientMutationId: string;
  success: boolean;
  comment: {
    approved: boolean;
  } | null;
};

/**
 * Send a comment using GraphQL API.
 *
 * @param {SendCommentVars} data - The comment data.
 * @returns {Promise<SentEmail>} The mutation response.
 */
export const sendComment = async (
  data: SendCommentVars
): Promise<SentComment> => {
  const response = await fetchAPI<SentComment, typeof sendCommentMutation>({
    api: getAPIUrl(),
    query: sendCommentMutation,
    variables: { ...data },
  });

  return response.createComment;
};