kleros/kleros-v2

View on GitHub
web/src/pages/Cases/CaseDetails/Voting/index.tsx

Summary

Maintainability
A
0 mins
Test Coverage
import React, { useMemo, useState } from "react";
import styled from "styled-components";

import Skeleton from "react-loading-skeleton";
import { useParams } from "react-router-dom";
import { useAccount } from "wagmi";

import VoteIcon from "svgs/icons/voted.svg";

import { Periods } from "consts/periods";
import { useLockOverlayScroll } from "hooks/useLockOverlayScroll";
import { useVotingContext } from "hooks/useVotingContext";
import { formatDate } from "utils/date";
import { isUndefined } from "utils/index";
import { isLastRound } from "utils/isLastRound";

import { useAppealCost } from "queries/useAppealCost";
import { useDisputeDetailsQuery } from "queries/useDisputeDetailsQuery";

import { responsiveSize } from "styles/responsiveSize";

import { getPeriodEndTimestamp } from "components/DisputeView";
import InfoCard from "components/InfoCard";
import Popup, { PopupType } from "components/Popup";

import Classic from "./Classic";
import VotingHistory from "./VotingHistory";

const Container = styled.div`
  padding: ${responsiveSize(16, 32)};
  padding-bottom: ${responsiveSize(8, 16)};
`;

const useFinalDate = (lastPeriodChange: string, currentPeriodIndex?: number, timesPerPeriod?: string[]) =>
  useMemo(() => {
    if (!isUndefined(currentPeriodIndex) && !isUndefined(timesPerPeriod))
      return getPeriodEndTimestamp(lastPeriodChange, currentPeriodIndex, timesPerPeriod);
    else return undefined;
  }, [lastPeriodChange, currentPeriodIndex, timesPerPeriod]);

interface IVoting {
  arbitrable?: `0x${string}`;
  currentPeriodIndex: number;
}

const Voting: React.FC<IVoting> = ({ arbitrable, currentPeriodIndex }) => {
  const { id } = useParams();
  const { isDisconnected } = useAccount();
  const { data: disputeData } = useDisputeDetailsQuery(id);
  const { data: appealCost } = useAppealCost(id);
  const { wasDrawn: userWasDrawn, hasVoted: voted, isLoading: isDrawDataLoading } = useVotingContext();
  const [isPopupOpen, setIsPopupOpen] = useState(false);
  useLockOverlayScroll(isPopupOpen);
  const lastPeriodChange = disputeData?.dispute?.lastPeriodChange;
  const timesPerPeriod = disputeData?.dispute?.court?.timesPerPeriod;
  const finalDate = useFinalDate(lastPeriodChange, currentPeriodIndex, timesPerPeriod);

  const isCommitOrVotePeriod = useMemo(
    () => [Periods.vote, Periods.commit].includes(currentPeriodIndex),
    [currentPeriodIndex]
  );

  return (
    <Container>
      {isLastRound(appealCost) && (
        <>
          <InfoCard msg="This dispute is on its last round. Vote wisely, It cannot be appealed any further." />
          <br />
        </>
      )}

      {userWasDrawn || isDisconnected ? null : (
        <>
          {isDrawDataLoading ? (
            <Skeleton width={300} height={20} />
          ) : (
            <InfoCard msg="You were not drawn in current round." />
          )}
          <br />
        </>
      )}

      {isPopupOpen && (
        <Popup
          title="Thanks for Voting"
          icon={VoteIcon}
          popupType={
            disputeData?.dispute?.court?.hiddenVotes && currentPeriodIndex === Periods.commit
              ? PopupType.VOTE_WITH_COMMIT
              : PopupType.VOTE_WITHOUT_COMMIT
          }
          date={finalDate ? formatDate(finalDate) : ""}
          isCommit={false}
          setIsOpen={setIsPopupOpen}
        />
      )}
      {userWasDrawn && isCommitOrVotePeriod && !voted ? (
        <>
          <VotingHistory {...{ arbitrable }} isQuestion={false} />
          <Classic arbitrable={arbitrable ?? "0x0"} setIsOpen={setIsPopupOpen} />
        </>
      ) : (
        <VotingHistory {...{ arbitrable }} isQuestion={true} />
      )}
    </Container>
  );
};

export default Voting;