aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/organisms/layout/comments-list.tsx
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-04-22 17:27:01 +0200
committerArmand Philippot <git@armandphilippot.com>2022-04-22 17:34:04 +0200
commitcb6a54e54f2f013e06049b20388ca78e26201e16 (patch)
treeeac5f3a2200d9f5b776c999825a8e28098b46193 /src/components/organisms/layout/comments-list.tsx
parentfd9831446ff87414da772b17327368cb291192e6 (diff)
chore: add a CommentsList component
Diffstat (limited to 'src/components/organisms/layout/comments-list.tsx')
-rw-r--r--src/components/organisms/layout/comments-list.tsx65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/components/organisms/layout/comments-list.tsx b/src/components/organisms/layout/comments-list.tsx
new file mode 100644
index 0000000..03f508e
--- /dev/null
+++ b/src/components/organisms/layout/comments-list.tsx
@@ -0,0 +1,65 @@
+import SingleComment, {
+ type CommentProps,
+} from '@components/organisms/layout/comment';
+import { FC } from 'react';
+import styles from './comments-list.module.scss';
+
+export type Comment = Omit<CommentProps, 'canReply' | 'saveComment'> & {
+ child?: Comment[];
+};
+
+export type CommentsListProps = {
+ /**
+ * An array of comments.
+ */
+ comments: Comment[];
+ /**
+ * The maximum depth. Use `0` to not display nested comments.
+ */
+ depth: 0 | 1 | 2 | 3 | 4;
+ /**
+ * A callback function to save comment form data.
+ */
+ saveComment: CommentProps['saveComment'];
+};
+
+/**
+ * CommentsList component
+ *
+ * Render a comments list.
+ */
+const CommentsList: FC<CommentsListProps> = ({
+ comments,
+ depth,
+ saveComment,
+}) => {
+ /**
+ * Get each comment wrapped in a list item.
+ *
+ * @param {Comment[]} commentsList - An array of comments.
+ * @returns {JSX.Element[]} The list items.
+ */
+ const getItems = (
+ commentsList: Comment[],
+ startLevel: number
+ ): JSX.Element[] => {
+ const isLastLevel = startLevel === depth;
+
+ return commentsList.map(({ child, ...comment }) => (
+ <li key={comment.id} className={styles.item}>
+ <SingleComment
+ saveComment={saveComment}
+ canReply={!isLastLevel}
+ {...comment}
+ />
+ {child && !isLastLevel && (
+ <ol className={styles.list}>{getItems(child, startLevel + 1)}</ol>
+ )}
+ </li>
+ ));
+ };
+
+ return <ol className={styles.list}>{getItems(comments, 0)}</ol>;
+};
+
+export default CommentsList;