Newer
Older
taehui / qwilight-fe / src / note / NoteItem.tsx
@Taehui Taehui on 9 Mar 3 KB 2024-03-09 오후 8:25
import { useState } from "react";
import { observer } from "mobx-react-lite";
import { Col, Collapse, ListGroupItem, Row, Spinner } from "reactstrap";
import { sprintf } from "sprintf-js";
import { useTranslation } from "react-i18next";
import { Item, Menu, useContextMenu } from "react-contexify";
import Swal from "sweetalert2";

import w0 from "src/assets/w0.png";
import w1 from "src/assets/w1.png";
import w2 from "src/assets/w2.png";
import w4 from "src/assets/w4.png";
import w5 from "src/assets/w5.png";
import w6 from "src/assets/w6.png";
import w7 from "src/assets/w7.png";

import CommentItems from "src/note/CommentItems";
import { NoteAPINote } from "src/wwwAPI";
import { wwwAXIOS } from "src/Www";
import { formatText, getGenreText } from "src/Utility";
import useGetComment from "./useGetComment";

const ws = [w0, w1, w2, "", w4, w5, w6, w7];

export default observer(
  ({
    noteID,
    artist,
    title,
    genre,
    levelText,
    level,
    highestCount,
    totalCount,
    fittedText,
    wantAvatarID,
    wantAvatarName,
    handled,
  }: NoteAPINote & { handled?: number }) => {
    const [isCommentOpened, setCommentOpened] = useState(false);
    const { t } = useTranslation();

    const { show: viewToilInput } = useContextMenu({
      id: `toil-${noteID}`,
    });

    const {
      data: { comments, commentPlace, totalComments },
      isFetched: isCommentLoaded,
    } = useGetComment(noteID, isCommentOpened);

    return (
      <ListGroupItem>
        <Row
          className="g-0 route"
          onClick={async () => {
            setCommentOpened((prevState) => !prevState);
          }}
          onContextMenu={(event) => {
            event.preventDefault();
            viewToilInput({ event, props: { noteID } });
          }}
        >
          {typeof handled === "number" && (
            <Col className="m-1" xs="auto">
              <img src={ws[handled]} width={8} height={48} alt="" />
            </Col>
          )}
          <Col className="m-1" xs="auto">
            <span className={`level${level}`}>{levelText}</span>{" "}
            <span className="title">{title}</span>{" "}
            {isCommentOpened && !isCommentLoaded && (
              <Spinner size="sm" color="primary" />
            )}
            <br />
            {fittedText && (
              <span className="fittedText">{fittedText}</span>
            )}{" "}
            <span className="artist">{artist}</span>{" "}
            <span className="genre">{getGenreText(genre)}</span>
            <br />
            {typeof highestCount === "number" &&
              typeof totalCount === "number" && (
                <>
                  <span className="fittedText">
                    {sprintf(t("highestCountText"), formatText(highestCount))}
                  </span>
                  <br />
                  <span className="fittedText">
                    {sprintf(t("totalCountText"), formatText(totalCount))}
                  </span>
                </>
              )}
          </Col>
        </Row>
        {noteID && (
          <Menu id={`toil-${noteID}`}>
            <Item
              onClick={async ({ props: { noteID } }) => {
                const { isConfirmed, value } = await Swal.fire({
                  title: t("toilNoteFileText"),
                  input: "text",
                });
                if (isConfirmed) {
                  await wwwAXIOS.post("/toil", {
                    noteID,
                    commentary: value,
                  });
                }
              }}
            >
              <span>{t("toilNoteFile")}</span>
            </Item>
          </Menu>
        )}
        <Collapse isOpen={isCommentOpened}>
          <CommentItems
            comments={comments}
            commentPlace={commentPlace}
            totalCount={totalComments}
            wantAvatarID={wantAvatarID}
            wantAvatarName={wantAvatarName}
          />
        </Collapse>
      </ListGroupItem>
    );
  },
);