Newer
Older
taehui / taehui-fe / src / forum / CommentView.tsx
@Taehui Taehui on 13 Mar 3 KB v1.0.0
import { ReactNode, useMemo, useState } from "react";
import { observer } from "mobx-react-lite";
import { useParams } from "react-router-dom";
import { toast } from "react-toastify";
import { Badge, Button, Col, Row } from "reactstrap";
import { useTranslation } from "react-i18next";
import ReactTextareaAutosize from "react-textarea-autosize";
import { sprintf } from "sprintf-js";

import { useAvatarStore } from "src/Stores";
import CommentItem from "src/forum/CommentItem";
import AvatarTitle from "src/AvatarTitle";
import { GetCommentAPI } from "src/wwwAPI";
import useGetComment from "src/forum/useGetComment";
import usePostComment from "src/forum/usePostComment";

export default observer(() => {
  const { t } = useTranslation();
  const { taehuiAvatarID, taehuiAvatarName, taehuiLevel } = useAvatarStore();
  const [textInput, setTextInput] = useState("");

  type CommentViewParams = { essayID: string };
  const { essayID } = useParams<CommentViewParams>() as CommentViewParams;

  const { data: comment } = useGetComment(essayID);
  const { mutateAsync: postComment } = usePostComment();

  const commentComponents = useMemo(() => {
    const commentComponents: ReactNode[] = [];

    const setCommentComponents =
      (level: number) =>
      ({
        commentID,
        avatarID,
        avatarName,
        date,
        text,
        comments,
      }: GetCommentAPI[number]) => {
        commentComponents.push(
          <CommentItem
            commentID={commentID}
            avatarID={avatarID}
            avatarName={avatarName}
            date={date}
            text={text}
            level={level}
          />,
        );

        comments.forEach(setCommentComponents(level + 1));
      };

    comment.forEach((comment) => {
      setCommentComponents(0)(comment);
    });

    return commentComponents;
  }, [comment]);

  return (
    <>
      <Row className="g-0">
        <Col className="m-1">
          <Badge>{sprintf(t("commentCount"), commentComponents.length)}</Badge>
        </Col>
      </Row>
      {commentComponents}
      {taehuiLevel >= 1 && (
        <Row className="g-0">
          <AvatarTitle avatarID={taehuiAvatarID} avatarName={taehuiAvatarName}>
            <Row className="g-0">
              <Col className="m-1">
                <ReactTextareaAutosize
                  className="form-control"
                  placeholder={t("text")}
                  value={textInput}
                  onChange={({ target: { value } }) => {
                    setTextInput(value);
                  }}
                />
              </Col>
              <Col className="m-1" xs="auto">
                <Button
                  color="success"
                  onClick={async () => {
                    if (textInput) {
                      await postComment({
                        essayID,
                        targetCommentID: -1,
                        text: textInput,
                      });
                      setTextInput("");
                    } else {
                      toast.error(t("failedValidation"));
                    }
                  }}
                >
                  {t("postComment")}
                </Button>
              </Col>
            </Row>
          </AvatarTitle>
        </Row>
      )}
    </>
  );
});