Newer
Older
taehui / taehui-fe / src / app / [language] / commentary / components / CommentaryItem.tsx
@Taehui Taehui on 10 Jun 4 KB v1.0.0
import usePutCommentary from "@/app/[language]/commentary/query/usePutCommentary";
import useWipeCommentary from "@/app/[language]/commentary/query/useWipeCommentary";
import { GetCommentaryAPI } from "@/type/wwwAPI";
import { useTranslations } from "next-intl";
import { useState } from "react";
import { PencilFill, TrashFill } from "react-bootstrap-icons";
import Button from "react-bootstrap/Button";
import ButtonGroup from "react-bootstrap/ButtonGroup";
import Col from "react-bootstrap/Col";
import FormControl from "react-bootstrap/FormControl";
import InputGroup from "react-bootstrap/InputGroup";
import InputGroupText from "react-bootstrap/InputGroupText";
import Row from "react-bootstrap/Row";
import Stack from "react-bootstrap/Stack";
import ReactTextareaAutosize from "react-textarea-autosize";
import { toast } from "react-toastify";
import { getDatetime } from "taehui-lib/date";

export default function CommentaryItem({
  commentary: { commentaryID, avatarName, text, date },
}: {
  commentary: GetCommentaryAPI[number];
}) {
  const t = useTranslations();

  const [isModifyOpened, setModifyOpened] = useState(false);
  const [isWipeOpened, setWipeOpened] = useState(false);
  const [avatarCipher, setAvatarCipher] = useState("");
  const [input, setInput] = useState("");

  const { mutateAsync: wipeCommentary } = useWipeCommentary();
  const { mutateAsync: putCommentary } = usePutCommentary();

  if (isModifyOpened || isWipeOpened) {
    return (
      <Row>
        <Stack gap={2}>
          <InputGroup>
            <InputGroupText>{avatarName}</InputGroupText>
            <FormControl
              as={ReactTextareaAutosize}
              value={input}
              isValid={!isWipeOpened && !!input}
              isInvalid={!isWipeOpened && !input}
              disabled={isWipeOpened}
              placeholder={t("text")}
              onChange={({ target: { value } }) => setInput(value)}
            />
            <InputGroupText suppressHydrationWarning>
              {getDatetime(date)}
            </InputGroupText>
          </InputGroup>
          <InputGroup>
            <InputGroupText>{t("avatarCipher")}</InputGroupText>
            <FormControl
              type="password"
              value={avatarCipher}
              isInvalid={!avatarCipher}
              placeholder={t("avatarCipher")}
              onChange={({ target: { value } }) => setAvatarCipher(value)}
            />
            {isModifyOpened && (
              <Button
                variant="warning"
                onClick={async () => {
                  if (avatarCipher && input) {
                    await putCommentary({
                      commentaryID,
                      avatarCipher,
                      text: input,
                    });
                    setModifyOpened(false);
                  } else {
                    toast.error(t("failedValidation"));
                  }
                }}
              >
                <PencilFill />
              </Button>
            )}
            {isWipeOpened && (
              <Button
                variant="danger"
                onClick={async () => {
                  if (avatarCipher) {
                    await wipeCommentary({ commentaryID, avatarCipher });
                  } else {
                    toast.error(t("failedValidation"));
                  }
                }}
              >
                <TrashFill />
              </Button>
            )}
          </InputGroup>
        </Stack>
      </Row>
    );
  }

  const isLoading = !(commentaryID >= 0);

  return (
    <Row className="flex-nowrap">
      <Col xs="auto">{avatarName}</Col>
      <Col className="cc">
        <span style={{ whiteSpace: "break-spaces" }}>{text}</span>
      </Col>
      <Col xs="auto">
        <Stack gap={2}>
          {getDatetime(date)}
          <ButtonGroup>
            <Button
              disabled={isLoading}
              variant="warning"
              onClick={() => {
                setInput(text);
                setModifyOpened(true);
              }}
            >
              <PencilFill />
            </Button>
            <Button
              disabled={isLoading}
              variant="danger"
              onClick={() => {
                setInput(text);
                setWipeOpened(true);
              }}
            >
              <TrashFill />
            </Button>
          </ButtonGroup>
        </Stack>
      </Col>
    </Row>
  );
}