ApplyForm.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import BN from 'bn.js';
  2. import React from 'react';
  3. import { I18nProps } from '@polkadot/react-components/types';
  4. import { ApiProps } from '@polkadot/react-api/types';
  5. import { withCalls, withMulti } from '@polkadot/react-api/hoc';
  6. import { Labelled } from '@polkadot/react-components/index';
  7. import { Balance } from '@polkadot/types/interfaces';
  8. import translate from './translate';
  9. import TxButton from '@polkadot/joy-utils/react/components/TxButton';
  10. import InputStake from '@polkadot/joy-utils/react/components/InputStake';
  11. import { ElectionStake } from '@joystream/types/council';
  12. import { calcTotalStake, ZERO } from '@polkadot/joy-utils/functions/misc';
  13. import { MyAddressProps } from '@polkadot/joy-utils/react/hocs/accounts';
  14. import { withOnlyMembers } from '@polkadot/joy-utils/react/hocs/guards';
  15. type Props = ApiProps & I18nProps & MyAddressProps & {
  16. minStake?: Balance;
  17. alreadyStaked?: ElectionStake;
  18. };
  19. type State = {
  20. stake: BN;
  21. isStakeValid: boolean;
  22. };
  23. const DEFAULT_STATE: State = {
  24. stake: ZERO,
  25. isStakeValid: false
  26. };
  27. class ApplyForm extends React.PureComponent<Props, State> {
  28. state = DEFAULT_STATE;
  29. render () {
  30. const { stake, isStakeValid } = this.state;
  31. const hasAlreadyStakedEnough = this.alreadyStaked().gte(this.minStake());
  32. const minStake = hasAlreadyStakedEnough ? ZERO : this.minStake();
  33. const buttonLabel = hasAlreadyStakedEnough
  34. ? 'Add to my stake'
  35. : 'Apply to council';
  36. return (
  37. <div>
  38. <InputStake
  39. min={minStake}
  40. isValid={isStakeValid}
  41. onChange={this.onChangeStake}
  42. />
  43. <div style={{ marginTop: '.5rem' }}>
  44. <Labelled>
  45. <TxButton
  46. isDisabled={!isStakeValid}
  47. label={buttonLabel}
  48. params={[stake]}
  49. tx='councilElection.apply'
  50. />
  51. </Labelled>
  52. </div>
  53. </div>
  54. );
  55. }
  56. private alreadyStaked = (): BN => {
  57. return calcTotalStake(this.props.alreadyStaked);
  58. }
  59. private minStake = (): BN => {
  60. return this.props.minStake || new BN(1);
  61. }
  62. private onChangeStake = (stake?: BN): void => {
  63. stake = stake || ZERO;
  64. const isStakeGteMinStake = stake.add(this.alreadyStaked()).gte(this.minStake());
  65. const isStakeValid = !stake.isZero() && isStakeGteMinStake;
  66. this.setState({ stake, isStakeValid });
  67. }
  68. }
  69. // inject the actual API calls automatically into props
  70. export default withMulti(
  71. ApplyForm,
  72. translate,
  73. withOnlyMembers,
  74. withCalls<Props>(
  75. ['query.councilElection.minCouncilStake',
  76. { propName: 'minStake' }],
  77. ['query.councilElection.applicantStakes',
  78. { paramName: 'myAddress', propName: 'alreadyStaked' }]
  79. )
  80. );