polkadot-js/apps

View on GitHub
packages/page-democracy/src/Overview/Voting.tsx

Summary

Maintainability
C
1 day
Test Coverage
// Copyright 2017-2024 @polkadot/app-democracy authors & contributors
// SPDX-License-Identifier: Apache-2.0

import type { PropIndex, Proposal } from '@polkadot/types/interfaces';
import type { BN } from '@polkadot/util';

import React, { useMemo, useState } from 'react';

import { Button, ConvictionDropdown, Modal, TxButton, VoteAccount, VoteValue } from '@polkadot/react-components';
import { useAccounts, useApi, useToggle } from '@polkadot/react-hooks';
import { ProposedAction } from '@polkadot/react-params';

import { useTranslation } from '../translate.js';

interface Props {
  proposal?: Proposal;
  referendumId: PropIndex;
}

function Voting ({ proposal, referendumId }: Props): React.ReactElement<Props> | null {
  const { t } = useTranslation();
  const { api } = useApi();
  const { hasAccounts } = useAccounts();
  const [accountId, setAccountId] = useState<string | null>(null);
  const [balance, setBalance] = useState<BN | undefined>();
  const [conviction, setConviction] = useState(1);
  const [isVotingOpen, toggleVoting] = useToggle();

  const isCurrentVote = useMemo(
    () => !!api.query.democracy.votingOf,
    [api]
  );

  if (!hasAccounts) {
    return null;
  }

  const isDisabled = isCurrentVote ? !balance : false;

  return (
    <>
      {isVotingOpen && (
        <Modal
          header={t('Vote on proposal')}
          onClose={toggleVoting}
          size='large'
        >
          <Modal.Content>
            <Modal.Columns hint={t('If this proposal is passed, the changes will be applied via dispatch and the deposit returned.')}>
              <ProposedAction
                idNumber={referendumId}
                proposal={proposal}
              />
            </Modal.Columns>
            <Modal.Columns hint={t('The vote will be recorded for this account. If another account delegated to this one, the delegated votes will also be counted.')}>
              <VoteAccount onChange={setAccountId} />
            </Modal.Columns>
            <Modal.Columns
              hint={
                <>
                  <p>{t('The balance associated with the vote will be locked as per the conviction specified and will not be available for transfer during this period.')}</p>
                  <p>{t('Conviction locks do overlap and are not additive, meaning that funds locked during a previous vote can be locked again.')}</p>
                </>
              }
            >
              {isCurrentVote && (
                <VoteValue
                  accountId={accountId}
                  autoFocus
                  onChange={setBalance}
                />
              )}
              <ConvictionDropdown
                label={t('conviction')}
                onChange={setConviction}
                value={conviction}
                voteLockingPeriod={
                  api.consts.democracy.voteLockingPeriod ||
                  api.consts.democracy.enactmentPeriod
                }
              />
            </Modal.Columns>
          </Modal.Content>
          <Modal.Actions>
            <TxButton
              accountId={accountId}
              icon='ban'
              isDisabled={isDisabled}
              label={t('Vote Nay')}
              onStart={toggleVoting}
              params={
                isCurrentVote
                  ? [referendumId, { Standard: { balance, vote: { aye: false, conviction } } }]
                  : [referendumId, { aye: false, conviction }]
              }
              tx={api.tx.democracy.vote}
            />
            <TxButton
              accountId={accountId}
              icon='check'
              isDisabled={isDisabled}
              label={t('Vote Aye')}
              onStart={toggleVoting}
              params={
                isCurrentVote
                  ? [referendumId, { Standard: { balance, vote: { aye: true, conviction } } }]
                  : [referendumId, { aye: true, conviction }]
              }
              tx={api.tx.democracy.vote}
            />
          </Modal.Actions>
        </Modal>
      )}
      <Button
        icon='check-to-slot'
        label={t('Vote')}
        onClick={toggleVoting}
      />
    </>
  );
}

export default React.memo(Voting);