Newer
Older
taehui / qwilight-fe / src / note / NoteItem.tsx
@Taehui Taehui on 16 Mar 3 KB 2024-03-17 오전 2:53
import w0 from "@/assets/w0.png";
import w1 from "@/assets/w1.png";
import w2 from "@/assets/w2.png";
import w4 from "@/assets/w4.png";
import w5 from "@/assets/w5.png";
import w6 from "@/assets/w6.png";
import w7 from "@/assets/w7.png";

import CommentItems from "@/note/CommentItems";
import useGetComment from "@/note/useGetComment";
import usePostToil from "@/note/usePostToil";
import { formatText, getGenreText } from "@/Utility";
import { GetNoteAPI } from "@/wwwAPI";
import { useTranslations } from "next-intl";
import Image from "next/image";
import { useState } from "react";
import { Item, Menu, useContextMenu } from "react-contexify";
import { Col, Collapse, ListGroupItem, Row, Spinner } from "reactstrap";
import Swal from "sweetalert2";

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,
}: GetNoteAPI["notes"][number] & { handled?: number }) {
  const t = useTranslations();

  const [isCommentOpened, setCommentOpened] = useState(false);

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

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

  const { mutateAsync: postToil } = usePostToil();

  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">
            <Image src={ws[handled]} width={10} height={60} 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">
                  {t("highestCountText", {
                    highestCount: formatText(highestCount),
                  })}
                </span>
                <br />
                <span className="fittedText">
                  {t("totalCountText", { totalCount: 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 postToil({ 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>
  );
}