kleros/kleros-v2

View on GitHub
web/src/pages/Cases/CaseDetails/MaintenanceButtons/DrawButton.tsx

Summary

Maintainability
B
4 hrs
Test Coverage
import React, { useMemo, useState } from "react";
import styled from "styled-components";

import { usePublicClient } from "wagmi";

import { Button, Field } from "@kleros/ui-components-library";

import { useSimulateKlerosCoreDraw, useWriteKlerosCoreDraw } from "hooks/contracts/generated";
import { useSortitionModulePhase } from "hooks/useSortitionModule";
import { wrapWithToast } from "utils/wrapWithToast";

import useDisputeMaintenanceQuery from "queries/useDisputeMaintenanceQuery";

import { Period } from "src/graphql/graphql";
import { isUndefined } from "src/utils";

import { Phases } from "components/Phase";

import { IBaseMaintenanceButton } from ".";
import { Link } from "react-router-dom";
import { isKlerosUniversity } from "src/consts";
import { isAddress } from "viem";

const StyledButton = styled(Button)`
  width: 100%;
`;

const StyledLabel = styled.label``;
interface IDrawButton extends IBaseMaintenanceButton {
  numberOfVotes?: string;
  period?: string;
}

const isUniversity = isKlerosUniversity();

const DrawButton: React.FC<IDrawButton> = ({ id, numberOfVotes, setIsOpen, period }) => {
  const publicClient = usePublicClient();
  const { data: maintenanceData } = useDisputeMaintenanceQuery(id);
  const { data: phase } = useSortitionModulePhase();
  const [isSending, setIsSending] = useState(false);
  const [drawJuror, setDrawJuror] = useState("");

  const isDrawn = useMemo(() => maintenanceData?.dispute?.currentRound.jurorsDrawn, [maintenanceData]);

  const canDraw = useMemo(
    () =>
      !isUndefined(maintenanceData) &&
      !isDrawn &&
      period === Period.Evidence &&
      (isUniversity ? true : phase === Phases.drawing),
    [maintenanceData, isDrawn, phase, period, isUniversity]
  );

  const needToPassPhase = useMemo(
    () => !isUndefined(maintenanceData) && !isDrawn && period === Period.Evidence && phase !== Phases.drawing,
    [maintenanceData, isDrawn, phase, period]
  );

  const {
    data: drawConfig,
    isLoading: isLoadingConfig,
    isError,
  } = useSimulateKlerosCoreDraw({
    query: {
      enabled:
        !isUndefined(id) &&
        !isUndefined(numberOfVotes) &&
        !isUndefined(period) &&
        canDraw &&
        (isUniversity ? isAddress(drawJuror) : true),
    },
    // eslint-disable-next-line
    // @ts-ignore
    args: [BigInt(id ?? 0), isUniversity ? drawJuror : BigInt(numberOfVotes ?? 0)],
  });

  const { writeContractAsync: draw } = useWriteKlerosCoreDraw();

  const isLoading = useMemo(() => isLoadingConfig || isSending, [isLoadingConfig, isSending]);
  const isDisabled = useMemo(
    () =>
      isUndefined(id) ||
      isUndefined(numberOfVotes) ||
      isError ||
      isLoading ||
      !canDraw ||
      (isUniversity && !isAddress(drawJuror)),
    [id, numberOfVotes, isError, isLoading, canDraw, isUniversity, drawJuror]
  );
  const handleClick = () => {
    if (!drawConfig || !publicClient) return;

    setIsSending(true);

    wrapWithToast(async () => await draw(drawConfig.request), publicClient).finally(() => {
      setIsSending(false);
      setIsOpen(false);
    });
  };
  return (
    <>
      {needToPassPhase && !isUniversity ? (
        <StyledLabel>
          Jurors can be drawn in <small>drawing</small> phase.
          <br /> Pass phase <Link to="/courts/1/purpose/#maintenance">here</Link>.
        </StyledLabel>
      ) : null}
      {isUniversity && canDraw ? (
        <Field placeholder="Juror Address" onChange={(e) => setDrawJuror(e.target.value)} value={drawJuror} />
      ) : null}
      <StyledButton text="Draw" small isLoading={isLoading} disabled={isDisabled} onClick={handleClick} />
    </>
  );
};

export default DrawButton;