From bd9c9ae7e2ae973969569dd434836de9f38b07d4 Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
Date: Tue, 7 Nov 2023 16:55:58 +0100
Subject: refactor(components): split Comment component into 3 components

* add ApprovedComment, PendingComment and ReplyCommentForm components
* let consumer handle reply form visibility
* move structured data into article page (each article already has the
comments data and already handle json ltd schema so I prefered to move
the schema in the final consumer instead of adding a script element
foreach comment)
---
 src/components/organisms/layout/comments-list.tsx | 88 +++++++++++++++++++----
 1 file changed, 74 insertions(+), 14 deletions(-)

(limited to 'src/components/organisms/layout/comments-list.tsx')

diff --git a/src/components/organisms/layout/comments-list.tsx b/src/components/organisms/layout/comments-list.tsx
index 2d43583..385aea9 100644
--- a/src/components/organisms/layout/comments-list.tsx
+++ b/src/components/organisms/layout/comments-list.tsx
@@ -1,12 +1,20 @@
-import type { FC } from 'react';
+import { useState, type FC, useCallback } from 'react';
+import { useIntl } from 'react-intl';
 import type { SingleComment } from '../../../types';
-import { List, ListItem } from '../../atoms';
-import { UserComment, type UserCommentProps } from './comment';
+import { Heading, List, ListItem } from '../../atoms';
+import {
+  ApprovedComment,
+  type CommentReplyHandler,
+  PendingComment,
+  ReplyCommentForm,
+  type ReplyCommentFormProps,
+} from '../comment';
+import styles from './comments-list.module.scss';
 
 // eslint-disable-next-line @typescript-eslint/no-magic-numbers
 export type CommentsListDepth = 0 | 1 | 2 | 3 | 4;
 
-export type CommentsListProps = Pick<UserCommentProps, 'onSubmit'> & {
+export type CommentsListProps = Pick<ReplyCommentFormProps, 'onSubmit'> & {
   /**
    * An array of comments.
    */
@@ -27,6 +35,21 @@ export const CommentsList: FC<CommentsListProps> = ({
   depth,
   onSubmit,
 }) => {
+  const [replyingTo, setReplyingTo] = useState<number | null>(null);
+  const intl = useIntl();
+  const replyFormHeading = intl.formatMessage({
+    defaultMessage: 'Leave a reply',
+    description: 'CommentsList: comment form title',
+    id: 'w8uLLF',
+  });
+
+  const handleReplyFormVisibility: CommentReplyHandler = useCallback((id) => {
+    setReplyingTo((prevId) => {
+      if (prevId === id) return null;
+      return id;
+    });
+  }, []);
+
   /**
    * Get each comment wrapped in a list item.
    *
@@ -39,16 +62,53 @@ export const CommentsList: FC<CommentsListProps> = ({
   ): JSX.Element[] => {
     const isLastLevel = startLevel === depth;
 
-    return commentsList.map(({ replies, ...comment }) => (
-      <ListItem key={comment.id}>
-        <UserComment canReply={!isLastLevel} onSubmit={onSubmit} {...comment} />
-        {replies.length && !isLastLevel ? (
-          <List hideMarker isOrdered spacing="sm">
-            {getItems(replies, startLevel + 1)}
-          </List>
-        ) : null}
-      </ListItem>
-    ));
+    return commentsList.map(
+      ({ approved, meta, replies, parentId, ...comment }) => {
+        const replyBtnLabel =
+          replyingTo === comment.id
+            ? intl.formatMessage({
+                defaultMessage: 'Cancel reply',
+                description: 'CommentsList: cancel reply button',
+                id: 'uZj4QI',
+              })
+            : intl.formatMessage({
+                defaultMessage: 'Reply',
+                description: 'CommentsList: reply button',
+                id: 'Qa9twM',
+              });
+
+        return (
+          <ListItem key={comment.id}>
+            {approved ? (
+              <>
+                <ApprovedComment
+                  {...comment}
+                  author={meta.author}
+                  onReply={handleReplyFormVisibility}
+                  publicationDate={meta.date}
+                  replyBtn={replyBtnLabel}
+                />
+                {replyingTo === comment.id ? (
+                  <ReplyCommentForm
+                    className={styles.reply}
+                    heading={<Heading level={2}>{replyFormHeading}</Heading>}
+                    onSubmit={onSubmit}
+                    commentId={comment.id}
+                  />
+                ) : null}
+              </>
+            ) : (
+              <PendingComment />
+            )}
+            {replies.length && !isLastLevel ? (
+              <List hideMarker isOrdered spacing="sm">
+                {getItems(replies, startLevel + 1)}
+              </List>
+            ) : null}
+          </ListItem>
+        );
+      }
+    );
   };
 
   return (
-- 
cgit v1.2.3

