Society bid modal (& unbid, bidder overview counter) (#3194)

* Society bid modal (& bidder counter)

* Add unbid button (when bidder)
This commit is contained in:
Jaco Greeff 2020-07-14 15:41:26 +02:00 committed by GitHub
parent 3b84ab5863
commit b1def01f5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 142 additions and 13 deletions

View File

@ -4,7 +4,7 @@
import { Route } from './types';
import Component from '@polkadot/app-society';
import Component, { useCounter } from '@polkadot/app-society';
export default function create (t: <T = string> (key: string, text: string, options: { ns: string }) => T): Route {
return {
@ -17,6 +17,7 @@ export default function create (t: <T = string> (key: string, text: string, opti
},
icon: 'hand-spock',
name: 'society',
text: t<string>('nav.society', 'Society', { ns: 'apps-routing' })
text: t<string>('nav.society', 'Society', { ns: 'apps-routing' }),
useCounter
};
}

View File

@ -37,7 +37,7 @@ function Delegate ({ amount: _amount, conviction: _conviction, delegatedAccount:
header= {t<string>('Delegate democracy vote')}
size='large'
>
<Modal.Content className='ui--signer-Signer-Content'>
<Modal.Content>
<Modal.Columns>
<Modal.Column>
<InputAddress

View File

@ -21,7 +21,7 @@ function Undelegate ({ accountDelegating, onClose }: Props): React.ReactElement<
header= {t<string>('Undelegate')}
size='large'
>
<Modal.Content className='ui--signer-Signer-Content'>
<Modal.Content>
<Modal.Columns>
<Modal.Column>
<InputAddress

View File

@ -4,15 +4,29 @@
import { Bid } from '@polkadot/types/interfaces';
import React from 'react';
import { AddressSmall } from '@polkadot/react-components';
import React, { useEffect, useState } from 'react';
import { AddressSmall, TxButton } from '@polkadot/react-components';
import { useAccounts } from '@polkadot/react-hooks';
import { FormatBalance } from '@polkadot/react-query';
import { useTranslation } from '../translate';
interface Props {
index: number;
value: Bid;
}
function BidRow ({ value: { kind, value, who } }: Props): React.ReactElement<Props> {
function BidRow ({ index, value: { kind, value, who } }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { allAccounts } = useAccounts();
const [isBidder, setIsBidder] = useState(false);
useEffect((): void => {
const address = who.toString();
setIsBidder(allAccounts.some((accountId) => accountId === address));
}, [allAccounts, who]);
return (
<tr>
<td className='all top'>
@ -24,6 +38,16 @@ function BidRow ({ value: { kind, value, who } }: Props): React.ReactElement<Pro
<td className='number top'>
<FormatBalance value={value} />
</td>
<td className='button'>
<TxButton
accountId={who}
icon='times'
isDisabled={!isBidder}
label={t<string>('Unbid')}
params={[index]}
tx='society.unbid'
/>
</td>
</tr>
);
}

View File

@ -0,0 +1,69 @@
// Copyright 2017-2020 @polkadot/app-society authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import BN from 'bn.js';
import React, { useState } from 'react';
import { InputAddress, InputBalance, Modal, TxButton } from '@polkadot/react-components';
import { useTranslation } from '../translate';
interface Props {
onClose: () => void;
}
function BidNew ({ onClose }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [amount, setAmount] = useState<BN | undefined>();
const [accountId, setAccount] = useState<string | null | undefined>();
return (
<Modal
header= {t<string>('Bid to join')}
size='large'
>
<Modal.Content>
<Modal.Columns>
<Modal.Column>
<InputAddress
help={t<string>('The actual account you wish to sub,it the bid with')}
label={t<string>('bid account')}
onChange={setAccount}
type='account'
/>
</Modal.Column>
<Modal.Column>
<p>{t<string>('Your canidate/bid account. Once accepted this account will become a member.')}</p>
</Modal.Column>
</Modal.Columns>
<Modal.Columns>
<Modal.Column>
<InputBalance
autoFocus
help={t<string>('The amount to associate with your bid, should be less than the pot.')}
label={t<string>('bid amount')}
onChange={setAmount}
/>
</Modal.Column>
<Modal.Column>
<p>{t<string>('The amount to tie to your bid. The lowest bidder moves forward.')}</p>
</Modal.Column>
</Modal.Columns>
</Modal.Content>
<Modal.Actions onCancel={onClose}>
<TxButton
accountId={accountId}
icon='sign-in-alt'
isDisabled={!amount}
isPrimary
label={t<string>('Bid')}
onStart={onClose}
params={[amount]}
tx='society.bid'
/>
</Modal.Actions>
</Modal>
);
}
export default React.memo(BidNew);

View File

@ -23,7 +23,8 @@ function Bids ({ className }: Props): React.ReactElement<Props> {
const header = useMemo(() => [
[t('bids'), 'start'],
[t('kind')],
[t('value')]
[t('value')],
[]
], [t]);
return (
@ -32,8 +33,9 @@ function Bids ({ className }: Props): React.ReactElement<Props> {
empty={bids && t<string>('No bids')}
header={header}
>
{bids?.map((bid): React.ReactNode => (
{bids?.map((bid, index): React.ReactNode => (
<BidRow
index={index}
key={bid.who.toString()}
value={bid}
/>

View File

@ -6,27 +6,43 @@ import { DeriveSociety } from '@polkadot/api-derive/types';
import React from 'react';
import styled from 'styled-components';
import { useApi, useCall } from '@polkadot/react-hooks';
import { Button } from '@polkadot/react-components';
import { useApi, useCall, useToggle } from '@polkadot/react-hooks';
import useMembers from '../useMembers';
import BidNew from './BidNew';
import Bids from './Bids';
import Candidates from './Candidates';
import Defender from './Defender';
import Members from './Members';
import Summary from './Summary';
import { useTranslation } from '../translate';
interface Props {
className?: string;
}
function Overview ({ className }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
const info = useCall<DeriveSociety>(api.derive.society.info, []);
const { allMembers, isMember, ownMembers } = useMembers();
const [isBidOpen, toggleBidOpen] = useToggle();
return (
<div className={className}>
<Summary info={info} />
<Button.Group>
<Button
icon='plus'
label={t<string>('Submit bid')}
onClick={toggleBidOpen}
/>
{isBidOpen && (
<BidNew onClose={toggleBidOpen} />
)}
</Button.Group>
<Defender
info={info}
isMember={isMember}

View File

@ -8,12 +8,15 @@ import { Tabs } from '@polkadot/react-components';
import Overview from './Overview';
import { useTranslation } from './translate';
import useCounter from './useCounter';
interface Props {
basePath: string;
className?: string;
}
export { useCounter };
function SocietyApp ({ basePath, className }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const items = useMemo(() => [

View File

@ -0,0 +1,14 @@
// Copyright 2017-2020 @polkadot/app-society authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Bid } from '@polkadot/types/interfaces';
import { useApi, useCall } from '@polkadot/react-hooks';
export default function useCounter (): number {
const { api } = useApi();
const bids = useCall<Bid[]>(api.query.society?.bids, []);
return bids?.length || 0;
}

View File

@ -53,7 +53,7 @@ function BondExtra ({ controllerId, onClose, stakingInfo, stashId }: Props): Rea
header= {t<string>('Bond more funds')}
size='large'
>
<Modal.Content className='ui--signer-Signer-Content'>
<Modal.Content>
<Modal.Columns>
<Modal.Column>
<InputAddress

View File

@ -33,7 +33,7 @@ function Unbond ({ className = '', controllerId, onClose, stakingLedger, stashId
header={t<string>('Unbond funds')}
size='large'
>
<Modal.Content className='ui--signer-Signer-Content'>
<Modal.Content>
<Modal.Columns>
<Modal.Column>
<InputAddress

View File

@ -25,7 +25,7 @@ function Validate ({ controllerId, onClose, stashId }: Props): React.ReactElemen
header={t<string>('Set validator preferences')}
size='large'
>
<Modal.Content className='ui--signer-Signer-Content'>
<Modal.Content>
<ValidatePartial
controllerId={controllerId}
onChange={setTx}