Newer
Older
taehui / qwilight-fe / src / note / NoteItem.tsx
@Taehui Taehui on 12 Mar 3 KB 2024-03-12 오후 7:02
import { useState } from "react";
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 "src/note/useGetComment";

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

export default function NoteItem({
  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={() => {
          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>
  );
}